Project import generated by Copybara.

GitOrigin-RevId: df5bf87eca1b9de24d3afd9ee49b125f95dc1351
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000..7481eee
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,51 @@
+mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
+MEDIA_MODULE_PATH := $(dir $(mkfile_path))
+VERSION_CONTROL_CFLAGS := $(shell ${MEDIA_MODULE_PATH}/version_control.sh)
+
+CONFIGS := CONFIG_AMLOGIC_MEDIA_VDEC_MPEG12=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_MPEG2_MULTI=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4_MULTI=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_VC1=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_H264=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_H264_MULTI=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_H264_MVC=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_H265=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_VP9=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG_MULTI=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_REAL=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_AVS=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_AVS_MULTI=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_AVS2=m \
+	CONFIG_AMLOGIC_MEDIA_VENC_H264=m \
+	CONFIG_AMLOGIC_MEDIA_VENC_H265=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_AV1=m \
+	CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y \
+	CONFIG_AMLOGIC_MEDIA_GE2D=y \
+	CONFIG_AMLOGIC_MEDIA_VENC_MULTI=m \
+	CONFIG_AMLOGIC_MEDIA_VENC_JPEG=m
+
+EXTRA_INCLUDE := -I$(KERNEL_SRC)/$(M)/drivers/include
+
+CONFIGS_BUILD := -Wno-parentheses-equality -Wno-pointer-bool-conversion \
+				-Wno-unused-const-variable -Wno-typedef-redefinition \
+				-Wno-logical-not-parentheses -Wno-sometimes-uninitialized \
+				-Wno-frame-larger-than=
+
+KBUILD_CFLAGS_MODULE += $(GKI_EXT_MODULE_PREDEFINE)
+
+modules:
+	$(MAKE) -C  $(KERNEL_SRC) M=$(M)/drivers modules "EXTRA_CFLAGS+=-I$(INCLUDE) -Wno-error $(CONFIGS_BUILD) $(EXTRA_INCLUDE) $(KBUILD_CFLAGS_MODULE) ${VERSION_CONTROL_CFLAGS}" $(CONFIGS)
+
+all: modules
+
+modules_install:
+	$(MAKE) INSTALL_MOD_STRIP=1 M=$(M)/drivers -C $(KERNEL_SRC) modules_install
+	mkdir -p ${OUT_DIR}/../vendor_lib/modules
+	cd ${OUT_DIR}/$(M)/; find -name "*.ko" -exec cp {} ${OUT_DIR}/../vendor_lib/modules/ \;
+	mkdir -p ${OUT_DIR}/../vendor_lib/firmware/video
+	cp $(KERNEL_SRC)/$(M)/firmware/* ${OUT_DIR}/../vendor_lib/firmware/video/
+
+clean:
+	$(MAKE) -C $(KERNEL_SRC) M=$(M) clean
diff --git a/Media.mk b/Media.mk
new file mode 100644
index 0000000..58db63b
--- /dev/null
+++ b/Media.mk
@@ -0,0 +1,110 @@
+ifeq ($(KERNEL_A32_SUPPORT), true)
+KERNEL_ARCH := arm
+else
+KERNEL_ARCH := arm64
+endif
+
+CONFIGS := CONFIG_AMLOGIC_MEDIA_VDEC_MPEG12=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_MPEG2_MULTI=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_MPEG4_MULTI=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_VC1=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_H264=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_H264_MULTI=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_H264_MVC=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_H265=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_VP9=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG_MULTI=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_REAL=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_AVS=m \
+	CONFIG_AMLOGIC_MEDIA_VDEC_AVS2=m \
+	CONFIG_AMLOGIC_MEDIA_VENC_H264=m \
+	CONFIG_AMLOGIC_MEDIA_VENC_H265=m \
+	CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y \
+	CONFIG_AMLOGIC_MEDIA_GE2D=y \
+	CONFIG_AMLOGIC_MEDIA_VENC_MULTI=m \
+	CONFIG_AMLOGIC_MEDIA_VENC_JPEG=m
+
+define copy-media-modules
+$(foreach m, $(shell find $(strip $(1)) -name "*.ko"),\
+	$(shell cp $(m) $(strip $(2)) -rfa))
+endef
+
+ifneq (,$(TOP))
+KDIR := $(shell pwd)/$(PRODUCT_OUT)/obj/KERNEL_OBJ/
+
+MEDIA_DRIVERS := $(TOP)/hardware/amlogic/media_modules/drivers
+ifeq (,$(wildcard $(MEDIA_DRIVERS)))
+$(error No find the dir of drivers.)
+endif
+
+INCLUDE := $(MEDIA_DRIVERS)/include
+ifeq (,$(wildcard $(INCLUDE)))
+$(error No find the dir of include.)
+endif
+
+MEDIA_MODULES := $(shell pwd)/$(PRODUCT_OUT)/obj/media_modules
+ifeq (,$(wildcard $(MEDIA_MODULES)))
+$(shell mkdir $(MEDIA_MODULES) -p)
+endif
+
+MODS_OUT := $(shell pwd)/$(PRODUCT_OUT)/obj/lib_vendor
+ifeq (,$(wildcard $(MODS_OUT)))
+$(shell mkdir $(MODS_OUT) -p)
+endif
+
+UCODE_OUT := $(shell pwd)/$(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)/lib/firmware/video
+ifeq (,$(wildcard $(UCODE_OUT)))
+$(shell mkdir $(UCODE_OUT) -p)
+endif
+
+$(shell cp $(MEDIA_DRIVERS)/../firmware/* $(UCODE_OUT) -rfa)
+$(shell cp $(MEDIA_DRIVERS)/* $(MEDIA_MODULES) -rfa)
+
+define media-modules
+	PATH=$(KERNEL_TOOLPATHS):$$PATH \
+	$(MAKE) -C $(KDIR) M=$(MEDIA_MODULES) $(KERNEL_ARGS) $(CONFIGS) \
+	"EXTRA_CFLAGS+=-I$(INCLUDE) -Wno-error" modules; \
+	find $(MEDIA_MODULES) -name "*.ko" | PATH=$$(cd ./$(TARGET_HOST_TOOL_PATH); pwd):$$PATH xargs -i cp {} $(MODS_OUT)
+endef
+
+else
+KDIR := $(PWD)/kernel
+ifeq (,$(wildcard $(KDIR)))
+$(error No find the dir of kernel.)
+endif
+
+MEDIA_DRIVERS := $(PWD)/media_modules/drivers
+ifeq (,$(wildcard $(MEDIA_DRIVERS)))
+$(error No find the dir of drivers.)
+endif
+
+INCLUDE := $(MEDIA_DRIVERS)/include
+ifeq (,$(wildcard $(INCLUDE)))
+$(error No find the dir of include.)
+endif
+
+MODS_OUT ?= $(MEDIA_DRIVERS)/../modules
+ifeq (,$(wildcard $(MODS_OUT)))
+$(shell mkdir $(MODS_OUT) -p)
+endif
+
+modules:
+	CCACHE_NODIRECT="true" PATH=$(KERNEL_TOOLPATHS):$$PATH \
+	$(MAKE) -C $(KDIR) M=$(MEDIA_DRIVERS) ARCH=$(KERNEL_ARCH) $(KERNEL_ARGS) $(CONFIGS) \
+	EXTRA_CFLAGS+=-I$(INCLUDE) -j64
+
+copy-modules:
+	@echo "start copying media modules."
+	mkdir -p $(MODS_OUT)
+	$(call copy-media-modules, $(MEDIA_DRIVERS), $(MODS_OUT))
+
+all: modules copy-modules
+
+
+clean:
+	PATH=$(KERNEL_TOOLPATHS):$$PATH \
+	$(MAKE) -C $(KDIR) M=$(MEDIA_DRIVERS) $(KERNEL_ARGS) clean
+
+endif
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..4b1504d
--- /dev/null
+++ b/VERSION
@@ -0,0 +1,76 @@
+Major_V=5
+Minor_V=3
+BaseChangeId=Ifc17e92ef9c9e211b8f01ebae1e97c5855fea084
+
+
+#history version
+#V5.2.104-g795aee00.003025 Release Notes
+#Release_ChangeId_V5_2=I34801cba60d54bfd9f459f7445d0362989c23496
+#V5.1.77-g0cdebf27.003009 Release Notes
+#Release_ChangeId_V5_1=Id7e315bbf379d166ca4b335cef13c983a8ca5078
+#Feature develop total count: 6
+#    critical feature develop count: 0
+#    important feature develop count: 4
+#    normal feature develop count: 2
+#Feature develop detail information:
+#    improve pip channel play
+#    support decoder fence
+#    fixed can't get hdr information correctly.
+#    add multi-vdec info for new format av1 after revert
+#    change ptsadjust and threshold from s64 to s32.
+#    support dw 0x100
+#Fixed BUG total count: 30
+#    fixed critical BUG count: 3
+#    fixed important feature develop count: 15
+#    fixed normal feature develop count: 12
+#Fixed BUG detail information:
+#    add VIDTYPE_COMPRESS in vf for dw mode with afbc buffer
+#    fix some the crash caused by null pointer
+#    fixed vpp wrapper memory leak.
+#    metadata lose the last byte every frame in frame mode
+#    fix avs color abnormal.
+#    fix gst secure v4l2 decoder not work
+#    fix the playback stuck when resolution changed
+#    h265 ucode send 2 interrupts cause playback stuck
+#    fix av1 freeze when burn-in test.
+#    fixed playback stuck after seek.
+#    fix 8k display abnormal.
+#    fixed irq-vdec-0 takes more cpu slice.
+#    fixed AV1 seek freezing.
+#    fixed failed to allocate tvp memory
+#    fixed issue of reports resolution change.
+#V5.0 Release Notes
+#Release_ChangeId_V5_0=I6053e02900215d9006469c38ca375ace498b849f
+#upgrade Kernel version to 5.4
+#Android R + v4l2dec (no vpp)   xts clean
+#v4ldec driver seperate from amports drivers
+#
+#V4.0.0 Release Notes
+#upgrade Kernel version to 4.19
+#v4l2 support  for h264/h265/vp9 
+#add fra support in decoder driver
+#
+#V3.0.0 Release Notes
+#upgrade Kernel version to 4.9
+#media_module remove from kernel 
+#new firmware management
+#mjpeg/mpeg12/mpeg2 multi-instance decoder support
+#h264 4k afbc support
+#AVS2 decoder support
+#vdec double write support
+#add av1 decoder support
+#add decoder QOS info report
+#upgrade TA ucode to 0.2 version
+#
+#V2.0.0 Release Notes
+#upgrade  Kernel version to 3.14 
+#Introduce codec_mm memory managment
+#add afbc scatter memory support
+#add vp9 decoder support
+#add 264/265/vp9 multi-instance decoder support
+#
+#V1.0.0 Release Notes
+#based kernel to 3.10
+#add H264 4K decoder support
+#add H265 video decoder support
+#H265 decoder support afbc output
diff --git a/drivers/Makefile b/drivers/Makefile
new file mode 100644
index 0000000..e96ba44
--- /dev/null
+++ b/drivers/Makefile
@@ -0,0 +1,8 @@
+obj-y	+=	common/
+obj-y	+=	frame_provider/
+obj-y	+=	frame_sink/
+obj-y	+=	stream_input/
+obj-y	+=	amvdec_ports/
+obj-y	+=	framerate_adapter/
+obj-y	+=	media_sync/
+obj-$(CONFIG_AMLOGIC_MEDIA_V4L_DEC)	+=	amvdec_ports/
diff --git a/drivers/amvdec_ports/Makefile b/drivers/amvdec_ports/Makefile
new file mode 100644
index 0000000..2e7cff4
--- /dev/null
+++ b/drivers/amvdec_ports/Makefile
@@ -0,0 +1,26 @@
+obj-m += amvdec_ports.o
+amvdec_ports-objs += aml_vcodec_dec_drv.o
+amvdec_ports-objs += aml_vcodec_dec.o
+amvdec_ports-objs += aml_vcodec_util.o
+amvdec_ports-objs += aml_vcodec_adapt.o
+amvdec_ports-objs += aml_vcodec_vpp.o
+amvdec_ports-objs += aml_vcodec_ge2d.o
+amvdec_ports-objs += vdec_drv_if.o
+amvdec_ports-objs += aml_task_chain.o
+amvdec_ports-objs += decoder/vdec_h264_if.o
+amvdec_ports-objs += decoder/vdec_hevc_if.o
+amvdec_ports-objs += decoder/vdec_vp9_if.o
+amvdec_ports-objs += decoder/vdec_mpeg12_if.o
+amvdec_ports-objs += decoder/vdec_mpeg4_if.o
+amvdec_ports-objs += decoder/vdec_mjpeg_if.o
+amvdec_ports-objs += decoder/vdec_av1_if.o
+ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+amvdec_ports-objs += decoder/aml_h264_parser.o
+amvdec_ports-objs += decoder/aml_hevc_parser.o
+amvdec_ports-objs += decoder/aml_vp9_parser.o
+amvdec_ports-objs += decoder/aml_mpeg12_parser.o
+amvdec_ports-objs += decoder/aml_mpeg4_parser.o
+amvdec_ports-objs += decoder/aml_mjpeg_parser.o
+amvdec_ports-objs += utils/golomb.o
+endif
+amvdec_ports-objs += utils/common.o
diff --git a/drivers/amvdec_ports/aml_task_chain.c b/drivers/amvdec_ports/aml_task_chain.c
new file mode 100644
index 0000000..8dfe014
--- /dev/null
+++ b/drivers/amvdec_ports/aml_task_chain.c
@@ -0,0 +1,365 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+#include "aml_vcodec_drv.h"
+#include "aml_task_chain.h"
+
+#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2
+#include <trace/events/meson_atrace.h>
+
+struct task_item_name_s {
+	enum task_type_e	type;
+	const u8		*name;
+};
+
+static const struct task_item_name_s iname[] = {
+	{TASK_TYPE_DEC,		"dec"},
+	{TASK_TYPE_VPP,		"vpp"},
+	{TASK_TYPE_V4L_SINK,	"v4l-sink"},
+	{TASK_TYPE_GE2D,	"ge2d"},
+	{TASK_TYPE_MAX,		"unknown"},
+};
+
+static const u8 *type_to_name(enum task_type_e type)
+{
+	const u8 *name = "unknown";
+	int i, size = ARRAY_SIZE(iname);
+
+	for (i = 0; i < size; i++) {
+		if (type == iname[i].type)
+			name = iname[i].name;
+	}
+
+	return name;
+}
+
+static struct task_item_s *find_task_item(struct task_chain_s *task,
+					  enum task_type_e type)
+{
+	struct task_item_s *item = NULL;
+	ulong flags;
+
+	spin_lock_irqsave(&task->slock, flags);
+
+	if (!list_empty(&task->list_item)) {
+		struct task_item_s *p;
+
+		list_for_each_entry(p, &task->list_item, node) {
+			if (p->ops->type == type) {
+				item = p;
+				break;
+			}
+		}
+	}
+
+	if (item)
+		kref_get(&item->ref);
+
+	spin_unlock_irqrestore(&task->slock, flags);
+
+	return item;
+}
+
+static void task_item_release(struct kref *kref);
+
+static void task_item_vframe_push(struct task_item_s *item, struct vframe_s *vframe)
+{
+	int i = 0;
+
+	for (i = 0 ; i < 3; i++) {
+		if (item->vframe[i] == NULL) {
+			item->vframe[i] = vframe;
+			break;
+		}
+	}
+}
+
+static struct vframe_s *task_item_vframe_pop(struct task_item_s *item)
+{
+	struct vframe_s *vframe = NULL;
+	int i = 0;
+
+	for (i = 0 ; i < 3; i++) {
+		if (item->vframe[i] != NULL) {
+			vframe = item->vframe[i];
+			item->vframe[i] = NULL;
+			break;
+		}
+	}
+
+	return vframe;
+}
+
+static struct task_item_s *task_item_get(struct task_chain_s *task,
+				  enum task_type_e type)
+{
+	struct task_item_s *item = NULL;
+
+	item = find_task_item(task, type);
+	if (!item) {
+		v4l_dbg(task->ctx, V4L_DEBUG_CODEC_ERROR,
+			"TSK(%px):%d get item:%d fail.\n", task, task->id, type);
+	}
+
+	return item;
+}
+
+static int task_item_put(struct task_item_s *item)
+{
+	return kref_put(&item->ref, task_item_release);
+}
+
+static void task_buffer_submit(struct task_chain_s *task,
+			       enum task_type_e type)
+{
+	struct vdec_v4l2_buffer *fb =
+		(struct vdec_v4l2_buffer *)task->obj;
+	struct task_item_s *item = NULL;
+	struct task_item_s *item2 = NULL;
+	struct vframe_s *vf = NULL;
+
+	item = task_item_get(task, type);
+	if (item) {
+		item->ops->get_vframe(item->caller, &vf);
+		fb->vframe = (void *)vf;
+		task_item_vframe_push(item, vf);
+		item->is_active = false;
+
+		item2 = task_item_get(task, task->map[0][type]);
+		if (item2) {
+			item2->is_active = true;
+			item2->ops->fill_buffer(task->ctx, fb);
+
+			v4l_dbg(task->ctx, V4L_DEBUG_TASK_CHAIN,
+				"TSK(%px):%d, vf:%px, phy:%lx, submit %d => %d.\n",
+				task, task->id, vf, fb->m.mem[0].addr,
+				type, task->map[0][type]);
+
+			task->direction = TASK_DIR_SUBMIT;
+			task_item_put(item2);
+		}
+		task_item_put(item);
+	}
+}
+
+static void task_buffer_recycle(struct task_chain_s *task,
+			       enum task_type_e type)
+{
+	struct vdec_v4l2_buffer *fb =
+		(struct vdec_v4l2_buffer *)task->obj;
+	struct task_item_s *item = NULL;
+	struct task_item_s *item2 = NULL;
+
+	item = task_item_get(task, type);
+	if (item) {
+		item->is_active = false;
+
+		item2 = task_item_get(task, task->map[1][type]);
+		if (item2) {
+			struct vframe_s *vf = NULL;
+
+			item2->is_active = true;
+
+			vf = task_item_vframe_pop(item2);
+			item2->ops->put_vframe(item2->caller, vf);
+
+			v4l_dbg(task->ctx, V4L_DEBUG_TASK_CHAIN,
+				"TSK(%px):%d, vf:%px, phy:%lx, recycle %d => %d.\n",
+				task, task->id, vf, fb->m.mem[0].addr,
+				type, task->map[1][type]);
+
+			task->direction = TASK_DIR_RECYCLE;
+			task_item_put(item2);
+		}
+		task_item_put(item);
+	}
+}
+
+void task_chain_show(struct task_chain_s *task)
+{
+	struct task_item_s *item = NULL;
+	char buf[128] = {0};
+	char *pbuf = buf;
+	ulong flags;
+
+	if (!task || !task->ctx)
+		return;
+
+	spin_lock_irqsave(&task->slock, flags);
+
+	if (!list_empty(&task->list_item)) {
+		struct vdec_v4l2_buffer *fb =
+			(struct vdec_v4l2_buffer *)task->obj;
+
+		list_for_each_entry(item, &task->list_item, node) {
+			pbuf += sprintf(pbuf, "%s(%d)",
+				item->name, item->is_active);
+			if (item->node.next != &task->list_item) {
+				if (task->direction == TASK_DIR_SUBMIT)
+					pbuf += sprintf(pbuf, " ==> ");
+				else
+					pbuf += sprintf(pbuf, " <== ");
+			}
+		}
+		v4l_dbg(task->ctx, V4L_DEBUG_CODEC_PRINFO,
+			"vb:%2d, phy:%lx  %s\n",
+			task->id, fb->m.mem[0].addr, buf);
+	}
+
+	spin_unlock_irqrestore(&task->slock, flags);
+}
+EXPORT_SYMBOL(task_chain_show);
+
+static void task_chain_destroy(struct kref *kref)
+{
+	struct task_chain_s *task;
+
+	task = container_of(kref, struct task_chain_s, ref);
+
+	task->cur_type = TASK_TYPE_MAX;
+	memset(task->map, 0, sizeof(task->map));
+
+	v4l_dbg(task->ctx, V4L_DEBUG_TASK_CHAIN,
+		"TSK(%px):%d task chain destroyed.\n", task, task->id);
+
+	kfree(task);
+}
+
+static void task_item_release(struct kref *kref)
+{
+	struct task_item_s *item;
+
+	item = container_of(kref, struct task_item_s, ref);
+	list_del(&item->node);
+
+	v4l_dbg(item->task->ctx, V4L_DEBUG_TASK_CHAIN,
+		"TSK(%px):%d task item:(%px,%d) released.\n",
+		item->task, item->task->id, item, item->ops->type);
+
+	kref_put(&item->task->ref, task_chain_destroy);
+
+	kfree(item);
+}
+
+void task_chain_clean(struct task_chain_s *task)
+{
+	struct task_item_s *item, *tmp;
+
+	v4l_dbg(task->ctx, V4L_DEBUG_TASK_CHAIN,
+		"TSK(%px):%d task chain clean.\n", task, task->id);
+
+	if (!list_empty(&task->list_item)) {
+		list_for_each_entry_safe(item, tmp, &task->list_item, node)
+			kref_put(&item->ref, task_item_release);
+	}
+}
+EXPORT_SYMBOL(task_chain_clean);
+
+void task_chain_release(struct task_chain_s *task)
+{
+	v4l_dbg(task->ctx, V4L_DEBUG_TASK_CHAIN,
+		"TSK(%px):%d task chain release.\n", task, task->id);
+
+	kref_put(&task->ref, task_chain_destroy);
+}
+EXPORT_SYMBOL(task_chain_release);
+
+void task_order_attach(struct task_chain_s *task,
+			 struct task_ops_s *ops,
+			 void *caller)
+{
+	struct task_item_s *item;
+
+	item = kzalloc(sizeof(struct task_item_s), GFP_ATOMIC);
+	if (!item) {
+		v4l_dbg(task->ctx, V4L_DEBUG_CODEC_ERROR,
+			"TSK(%px):%d alloc item fail.\n", task, task->id);
+		return;
+	}
+
+	item->task	= task;
+	item->ops	= ops;
+	item->caller	= caller;
+	item->name	= type_to_name(ops->type);
+	kref_init(&item->ref);
+
+	task->map[0][ops->type] = task->cur_type;
+	task->map[1][task->cur_type] = ops->type;
+	task->cur_type = ops->type;
+	kref_get(&task->ref);
+
+	list_add(&item->node, &task->list_item);
+
+	v4l_dbg(task->ctx, V4L_DEBUG_TASK_CHAIN,
+		"TSK(%px):%d attach item:(%px,%d).\n",
+		task, task->id, item, ops->type);
+}
+EXPORT_SYMBOL(task_order_attach);
+
+void task_chain_update_object(struct task_chain_s *task, void *obj)
+{
+	/*
+	 * Note: have to invoke this funtion
+	 * if the task object has been changed.
+	 */
+	task->obj = obj;
+
+	v4l_dbg(task->ctx, V4L_DEBUG_TASK_CHAIN,
+		"TSK(%px):%d update task obj:%px.\n",
+		task, task->id, obj);
+}
+EXPORT_SYMBOL(task_chain_update_object);
+
+int task_chain_init(struct task_chain_s **task_out,
+			    void *v4l_ctx,
+			    void *obj,
+			    int vb_idx)
+{
+	struct task_chain_s *task;
+
+	task = kzalloc(sizeof(struct task_chain_s), GFP_ATOMIC);
+	if (!task) {
+		v4l_dbg(task->ctx, V4L_DEBUG_CODEC_ERROR,
+			"TSK(%px):%d alloc task fail.\n", task, task->id);
+		return -ENOMEM;
+	}
+
+	task->id	= vb_idx;
+	task->obj	= obj;
+	task->ctx	= v4l_ctx;
+	kref_init(&task->ref);
+	spin_lock_init(&task->slock);
+	INIT_LIST_HEAD(&task->list_item);
+
+	task->attach	= task_order_attach;
+	task->submit	= task_buffer_submit;
+	task->recycle	= task_buffer_recycle;
+
+	*task_out = task;
+
+	v4l_dbg(task->ctx, V4L_DEBUG_TASK_CHAIN,
+		"TSK(%px):%d task chain creat success.\n", task, task->id);
+	return 0;
+}
+EXPORT_SYMBOL(task_chain_init);
+
diff --git a/drivers/amvdec_ports/aml_task_chain.h b/drivers/amvdec_ports/aml_task_chain.h
new file mode 100644
index 0000000..fdbe2fb
--- /dev/null
+++ b/drivers/amvdec_ports/aml_task_chain.h
@@ -0,0 +1,125 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+
+#ifndef AML_TASK_CHAIN_H
+#define AML_TASK_CHAIN_H
+
+#include <linux/amlogic/media/vfm/vframe.h>
+
+enum task_type_e {
+	TASK_TYPE_DEC,
+	TASK_TYPE_VPP,
+	TASK_TYPE_V4L_SINK,
+	TASK_TYPE_GE2D,
+	TASK_TYPE_MAX
+};
+
+enum task_dir_e {
+	TASK_DIR_SUBMIT,
+	TASK_DIR_RECYCLE,
+	TASK_DIR_MAX
+};
+
+struct task_chain_s;
+
+/*
+ * struct task_ops_s - interface of the task item.
+ * @type	: type of task ops involves dec, vpp, v4l sink etc.
+ * @get_vframe	: get the video frame from caller's fifo.
+ * @put_vframe	: put the video frame to caller's fifo.
+ * @fill_buffer	: submit the buffer into next process module.
+ */
+struct task_ops_s {
+	enum task_type_e type;
+	void	(*get_vframe) (void *caller, struct vframe_s **vf);
+	void	(*put_vframe) (void *caller, struct vframe_s *vf);
+	void	(*fill_buffer) (void *v4l_ctx, void *fb_ctx);
+};
+
+/*
+ * struct task_item_s - items of the task chain.
+ * @node	: list node of the specific task item.
+ * @ref		: reference count of item be used by others.
+ * @name	: name of task item, map with task type.
+ * @is_active	: indicate this item whether is active.
+ * @vframe[3]	: store the vframes that get from caller.
+ * @task	: the context of the task chain.
+ * @caller	: it's the handle, meght it's dec, vpp or v4l-sink etc.
+ * @ops		: sets of interface which attach from task item.
+ */
+struct task_item_s {
+	struct list_head	node;
+	struct kref		ref;
+	const u8		*name;
+	bool			is_active;
+	void			*vframe[3];
+	struct task_chain_s	*task;
+	void			*caller;
+	struct task_ops_s	*ops;
+};
+
+/*
+ * struct task_chain_s - the manager struct of the task chain.
+ * @list_item	: all task items be attached are store in the list.
+ * @node	: will register to the task chain pool.
+ * @ref		: reference count of task chain be used by others.
+ * @slock	: used for list item write and read safely.
+ * @id		: it's vb index to be a mark used for task chain.
+ * @ctx		: the context of the v4l driver.
+ * @obj		: the object managed by task chain.
+ * @direction	: direction incluse 2 flows submit & recycle.
+ * @cur_type	: the latest item type before a new item be attached.
+ * @map		: the map store the pipeline information.
+ * @attach	: attach a new item to task chain.
+ * @submit	: submit the finish item to next item module.
+ * @recycle	: if item's date was consumed will be recycled to item.
+ */
+struct task_chain_s {
+	struct list_head	list_item;
+	struct list_head	node;
+	struct kref		ref;
+	spinlock_t		slock;
+	int			id;
+	void			*ctx;
+	void			*obj;
+	enum task_dir_e		direction;
+	enum task_type_e	cur_type;
+	u8			map[2][8];
+
+	void	(*attach) (struct task_chain_s *, struct task_ops_s *, void *);
+	void	(*submit) (struct task_chain_s *, enum task_type_e);
+	void	(*recycle) (struct task_chain_s *, enum task_type_e);
+};
+
+
+int task_chain_init(struct task_chain_s **task_out,
+		     void *v4l_ctx,
+		     void *obj,
+		     int vb_idx);
+void task_order_attach(struct task_chain_s *task,
+		       struct task_ops_s *ops,
+		       void *caller);
+void task_chain_clean(struct task_chain_s *task);
+void task_chain_release(struct task_chain_s *task);
+void task_chain_show(struct task_chain_s *task);
+void task_chain_update_object(struct task_chain_s *task, void *obj);
+
+#endif //AML_TASK_CHAIN_H
+
diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.c b/drivers/amvdec_ports/aml_vcodec_adapt.c
new file mode 100644
index 0000000..7e08371
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.c
@@ -0,0 +1,591 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/types.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/media/utils/aformat.h>
+#include <linux/amlogic/media/frame_sync/tsync.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include <linux/amlogic/media/frame_sync/timestamp.h>
+#include <linux/amlogic/media/utils/amports_config.h>
+#include <linux/amlogic/media/frame_sync/tsync_pcr.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/amlogic/media/codec_mm/configs.h>
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/media/utils/aformat.h>
+#include <linux/amlogic/media/registers/register.h>
+#include "../stream_input/amports/adec.h"
+#include "../stream_input/amports/streambuf.h"
+#include "../stream_input/amports/streambuf_reg.h"
+#include "../stream_input/parser/tsdemux.h"
+#include "../stream_input/parser/psparser.h"
+#include "../stream_input/parser/esparser.h"
+#include "../frame_provider/decoder/utils/vdec.h"
+#include "../common/media_clock/switch/amports_gate.h"
+#include <linux/delay.h>
+#include "aml_vcodec_adapt.h"
+#include <linux/crc32.h>
+
+#define DEFAULT_VIDEO_BUFFER_SIZE		(1024 * 1024 * 3)
+#define DEFAULT_VIDEO_BUFFER_SIZE_4K		(1024 * 1024 * 6)
+#define DEFAULT_VIDEO_BUFFER_SIZE_TVP		(1024 * 1024 * 10)
+#define DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP	(1024 * 1024 * 15)
+#define DEFAULT_AUDIO_BUFFER_SIZE		(1024*768*2)
+#define DEFAULT_SUBTITLE_BUFFER_SIZE		(1024*256)
+
+#define PTS_OUTSIDE	(1)
+#define SYNC_OUTSIDE	(2)
+
+//#define DATA_DEBUG
+
+extern int dump_output_frame;
+extern u32 dump_output_start_position;
+extern void aml_recycle_dma_buffers(struct aml_vcodec_ctx *ctx, u32 handle);
+
+static int slow_input = 0;
+
+static struct stream_buf_s bufs[BUF_MAX_NUM] = {
+	{
+		.reg_base = VLD_MEM_VIFIFO_REG_BASE,
+		.type = BUF_TYPE_VIDEO,
+		.buf_start = 0,
+		.buf_size = DEFAULT_VIDEO_BUFFER_SIZE,
+		.default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE,
+		.first_tstamp = INVALID_PTS
+	},
+	{
+		.reg_base = AIU_MEM_AIFIFO_REG_BASE,
+		.type = BUF_TYPE_AUDIO,
+		.buf_start = 0,
+		.buf_size = DEFAULT_AUDIO_BUFFER_SIZE,
+		.default_buf_size = DEFAULT_AUDIO_BUFFER_SIZE,
+		.first_tstamp = INVALID_PTS
+	},
+	{
+		.reg_base = 0,
+		.type = BUF_TYPE_SUBTITLE,
+		.buf_start = 0,
+		.buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE,
+		.default_buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE,
+		.first_tstamp = INVALID_PTS
+	},
+	{
+		.reg_base = 0,
+		.type = BUF_TYPE_USERDATA,
+		.buf_start = 0,
+		.buf_size = 0,
+		.first_tstamp = INVALID_PTS
+	},
+	{
+		.reg_base = HEVC_STREAM_REG_BASE,
+		.type = BUF_TYPE_HEVC,
+		.buf_start = 0,
+		.buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K,
+		.default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K,
+		.first_tstamp = INVALID_PTS
+	},
+};
+
+extern int aml_set_vfm_path, aml_set_vdec_type;
+extern bool aml_set_vfm_enable, aml_set_vdec_type_enable;
+
+static void set_default_params(struct aml_vdec_adapt *vdec)
+{
+	ulong sync_mode = (PTS_OUTSIDE | SYNC_OUTSIDE);
+
+	vdec->dec_prop.param = (void *)sync_mode;
+	vdec->dec_prop.format = vdec->format;
+	vdec->dec_prop.width = 1920;
+	vdec->dec_prop.height = 1088;
+	vdec->dec_prop.rate = 3200;
+}
+
+static int enable_hardware(struct stream_port_s *port)
+{
+	if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6)
+		return -1;
+
+	amports_switch_gate("demux", 1);
+	if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8)
+		amports_switch_gate("parser_top", 1);
+
+	if (port->type & PORT_TYPE_VIDEO) {
+		amports_switch_gate("vdec", 1);
+
+		if (has_hevc_vdec()) {
+			if (port->type & PORT_TYPE_HEVC)
+				vdec_poweron(VDEC_HEVC);
+			else
+				vdec_poweron(VDEC_1);
+		} else {
+			if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8)
+				vdec_poweron(VDEC_1);
+		}
+	}
+
+	return 0;
+}
+
+static int disable_hardware(struct stream_port_s *port)
+{
+	if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6)
+		return -1;
+
+	if (port->type & PORT_TYPE_VIDEO) {
+		if (has_hevc_vdec()) {
+			if (port->type & PORT_TYPE_HEVC)
+				vdec_poweroff(VDEC_HEVC);
+			else
+				vdec_poweroff(VDEC_1);
+		}
+
+		amports_switch_gate("vdec", 0);
+	}
+
+	if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8)
+		amports_switch_gate("parser_top", 0);
+
+	amports_switch_gate("demux", 0);
+
+	return 0;
+}
+
+static void user_buffer_init(void)
+{
+	struct stream_buf_s *pubuf = &bufs[BUF_TYPE_USERDATA];
+
+	pubuf->buf_size = 0;
+	pubuf->buf_start = 0;
+	pubuf->buf_wp = 0;
+	pubuf->buf_rp = 0;
+}
+
+static void video_component_release(struct stream_port_s *port)
+{
+	struct aml_vdec_adapt *ada_ctx
+		= container_of(port, struct aml_vdec_adapt, port);
+	struct vdec_s *vdec = ada_ctx->vdec;
+
+	vdec_release(vdec);
+
+}
+
+static int video_component_init(struct stream_port_s *port,
+			  struct stream_buf_s *pbuf)
+{
+	int ret = -1;
+	struct aml_vdec_adapt *ada_ctx
+		= container_of(port, struct aml_vdec_adapt, port);
+	struct vdec_s *vdec = ada_ctx->vdec;
+
+	if ((vdec->port_flag & PORT_FLAG_VFORMAT) == 0) {
+		v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "vformat not set\n");
+		return -EPERM;
+	}
+
+	if ((vdec->sys_info->height * vdec->sys_info->width) > 1920 * 1088
+		|| port->vformat == VFORMAT_H264_4K2K) {
+		port->is_4k = true;
+		if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX
+				&& (port->vformat == VFORMAT_H264))
+			vdec_poweron(VDEC_HEVC);
+	} else
+		port->is_4k = false;
+
+	if (port->type & PORT_TYPE_FRAME ||
+		(port->type & PORT_TYPE_ES)) {
+		ret = vdec_init(vdec, port->is_4k, true);
+		if (ret < 0) {
+			v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "failed\n");
+			video_component_release(port);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int vdec_ports_release(struct stream_port_s *port)
+{
+	struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO];
+
+	if (has_hevc_vdec()) {
+		if (port->vformat == VFORMAT_HEVC ||
+			port->vformat == VFORMAT_VP9)
+			pvbuf = &bufs[BUF_TYPE_HEVC];
+	}
+
+	if (port->type & PORT_TYPE_MPTS) {
+		tsync_pcr_stop();
+		tsdemux_release();
+	}
+
+	if (port->type & PORT_TYPE_MPPS)
+		psparser_release();
+
+	if (port->type & PORT_TYPE_VIDEO)
+		video_component_release(port);
+
+	port->pcr_inited = 0;
+	port->flag = 0;
+
+	return 0;
+}
+
+static void set_vdec_properity(struct vdec_s *vdec,
+	struct aml_vdec_adapt *ada_ctx)
+{
+	vdec->sys_info	= &ada_ctx->dec_prop;
+	vdec->port	= &ada_ctx->port;
+	vdec->format	= ada_ctx->video_type;
+	vdec->sys_info_store = ada_ctx->dec_prop;
+
+	/* binding v4l2 ctx to vdec. */
+	vdec->private = ada_ctx->ctx;
+
+	/* set video format, sys info and vfm map.*/
+	vdec->port->vformat = vdec->format;
+	vdec->port->type |= PORT_TYPE_VIDEO;
+	vdec->port_flag |= (vdec->port->flag | PORT_FLAG_VFORMAT);
+	if (vdec->slave) {
+		vdec->slave->format = ada_ctx->dec_prop.format;
+		vdec->slave->port_flag |= PORT_FLAG_VFORMAT;
+	}
+
+	vdec->type = VDEC_TYPE_FRAME_BLOCK;
+	vdec->port->type |= PORT_TYPE_FRAME;
+	vdec->frame_base_video_path = FRAME_BASE_PATH_V4L_OSD;
+
+	if (aml_set_vdec_type_enable) {
+		if (aml_set_vdec_type == VDEC_TYPE_STREAM_PARSER) {
+			vdec->type = VDEC_TYPE_STREAM_PARSER;
+			vdec->port->type &= ~PORT_TYPE_FRAME;
+			vdec->port->type |= PORT_TYPE_ES;
+		} else if (aml_set_vdec_type == VDEC_TYPE_FRAME_BLOCK) {
+			vdec->type = VDEC_TYPE_FRAME_BLOCK;
+			vdec->port->type &= ~PORT_TYPE_ES;
+			vdec->port->type |= PORT_TYPE_FRAME;
+		}
+	}
+
+	if (aml_set_vfm_enable)
+		vdec->frame_base_video_path = aml_set_vfm_path;
+
+	vdec->port->flag = vdec->port_flag;
+
+	vdec->config_len = ada_ctx->config.length >
+		PAGE_SIZE ? PAGE_SIZE : ada_ctx->config.length;
+	memcpy(vdec->config, ada_ctx->config.buf, vdec->config_len);
+
+	ada_ctx->vdec = vdec;
+}
+
+static int vdec_ports_init(struct aml_vdec_adapt *ada_ctx)
+{
+	int ret = -1;
+	struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO];
+	struct vdec_s *vdec = NULL;
+
+	/* create the vdec instance.*/
+	vdec = vdec_create(&ada_ctx->port, NULL);
+	if (IS_ERR_OR_NULL(vdec))
+		return -1;
+
+	vdec->disable_vfm = true;
+	set_vdec_properity(vdec, ada_ctx);
+
+	/* init hw and gate*/
+	ret = enable_hardware(vdec->port);
+	if (ret < 0) {
+		v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "enable hw fail.\n");
+		return ret;
+	}
+
+	stbuf_fetch_init();
+	user_buffer_init();
+
+	if ((vdec->port->type & PORT_TYPE_VIDEO)
+		&& (vdec->port_flag & PORT_FLAG_VFORMAT)) {
+		vdec->port->is_4k = false;
+		if (has_hevc_vdec()) {
+			if (vdec->port->vformat == VFORMAT_HEVC ||
+				vdec->port->vformat == VFORMAT_VP9)
+				pvbuf = &bufs[BUF_TYPE_HEVC];
+		}
+
+		ret = video_component_init(vdec->port, pvbuf);
+		if (ret < 0) {
+			v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "video_component_init  failed\n");
+			return ret;
+		}
+
+		/* connect vdec at the end after all HW initialization */
+		vdec_connect(vdec);
+	}
+
+	return 0;
+}
+
+int video_decoder_init(struct aml_vdec_adapt *vdec)
+{
+	int ret = -1;
+
+	/* sets configure data */
+	set_default_params(vdec);
+
+	/* init the buffer work space and connect vdec.*/
+	ret = vdec_ports_init(vdec);
+	if (ret < 0) {
+		v4l_dbg(vdec->ctx, V4L_DEBUG_CODEC_ERROR, "vdec ports init fail.\n");
+		goto out;
+	}
+out:
+	return ret;
+}
+
+int video_decoder_release(struct aml_vdec_adapt *vdec)
+{
+	int ret = -1;
+	struct stream_port_s *port = &vdec->port;
+
+	ret = vdec_ports_release(port);
+	if (ret < 0) {
+		v4l_dbg(vdec->ctx, V4L_DEBUG_CODEC_ERROR, "vdec ports release fail.\n");
+		goto out;
+	}
+
+	/* disable gates */
+	ret = disable_hardware(port);
+	if (ret < 0) {
+		v4l_dbg(vdec->ctx, V4L_DEBUG_CODEC_ERROR, "disable hw fail.\n");
+		goto out;
+	}
+out:
+	return ret;
+}
+
+void dump(const char* path, const char *data, unsigned int size)
+{
+	struct file *fp;
+
+	fp = filp_open(path,
+			O_CREAT | O_RDWR | O_LARGEFILE | O_APPEND, 0600);
+	if (!IS_ERR(fp)) {
+		kernel_write(fp, data, size, 0);
+		filp_close(fp, NULL);
+	} else {
+		pr_info("Dump ES fail, should check RW permission, size:%x\n", size);
+	}
+}
+
+int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx,
+	const char *buf, unsigned int count)
+{
+	int ret = -1;
+	int try_cnt = 100;
+	struct stream_port_s *port = &ada_ctx->port;
+	struct vdec_s *vdec = ada_ctx->vdec;
+	struct stream_buf_s *pbuf = NULL;
+
+	if (has_hevc_vdec()) {
+		pbuf = (port->type & PORT_TYPE_HEVC) ? &bufs[BUF_TYPE_HEVC] :
+			&bufs[BUF_TYPE_VIDEO];
+	} else
+		pbuf = &bufs[BUF_TYPE_VIDEO];
+
+	/*if (!(port_get_inited(priv))) {
+		r = video_decoder_init(priv);
+		if (r < 0)
+			return r;
+	}*/
+
+	do {
+		if (vdec->port_flag & PORT_FLAG_DRM)
+			ret = drm_write(ada_ctx->filp, pbuf, buf, count);
+		else
+			ret = esparser_write(ada_ctx->filp, pbuf, buf, count);
+
+		if (ret == -EAGAIN)
+			msleep(30);
+	} while (ret == -EAGAIN && try_cnt--);
+
+	if (slow_input) {
+		v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO,
+			"slow_input: es codec write size %x\n", ret);
+		msleep(10);
+	}
+
+#ifdef DATA_DEBUG
+	/* dump to file */
+	//dump_write(vbuf, size);
+	//v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO, "vbuf: %p, size: %u, ret: %d\n", vbuf, size, ret);
+#endif
+
+	return ret;
+}
+
+bool vdec_input_full(struct aml_vdec_adapt *ada_ctx)
+{
+	struct vdec_s *vdec = ada_ctx->vdec;
+
+	return (vdec->input.have_frame_num > 60) ? true : false;
+}
+
+int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx,
+	const char *buf, unsigned int count, u64 timestamp, ulong meta_ptr)
+{
+	int ret = -1;
+	struct vdec_s *vdec = ada_ctx->vdec;
+
+	/* set timestamp */
+	vdec_set_timestamp(vdec, timestamp);
+
+	/* set metadata */
+	vdec_set_metadata(vdec, meta_ptr);
+
+	ret = vdec_write_vframe(vdec, buf, count);
+
+	if (slow_input) {
+		v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO,
+			"slow_input: frame codec write size %d\n", ret);
+		msleep(30);
+	}
+
+	if (dump_output_frame > 0 &&
+		(!dump_output_start_position ||
+		(dump_output_start_position == crc32_le(0, buf, count)))) {
+		dump("/data/es.data", buf, count);
+		dump_output_frame--;
+		dump_output_start_position = 0;
+	}
+
+	v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_INPUT,
+		"write frames, vbuf: %p, size: %u, ret: %d, crc: %x, ts: %llu\n",
+		buf, count, ret, crc32_le(0, buf, count), timestamp);
+
+	return ret;
+}
+
+void vdec_vframe_input_free(void *priv, u32 handle)
+{
+	struct aml_vcodec_ctx *ctx = priv;
+
+	aml_recycle_dma_buffers(ctx, handle);
+}
+
+int vdec_vframe_write_with_dma(struct aml_vdec_adapt *ada_ctx,
+	ulong addr, u32 count, u64 timestamp, u32 handle,
+	chunk_free free, void* priv)
+{
+	int ret = -1;
+	struct vdec_s *vdec = ada_ctx->vdec;
+
+	/* set timestamp */
+	vdec_set_timestamp(vdec, timestamp);
+
+	ret = vdec_write_vframe_with_dma(vdec, addr, count,
+		handle, free, priv);
+
+	if (slow_input) {
+		v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO,
+			"slow_input: frame codec write size %d\n", ret);
+		msleep(30);
+	}
+
+	v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_INPUT,
+		"write frames, vbuf: %lx, size: %u, ret: %d, ts: %llu\n",
+		addr, count, ret, timestamp);
+
+	return ret;
+}
+
+void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx)
+{
+	struct vdec_s *vdec = ada_ctx->vdec;
+
+	if (vdec)
+		vdec_set_eos(vdec, true);
+}
+
+int aml_codec_reset(struct aml_vdec_adapt *ada_ctx, int *mode)
+{
+	struct vdec_s *vdec = ada_ctx->vdec;
+	int ret = 0;
+
+	if (vdec) {
+		if (ada_ctx->ctx->v4l_resolution_change)
+			*mode = V4L_RESET_MODE_LIGHT;
+		else
+			vdec_set_eos(vdec, false);
+
+		v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO,
+			"reset mode: %d, es frames buffering: %d\n",
+			*mode, vdec_frame_number(ada_ctx));
+
+		ret = vdec_v4l2_reset(vdec, *mode);
+		*mode = V4L_RESET_MODE_NORMAL;
+	}
+
+	return ret;
+}
+
+bool is_input_ready(struct aml_vdec_adapt *ada_ctx)
+{
+	struct vdec_s *vdec = ada_ctx->vdec;
+	int state = VDEC_STATUS_UNINITIALIZED;
+
+	if (vdec) {
+		state = vdec_get_status(vdec);
+
+		if (state == VDEC_STATUS_CONNECTED
+			|| state == VDEC_STATUS_ACTIVE)
+			return true;
+	}
+
+	return false;
+}
+
+int vdec_frame_number(struct aml_vdec_adapt *ada_ctx)
+{
+	struct vdec_s *vdec = ada_ctx->vdec;
+
+	if (vdec)
+		return vdec_get_frame_num(vdec);
+	else
+		return -1;
+}
+
+int vdec_get_instance_num(void)
+{
+	return vdec_get_core_nr();
+}
+
+void v4l2_config_vdec_parm(struct aml_vdec_adapt *ada_ctx, u8 *data, u32 len)
+{
+	struct vdec_s *vdec = ada_ctx->vdec;
+
+	vdec->config_len = len > PAGE_SIZE ? PAGE_SIZE : len;
+	memcpy(vdec->config, data, vdec->config_len);
+}
+
+void vdec_set_duration(s32 duration)
+{
+	vdec_frame_rate_uevent(duration);
+}
diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.h b/drivers/amvdec_ports/aml_vcodec_adapt.h
new file mode 100644
index 0000000..c8641ce
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.h
@@ -0,0 +1,79 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#ifndef VDEC_ADAPT_H
+#define VDEC_ADAPT_H
+
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include "../stream_input/amports/streambuf.h"
+#include "../frame_provider/decoder/utils/vdec_input.h"
+#include "aml_vcodec_drv.h"
+
+struct aml_vdec_adapt {
+	int format;
+	void *vsi;
+	int32_t failure;
+	uint32_t inst_addr;
+	unsigned int signaled;
+	struct aml_vcodec_ctx *ctx;
+	wait_queue_head_t wq;
+	struct file *filp;
+	struct vdec_s *vdec;
+	struct stream_port_s port;
+	struct dec_sysinfo dec_prop;
+	struct v4l2_config_parm config;
+	int video_type;
+	char *frm_name;
+};
+
+int video_decoder_init(struct aml_vdec_adapt *ada_ctx);
+
+int video_decoder_release(struct aml_vdec_adapt *ada_ctx);
+
+int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx,
+	const char *buf, unsigned int count);
+
+int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx,
+	const char *buf, unsigned int count, u64 timestamp, ulong meta_ptr);
+
+void vdec_vframe_input_free(void *priv, u32 handle);
+
+int vdec_vframe_write_with_dma(struct aml_vdec_adapt *ada_ctx,
+	ulong addr, u32 count, u64 timestamp, u32 handle,
+	chunk_free free, void *priv);
+
+bool vdec_input_full(struct aml_vdec_adapt *ada_ctx);
+
+void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx);
+
+int aml_codec_reset(struct aml_vdec_adapt *ada_ctx, int *flag);
+
+extern void dump_write(const char __user *buf, size_t count);
+
+bool is_input_ready(struct aml_vdec_adapt *ada_ctx);
+
+int vdec_frame_number(struct aml_vdec_adapt *ada_ctx);
+
+int vdec_get_instance_num(void);
+
+void vdec_set_duration(s32 duration);
+
+#endif /* VDEC_ADAPT_H */
+
diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c
new file mode 100644
index 0000000..2bbfb6e
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_dec.c
@@ -0,0 +1,4593 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-dma-sg.h>
+
+#include <linux/delay.h>
+#include <linux/atomic.h>
+#include <linux/crc32.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/amlogic/meson_uvm_core.h>
+#include <linux/scatterlist.h>
+#include <linux/sched/clock.h>
+#include <linux/highmem.h>
+#include <uapi/linux/sched/types.h>
+
+#include "aml_vcodec_drv.h"
+#include "aml_vcodec_dec.h"
+#include "aml_vcodec_util.h"
+#include "vdec_drv_if.h"
+#include "aml_vcodec_adapt.h"
+#include "aml_vcodec_vpp.h"
+#include "aml_vcodec_ge2d.h"
+
+#include "../frame_provider/decoder/utils/decoder_bmmu_box.h"
+#include "../frame_provider/decoder/utils/decoder_mmu_box.h"
+#include "../common/chips/decoder_cpu_ver_info.h"
+#include "utils/common.h"
+#include "../frame_provider/decoder/utils/vdec_sync.h"
+
+
+#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2
+#include <trace/events/meson_atrace.h>
+
+
+#define OUT_FMT_IDX		(0) //default h264
+#define CAP_FMT_IDX		(9) //capture nv21
+#define CAP_FMT_I420_IDX	(12) //use for mjpeg
+
+#define AML_VDEC_MIN_W	64U
+#define AML_VDEC_MIN_H	64U
+#define DFT_CFG_WIDTH	AML_VDEC_MIN_W
+#define DFT_CFG_HEIGHT	AML_VDEC_MIN_H
+
+#define V4L2_CID_USER_AMLOGIC_BASE (V4L2_CID_USER_BASE + 0x1100)
+#define AML_V4L2_SET_DRMMODE (V4L2_CID_USER_AMLOGIC_BASE + 0)
+#define AML_V4L2_GET_INPUT_BUFFER_NUM (V4L2_CID_USER_AMLOGIC_BASE + 1)
+#define AML_V4L2_SET_DURATION (V4L2_CID_USER_AMLOGIC_BASE + 2)
+#define AML_V4L2_GET_FILMGRAIN_INFO (V4L2_CID_USER_AMLOGIC_BASE + 3)
+
+#define WORK_ITEMS_MAX (32)
+#define MAX_DI_INSTANCE (2)
+
+//#define USEC_PER_SEC 1000000
+
+#define call_void_memop(vb, op, args...)				\
+	do {								\
+		if ((vb)->vb2_queue->mem_ops->op)			\
+			(vb)->vb2_queue->mem_ops->op(args);		\
+	} while (0)
+
+static struct aml_video_fmt aml_video_formats[] = {
+	{
+		.name = "H.264",
+		.fourcc = V4L2_PIX_FMT_H264,
+		.type = AML_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.name = "H.265",
+		.fourcc = V4L2_PIX_FMT_HEVC,
+		.type = AML_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.name = "VP9",
+		.fourcc = V4L2_PIX_FMT_VP9,
+		.type = AML_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.name = "MPEG1",
+		.fourcc = V4L2_PIX_FMT_MPEG1,
+		.type = AML_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.name = "MPEG2",
+		.fourcc = V4L2_PIX_FMT_MPEG2,
+		.type = AML_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.name = "MPEG4",
+		.fourcc = V4L2_PIX_FMT_MPEG4,
+		.type = AML_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.name = "MJPEG",
+		.fourcc = V4L2_PIX_FMT_MJPEG,
+		.type = AML_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.name = "AV1",
+		.fourcc = V4L2_PIX_FMT_AV1,
+		.type = AML_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.name = "NV21",
+		.fourcc = V4L2_PIX_FMT_NV21,
+		.type = AML_FMT_FRAME,
+		.num_planes = 1,
+	},
+	{
+		.name = "NV21M",
+		.fourcc = V4L2_PIX_FMT_NV21M,
+		.type = AML_FMT_FRAME,
+		.num_planes = 2,
+	},
+	{
+		.name = "NV12",
+		.fourcc = V4L2_PIX_FMT_NV12,
+		.type = AML_FMT_FRAME,
+		.num_planes = 1,
+	},
+	{
+		.name = "NV12M",
+		.fourcc = V4L2_PIX_FMT_NV12M,
+		.type = AML_FMT_FRAME,
+		.num_planes = 2,
+	},
+	{
+		.name = "YUV420",
+		.fourcc = V4L2_PIX_FMT_YUV420,
+		.type = AML_FMT_FRAME,
+		.num_planes = 1,
+	},
+	{
+		.name = "YUV420M",
+		.fourcc = V4L2_PIX_FMT_YUV420M,
+		.type = AML_FMT_FRAME,
+		.num_planes = 2,
+	},
+};
+
+static const struct aml_codec_framesizes aml_vdec_framesizes[] = {
+	{
+		.fourcc	= V4L2_PIX_FMT_H264,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+	{
+		.fourcc	= V4L2_PIX_FMT_HEVC,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP9,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_MPEG1,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_MPEG2,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_MPEG4,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_MJPEG,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_AV1,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV21,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV21M,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV12,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV12M,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YUV420,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YUV420M,
+		.stepwise = {  AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
+				AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
+	},
+};
+
+#define NUM_SUPPORTED_FRAMESIZE ARRAY_SIZE(aml_vdec_framesizes)
+#define NUM_FORMATS ARRAY_SIZE(aml_video_formats)
+
+extern bool multiplanar;
+extern int dump_capture_frame;
+extern int bypass_vpp;
+extern int bypass_ge2d;
+extern bool support_format_I420;
+extern bool support_mjpeg;
+extern int bypass_progressive;
+extern int force_enable_nr;
+extern int force_enable_di_local_buffer;
+extern int max_di_instance;
+extern int bypass_nr_flag;
+
+extern int dmabuf_fd_install_data(int fd, void* data, u32 size);
+extern bool is_v4l2_buf_file(struct file *file);
+extern int get_double_write_ratio(int dw_mode);
+static void box_release(struct kref *kref);
+static struct internal_comp_buf* vb_to_comp(struct aml_vcodec_ctx *ctx,
+					    struct vb2_buffer *vb);
+static void update_ctx_dimension(struct aml_vcodec_ctx *ctx, u32 type);
+static void copy_v4l2_format_dimention(struct v4l2_pix_format_mplane *pix_mp,
+				       struct v4l2_pix_format *pix,
+				       struct aml_q_data *q_data,
+				       u32 type);
+
+static ulong aml_vcodec_ctx_lock(struct aml_vcodec_ctx *ctx)
+{
+	ulong flags;
+
+	spin_lock_irqsave(&ctx->slock, flags);
+
+	return flags;
+}
+
+static void aml_vcodec_ctx_unlock(struct aml_vcodec_ctx *ctx, ulong flags)
+{
+	spin_unlock_irqrestore(&ctx->slock, flags);
+}
+
+static ulong dmabuf_contiguous_size(struct sg_table *sgt)
+{
+	struct scatterlist *s;
+	dma_addr_t expected = sg_dma_address(sgt->sgl);
+	ulong size = 0;
+	u32 i;
+
+	for_each_sg(sgt->sgl, s, sgt->nents, i) {
+		if (sg_dma_address(s) != expected)
+			break;
+		expected = sg_dma_address(s) + sg_dma_len(s);
+		size += sg_dma_len(s);
+	}
+
+	return size;
+}
+
+static struct aml_video_fmt *aml_vdec_find_format(struct v4l2_format *f)
+{
+	struct aml_video_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < NUM_FORMATS; k++) {
+		fmt = &aml_video_formats[k];
+		if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static struct aml_q_data *aml_vdec_get_q_data(struct aml_vcodec_ctx *ctx,
+					      enum v4l2_buf_type type)
+{
+	if (V4L2_TYPE_IS_OUTPUT(type))
+		return &ctx->q_data[AML_Q_DATA_SRC];
+
+	return &ctx->q_data[AML_Q_DATA_DST];
+}
+
+void aml_vdec_dispatch_event(struct aml_vcodec_ctx *ctx, u32 changes)
+{
+	struct v4l2_event event = {0};
+
+	switch (changes) {
+	case V4L2_EVENT_SRC_CH_RESOLUTION:
+	case V4L2_EVENT_SRC_CH_HDRINFO:
+	case V4L2_EVENT_REQUEST_RESET:
+	case V4L2_EVENT_REQUEST_EXIT:
+		event.type = V4L2_EVENT_SOURCE_CHANGE;
+		event.u.src_change.changes = changes;
+		break;
+	case V4L2_EVENT_SEND_EOS:
+		event.type = V4L2_EVENT_EOS;
+		break;
+	default:
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"unsupport dispatch event %x\n", changes);
+		return;
+	}
+
+	v4l2_event_queue_fh(&ctx->fh, &event);
+	if (changes != V4L2_EVENT_SRC_CH_HDRINFO)
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "changes: %x\n", changes);
+	else
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO, "changes: %x\n", changes);
+}
+
+static void aml_vdec_flush_decoder(struct aml_vcodec_ctx *ctx)
+{
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO, "%s\n", __func__);
+
+	aml_decoder_flush(ctx->ada_ctx);
+}
+
+/* Conditions:
+ * Always connect VPP for mpeg2 and h264 when the stream size is under 2K.
+ * Always connect VPP for hevc/av1/vp9 when color space is not SDR and
+ *     stream size is under 2K.
+ * For DV, need application to notify V4L2 driver to enforce the color space
+ *     conversion. Plan to do it through a system node.
+ * Do not connect VPP in other cases.
+ */
+static bool vpp_needed(struct aml_vcodec_ctx *ctx, u32* mode)
+{
+	int width = ctx->picinfo.coded_width;
+	int height = ctx->picinfo.coded_height;
+	int size = 1920 * 1088;
+
+	if (bypass_vpp)
+		return false;
+
+	if (!ctx->vpp_cfg.enable_nr &&
+		(ctx->picinfo.field == V4L2_FIELD_NONE)) {
+		return false;
+	}
+
+	if (!ctx->vpp_cfg.enable_nr &&
+		(ctx->output_pix_fmt == V4L2_PIX_FMT_HEVC)) {
+		if (is_over_size(width, height, size)) {
+			return false;
+		}
+	}
+
+	if ((ctx->output_pix_fmt == V4L2_PIX_FMT_H264) &&
+		(ctx->picinfo.field != V4L2_FIELD_NONE)) {
+		if (is_over_size(width, height, size)) {
+			return false;
+		}
+	}
+
+	if (ctx->vpp_cfg.enable_nr) {
+		if (ctx->vpp_cfg.enable_local_buf)
+			*mode = VPP_MODE_NOISE_REDUC_LOCAL;
+		else
+			*mode = VPP_MODE_NOISE_REDUC;
+	} else {
+		if (ctx->vpp_cfg.enable_local_buf)
+			*mode = VPP_MODE_DI_LOCAL;
+		else
+			*mode = VPP_MODE_DI;
+	}
+
+#if 0//enable later
+	if (ctx->colorspace != V4L2_COLORSPACE_DEFAULT &&
+		!is_over_size(width, height, size)) {
+		if (ctx->vpp_cfg.enable_local_buf)
+			*mode = VPP_MODE_COLOR_CONV_LOCAL;
+		else
+			*mode = VPP_MODE_COLOR_CONV;
+	}
+#endif
+
+	return true;
+}
+
+static bool ge2d_needed(struct aml_vcodec_ctx *ctx, u32* mode)
+{
+	bool enable_fence = (ctx->config.parm.dec.cfg.low_latency_mode & 2) ? 1 : 0;
+
+	if ((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) && enable_fence) {
+		return false;
+	}
+
+	if (bypass_ge2d)
+		return false;
+
+	if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) {
+		if ((ctx->output_pix_fmt != V4L2_PIX_FMT_H264) &&
+			(ctx->output_pix_fmt != V4L2_PIX_FMT_MPEG1) &&
+			(ctx->output_pix_fmt != V4L2_PIX_FMT_MPEG2) &&
+			(ctx->output_pix_fmt != V4L2_PIX_FMT_MPEG4) &&
+			(ctx->output_pix_fmt != V4L2_PIX_FMT_MJPEG)) {
+			return false;
+		}
+	} else if (ctx->output_pix_fmt != V4L2_PIX_FMT_MJPEG) {
+			return false;
+	}
+
+	if (ctx->picinfo.field != V4L2_FIELD_NONE) {
+		return false;
+	}
+
+	if ((ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) ||
+		(ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12M))
+		*mode = GE2D_MODE_CONVERT_NV12;
+	else if ((ctx->cap_pix_fmt == V4L2_PIX_FMT_NV21) ||
+		(ctx->cap_pix_fmt == V4L2_PIX_FMT_NV21M))
+		*mode = GE2D_MODE_CONVERT_NV21;
+	else
+		*mode = GE2D_MODE_CONVERT_NV21;
+
+	*mode |= GE2D_MODE_CONVERT_LE;
+
+	return true;
+}
+
+static u32 v4l_buf_size_decision(struct aml_vcodec_ctx *ctx)
+{
+	u32 mode, total_size;
+	struct vdec_pic_info *picinfo = &ctx->picinfo;
+	struct aml_vpp_cfg_infos *vpp = &ctx->vpp_cfg;
+	struct aml_ge2d_cfg_infos *ge2d = &ctx->ge2d_cfg;
+
+	if (vpp_needed(ctx, &mode)) {
+		vpp->mode        = mode;
+		vpp->fmt         = ctx->cap_pix_fmt;
+		vpp->is_drm      = ctx->is_drm_mode;
+		vpp->buf_size = aml_v4l2_vpp_get_buf_num(vpp->mode)
+			+ picinfo->vpp_margin;
+
+		if (picinfo->field == V4L2_FIELD_NONE) {
+			vpp->is_prog = true;
+			vpp->buf_size = 0;
+		} else {
+			vpp->is_prog = false;
+			/* for between with dec & vpp. */
+			picinfo->dpb_margin = 2;
+		}
+
+		if (vpp->is_prog &&
+			!vpp->enable_local_buf &&
+			bypass_progressive) {
+			vpp->is_bypass_p = true;
+		}
+		ctx->vpp_is_need = true;
+	} else {
+		vpp->buf_size = 0;
+		ctx->vpp_is_need = false;
+	}
+
+	if (ge2d_needed(ctx, &mode)) {
+		ge2d->mode = mode;
+		ge2d->buf_size = 4 + picinfo->dpb_margin;
+		ctx->ge2d_is_need = true;
+		picinfo->dpb_margin = 2;
+	} else {
+		ge2d->buf_size = 0;
+		ctx->ge2d_is_need = false;
+	}
+
+	ctx->dpb_size = picinfo->dpb_frames + picinfo->dpb_margin;
+	ctx->vpp_size = vpp->buf_size;
+	ctx->ge2d_size = ge2d->buf_size;
+
+	total_size = ctx->dpb_size + ctx->vpp_size + ctx->ge2d_size;
+
+	if (total_size > V4L_CAP_BUFF_MAX) {
+		if (ctx->ge2d_size) {
+			ctx->dpb_size = V4L_CAP_BUFF_MAX - ctx->ge2d_size - ctx->vpp_size;
+		} else if (ctx->vpp_size) {
+			ctx->dpb_size = V4L_CAP_BUFF_MAX - ctx->vpp_size;
+		} else {
+			ctx->dpb_size = V4L_CAP_BUFF_MAX;
+		}
+		picinfo->dpb_margin = ctx->dpb_size - picinfo->dpb_frames;
+		total_size = V4L_CAP_BUFF_MAX;
+	}
+	vdec_if_set_param(ctx, SET_PARAM_PIC_INFO, picinfo);
+
+	return total_size;
+}
+
+void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx)
+{
+	if (vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->last_decoded_picinfo)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"Cannot get param : GET_PARAM_PICTURE_INFO ERR\n");
+		return;
+	}
+
+	if (ctx->last_decoded_picinfo.visible_width == 0 ||
+		ctx->last_decoded_picinfo.visible_height == 0 ||
+		ctx->last_decoded_picinfo.coded_width == 0 ||
+		ctx->last_decoded_picinfo.coded_height == 0) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"Cannot get correct pic info\n");
+		return;
+	}
+
+	/*if ((ctx->last_decoded_picinfo.visible_width == ctx->picinfo.visible_width) ||
+	    (ctx->last_decoded_picinfo.visible_height == ctx->picinfo.visible_height))
+		return;*/
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+		"new(%d,%d), old(%d,%d), real(%d,%d)\n",
+			ctx->last_decoded_picinfo.visible_width,
+			ctx->last_decoded_picinfo.visible_height,
+			ctx->picinfo.visible_width, ctx->picinfo.visible_height,
+			ctx->last_decoded_picinfo.coded_width,
+			ctx->last_decoded_picinfo.coded_width);
+
+	ctx->picinfo = ctx->last_decoded_picinfo;
+
+	if (ctx->vpp_is_need)
+		ctx->vpp_cfg.is_vpp_reset = true;
+
+	v4l_buf_size_decision(ctx);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Update picture buffer count: dec:%u, vpp:%u, ge2d:%u, margin:%u, total:%u\n",
+		ctx->picinfo.dpb_frames, ctx->vpp_size, ctx->ge2d_size,
+		ctx->picinfo.dpb_margin,
+		CTX_BUF_TOTAL(ctx));
+}
+
+void vdec_frame_buffer_release(void *data)
+{
+	struct file_private_data *priv_data =
+		(struct file_private_data *) data;
+	struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)
+		priv_data->v4l_dec_ctx;
+	struct aml_video_dec_buf *vb = (struct aml_video_dec_buf *)
+		priv_data->vb_handle;
+	struct uvm_hook_mod_info *uvm = NULL;
+
+	if (ctx && ctx->uvm_proxy) {
+		uvm = &ctx->uvm_proxy[vb->internal_index];
+		uvm->free(uvm->arg);
+	}
+
+	memset(data, 0, sizeof(struct file_private_data));
+	kfree(data);
+}
+
+static void v4l2_buff_done(struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state)
+{
+	struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(buf->vb2_buf.vb2_queue);
+
+	mutex_lock(&ctx->buff_done_lock);
+	if (buf->vb2_buf.state != VB2_BUF_STATE_ACTIVE) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "vb is not active state = %d!\n",
+			buf->vb2_buf.state);
+		mutex_unlock(&ctx->buff_done_lock);
+		return;
+	}
+	v4l2_m2m_buf_done(buf, state);
+	mutex_unlock(&ctx->buff_done_lock);
+}
+
+static void comp_buf_set_vframe(struct aml_vcodec_ctx *ctx,
+			 struct vb2_buffer *vb,
+			 struct vframe_s *vf)
+{
+	dmabuf_set_vframe(vb->planes[0].dbuf, vf, VF_SRC_DECODER);
+}
+
+static void fb_map_table_clean(struct aml_vcodec_ctx *ctx)
+{
+	int i;
+	ulong flags;
+
+	flags = aml_vcodec_ctx_lock(ctx);
+
+	for (i = 0; i < ARRAY_SIZE(ctx->fb_map); i++) {
+		ctx->fb_map[i].addr	= 0;
+		ctx->fb_map[i].vframe	= NULL;
+		ctx->fb_map[i].task	= NULL;
+		ctx->fb_map[i].icomp	= 0;
+	}
+
+	aml_vcodec_ctx_unlock(ctx, flags);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "%s done\n", __func__);
+}
+
+static void fb_map_table_hold(struct aml_vcodec_ctx *ctx,
+				struct vb2_buffer *vb,
+				struct vframe_s *vf,
+				struct task_chain_s *task,
+				u32 icomp)
+{
+	int i;
+	ulong addr, flags;
+
+	flags = aml_vcodec_ctx_lock(ctx);
+
+	addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+	for (i = 0; i < ARRAY_SIZE(ctx->fb_map); i++) {
+		if (!ctx->fb_map[i].addr ||
+			(addr == ctx->fb_map[i].addr)) {
+			ctx->fb_map[i].task	= task;
+			ctx->fb_map[i].addr	= addr;
+			ctx->fb_map[i].vframe	= vf;
+			ctx->fb_map[i].icomp	= icomp;
+
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+				"%s, task:%px, vf:%px, addr:%lx, icomp:%u\n",
+				__func__, task, vf, addr, icomp);
+			break;
+		}
+	}
+
+	aml_vcodec_ctx_unlock(ctx, flags);
+
+	if (i >= ARRAY_SIZE(ctx->fb_map)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"%s, table is full. addr:%lx, vf:%px\n",
+			__func__, addr, vf);
+	}
+}
+
+static void fb_map_table_fetch(struct aml_vcodec_ctx *ctx,
+				struct vb2_buffer *vb,
+				struct vframe_s **vf,
+				struct task_chain_s **task,
+				u32 *icomp)
+{
+	int i;
+	ulong addr, flags;
+
+	flags = aml_vcodec_ctx_lock(ctx);
+
+	addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+	for (i = 0; i < ARRAY_SIZE(ctx->fb_map); i++) {
+		if (addr == ctx->fb_map[i].addr) {
+			*task = ctx->fb_map[i].task;
+			*vf = ctx->fb_map[i].vframe;
+			*icomp = ctx->fb_map[i].icomp;
+
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+				"%s, task:%px, vf:%px, addr:%lx, icomp:%u\n",
+				__func__, task, vf, addr, *icomp);
+
+			ctx->fb_map[i].task	= NULL;
+			ctx->fb_map[i].vframe	= NULL;
+			ctx->fb_map[i].addr	= 0;
+			ctx->fb_map[i].icomp	= 0;
+			break;
+		}
+	}
+
+	aml_vcodec_ctx_unlock(ctx, flags);
+
+	if (i >= ARRAY_SIZE(ctx->fb_map)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+			"%s, there is new addr:%lx.\n",
+			__func__, addr);
+	}
+}
+
+static bool is_fb_mapped(struct aml_vcodec_ctx *ctx, ulong addr)
+{
+	int i;
+	ulong flags;
+
+	flags = aml_vcodec_ctx_lock(ctx);
+
+	for (i = 0; i < ARRAY_SIZE(ctx->fb_map); i++) {
+		if (addr == ctx->fb_map[i].addr)
+			break;
+	}
+
+	aml_vcodec_ctx_unlock(ctx, flags);
+
+	if (i >= ARRAY_SIZE(ctx->fb_map)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+			"%s, addr:%lx isn't output.\n",
+			__func__, addr);
+		return false;
+	}
+
+	return true;
+}
+
+ static void post_frame_to_upper(struct aml_vcodec_ctx *ctx,
+	struct vdec_v4l2_buffer *fb)
+{
+	struct aml_video_dec_buf *dstbuf =
+		container_of(fb, struct aml_video_dec_buf, frame_buffer);
+	struct vb2_buffer *vb2_buf = &dstbuf->vb.vb2_buf;
+	struct vframe_s *vf = fb->vframe;
+	struct vb2_v4l2_buffer *vb2_v4l2 = NULL;
+
+	vf->index_disp = ctx->index_disp;
+	ctx->index_disp++;
+	ctx->post_to_upper_done = false;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_OUTPUT,
+		"OUT_BUFF (%s, st:%d, seq:%d) vb:(%d, %px), vf:(%d, %px), ts:%lld, "
+		"Y:(%lx, %u) C/U:(%lx, %u) V:(%lx, %u)\n",
+		ctx->ada_ctx->frm_name, fb->status, vf->index_disp,
+		vb2_buf->index, vb2_buf,
+		vf->index & 0xff, vf,
+		vf->timestamp,
+		fb->m.mem[0].addr, fb->m.mem[0].size,
+		fb->m.mem[1].addr, fb->m.mem[1].size,
+		fb->m.mem[2].addr, fb->m.mem[2].size);
+
+	vb2_v4l2 = container_of(vb2_buf, struct vb2_v4l2_buffer, vb2_buf);
+
+	if (dstbuf->frame_buffer.num_planes == 1) {
+		vb2_set_plane_payload(vb2_buf, 0, fb->m.mem[0].bytes_used);
+	} else if (dstbuf->frame_buffer.num_planes == 2) {
+		vb2_set_plane_payload(vb2_buf, 0, fb->m.mem[0].bytes_used);
+		vb2_set_plane_payload(vb2_buf, 1, fb->m.mem[1].bytes_used);
+	}
+	vb2_buf->timestamp = vf->timestamp;
+	dstbuf->vb.flags |= vf->frame_type;
+
+	if ((ctx->picinfo.field == V4L2_FIELD_INTERLACED) && (!ctx->vpp_is_need)) {
+		vb2_v4l2->field = V4L2_FIELD_INTERLACED;
+	}
+
+	do {
+		unsigned int dw_mode = VDEC_DW_NO_AFBC;
+		struct file *fp;
+		char file_name[32] = {0};
+
+		if (!dump_capture_frame || ctx->is_drm_mode)
+			break;
+		if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode))
+			break;
+		if (dw_mode == VDEC_DW_AFBC_ONLY)
+			break;
+
+		snprintf(file_name, 32, "/data/dec_dump_%ux%u.raw", vf->width, vf->height);
+
+		fp = filp_open(file_name,
+				O_CREAT | O_RDWR | O_LARGEFILE | O_APPEND, 0600);
+
+		if (!IS_ERR(fp)) {
+			struct vb2_buffer *vb = vb2_buf;
+
+			kernel_write(fp,vb2_plane_vaddr(vb, 0),vb->planes[0].length, 0);
+			if (dstbuf->frame_buffer.num_planes == 2)
+				kernel_write(fp,vb2_plane_vaddr(vb, 1),
+						vb->planes[1].length, 0);
+			pr_info("dump idx: %d %dx%d\n", dump_capture_frame, vf->width, vf->height);
+			dump_capture_frame--;
+			filp_close(fp, NULL);
+		}
+	} while(0);
+
+	ATRACE_COUNTER("VC_OUT_VSINK-1.submit", vb2_buf->index);
+	ATRACE_COUNTER("V_ST_VSINK-input_buffering", vdec_frame_number(ctx->ada_ctx));
+
+	if (vf->flag & VFRAME_FLAG_EMPTY_FRAME_V4L) {
+		dstbuf->vb.flags = V4L2_BUF_FLAG_LAST;
+		if (dstbuf->frame_buffer.num_planes == 1) {
+			vb2_set_plane_payload(vb2_buf, 0, 0);
+		} else if (dstbuf->frame_buffer.num_planes == 2) {
+			vb2_set_plane_payload(vb2_buf, 0, 0);
+			vb2_set_plane_payload(vb2_buf, 1, 0);
+		}
+		ctx->has_receive_eos = true;
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+			"recevie a empty frame. idx: %d, state: %d\n",
+			vb2_buf->index, vb2_buf->state);
+	}
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+		"receive vbuf idx: %d, state: %d\n",
+		vb2_buf->index, vb2_buf->state);
+
+	if (vf->flag & VFRAME_FLAG_EMPTY_FRAME_V4L) {
+		if (ctx->v4l_resolution_change) {
+			/* make the run to stanby until new buffs to enque. */
+			ctx->v4l_codec_dpb_ready = false;
+			ctx->reset_flag = V4L_RESET_MODE_LIGHT;
+			ctx->vpp_cfg.res_chg = true;
+
+			/*
+			 * After all buffers containing decoded frames from
+			 * before the resolution change point ready to be
+			 * dequeued on the CAPTURE queue, the driver sends a
+			 * V4L2_EVENT_SOURCE_CHANGE event for source change
+			 * type V4L2_EVENT_SRC_CH_RESOLUTION, also the upper
+			 * layer will get new information from cts->picinfo.
+			 */
+			aml_vdec_dispatch_event(ctx, V4L2_EVENT_SRC_CH_RESOLUTION);
+		} else
+			aml_vdec_dispatch_event(ctx, V4L2_EVENT_SEND_EOS);
+	}
+
+	if (dstbuf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE) {
+		/* binding vframe handle. */
+		if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) {
+			if (vf->canvas0_config[0].block_mode == CANVAS_BLKMODE_LINEAR) {
+				if ((ctx->output_pix_fmt != V4L2_PIX_FMT_H264) &&
+					(ctx->output_pix_fmt != V4L2_PIX_FMT_MPEG1) &&
+					(ctx->output_pix_fmt != V4L2_PIX_FMT_MPEG2) &&
+					(ctx->output_pix_fmt != V4L2_PIX_FMT_MPEG4) &&
+					(ctx->output_pix_fmt != V4L2_PIX_FMT_MJPEG)) {
+					vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
+				}
+				else {
+					if (fb->status == FB_ST_GE2D)
+						vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
+				}
+			}
+		} else {
+			if (vf->canvas0_config[0].block_mode == CANVAS_BLKMODE_LINEAR)
+				vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
+		}
+
+		vf->omx_index = vf->index_disp;
+		dstbuf->privdata.vf = *vf;
+
+		if (vb2_buf->memory == VB2_MEMORY_DMABUF) {
+			struct dma_buf * dma;
+
+			dma = dstbuf->vb.vb2_buf.planes[0].dbuf;
+			if (dmabuf_is_uvm(dma)) {
+				/* only Y will contain vframe */
+				comp_buf_set_vframe(ctx, vb2_buf, vf);
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+					"set vf(%px) into %dth buf\n",
+					vf, vb2_buf->index);
+			}
+		}
+
+		fb_map_table_hold(ctx, vb2_buf, vf, fb->task, dstbuf->internal_index);
+
+		v4l2_buff_done(&dstbuf->vb, VB2_BUF_STATE_DONE);
+
+		fb->status = FB_ST_DISPLAY;
+	}
+
+	mutex_lock(&ctx->state_lock);
+	if (ctx->state == AML_STATE_FLUSHING &&
+		ctx->has_receive_eos) {
+		ctx->state = AML_STATE_FLUSHED;
+		ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
+			"vcodec state (AML_STATE_FLUSHED)\n");
+	}
+	mutex_unlock(&ctx->state_lock);
+
+	if (ctx->post_to_upper_done == false) {
+		ctx->post_to_upper_done = true;
+		wake_up_interruptible(&ctx->post_done_wq);
+	}
+
+	ctx->decoded_frame_cnt++;
+}
+
+static void fill_capture_done_cb(void *v4l_ctx, void *fb_ctx)
+{
+	struct aml_vcodec_ctx *ctx =
+		(struct aml_vcodec_ctx *)v4l_ctx;
+	struct vdec_v4l2_buffer *fb =
+		(struct vdec_v4l2_buffer *)fb_ctx;
+	struct aml_video_dec_buf *aml_buff =
+		container_of(fb, struct aml_video_dec_buf, frame_buffer);
+	struct vb2_v4l2_buffer *vb = &aml_buff->vb;
+
+	if (ctx->is_stream_off) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT,
+			"ignore buff idx: %d streamoff\n", fb->buf_idx);
+		return;
+	}
+
+	ATRACE_COUNTER("VC_OUT_VSINK-0.receive", vb->vb2_buf.index);
+
+	mutex_lock(&ctx->capture_buffer_lock);
+	kfifo_put(&ctx->capture_buffer, vb);
+	mutex_unlock(&ctx->capture_buffer_lock);
+
+	aml_thread_post_task(ctx, AML_THREAD_CAPTURE);
+}
+
+static void update_vdec_buf_plane(struct aml_vcodec_ctx *ctx,
+				  struct vdec_v4l2_buffer *fb,
+				  struct vb2_buffer *vb)
+{
+	int i;
+	char plane_n[3] = {'Y','U','V'};
+
+	fb->num_planes = vb->num_planes;
+	fb->buf_idx = vb->index;
+
+	for (i = 0 ; i < vb->num_planes ; i++) {
+		fb->m.mem[i].addr	= vb2_dma_contig_plane_dma_addr(vb, i);
+		fb->m.mem[i].dbuf	= vb->planes[i].dbuf;
+		if (i == 0) {
+			//Y
+			if (vb->num_planes == 1) {
+				fb->m.mem[0].size	= ctx->picinfo.y_len_sz +
+					ctx->picinfo.c_len_sz;
+				fb->m.mem[0].offset = ctx->picinfo.y_len_sz;
+			} else {
+				fb->m.mem[0].size	= ctx->picinfo.y_len_sz;
+				fb->m.mem[0].offset = 0;
+			}
+		} else {
+			if (vb->num_planes == 2) {
+				//UV
+				fb->m.mem[1].size	= ctx->picinfo.c_len_sz;
+				fb->m.mem[1].offset = ctx->picinfo.c_len_sz >> 1;
+			} else {
+				fb->m.mem[i].size  = ctx->picinfo.c_len_sz >> 1;
+				fb->m.mem[i].offset = 0;
+			}
+		}
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+				"idx: %u, %c:(0x%lx, %d)\n", vb->index,
+				plane_n[i], fb->m.mem[i].addr, fb->m.mem[i].size);
+	}
+}
+
+static bool fb_token_insert(struct aml_vcodec_ctx *ctx,
+			    ulong *token)
+{
+	ulong vb_handle;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ctx->token_table); i++) {
+		if (ctx->token_table[i] &&
+			(ctx->token_table[i] == *token)) {
+			return true;
+		}
+	}
+
+	if (!v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx))
+		return false;
+
+	vb_handle = (ulong)v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+
+	for (i = 0; i < ARRAY_SIZE(ctx->token_table); i++) {
+		if (!ctx->token_table[i]) {
+			ctx->token_table[i] = vb_handle;
+			break;
+		}
+	}
+
+	if (i >= ARRAY_SIZE(ctx->token_table)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"%s, table is full. token:%lx\n",
+			__func__, vb_handle);
+		return false;
+	}
+
+	*token = vb_handle;
+
+	return true;
+}
+
+static void fb_token_remove(struct aml_vcodec_ctx *ctx,
+			    ulong token)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ctx->token_table); i++) {
+		if (token == ctx->token_table[i]) {
+			ctx->token_table[i] = 0;
+			break;
+		}
+	}
+
+	if (i >= ARRAY_SIZE(ctx->token_table)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"%s, remove token err, token:%lx.\n",
+			__func__, token);
+	}
+}
+
+static void fb_token_clean(struct aml_vcodec_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ctx->token_table); i++) {
+		ctx->token_table[i] = 0;
+	}
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "%s done\n", __func__);
+}
+
+static bool fb_buff_query(struct aml_fb_ops *fb, ulong *token)
+{
+	struct aml_vcodec_ctx *ctx =
+		container_of(fb, struct aml_vcodec_ctx, fb_ops);
+	struct vb2_queue * que = v4l2_m2m_get_dst_vq(ctx->m2m_ctx);
+	bool ret = false;
+	ulong flags;
+
+	if (!que->streaming)
+		return false;
+
+	flags = aml_vcodec_ctx_lock(ctx);
+
+	ret = fb_token_insert(ctx, token);
+
+	aml_vcodec_ctx_unlock(ctx, flags);
+
+	return ret;
+}
+
+static void aml_task_chain_remove(struct aml_vcodec_ctx *ctx)
+{
+	struct task_chain_s *task, *tmp;
+
+	list_for_each_entry_safe(task, tmp, &ctx->task_chain_pool, node) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+			"remove task chain:%d, %px\n", task->id, task);
+		list_del(&task->node);
+		task_chain_clean(task);
+		task_chain_release(task);
+	}
+}
+
+static struct task_ops_s *get_v4l_sink_ops(void);
+
+static void aml_creat_pipeline(struct aml_vcodec_ctx *ctx,
+			       struct vdec_v4l2_buffer *fb,
+			       u32 requester)
+{
+	struct task_chain_s *task = fb->task;
+	/*
+	 * line 1: dec <==> vpp <==> v4l-sink, for P / P + DI.NR.
+	 * line 2: dec <==> vpp, vpp <==> v4l-sink, for I / I + DI.NR.
+	 * line 3: dec <==> v4l-sink, only for P.
+	 * line 4: dec <==> ge2d, ge2d <==> v4l-sink, used for fmt convert.
+	 * line 5: dec <==> ge2d, ge2d <==>vpp, vpp <==> v4l-sink.
+	 * line 6: dec <==> ge2d, ge2d <==> vpp <==> v4l-sink.
+	 */
+
+	switch (requester) {
+	case AML_FB_REQ_DEC:
+		if (ctx->ge2d) {
+			/* dec <==> ge2d. */
+			task->attach(task, get_ge2d_ops(), ctx->ge2d);
+		} else if (ctx->vpp) {
+			if (ctx->vpp->is_prog) {
+				/* dec <==> vpp <==> v4l-sink. */
+				task->attach(task, get_v4l_sink_ops(), ctx);
+				task->attach(task, get_vpp_ops(), ctx->vpp);
+			} else {
+				/* dec <==> vpp. */
+				task->attach(task, get_vpp_ops(), ctx->vpp);
+			}
+		} else {
+			/* dec <==> v4l-sink. */
+			task->attach(task, get_v4l_sink_ops(), ctx);
+		}
+		break;
+
+	case AML_FB_REQ_GE2D:
+		if (ctx->vpp) {
+			if (ctx->vpp->is_prog) {
+				/* ge2d <==> vpp <==> v4l-sink. */
+				task->attach(task, get_v4l_sink_ops(), ctx);
+				task->attach(task, get_vpp_ops(), ctx->vpp);
+				task->attach(task, get_ge2d_ops(), ctx->ge2d);
+			} else {
+				/* ge2d <==> vpp. */
+				task->attach(task, get_vpp_ops(), ctx->vpp);
+				task->attach(task, get_ge2d_ops(), ctx->ge2d);
+			}
+		} else {
+			/* ge2d <==> v4l-sink. */
+			task->attach(task, get_v4l_sink_ops(), ctx);
+			task->attach(task, get_ge2d_ops(), ctx->ge2d);
+		}
+		break;
+
+	case AML_FB_REQ_VPP:
+		/* vpp <==> v4l-sink. */
+		task->attach(task, get_v4l_sink_ops(), ctx);
+		task->attach(task, get_vpp_ops(), ctx->vpp);
+		break;
+
+	default:
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"unsupport requester %x\n", requester);
+	}
+}
+
+static int fb_buff_from_queue(struct aml_fb_ops *fb_ops,
+		ulong token, struct vdec_v4l2_buffer **out_fb,
+		u32 requester)
+{
+	struct aml_vcodec_ctx *ctx =
+		container_of(fb_ops, struct aml_vcodec_ctx, fb_ops);
+	struct aml_video_dec_buf *aml_buf = NULL;
+	struct vb2_v4l2_buffer *v4l_buf = NULL;
+	struct vdec_v4l2_buffer *fb = NULL;
+	u32 buf_status = 0;
+	ulong flags;
+
+	flags = aml_vcodec_ctx_lock(ctx);
+
+	if (ctx->is_stream_off) {
+		aml_vcodec_ctx_unlock(ctx, flags);
+		return -1;
+	}
+
+	v4l_buf = (struct vb2_v4l2_buffer *) token;
+	if (!v4l_buf) {
+		aml_vcodec_ctx_unlock(ctx, flags);
+		return -1;
+	}
+
+	aml_buf = container_of(v4l_buf, struct aml_video_dec_buf, vb);
+
+	fb		= &aml_buf->frame_buffer;
+	fb->buf_idx	= v4l_buf->vb2_buf.index;
+	aml_buf->used	= true;
+	ctx->buf_used_count++;
+
+	if (requester == AML_FB_REQ_VPP) {
+		buf_status = V4L_CAP_BUFF_IN_VPP;
+		ctx->cap_pool.vpp++;
+	} else if (requester == AML_FB_REQ_DEC) {
+		buf_status = V4L_CAP_BUFF_IN_DEC;
+		ctx->cap_pool.dec++;
+	} else if (requester == AML_FB_REQ_GE2D) {
+		buf_status = V4L_CAP_BUFF_IN_GE2D;
+		ctx->cap_pool.ge2d++;
+	}
+
+	ctx->cap_pool.seq[ctx->cap_pool.out++] =
+		(buf_status << 16 | fb->buf_idx);
+
+	update_vdec_buf_plane(ctx, fb, &v4l_buf->vb2_buf);
+
+	aml_creat_pipeline(ctx, fb, requester);
+
+	fb_token_remove(ctx, token);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"vid:%d, task:%px, phy:%lx, state:%d, ready:%d, requester:%d\n",
+		fb->buf_idx, fb->task, fb->m.mem[0].addr, v4l_buf->vb2_buf.state,
+		v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx), requester);
+
+	ATRACE_COUNTER("VC_IN_VSINK-3.require", v4l_buf->vb2_buf.index);
+
+	*out_fb = fb;
+
+	aml_vcodec_ctx_unlock(ctx, flags);
+
+	return 0;
+}
+
+static struct task_ops_s v4l_sink_ops = {
+	.type		= TASK_TYPE_V4L_SINK,
+	.fill_buffer	= fill_capture_done_cb,
+};
+
+static struct task_ops_s *get_v4l_sink_ops(void)
+{
+	return &v4l_sink_ops;
+}
+
+void aml_vdec_basic_information(struct aml_vcodec_ctx *ctx)
+{
+	struct aml_q_data *outq = NULL;
+	struct aml_q_data *capq = NULL;
+	struct vdec_pic_info pic;
+
+	if (vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &pic)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"get pic info err\n");
+		return;
+	}
+
+	outq = aml_vdec_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	capq = aml_vdec_get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
+	pr_info("\n==== Show Basic Information ==== \n");
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Format     : %s\n",
+		outq->fmt->name);
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Color space: %s\n",
+		capq->fmt->name);
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Scan type  : %s\n",
+		(pic.field == V4L2_FIELD_NONE) ?
+		"Progressive" : "Interlaced");
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Resolution : visible(%dx%d), coded(%dx%d)\n",
+		pic.visible_width, pic.visible_height,
+		pic.coded_width, pic.coded_height);
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Buffer num : dec:%d, vpp:%d, ge2d:%d, margin:%d, total:%d\n",
+		ctx->picinfo.dpb_frames, ctx->vpp_size, ctx->ge2d_size,
+		ctx->picinfo.dpb_margin, CTX_BUF_TOTAL(ctx));
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Config     : dw:%d, drm:%d, byp:%d, lc:%d, nr:%d, ge2d:%x\n",
+		ctx->config.parm.dec.cfg.double_write_mode,
+		ctx->is_drm_mode,
+		ctx->vpp_cfg.is_bypass_p,
+		ctx->vpp_cfg.enable_local_buf,
+		ctx->vpp_cfg.enable_nr,
+		ctx->ge2d_cfg.mode);
+}
+
+void aml_buffer_status(struct aml_vcodec_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *vb = NULL;
+	struct aml_video_dec_buf *aml_buff = NULL;
+	struct vdec_v4l2_buffer *fb = NULL;
+	struct vb2_queue *q = NULL;
+	ulong flags;
+	int i;
+
+	flags = aml_vcodec_ctx_lock(ctx);
+
+	q = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	if (!q->streaming) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"can't achieve buffers status before start streaming.\n");
+	}
+
+	pr_info("\n==== Show Buffer Status ======== \n");
+	for (i = 0; i < q->num_buffers; ++i) {
+		vb = to_vb2_v4l2_buffer(q->bufs[i]);
+		aml_buff = container_of(vb, struct aml_video_dec_buf, vb);
+		fb = &aml_buff->frame_buffer;
+
+		/* print out task chain status. */
+		task_chain_show(fb->task);
+	}
+
+	aml_vcodec_ctx_unlock(ctx, flags);
+}
+
+static void aml_check_dpb_ready(struct aml_vcodec_ctx *ctx)
+{
+	if (!ctx->v4l_codec_dpb_ready) {
+		/*
+		 * make sure enough dst bufs for decoding.
+		 */
+		if ((ctx->dpb_size) && (ctx->cap_pool.in >= ctx->dpb_size))
+			ctx->v4l_codec_dpb_ready = true;
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+			"dpb: %d, vpp: %d, ready: %d, used: %d, dpb is ready: %s\n",
+			ctx->dpb_size, ctx->vpp_size,
+			v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx),
+			ctx->cap_pool.out, ctx->v4l_codec_dpb_ready ? "yes" : "no");
+	}
+}
+
+static void reconfig_vpp_status(struct aml_vcodec_ctx *ctx)
+{
+	if (bypass_nr_flag &&
+		!ctx->vpp_cfg.is_prog &&
+		((ctx->vpp_cfg.mode == VPP_MODE_NOISE_REDUC_LOCAL) ||
+		(ctx->vpp_cfg.mode == VPP_MODE_NOISE_REDUC))) {
+		ctx->vpp_cfg.enable_nr = 0;
+		ctx->vpp_cfg.enable_local_buf = 0;
+
+		ctx->vpp_cfg.mode = VPP_MODE_DI;
+	}
+}
+
+static int is_vdec_ready(struct aml_vcodec_ctx *ctx)
+{
+	struct aml_vcodec_dev *dev = ctx->dev;
+
+	if (!is_input_ready(ctx->ada_ctx)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"the decoder input has not ready.\n");
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		return 0;
+	}
+
+	if (ctx->state == AML_STATE_PROBE) {
+		mutex_lock(&ctx->state_lock);
+		if (ctx->state == AML_STATE_PROBE) {
+			ctx->state = AML_STATE_READY;
+			ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
+				"vcodec state (AML_STATE_READY)\n");
+		}
+		mutex_unlock(&ctx->state_lock);
+	}
+
+	mutex_lock(&ctx->state_lock);
+	if (ctx->state == AML_STATE_READY) {
+		if (ctx->m2m_ctx->out_q_ctx.q.streaming &&
+			ctx->m2m_ctx->cap_q_ctx.q.streaming) {
+			ctx->state = AML_STATE_ACTIVE;
+			ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
+				"vcodec state (AML_STATE_ACTIVE)\n");
+		}
+	}
+	mutex_unlock(&ctx->state_lock);
+
+	/* check dpb ready */
+	//aml_check_dpb_ready(ctx);
+
+	return 1;
+}
+
+static bool is_enough_work_items(struct aml_vcodec_ctx *ctx)
+{
+	struct aml_vcodec_dev *dev = ctx->dev;
+
+	if (vdec_frame_number(ctx->ada_ctx) >= WORK_ITEMS_MAX) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		return false;
+	}
+
+	return true;
+}
+
+static void aml_wait_buf_ready(struct aml_vcodec_ctx *ctx)
+{
+	ulong expires;
+
+	expires = jiffies + msecs_to_jiffies(1000);
+	while (!ctx->v4l_codec_dpb_ready) {
+		u32 ready_num = 0;
+
+		if (time_after(jiffies, expires)) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"the DPB state has not ready.\n");
+			break;
+		}
+
+		ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx);
+		if ((ready_num + ctx->buf_used_count) >= CTX_BUF_TOTAL(ctx))
+			ctx->v4l_codec_dpb_ready = true;
+	}
+}
+
+void dmabuff_recycle_worker(struct work_struct *work)
+{
+	struct aml_vcodec_ctx *ctx =
+		container_of(work, struct aml_vcodec_ctx, dmabuff_recycle_work);
+	struct vb2_v4l2_buffer *vb = NULL;
+	struct aml_video_dec_buf *buf = NULL;
+	unsigned long flags;
+
+	for (;;) {
+		spin_lock_irqsave(&ctx->dmabuff_recycle_lock, flags);
+		if (!kfifo_get(&ctx->dmabuff_recycle, &vb)) {
+			spin_unlock_irqrestore(&ctx->dmabuff_recycle_lock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(&ctx->dmabuff_recycle_lock, flags);
+
+		buf = container_of(vb, struct aml_video_dec_buf, vb);
+
+		if (ctx->is_out_stream_off)
+			continue;
+
+		if (wait_event_interruptible_timeout
+			(ctx->wq, buf->used == false,
+			 msecs_to_jiffies(200)) == 0) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"wait recycle dma buff timeout.\n");
+		}
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT,
+			"recycle buff idx: %d, vbuf: %lx\n", vb->vb2_buf.index,
+			(ulong)sg_dma_address(buf->out_sgt->sgl));
+
+		ATRACE_COUNTER("VO_OUT_VSINK-2.write_secure_end", vb->vb2_buf.index);
+
+		if (vb->vb2_buf.state != VB2_BUF_STATE_ERROR)
+			v4l2_buff_done(vb, buf->error ? VB2_BUF_STATE_ERROR :
+				VB2_BUF_STATE_DONE);
+	}
+}
+
+void aml_recycle_dma_buffers(struct aml_vcodec_ctx *ctx, u32 handle)
+{
+	struct aml_vcodec_dev *dev = ctx->dev;
+	struct vb2_v4l2_buffer *vb = NULL;
+	struct vb2_queue *q = NULL;
+	int index = handle & 0xf;
+	unsigned long flags;
+
+	if (ctx->is_out_stream_off) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT,
+			"ignore buff idx: %d streamoff\n", index);
+		return;
+	}
+
+	q = v4l2_m2m_get_vq(ctx->m2m_ctx,
+		V4L2_BUF_TYPE_VIDEO_OUTPUT);
+
+	vb = to_vb2_v4l2_buffer(q->bufs[index]);
+
+	spin_lock_irqsave(&ctx->dmabuff_recycle_lock, flags);
+	kfifo_put(&ctx->dmabuff_recycle, vb);
+	spin_unlock_irqrestore(&ctx->dmabuff_recycle_lock, flags);
+
+	queue_work(dev->decode_workqueue, &ctx->dmabuff_recycle_work);
+}
+
+static void aml_vdec_worker(struct work_struct *work)
+{
+	struct aml_vcodec_ctx *ctx =
+		container_of(work, struct aml_vcodec_ctx, decode_work);
+	struct aml_vcodec_dev *dev = ctx->dev;
+	struct aml_video_dec_buf *aml_buf;
+	struct vb2_v4l2_buffer *vb2_v4l2;
+	struct vb2_buffer *vb;
+	struct aml_vcodec_mem buf;
+	bool res_chg = false;
+	int ret;
+
+	if (ctx->state < AML_STATE_INIT ||
+		ctx->state > AML_STATE_FLUSHED) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		goto out;
+	}
+
+	if (!is_vdec_ready(ctx)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"the decoder has not ready.\n");
+		goto out;
+	}
+
+	vb2_v4l2 = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+	if (vb2_v4l2 == NULL) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"src_buf empty.\n");
+		goto out;
+	}
+
+	vb = (struct vb2_buffer *)vb2_v4l2;
+
+	/*this case for google, but some frames are droped on ffmpeg, so disabled temp.*/
+	if (0 && !is_enough_work_items(ctx))
+		goto out;
+
+	aml_buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
+	if (aml_buf->lastframe) {
+		ulong expires;
+
+		/*the empty data use to flushed the decoder.*/
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+			"Got empty flush input buffer.\n");
+
+		/*
+		 * when inputs a small amount of src buff, then soon to
+		 * switch state FLUSHING, must to wait the DBP to be ready.
+		 * (!ctx->v4l_codec_dpb_ready) change to  only need one buf
+		 * for run ready in new version.
+		 */
+		expires = jiffies + msecs_to_jiffies(5000);
+		while ((vdec_frame_number(ctx->ada_ctx) > 0) &&
+			(ctx->cap_pool.in < 1)) {
+			if (time_after(jiffies, expires)) {
+				aml_vdec_flush_decoder(ctx);
+				v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+				v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+				aml_vdec_dispatch_event(ctx, V4L2_EVENT_REQUEST_EXIT);
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+					"capture buffer waiting timeout.\n");
+				goto out;
+			}
+			usleep_range(5000, 5500);
+		}
+
+		mutex_lock(&ctx->state_lock);
+		if (ctx->state == AML_STATE_ACTIVE) {
+			ctx->state = AML_STATE_FLUSHING;// prepare flushing
+			ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
+				"vcodec state (AML_STATE_FLUSHING-LASTFRM)\n");
+		}
+		mutex_unlock(&ctx->state_lock);
+
+		v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+
+		/* sets eos data for vdec input. */
+		aml_vdec_flush_decoder(ctx);
+
+		goto out;
+	}
+
+	buf.index	= vb->index;
+	buf.vaddr	= vb2_plane_vaddr(vb, 0);
+	buf.addr	= sg_dma_address(aml_buf->out_sgt->sgl);
+	buf.size	= vb->planes[0].bytesused;
+	buf.model	= vb->memory;
+	buf.timestamp	= vb->timestamp;
+	buf.meta_ptr	= (ulong)aml_buf->meta_data;
+
+	if (!buf.vaddr && !buf.addr) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"id=%d src_addr is NULL.\n", vb->index);
+		goto out;
+	}
+
+	aml_buf->used = true;
+
+	/* v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+		"size: 0x%zx, crc: 0x%x\n",
+		buf.size, crc32(0, buf.va, buf.size));*/
+
+	/* pts = (time / 10e6) * (90k / fps) */
+	/*v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+		"timestamp: 0x%llx\n", src_buf->timestamp);*/
+
+	if (ctx->is_drm_mode &&
+		(buf.model == VB2_MEMORY_DMABUF)) {
+		ATRACE_COUNTER("VO_IN_VSINK-2.write_secure", buf.size);
+	} else {
+		ATRACE_COUNTER("VO_IN_VSINK-2.write", buf.size);
+	}
+
+	ATRACE_COUNTER("V_ST_VSINK-input_buffering", vdec_frame_number(ctx->ada_ctx));
+
+	ret = vdec_if_decode(ctx, &buf, &res_chg);
+	if (ret > 0) {
+		/*
+		 * we only return src buffer with VB2_BUF_STATE_DONE
+		 * when decode success without resolution change.
+		 */
+		aml_buf->used = false;
+		v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+
+		if (ctx->is_drm_mode &&
+			(buf.model == VB2_MEMORY_DMABUF)) {
+			wake_up_interruptible(&ctx->wq);
+		} else {
+			ATRACE_COUNTER("VO_OUT_VSINK-0.wrtie_end", buf.size);
+			v4l2_buff_done(&aml_buf->vb,
+				VB2_BUF_STATE_DONE);
+		}
+	} else if (ret && ret != -EAGAIN) {
+		aml_buf->used = false;
+		v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+
+		if (ctx->is_drm_mode &&
+			(buf.model == VB2_MEMORY_DMABUF)) {
+			wake_up_interruptible(&ctx->wq);
+		} else {
+			ATRACE_COUNTER("VO_OUT_VSINK-3.write_error", buf.size);
+			v4l2_buff_done(&aml_buf->vb,
+				VB2_BUF_STATE_ERROR);
+		}
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"error processing src data. %d.\n", ret);
+	} else if (res_chg) {
+		/* wait the DPB state to be ready. */
+		aml_wait_buf_ready(ctx);
+
+		aml_buf->used = false;
+		aml_vdec_pic_info_update(ctx);
+		/*
+		 * On encountering a resolution change in the stream.
+		 * The driver must first process and decode all
+		 * remaining buffers from before the resolution change
+		 * point, so call flush decode here
+		 */
+		mutex_lock(&ctx->state_lock);
+		if (ctx->state == AML_STATE_ACTIVE) {
+			ctx->state = AML_STATE_FLUSHING;// prepare flushing
+			ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
+				"vcodec state (AML_STATE_FLUSHING-RESCHG)\n");
+		}
+		mutex_unlock(&ctx->state_lock);
+
+		ctx->v4l_resolution_change = true;
+		while (ctx->m2m_ctx->job_flags & TRANS_RUNNING) {
+			v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
+		}
+
+		aml_vdec_flush_decoder(ctx);
+
+		goto out;
+	} else {
+		ATRACE_COUNTER("VO_OUT_VSINK-1.write_again", buf.size);
+		/* decoder is lack of resource, retry after short delay */
+		if (vdec_get_instance_num() < 2)
+			usleep_range(2000, 4000);
+	}
+
+	v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+out:
+	return;
+}
+
+static void aml_vdec_reset(struct aml_vcodec_ctx *ctx)
+{
+	if (ctx->state == AML_STATE_ABORT) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"the decoder will be exited.\n");
+		goto out;
+	}
+
+	if (aml_codec_reset(ctx->ada_ctx, &ctx->reset_flag)) {
+		ctx->state = AML_STATE_ABORT;
+		ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
+			"vcodec state (AML_STATE_ABORT).\n");
+	}
+out:
+	complete(&ctx->comp);
+	return;
+}
+
+void wait_vcodec_ending(struct aml_vcodec_ctx *ctx)
+{
+	/* disable queue output item to worker. */
+	ctx->output_thread_ready = false;
+	ctx->is_stream_off = true;
+
+	/* flush output buffer worker. */
+	cancel_work_sync(&ctx->decode_work);
+	cancel_work_sync(&ctx->dmabuff_recycle_work);
+
+	/* clean output cache and decoder status . */
+	if (ctx->state > AML_STATE_INIT)
+		aml_vdec_reset(ctx);
+
+	/* pause the job and clean trans status. */
+	while (ctx->m2m_ctx->job_flags & TRANS_RUNNING) {
+		v4l2_m2m_job_pause(ctx->dev->m2m_dev_dec, ctx->m2m_ctx);
+	}
+
+	ctx->v4l_codec_dpb_ready = false;
+}
+
+void aml_thread_capture_worker(struct aml_vcodec_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *vb = NULL;
+	struct aml_video_dec_buf *aml_buff = NULL;
+	struct vdec_v4l2_buffer *fb = NULL;
+
+	for (;;) {
+		mutex_lock(&ctx->capture_buffer_lock);
+		if (!kfifo_get(&ctx->capture_buffer, &vb)) {
+			mutex_unlock(&ctx->capture_buffer_lock);
+			break;
+		}
+		mutex_unlock(&ctx->capture_buffer_lock);
+
+		aml_buff = container_of(vb, struct aml_video_dec_buf, vb);
+		fb = &aml_buff->frame_buffer;
+
+		if (ctx->is_stream_off)
+			continue;
+
+		post_frame_to_upper(ctx, fb);
+	}
+}
+EXPORT_SYMBOL_GPL(aml_thread_capture_worker);
+
+static int vdec_capture_thread(void *data)
+{
+	struct aml_vdec_thread *thread =
+		(struct aml_vdec_thread *) data;
+	struct aml_vcodec_ctx *ctx =
+		(struct aml_vcodec_ctx *) thread->priv;
+
+	for (;;) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+			"%s, state: %d\n", __func__, ctx->state);
+
+		if (down_interruptible(&thread->sem))
+			break;
+
+		if (thread->stop)
+			break;
+
+		/* handle event. */
+		thread->func(ctx);
+	}
+
+	while (!kthread_should_stop()) {
+		usleep_range(1000, 2000);
+	}
+
+	return 0;
+}
+
+void aml_thread_post_task(struct aml_vcodec_ctx *ctx,
+	enum aml_thread_type type)
+{
+	struct aml_vdec_thread *thread = NULL;
+	ulong flags;
+
+	spin_lock_irqsave(&ctx->tsplock, flags);
+	list_for_each_entry(thread, &ctx->vdec_thread_list, node) {
+		if (thread->task == NULL)
+			continue;
+
+		if (thread->type == type)
+			up(&thread->sem);
+	}
+	spin_unlock_irqrestore(&ctx->tsplock, flags);
+}
+EXPORT_SYMBOL_GPL(aml_thread_post_task);
+
+int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func,
+	enum aml_thread_type type, const char *thread_name)
+{
+	struct aml_vdec_thread *thread;
+	struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+	int ret = 0;
+
+	thread = kzalloc(sizeof(*thread), GFP_KERNEL);
+	if (thread == NULL)
+		return -ENOMEM;
+
+	thread->type = type;
+	thread->func = func;
+	thread->priv = ctx;
+	sema_init(&thread->sem, 0);
+
+	thread->task = kthread_run(vdec_capture_thread, thread, "aml-%s-%d", thread_name, ctx->id);
+	if (IS_ERR(thread->task)) {
+		ret = PTR_ERR(thread->task);
+		thread->task = NULL;
+		goto err;
+	}
+	sched_setscheduler_nocheck(thread->task, SCHED_FIFO, &param);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+			"%s, policy is:%d priority is:%d\n",
+			__func__, thread->task->policy, thread->task->rt_priority);
+
+	list_add(&thread->node, &ctx->vdec_thread_list);
+
+	return 0;
+
+err:
+	kfree(thread);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(aml_thread_start);
+
+void aml_thread_stop(struct aml_vcodec_ctx *ctx)
+{
+	struct aml_vdec_thread *thread = NULL;
+	ulong flags;
+
+	while (!list_empty(&ctx->vdec_thread_list)) {
+		thread = list_entry(ctx->vdec_thread_list.next,
+			struct aml_vdec_thread, node);
+		spin_lock_irqsave(&ctx->tsplock, flags);
+		list_del(&thread->node);
+		spin_unlock_irqrestore(&ctx->tsplock, flags);
+
+		thread->stop = true;
+		up(&thread->sem);
+		kthread_stop(thread->task);
+		thread->task = NULL;
+		kfree(thread);
+	}
+}
+EXPORT_SYMBOL_GPL(aml_thread_stop);
+
+static int vidioc_try_decoder_cmd(struct file *file, void *priv,
+				struct v4l2_decoder_cmd *cmd)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, cmd: %u\n", __func__, cmd->cmd);
+
+	switch (cmd->cmd) {
+	case V4L2_DEC_CMD_STOP:
+	case V4L2_DEC_CMD_START:
+		if (cmd->cmd == V4L2_DEC_CMD_START) {
+			if (cmd->start.speed == ~0)
+				cmd->start.speed = 0;
+			if (cmd->start.format == ~0)
+				cmd->start.format = 0;
+		}
+
+		if (cmd->flags == ~0)
+			cmd->flags = 0;
+
+		if ((cmd->flags != 0) && (cmd->flags != ~0)) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+				"cmd->flags=%u\n", cmd->flags);
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vidioc_decoder_cmd(struct file *file, void *priv,
+				struct v4l2_decoder_cmd *cmd)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct vb2_queue *src_vq, *dst_vq;
+	int ret;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, cmd: %u\n", __func__, cmd->cmd);
+
+	ret = vidioc_try_decoder_cmd(file, priv, cmd);
+	if (ret)
+		return ret;
+
+	switch (cmd->cmd) {
+	case V4L2_DEC_CMD_STOP:
+		src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
+				V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+		if (!vb2_is_streaming(src_vq)) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"Output stream is off. No need to flush.\n");
+			return 0;
+		}
+
+		dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
+			multiplanar ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
+			V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		if (!vb2_is_streaming(dst_vq)) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"Capture stream is off. No need to flush.\n");
+			return 0;
+		}
+
+		/* flush pipeline */
+		v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb);
+		v4l2_m2m_try_schedule(ctx->m2m_ctx);//pay attention
+		ctx->receive_cmd_stop = true;
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+			"%s, receive cmd stop and prepare flush pipeline.\n", __func__);
+		break;
+
+	case V4L2_DEC_CMD_START:
+		dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
+			multiplanar ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
+			V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		vb2_clear_last_buffer_dequeued(dst_vq);//pay attention
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+			"%s, receive cmd start.\n", __func__);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void aml_wait_resource(struct aml_vcodec_ctx *ctx)
+{
+	ulong expires = jiffies + msecs_to_jiffies(1000);
+
+	while (atomic_read(&ctx->dev->vpp_count) >= max_di_instance) {
+		if (time_after(jiffies, expires)) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+				"wait resource timeout.\n");
+			break;
+		}
+		usleep_range(2000, 4000);
+	}
+}
+
+static int vidioc_decoder_streamon(struct file *file, void *priv,
+	enum v4l2_buf_type i)
+{
+	struct v4l2_fh *fh = file->private_data;
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+	struct vb2_queue *q;
+
+	q = v4l2_m2m_get_vq(fh->m2m_ctx, i);
+	if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
+		ctx->is_stream_off) {
+		if (ctx->vpp_is_need) {
+			int ret;
+
+			if (ctx->vpp_cfg.fmt == 0)
+				ctx->vpp_cfg.fmt = ctx->cap_pix_fmt;
+
+			if (ctx->vpp == NULL)
+				aml_wait_resource(ctx);
+
+			if ((atomic_read(&ctx->dev->vpp_count) < max_di_instance) ||
+				(ctx->vpp != NULL)) {
+				if (ctx->vpp && ctx->vpp_cfg.is_vpp_reset &&
+					(ctx->vpp->is_prog == ctx->vpp_cfg.is_prog) &&
+					(ctx->vpp->is_bypass_p == ctx->vpp_cfg.is_bypass_p) &&
+					(ctx->vpp->work_mode == ctx->vpp_cfg.mode)) {
+					aml_v4l2_vpp_reset(ctx->vpp);
+				} else {
+					if (ctx->vpp) {
+						atomic_dec(&ctx->dev->vpp_count);
+						aml_v4l2_vpp_destroy(ctx->vpp);
+						ctx->vpp = NULL;
+					}
+
+					ret = aml_v4l2_vpp_init(ctx, &ctx->vpp_cfg, &ctx->vpp);
+					if (ret) {
+						v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+							"vpp_wrapper init err:%d vpp_cfg.fmt: %d\n",
+							ret, ctx->vpp_cfg.fmt);
+						return ret;
+					}
+
+					atomic_inc(&ctx->dev->vpp_count);
+
+					v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+						"vpp_wrapper instance count: %d\n",
+						atomic_read(&ctx->dev->vpp_count));
+				}
+			} else {
+				ctx->vpp_cfg.enable_local_buf = 0;
+				ctx->vpp_cfg.enable_nr = 0;
+				ctx->picinfo.dpb_margin += ctx->vpp_size;
+				ctx->dpb_size = ctx->picinfo.dpb_margin + ctx->picinfo.dpb_frames;
+				ctx->vpp_size = 0;
+				vdec_if_set_param(ctx, SET_PARAM_PIC_INFO, &ctx->picinfo);
+				ctx->vpp_is_need = false;
+			}
+			ctx->vpp_cfg.is_vpp_reset = false;
+		} else {
+			if (ctx->vpp) {
+				atomic_dec(&ctx->dev->vpp_count);
+				aml_v4l2_vpp_destroy(ctx->vpp);
+				ctx->vpp = NULL;
+			}
+		}
+
+		if (ctx->ge2d_is_need) {
+			int ret;
+
+			if (ctx->ge2d) {
+				aml_v4l2_ge2d_destroy(ctx->ge2d);
+				ctx->ge2d = NULL;
+			}
+
+			ret = aml_v4l2_ge2d_init(ctx, &ctx->ge2d_cfg, &ctx->ge2d);
+			if (ret) {
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+					"ge2d_wrapper init err:%d\n", ret);
+				return ret;
+			}
+		}
+
+		ctx->is_stream_off = false;
+	} else
+		ctx->is_out_stream_off = false;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %d\n", __func__, q->type);
+
+	return v4l2_m2m_ioctl_streamon(file, priv, i);
+}
+
+static int vidioc_decoder_streamoff(struct file *file, void *priv,
+	enum v4l2_buf_type i)
+{
+	struct v4l2_fh *fh = file->private_data;
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+	struct vb2_queue *q;
+	ulong flags;
+
+	q = v4l2_m2m_get_vq(fh->m2m_ctx, i);
+
+	flags = aml_vcodec_ctx_lock(ctx);
+
+	if (V4L2_TYPE_IS_OUTPUT(q->type))
+		ctx->is_out_stream_off = true;
+	else
+		ctx->is_stream_off = true;
+
+	aml_vcodec_ctx_unlock(ctx, flags);
+
+	if (!V4L2_TYPE_IS_OUTPUT(q->type)) {
+		if (ctx->vpp) {
+			reconfig_vpp_status(ctx);
+		}
+	} else {
+		ctx->index_disp = 0;
+	}
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %d\n", __func__, q->type);
+
+	return v4l2_m2m_ioctl_streamoff(file, priv, i);
+}
+
+static int vidioc_decoder_reqbufs(struct file *file, void *priv,
+	struct v4l2_requestbuffers *rb)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct v4l2_fh *fh = file->private_data;
+	struct vb2_queue *q;
+
+	q = v4l2_m2m_get_vq(fh->m2m_ctx, rb->type);
+
+	if (!rb->count) {
+		if (!V4L2_TYPE_IS_OUTPUT(rb->type)) {
+			if (wait_event_interruptible_timeout
+				(ctx->post_done_wq, ctx->post_to_upper_done == true,
+				 msecs_to_jiffies(200)) == 0) {
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+					"wait post frame to upper finish timeout.\n");
+			}
+		}
+		vb2_queue_release(q);
+	}
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %d, count: %d\n",
+		__func__, q->type, rb->count);
+
+	if (!V4L2_TYPE_IS_OUTPUT(rb->type)) {
+		/* driver needs match v4l buffer number with total size*/
+		if (rb->count > CTX_BUF_TOTAL(ctx)) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+					"reqbufs (st:%d) %d -> %d\n",
+					ctx->state, rb->count, CTX_BUF_TOTAL(ctx));
+			ctx->picinfo.dpb_margin += (rb->count - CTX_BUF_TOTAL(ctx));
+			ctx->dpb_size = ctx->picinfo.dpb_frames + ctx->picinfo.dpb_margin;
+			vdec_if_set_param(ctx, SET_PARAM_PIC_INFO, &ctx->picinfo);
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+					"%s buf updated, dec: %d (%d + %d), vpp %d\n",
+					__func__,
+					ctx->dpb_size,
+					ctx->picinfo.dpb_frames,
+					ctx->picinfo.dpb_margin,
+					ctx->vpp_size);
+			//rb->count = ctx->dpb_size;
+		}
+	} else {
+		ctx->output_dma_mode =
+			(rb->memory == VB2_MEMORY_DMABUF) ? 1 : 0;
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT,
+			"output buffer memory mode is %d\n", rb->memory);
+	}
+
+	return v4l2_m2m_ioctl_reqbufs(file, priv, rb);
+}
+
+static int vidioc_vdec_querybuf(struct file *file, void *priv,
+	struct v4l2_buffer *buf)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %d\n", __func__, buf->type);
+
+	return v4l2_m2m_ioctl_querybuf(file, priv, buf);
+}
+
+static int vidioc_vdec_expbuf(struct file *file, void *priv,
+	struct v4l2_exportbuffer *eb)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %d\n", __func__, eb->type);
+
+	return v4l2_m2m_ioctl_expbuf(file, priv, eb);
+}
+
+void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx)
+{
+	ulong flags;
+
+	if (kref_read(&ctx->box_ref))
+		kref_put(&ctx->box_ref, box_release);
+
+	flags = aml_vcodec_ctx_lock(ctx);
+	ctx->state = AML_STATE_ABORT;
+	ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
+		"vcodec state (AML_STATE_ABORT)\n");
+	aml_vcodec_ctx_unlock(ctx, flags);
+
+	vdec_if_deinit(ctx);
+}
+
+void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx)
+{
+	struct aml_q_data *q_data;
+
+	ctx->m2m_ctx->q_lock = &ctx->dev->dev_mutex;
+	ctx->fh.m2m_ctx = ctx->m2m_ctx;
+	ctx->fh.ctrl_handler = &ctx->ctrl_hdl;
+	INIT_WORK(&ctx->decode_work, aml_vdec_worker);
+	ctx->colorspace = V4L2_COLORSPACE_REC709;
+	ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
+	ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+	ctx->dev->dec_capability = 0;//VCODEC_CAPABILITY_4K_DISABLED;//disable 4k
+
+	q_data = &ctx->q_data[AML_Q_DATA_SRC];
+	memset(q_data, 0, sizeof(struct aml_q_data));
+	q_data->visible_width = DFT_CFG_WIDTH;
+	q_data->visible_height = DFT_CFG_HEIGHT;
+	q_data->coded_width = DFT_CFG_WIDTH;
+	q_data->coded_height = DFT_CFG_HEIGHT;
+	q_data->fmt = &aml_video_formats[OUT_FMT_IDX];
+	q_data->field = V4L2_FIELD_NONE;
+
+	q_data->sizeimage[0] = (1024 * 1024);//DFT_CFG_WIDTH * DFT_CFG_HEIGHT; //1m
+	q_data->bytesperline[0] = 0;
+
+	q_data = &ctx->q_data[AML_Q_DATA_DST];
+	memset(q_data, 0, sizeof(struct aml_q_data));
+	q_data->visible_width = DFT_CFG_WIDTH;
+	q_data->visible_height = DFT_CFG_HEIGHT;
+	q_data->coded_width = DFT_CFG_WIDTH;
+	q_data->coded_height = DFT_CFG_HEIGHT;
+	q_data->fmt = &aml_video_formats[CAP_FMT_IDX];
+	if (support_format_I420)
+		q_data->fmt = &aml_video_formats[CAP_FMT_I420_IDX];
+
+	q_data->field = V4L2_FIELD_NONE;
+
+	v4l_bound_align_image(&q_data->coded_width,
+				AML_VDEC_MIN_W,
+				AML_VDEC_MAX_W, 4,
+				&q_data->coded_height,
+				AML_VDEC_MIN_H,
+				AML_VDEC_MAX_H, 5, 6);
+
+	q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height;
+	q_data->bytesperline[0] = q_data->coded_width;
+	q_data->sizeimage[1] = q_data->sizeimage[0] / 2;
+	q_data->bytesperline[1] = q_data->coded_width;
+	ctx->reset_flag = V4L_RESET_MODE_NORMAL;
+
+	ctx->fb_ops.query	= fb_buff_query;
+	ctx->fb_ops.alloc	= fb_buff_from_queue;
+
+	ctx->state = AML_STATE_IDLE;
+	ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
+		"vcodec state (AML_STATE_IDLE)\n");
+}
+
+static int vidioc_vdec_qbuf(struct file *file, void *priv,
+	struct v4l2_buffer *buf)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+	int ret;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %d\n", __func__, buf->type);
+
+	if (ctx->state == AML_STATE_ABORT) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"Call on QBUF after unrecoverable error, type = %s\n",
+			V4L2_TYPE_IS_OUTPUT(buf->type) ? "OUT" : "IN");
+		return -EIO;
+	}
+
+	ret = v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+
+	if (V4L2_TYPE_IS_OUTPUT(buf->type)) {
+		if (V4L2_TYPE_IS_MULTIPLANAR(buf->type)) {
+			if (ret == -EAGAIN)
+				ATRACE_COUNTER("VO_IN_VSINK-1.que_again", buf->m.planes[0].bytesused);
+			else
+				ATRACE_COUNTER("VO_IN_VSINK-0.que", buf->m.planes[0].bytesused);
+		} else {
+			if (ret == -EAGAIN)
+				ATRACE_COUNTER("VO_IN_VSINK-1.que_again", buf->length);
+			else
+				ATRACE_COUNTER("VO_IN_VSINK-0.que", buf->length);
+		}
+	} else {
+		if (ret == -EAGAIN)
+			ATRACE_COUNTER("VC_IN_VSINK-1.que_again", buf->index);
+		else
+			ATRACE_COUNTER("VC_IN_VSINK-0.que", buf->index);
+	}
+
+	return ret;
+}
+
+static int vidioc_vdec_dqbuf(struct file *file, void *priv,
+	struct v4l2_buffer *buf)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+	int ret;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %d\n", __func__, buf->type);
+
+	if (ctx->state == AML_STATE_ABORT) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"Call on DQBUF after unrecoverable error, type = %s\n",
+			V4L2_TYPE_IS_OUTPUT(buf->type) ? "OUT" : "IN");
+		if (!V4L2_TYPE_IS_OUTPUT(buf->type))
+			return -EIO;
+	}
+
+	ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+	if (!ret && !V4L2_TYPE_IS_OUTPUT(buf->type)) {
+		struct vb2_queue *vq;
+		struct vb2_v4l2_buffer *vb2_v4l2 = NULL;
+		struct aml_video_dec_buf *aml_buf = NULL;
+		struct file *file = NULL;
+
+		vq = v4l2_m2m_get_vq(ctx->m2m_ctx, buf->type);
+		vb2_v4l2 = to_vb2_v4l2_buffer(vq->bufs[buf->index]);
+		aml_buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
+		aml_buf->privdata.vb_handle	= (ulong) aml_buf;
+		aml_buf->privdata.v4l_dec_ctx	= (ulong) ctx;
+
+		file = fget(vb2_v4l2->private);
+		if (file && is_v4l2_buf_file(file)) {
+			dmabuf_fd_install_data(vb2_v4l2->private,
+				(void*)&aml_buf->privdata,
+				sizeof(struct file_private_data));
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO, "disp: %d, vf: %lx\n",
+				aml_buf->privdata.vf.index_disp,
+				(ulong) v4l_get_vf_handle(vb2_v4l2->private));
+			fput(file);
+		}
+	}
+
+	if (V4L2_TYPE_IS_OUTPUT(buf->type)) {
+		if (V4L2_TYPE_IS_MULTIPLANAR(buf->type)) {
+			if (ret == -EAGAIN)
+				ATRACE_COUNTER("VO_OUT_VSINK-5.deque_again", buf->m.planes[0].bytesused);
+			else
+				ATRACE_COUNTER("VO_OUT_VSINK-4.deque", buf->m.planes[0].bytesused);
+		} else {
+			if (ret == -EAGAIN)
+				ATRACE_COUNTER("VO_OUT_VSINK-5.deque_again", buf->length);
+			else
+				ATRACE_COUNTER("VO_OUT_VSINK-4.deque", buf->length);
+		}
+	} else {
+		if (ret == -EAGAIN)
+			ATRACE_COUNTER("VC_OUT_VSINK-3.deque_again", buf->index);
+		else
+			ATRACE_COUNTER("VC_OUT_VSINK-2.deque", buf->index);
+	}
+
+	return ret;
+}
+
+static int vidioc_vdec_querycap(struct file *file, void *priv,
+	struct v4l2_capability *cap)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct video_device *vfd_dec = video_devdata(file);
+
+	strlcpy(cap->driver, AML_VCODEC_DEC_NAME, sizeof(cap->driver));
+	strlcpy(cap->bus_info, AML_PLATFORM_STR, sizeof(cap->bus_info));
+	strlcpy(cap->card, AML_PLATFORM_STR, sizeof(cap->card));
+	cap->device_caps = vfd_dec->device_caps;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s, %s\n", __func__, cap->card);
+
+	return 0;
+}
+
+static int vidioc_vdec_subscribe_evt(struct v4l2_fh *fh,
+	const struct v4l2_event_subscription *sub)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %d\n", __func__, sub->type);
+
+	switch (sub->type) {
+	case V4L2_EVENT_EOS:
+		return v4l2_event_subscribe(fh, sub, 2, NULL);
+	case V4L2_EVENT_SOURCE_CHANGE:
+		return v4l2_src_change_event_subscribe(fh, sub);
+	default:
+		return v4l2_ctrl_subscribe_event(fh, sub);
+	}
+}
+
+static int vidioc_vdec_event_unsubscribe(struct v4l2_fh *fh,
+	const struct v4l2_event_subscription *sub)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s, type: %d\n",
+		__func__, sub->type);
+
+	return v4l2_event_unsubscribe(fh, sub);
+}
+
+static int vidioc_try_fmt(struct v4l2_format *f, struct aml_video_fmt *fmt)
+{
+	int i;
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
+		if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+			pix_mp->num_planes = 1;
+			pix_mp->plane_fmt[0].bytesperline = 0;
+
+			if ((pix_mp->pixelformat != V4L2_PIX_FMT_MPEG2) &&
+			    (pix_mp->pixelformat != V4L2_PIX_FMT_H264) &&
+			    (pix_mp->pixelformat != V4L2_PIX_FMT_MPEG1)) {
+				pix_mp->field = V4L2_FIELD_NONE;
+			} else if (pix_mp->field != V4L2_FIELD_NONE) {
+				if (pix_mp->field == V4L2_FIELD_ANY)
+					pix_mp->field = V4L2_FIELD_NONE;
+
+				pr_info("%s, field: %u, fmt: %x\n",
+					__func__, pix_mp->field,
+					pix_mp->pixelformat);
+			}
+		} else {
+			if (pix_mp->field != V4L2_FIELD_INTERLACED)
+				pix_mp->field = V4L2_FIELD_NONE;
+			pix_mp->height = clamp(pix_mp->height,
+						AML_VDEC_MIN_H,
+						AML_VDEC_MAX_H);
+			pix_mp->width = clamp(pix_mp->width,
+						AML_VDEC_MIN_W,
+						AML_VDEC_MAX_W);
+
+			pix_mp->num_planes = fmt->num_planes;
+
+			pix_mp->plane_fmt[0].bytesperline = pix_mp->width;
+			pix_mp->plane_fmt[0].sizeimage =
+				pix_mp->width * pix_mp->height;
+
+			pix_mp->plane_fmt[1].bytesperline = pix_mp->width;
+			pix_mp->plane_fmt[1].sizeimage =
+				pix_mp->width * pix_mp->height / 2;
+		}
+
+		for (i = 0; i < pix_mp->num_planes; i++) {
+			memset(&(pix_mp->plane_fmt[i].reserved[0]), 0x0,
+				   sizeof(pix_mp->plane_fmt[0].reserved));
+		}
+		memset(&pix_mp->reserved, 0x0, sizeof(pix_mp->reserved));
+
+		pix_mp->flags = 0;
+	} else {
+		if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+			pix->bytesperline = 0;
+			if ((pix->pixelformat != V4L2_PIX_FMT_MPEG2) &&
+			    (pix->pixelformat != V4L2_PIX_FMT_H264) &&
+			    (pix->pixelformat != V4L2_PIX_FMT_MPEG1)) {
+				pix->field = V4L2_FIELD_NONE;
+			} else if (pix->field != V4L2_FIELD_NONE) {
+				if (pix->field == V4L2_FIELD_ANY)
+					pix->field = V4L2_FIELD_NONE;
+
+				pr_info("%s, field: %u, fmt: %x\n",
+					__func__, pix->field,
+					pix->pixelformat);
+			}
+		} else {
+			if (pix->field != V4L2_FIELD_INTERLACED)
+				pix->field = V4L2_FIELD_NONE;
+
+			pix->height = clamp(pix->height,
+						AML_VDEC_MIN_H,
+						AML_VDEC_MAX_H);
+			pix->width = clamp(pix->width,
+						AML_VDEC_MIN_W,
+						AML_VDEC_MAX_W);
+
+			pix->bytesperline = pix->width;
+			pix->sizeimage = pix->width * pix->height;
+		}
+		pix->flags = 0;
+	}
+
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap_out(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct aml_q_data *q_data = NULL;
+	struct aml_video_fmt *fmt = NULL;
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct vb2_queue *dst_vq;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %u, planes: %u, fmt: %x\n",
+		__func__, f->type,
+		V4L2_TYPE_IS_MULTIPLANAR(f->type) ?
+		f->fmt.pix_mp.num_planes : 1,
+		f->fmt.pix_mp.pixelformat);
+
+	dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	if (!dst_vq) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"no vb2 queue for type=%d\n", V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		return -EINVAL;
+	}
+
+	if (!V4L2_TYPE_IS_MULTIPLANAR(f->type) && dst_vq->is_multiplanar)
+		return -EINVAL;
+
+	fmt = aml_vdec_find_format(f);
+	if (!fmt) {
+		if (V4L2_TYPE_IS_OUTPUT(f->type))
+			f->fmt.pix.pixelformat = aml_video_formats[OUT_FMT_IDX].fourcc;
+		else
+			f->fmt.pix.pixelformat = aml_video_formats[CAP_FMT_IDX].fourcc;
+		fmt = aml_vdec_find_format(f);
+	}
+
+	vidioc_try_fmt(f, fmt);
+
+	q_data = aml_vdec_get_q_data(ctx, f->type);
+	if (!q_data)
+		return -EINVAL;
+
+	if (ctx->state >= AML_STATE_PROBE)
+		update_ctx_dimension(ctx, f->type);
+	copy_v4l2_format_dimention(pix_mp, pix, q_data, f->type);
+
+	if (!V4L2_TYPE_IS_OUTPUT(f->type))
+		return 0;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
+		if (pix_mp->plane_fmt[0].sizeimage == 0) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+				"sizeimage of output format must be given\n");
+			return -EINVAL;
+		}
+	} else {
+		if (pix->sizeimage == 0) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+				"sizeimage of output format must be given\n");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int vidioc_vdec_g_selection(struct file *file, void *priv,
+	struct v4l2_selection *s)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct aml_q_data *q_data;
+	int ratio = 1;
+
+	if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE))
+		return -EINVAL;
+
+	if (ctx->internal_dw_scale) {
+		if (ctx->state >= AML_STATE_PROBE) {
+			unsigned int dw_mode = VDEC_DW_NO_AFBC;
+			if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode))
+				return -EBUSY;
+			ratio = get_double_write_ratio(dw_mode);
+		}
+	}
+
+	q_data = &ctx->q_data[AML_Q_DATA_DST];
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+	case V4L2_SEL_TGT_COMPOSE:
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = ctx->picinfo.visible_width / ratio;
+		s->r.height = ctx->picinfo.visible_height / ratio;
+		break;
+	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = ctx->picinfo.coded_width / ratio;
+		s->r.height = ctx->picinfo.coded_height / ratio;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (ctx->state < AML_STATE_PROBE) {
+		/* set to default value if header info not ready yet*/
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = q_data->visible_width;
+		s->r.height = q_data->visible_height;
+	}
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s, type: %d\n",
+		__func__, s->type);
+
+	return 0;
+}
+
+static int vidioc_vdec_s_selection(struct file *file, void *priv,
+	struct v4l2_selection *s)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+	int ratio = 1;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s, type: %d\n",
+		__func__, s->type);
+
+	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (ctx->internal_dw_scale) {
+		if (ctx->state >= AML_STATE_PROBE) {
+			unsigned int dw_mode = VDEC_DW_NO_AFBC;
+			if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode))
+				return -EBUSY;
+			ratio = get_double_write_ratio(dw_mode);
+		}
+	}
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_COMPOSE:
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = ctx->picinfo.visible_width / ratio;
+		s->r.height = ctx->picinfo.visible_height / ratio;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* called when it is beyong AML_STATE_PROBE */
+static void update_ctx_dimension(struct aml_vcodec_ctx *ctx, u32 type)
+{
+	struct aml_q_data *q_data;
+	unsigned int dw_mode = VDEC_DW_NO_AFBC;
+	int ratio = 1;
+
+	q_data = aml_vdec_get_q_data(ctx, type);
+
+	if (ctx->internal_dw_scale) {
+		if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode))
+			return;
+		ratio = get_double_write_ratio(dw_mode);
+	}
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
+		q_data->sizeimage[0] = ctx->picinfo.y_len_sz;
+		q_data->sizeimage[1] = ctx->picinfo.c_len_sz;
+
+		q_data->coded_width = ALIGN(ctx->picinfo.coded_width / ratio, 64);
+		q_data->coded_height = ALIGN(ctx->picinfo.coded_height / ratio, 64);
+
+		q_data->bytesperline[0] = ALIGN(ctx->picinfo.coded_width / ratio, 64);
+		q_data->bytesperline[1] = ALIGN(ctx->picinfo.coded_width / ratio, 64);
+	} else {
+		q_data->coded_width = ALIGN(ctx->picinfo.coded_width / ratio, 64);
+		q_data->coded_height = ALIGN(ctx->picinfo.coded_height / ratio, 64);
+		q_data->sizeimage[0] = ctx->picinfo.y_len_sz;
+		q_data->sizeimage[0] += ctx->picinfo.c_len_sz;
+		q_data->bytesperline[0] = ALIGN(ctx->picinfo.coded_width / ratio, 64);
+	}
+}
+
+static void copy_v4l2_format_dimention(struct v4l2_pix_format_mplane *pix_mp,
+				       struct v4l2_pix_format *pix,
+				       struct aml_q_data *q_data,
+				       u32 type)
+{
+	int i;
+
+	if (!pix || !pix_mp || !q_data)
+		return;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
+		pix_mp->width		= q_data->coded_width;
+		pix_mp->height		= q_data->coded_height;
+		pix_mp->num_planes	= q_data->fmt->num_planes;
+		pix_mp->pixelformat	= q_data->fmt->fourcc;
+
+		for (i = 0; i < q_data->fmt->num_planes; i++) {
+			pix_mp->plane_fmt[i].bytesperline = q_data->bytesperline[i];
+			pix_mp->plane_fmt[i].sizeimage = q_data->sizeimage[i];
+		}
+	} else {
+		pix->width		= q_data->coded_width;
+		pix->height		= q_data->coded_height;
+		pix->pixelformat	= q_data->fmt->fourcc;
+		pix->bytesperline	= q_data->bytesperline[0];
+		pix->sizeimage		= q_data->sizeimage[0];
+	}
+}
+
+static int vidioc_vdec_s_fmt(struct file *file, void *priv,
+	struct v4l2_format *f)
+{
+	int ret = 0;
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct aml_q_data *q_data = NULL;
+	struct aml_video_fmt *fmt;
+	struct vb2_queue *dst_vq;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %u, planes: %u, fmt: %x\n",
+		__func__, f->type,
+		V4L2_TYPE_IS_MULTIPLANAR(f->type) ?
+		f->fmt.pix_mp.num_planes : 1,
+		f->fmt.pix_mp.pixelformat);
+
+	dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	if (!dst_vq) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"no vb2 queue for type=%d\n", V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		return -EINVAL;
+	}
+
+	if (!V4L2_TYPE_IS_MULTIPLANAR(f->type) && dst_vq->is_multiplanar)
+		return -EINVAL;
+
+	q_data = aml_vdec_get_q_data(ctx, f->type);
+	if (!q_data)
+		return -EINVAL;
+
+	if ((f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) &&
+	    vb2_is_busy(&ctx->m2m_ctx->out_q_ctx.q)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"out_q_ctx buffers already requested\n");
+		ret = -EBUSY;
+	}
+
+	if ((!V4L2_TYPE_IS_OUTPUT(f->type)) &&
+	    vb2_is_busy(&ctx->m2m_ctx->cap_q_ctx.q)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"cap_q_ctx buffers already requested\n");
+		ret = -EBUSY;
+	}
+
+	fmt = aml_vdec_find_format(f);
+	if (fmt == NULL) {
+		if (V4L2_TYPE_IS_OUTPUT(f->type))
+			fmt = &aml_video_formats[OUT_FMT_IDX];
+		else
+			fmt = &aml_video_formats[CAP_FMT_IDX];
+		f->fmt.pix.pixelformat = fmt->fourcc;
+	}
+
+	q_data->fmt = fmt;
+	vidioc_try_fmt(f, q_data->fmt);
+
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		q_data->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage;
+		q_data->coded_width = pix_mp->width;
+		q_data->coded_height = pix_mp->height;
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+			"w: %d, h: %d, size: %d\n",
+			pix_mp->width, pix_mp->height,
+			pix_mp->plane_fmt[0].sizeimage);
+
+		ctx->output_pix_fmt = pix_mp->pixelformat;
+		ctx->colorspace = f->fmt.pix_mp.colorspace;
+		ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
+		ctx->quantization = f->fmt.pix_mp.quantization;
+		ctx->xfer_func = f->fmt.pix_mp.xfer_func;
+
+		mutex_lock(&ctx->state_lock);
+		if (ctx->state == AML_STATE_IDLE) {
+			ret = vdec_if_init(ctx, q_data->fmt->fourcc);
+			if (ret) {
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+					"vdec_if_init() fail ret=%d\n", ret);
+				mutex_unlock(&ctx->state_lock);
+				return -EINVAL;
+			}
+			ctx->state = AML_STATE_INIT;
+			ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
+				"vcodec state (AML_STATE_INIT)\n");
+		}
+		mutex_unlock(&ctx->state_lock);
+	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+		q_data->sizeimage[0] = pix->sizeimage;
+		q_data->coded_width = pix->width;
+		q_data->coded_height = pix->height;
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+			"w: %d, h: %d, size: %d\n",
+			pix->width, pix->height,
+			pix->sizeimage);
+
+		ctx->output_pix_fmt = pix->pixelformat;
+		ctx->colorspace = f->fmt.pix.colorspace;
+		ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
+		ctx->quantization = f->fmt.pix.quantization;
+		ctx->xfer_func = f->fmt.pix.xfer_func;
+
+		mutex_lock(&ctx->state_lock);
+		if (ctx->state == AML_STATE_IDLE) {
+			ret = vdec_if_init(ctx, q_data->fmt->fourcc);
+			if (ret) {
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+					"vdec_if_init() fail ret=%d\n", ret);
+				mutex_unlock(&ctx->state_lock);
+				return -EINVAL;
+			}
+			ctx->state = AML_STATE_INIT;
+			ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
+				"vcodec state (AML_STATE_INIT)\n");
+		}
+		mutex_unlock(&ctx->state_lock);
+	}
+
+	if (!V4L2_TYPE_IS_OUTPUT(f->type)) {
+		ctx->cap_pix_fmt = V4L2_TYPE_IS_MULTIPLANAR(f->type) ?
+			pix_mp->pixelformat : pix->pixelformat;
+		if (ctx->state >= AML_STATE_PROBE) {
+			update_ctx_dimension(ctx, f->type);
+			copy_v4l2_format_dimention(pix_mp, pix, q_data, f->type);
+			v4l_buf_size_decision(ctx);
+		}
+	}
+
+	return 0;
+}
+
+static int vidioc_enum_framesizes(struct file *file, void *priv,
+				struct v4l2_frmsizeenum *fsize)
+{
+	int i = 0;
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s, idx: %d, pix fmt: %x\n",
+		__func__, fsize->index, fsize->pixel_format);
+
+	if (fsize->index != 0)
+		return -EINVAL;
+
+	for (i = 0; i < NUM_SUPPORTED_FRAMESIZE; ++i) {
+		if (fsize->pixel_format != aml_vdec_framesizes[i].fourcc)
+			continue;
+
+		fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+		fsize->stepwise = aml_vdec_framesizes[i].stepwise;
+		if (!(ctx->dev->dec_capability &
+				VCODEC_CAPABILITY_4K_DISABLED)) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO, "4K is enabled\n");
+			fsize->stepwise.max_width =
+					VCODEC_DEC_4K_CODED_WIDTH;
+			fsize->stepwise.max_height =
+					VCODEC_DEC_4K_CODED_HEIGHT;
+		}
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+			"%x, %d %d %d %d %d %d\n",
+			ctx->dev->dec_capability,
+			fsize->stepwise.min_width,
+			fsize->stepwise.max_width,
+			fsize->stepwise.step_width,
+			fsize->stepwise.min_height,
+			fsize->stepwise.max_height,
+			fsize->stepwise.step_height);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue)
+{
+	struct aml_video_fmt *fmt;
+	int i = 0, j = 0;
+
+	/* I420 only used for mjpeg. */
+	if (!output_queue && support_mjpeg && support_format_I420) {
+		for (i = 0; i < NUM_FORMATS; i++) {
+			fmt = &aml_video_formats[i];
+			if ((fmt->fourcc == V4L2_PIX_FMT_YUV420) ||
+				(fmt->fourcc == V4L2_PIX_FMT_YUV420M)) {
+				break;
+			}
+		}
+	}
+
+	for (; i < NUM_FORMATS; i++) {
+		fmt = &aml_video_formats[i];
+		if (output_queue && (fmt->type != AML_FMT_DEC))
+			continue;
+		if (!output_queue && (fmt->type != AML_FMT_FRAME))
+			continue;
+		if (support_mjpeg && !support_format_I420 &&
+			((fmt->fourcc == V4L2_PIX_FMT_YUV420) ||
+			(fmt->fourcc == V4L2_PIX_FMT_YUV420M)))
+			continue;
+
+		if (j == f->index) {
+			f->pixelformat = fmt->fourcc;
+			return 0;
+		}
+		++j;
+	}
+
+	return -EINVAL;
+}
+
+static int vidioc_vdec_enum_fmt_vid_cap_mplane(struct file *file,
+	void *priv, struct v4l2_fmtdesc *f)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s\n", __func__);
+
+	return vidioc_enum_fmt(f, false);
+}
+
+static int vidioc_vdec_enum_fmt_vid_out_mplane(struct file *file,
+	void *priv, struct v4l2_fmtdesc *f)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s\n", __func__);
+
+	return vidioc_enum_fmt(f, true);
+}
+
+static int vidioc_vdec_g_fmt(struct file *file, void *priv,
+	struct v4l2_format *f)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct vb2_queue *vq;
+	struct vb2_queue *dst_vq;
+	struct aml_q_data *q_data;
+	int ret = 0;
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+	if (!vq) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"no vb2 queue for type=%d\n", f->type);
+		return -EINVAL;
+	}
+
+	dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	if (!dst_vq) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"no vb2 queue for type=%d\n", V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		return -EINVAL;
+	}
+
+	if (!V4L2_TYPE_IS_MULTIPLANAR(f->type) && dst_vq->is_multiplanar)
+		return -EINVAL;
+
+	q_data = aml_vdec_get_q_data(ctx, f->type);
+
+	ret = vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->picinfo);
+	if (ret) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"GET_PARAM_PICTURE_INFO err\n");
+	} else {
+		if ((ctx->picinfo.visible_height < 16 && ctx->picinfo.visible_height > 0) ||
+			(ctx->picinfo.visible_width < 16 && ctx->picinfo.visible_width > 0)) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"The width or height of the stream is less than 16\n");
+			return -EPERM;
+		}
+	}
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
+		pix_mp->field = ret ? V4L2_FIELD_NONE : ctx->picinfo.field;
+		pix_mp->colorspace = ctx->colorspace;
+		pix_mp->ycbcr_enc = ctx->ycbcr_enc;
+		pix_mp->quantization = ctx->quantization;
+		pix_mp->xfer_func = ctx->xfer_func;
+	} else {
+		pix->field = ret ? V4L2_FIELD_NONE : ctx->picinfo.field;
+		pix->colorspace = ctx->colorspace;
+		pix->ycbcr_enc = ctx->ycbcr_enc;
+		pix->quantization = ctx->quantization;
+		pix->xfer_func = ctx->xfer_func;
+	}
+
+	if ((!V4L2_TYPE_IS_OUTPUT(f->type)) &&
+	    (ctx->state >= AML_STATE_PROBE)) {
+		update_ctx_dimension(ctx, f->type);
+		copy_v4l2_format_dimention(pix_mp, pix, q_data, f->type);
+	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		/*
+		 * This is run on OUTPUT
+		 * The buffer contains compressed image
+		 * so width and height have no meaning.
+		 * Assign value here to pass v4l2-compliance test
+		 */
+		copy_v4l2_format_dimention(pix_mp, pix, q_data, f->type);
+	} else {
+		copy_v4l2_format_dimention(pix_mp, pix, q_data, f->type);
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+			"type=%d state=%d Format information could not be read, not ready yet!\n",
+			f->type, ctx->state);
+	}
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %u, planes: %u, fmt: %x\n",
+		__func__, f->type,
+		V4L2_TYPE_IS_MULTIPLANAR(f->type) ?
+		q_data->fmt->num_planes : 1,
+		q_data->fmt->fourcc);
+
+	return 0;
+}
+
+static int vidioc_vdec_create_bufs(struct file *file, void *priv,
+	struct v4l2_create_buffers *create)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %u, count: %u\n",
+		__func__, create->format.type, create->count);
+
+	return v4l2_m2m_ioctl_create_bufs(file, priv, create);
+}
+
+/*int vidioc_vdec_g_ctrl(struct file *file, void *fh,
+	struct v4l2_control *a)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, id: %d\n", __func__, a->id);
+
+	if (a->id == V4L2_CID_MIN_BUFFERS_FOR_CAPTURE)
+		a->value = 4;
+	else if (a->id == V4L2_CID_MIN_BUFFERS_FOR_OUTPUT)
+		a->value = 8;
+
+	return 0;
+}*/
+
+static int vb2ops_vdec_queue_setup(struct vb2_queue *vq,
+				unsigned int *nbuffers,
+				unsigned int *nplanes,
+				unsigned int sizes[], struct device *alloc_devs[])
+{
+	struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vq);
+	struct aml_q_data *q_data;
+	unsigned int i;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s, type: %d\n",
+		__func__, vq->type);
+
+	q_data = aml_vdec_get_q_data(ctx, vq->type);
+	if (q_data == NULL) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"vq->type=%d err\n", vq->type);
+		return -EINVAL;
+	}
+
+	if (*nplanes) {
+		for (i = 0; i < *nplanes; i++) {
+			if (sizes[i] < q_data->sizeimage[i])
+				return -EINVAL;
+			alloc_devs[i] = &ctx->dev->plat_dev->dev;
+
+			if (!V4L2_TYPE_IS_OUTPUT(vq->type))
+				alloc_devs[i] = v4l_get_dev_from_codec_mm();
+		}
+	} else {
+		int dw_mode = VDEC_DW_NO_AFBC;
+
+		if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+			*nplanes = 2;
+		else
+			*nplanes = 1;
+
+		if (!vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode)) {
+			if (dw_mode == VDEC_DW_AFBC_ONLY)
+				*nplanes = 1;
+		}
+
+		for (i = 0; i < *nplanes; i++) {
+			sizes[i] = q_data->sizeimage[i];
+			if (V4L2_TYPE_IS_OUTPUT(vq->type) && ctx->output_dma_mode)
+				sizes[i] = 1;
+			alloc_devs[i] = &ctx->dev->plat_dev->dev;
+
+			if (!V4L2_TYPE_IS_OUTPUT(vq->type))
+				alloc_devs[i] = v4l_get_dev_from_codec_mm();
+		}
+	}
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"type: %d, plane: %d, buf cnt: %d, size: [Y: %u, C: %u]\n",
+		vq->type, *nplanes, *nbuffers, sizes[0], sizes[1]);
+
+	return 0;
+}
+
+static int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb)
+{
+	struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct aml_q_data *q_data;
+	struct vb2_v4l2_buffer *vb2_v4l2 = NULL;
+	struct aml_video_dec_buf *buf = NULL;
+	int i;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %d, idx: %d\n",
+		__func__, vb->vb2_queue->type, vb->index);
+
+	if (vb->memory == VB2_MEMORY_DMABUF
+		&& V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
+		return 0;
+
+	q_data = aml_vdec_get_q_data(ctx, vb->vb2_queue->type);
+
+	for (i = 0; i < q_data->fmt->num_planes; i++) {
+		if (vb2_plane_size(vb, i) < q_data->sizeimage[i]) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"data will not fit into plane %d (%lu < %d)\n",
+				i, vb2_plane_size(vb, i),
+				q_data->sizeimage[i]);
+		}
+	}
+
+	vb2_v4l2 = to_vb2_v4l2_buffer(vb);
+	buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
+
+	if (vb2_v4l2->meta_ptr && (copy_from_user(buf->meta_data,
+		(void *)vb2_v4l2->meta_ptr, META_DATA_SIZE + 4))) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"%s:copy meta data error. ptr: %lx\n", __func__, vb2_v4l2->meta_ptr);
+	}
+
+	return 0;
+}
+
+static int init_mmu_bmmu_box(struct aml_vcodec_ctx *ctx)
+{
+	int i;
+	int mmu_flag = ctx->is_drm_mode? CODEC_MM_FLAGS_TVP:0;
+	int bmmu_flag = mmu_flag;
+	u32 dw_mode = VDEC_DW_NO_AFBC;
+
+	ctx->comp_bufs = vzalloc(sizeof(*ctx->comp_bufs) * V4L_CAP_BUFF_MAX);
+	if (!ctx->comp_bufs)
+		return -ENOMEM;
+
+	if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "invalid dw_mode\n");
+		goto free_comp_bufs;
+	}
+
+	/* init mmu box */
+	ctx->mmu_box = decoder_mmu_box_alloc_box("v4l2_dec",
+			ctx->id, V4L_CAP_BUFF_MAX,
+			ctx->comp_info.max_size * SZ_1M, mmu_flag);
+	if (!ctx->mmu_box) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to create mmu box\n");
+		goto free_comp_bufs;
+	}
+
+	/* init bmmu box */
+	bmmu_flag |= CODEC_MM_FLAGS_CMA_CLEAR | CODEC_MM_FLAGS_FOR_VDECODER;
+	ctx->bmmu_box  = decoder_bmmu_box_alloc_box("v4l2_dec",
+			ctx->id, V4L_CAP_BUFF_MAX,
+			4 + PAGE_SHIFT, bmmu_flag);
+	if (!ctx->bmmu_box) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to create bmmu box\n");
+		goto free_mmubox;
+	}
+
+	if (dw_mode & 0x20) {
+		/* init mmu box dw*/
+		ctx->mmu_box_dw = decoder_mmu_box_alloc_box("v4l2_dec",
+				ctx->id, V4L_CAP_BUFF_MAX,
+				ctx->comp_info.max_size * SZ_1M, mmu_flag);
+		if (!ctx->mmu_box_dw) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to create mmu box dw\n");
+			goto free_bmmubox;
+		}
+
+		/* init bmmu box dw*/
+		bmmu_flag |= CODEC_MM_FLAGS_CMA_CLEAR | CODEC_MM_FLAGS_FOR_VDECODER;
+		ctx->bmmu_box_dw  = decoder_bmmu_box_alloc_box("v4l2_dec",
+				ctx->id, V4L_CAP_BUFF_MAX,
+				4 + PAGE_SHIFT, bmmu_flag);
+		if (!ctx->bmmu_box_dw) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to create bmmu box dw\n");
+			goto free_mmubox_dw;
+		}
+	}
+
+	kref_init(&ctx->box_ref);
+	for (i = 0; i < V4L_CAP_BUFF_MAX; i++) {
+		struct internal_comp_buf *buf;
+		buf = &ctx->comp_bufs[i];
+		buf->index = i;
+		buf->ref = 0;
+		buf->box_ref = &ctx->box_ref;
+		buf->mmu_box = ctx->mmu_box;
+		buf->bmmu_box = ctx->bmmu_box;
+		buf->mmu_box_dw = ctx->mmu_box_dw;
+		buf->bmmu_box_dw = ctx->bmmu_box_dw;
+	}
+	kref_get(&ctx->ctx_ref);
+
+	ctx->uvm_proxy = vzalloc(sizeof(*ctx->uvm_proxy) * V4L_CAP_BUFF_MAX);
+	if (!ctx->uvm_proxy)
+		goto free_mmubox;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+		"box init, bmmu: %px, mmu: %px, mmu_dw: %px bmmu_dw: %px\n",
+		ctx->bmmu_box, ctx->mmu_box, ctx->mmu_box_dw, ctx->bmmu_box_dw);
+
+	return 0;
+free_mmubox_dw:
+	decoder_mmu_box_free(ctx->mmu_box_dw);
+	ctx->mmu_box_dw = NULL;
+
+free_bmmubox:
+	decoder_bmmu_box_free(ctx->bmmu_box);
+	ctx->bmmu_box = NULL;
+
+free_mmubox:
+	decoder_mmu_box_free(ctx->mmu_box);
+	ctx->mmu_box = NULL;
+
+free_comp_bufs:
+	vfree(ctx->comp_bufs);
+	ctx->comp_bufs = NULL;
+
+	return -1;
+}
+
+void aml_alloc_buffer(struct aml_vcodec_ctx *ctx, int flag)
+{
+	int i = 0;
+
+	if (flag & DV_TYPE) {
+		for (i = 0; i < V4L_CAP_BUFF_MAX; i++) {
+			ctx->aux_infos.bufs[i].md_buf = vzalloc(MD_BUF_SIZE);
+			if (ctx->aux_infos.bufs[i].md_buf == NULL) {
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+					"v4l2 alloc %dth dv md buffer fail\n", i);
+			}
+
+			ctx->aux_infos.bufs[i].comp_buf = vzalloc(COMP_BUF_SIZE);
+			if (ctx->aux_infos.bufs[i].comp_buf == NULL) {
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+					"v4l2 alloc %dth dv comp buffer fail\n", i);
+			}
+		}
+	}
+
+	if (flag & SEI_TYPE) {
+		for (i = 0; i < V4L_CAP_BUFF_MAX; i++) {
+			ctx->aux_infos.bufs[i].sei_buf = vzalloc(SEI_BUF_SIZE);
+			if (ctx->aux_infos.bufs[i].sei_buf) {
+				ctx->aux_infos.bufs[i].sei_size  = 0;
+				ctx->aux_infos.bufs[i].sei_state = 1;
+				ctx->aux_infos.sei_need_free = false;
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+					"v4l2 alloc %dth aux buffer:%px\n",
+					i, ctx->aux_infos.bufs[i].sei_buf);
+			} else {
+				ctx->aux_infos.bufs[i].sei_buf = NULL;
+				ctx->aux_infos.bufs[i].sei_state = 0;
+				ctx->aux_infos.bufs[i].sei_size  = 0;
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+					"v4l2 alloc %dth aux buffer fail\n", i);
+			}
+		}
+	}
+}
+
+void aml_free_buffer(struct aml_vcodec_ctx *ctx, int flag)
+{
+	int i = 0;
+
+	if (flag & DV_TYPE) {
+		for (i = 0; i < V4L_CAP_BUFF_MAX; i++) {
+			if (ctx->aux_infos.bufs[i].md_buf != NULL) {
+				vfree(ctx->aux_infos.bufs[i].md_buf);
+				ctx->aux_infos.bufs[i].md_buf = NULL;
+			}
+
+			if (ctx->aux_infos.bufs[i].comp_buf != NULL) {
+				vfree(ctx->aux_infos.bufs[i].comp_buf);
+				ctx->aux_infos.bufs[i].comp_buf = NULL;
+			}
+		}
+	}
+
+	if (flag & SEI_TYPE) {
+		for (i = 0; i < V4L_CAP_BUFF_MAX; i++) {
+			if (ctx->aux_infos.bufs[i].sei_buf != NULL) {
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+					"v4l2 free %dth aux buffer:%px\n",
+					i, ctx->aux_infos.bufs[i].sei_buf);
+				vfree(ctx->aux_infos.bufs[i].sei_buf);
+				ctx->aux_infos.bufs[i].sei_state = 0;
+				ctx->aux_infos.bufs[i].sei_size = 0;
+				ctx->aux_infos.bufs[i].sei_buf = NULL;
+			}
+		}
+	}
+}
+
+void aml_free_one_sei_buffer(struct aml_vcodec_ctx *ctx, char **addr, int *size, int idx)
+{
+	if (ctx->aux_infos.bufs[idx].sei_buf != NULL) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+			"v4l2 free %dth aux buffer:%px\n",
+			idx, ctx->aux_infos.bufs[idx].sei_buf);
+
+		vfree(ctx->aux_infos.bufs[idx].sei_buf);
+		ctx->aux_infos.bufs[idx].sei_state = 0;
+		ctx->aux_infos.bufs[idx].sei_size = 0;
+		ctx->aux_infos.bufs[idx].sei_buf = NULL;
+		*addr = NULL;
+		*size = 0;
+		ctx->aux_infos.sei_need_free = true;
+	}
+}
+
+void aml_bind_sei_buffer(struct aml_vcodec_ctx *ctx, char **addr, int *size, int *idx)
+{
+	int index = ctx->aux_infos.sei_index;
+	int count = 0;
+
+	if (ctx->aux_infos.sei_need_free) {
+		for (count = 0; count < V4L_CAP_BUFF_MAX; count++) {
+			if ((ctx->aux_infos.bufs[index].sei_buf != NULL) &&
+				(ctx->aux_infos.bufs[index].sei_state == 1)) {
+				break;
+			}
+			index = (index + 1) % V4L_CAP_BUFF_MAX;
+		}
+	} else {
+		for (count = 0; count < V4L_CAP_BUFF_MAX; count++) {
+			if ((ctx->aux_infos.bufs[index].sei_buf != NULL) &&
+				((ctx->aux_infos.bufs[index].sei_state == 1) ||
+				(ctx->aux_infos.bufs[index].sei_state == 2))) {
+				memset(ctx->aux_infos.bufs[index].sei_buf, 0, SEI_BUF_SIZE);
+				ctx->aux_infos.bufs[index].sei_size = 0;
+				break;
+			}
+			index = (index + 1) % V4L_CAP_BUFF_MAX;
+		}
+	}
+
+	if (count == V4L_CAP_BUFF_MAX) {
+		*addr = NULL;
+		*size = 0;
+	} else {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+			"v4l2 bind %dth aux buffer:%px, count = %d\n",
+			index, ctx->aux_infos.bufs[index].sei_buf, count);
+		*addr = ctx->aux_infos.bufs[index].sei_buf;
+		*size = ctx->aux_infos.bufs[index].sei_size;
+		*idx  = index;
+		ctx->aux_infos.bufs[index].sei_state = 2;
+		ctx->aux_infos.sei_index = (index + 1) % V4L_CAP_BUFF_MAX;
+	}
+}
+
+void aml_bind_dv_buffer(struct aml_vcodec_ctx *ctx, char **comp_buf, char **md_buf)
+{
+	int index = ctx->aux_infos.dv_index;
+
+	if ((ctx->aux_infos.bufs[index].comp_buf != NULL) &&
+		(ctx->aux_infos.bufs[index].md_buf != NULL)) {
+		*comp_buf = ctx->aux_infos.bufs[index].comp_buf;
+		*md_buf = ctx->aux_infos.bufs[index].md_buf;
+		ctx->aux_infos.dv_index = (index + 1) % V4L_CAP_BUFF_MAX;
+	}
+}
+
+void aml_v4l_ctx_release(struct kref *kref)
+{
+	struct aml_vcodec_ctx * ctx;
+
+	ctx = container_of(kref, struct aml_vcodec_ctx, ctx_ref);
+
+	if (ctx->vpp) {
+		atomic_dec(&ctx->dev->vpp_count);
+		aml_v4l2_vpp_destroy(ctx->vpp);
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+			"vpp destory inst count:%d.\n",
+			atomic_read(&ctx->dev->vpp_count));
+	}
+
+	if (ctx->ge2d) {
+		aml_v4l2_ge2d_destroy(ctx->ge2d);
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+			"ge2d destory.\n");
+	}
+
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+	aml_task_chain_remove(ctx);
+
+	vfree(ctx->meta_infos.meta_bufs);
+	ctx->aux_infos.free_buffer(ctx, SEI_TYPE | DV_TYPE);
+	ctx->aux_infos.free_buffer(ctx, 1);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+		"v4ldec has been destroyed.\n");
+
+	if (ctx->sync) {
+		vdec_clean_all_fence(ctx->sync);
+	}
+
+	kfree(ctx);
+}
+
+static void box_release(struct kref *kref)
+{
+	struct aml_vcodec_ctx * ctx
+		= container_of(kref, struct aml_vcodec_ctx, box_ref);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"%s, bmmu: %px, mmu: %px mmu_dw: %pu\n",
+		__func__, ctx->bmmu_box, ctx->mmu_box,ctx->mmu_box_dw);
+
+	decoder_bmmu_box_free(ctx->bmmu_box);
+	decoder_mmu_box_free(ctx->mmu_box);
+
+	if (ctx->config.parm.dec.cfg.double_write_mode & 0x20) {
+		decoder_mmu_box_free(ctx->mmu_box_dw);
+		decoder_bmmu_box_free(ctx->bmmu_box_dw);
+	}
+	vfree(ctx->comp_bufs);
+	vfree(ctx->uvm_proxy);
+	kref_put(&ctx->ctx_ref, aml_v4l_ctx_release);
+}
+
+static void internal_buf_free(void *arg)
+{
+	struct internal_comp_buf* ibuf =
+		(struct internal_comp_buf*)arg;
+	struct aml_vcodec_ctx * ctx
+		= container_of(ibuf->box_ref,struct aml_vcodec_ctx, box_ref);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"%s, idx:%d\n", __func__, ibuf->index);
+
+	mutex_lock(&ctx->comp_lock);
+
+	if (!(ibuf->ref & 0xff00)) {
+		decoder_mmu_box_free_idx(ibuf->mmu_box, ibuf->index);
+		decoder_bmmu_box_free_idx(ibuf->bmmu_box, ibuf->index);
+
+		if (ctx->config.parm.dec.cfg.double_write_mode & 0x20) {
+			decoder_mmu_box_free_idx(ibuf->mmu_box_dw, ibuf->index);
+			decoder_bmmu_box_free_idx(ibuf->bmmu_box_dw, ibuf->index);
+		}
+	}
+	ibuf->ref = 0;
+
+	mutex_unlock(&ctx->comp_lock);
+
+	kref_put(ibuf->box_ref, box_release);
+}
+
+static void internal_buf_free2(void *arg)
+{
+	struct internal_comp_buf *ibuf =
+		container_of(arg, struct internal_comp_buf, priv_data);
+	struct aml_vcodec_ctx * ctx
+		= container_of(ibuf->box_ref, struct aml_vcodec_ctx, box_ref);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"%s, idx: %d\n", __func__, ibuf->index);
+
+	mutex_lock(&ctx->comp_lock);
+
+	if (!(ibuf->ref & 0xff00)) {
+		decoder_mmu_box_free_idx(ibuf->mmu_box, ibuf->index);
+		decoder_bmmu_box_free_idx(ibuf->bmmu_box, ibuf->index);
+
+		if (ctx->config.parm.dec.cfg.double_write_mode & 0x20) {
+			decoder_mmu_box_free_idx(ibuf->mmu_box_dw, ibuf->index);
+			decoder_bmmu_box_free_idx(ibuf->bmmu_box_dw, ibuf->index);
+		}
+	}
+	ibuf->ref = 0;
+
+	mutex_unlock(&ctx->comp_lock);
+
+	kref_put(ibuf->box_ref, box_release);
+}
+
+static void aml_uvm_buf_free(void *arg)
+{
+	struct aml_uvm_buff_ref * ubuf =
+		(struct aml_uvm_buff_ref*)arg;
+	struct aml_vcodec_ctx * ctx
+		= container_of(ubuf->ref, struct aml_vcodec_ctx, ctx_ref);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"%s, vb:%d, dbuf:%px, ino:%lu\n",
+		__func__, ubuf->index, ubuf->dbuf,
+		file_inode(ubuf->dbuf->file)->i_ino);
+
+	kref_put(ubuf->ref, aml_v4l_ctx_release);
+	vfree(ubuf);
+}
+
+static int uvm_attach_hook_mod_local(struct aml_vcodec_ctx *ctx,
+				     struct uvm_hook_mod_info *uvm)
+{
+	struct internal_comp_buf* ibuf = uvm->arg;
+
+	ctx->uvm_proxy[ibuf->index] = *uvm;
+
+	return 0;
+}
+
+static int update_comp_buffer_to_reuse(struct aml_vcodec_ctx *ctx,
+				       struct aml_video_dec_buf *buf)
+{
+	struct internal_comp_buf* ibuf = NULL;
+
+	mutex_lock(&ctx->comp_lock);
+
+	ibuf = vb_to_comp(ctx, &buf->vb.vb2_buf);
+	if (!ibuf) {
+		mutex_unlock(&ctx->comp_lock);
+		return 0;
+	}
+
+	if (ibuf->ref & 0xff) {
+		buf->internal_index = ibuf->index;
+		ibuf->frame_buffer_size = ctx->comp_info.frame_buffer_size;
+
+		if (ctx->comp_info.header_size != ibuf->header_size) {
+			decoder_bmmu_box_free_idx(ctx->bmmu_box, ibuf->index);
+			if (decoder_bmmu_box_alloc_buf_phy(ctx->bmmu_box,
+				ibuf->index, ctx->comp_info.header_size,
+				"v4l2_dec", &ibuf->header_addr) < 0) {
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+					"fail to alloc %dth bmmu\n",
+					ibuf->index);
+				mutex_unlock(&ctx->comp_lock);
+				return -ENOMEM;
+			}
+			ibuf->header_size = ctx->comp_info.header_size;
+		}
+
+		ibuf->ref |= (1 << 8);
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+			"%s, reuse comp buffer vb2:%d <--> internal: %d, header_addr 0x%lx, size: %u\n",
+			__func__, buf->vb.vb2_buf.index,
+			buf->internal_index,
+			ibuf->header_addr,
+			ibuf->header_size);
+	}
+
+	mutex_unlock(&ctx->comp_lock);
+
+	return (ibuf->ref & 0xff00) ? 1 : 0;
+}
+
+static int bind_comp_buffer_to_uvm(struct aml_vcodec_ctx *ctx,
+		struct aml_video_dec_buf *buf)
+{
+	int ret, i;
+	struct dma_buf * dma = buf->vb.vb2_buf.planes[0].dbuf;
+	struct aml_dec_params *parms = &ctx->config.parm.dec;
+	struct uvm_hook_mod_info u_info;
+	struct internal_comp_buf* ibuf;
+	u32 dw_mode = VDEC_DW_NO_AFBC;
+
+	/* get header and page size */
+	if (vdec_if_get_param(ctx, GET_PARAM_COMP_BUF_INFO, &ctx->comp_info)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to get comp info\n");
+		return -EINVAL;
+	}
+
+	if (!ctx->bmmu_box || !ctx->mmu_box)
+		if (init_mmu_bmmu_box(ctx))
+			return -EINVAL;
+
+	ret = update_comp_buffer_to_reuse(ctx, buf);
+	if (ret < 0)
+		return ret;
+
+	if (ret == 1 /*reused*/)
+		return 0;
+
+	for (i = 0; i < V4L_CAP_BUFF_MAX; i++) {
+		if (!ctx->comp_bufs[i].ref)
+			break;
+	}
+
+	if (i == V4L_CAP_BUFF_MAX) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "out of internal buf\n");
+		return -EINVAL;
+	}
+
+	if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "invalid dw_mode\n");
+		return -EINVAL;
+	}
+
+	buf->internal_index	= i;
+	ibuf			= &ctx->comp_bufs[i];
+	ibuf->frame_buffer_size	= ctx->comp_info.frame_buffer_size;
+	ibuf->header_size	= ctx->comp_info.header_size;
+
+	/* allocate header */
+	ret = decoder_bmmu_box_alloc_buf_phy(ctx->bmmu_box,
+			ibuf->index, ctx->comp_info.header_size,
+			"v4l2_dec", &ibuf->header_addr);
+	if (ret < 0) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to alloc %dth bmmu\n", i);
+		return -ENOMEM;
+	}
+
+	if (dw_mode & 0x20) {
+		ret = decoder_bmmu_box_alloc_buf_phy(ctx->bmmu_box_dw,
+			ibuf->index, ctx->comp_info.header_size,
+			"v4l2_dec", &ibuf->header_dw_addr);
+		if (ret < 0) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to alloc %dth bmmu dw\n", i);
+			return -ENOMEM;
+		}
+	}
+
+	kref_get(&ctx->box_ref);
+	ibuf->ref = 1;
+
+	/* frame SG buffer need to be realloc inside decoder,
+	 * just before slice decoding to save memory
+	 */
+	u_info.type = VF_SRC_DECODER;
+	u_info.arg = ibuf;
+	u_info.free = internal_buf_free;
+
+	if (parms->cfg.uvm_hook_type == VF_PROCESS_V4LVIDEO) {
+		/* adapted video composer to use for hwc. */
+		ibuf->priv_data.v4l_inst_id = ctx->id;
+		u_info.type = VF_PROCESS_V4LVIDEO;
+		u_info.arg = &ibuf->priv_data;
+		u_info.free = internal_buf_free2;
+	}
+
+	ret = dmabuf_is_uvm(dma) ?
+		uvm_attach_hook_mod(dma, &u_info) :
+		uvm_attach_hook_mod_local(ctx, &u_info);
+	if (ret < 0) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to set dmabuf priv buf\n");
+		goto bmmu_box_free;
+	}
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"%s, bind vb2:(%d, %px) <--> internal: (%d, %px) header_addr 0x%lx, size: %u\n",
+		__func__, buf->vb.vb2_buf.index,
+		dma, i, ibuf, ibuf->header_addr,
+		ctx->comp_info.header_size);
+
+	return 0;
+
+bmmu_box_free:
+	if (dw_mode & 0x20) {
+		decoder_bmmu_box_free_idx(ibuf->bmmu_box_dw, ibuf->index);
+	}
+	decoder_bmmu_box_free_idx(ibuf->bmmu_box, ibuf->index);
+	kref_put(&ctx->box_ref, box_release);
+	ibuf->ref = 0;
+	return -EINVAL;
+}
+
+static int aml_uvm_buff_attach(struct vb2_buffer * vb)
+{
+	int ret = 0;
+	struct dma_buf *dbuf = vb->planes[0].dbuf;
+	struct uvm_hook_mod_info u_info;
+	struct aml_vcodec_ctx *ctx =
+		vb2_get_drv_priv(vb->vb2_queue);
+	struct aml_uvm_buff_ref *ubuf = NULL;
+
+	if (vb->memory != VB2_MEMORY_DMABUF || !dmabuf_is_uvm(dbuf))
+		return 0;
+
+	ubuf = vzalloc(sizeof(struct aml_uvm_buff_ref));
+	if (ubuf == NULL)
+		return -ENOMEM;
+
+	ubuf->index	= vb->index;
+	ubuf->addr	= vb2_dma_contig_plane_dma_addr(vb, 0);
+	ubuf->dbuf	= dbuf;
+	ubuf->ref	= &ctx->ctx_ref;
+
+	u_info.type	= VF_PROCESS_DECODER;
+	u_info.arg	= (void *)ubuf;
+	u_info.free	= aml_uvm_buf_free;
+	ret = uvm_attach_hook_mod(dbuf, &u_info);
+	if (ret < 0) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"aml uvm buffer %d attach fail.\n",
+			ubuf->index);
+		return ret;
+	}
+
+	kref_get(ubuf->ref);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"%s, vb:%d, dbuf:%px, ino:%lu\n",
+		__func__, ubuf->index, ubuf->dbuf,
+		file_inode(ubuf->dbuf->file)->i_ino);
+
+	return ret;
+}
+
+static struct internal_comp_buf* vb_to_comp(struct aml_vcodec_ctx *ctx,
+					    struct vb2_buffer *vb)
+{
+	struct aml_dec_params *parms = &ctx->config.parm.dec;
+	bool is_v4lvideo = (parms->cfg.uvm_hook_type == VF_PROCESS_V4LVIDEO);
+	enum uvm_hook_mod_type u_type =
+		is_v4lvideo ? VF_PROCESS_V4LVIDEO : VF_SRC_DECODER;
+	struct dma_buf *dbuf = vb->planes[0].dbuf;
+	struct internal_comp_buf *ibuf = NULL;
+	struct uvm_hook_mod *uhmod = NULL;
+
+	uhmod = uvm_get_hook_mod(dbuf, u_type);
+	if (IS_ERR_OR_NULL(uhmod))
+		return NULL;
+
+	ibuf = !is_v4lvideo ? (struct internal_comp_buf *) uhmod->arg :
+		container_of(uhmod->arg, struct internal_comp_buf, priv_data);
+
+	uvm_put_hook_mod(dbuf, u_type);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+		"%s, vb2: (%d, %px) --> comp: (%d, %px)\n",
+		__func__, vb->index, dbuf, ibuf->index, ibuf);
+
+	return ibuf;
+}
+
+static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb)
+{
+	struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vb2_v4l2 = to_vb2_v4l2_buffer(vb);
+	struct aml_video_dec_buf *buf =
+		container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
+	struct vdec_v4l2_buffer *fb = &buf->frame_buffer;
+	struct aml_vcodec_mem src_mem;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, vb: %lx, type: %d, idx: %d, state: %d, used: %d, ts: %llu\n",
+		__func__, (ulong) vb, vb->vb2_queue->type,
+		vb->index, vb->state, buf->used, vb->timestamp);
+
+	/*
+	 * check if this buffer is ready to be used after decode
+	 */
+	if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
+		u32 dw_mode = VDEC_DW_NO_AFBC;
+
+		if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode)) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "invalid dw_mode\n");
+			return;
+
+		}
+
+		if (!buf->que_in_m2m) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+				"enque capture buf idx %d, vf: %lx\n",
+				vb->index, (ulong) v4l_get_vf_handle(vb2_v4l2->private));
+
+			/* bind compressed buffer to uvm */
+			if ((dw_mode != VDEC_DW_NO_AFBC) &&
+				vb->memory == VB2_MEMORY_DMABUF &&
+				bind_comp_buffer_to_uvm(ctx, buf)) {
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to bind comp buffer\n");
+				return;
+			}
+
+			/* DI hook must be detached if the dmabuff be reused. */
+			if (ctx->vpp_cfg.enable_local_buf) {
+				struct dma_buf *dma = vb->planes[0].dbuf;
+
+				if (dmabuf_is_uvm(dma) &&
+					uvm_detach_hook_mod(dma, VF_PROCESS_DI) < 0) {
+					v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+						"dmabuf without attach DI hook.\n");
+				}
+			}
+
+			task_chain_clean(fb->task);
+
+			ctx->cap_pool.seq[ctx->cap_pool.in++] =
+				(V4L_CAP_BUFF_IN_M2M << 16 | vb->index);
+			v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2);
+			buf->que_in_m2m = true;
+
+			fb->status = FB_ST_INIT;
+			ATRACE_COUNTER("VC_IN_VSINK-2.storage", vb->index);
+
+			/* check dpb ready */
+			aml_check_dpb_ready(ctx);
+		} else {
+			struct vframe_s *vf = fb->vframe;
+			struct task_chain_s *task = fb->task;
+
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_OUTPUT,
+				"IN__BUFF (%s, st:%d, seq:%d) vb:(%d, %px), vf:(%d, %px), ts:%lld, "
+				"Y:(%lx, %u) C/U:(%lx, %u) V:(%lx, %u)\n",
+				ctx->ada_ctx->frm_name, fb->status, vf ? vf->index_disp : -1,
+				vb->index, vb,
+				vf ? vf->index & 0xff : -1, vf,
+				vf ? vf->timestamp : 0,
+				fb->m.mem[0].addr, fb->m.mem[0].size,
+				fb->m.mem[1].addr, fb->m.mem[1].size,
+				fb->m.mem[2].addr, fb->m.mem[2].size);
+
+			ATRACE_COUNTER("VC_IN_VSINK-4.recycle", vb->index);
+
+			task->recycle(task, TASK_TYPE_V4L_SINK);
+		}
+
+		wake_up_interruptible(&ctx->cap_wq);
+		return;
+	}
+
+	v4l2_m2m_buf_queue(ctx->m2m_ctx, to_vb2_v4l2_buffer(vb));
+
+	if (ctx->state != AML_STATE_INIT) {
+		return;
+	}
+
+	buf->used = true;
+	vb2_v4l2 = to_vb2_v4l2_buffer(vb);
+	buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
+	if (buf->lastframe) {
+		/* This shouldn't happen. Just in case. */
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"Invalid flush buffer.\n");
+		buf->used = false;
+		v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		if (ctx->is_drm_mode && (vb->memory == VB2_MEMORY_DMABUF))
+			wake_up_interruptible(&ctx->wq);
+
+		return;
+	}
+
+	src_mem.index	= vb->index;
+	src_mem.vaddr	= vb2_plane_vaddr(vb, 0);
+	src_mem.addr	= sg_dma_address(buf->out_sgt->sgl);
+	src_mem.size	= vb->planes[0].bytesused;
+	src_mem.model	= vb->memory;
+	src_mem.timestamp = vb->timestamp;
+	src_mem.meta_ptr = (ulong)buf->meta_data;
+
+	if (vdec_if_probe(ctx, &src_mem, NULL)) {
+		buf->used = false;
+		v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+
+		if (ctx->is_drm_mode &&
+			(src_mem.model == VB2_MEMORY_DMABUF)) {
+			wake_up_interruptible(&ctx->wq);
+		} else {
+			v4l2_buff_done(to_vb2_v4l2_buffer(vb),
+				VB2_BUF_STATE_DONE);
+		}
+
+		return;
+	}
+
+	/*
+	 * If on model dmabuf must remove the buffer
+	 * because this data has been consumed by hw.
+	 */
+	buf->used = false;
+	v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+
+	if (ctx->is_drm_mode &&
+		(src_mem.model == VB2_MEMORY_DMABUF)) {
+		wake_up_interruptible(&ctx->wq);
+	} else if (ctx->param_sets_from_ucode) {
+		v4l2_buff_done(to_vb2_v4l2_buffer(vb),
+			VB2_BUF_STATE_DONE);
+	}
+
+	if (vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->picinfo)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"GET_PARAM_PICTURE_INFO err\n");
+		return;
+	}
+
+	if (!ctx->picinfo.dpb_frames)
+		return;
+
+	v4l_buf_size_decision(ctx);
+	ctx->last_decoded_picinfo = ctx->picinfo;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Picture buffer count: dec:%u, vpp:%u, ge2d:%u, margin:%u, total:%u\n",
+		ctx->picinfo.dpb_frames, ctx->vpp_size, ctx->ge2d_size,
+		ctx->picinfo.dpb_margin,
+		CTX_BUF_TOTAL(ctx));
+
+	aml_vdec_dispatch_event(ctx, V4L2_EVENT_SRC_CH_RESOLUTION);
+
+	mutex_lock(&ctx->state_lock);
+	if (ctx->state == AML_STATE_INIT) {
+		ctx->state = AML_STATE_PROBE;
+		ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
+			"vcodec state (AML_STATE_PROBE)\n");
+	}
+	mutex_unlock(&ctx->state_lock);
+}
+
+static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb)
+{
+	struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vb2_v4l2 = NULL;
+	struct aml_video_dec_buf *buf = NULL;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %d, idx: %d\n",
+		__func__, vb->vb2_queue->type, vb->index);
+
+	vb2_v4l2 = to_vb2_v4l2_buffer(vb);
+	buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
+
+	if (buf->error) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"Unrecoverable error on buffer.\n");
+		ctx->state = AML_STATE_ABORT;
+		ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
+			"vcodec state (AML_STATE_ABORT)\n");
+	}
+}
+
+static int vb2ops_vdec_buf_init(struct vb2_buffer *vb)
+{
+	struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb,
+					struct vb2_v4l2_buffer, vb2_buf);
+	struct aml_video_dec_buf *buf = container_of(vb2_v4l2,
+					struct aml_video_dec_buf, vb);
+	struct vdec_v4l2_buffer *fb = &buf->frame_buffer;
+	u32 size, phy_addr = 0;
+	int i;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s, type: %d, idx: %d\n",
+		__func__, vb->vb2_queue->type, vb->index);
+
+	if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
+		buf->lastframe = false;
+	}
+
+	/* codec_mm buffers count */
+	if (!V4L2_TYPE_IS_OUTPUT(vb->type)) {
+		if (vb->memory == VB2_MEMORY_MMAP) {
+			char *owner = __getname();
+
+			snprintf(owner, PATH_MAX, "%s-%d", "v4l-output", ctx->id);
+			strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer));
+			buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0';
+			__putname(owner);
+
+			for (i = 0; i < vb->num_planes; i++) {
+				size = vb->planes[i].length;
+				phy_addr = vb2_dma_contig_plane_dma_addr(vb, i);
+				buf->mem[i] = v4l_reqbufs_from_codec_mm(buf->mem_onwer,
+						phy_addr, size, vb->index);
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+						"OUT %c alloc, addr: %x, size: %u, idx: %u\n",
+						(i == 0? 'Y':'C'), phy_addr, size, vb->index);
+			}
+		} else if (vb->memory == VB2_MEMORY_DMABUF) {
+			unsigned int dw_mode = VDEC_DW_NO_AFBC;
+
+			for (i = 0; i < vb->num_planes; i++) {
+				struct dma_buf * dma;
+
+				if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode)) {
+					v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "invalid dw_mode\n");
+					return -EINVAL;
+				}
+				/* None-DW mode means single layer */
+				if (dw_mode == VDEC_DW_AFBC_ONLY && i > 0) {
+					v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+							"only support single plane in dw mode 0\n");
+					return -EINVAL;
+				}
+				size = vb->planes[i].length;
+				dma = vb->planes[i].dbuf;
+
+				if (!dmabuf_is_uvm(dma))
+					v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "non-uvm dmabuf\n");
+			}
+		}
+	}
+
+	if (!V4L2_TYPE_IS_OUTPUT(vb->type)) {
+		struct vframe_s *vf = NULL;
+		struct task_chain_s *task = NULL;
+		struct task_chain_s *task_pre = fb->task;
+		u32 icomp = -1;
+
+		fb_map_table_fetch(ctx, vb, &vf, &task, &icomp);
+		if (vf) {
+			fb->task		= task;
+			fb->vframe		= vf;
+			vf->v4l_mem_handle	= (ulong)fb;
+			buf->internal_index	= icomp;
+			task_chain_update_object(task, fb);
+		} else {
+			buf->que_in_m2m = false;
+
+			if (aml_uvm_buff_attach(vb))
+				return -EFAULT;
+
+			if (task_chain_init(&fb->task, ctx, fb, vb->index))
+				return -EFAULT;
+
+			list_add(&fb->task->node, &ctx->task_chain_pool);
+ 		}
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+			"init buffer(%s), vb idx:%d, task:(%px -> %px), addr:(%lx -> %lx), icomp:%d\n",
+			vf ? "update" : "idel",
+			vb->index, task_pre, fb->task,
+			fb->m.mem[0].addr,
+			(ulong) vb2_dma_contig_plane_dma_addr(vb, 0),
+			(int)icomp);
+
+		update_vdec_buf_plane(ctx, fb, vb);
+	}
+
+	if (V4L2_TYPE_IS_OUTPUT(vb->type)) {
+		ulong contig_size;
+
+		buf->out_sgt = vb2_dma_sg_plane_desc(vb, 0);
+
+		contig_size = dmabuf_contiguous_size(buf->out_sgt);
+		if (contig_size < vb->planes[0].bytesused) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"contiguous mapping is too small %lu/%u\n",
+				contig_size, size);
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
+static void vb2ops_vdec_buf_cleanup(struct vb2_buffer *vb)
+{
+	struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb,
+					struct vb2_v4l2_buffer, vb2_buf);
+	struct aml_video_dec_buf *buf = container_of(vb2_v4l2,
+					struct aml_video_dec_buf, vb);
+	struct vdec_v4l2_buffer *fb = &buf->frame_buffer;;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s, type: %d, idx: %d\n",
+		__func__, vb->vb2_queue->type, vb->index);
+
+	if (!V4L2_TYPE_IS_OUTPUT(vb->type)) {
+		if (vb->memory == VB2_MEMORY_MMAP) {
+			int i;
+
+			for (i = 0; i < vb->num_planes ; i++) {
+				v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
+					"OUT %c clean, addr: %lx, size: %u, idx: %u\n",
+					(i == 0)? 'Y':'C',
+					buf->mem[i]->phy_addr, buf->mem[i]->buffer_size, vb->index);
+				v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[i]);
+				buf->mem[i] = NULL;
+			}
+		}
+		if (ctx->output_thread_ready) {
+			if (!is_fb_mapped(ctx, fb->m.mem[0].addr)) {
+				list_del(&fb->task->node);
+				task_chain_clean(fb->task);
+				task_chain_release(fb->task);
+			}
+		}
+	}
+}
+
+static int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q);
+
+	ctx->has_receive_eos = false;
+	ctx->v4l_resolution_change = false;
+
+	/* vdec has ready to decode subsequence data of new resolution. */
+	v4l2_m2m_job_resume(ctx->dev->m2m_dev_dec, ctx->m2m_ctx);
+
+	v4l2_m2m_set_dst_buffered(ctx->fh.m2m_ctx, true);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %d\n", __func__, q->type);
+
+	return 0;
+}
+
+static void vb2ops_vdec_stop_streaming(struct vb2_queue *q)
+{
+	struct aml_video_dec_buf *buf = NULL;
+	struct vb2_v4l2_buffer *vb2_v4l2 = NULL;
+	struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q);
+	int i;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, type: %d, state: %x, frame_cnt: %d\n",
+		__func__, q->type, ctx->state, ctx->decoded_frame_cnt);
+
+	if (V4L2_TYPE_IS_OUTPUT(q->type))
+		ctx->is_out_stream_off = true;
+	else
+		ctx->is_stream_off = true;
+
+	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+		struct vb2_queue * que = v4l2_m2m_get_dst_vq(ctx->m2m_ctx);
+		unsigned long flags;
+
+		cancel_work_sync(&ctx->dmabuff_recycle_work);
+		spin_lock_irqsave(&ctx->dmabuff_recycle_lock, flags);
+		INIT_KFIFO(ctx->dmabuff_recycle);
+		spin_unlock_irqrestore(&ctx->dmabuff_recycle_lock, flags);
+
+		while ((vb2_v4l2 = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
+			v4l2_buff_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
+
+		for (i = 0; i < q->num_buffers; ++i) {
+			vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]);
+			if (vb2_v4l2->vb2_buf.state == VB2_BUF_STATE_ACTIVE)
+				v4l2_buff_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
+		}
+
+		/*
+		 * drop es frame was stored in the vdec_input
+		 * if the capture queue have not start streaming.
+		 */
+		if (!que->streaming &&
+			(vdec_frame_number(ctx->ada_ctx) > 0) &&
+			(ctx->state < AML_STATE_ACTIVE)) {
+			ctx->state = AML_STATE_INIT;
+			ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+			ctx->v4l_resolution_change = false;
+			ctx->reset_flag = V4L_RESET_MODE_NORMAL;
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+				"force reset to drop es frames.\n");
+			wake_up_interruptible(&ctx->cap_wq);
+			aml_vdec_reset(ctx);
+		}
+	} else {
+		/* clean output cache and decoder status . */
+		if (ctx->state > AML_STATE_INIT) {
+			wake_up_interruptible(&ctx->cap_wq);
+			aml_vdec_reset(ctx);
+		}
+
+		cancel_work_sync(&ctx->decode_work);
+		mutex_lock(&ctx->capture_buffer_lock);
+		INIT_KFIFO(ctx->capture_buffer);
+		mutex_unlock(&ctx->capture_buffer_lock);
+
+		while ((vb2_v4l2 = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)))
+			v4l2_buff_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
+
+		for (i = 0; i < q->num_buffers; ++i) {
+			vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]);
+			buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
+			buf->frame_buffer.status	= FB_ST_FREE;
+			buf->frame_buffer.vframe	= NULL;
+			buf->que_in_m2m			= false;
+			buf->used			= false;
+			buf->vb.flags			= 0;
+			ctx->cap_pool.seq[i]		= 0;
+
+			if (vb2_v4l2->vb2_buf.state == VB2_BUF_STATE_ACTIVE)
+				v4l2_buff_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
+
+			/*v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO, "idx: %d, state: %d\n",
+				q->bufs[i]->index, q->bufs[i]->state);*/
+		}
+
+		fb_map_table_clean(ctx);
+
+		fb_token_clean(ctx);
+
+		ctx->buf_used_count = 0;
+		ctx->cap_pool.in = 0;
+		ctx->cap_pool.out = 0;
+		ctx->cap_pool.dec = 0;
+		ctx->cap_pool.vpp = 0;
+	}
+}
+
+static void m2mops_vdec_device_run(void *priv)
+{
+	struct aml_vcodec_ctx *ctx = priv;
+	struct aml_vcodec_dev *dev = ctx->dev;
+
+	if (ctx->output_thread_ready)
+		queue_work(dev->decode_workqueue, &ctx->decode_work);
+}
+
+static int m2mops_vdec_job_ready(void *m2m_priv)
+{
+	struct aml_vcodec_ctx *ctx = m2m_priv;
+
+	if (ctx->state < AML_STATE_PROBE ||
+		ctx->state > AML_STATE_FLUSHED)
+		return 0;
+
+	return 1;
+}
+
+static void m2mops_vdec_job_abort(void *priv)
+{
+	struct aml_vcodec_ctx *ctx = priv;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO, "%s\n", __func__);
+}
+
+static int aml_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct aml_vcodec_ctx *ctx = ctrl_to_ctx(ctrl);
+	int ret = 0;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
+		"%s, id: %d\n", __func__, ctrl->id);
+
+	switch (ctrl->id) {
+	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
+		if (ctx->state >= AML_STATE_PROBE) {
+			ctrl->val = CTX_BUF_TOTAL(ctx);
+		} else {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"Seqinfo not ready.\n");
+			ctrl->val = 0;
+		}
+		break;
+	case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
+		ctrl->val = 4;
+		break;
+	case AML_V4L2_GET_INPUT_BUFFER_NUM:
+		if (ctx->ada_ctx != NULL)
+			ctrl->val = vdec_frame_number(ctx->ada_ctx);
+		break;
+	case AML_V4L2_GET_FILMGRAIN_INFO:
+		ctrl->val = ctx->film_grain_present;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int aml_vdec_try_s_v_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct aml_vcodec_ctx *ctx = ctrl_to_ctx(ctrl);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s\n", __func__);
+
+	if (ctrl->id == AML_V4L2_SET_DRMMODE) {
+		ctx->is_drm_mode = ctrl->val;
+		ctx->param_sets_from_ucode = true;
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+			"set stream mode: %x\n", ctrl->val);
+	} else if (ctrl->id == AML_V4L2_SET_DURATION) {
+		vdec_set_duration(ctrl->val);
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+			"set duration: %x\n", ctrl->val);
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops aml_vcodec_dec_ctrl_ops = {
+	.g_volatile_ctrl = aml_vdec_g_v_ctrl,
+	.try_ctrl = aml_vdec_try_s_v_ctrl,
+};
+
+static const struct v4l2_ctrl_config ctrl_st_mode = {
+	.name	= "drm mode",
+	.id	= AML_V4L2_SET_DRMMODE,
+	.ops	= &aml_vcodec_dec_ctrl_ops,
+	.type	= V4L2_CTRL_TYPE_BOOLEAN,
+	.flags	= V4L2_CTRL_FLAG_WRITE_ONLY,
+	.min	= 0,
+	.max	= 1,
+	.step	= 1,
+	.def	= 0,
+};
+
+static const struct v4l2_ctrl_config ctrl_gt_input_buffer_number = {
+	.name	= "input buffer number",
+	.id	= AML_V4L2_GET_INPUT_BUFFER_NUM,
+	.ops	= &aml_vcodec_dec_ctrl_ops,
+	.type	= V4L2_CTRL_TYPE_INTEGER,
+	.flags	= V4L2_CTRL_FLAG_VOLATILE,
+	.min	= 0,
+	.max	= 128,
+	.step	= 1,
+	.def	= 0,
+};
+
+static const struct v4l2_ctrl_config ctrl_st_duration = {
+	.name	= "duration",
+	.id	= AML_V4L2_SET_DURATION,
+	.ops	= &aml_vcodec_dec_ctrl_ops,
+	.type	= V4L2_CTRL_TYPE_INTEGER,
+	.flags	= V4L2_CTRL_FLAG_WRITE_ONLY,
+	.min	= 0,
+	.max	= 96000,
+	.step	= 1,
+	.def	= 0,
+};
+
+static const struct v4l2_ctrl_config ctrl_gt_filmgrain_info = {
+	.name	= "filmgrain info",
+	.id	= AML_V4L2_GET_FILMGRAIN_INFO,
+	.ops	= &aml_vcodec_dec_ctrl_ops,
+	.type	= V4L2_CTRL_TYPE_INTEGER,
+	.flags	= V4L2_CTRL_FLAG_VOLATILE,
+	.min	= 0,
+	.max	= 1,
+	.step	= 1,
+	.def	= 0,
+};
+
+int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx)
+{
+	int ret;
+	struct v4l2_ctrl *ctrl;
+
+	v4l2_ctrl_handler_init(&ctx->ctrl_hdl, 3);
+	ctrl = v4l2_ctrl_new_std(&ctx->ctrl_hdl,
+				&aml_vcodec_dec_ctrl_ops,
+				V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
+				0, 32, 1, 2);
+	if ((ctrl == NULL) || (ctx->ctrl_hdl.error)) {
+		ret = ctx->ctrl_hdl.error;
+		goto err;
+	}
+	ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+	ctrl = v4l2_ctrl_new_std(&ctx->ctrl_hdl,
+				&aml_vcodec_dec_ctrl_ops,
+				V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
+				0, 32, 1, 8);
+	if ((ctrl == NULL) || (ctx->ctrl_hdl.error)) {
+		ret = ctx->ctrl_hdl.error;
+		goto err;
+	}
+	ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+	ctrl = v4l2_ctrl_new_custom(&ctx->ctrl_hdl, &ctrl_st_mode, NULL);
+	if ((ctrl == NULL) || (ctx->ctrl_hdl.error)) {
+		ret = ctx->ctrl_hdl.error;
+		goto err;
+	}
+
+	ctrl = v4l2_ctrl_new_custom(&ctx->ctrl_hdl, &ctrl_gt_input_buffer_number, NULL);
+	if ((ctrl == NULL) || (ctx->ctrl_hdl.error)) {
+		ret = ctx->ctrl_hdl.error;
+		goto err;
+	}
+
+	ctrl = v4l2_ctrl_new_custom(&ctx->ctrl_hdl, &ctrl_st_duration, NULL);
+	if ((ctrl == NULL) || (ctx->ctrl_hdl.error)) {
+		ret = ctx->ctrl_hdl.error;
+		goto err;
+	}
+
+	ctrl = v4l2_ctrl_new_custom(&ctx->ctrl_hdl, &ctrl_gt_filmgrain_info, NULL);
+	if ((ctrl == NULL) || (ctx->ctrl_hdl.error)) {
+		ret = ctx->ctrl_hdl.error;
+		goto err;
+	}
+
+	v4l2_ctrl_handler_setup(&ctx->ctrl_hdl);
+
+	return 0;
+err:
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+		"Adding control failed %d\n",
+		ctx->ctrl_hdl.error);
+	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+	return ret;
+}
+
+static int vidioc_vdec_g_parm(struct file *file, void *fh,
+	struct v4l2_streamparm *a)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+	struct vb2_queue *dst_vq;
+
+	dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	if (!dst_vq) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"no vb2 queue for type=%d\n", V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		return -EINVAL;
+	}
+
+	if (!V4L2_TYPE_IS_MULTIPLANAR(a->type) && dst_vq->is_multiplanar)
+		return -EINVAL;
+
+	if ((a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) || (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) {
+		if (vdec_if_get_param(ctx, GET_PARAM_CONFIG_INFO, &ctx->config.parm.dec))
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"GET_PARAM_CONFIG_INFO err\n");
+		else
+			memcpy(a->parm.raw_data, ctx->config.parm.data,
+				sizeof(a->parm.raw_data));
+	}
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s\n", __func__);
+
+	return 0;
+}
+
+static int check_dec_cfginfo(struct aml_vdec_cfg_infos *cfg)
+{
+	if (cfg->double_write_mode != 0 &&
+		cfg->double_write_mode != 1 &&
+		cfg->double_write_mode != 2 &&
+		cfg->double_write_mode != 3 &&
+		cfg->double_write_mode != 4 &&
+		cfg->double_write_mode != 16 &&
+		cfg->double_write_mode != 0x21 &&
+		cfg->double_write_mode != 0x100 &&
+		cfg->double_write_mode != 0x200) {
+		pr_err("invalid double write mode %d\n", cfg->double_write_mode);
+		return -1;
+	}
+	if (cfg->ref_buf_margin > 20) {
+		pr_err("invalid margin %d\n", cfg->ref_buf_margin);
+		return -1;
+	}
+
+	if (mandatory_dw_mmu) {
+		cfg->double_write_mode = 0x21;
+	}
+
+	pr_info("double write mode %d margin %d\n",
+		cfg->double_write_mode, cfg->ref_buf_margin);
+	return 0;
+}
+
+static int vidioc_vdec_s_parm(struct file *file, void *fh,
+	struct v4l2_streamparm *a)
+{
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+	struct vb2_queue *dst_vq;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s\n", __func__);
+
+	dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	if (!dst_vq) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"no vb2 queue for type=%d\n", V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		return -EINVAL;
+	}
+
+	if (!V4L2_TYPE_IS_MULTIPLANAR(a->type) && dst_vq->is_multiplanar)
+		return -EINVAL;
+
+	if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT ||
+		a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		struct aml_dec_params *in =
+			(struct aml_dec_params *) a->parm.raw_data;
+		struct aml_dec_params *dec = &ctx->config.parm.dec;
+
+		ctx->config.type = V4L2_CONFIG_PARM_DECODE;
+
+		if (in->parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO) {
+			if (check_dec_cfginfo(&in->cfg))
+				return -EINVAL;
+			dec->cfg = in->cfg;
+		}
+		if (in->parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO)
+			dec->ps = in->ps;
+		if (in->parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO)
+			dec->hdr = in->hdr;
+		if (in->parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO)
+			dec->cnt = in->cnt;
+
+		dec->parms_status |= in->parms_status;
+
+		/* aml v4l driver parms config. */
+		ctx->vpp_cfg.enable_nr =
+			(dec->cfg.metadata_config_flag & (1 << 15));
+		if (force_enable_nr)
+			ctx->vpp_cfg.enable_nr = true;
+
+		ctx->vpp_cfg.enable_local_buf =
+			(dec->cfg.metadata_config_flag & (1 << 14));
+		if (force_enable_di_local_buffer)
+			ctx->vpp_cfg.enable_local_buf = true;
+
+		ctx->internal_dw_scale = dec->cfg.metadata_config_flag & (1 << 13);
+		ctx->second_field_pts_mode = dec->cfg.metadata_config_flag & (1 << 12);
+
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s parms:%x metadata_config_flag: 0x%x\n",
+				__func__, in->parms_status, dec->cfg.metadata_config_flag);
+
+		memset(a->parm.output.reserved, 0, sizeof(a->parm.output.reserved));
+	} else {
+		memset(a->parm.capture.reserved, 0, sizeof(a->parm.capture.reserved));
+	}
+
+	return 0;
+}
+
+
+const struct v4l2_m2m_ops aml_vdec_m2m_ops = {
+	.device_run	= m2mops_vdec_device_run,
+	.job_ready	= m2mops_vdec_job_ready,
+	.job_abort	= m2mops_vdec_job_abort,
+};
+
+static const struct vb2_ops aml_vdec_vb2_ops = {
+	.queue_setup	= vb2ops_vdec_queue_setup,
+	.buf_prepare	= vb2ops_vdec_buf_prepare,
+	.buf_queue	= vb2ops_vdec_buf_queue,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
+	.buf_init	= vb2ops_vdec_buf_init,
+	.buf_cleanup	= vb2ops_vdec_buf_cleanup,
+	.buf_finish	= vb2ops_vdec_buf_finish,
+	.start_streaming = vb2ops_vdec_start_streaming,
+	.stop_streaming	= vb2ops_vdec_stop_streaming,
+};
+
+const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = {
+	.vidioc_streamon		= vidioc_decoder_streamon,
+	.vidioc_streamoff		= vidioc_decoder_streamoff,
+	.vidioc_reqbufs			= vidioc_decoder_reqbufs,
+	.vidioc_querybuf		= vidioc_vdec_querybuf,
+	.vidioc_expbuf			= vidioc_vdec_expbuf,
+	//.vidioc_g_ctrl		= vidioc_vdec_g_ctrl,
+
+	.vidioc_qbuf			= vidioc_vdec_qbuf,
+	.vidioc_dqbuf			= vidioc_vdec_dqbuf,
+
+	.vidioc_try_fmt_vid_cap_mplane	= vidioc_try_fmt_vid_cap_out,
+	.vidioc_try_fmt_vid_cap		= vidioc_try_fmt_vid_cap_out,
+	.vidioc_try_fmt_vid_out_mplane	= vidioc_try_fmt_vid_cap_out,
+	.vidioc_try_fmt_vid_out		= vidioc_try_fmt_vid_cap_out,
+
+	.vidioc_s_fmt_vid_cap_mplane	= vidioc_vdec_s_fmt,
+	.vidioc_s_fmt_vid_cap		= vidioc_vdec_s_fmt,
+	.vidioc_s_fmt_vid_out_mplane	= vidioc_vdec_s_fmt,
+	.vidioc_s_fmt_vid_out		= vidioc_vdec_s_fmt,
+	.vidioc_g_fmt_vid_cap_mplane	= vidioc_vdec_g_fmt,
+	.vidioc_g_fmt_vid_cap		= vidioc_vdec_g_fmt,
+	.vidioc_g_fmt_vid_out_mplane	= vidioc_vdec_g_fmt,
+	.vidioc_g_fmt_vid_out		= vidioc_vdec_g_fmt,
+
+	.vidioc_create_bufs		= vidioc_vdec_create_bufs,
+
+	//fixme
+	//.vidioc_enum_fmt_vid_cap_mplane	= vidioc_vdec_enum_fmt_vid_cap_mplane,
+	//.vidioc_enum_fmt_vid_out_mplane = vidioc_vdec_enum_fmt_vid_out_mplane,
+	.vidioc_enum_fmt_vid_cap	= vidioc_vdec_enum_fmt_vid_cap_mplane,
+	.vidioc_enum_fmt_vid_out	= vidioc_vdec_enum_fmt_vid_out_mplane,
+	.vidioc_enum_framesizes		= vidioc_enum_framesizes,
+
+	.vidioc_querycap		= vidioc_vdec_querycap,
+	.vidioc_subscribe_event		= vidioc_vdec_subscribe_evt,
+	.vidioc_unsubscribe_event	= vidioc_vdec_event_unsubscribe,
+	.vidioc_g_selection		= vidioc_vdec_g_selection,
+	.vidioc_s_selection		= vidioc_vdec_s_selection,
+
+	.vidioc_decoder_cmd		= vidioc_decoder_cmd,
+	.vidioc_try_decoder_cmd		= vidioc_try_decoder_cmd,
+
+	.vidioc_g_parm			= vidioc_vdec_g_parm,
+	.vidioc_s_parm			= vidioc_vdec_s_parm,
+};
+
+int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
+			   struct vb2_queue *dst_vq)
+{
+	struct aml_vcodec_ctx *ctx = priv;
+	int ret = 0;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO, "%s\n", __func__);
+
+	src_vq->type		= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes	= VB2_DMABUF | VB2_MMAP | VB2_USERPTR;
+	src_vq->drv_priv	= ctx;
+	src_vq->buf_struct_size = sizeof(struct aml_video_dec_buf);
+	src_vq->ops		= &aml_vdec_vb2_ops;
+	src_vq->mem_ops		= &vb2_dma_sg_memops;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock		= &ctx->dev->dev_mutex;
+	ret = vb2_queue_init(src_vq);
+	if (ret) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"Failed to initialize videobuf2 queue(output)\n");
+		return ret;
+	}
+
+	dst_vq->type		= multiplanar ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
+					V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	dst_vq->io_modes	= VB2_DMABUF | VB2_MMAP | VB2_USERPTR;
+	dst_vq->drv_priv	= ctx;
+	dst_vq->buf_struct_size = sizeof(struct aml_video_dec_buf);
+	dst_vq->ops		= &aml_vdec_vb2_ops;
+	dst_vq->mem_ops		= &vb2_dma_contig_memops;
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock		= &ctx->dev->dev_mutex;
+	dst_vq->min_buffers_needed = 1;
+	ret = vb2_queue_init(dst_vq);
+	if (ret) {
+		vb2_queue_release(src_vq);
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"Failed to initialize videobuf2 queue(capture)\n");
+	}
+
+	return ret;
+}
+
diff --git a/drivers/amvdec_ports/aml_vcodec_dec.h b/drivers/amvdec_ports/aml_vcodec_dec.h
new file mode 100644
index 0000000..a23522c
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_dec.h
@@ -0,0 +1,148 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#ifndef _AML_VCODEC_DEC_H_
+#define _AML_VCODEC_DEC_H_
+
+#include <linux/kref.h>
+#include <linux/scatterlist.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/amlogic/media/video_sink/v4lvideo_ext.h>
+#include "aml_vcodec_util.h"
+#include "aml_task_chain.h"
+
+#define VCODEC_CAPABILITY_4K_DISABLED	0x10
+#define VCODEC_DEC_4K_CODED_WIDTH	4096U
+#define VCODEC_DEC_4K_CODED_HEIGHT	2304U
+#define AML_VDEC_MAX_W			2048U
+#define AML_VDEC_MAX_H			1088U
+
+#define AML_VDEC_IRQ_STATUS_DEC_SUCCESS	0x10000
+#define V4L2_BUF_FLAG_LAST		0x00100000
+
+#define VDEC_GATHER_MEMORY_TYPE		0
+#define VDEC_SCATTER_MEMORY_TYPE	1
+
+#define META_DATA_SIZE			(256)
+#define MD_BUF_SIZE			(1024)
+#define COMP_BUF_SIZE			(8196)
+#define SEI_BUF_SIZE			(2 * 12 * 1024)
+#define SEI_TYPE	(1)
+#define DV_TYPE		(2)
+
+
+/*
+ * struct vdec_v4l2_buffer - decoder frame buffer
+ * @mem_type	: gather or scatter memory.
+ * @num_planes	: used number of the plane
+ * @mem[4]	: array mem for used planes,
+ *		  mem[0]: Y, mem[1]: C/U, mem[2]: V
+ * @vf_fd	: the file handle of video frame
+ * @status      : frame buffer status (vdec_fb_status)
+ * @buf_idx	: the index from vb2 index.
+ * @vframe	: store the vframe that get from caller.
+ * @task	: the context of task chain manager.
+ */
+
+struct vdec_v4l2_buffer {
+	int	mem_type;
+	int	num_planes;
+	union {
+		struct	aml_vcodec_mem mem[4];
+		u32	vf_fd;
+	} m;
+	u32	status;
+	u32	buf_idx;
+	void	*vframe;
+
+	struct task_chain_s *task;
+};
+
+/**
+ * struct aml_video_dec_buf - Private data related to each VB2 buffer.
+ * @b:		VB2 buffer
+ * @list:	link list
+ * @used:	Capture buffer contain decoded frame data and keep in
+ *			codec data structure
+ * @lastframe:		Intput buffer is last buffer - EOS
+ * @error:		An unrecoverable error occurs on this buffer.
+ * @frame_buffer:	Decode status, and buffer information of Capture buffer
+ *
+ * Note : These status information help us track and debug buffer state
+ */
+struct aml_video_dec_buf {
+	struct vb2_v4l2_buffer vb;
+	struct list_head list;
+
+	struct vdec_v4l2_buffer frame_buffer;
+	struct file_private_data privdata;
+	struct codec_mm_s *mem[2];
+	char mem_onwer[32];
+	bool used;
+	bool que_in_m2m;
+	bool lastframe;
+	bool error;
+
+	/* internal compressed buffer */
+	unsigned int internal_index;
+
+	ulong vpp_buf_handle;
+	ulong ge2d_buf_handle;
+
+	/*4 bytes data for data len*/
+	char meta_data[META_DATA_SIZE + 4];
+
+	struct sg_table *out_sgt;
+	struct sg_table *cap_sgt;
+};
+
+extern const struct v4l2_ioctl_ops aml_vdec_ioctl_ops;
+extern const struct v4l2_m2m_ops aml_vdec_m2m_ops;
+
+/*
+ * aml_vdec_lock/aml_vdec_unlock are for ctx instance to
+ * get/release lock before/after access decoder hw.
+ * aml_vdec_lock get decoder hw lock and set curr_ctx
+ * to ctx instance that get lock
+ */
+void aml_vdec_unlock(struct aml_vcodec_ctx *ctx);
+void aml_vdec_lock(struct aml_vcodec_ctx *ctx);
+int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
+			   struct vb2_queue *dst_vq);
+void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx);
+void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx);
+int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx);
+void wait_vcodec_ending(struct aml_vcodec_ctx *ctx);
+void vdec_frame_buffer_release(void *data);
+void aml_vdec_dispatch_event(struct aml_vcodec_ctx *ctx, u32 changes);
+void* v4l_get_vf_handle(int fd);
+void aml_v4l_ctx_release(struct kref *kref);
+void dmabuff_recycle_worker(struct work_struct *work);
+void aml_buffer_status(struct aml_vcodec_ctx *ctx);
+void aml_vdec_basic_information(struct aml_vcodec_ctx *ctx);
+
+void aml_alloc_buffer(struct aml_vcodec_ctx *ctx, int flag);
+void aml_free_buffer(struct aml_vcodec_ctx *ctx, int flag);
+void aml_free_one_sei_buffer(struct aml_vcodec_ctx *ctx, char **addr, int *size, int idx);
+void aml_bind_sei_buffer(struct aml_vcodec_ctx *v4l, char **addr, int *size, int *idx);
+void aml_bind_dv_buffer(struct aml_vcodec_ctx *v4l, char **comp_buf, char **md_buf);
+
+#endif /* _AML_VCODEC_DEC_H_ */
diff --git a/drivers/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amvdec_ports/aml_vcodec_dec_drv.c
new file mode 100644
index 0000000..18f0254
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_dec_drv.c
@@ -0,0 +1,754 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+
+#define DEBUG
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+#include <linux/kthread.h>
+#include <linux/compat.h>
+#include "aml_vcodec_drv.h"
+#include "aml_vcodec_dec.h"
+#include "aml_vcodec_util.h"
+#include "aml_vcodec_vpp.h"
+#include <linux/file.h>
+#include <linux/anon_inodes.h>
+
+#define VDEC_HW_ACTIVE		0x10
+#define VDEC_IRQ_CFG		0x11
+#define VDEC_IRQ_CLR		0x10
+#define VDEC_IRQ_CFG_REG	0xa4
+
+#define V4LVIDEO_IOC_MAGIC  'I'
+#define V4LVIDEO_IOCTL_ALLOC_FD				_IOW(V4LVIDEO_IOC_MAGIC, 0x02, int)
+#define V4LVIDEO_IOCTL_CHECK_FD				_IOW(V4LVIDEO_IOC_MAGIC, 0x03, int)
+#define V4LVIDEO_IOCTL_SET_CONFIG_PARAMS	_IOWR(V4LVIDEO_IOC_MAGIC, 0x04, struct v4l2_config_parm)
+#define V4LVIDEO_IOCTL_GET_CONFIG_PARAMS	_IOWR(V4LVIDEO_IOC_MAGIC, 0x05, struct v4l2_config_parm)
+
+bool param_sets_from_ucode = 1;
+bool enable_drm_mode;
+extern void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx);
+
+static int fops_vcodec_open(struct file *file)
+{
+	struct aml_vcodec_dev *dev = video_drvdata(file);
+	struct aml_vcodec_ctx *ctx = NULL;
+	struct aml_video_dec_buf *aml_buf = NULL;
+	int ret = 0;
+	struct vb2_queue *src_vq;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+	kref_init(&ctx->ctx_ref);
+
+	aml_buf = kzalloc(sizeof(*aml_buf), GFP_KERNEL);
+	if (!aml_buf) {
+		kfree(ctx);
+		return -ENOMEM;
+	}
+
+	ctx->meta_infos.meta_bufs = vzalloc(sizeof(struct meta_data) * V4L_CAP_BUFF_MAX);
+	if (ctx->meta_infos.meta_bufs == NULL) {
+		kfree(aml_buf);
+		kfree(ctx);
+		return -ENOMEM;
+	}
+
+	mutex_lock(&dev->dev_mutex);
+	ctx->empty_flush_buf = aml_buf;
+	ctx->id = dev->id_counter++;
+	v4l2_fh_init(&ctx->fh, video_devdata(file));
+	file->private_data = &ctx->fh;
+	v4l2_fh_add(&ctx->fh);
+	INIT_LIST_HEAD(&ctx->list);
+	INIT_LIST_HEAD(&ctx->vdec_thread_list);
+	INIT_LIST_HEAD(&ctx->task_chain_pool);
+	dev->filp = file;
+	ctx->dev = dev;
+	init_waitqueue_head(&ctx->queue);
+	mutex_init(&ctx->capture_buffer_lock);
+	mutex_init(&ctx->buff_done_lock);
+	mutex_init(&ctx->state_lock);
+	mutex_init(&ctx->comp_lock);
+	spin_lock_init(&ctx->slock);
+	spin_lock_init(&ctx->tsplock);
+	spin_lock_init(&ctx->dmabuff_recycle_lock);
+	init_completion(&ctx->comp);
+	init_waitqueue_head(&ctx->wq);
+	init_waitqueue_head(&ctx->cap_wq);
+	init_waitqueue_head(&ctx->post_done_wq);
+	INIT_WORK(&ctx->dmabuff_recycle_work, dmabuff_recycle_worker);
+	INIT_KFIFO(ctx->dmabuff_recycle);
+	INIT_KFIFO(ctx->capture_buffer);
+
+	ctx->post_to_upper_done = true;
+	ctx->param_sets_from_ucode = param_sets_from_ucode ? 1 : 0;
+
+	if (enable_drm_mode) {
+		ctx->is_drm_mode = true;
+		ctx->param_sets_from_ucode = true;
+	}
+
+	ctx->type = AML_INST_DECODER;
+	ret = aml_vcodec_dec_ctrls_setup(ctx);
+	if (ret) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"Failed to setup vcodec controls\n");
+		goto err_ctrls_setup;
+	}
+	ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx,
+		&aml_vcodec_dec_queue_init);
+	if (IS_ERR((__force void *)ctx->m2m_ctx)) {
+		ret = PTR_ERR((__force void *)ctx->m2m_ctx);
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"Failed to v4l2_m2m_ctx_init() (%d)\n", ret);
+		goto err_m2m_ctx_init;
+	}
+	src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
+				V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+	ctx->output_thread_ready = true;
+	ctx->empty_flush_buf->vb.vb2_buf.vb2_queue = src_vq;
+	ctx->empty_flush_buf->lastframe = true;
+	ctx->vdec_pic_info_update = aml_vdec_pic_info_update;
+	aml_vcodec_dec_set_default_params(ctx);
+	ctx->is_stream_off = true;
+
+	ctx->aux_infos.dv_index = 0;
+	ctx->aux_infos.sei_index = 0;
+	ctx->aux_infos.alloc_buffer = aml_alloc_buffer;
+	ctx->aux_infos.free_buffer = aml_free_buffer;
+	ctx->aux_infos.bind_sei_buffer = aml_bind_sei_buffer;
+	ctx->aux_infos.bind_dv_buffer = aml_bind_dv_buffer;
+	ctx->aux_infos.free_one_sei_buffer = aml_free_one_sei_buffer;
+
+	ret = aml_thread_start(ctx, aml_thread_capture_worker, AML_THREAD_CAPTURE, "cap");
+	if (ret) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"Failed to creat capture thread.\n");
+		goto err_creat_thread;
+	}
+
+	list_add(&ctx->list, &dev->ctx_list);
+
+	mutex_unlock(&dev->dev_mutex);
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "%s decoder %lx\n",
+		dev_name(&dev->plat_dev->dev), (ulong)ctx);
+
+	return 0;
+
+	/* Deinit when failure occurred */
+err_creat_thread:
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+err_m2m_ctx_init:
+	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+err_ctrls_setup:
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	vfree(ctx->meta_infos.meta_bufs);
+	kfree(ctx->empty_flush_buf);
+	kfree(ctx);
+	mutex_unlock(&dev->dev_mutex);
+
+	return ret;
+}
+
+static int fops_vcodec_release(struct file *file)
+{
+	struct aml_vcodec_dev *dev = video_drvdata(file);
+	struct aml_vcodec_ctx *ctx = fh_to_ctx(file->private_data);
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "release decoder %lx\n", (ulong) ctx);
+	mutex_lock(&dev->dev_mutex);
+
+	aml_thread_stop(ctx);
+	wait_vcodec_ending(ctx);
+	vb2_queue_release(&ctx->m2m_ctx->cap_q_ctx.q);
+	vb2_queue_release(&ctx->m2m_ctx->out_q_ctx.q);
+
+	aml_vcodec_dec_release(ctx);
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+
+	list_del_init(&ctx->list);
+
+	kfree(ctx->empty_flush_buf);
+	kref_put(&ctx->ctx_ref, aml_v4l_ctx_release);
+	mutex_unlock(&dev->dev_mutex);
+	return 0;
+}
+
+static int v4l2video_file_release(struct inode *inode, struct file *file)
+{
+	v4l_dbg(0, V4L_DEBUG_CODEC_BUFMGR, "file: %lx, data: %lx\n",
+		(ulong) file, (ulong) file->private_data);
+
+	if (file->private_data)
+		vdec_frame_buffer_release(file->private_data);
+
+	return 0;
+}
+
+const struct file_operations v4l2_file_fops = {
+	.release = v4l2video_file_release,
+};
+
+int v4l2_alloc_fd(int *fd)
+{
+	struct file *file = NULL;
+	int file_fd = get_unused_fd_flags(O_CLOEXEC);
+
+	if (file_fd < 0) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"get unused fd fail\n");
+		return -ENODEV;
+	}
+
+	file = anon_inode_getfile("v4l2_meta_file", &v4l2_file_fops, NULL, 0);
+	if (IS_ERR(file)) {
+		put_unused_fd(file_fd);
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"anon_inode_getfile fail\n");
+		return -ENODEV;
+	}
+
+	file->private_data =
+		kzalloc(sizeof(struct file_private_data), GFP_KERNEL);
+	if (!file->private_data) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"alloc priv data faild.\n");
+		return -ENOMEM;
+	}
+
+	v4l_dbg(0, V4L_DEBUG_CODEC_BUFMGR, "fd %d, file %lx, data: %lx\n",
+		file_fd, (ulong) file, (ulong) file->private_data);
+
+	fd_install(file_fd, file);
+	*fd = file_fd;
+
+	return 0;
+}
+
+extern const struct file_operations v4l2_file_fops;
+bool is_v4l2_buf_file(struct file *file)
+{
+	return file->f_op == &v4l2_file_fops;
+}
+
+int v4l2_check_fd(int fd)
+{
+	struct file *file;
+
+	file = fget(fd);
+
+	if (!file) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"fget fd %d fail!\n", fd);
+		return -EBADF;
+	}
+
+	if (!is_v4l2_buf_file(file)) {
+		fput(file);
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"is_v4l2_buf_file fail!\n");
+		return -1;
+	}
+
+	fput(file);
+
+	v4l_dbg(0, V4L_DEBUG_CODEC_EXINFO,
+		"ioctl ok, comm %s, pid %d\n",
+		 current->comm, current->pid);
+
+	return 0;
+}
+
+int dmabuf_fd_install_data(int fd, void* data, u32 size)
+{
+	struct file *file;
+
+	file = fget(fd);
+
+	if (!file) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"fget fd %d fail!, comm %s, pid %d\n",
+			fd, current->comm, current->pid);
+		return -EBADF;
+	}
+
+	if (!is_v4l2_buf_file(file)) {
+		fput(file);
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"the buf file checked fail!\n");
+		return -EBADF;
+	}
+
+	memcpy(file->private_data, data, size);
+
+	fput(file);
+
+	return 0;
+}
+
+void* v4l_get_vf_handle(int fd)
+{
+	struct file *file;
+	struct file_private_data *data = NULL;
+	void *vf_handle = 0;
+
+	file = fget(fd);
+
+	if (!file) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"fget fd %d fail!, comm %s, pid %d\n",
+			fd, current->comm, current->pid);
+		return NULL;
+	}
+
+	if (!is_v4l2_buf_file(file)) {
+		fput(file);
+#if 0
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"the buf file checked fail!\n");
+#endif
+		return NULL;
+	}
+
+	data = (struct file_private_data*) file->private_data;
+	if (data) {
+		vf_handle = &data->vf;
+		v4l_dbg(0, V4L_DEBUG_CODEC_BUFMGR, "file: %lx, data: %lx\n",
+			(ulong) file, (ulong) data);
+	}
+
+	fput(file);
+
+	return vf_handle;
+}
+
+
+static long v4l2_vcodec_ioctl(struct file *file,
+			unsigned int cmd,
+			ulong arg)
+{
+	long ret = 0;
+	void __user *argp = (void __user *)arg;
+
+	switch (cmd) {
+	case V4LVIDEO_IOCTL_ALLOC_FD:
+	{
+		u32 v4lvideo_fd = 0;
+
+		ret = v4l2_alloc_fd(&v4lvideo_fd);
+		if (ret != 0)
+			break;
+		put_user(v4lvideo_fd, (u32 __user *)argp);
+		v4l_dbg(0, V4L_DEBUG_CODEC_EXINFO,
+			"V4LVIDEO_IOCTL_ALLOC_FD fd %d\n",
+			v4lvideo_fd);
+		break;
+	}
+	case V4LVIDEO_IOCTL_CHECK_FD:
+	{
+		u32 v4lvideo_fd = 0;
+
+		get_user(v4lvideo_fd, (u32 __user *)argp);
+		ret = v4l2_check_fd(v4lvideo_fd);
+		if (ret != 0)
+			break;
+		v4l_dbg(0, V4L_DEBUG_CODEC_EXINFO,
+			"V4LVIDEO_IOCTL_CHECK_FD fd %d\n",
+			v4lvideo_fd);
+		break;
+	}
+	case V4LVIDEO_IOCTL_SET_CONFIG_PARAMS:
+	{
+		struct aml_vcodec_ctx *ctx = NULL;
+
+		if (is_v4l2_buf_file(file))
+			break;
+
+		ctx = fh_to_ctx(file->private_data);
+		if (copy_from_user((void *)&ctx->config,
+			(void *)argp, sizeof(ctx->config))) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+				"set config parm err\n");
+			return -EFAULT;
+		}
+		break;
+	}
+	case V4LVIDEO_IOCTL_GET_CONFIG_PARAMS:
+	{
+		struct aml_vcodec_ctx *ctx = NULL;
+
+		if (is_v4l2_buf_file(file))
+			break;
+
+		ctx = fh_to_ctx(file->private_data);
+		if (copy_to_user((void *)argp,
+			(void *)&ctx->config, sizeof(ctx->config))) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+				"get config parm err\n");
+			return -EFAULT;
+		}
+		break;
+	}
+	default:
+		return video_ioctl2(file, cmd, arg);
+	}
+	return ret;
+}
+
+#ifdef CONFIG_COMPAT
+static long v4l2_compat_ioctl(struct file *file,
+	unsigned int cmd, ulong arg)
+{
+	long ret = 0;
+
+	ret = v4l2_vcodec_ioctl(file, cmd, (ulong)compat_ptr(arg));
+	return ret;
+}
+#endif
+
+static const struct v4l2_file_operations aml_vcodec_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fops_vcodec_open,
+	.release	= fops_vcodec_release,
+	.poll		= v4l2_m2m_fop_poll,
+	.unlocked_ioctl = v4l2_vcodec_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl32 = v4l2_compat_ioctl,
+#endif
+	.mmap		= v4l2_m2m_fop_mmap,
+};
+
+static ssize_t status_show(struct class *cls,
+	struct class_attribute *attr, char *buf)
+{
+	struct aml_vcodec_dev *dev = container_of(cls,
+		struct aml_vcodec_dev, v4ldec_class);
+	struct aml_vcodec_ctx *ctx = NULL;
+	char *pbuf = buf;
+
+	mutex_lock(&dev->dev_mutex);
+
+	if (list_empty(&dev->ctx_list)) {
+		pbuf += sprintf(pbuf, "No v4ldec context.\n");
+		goto out;
+	}
+
+	list_for_each_entry(ctx, &dev->ctx_list, list) {
+		/* basic information. */
+		aml_vdec_basic_information(ctx);
+
+		/* buffers status. */
+		aml_buffer_status(ctx);
+	}
+out:
+	mutex_unlock(&dev->dev_mutex);
+
+	return pbuf - buf;
+}
+
+static CLASS_ATTR_RO(status);
+
+static struct attribute *v4ldec_class_attrs[] = {
+	&class_attr_status.attr,
+	NULL
+};
+
+ATTRIBUTE_GROUPS(v4ldec_class);
+
+static int aml_vcodec_probe(struct platform_device *pdev)
+{
+	struct aml_vcodec_dev *dev;
+	struct video_device *vfd_dec;
+	int ret = 0;
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&dev->ctx_list);
+	dev->plat_dev = pdev;
+	atomic_set(&dev->vpp_count, 0);
+
+	mutex_init(&dev->dec_mutex);
+	mutex_init(&dev->dev_mutex);
+	spin_lock_init(&dev->irqlock);
+
+	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
+		"[/AML_V4L2_VDEC]");
+
+	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "v4l2_device_register err=%d\n", ret);
+		goto err_res;
+	}
+
+	init_waitqueue_head(&dev->queue);
+
+	vfd_dec = video_device_alloc();
+	if (!vfd_dec) {
+		dev_err(&pdev->dev, "Failed to allocate video device\n");
+		ret = -ENOMEM;
+		goto err_dec_alloc;
+	}
+
+	vfd_dec->fops		= &aml_vcodec_fops;
+	vfd_dec->ioctl_ops	= &aml_vdec_ioctl_ops;
+	vfd_dec->release	= video_device_release;
+	vfd_dec->lock		= &dev->dev_mutex;
+	vfd_dec->v4l2_dev	= &dev->v4l2_dev;
+	vfd_dec->vfl_dir	= VFL_DIR_M2M;
+	vfd_dec->device_caps	= V4L2_CAP_VIDEO_M2M_MPLANE |
+					V4L2_CAP_STREAMING;
+
+	snprintf(vfd_dec->name, sizeof(vfd_dec->name), "%s",
+		AML_VCODEC_DEC_NAME);
+	video_set_drvdata(vfd_dec, dev);
+	dev->vfd_dec = vfd_dec;
+	platform_set_drvdata(pdev, dev);
+
+	dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops);
+	if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
+		dev_err(&pdev->dev, "Failed to init mem2mem dec device\n");
+		ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
+		goto err_dec_mem_init;
+	}
+
+	dev->decode_workqueue =
+		alloc_ordered_workqueue("output-worker",
+			__WQ_LEGACY | WQ_MEM_RECLAIM | WQ_HIGHPRI);
+	if (!dev->decode_workqueue) {
+		dev_err(&pdev->dev, "Failed to create decode workqueue\n");
+		ret = -EINVAL;
+		goto err_event_workq;
+	}
+
+	//dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);
+
+	ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, 26);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register video device\n");
+		goto err_dec_reg;
+	}
+
+	/*init class*/
+	dev->v4ldec_class.name = "v4ldec";
+	dev->v4ldec_class.owner = THIS_MODULE;
+	dev->v4ldec_class.class_groups = v4ldec_class_groups;
+	ret = class_register(&dev->v4ldec_class);
+	if (ret) {
+		dev_err(&pdev->dev, "v4l dec class create fail.\n");
+		goto err_reg_class;
+	}
+
+	dev_info(&pdev->dev, "v4ldec registered as /dev/video%d\n", vfd_dec->num);
+
+	return 0;
+
+err_reg_class:
+	class_unregister(&dev->v4ldec_class);
+err_dec_reg:
+	destroy_workqueue(dev->decode_workqueue);
+err_event_workq:
+	v4l2_m2m_release(dev->m2m_dev_dec);
+err_dec_mem_init:
+	video_unregister_device(vfd_dec);
+err_dec_alloc:
+	v4l2_device_unregister(&dev->v4l2_dev);
+err_res:
+
+	return ret;
+}
+
+static int aml_vcodec_dec_remove(struct platform_device *pdev)
+{
+	struct aml_vcodec_dev *dev = platform_get_drvdata(pdev);
+
+	flush_workqueue(dev->decode_workqueue);
+	destroy_workqueue(dev->decode_workqueue);
+
+	class_unregister(&dev->v4ldec_class);
+
+	if (dev->m2m_dev_dec)
+		v4l2_m2m_release(dev->m2m_dev_dec);
+
+	if (dev->vfd_dec)
+		video_unregister_device(dev->vfd_dec);
+
+	v4l2_device_unregister(&dev->v4l2_dev);
+
+	dev_info(&pdev->dev, "v4ldec removed.\n");
+
+	return 0;
+}
+
+static const struct of_device_id aml_vcodec_match[] = {
+	{.compatible = "amlogic, vcodec-dec",},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, aml_vcodec_match);
+
+static struct platform_driver aml_vcodec_dec_driver = {
+	.probe	= aml_vcodec_probe,
+	.remove	= aml_vcodec_dec_remove,
+	.driver	= {
+		.name	= AML_VCODEC_DEC_NAME,
+		.of_match_table = aml_vcodec_match,
+	},
+};
+
+static int __init amvdec_ports_init(void)
+{
+	pr_info("v4l dec module init\n");
+
+	if (platform_driver_register(&aml_vcodec_dec_driver)) {
+		pr_err("failed to register v4l dec driver\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit amvdec_ports_exit(void)
+{
+	pr_info("v4l dec module exit\n");
+
+	platform_driver_unregister(&aml_vcodec_dec_driver);
+}
+
+module_init(amvdec_ports_init);
+module_exit(amvdec_ports_exit);
+
+u32 debug_mode;
+EXPORT_SYMBOL(debug_mode);
+module_param(debug_mode, uint, 0644);
+
+u32 mandatory_dw_mmu;
+EXPORT_SYMBOL(mandatory_dw_mmu);
+module_param(mandatory_dw_mmu, uint, 0644);
+
+bool aml_set_vfm_enable;
+EXPORT_SYMBOL(aml_set_vfm_enable);
+module_param(aml_set_vfm_enable, bool, 0644);
+
+int aml_set_vfm_path;
+EXPORT_SYMBOL(aml_set_vfm_path);
+module_param(aml_set_vfm_path, int, 0644);
+
+bool aml_set_vdec_type_enable;
+EXPORT_SYMBOL(aml_set_vdec_type_enable);
+module_param(aml_set_vdec_type_enable, bool, 0644);
+
+int aml_set_vdec_type;
+EXPORT_SYMBOL(aml_set_vdec_type);
+module_param(aml_set_vdec_type, int, 0644);
+
+int vp9_need_prefix;
+EXPORT_SYMBOL(vp9_need_prefix);
+module_param(vp9_need_prefix, int, 0644);
+
+int av1_need_prefix;
+EXPORT_SYMBOL(av1_need_prefix);
+module_param(av1_need_prefix, int, 0644);
+
+bool multiplanar;
+EXPORT_SYMBOL(multiplanar);
+module_param(multiplanar, bool, 0644);
+
+int dump_capture_frame;
+EXPORT_SYMBOL(dump_capture_frame);
+module_param(dump_capture_frame, int, 0644);
+
+int dump_vpp_input;
+EXPORT_SYMBOL(dump_vpp_input);
+module_param(dump_vpp_input, int, 0644);
+
+int dump_ge2d_input;
+EXPORT_SYMBOL(dump_ge2d_input);
+module_param(dump_ge2d_input, int, 0644);
+
+int dump_output_frame;
+EXPORT_SYMBOL(dump_output_frame);
+module_param(dump_output_frame, int, 0644);
+
+u32 dump_output_start_position;
+EXPORT_SYMBOL(dump_output_start_position);
+module_param(dump_output_start_position, uint, 0644);
+
+EXPORT_SYMBOL(param_sets_from_ucode);
+module_param(param_sets_from_ucode, bool, 0644);
+
+EXPORT_SYMBOL(enable_drm_mode);
+module_param(enable_drm_mode, bool, 0644);
+
+int bypass_vpp;
+EXPORT_SYMBOL(bypass_vpp);
+module_param(bypass_vpp, int, 0644);
+
+int bypass_ge2d;
+EXPORT_SYMBOL(bypass_ge2d);
+module_param(bypass_ge2d, int, 0644);
+
+int max_di_instance = 2;
+EXPORT_SYMBOL(max_di_instance);
+module_param(max_di_instance, int, 0644);
+
+int bypass_progressive = 1;
+EXPORT_SYMBOL(bypass_progressive);
+module_param(bypass_progressive, int, 0644);
+
+bool support_mjpeg;
+EXPORT_SYMBOL(support_mjpeg);
+module_param(support_mjpeg, bool, 0644);
+
+bool support_format_I420;
+EXPORT_SYMBOL(support_format_I420);
+module_param(support_format_I420, bool, 0644);
+
+int force_enable_nr;
+EXPORT_SYMBOL(force_enable_nr);
+module_param(force_enable_nr, int, 0644);
+
+int force_enable_di_local_buffer;
+EXPORT_SYMBOL(force_enable_di_local_buffer);
+module_param(force_enable_di_local_buffer, int, 0644);
+
+int vpp_bypass_frames;
+EXPORT_SYMBOL(vpp_bypass_frames);
+module_param(vpp_bypass_frames, int, 0644);
+
+int bypass_nr_flag;
+EXPORT_SYMBOL(bypass_nr_flag);
+module_param(bypass_nr_flag, int, 0644);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("AML video codec V4L2 decoder driver");
+
diff --git a/drivers/amvdec_ports/aml_vcodec_drv.h b/drivers/amvdec_ports/aml_vcodec_drv.h
new file mode 100644
index 0000000..522fe67
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_drv.h
@@ -0,0 +1,788 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#ifndef _AML_VCODEC_DRV_H_
+#define _AML_VCODEC_DRV_H_
+
+#include <linux/kref.h>
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+#include <linux/kfifo.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/video_sink/v4lvideo_ext.h>
+#include "aml_vcodec_util.h"
+#include "aml_vcodec_dec.h"
+
+#define AML_VCODEC_DRV_NAME	"aml_vcodec_drv"
+#define AML_VCODEC_DEC_NAME	"aml-vcodec-dec"
+#define AML_VCODEC_ENC_NAME	"aml-vcodec-enc"
+#define AML_PLATFORM_STR	"platform:amlogic"
+
+#define AML_VCODEC_MAX_PLANES	3
+#define AML_V4L2_BENCHMARK	0
+#define WAIT_INTR_TIMEOUT_MS	1000
+
+/* codec types of get/set parms. */
+#define V4L2_CONFIG_PARM_ENCODE		(0)
+#define V4L2_CONFIG_PARM_DECODE		(1)
+
+/* types of decode parms. */
+#define V4L2_CONFIG_PARM_DECODE_CFGINFO	(1 << 0)
+#define V4L2_CONFIG_PARM_DECODE_PSINFO	(1 << 1)
+#define V4L2_CONFIG_PARM_DECODE_HDRINFO	(1 << 2)
+#define V4L2_CONFIG_PARM_DECODE_CNTINFO	(1 << 3)
+
+/* amlogic event define. */
+/* #define V4L2_EVENT_SRC_CH_RESOLUTION	(1 << 0) */
+#define V4L2_EVENT_SRC_CH_HDRINFO	(1 << 1)
+#define V4L2_EVENT_SRC_CH_PSINFO	(1 << 2)
+#define V4L2_EVENT_SRC_CH_CNTINFO	(1 << 3)
+
+/* exception handing */
+#define V4L2_EVENT_REQUEST_RESET	(1 << 8)
+#define V4L2_EVENT_REQUEST_EXIT		(1 << 9)
+
+/* eos event */
+#define V4L2_EVENT_SEND_EOS		(1 << 16)
+
+/* v4l buffer pool */
+#define V4L_CAP_BUFF_MAX		(32)
+#define V4L_CAP_BUFF_INVALID		(0)
+#define V4L_CAP_BUFF_IN_M2M		(1)
+#define V4L_CAP_BUFF_IN_DEC		(2)
+#define V4L_CAP_BUFF_IN_VPP		(3)
+#define V4L_CAP_BUFF_IN_GE2D		(4)
+
+/* v4l reset mode */
+#define V4L_RESET_MODE_NORMAL		(1 << 0) /* reset vdec_input and decoder. */
+#define V4L_RESET_MODE_LIGHT		(1 << 1) /* just only reset decoder. */
+
+/* m2m job queue's status */
+/* Instance is already queued on the job_queue */
+#define TRANS_QUEUED		(1 << 0)
+/* Instance is currently running in hardware */
+#define TRANS_RUNNING		(1 << 1)
+/* Instance is currently aborting */
+#define TRANS_ABORT		(1 << 2)
+
+#define CTX_BUF_TOTAL(ctx) (ctx->dpb_size + ctx->vpp_size + ctx->ge2d_size)
+/**
+ * enum aml_hw_reg_idx - AML hw register base index
+ */
+enum aml_hw_reg_idx {
+	VDEC_SYS,
+	VDEC_MISC,
+	VDEC_LD,
+	VDEC_TOP,
+	VDEC_CM,
+	VDEC_AD,
+	VDEC_AV,
+	VDEC_PP,
+	VDEC_HWD,
+	VDEC_HWQ,
+	VDEC_HWB,
+	VDEC_HWG,
+	NUM_MAX_VDEC_REG_BASE,
+	/* h264 encoder */
+	VENC_SYS = NUM_MAX_VDEC_REG_BASE,
+	/* vp8 encoder */
+	VENC_LT_SYS,
+	NUM_MAX_VCODEC_REG_BASE
+};
+
+/**
+ * enum aml_instance_type - The type of an AML Vcodec instance.
+ */
+enum aml_instance_type {
+	AML_INST_DECODER		= 0,
+	AML_INST_ENCODER		= 1,
+};
+
+/**
+ * enum aml_instance_state - The state of an AML Vcodec instance.
+ * @AML_STATE_IDLE	- default state when instance is created
+ * @AML_STATE_INIT	- vcodec instance is initialized
+ * @AML_STATE_PROBE	- vdec/venc had sps/pps header parsed/encoded
+ * @AML_STATE_ACTIVE	- vdec is ready for work.
+ * @AML_STATE_FLUSHING	- vdec is flushing. Only used by decoder
+ * @AML_STATE_FLUSHED	- decoder has transacted the last frame.
+ * @AML_STATE_ABORT	- vcodec should be aborted
+ */
+enum aml_instance_state {
+	AML_STATE_IDLE,
+	AML_STATE_INIT,
+	AML_STATE_PROBE,
+	AML_STATE_READY,
+	AML_STATE_ACTIVE,
+	AML_STATE_FLUSHING,
+	AML_STATE_FLUSHED,
+	AML_STATE_ABORT,
+};
+
+/**
+ * struct aml_encode_param - General encoding parameters type
+ */
+enum aml_encode_param {
+	AML_ENCODE_PARAM_NONE = 0,
+	AML_ENCODE_PARAM_BITRATE = (1 << 0),
+	AML_ENCODE_PARAM_FRAMERATE = (1 << 1),
+	AML_ENCODE_PARAM_INTRA_PERIOD = (1 << 2),
+	AML_ENCODE_PARAM_FORCE_INTRA = (1 << 3),
+	AML_ENCODE_PARAM_GOP_SIZE = (1 << 4),
+};
+
+enum aml_fmt_type {
+	AML_FMT_DEC = 0,
+	AML_FMT_ENC = 1,
+	AML_FMT_FRAME = 2,
+};
+
+/**
+ * struct aml_video_fmt - Structure used to store information about pixelformats
+ */
+struct aml_video_fmt {
+	u32			fourcc;
+	enum aml_fmt_type	type;
+	u32			num_planes;
+	const u8		*name;
+};
+
+/**
+ * struct aml_codec_framesizes - Structure used to store information about
+ *							framesizes
+ */
+struct aml_codec_framesizes {
+	u32	fourcc;
+	struct	v4l2_frmsize_stepwise	stepwise;
+};
+
+/**
+ * struct aml_q_type - Type of queue
+ */
+enum aml_q_type {
+	AML_Q_DATA_SRC = 0,
+	AML_Q_DATA_DST = 1,
+};
+
+
+/**
+ * struct aml_q_data - Structure used to store information about queue
+ */
+struct aml_q_data {
+	u32	visible_width;
+	u32	visible_height;
+	u32	coded_width;
+	u32	coded_height;
+	enum v4l2_field	field;
+	u32	bytesperline[AML_VCODEC_MAX_PLANES];
+	u32	sizeimage[AML_VCODEC_MAX_PLANES];
+	struct aml_video_fmt	*fmt;
+	bool resolution_changed;
+};
+
+/**
+ * struct aml_enc_params - General encoding parameters
+ * @bitrate: target bitrate in bits per second
+ * @num_b_frame: number of b frames between p-frame
+ * @rc_frame: frame based rate control
+ * @rc_mb: macroblock based rate control
+ * @seq_hdr_mode: H.264 sequence header is encoded separately or joined
+ *		  with the first frame
+ * @intra_period: I frame period
+ * @gop_size: group of picture size, it's used as the intra frame period
+ * @framerate_num: frame rate numerator. ex: framerate_num=30 and
+ *		   framerate_denom=1 menas FPS is 30
+ * @framerate_denom: frame rate denominator. ex: framerate_num=30 and
+ *		     framerate_denom=1 menas FPS is 30
+ * @h264_max_qp: Max value for H.264 quantization parameter
+ * @h264_profile: V4L2 defined H.264 profile
+ * @h264_level: V4L2 defined H.264 level
+ * @force_intra: force/insert intra frame
+ */
+struct aml_enc_params {
+	u32	bitrate;
+	u32	num_b_frame;
+	u32	rc_frame;
+	u32	rc_mb;
+	u32	seq_hdr_mode;
+	u32	intra_period;
+	u32	gop_size;
+	u32	framerate_num;
+	u32	framerate_denom;
+	u32	h264_max_qp;
+	u32	h264_profile;
+	u32	h264_level;
+	u32	force_intra;
+};
+
+/**
+ * struct vdec_pic_info  - picture size information
+ * @visible_width: picture width
+ * @visible_height: picture height
+ * @coded_width: picture buffer width (64 aligned up from pic_w)
+ * @coded_height: picture buffer heiht (64 aligned up from pic_h)
+ * @y_bs_sz: Y bitstream size
+ * @c_bs_sz: CbCr bitstream size
+ * @y_len_sz: additional size required to store decompress information for y
+ *		plane
+ * @c_len_sz: additional size required to store decompress information for cbcr
+ *		plane
+ * E.g. suppose picture size is 176x144,
+ *      buffer size will be aligned to 176x160.
+ * @profile_idc: source profile level
+ * @field: frame/field information.
+ * @dpb_frames: used for DPB size of calculation.
+ * @dpb_margin: extra buffers for decoder.
+ * @vpp_margin: extra buffers for vpp.
+ */
+struct vdec_pic_info {
+	u32 visible_width;
+	u32 visible_height;
+	u32 coded_width;
+	u32 coded_height;
+	u32 y_bs_sz;
+	u32 c_bs_sz;
+	u32 y_len_sz;
+	u32 c_len_sz;
+	int profile_idc;
+	enum v4l2_field field;
+	u32 dpb_frames;
+	u32 dpb_margin;
+	u32 vpp_margin;
+};
+
+/**
+ * struct vdec_comp_buf_info - compressed buffer info
+ * @max_size: max size needed for MMU Box in MB
+ * @header_size: contineous size for the compressed header
+ * @frame_buffer_size: SG page number to store the frame
+ */
+struct vdec_comp_buf_info {
+	u32 max_size;
+	u32 header_size;
+	u32 frame_buffer_size;
+};
+
+struct aml_vdec_cfg_infos {
+	u32 double_write_mode;
+	u32 init_width;
+	u32 init_height;
+	u32 ref_buf_margin;
+	u32 canvas_mem_mode;
+	u32 canvas_mem_endian;
+	u32 low_latency_mode;
+	u32 uvm_hook_type;
+	/*
+	 * bit 16	: force progressive output flag.
+	 * bit 15	: enable nr.
+	 * bit 14	: enable di local buff.
+	 * bit 13	: report downscale yuv buffer size flag.
+	 * bit 12	: for second field pts mode.
+	 * bit 11	: disable error policy
+	 * bit 1	: Non-standard dv flag.
+	 * bit 0	: dv two layer flag.
+	 */
+	u32 metadata_config_flag; // for metadata config flag
+	u32 duration;
+	u32 data[4];
+};
+
+struct aml_vdec_hdr_infos {
+	/*
+	 * bit 29   : present_flag
+	 * bit 28-26: video_format "component", "PAL", "NTSC", "SECAM", "MAC", "unspecified"
+	 * bit 25   : range "limited", "full_range"
+	 * bit 24   : color_description_present_flag
+	 * bit 23-16: color_primaries "unknown", "bt709", "undef", "bt601",
+	 *            "bt470m", "bt470bg", "smpte170m", "smpte240m", "film", "bt2020"
+	 * bit 15-8 : transfer_characteristic unknown", "bt709", "undef", "bt601",
+	 *            "bt470m", "bt470bg", "smpte170m", "smpte240m",
+	 *            "linear", "log100", "log316", "iec61966-2-4",
+	 *            "bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12",
+	 *            "smpte-st-2084", "smpte-st-428"
+	 * bit 7-0  : matrix_coefficient "GBR", "bt709", "undef", "bt601",
+	 *            "fcc", "bt470bg", "smpte170m", "smpte240m",
+	 *            "YCgCo", "bt2020nc", "bt2020c"
+	 */
+	u32 signal_type;
+	struct vframe_master_display_colour_s color_parms;
+};
+
+struct aml_vdec_ps_infos {
+	u32 visible_width;
+	u32 visible_height;
+	u32 coded_width;
+	u32 coded_height;
+	u32 profile;
+	u32 mb_width;
+	u32 mb_height;
+	u32 dpb_size;
+	u32 ref_frames;
+	u32 dpb_frames;
+	u32 dpb_margin;
+	u32 field;
+	u32 data[3];
+};
+
+struct aml_vdec_cnt_infos {
+	u32 bit_rate;
+	u32 frame_count;
+	u32 error_frame_count;
+	u32 drop_frame_count;
+	u32 total_data;
+};
+
+struct aml_dec_params {
+	u32 parms_status;
+	struct aml_vdec_cfg_infos	cfg;
+	struct aml_vdec_ps_infos	ps;
+	struct aml_vdec_hdr_infos	hdr;
+	struct aml_vdec_cnt_infos	cnt;
+};
+
+struct v4l2_config_parm {
+	u32 type;
+	u32 length;
+	union {
+		struct aml_dec_params dec;
+		struct aml_enc_params enc;
+		u8 data[200];
+	} parm;
+	u8 buf[4096];
+};
+
+struct v4l_buff_pool {
+	/*
+	 * bit 31-16: buffer state
+	 * bit 15- 0: buffer index
+	 */
+	u32 seq[V4L_CAP_BUFF_MAX];
+	u32 in, out;
+	u32 dec, vpp, ge2d;
+};
+
+enum aml_thread_type {
+	AML_THREAD_OUTPUT,
+	AML_THREAD_CAPTURE,
+};
+
+typedef void (*aml_thread_func)(struct aml_vcodec_ctx *ctx);
+
+struct aml_vdec_thread {
+	struct list_head	node;
+	spinlock_t		lock;
+	struct semaphore	sem;
+	struct task_struct	*task;
+	enum aml_thread_type	type;
+	void			*priv;
+	int			stop;
+
+	aml_thread_func		func;
+};
+
+/* struct internal_comp_buf - compressed buffer
+ * @index: index of this buf within (B)MMU BOX
+ * @ref: [0-7]:reference number of this buf
+ *       [8-15]: use for reuse.
+ * @mmu_box: mmu_box of context
+ * @bmmu_box: bmmu_box of context
+ * @box_ref: box_ref of context
+ * @header_addr: header for compressed buffer
+ * @frame_buffer_size: SG buffer page number from
+ * @priv_data use for video composer
+ *  struct vdec_comp_buf_info
+ */
+struct internal_comp_buf {
+	u32		index;
+	u32		ref;
+	void		*mmu_box;
+	void		*bmmu_box;
+	struct kref	*box_ref;
+
+	ulong		header_addr;
+	u32		header_size;
+	u32		frame_buffer_size;
+	struct file_private_data priv_data;
+	ulong	header_dw_addr;
+	void	*mmu_box_dw;
+	void	*bmmu_box_dw;
+};
+
+/*
+ * struct aml_uvm_buff_ref - uvm buff is used reseve ctx ref count.
+ * @index	: index of video buffer.
+ * @addr	: physic address of video buffer.
+ * @ref		: reference of v4ldec context.
+ * @dma		: dma buf of associated with vb.
+ */
+struct aml_uvm_buff_ref {
+	int		index;
+	ulong		addr;
+	struct kref	*ref;
+	struct dma_buf	*dbuf;
+};
+
+/*
+ * enum aml_fb_requester - indicate which module request fb buffers.
+ */
+enum aml_fb_requester {
+	AML_FB_REQ_DEC,
+	AML_FB_REQ_VPP,
+	AML_FB_REQ_GE2D,
+	AML_FB_REQ_MAX
+};
+
+/*
+ * @query: try to achieved fb token.
+ * @alloc: used for allocte fb buffer.
+ */
+struct aml_fb_ops {
+	bool		(*query)(struct aml_fb_ops *, ulong *);
+	int		(*alloc)(struct aml_fb_ops *, ulong, struct vdec_v4l2_buffer **, u32);
+};
+
+/*
+ * struct aml_fb_map_table - record some buffer map infos
+ * @addr	: yuv linear buffer address.
+ * @header_addr	: used for compress buffer.
+ * @vframe	: which is from decoder or vpp vf pool.
+ * @task	: context of task chain.
+ * @icomp	: compress buffer index.
+ */
+struct aml_fb_map_table {
+	ulong		addr;
+	ulong		header_addr;
+	struct vframe_s	*vframe;
+	struct task_chain_s *task;
+	u32		icomp;
+};
+
+/*
+ * struct aux_data - record sei data and dv data
+ * @sei_size:	sei data size.
+ * @sei_buf:	sei data addr.
+ * @sei_state:	sei buffer state. (0 free, 1 not used, 2 used)
+ * @comp_buf:	stores comp data parsed from sei data.
+ * @md_buf:	stores md data parsed from sei data.
+ */
+struct aux_data {
+	int		sei_size;
+	char*		sei_buf;
+	int		sei_state;
+	char*		comp_buf;
+	char*		md_buf;
+};
+
+/*
+ * struct aux_info - record aux data infos
+ * @sei_index:		sei data index.
+ * @dv_index:		dv data index.
+ * @sei_need_free:	sei buffer need to free.
+ * @bufs:		stores aux data.
+ * @alloc_buffer:	alloc aux buffer functions.
+ * @free_buffer:	free aux buffer functions.
+ * @free_one_sei_buffer:free sei buffer with index functions.
+ * @bind_sei_buffer:	bind sei buffer functions.
+ * @bind_dv_buffer:	bind dv buffer functions.
+ */
+struct aux_info {
+	int	sei_index;
+	int 	dv_index;
+	bool    sei_need_free;
+	struct aux_data bufs[V4L_CAP_BUFF_MAX];
+	void 	(*alloc_buffer)(struct aml_vcodec_ctx *ctx, int flag);
+	void 	(*free_buffer)(struct aml_vcodec_ctx *ctx, int flag);
+	void 	(*free_one_sei_buffer)(struct aml_vcodec_ctx *ctx, char **addr, int *size, int idx);
+	void 	(*bind_sei_buffer)(struct aml_vcodec_ctx *ctx, char **addr, int *size, int *idx);
+	void	(*bind_dv_buffer)(struct aml_vcodec_ctx *ctx, char **comp_buf, char **md_buf);
+};
+
+/*
+ * struct meta_data - record meta data.
+ * @buf[META_DATA_SIZE]: meta data information.
+ */
+struct meta_data {
+	char buf[META_DATA_SIZE];
+};
+
+/*
+ * struct meta_info - record some meta data infos
+ * @index: meta data index.
+ * @meta_bufs: record meta data.
+ */
+struct meta_info {
+	int		index;
+	struct meta_data *meta_bufs;
+};
+
+/*
+ * struct aml_vpp_cfg_infos - config vpp init param
+ * @mode	: vpp work mode
+ * @fmt		: picture format used to switch nv21 or nv12.
+ * @buf_size: config buffer size for vpp
+ * @is_drm	: is drm mode
+ * @is_prog	: is a progressive source.
+ * @is_bypass_p	: to set progressive bypass in vpp
+ * @enable_nr	: enable nosie reduce.
+ * @enable_local_buf: DI used buff alloc by itself.
+ * @res_chg	: indicate resolution changed.
+ * @is_vpp_reset: vpp reset just used to res chg.
+ */
+struct aml_vpp_cfg_infos {
+	u32	mode;
+	u32	fmt;
+	u32	buf_size;
+	bool	is_drm;
+	bool	is_prog;
+	bool	is_bypass_p;
+	bool	enable_nr;
+	bool	enable_local_buf;
+	bool	res_chg;
+	bool	is_vpp_reset;
+};
+
+struct aml_ge2d_cfg_infos {
+	u32	mode;
+	u32	buf_size;
+	bool	is_drm;
+};
+
+/*
+ * struct aml_vcodec_ctx - Context (instance) private data.
+ * @id: index of the context that this structure describes.
+ * @ctx_ref: for deferred free of this context.
+ * @type: type of the instance - decoder or encoder.
+ * @dev: pointer to the aml_vcodec_dev of the device.
+ * @m2m_ctx: pointer to the v4l2_m2m_ctx of the context.
+ * @ada_ctx: pointer to the aml_vdec_adapt of the context.
+ * @vpp: pointer to video post processor
+ * @dec_if: hooked decoder driver interface.
+ * @drv_handle: driver handle for specific decode instance
+ * @fh: struct v4l2_fh.
+ * @ctrl_hdl: handler for v4l2 framework.
+ * @slock: protect v4l2 codec context.
+ * @tsplock: protect the vdec thread context.
+ * @empty_flush_buf: a fake size-0 capture buffer that indicates flush.
+ * @list: link to ctx_list of aml_vcodec_dev.
+ * @q_data: store information of input and output queue of the context.
+ * @queue: waitqueue that can be used to wait for this context to finish.
+ * @state_lock: protect the codec status.
+ * @state: state of the context.
+ * @decode_work: decoder work be used to output buffer.
+ * @output_thread_ready: indicate the output thread ready.
+ * @cap_pool: capture buffers are remark in the pool.
+ * @vdec_thread_list: vdec thread be used to capture.
+ * @dpb_size: store dpb count after header parsing
+ * @vpp_size: store vpp buffer count after header parsing
+ * @param_change: indicate encode parameter type
+ * @param_sets_from_ucode: if true indicate ps from ucode.
+ * @v4l_codec_dpb_ready: queue buffer number greater than dpb.
+ # @v4l_resolution_change: indicate resolution change happend.
+ * @comp: comp be used for sync picture information with decoder.
+ * @config: used to set or get parms for application.
+ * @picinfo: store picture info after header parsing.
+ * @last_decoded_picinfo: pic information get from latest decode.
+ * @colorspace: enum v4l2_colorspace; supplemental to pixelformat.
+ * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding.
+ * @quantization: enum v4l2_quantization, colorspace quantization.
+ * @xfer_func: enum v4l2_xfer_func, colorspace transfer function.
+ * @cap_pix_fmt: the picture format used to switch nv21 or nv12.
+ * @has_receive_eos: if receive last frame of capture that be set.
+ * @is_drm_mode: decoding work on drm mode if that set.
+ * @is_stream_mode: vdec input used to stream mode, default frame mode.
+ * @is_stream_off: the value used to handle reset active.
+ * @is_out_stream_off: streamoff called for output port.
+ * @receive_cmd_stop: if receive the cmd flush decoder.
+ * @reset_flag: reset mode includes lightly and normal mode.
+ * @decoded_frame_cnt: the capture buffer deque number to be count.
+ * @buf_used_count: means that decode allocate how many buffs from v4l.
+ * @wq: wait recycle dma buffer finish.
+ * @cap_wq: the wq used for wait capture buffer.
+ * @dmabuff_recycle_lock: protect the lock dmabuff free.
+ * @dmabuff_recycle_work: used for recycle dmabuff.
+ * @dmabuff_recycle: kfifo used for store vb buff.
+ * @capture_buffer: kfifo used for store capture vb buff.
+ * @mmu_box: mmu_box of context.
+ * @bmmu_box: bmmu_box of context.
+ * @box_ref: box_ref of context.
+ * @comp_info: compress buffer information.
+ * @comp_bufs: compress buffer describe.
+ * @comp_lock: used for lock ibuf free cb.
+ * @fb_ops: frame buffer ops interface.
+ * @dv_infos: dv data information.
+ * @vpp_cfg: vpp init parms of configuration.
+ * @vdec_pic_info_update: update pic info cb.
+ * @vpp_is_need: the instance is need vpp.
+ * @task_chain_pool: used to store task chain inst.
+ * @index_disp: the number of frames output.
+ */
+struct aml_vcodec_ctx {
+	int				id;
+	struct kref			ctx_ref;
+	enum aml_instance_type		type;
+	struct aml_vcodec_dev		*dev;
+	struct v4l2_m2m_ctx		*m2m_ctx;
+	struct aml_vdec_adapt		*ada_ctx;
+	struct aml_v4l2_vpp		*vpp;
+	const struct vdec_common_if	*dec_if;
+	ulong				drv_handle;
+	struct v4l2_fh			fh;
+	struct v4l2_ctrl_handler	ctrl_hdl;
+	spinlock_t			slock;
+	spinlock_t			tsplock;
+	struct aml_video_dec_buf	*empty_flush_buf;
+	struct list_head		list;
+
+	struct aml_q_data		q_data[2];
+	wait_queue_head_t		queue;
+	struct mutex			state_lock;
+	enum aml_instance_state		state;
+	struct work_struct		decode_work;
+	bool				output_thread_ready;
+	struct v4l_buff_pool		cap_pool;
+	struct list_head		vdec_thread_list;
+
+	int				dpb_size;
+	int				vpp_size;
+	int				ge2d_size;
+	bool				param_sets_from_ucode;
+	bool				v4l_codec_dpb_ready;
+	bool				v4l_resolution_change;
+	struct completion		comp;
+	struct v4l2_config_parm		config;
+	struct vdec_pic_info		picinfo;
+	struct vdec_pic_info		last_decoded_picinfo;
+	enum v4l2_colorspace		colorspace;
+	enum v4l2_ycbcr_encoding	ycbcr_enc;
+	enum v4l2_quantization		quantization;
+	enum v4l2_xfer_func		xfer_func;
+	u32				cap_pix_fmt;
+	u32				output_pix_fmt;
+
+	bool				has_receive_eos;
+	bool				is_drm_mode;
+	bool				output_dma_mode;
+	bool				is_stream_off;
+	bool				is_out_stream_off;
+	bool				receive_cmd_stop;
+	int				reset_flag;
+	int				decoded_frame_cnt;
+	int				buf_used_count;
+	wait_queue_head_t		wq, cap_wq, post_done_wq;
+	struct mutex			capture_buffer_lock;
+	spinlock_t			dmabuff_recycle_lock;
+	struct mutex			buff_done_lock;
+	struct work_struct		dmabuff_recycle_work;
+	DECLARE_KFIFO(dmabuff_recycle, struct vb2_v4l2_buffer *, 32);
+	DECLARE_KFIFO(capture_buffer, struct vb2_v4l2_buffer *, 32);
+
+	/* compressed buffer support */
+	void				*bmmu_box;
+	void				*mmu_box;
+	struct kref			box_ref;
+	struct vdec_comp_buf_info	comp_info;
+	struct internal_comp_buf	*comp_bufs;
+	struct uvm_hook_mod_info	*uvm_proxy;
+	struct mutex			comp_lock;
+
+	struct aml_fb_ops		fb_ops;
+	ulong				token_table[32];
+
+	struct aml_fb_map_table		fb_map[32];
+	struct aml_vpp_cfg_infos 	vpp_cfg;
+	void (*vdec_pic_info_update)(struct aml_vcodec_ctx *ctx);
+	bool				vpp_is_need;
+	struct list_head		task_chain_pool;
+	struct meta_info		meta_infos;
+	struct vdec_sync		*sync;
+	u32             		internal_dw_scale;
+
+	/* ge2d field. */
+	struct aml_v4l2_ge2d		*ge2d;
+	struct aml_ge2d_cfg_infos 	ge2d_cfg;
+	bool				ge2d_is_need;
+
+	bool 				second_field_pts_mode;
+	struct aux_info			aux_infos;
+	u32				index_disp;
+	bool				post_to_upper_done;
+	bool			film_grain_present;
+	void			*bmmu_box_dw;
+	void			*mmu_box_dw;
+};
+
+/**
+ * struct aml_vcodec_dev - driver data.
+ * @v4l2_dev		: V4L2 device to register video devices for.
+ * @vfd_dec		: Video device for decoder.
+ * @plat_dev		: platform device.
+ * @m2m_dev_dec		: m2m device for decoder.
+ * @curr_ctx		: The context that is waiting for codec hardware.
+ * @id_counter		: used to identify current opened instance.
+ * @dec_capability	: used to identify decode capability, ex: 4k
+ * @decode_workqueue	: the worker used to output buffer schedule.
+ * @ctx_list		: list of struct aml_vcodec_ctx.
+ * @irqlock		: protect data access by irq handler and work thread.
+ * @dev_mutex		: video_device lock.
+ * @dec_mutex		: decoder hardware lock.
+ * @queue		: waitqueue for waiting for completion of device commands.
+ * @vpp_count		: count the number of open vpp.
+ * @v4ldec_class	: creat class sysfs uesd to show some information.
+ */
+struct aml_vcodec_dev {
+	struct v4l2_device		v4l2_dev;
+	struct video_device		*vfd_dec;
+	struct platform_device		*plat_dev;
+	struct v4l2_m2m_dev		*m2m_dev_dec;
+	struct aml_vcodec_ctx		*curr_ctx;
+	ulong				id_counter;
+	u32				dec_capability;
+	struct workqueue_struct		*decode_workqueue;
+	struct list_head		ctx_list;
+	struct file			*filp;
+	spinlock_t			irqlock;
+	struct mutex			dev_mutex;
+	struct mutex			dec_mutex;
+	wait_queue_head_t		queue;
+	atomic_t			vpp_count;
+	struct class			v4ldec_class;
+};
+
+static inline struct aml_vcodec_ctx *fh_to_ctx(struct v4l2_fh *fh)
+{
+	return container_of(fh, struct aml_vcodec_ctx, fh);
+}
+
+static inline struct aml_vcodec_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl)
+{
+	return container_of(ctrl->handler, struct aml_vcodec_ctx, ctrl_hdl);
+}
+
+void aml_thread_capture_worker(struct aml_vcodec_ctx *ctx);
+void aml_thread_post_task(struct aml_vcodec_ctx *ctx, enum aml_thread_type type);
+int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func,
+	enum aml_thread_type type, const char *thread_name);
+void aml_thread_stop(struct aml_vcodec_ctx *ctx);
+
+#endif /* _AML_VCODEC_DRV_H_ */
diff --git a/drivers/amvdec_ports/aml_vcodec_ge2d.c b/drivers/amvdec_ports/aml_vcodec_ge2d.c
new file mode 100644
index 0000000..2d331ed
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_ge2d.c
@@ -0,0 +1,968 @@
+/*
+* Copyright (C) 2020 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <linux/sched/clock.h>
+#include <uapi/linux/sched/types.h>
+#include <linux/amlogic/meson_uvm_core.h>
+#include <linux/amlogic/media/ge2d/ge2d.h>
+#include <linux/amlogic/media/canvas/canvas_mgr.h>
+
+#include "../common/chips/decoder_cpu_ver_info.h"
+#include "aml_vcodec_ge2d.h"
+#include "aml_vcodec_adapt.h"
+#include "vdec_drv_if.h"
+
+#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2
+#include <trace/events/meson_atrace.h>
+
+#define GE2D_BUF_GET_IDX(ge2d_buf) (ge2d_buf->aml_buf->vb.vb2_buf.index)
+#define INPUT_PORT 0
+#define OUTPUT_PORT 1
+
+extern int dump_ge2d_input;
+extern int ge2d_bypass_frames;
+
+enum GE2D_FLAG {
+	GE2D_FLAG_P		= 0x1,
+	GE2D_FLAG_I		= 0x2,
+	GE2D_FLAG_EOS		= 0x4,
+	GE2D_FLAG_BUF_BY_PASS	= 0x8,
+	GE2D_FLAG_MAX		= 0x7FFFFFFF,
+};
+
+enum videocom_source_type {
+	DECODER_8BIT_NORMAL = 0,
+	DECODER_8BIT_BOTTOM,
+	DECODER_8BIT_TOP,
+	DECODER_10BIT_NORMAL,
+	DECODER_10BIT_BOTTOM,
+	DECODER_10BIT_TOP
+};
+
+#ifndef  CONFIG_AMLOGIC_MEDIA_GE2D
+inline void stretchblt_noalpha(struct ge2d_context_s *wq,
+		int src_x, int src_y, int src_w, int src_h,
+		int dst_x, int dst_y, int dst_w, int dst_h) { return; }
+inline int ge2d_context_config_ex(struct ge2d_context_s *context,
+		struct config_para_ex_s *ge2d_config) { return -1; }
+inline struct ge2d_context_s *create_ge2d_work_queue(void) { return NULL; }
+inline int destroy_ge2d_work_queue(struct ge2d_context_s *ge2d_work_queue) { return -1; }
+#endif
+
+static int get_source_type(struct vframe_s *vf)
+{
+	enum videocom_source_type ret;
+	int interlace_mode;
+
+	interlace_mode = vf->type & VIDTYPE_TYPEMASK;
+
+	if ((vf->bitdepth & BITDEPTH_Y10)  &&
+		(!(vf->type & VIDTYPE_COMPRESS)) &&
+		(get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL)) {
+		if (interlace_mode == VIDTYPE_INTERLACE_TOP)
+			ret = DECODER_10BIT_TOP;
+		else if (interlace_mode == VIDTYPE_INTERLACE_BOTTOM)
+			ret = DECODER_10BIT_BOTTOM;
+		else
+			ret = DECODER_10BIT_NORMAL;
+	} else {
+		if (interlace_mode == VIDTYPE_INTERLACE_TOP)
+			ret = DECODER_8BIT_TOP;
+		else if (interlace_mode == VIDTYPE_INTERLACE_BOTTOM)
+			ret = DECODER_8BIT_BOTTOM;
+		else
+			ret = DECODER_8BIT_NORMAL;
+	}
+
+	return ret;
+}
+
+static int get_input_format(struct vframe_s *vf)
+{
+	int format = GE2D_FORMAT_M24_YUV420;
+	enum videocom_source_type soure_type;
+
+	soure_type = get_source_type(vf);
+
+	switch (soure_type) {
+	case DECODER_8BIT_NORMAL:
+		if (vf->type & VIDTYPE_VIU_422)
+			format = GE2D_FORMAT_S16_YUV422;
+		else if (vf->type & VIDTYPE_VIU_NV21)
+			format = GE2D_FORMAT_M24_NV21;
+		else if (vf->type & VIDTYPE_VIU_NV12)
+			format = GE2D_FORMAT_M24_NV12;
+		else if (vf->type & VIDTYPE_VIU_444)
+			format = GE2D_FORMAT_S24_YUV444;
+		else
+			format = GE2D_FORMAT_M24_YUV420;
+		break;
+	case DECODER_8BIT_BOTTOM:
+		if (vf->type & VIDTYPE_VIU_422)
+			format = GE2D_FORMAT_S16_YUV422
+				| (GE2D_FORMAT_S16_YUV422B & (3 << 3));
+		else if (vf->type & VIDTYPE_VIU_NV21)
+			format = GE2D_FORMAT_M24_NV21
+				| (GE2D_FORMAT_M24_NV21B & (3 << 3));
+		else if (vf->type & VIDTYPE_VIU_NV12)
+			format = GE2D_FORMAT_M24_NV12
+				| (GE2D_FORMAT_M24_NV12B & (3 << 3));
+		else if (vf->type & VIDTYPE_VIU_444)
+			format = GE2D_FORMAT_S24_YUV444
+				| (GE2D_FORMAT_S24_YUV444B & (3 << 3));
+		else
+			format = GE2D_FORMAT_M24_YUV420
+				| (GE2D_FMT_M24_YUV420B & (3 << 3));
+		break;
+	case DECODER_8BIT_TOP:
+		if (vf->type & VIDTYPE_VIU_422)
+			format = GE2D_FORMAT_S16_YUV422
+				| (GE2D_FORMAT_S16_YUV422T & (3 << 3));
+		else if (vf->type & VIDTYPE_VIU_NV21)
+			format = GE2D_FORMAT_M24_NV21
+				| (GE2D_FORMAT_M24_NV21T & (3 << 3));
+		else if (vf->type & VIDTYPE_VIU_NV12)
+			format = GE2D_FORMAT_M24_NV12
+				| (GE2D_FORMAT_M24_NV12T & (3 << 3));
+		else if (vf->type & VIDTYPE_VIU_444)
+			format = GE2D_FORMAT_S24_YUV444
+				| (GE2D_FORMAT_S24_YUV444T & (3 << 3));
+		else
+			format = GE2D_FORMAT_M24_YUV420
+				| (GE2D_FMT_M24_YUV420T & (3 << 3));
+		break;
+	case DECODER_10BIT_NORMAL:
+		if (vf->type & VIDTYPE_VIU_422) {
+			if (vf->bitdepth & FULL_PACK_422_MODE)
+				format = GE2D_FORMAT_S16_10BIT_YUV422;
+			else
+				format = GE2D_FORMAT_S16_12BIT_YUV422;
+		}
+		break;
+	case DECODER_10BIT_BOTTOM:
+		if (vf->type & VIDTYPE_VIU_422) {
+			if (vf->bitdepth & FULL_PACK_422_MODE)
+				format = GE2D_FORMAT_S16_10BIT_YUV422
+					| (GE2D_FORMAT_S16_10BIT_YUV422B
+					& (3 << 3));
+			else
+				format = GE2D_FORMAT_S16_12BIT_YUV422
+					| (GE2D_FORMAT_S16_12BIT_YUV422B
+					& (3 << 3));
+		}
+		break;
+	case DECODER_10BIT_TOP:
+		if (vf->type & VIDTYPE_VIU_422) {
+			if (vf->bitdepth & FULL_PACK_422_MODE)
+				format = GE2D_FORMAT_S16_10BIT_YUV422
+					| (GE2D_FORMAT_S16_10BIT_YUV422T
+					& (3 << 3));
+			else
+				format = GE2D_FORMAT_S16_12BIT_YUV422
+					| (GE2D_FORMAT_S16_12BIT_YUV422T
+					& (3 << 3));
+		}
+		break;
+	default:
+		format = GE2D_FORMAT_M24_YUV420;
+	}
+	return format;
+}
+
+static int v4l_ge2d_empty_input_done(struct aml_v4l2_ge2d_buf *buf)
+{
+	struct aml_v4l2_ge2d *ge2d = buf->caller_data;
+	struct vdec_v4l2_buffer *fb = NULL;
+	bool eos = false;
+
+	if (!ge2d || !ge2d->ctx) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"fatal %s %d ge2d:%px\n",
+			__func__, __LINE__, ge2d);
+		return -1;
+	}
+
+	fb 	= &buf->aml_buf->frame_buffer;
+	eos	= (buf->flag & GE2D_FLAG_EOS);
+
+	v4l_dbg(ge2d->ctx, V4L_DEBUG_GE2D_BUFMGR,
+		"ge2d_input done: vf:%px, idx: %d, flag(vf:%x ge2d:%x) %s, ts:%lld, "
+		"in:%d, out:%d, vf:%d, in done:%d, out done:%d\n",
+		buf->vf,
+		buf->vf->index,
+		buf->vf->flag,
+		buf->flag,
+		eos ? "eos" : "",
+		buf->vf->timestamp,
+		kfifo_len(&ge2d->input),
+		kfifo_len(&ge2d->output),
+		kfifo_len(&ge2d->frame),
+		kfifo_len(&ge2d->in_done_q),
+		kfifo_len(&ge2d->out_done_q));
+
+	fb->task->recycle(fb->task, TASK_TYPE_GE2D);
+
+	kfifo_put(&ge2d->input, buf);
+
+	ATRACE_COUNTER("VC_IN_GE2D-1.recycle", fb->buf_idx);
+
+	return 0;
+}
+
+static int v4l_ge2d_fill_output_done(struct aml_v4l2_ge2d_buf *buf)
+{
+	struct aml_v4l2_ge2d *ge2d = buf->caller_data;
+	struct vdec_v4l2_buffer *fb = NULL;
+	bool bypass = false;
+	bool eos = false;
+
+	if (!ge2d || !ge2d->ctx) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"fatal %s %d ge2d:%px\n",
+			__func__, __LINE__, ge2d);
+		return -1;
+	}
+
+	fb	= &buf->aml_buf->frame_buffer;
+	eos	= (buf->flag & GE2D_FLAG_EOS);
+	bypass	= (buf->flag & GE2D_FLAG_BUF_BY_PASS);
+
+	/* recovery fb handle. */
+	buf->vf->v4l_mem_handle = (ulong)fb;
+
+	kfifo_put(&ge2d->out_done_q, buf);
+
+	v4l_dbg(ge2d->ctx, V4L_DEBUG_GE2D_BUFMGR,
+		"ge2d_output done: vf:%px, idx:%d, flag(vf:%x ge2d:%x) %s, ts:%lld, "
+		"in:%d, out:%d, vf:%d, in done:%d, out done:%d, wxh:%ux%u\n",
+		buf->vf,
+		buf->vf->index,
+		buf->vf->flag,
+		buf->flag,
+		eos ? "eos" : "",
+		buf->vf->timestamp,
+		kfifo_len(&ge2d->input),
+		kfifo_len(&ge2d->output),
+		kfifo_len(&ge2d->frame),
+		kfifo_len(&ge2d->in_done_q),
+		kfifo_len(&ge2d->out_done_q),
+		buf->vf->width, buf->vf->height);
+
+	ATRACE_COUNTER("VC_OUT_GE2D-2.submit", fb->buf_idx);
+
+	fb->task->submit(fb->task, TASK_TYPE_GE2D);
+
+	ge2d->out_num[OUTPUT_PORT]++;
+
+	return 0;
+}
+
+static void ge2d_vf_get(void *caller, struct vframe_s **vf_out)
+{
+	struct aml_v4l2_ge2d *ge2d = (struct aml_v4l2_ge2d *)caller;
+	struct aml_v4l2_ge2d_buf *buf = NULL;
+	struct vdec_v4l2_buffer *fb = NULL;
+	struct vframe_s *vf = NULL;
+	bool bypass = false;
+	bool eos = false;
+
+	if (!ge2d || !ge2d->ctx) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"fatal %s %d ge2d:%px\n",
+			__func__, __LINE__, ge2d);
+		return;
+	}
+
+	if (kfifo_get(&ge2d->out_done_q, &buf)) {
+		fb	= &buf->aml_buf->frame_buffer;
+		eos	= (buf->flag & GE2D_FLAG_EOS);
+		bypass	= (buf->flag & GE2D_FLAG_BUF_BY_PASS);
+		vf	= buf->vf;
+
+		if (eos) {
+			v4l_dbg(ge2d->ctx, V4L_DEBUG_GE2D_DETAIL,
+				"%s %d got eos\n",
+				__func__, __LINE__);
+			vf->type |= VIDTYPE_V4L_EOS;
+			vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+		}
+
+		*vf_out = vf;
+
+		ATRACE_COUNTER("VC_OUT_GE2D-3.vf_get", fb->buf_idx);
+
+		v4l_dbg(ge2d->ctx, V4L_DEBUG_GE2D_BUFMGR,
+			"%s: vf:%px, index:%d, flag(vf:%x ge2d:%x), ts:%lld, type:%x, wxh:%ux%u\n",
+			__func__, vf,
+			vf->index,
+			vf->flag,
+			buf->flag,
+			vf->timestamp, vf->type, vf->width, vf->height);
+	}
+}
+
+static void ge2d_vf_put(void *caller, struct vframe_s *vf)
+{
+	struct aml_v4l2_ge2d *ge2d = (struct aml_v4l2_ge2d *)caller;
+	struct vdec_v4l2_buffer *fb = NULL;
+	struct aml_video_dec_buf *aml_buf = NULL;
+	struct aml_v4l2_ge2d_buf *buf = NULL;
+	bool bypass = false;
+	bool eos = false;
+
+	fb	= (struct vdec_v4l2_buffer *) vf->v4l_mem_handle;
+	aml_buf	= container_of(fb, struct aml_video_dec_buf, frame_buffer);
+	buf	= (struct aml_v4l2_ge2d_buf *) aml_buf->ge2d_buf_handle;
+	eos	= (buf->flag & GE2D_FLAG_EOS);
+	bypass	= (buf->flag & GE2D_FLAG_BUF_BY_PASS);
+
+	v4l_dbg(ge2d->ctx, V4L_DEBUG_GE2D_BUFMGR,
+		"%s: vf:%px, index:%d, flag(vf:%x ge2d:%x), ts:%lld\n",
+		__func__, vf,
+		vf->index,
+		vf->flag,
+		buf->flag,
+		vf->timestamp);
+
+	ATRACE_COUNTER("VC_IN_GE2D-0.vf_put", fb->buf_idx);
+
+	mutex_lock(&ge2d->output_lock);
+	kfifo_put(&ge2d->frame, vf);
+	kfifo_put(&ge2d->output, buf);
+	mutex_unlock(&ge2d->output_lock);
+	up(&ge2d->sem_out);
+}
+
+static int aml_v4l2_ge2d_thread(void* param)
+{
+	struct aml_v4l2_ge2d* ge2d = param;
+	struct aml_vcodec_ctx *ctx = ge2d->ctx;
+	struct config_para_ex_s ge2d_config;
+	u32 src_fmt = 0, dst_fmt = 0;
+	struct canvas_s cd;
+	ulong start_time;
+
+	v4l_dbg(ctx, V4L_DEBUG_GE2D_DETAIL, "enter ge2d thread\n");
+	while (ge2d->running) {
+		struct aml_v4l2_ge2d_buf *in_buf;
+		struct aml_v4l2_ge2d_buf *out_buf = NULL;
+		struct vframe_s *vf_out = NULL;
+		struct vdec_v4l2_buffer *fb;
+
+		if (down_interruptible(&ge2d->sem_in))
+			goto exit;
+retry:
+		if (!ge2d->running)
+			break;
+
+		if (kfifo_is_empty(&ge2d->output)) {
+			if (down_interruptible(&ge2d->sem_out))
+				goto exit;
+			goto retry;
+		}
+
+		mutex_lock(&ge2d->output_lock);
+		if (!kfifo_get(&ge2d->output, &out_buf)) {
+			mutex_unlock(&ge2d->output_lock);
+			v4l_dbg(ctx, 0, "ge2d can not get output\n");
+			goto exit;
+		}
+		mutex_unlock(&ge2d->output_lock);
+
+		/* bind v4l2 buffers */
+		if (!out_buf->aml_buf) {
+			struct vdec_v4l2_buffer *out;
+
+			if (!ctx->fb_ops.query(&ctx->fb_ops, &ge2d->fb_token)) {
+				usleep_range(500, 550);
+				mutex_lock(&ge2d->output_lock);
+				kfifo_put(&ge2d->output, out_buf);
+				mutex_unlock(&ge2d->output_lock);
+				goto retry;
+			}
+
+			if (ctx->fb_ops.alloc(&ctx->fb_ops, ge2d->fb_token, &out, AML_FB_REQ_GE2D)) {
+				usleep_range(5000, 5500);
+				mutex_lock(&ge2d->output_lock);
+				kfifo_put(&ge2d->output, out_buf);
+				mutex_unlock(&ge2d->output_lock);
+				goto retry;
+			}
+
+			out_buf->aml_buf = container_of(out,
+				struct aml_video_dec_buf, frame_buffer);
+			out_buf->aml_buf->ge2d_buf_handle = (ulong) out_buf;
+			v4l_dbg(ctx, V4L_DEBUG_GE2D_BUFMGR,
+				"ge2d bind buf:%d to ge2d_buf:%px\n",
+				GE2D_BUF_GET_IDX(out_buf), out_buf);
+
+			out->m.mem[0].bytes_used = out->m.mem[0].size;
+			out->m.mem[1].bytes_used = out->m.mem[1].size;
+		}
+
+		/* safe to pop in_buf */
+		if (!kfifo_get(&ge2d->in_done_q, &in_buf)) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"ge2d can not get input\n");
+			goto exit;
+		}
+
+		mutex_lock(&ge2d->output_lock);
+		if (!kfifo_get(&ge2d->frame, &vf_out)) {
+			mutex_unlock(&ge2d->output_lock);
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"ge2d can not get frame\n");
+			goto exit;
+		}
+		mutex_unlock(&ge2d->output_lock);
+
+		fb = &out_buf->aml_buf->frame_buffer;
+		fb->status = FB_ST_GE2D;
+
+		/* fill output vframe information. */
+		memcpy(vf_out, in_buf->vf, sizeof(*vf_out));
+		memcpy(vf_out->canvas0_config,
+			in_buf->vf->canvas0_config,
+			2 * sizeof(struct canvas_config_s));
+
+		vf_out->canvas0_config[0].phy_addr = fb->m.mem[0].addr;
+		if (fb->num_planes == 1) {
+			vf_out->canvas0_config[1].phy_addr =
+				fb->m.mem[0].addr + fb->m.mem[0].offset;
+			vf_out->canvas0_config[2].phy_addr =
+				fb->m.mem[0].addr + fb->m.mem[0].offset
+				+ (fb->m.mem[0].offset >> 2);
+		} else {
+			vf_out->canvas0_config[1].phy_addr =
+				fb->m.mem[1].addr;
+			vf_out->canvas0_config[2].phy_addr =
+				fb->m.mem[2].addr;
+		}
+
+		/* fill outbuf parms. */
+		out_buf->vf		= vf_out;
+		out_buf->flag		= 0;
+		out_buf->caller_data	= ge2d;
+
+		/* fill inbuf parms. */
+		in_buf->caller_data	= ge2d;
+
+		memset(&ge2d_config, 0, sizeof(ge2d_config));
+
+		src_fmt = get_input_format(in_buf->vf);
+		if (in_buf->vf->canvas0_config[0].endian == 7)
+			src_fmt |= GE2D_BIG_ENDIAN;
+		else
+			src_fmt |= GE2D_LITTLE_ENDIAN;
+
+		/* negotiate format of destination */
+		dst_fmt = get_input_format(in_buf->vf);
+		if (ge2d->work_mode & GE2D_MODE_CONVERT_NV12)
+			dst_fmt |= GE2D_FORMAT_M24_NV12;
+		else if (ge2d->work_mode & GE2D_MODE_CONVERT_NV21)
+			dst_fmt |= GE2D_FORMAT_M24_NV21;
+
+		if (ge2d->work_mode & GE2D_MODE_CONVERT_LE)
+			dst_fmt |= GE2D_LITTLE_ENDIAN;
+		else
+			dst_fmt |= GE2D_BIG_ENDIAN;
+
+		if ((dst_fmt & GE2D_COLOR_MAP_MASK) == GE2D_COLOR_MAP_NV12) {
+			vf_out->type |= VIDTYPE_VIU_NV12;
+			vf_out->type &= ~VIDTYPE_VIU_NV21;
+		} else if ((dst_fmt & GE2D_COLOR_MAP_MASK) == GE2D_COLOR_MAP_NV21) {
+			vf_out->type |= VIDTYPE_VIU_NV21;
+			vf_out->type &= ~VIDTYPE_VIU_NV12;
+		}
+		if ((dst_fmt & GE2D_ENDIAN_MASK) == GE2D_LITTLE_ENDIAN) {
+			vf_out->canvas0_config[0].endian = 0;
+			vf_out->canvas0_config[1].endian = 0;
+			vf_out->canvas0_config[2].endian = 0;
+		} else if ((dst_fmt & GE2D_ENDIAN_MASK) == GE2D_BIG_ENDIAN){
+			vf_out->canvas0_config[0].endian = 7;
+			vf_out->canvas0_config[1].endian = 7;
+			vf_out->canvas0_config[2].endian = 7;
+		}
+
+		start_time = local_clock();
+		/* src canvas configure. */
+		if ((in_buf->vf->canvas0Addr == 0) ||
+			(in_buf->vf->canvas0Addr == (u32)-1)) {
+			canvas_config_config(ge2d->src_canvas_id[0], &in_buf->vf->canvas0_config[0]);
+			canvas_config_config(ge2d->src_canvas_id[1], &in_buf->vf->canvas0_config[1]);
+			canvas_config_config(ge2d->src_canvas_id[2], &in_buf->vf->canvas0_config[2]);
+			ge2d_config.src_para.canvas_index =
+				ge2d->src_canvas_id[0] |
+				ge2d->src_canvas_id[1] << 8 |
+				ge2d->src_canvas_id[2] << 16;
+
+			ge2d_config.src_planes[0].addr =
+				in_buf->vf->canvas0_config[0].phy_addr;
+			ge2d_config.src_planes[0].w =
+				in_buf->vf->canvas0_config[0].width;
+			ge2d_config.src_planes[0].h =
+				in_buf->vf->canvas0_config[0].height;
+			ge2d_config.src_planes[1].addr =
+				in_buf->vf->canvas0_config[1].phy_addr;
+			ge2d_config.src_planes[1].w =
+				in_buf->vf->canvas0_config[1].width;
+			ge2d_config.src_planes[1].h =
+				in_buf->vf->canvas0_config[1].height;
+			ge2d_config.src_planes[2].addr =
+				in_buf->vf->canvas0_config[2].phy_addr;
+			ge2d_config.src_planes[2].w =
+				in_buf->vf->canvas0_config[2].width;
+			ge2d_config.src_planes[2].h =
+				in_buf->vf->canvas0_config[2].height;
+		} else {
+			ge2d_config.src_para.canvas_index = in_buf->vf->canvas0Addr;
+		}
+		ge2d_config.src_para.mem_type	= CANVAS_TYPE_INVALID;
+		ge2d_config.src_para.format	= src_fmt;
+		ge2d_config.src_para.fill_color_en = 0;
+		ge2d_config.src_para.fill_mode	= 0;
+		ge2d_config.src_para.x_rev	= 0;
+		ge2d_config.src_para.y_rev	= 0;
+		ge2d_config.src_para.color	= 0xffffffff;
+		ge2d_config.src_para.top	= 0;
+		ge2d_config.src_para.left	= 0;
+		ge2d_config.src_para.width	= in_buf->vf->width;
+		if (in_buf->vf->type & VIDTYPE_INTERLACE)
+			ge2d_config.src_para.height = in_buf->vf->height >> 1;
+		else
+			ge2d_config.src_para.height = in_buf->vf->height;
+
+		/* dst canvas configure. */
+		canvas_config_config(ge2d->dst_canvas_id[0], &vf_out->canvas0_config[0]);
+		if ((ge2d_config.src_para.format & 0xfffff) == GE2D_FORMAT_M24_YUV420) {
+			vf_out->canvas0_config[1].width <<= 1;
+		}
+		canvas_config_config(ge2d->dst_canvas_id[1], &vf_out->canvas0_config[1]);
+		canvas_config_config(ge2d->dst_canvas_id[2], &vf_out->canvas0_config[2]);
+		ge2d_config.dst_para.canvas_index =
+			ge2d->dst_canvas_id[0] |
+			ge2d->dst_canvas_id[1] << 8;
+		canvas_read(ge2d->dst_canvas_id[0], &cd);
+		ge2d_config.dst_planes[0].addr	= cd.addr;
+		ge2d_config.dst_planes[0].w	= cd.width;
+		ge2d_config.dst_planes[0].h	= cd.height;
+		canvas_read(ge2d->dst_canvas_id[1], &cd);
+		ge2d_config.dst_planes[1].addr	= cd.addr;
+		ge2d_config.dst_planes[1].w	= cd.width;
+		ge2d_config.dst_planes[1].h	= cd.height;
+
+		ge2d_config.dst_para.format	=  dst_fmt;
+		ge2d_config.dst_para.width	= in_buf->vf->width;
+		ge2d_config.dst_para.height	= in_buf->vf->height;
+		ge2d_config.dst_para.mem_type	= CANVAS_TYPE_INVALID;
+		ge2d_config.dst_para.fill_color_en = 0;
+		ge2d_config.dst_para.fill_mode	= 0;
+		ge2d_config.dst_para.x_rev	= 0;
+		ge2d_config.dst_para.y_rev	= 0;
+		ge2d_config.dst_para.color	= 0;
+		ge2d_config.dst_para.top	= 0;
+		ge2d_config.dst_para.left	= 0;
+
+		/* other ge2d parameters configure. */
+		ge2d_config.src_key.key_enable	= 0;
+		ge2d_config.src_key.key_mask	= 0;
+		ge2d_config.src_key.key_mode	= 0;
+		ge2d_config.alu_const_color	= 0;
+		ge2d_config.bitmask_en		= 0;
+		ge2d_config.src1_gb_alpha	= 0;
+		ge2d_config.dst_xy_swap		= 0;
+		ge2d_config.src2_para.mem_type	= CANVAS_TYPE_INVALID;
+
+		ATRACE_COUNTER("VC_OUT_GE2D-1.handle_start",
+			in_buf->aml_buf->frame_buffer.buf_idx);
+
+		v4l_dbg(ctx, V4L_DEBUG_GE2D_BUFMGR,
+			"ge2d_handle start: dec vf:%px/%d, ge2d vf:%px/%d, iphy:%lx/%lx %dx%d ophy:%lx/%lx %dx%d, vf:%ux%u, fmt(src:%x, dst:%x), "
+			"in:%d, out:%d, vf:%d, in done:%d, out done:%d\n",
+			in_buf->vf, in_buf->vf->index,
+			out_buf->vf, GE2D_BUF_GET_IDX(out_buf),
+			in_buf->vf->canvas0_config[0].phy_addr,
+			in_buf->vf->canvas0_config[1].phy_addr,
+			in_buf->vf->canvas0_config[0].width,
+			in_buf->vf->canvas0_config[0].height,
+			vf_out->canvas0_config[0].phy_addr,
+			vf_out->canvas0_config[1].phy_addr,
+			vf_out->canvas0_config[0].width,
+			vf_out->canvas0_config[0].height,
+			vf_out->width, vf_out->height,
+			src_fmt, dst_fmt,
+			kfifo_len(&ge2d->input),
+			kfifo_len(&ge2d->output),
+			kfifo_len(&ge2d->frame),
+			kfifo_len(&ge2d->in_done_q),
+			kfifo_len(&ge2d->out_done_q));
+
+		if (ge2d_context_config_ex(ge2d->ge2d_context, &ge2d_config) < 0) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"ge2d_context_config_ex error.\n");
+			goto exit;
+		}
+
+		if (!(in_buf->flag & GE2D_FLAG_EOS)) {
+			if (in_buf->vf->type & VIDTYPE_INTERLACE) {
+				stretchblt_noalpha(ge2d->ge2d_context,
+					0, 0, in_buf->vf->width, in_buf->vf->height / 2,
+					0, 0, in_buf->vf->width, in_buf->vf->height);
+			} else {
+				stretchblt_noalpha(ge2d->ge2d_context,
+					0, 0, in_buf->vf->width, in_buf->vf->height,
+					0, 0, in_buf->vf->width, in_buf->vf->height);
+			}
+		}
+
+		//pr_info("consume time %d us\n", div64_u64(local_clock() - start_time, 1000));
+
+		v4l_ge2d_fill_output_done(out_buf);
+		v4l_ge2d_empty_input_done(in_buf);
+
+		ge2d->in_num[INPUT_PORT]++;
+		ge2d->out_num[INPUT_PORT]++;
+	}
+exit:
+	while (!kthread_should_stop()) {
+		usleep_range(1000, 2000);
+	}
+
+	v4l_dbg(ctx, V4L_DEBUG_GE2D_DETAIL, "exit ge2d thread\n");
+
+	return 0;
+}
+
+int aml_v4l2_ge2d_get_buf_num(u32 mode)
+{
+	return 4;
+}
+
+int aml_v4l2_ge2d_init(
+		struct aml_vcodec_ctx *ctx,
+		struct aml_ge2d_cfg_infos *cfg,
+		struct aml_v4l2_ge2d** ge2d_handle)
+{
+	struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+	struct aml_v4l2_ge2d *ge2d;
+	u32 work_mode = cfg->mode;
+	u32 buf_size;
+	int i, ret;
+
+	if (!cfg || !ge2d_handle)
+		return -EINVAL;
+
+	ge2d = kzalloc(sizeof(*ge2d), GFP_KERNEL);
+	if (!ge2d)
+		return -ENOMEM;
+
+	ge2d->work_mode = work_mode;
+
+	/* default convert little endian. */
+	if (!ge2d->work_mode) {
+		ge2d->work_mode = GE2D_MODE_CONVERT_LE;
+	}
+
+	ge2d->ge2d_context = create_ge2d_work_queue();
+	if (!ge2d->ge2d_context) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"ge2d_create_instance fail\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	INIT_KFIFO(ge2d->input);
+	INIT_KFIFO(ge2d->output);
+	INIT_KFIFO(ge2d->frame);
+	INIT_KFIFO(ge2d->out_done_q);
+	INIT_KFIFO(ge2d->in_done_q);
+
+	ge2d->ctx = ctx;
+	buf_size = cfg->buf_size;
+	ge2d->buf_size = buf_size;
+
+	/* setup output fifo */
+	ret = kfifo_alloc(&ge2d->output, buf_size, GFP_KERNEL);
+	if (ret) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"alloc output fifo fail.\n");
+		ret = -ENOMEM;
+		goto error2;
+	}
+
+	ge2d->ovbpool = vzalloc(buf_size * sizeof(*ge2d->ovbpool));
+	if (!ge2d->ovbpool) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"alloc output vb pool fail.\n");
+		ret = -ENOMEM;
+		goto error3;
+	}
+
+	/* setup vframe fifo */
+	ret = kfifo_alloc(&ge2d->frame, buf_size, GFP_KERNEL);
+	if (ret) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"alloc ge2d vframe fifo fail.\n");
+		ret = -ENOMEM;
+		goto error4;
+	}
+
+	ge2d->vfpool = vzalloc(buf_size * sizeof(*ge2d->vfpool));
+	if (!ge2d->vfpool) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"alloc vf pool fail.\n");
+		ret = -ENOMEM;
+		goto error5;
+	}
+
+	ret = kfifo_alloc(&ge2d->input, GE2D_FRAME_SIZE, GFP_KERNEL);
+	if (ret) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"alloc input fifo fail.\n");
+		ret = -ENOMEM;
+		goto error6;
+	}
+
+	ge2d->ivbpool = vzalloc(GE2D_FRAME_SIZE * sizeof(*ge2d->ivbpool));
+	if (!ge2d->ivbpool) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"alloc input vb pool fail.\n");
+		ret = -ENOMEM;
+		goto error7;
+	}
+
+	for (i = 0 ; i < GE2D_FRAME_SIZE ; i++) {
+		kfifo_put(&ge2d->input, &ge2d->ivbpool[i]);
+	}
+
+	for (i = 0 ; i < buf_size ; i++) {
+		kfifo_put(&ge2d->output, &ge2d->ovbpool[i]);
+		kfifo_put(&ge2d->frame, &ge2d->vfpool[i]);
+	}
+
+	ge2d->src_canvas_id[0] = canvas_pool_map_alloc_canvas("v4ldec-ge2d");
+	ge2d->src_canvas_id[1] = canvas_pool_map_alloc_canvas("v4ldec-ge2d");
+	ge2d->src_canvas_id[2] = canvas_pool_map_alloc_canvas("v4ldec-ge2d");
+	ge2d->dst_canvas_id[0] = canvas_pool_map_alloc_canvas("v4ldec-ge2d");
+	ge2d->dst_canvas_id[1] = canvas_pool_map_alloc_canvas("v4ldec-ge2d");
+	ge2d->dst_canvas_id[2] = canvas_pool_map_alloc_canvas("v4ldec-ge2d");
+	if ((ge2d->src_canvas_id[0] <= 0) ||
+		(ge2d->src_canvas_id[1] <= 0) ||
+		(ge2d->src_canvas_id[2] <= 0) ||
+		(ge2d->dst_canvas_id[0] <= 0) ||
+		(ge2d->dst_canvas_id[1] <= 0) ||
+		(ge2d->dst_canvas_id[2] <= 0)) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"canvas pool alloc fail. src(%d, %d, %d) dst(%d, %d, %d).\n",
+			ge2d->src_canvas_id[0],
+			ge2d->src_canvas_id[1],
+			ge2d->src_canvas_id[2],
+			ge2d->dst_canvas_id[0],
+			ge2d->dst_canvas_id[1],
+			ge2d->dst_canvas_id[2]);
+		goto error8;
+	}
+
+	mutex_init(&ge2d->output_lock);
+	sema_init(&ge2d->sem_in, 0);
+	sema_init(&ge2d->sem_out, 0);
+
+	ge2d->running = true;
+	ge2d->task = kthread_run(aml_v4l2_ge2d_thread, ge2d,
+		"%s", "aml-v4l2-ge2d");
+	if (IS_ERR(ge2d->task)) {
+		ret = PTR_ERR(ge2d->task);
+		goto error9;
+	}
+	sched_setscheduler_nocheck(ge2d->task, SCHED_FIFO, &param);
+
+	*ge2d_handle = ge2d;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+		"GE2D_CFG bsize:%d, wkm:%x, bm:%x, drm:%d\n",
+		ge2d->buf_size,
+		ge2d->work_mode,
+		ge2d->buffer_mode,
+		cfg->is_drm);
+
+	return 0;
+
+error9:
+	if (ge2d->src_canvas_id[0] > 0)
+		canvas_pool_map_free_canvas(ge2d->src_canvas_id[0]);
+	if (ge2d->src_canvas_id[1] > 0)
+		canvas_pool_map_free_canvas(ge2d->src_canvas_id[1]);
+	if (ge2d->src_canvas_id[2] > 0)
+		canvas_pool_map_free_canvas(ge2d->src_canvas_id[2]);
+	if (ge2d->dst_canvas_id[0] > 0)
+		canvas_pool_map_free_canvas(ge2d->dst_canvas_id[0]);
+	if (ge2d->dst_canvas_id[1] > 0)
+		canvas_pool_map_free_canvas(ge2d->dst_canvas_id[1]);
+	if (ge2d->dst_canvas_id[2] > 0)
+		canvas_pool_map_free_canvas(ge2d->dst_canvas_id[2]);
+error8:
+	vfree(ge2d->ivbpool);
+error7:
+	kfifo_free(&ge2d->input);
+error6:
+	vfree(ge2d->vfpool);
+error5:
+	kfifo_free(&ge2d->frame);
+error4:
+	vfree(ge2d->ovbpool);
+error3:
+	kfifo_free(&ge2d->output);
+error2:
+	destroy_ge2d_work_queue(ge2d->ge2d_context);
+error:
+	kfree(ge2d);
+
+	return ret;
+}
+EXPORT_SYMBOL(aml_v4l2_ge2d_init);
+
+int aml_v4l2_ge2d_destroy(struct aml_v4l2_ge2d* ge2d)
+{
+	v4l_dbg(ge2d->ctx, V4L_DEBUG_GE2D_DETAIL,
+		"ge2d destroy begin\n");
+
+	ge2d->running = false;
+	up(&ge2d->sem_in);
+	up(&ge2d->sem_out);
+	kthread_stop(ge2d->task);
+
+	destroy_ge2d_work_queue(ge2d->ge2d_context);
+	/* no more ge2d callback below this line */
+
+	kfifo_free(&ge2d->frame);
+	vfree(ge2d->vfpool);
+	kfifo_free(&ge2d->output);
+	vfree(ge2d->ovbpool);
+	kfifo_free(&ge2d->input);
+	vfree(ge2d->ivbpool);
+	mutex_destroy(&ge2d->output_lock);
+
+	canvas_pool_map_free_canvas(ge2d->src_canvas_id[0]);
+	canvas_pool_map_free_canvas(ge2d->src_canvas_id[1]);
+	canvas_pool_map_free_canvas(ge2d->src_canvas_id[2]);
+	canvas_pool_map_free_canvas(ge2d->dst_canvas_id[0]);
+	canvas_pool_map_free_canvas(ge2d->dst_canvas_id[1]);
+	canvas_pool_map_free_canvas(ge2d->dst_canvas_id[2]);
+
+	v4l_dbg(ge2d->ctx, V4L_DEBUG_GE2D_DETAIL,
+		"ge2d destroy done\n");
+
+	kfree(ge2d);
+
+	return 0;
+}
+EXPORT_SYMBOL(aml_v4l2_ge2d_destroy);
+
+static int aml_v4l2_ge2d_push_vframe(struct aml_v4l2_ge2d* ge2d, struct vframe_s *vf)
+{
+	struct aml_v4l2_ge2d_buf* in_buf;
+	struct vdec_v4l2_buffer *fb = NULL;
+
+	if (!ge2d)
+		return -EINVAL;
+
+	if (!kfifo_get(&ge2d->input, &in_buf)) {
+		v4l_dbg(ge2d->ctx, V4L_DEBUG_CODEC_ERROR,
+			"cat not get free input buffer.\n");
+		return -1;
+	}
+
+	if (vf->type & VIDTYPE_V4L_EOS)
+		in_buf->flag |= GE2D_FLAG_EOS;
+
+	v4l_dbg(ge2d->ctx, V4L_DEBUG_GE2D_BUFMGR,
+		"ge2d_push_vframe: vf:%px, idx:%d, type:%x, ts:%lld\n",
+		vf, vf->index, vf->type, vf->timestamp);
+
+	fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
+	in_buf->aml_buf = container_of(fb, struct aml_video_dec_buf, frame_buffer);
+	in_buf->vf = vf;
+
+	do {
+		unsigned int dw_mode = VDEC_DW_NO_AFBC;
+		struct file *fp;
+
+		if (!dump_ge2d_input || ge2d->ctx->is_drm_mode)
+			break;
+
+		if (vdec_if_get_param(ge2d->ctx, GET_PARAM_DW_MODE, &dw_mode))
+			break;
+
+		if (dw_mode == VDEC_DW_AFBC_ONLY)
+			break;
+
+		fp = filp_open("/data/dec_dump_before.raw",
+				O_CREAT | O_RDWR | O_LARGEFILE | O_APPEND, 0600);
+		if (!IS_ERR(fp)) {
+			struct vb2_buffer *vb = &in_buf->aml_buf->vb.vb2_buf;
+
+			kernel_write(fp,vb2_plane_vaddr(vb, 0),vb->planes[0].length, 0);
+			if (in_buf->aml_buf->frame_buffer.num_planes == 2)
+				kernel_write(fp,vb2_plane_vaddr(vb, 1),
+						vb->planes[1].length, 0);
+			dump_ge2d_input--;
+			filp_close(fp, NULL);
+		}
+	} while(0);
+
+	ATRACE_COUNTER("VC_OUT_GE2D-0.receive", fb->buf_idx);
+
+	kfifo_put(&ge2d->in_done_q, in_buf);
+	up(&ge2d->sem_in);
+
+	return 0;
+}
+
+static void fill_ge2d_buf_cb(void *v4l_ctx, void *fb_ctx)
+{
+	struct aml_vcodec_ctx *ctx =
+		(struct aml_vcodec_ctx *)v4l_ctx;
+	struct vdec_v4l2_buffer *fb =
+		(struct vdec_v4l2_buffer *)fb_ctx;
+	int ret = -1;
+
+	ret = aml_v4l2_ge2d_push_vframe(ctx->ge2d, fb->vframe);
+	if (ret < 0) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"ge2d push vframe err, ret: %d\n", ret);
+	}
+}
+
+static struct task_ops_s ge2d_ops = {
+	.type		= TASK_TYPE_GE2D,
+	.get_vframe	= ge2d_vf_get,
+	.put_vframe	= ge2d_vf_put,
+	.fill_buffer	= fill_ge2d_buf_cb,
+};
+
+struct task_ops_s *get_ge2d_ops(void)
+{
+	return &ge2d_ops;
+}
+EXPORT_SYMBOL(get_ge2d_ops);
+
diff --git a/drivers/amvdec_ports/aml_vcodec_ge2d.h b/drivers/amvdec_ports/aml_vcodec_ge2d.h
new file mode 100644
index 0000000..a12931d
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_ge2d.h
@@ -0,0 +1,89 @@
+/*
+* Copyright (C) 2020 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#ifndef _AML_VCODEC_GE2D_H_
+#define _AML_VCODEC_GE2D_H_
+
+#include <linux/kfifo.h>
+#include "aml_vcodec_drv.h"
+#include "aml_vcodec_dec.h"
+
+/* define ge2d work mode. */
+#define GE2D_MODE_CONVERT_NV12		(1 << 0)
+#define GE2D_MODE_CONVERT_NV21		(1 << 1)
+#define GE2D_MODE_CONVERT_LE		(1 << 2)
+#define GE2D_MODE_CONVERT_BE		(1 << 3)
+#define GE2D_MODE_SEPARATE_FIELD	(1 << 4)
+#define GE2D_MODE_422_TO_420		(1 << 5)
+
+#define GE2D_FRAME_SIZE 64
+
+struct aml_v4l2_ge2d_buf {
+	u32			flag;
+	struct vframe_s		*vf;
+	void			*caller_data;
+	struct aml_video_dec_buf *aml_buf;
+};
+
+struct aml_v4l2_ge2d {
+	struct ge2d_context_s	*ge2d_context; /* handle of GE2D */
+	u32			buf_size; /* buffer size for ge2d */
+	u32			work_mode; /* enum ge2d_work_mode */
+	u32			buffer_mode;
+	struct aml_vcodec_ctx	*ctx;
+
+	DECLARE_KFIFO_PTR(input, typeof(struct aml_v4l2_ge2d_buf*));
+	DECLARE_KFIFO_PTR(output, typeof(struct aml_v4l2_ge2d_buf*));
+	DECLARE_KFIFO_PTR(frame, typeof(struct vframe_s *));
+	DECLARE_KFIFO(out_done_q, struct aml_v4l2_ge2d_buf *, GE2D_FRAME_SIZE);
+	DECLARE_KFIFO(in_done_q, struct aml_v4l2_ge2d_buf *, GE2D_FRAME_SIZE);
+
+	struct vframe_s		*vfpool;
+	struct aml_v4l2_ge2d_buf *ovbpool;
+	struct aml_v4l2_ge2d_buf *ivbpool;
+	struct task_struct	*task;
+	bool			running;
+	struct semaphore	sem_in, sem_out;
+
+	/* In p to i transition, output/frame can be multi writer */
+	struct mutex		output_lock;
+
+	/* for debugging */
+	/*
+	 * in[0] --> ge2d <-- in[1]
+	 * out[0]<-- ge2d --> out[1]
+	 */
+	int			in_num[2];
+	int			out_num[2];
+	ulong			fb_token;
+
+	int			src_canvas_id[3];
+	int			dst_canvas_id[3];
+};
+
+struct task_ops_s *get_ge2d_ops(void);
+
+int aml_v4l2_ge2d_init(
+		struct aml_vcodec_ctx *ctx,
+		struct aml_ge2d_cfg_infos *cfg,
+		struct aml_v4l2_ge2d** ge2d_handle);
+
+int aml_v4l2_ge2d_destroy(struct aml_v4l2_ge2d* ge2d);
+
+#endif
diff --git a/drivers/amvdec_ports/aml_vcodec_util.c b/drivers/amvdec_ports/aml_vcodec_util.c
new file mode 100644
index 0000000..54b0d06
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_util.c
@@ -0,0 +1,46 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/module.h>
+
+#include "aml_vcodec_drv.h"
+#include "aml_vcodec_util.h"
+
+void aml_vcodec_set_curr_ctx(struct aml_vcodec_dev *dev,
+	struct aml_vcodec_ctx *ctx)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+	dev->curr_ctx = ctx;
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+}
+EXPORT_SYMBOL(aml_vcodec_set_curr_ctx);
+
+struct aml_vcodec_ctx *aml_vcodec_get_curr_ctx(struct aml_vcodec_dev *dev)
+{
+	unsigned long flags;
+	struct aml_vcodec_ctx *ctx;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+	ctx = dev->curr_ctx;
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+	return ctx;
+}
+EXPORT_SYMBOL(aml_vcodec_get_curr_ctx);
diff --git a/drivers/amvdec_ports/aml_vcodec_util.h b/drivers/amvdec_ports/aml_vcodec_util.h
new file mode 100644
index 0000000..96c5453
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_util.h
@@ -0,0 +1,106 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#ifndef _AML_VCODEC_UTIL_H_
+#define _AML_VCODEC_UTIL_H_
+
+#include <linux/types.h>
+#include <linux/dma-direction.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+/*
+typedef unsigned long long	u64;
+typedef signed long long	s64;
+typedef unsigned int		u32;
+typedef unsigned short int	u16;
+typedef short int		s16;
+typedef unsigned char		u8;
+*/
+#define CODEC_MODE(a, b, c, d)\
+	(((u8)(a) << 24) | ((u8)(b) << 16) | ((u8)(c) << 8) | (u8)(d))
+
+#define BUFF_IDX(h, i)\
+	(((ulong)(h) << 8) | (u8)(i))
+
+struct aml_vcodec_mem {
+	int	index;
+	ulong	addr;
+	u32	size;
+	void	*vaddr;
+	u32	bytes_used;
+	u32	offset;
+	u64	timestamp;
+	u32	model;
+	ulong	meta_ptr;
+	struct dma_buf *dbuf;
+};
+
+struct aml_vcodec_ctx;
+struct aml_vcodec_dev;
+
+extern u32 debug_mode;
+extern u32 mandatory_dw_mmu;
+
+#ifdef v4l_dbg
+#undef v4l_dbg
+#endif
+
+/* v4l debug define. */
+#define V4L_DEBUG_CODEC_ERROR	(0)
+#define V4L_DEBUG_CODEC_PRINFO	(1 << 0)
+#define V4L_DEBUG_CODEC_STATE	(1 << 1)
+#define V4L_DEBUG_CODEC_BUFMGR	(1 << 2)
+#define V4L_DEBUG_CODEC_INPUT	(1 << 3)
+#define V4L_DEBUG_CODEC_OUTPUT	(1 << 4)
+#define V4L_DEBUG_CODEC_COUNT	(1 << 5)
+#define V4L_DEBUG_CODEC_PARSER	(1 << 6)
+#define V4L_DEBUG_CODEC_PROT	(1 << 7)
+#define V4L_DEBUG_CODEC_EXINFO	(1 << 8)
+#define V4L_DEBUG_VPP_BUFMGR	(1 << 9)
+#define V4L_DEBUG_VPP_DETAIL	(1 << 10)
+#define V4L_DEBUG_TASK_CHAIN	(1 << 11)
+#define V4L_DEBUG_GE2D_BUFMGR	(1 << 12)
+#define V4L_DEBUG_GE2D_DETAIL	(1 << 13)
+
+#define __v4l_dbg(h, id, fmt, args...)					\
+	do {								\
+		if (h)							\
+			pr_info("[%d]: " fmt, id, ##args);		\
+		else							\
+			pr_info(fmt, ##args);				\
+	} while (0)
+
+#define v4l_dbg(h, flags, fmt, args...)						\
+	do {									\
+		struct aml_vcodec_ctx *__ctx = (struct aml_vcodec_ctx *) h;	\
+		if ((flags == V4L_DEBUG_CODEC_ERROR) ||				\
+			(flags == V4L_DEBUG_CODEC_PRINFO) ||			\
+			(debug_mode & flags)) {				\
+			if (flags == V4L_DEBUG_CODEC_ERROR) {			\
+				__v4l_dbg(h, __ctx->id, "[ERR]: " fmt, ##args);	\
+			} else	{						\
+				__v4l_dbg(h, __ctx->id, fmt, ##args);		\
+			}							\
+		}								\
+	} while (0)
+
+void aml_vcodec_set_curr_ctx(struct aml_vcodec_dev *dev,
+	struct aml_vcodec_ctx *ctx);
+struct aml_vcodec_ctx *aml_vcodec_get_curr_ctx(struct aml_vcodec_dev *dev);
+
+#endif /* _AML_VCODEC_UTIL_H_ */
diff --git a/drivers/amvdec_ports/aml_vcodec_vpp.c b/drivers/amvdec_ports/aml_vcodec_vpp.c
new file mode 100644
index 0000000..9f4e960
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_vpp.c
@@ -0,0 +1,1102 @@
+/*
+* Copyright (C) 2020 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <uapi/linux/sched/types.h>
+#include <linux/amlogic/meson_uvm_core.h>
+
+#include "aml_vcodec_vpp.h"
+#include "aml_vcodec_adapt.h"
+#include "vdec_drv_if.h"
+#include "../common/chips/decoder_cpu_ver_info.h"
+
+#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2
+#include <trace/events/meson_atrace.h>
+
+#define VPP_BUF_GET_IDX(vpp_buf) (vpp_buf->aml_buf->vb.vb2_buf.index)
+#define INPUT_PORT 0
+#define OUTPUT_PORT 1
+
+extern int dump_vpp_input;
+extern int vpp_bypass_frames;
+
+static void di_release_keep_buf_wrap(void *arg)
+{
+	struct di_buffer *buf = (struct di_buffer *)arg;
+
+	v4l_dbg(0, V4L_DEBUG_VPP_BUFMGR,
+		"%s release di local buffer %px, vf:%px, comm:%s, pid:%d\n",
+		__func__ , buf, buf->vf,
+		current->comm, current->pid);
+
+	di_release_keep_buf(buf);
+
+	ATRACE_COUNTER("VC_OUT_VPP_LC-2.lc_release", buf->mng.index);
+}
+
+static int attach_DI_buffer(struct aml_v4l2_vpp_buf *vpp_buf)
+{
+	struct aml_v4l2_vpp *vpp = vpp_buf->di_buf.caller_data;
+	struct dma_buf *dma = NULL;
+	struct aml_video_dec_buf *aml_buf = NULL;
+	struct uvm_hook_mod_info u_info;
+	int ret;
+
+	aml_buf = vpp_buf->aml_buf;
+	if (!aml_buf)
+		return -EINVAL;
+
+	dma = aml_buf->vb.vb2_buf.planes[0].dbuf;
+	if (!dma || !dmabuf_is_uvm(dma)) {
+		v4l_dbg(vpp->ctx, V4L_DEBUG_CODEC_ERROR,
+			"attach_DI_buffer err\n");
+		return -EINVAL;
+	}
+
+	if (!vpp_buf->di_local_buf) {
+		v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_BUFMGR,
+			"attach_DI_buffer nothing\n");
+		return 0;
+	}
+
+	if (uvm_get_hook_mod(dma, VF_PROCESS_DI)) {
+		uvm_put_hook_mod(dma, VF_PROCESS_DI);
+		v4l_dbg(vpp->ctx, V4L_DEBUG_CODEC_ERROR,
+			"attach_DI_buffer exist hook\n");
+		return -EINVAL;
+	}
+	u_info.type = VF_PROCESS_DI;
+	u_info.arg = (void *)vpp_buf->di_local_buf;
+	u_info.free = di_release_keep_buf_wrap;
+
+	ret = uvm_attach_hook_mod(dma, &u_info);
+	if (ret < 0) {
+		v4l_dbg(vpp->ctx, V4L_DEBUG_CODEC_ERROR,
+			"fail to set dmabuf DI hook\n");
+	}
+
+	ATRACE_COUNTER("VC_OUT_VPP_LC-0.lc_attach", vpp_buf->di_local_buf->mng.index);
+
+	v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_BUFMGR,
+		"%s attach di local buffer %px, dbuf:%px\n",
+		__func__ , vpp_buf->di_local_buf, dma);
+
+	return ret;
+}
+
+static int detach_DI_buffer(struct aml_v4l2_vpp_buf *vpp_buf)
+{
+	struct aml_v4l2_vpp *vpp = vpp_buf->di_buf.caller_data;
+	struct dma_buf *dma = NULL;
+	struct aml_video_dec_buf *aml_buf = NULL;
+	int ret;
+
+	aml_buf = vpp_buf->aml_buf;
+	if (!aml_buf)
+		return -EINVAL;
+
+	dma = aml_buf->vb.vb2_buf.planes[0].dbuf;
+	if (!dma || !dmabuf_is_uvm(dma)) {
+		v4l_dbg(vpp->ctx, V4L_DEBUG_CODEC_ERROR,
+			"detach_DI_buffer err\n");
+		return -EINVAL;
+	}
+
+	if (!vpp_buf->di_local_buf) {
+		v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_BUFMGR,
+			"detach_DI_buffer nothing\n");
+		return 0;
+	}
+
+	ATRACE_COUNTER("VC_OUT_VPP_LC-1.lc_detach", vpp_buf->di_local_buf->mng.index);
+
+	ret = uvm_detach_hook_mod(dma, VF_PROCESS_DI);
+	if (ret < 0) {
+		v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_BUFMGR,
+			"fail to remove dmabuf DI hook\n");
+	}
+
+	v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_BUFMGR,
+		"%s detach di local buffer %px, dbuf:%px\n",
+		__func__ , vpp_buf->di_local_buf, dma);
+
+	return ret;
+}
+
+static void release_DI_buff(struct aml_v4l2_vpp* vpp)
+{
+	struct aml_v4l2_vpp_buf *vpp_buf = NULL;
+
+	while (kfifo_get(&vpp->out_done_q, &vpp_buf)) {
+		if (vpp_buf->di_buf.private_data) {
+			di_release_keep_buf(vpp_buf->di_local_buf);
+			v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_BUFMGR,
+				"%s release di local buffer %px\n",
+				__func__ , vpp_buf->di_local_buf);
+		}
+	}
+}
+
+static int is_di_input_buff_full(struct aml_v4l2_vpp *vpp)
+{
+	return ((vpp->in_num[INPUT_PORT] - vpp->in_num[OUTPUT_PORT])
+		> vpp->di_ibuf_num) ? true : false;
+}
+
+static int is_di_output_buff_full(struct aml_v4l2_vpp *vpp)
+{
+	return ((vpp->out_num[INPUT_PORT] - vpp->out_num[OUTPUT_PORT])
+		> vpp->di_obuf_num) ? true : false;
+}
+
+static enum DI_ERRORTYPE
+	v4l_vpp_fill_output_done_alloc_buffer(struct di_buffer *buf)
+{
+	struct aml_v4l2_vpp *vpp = buf->caller_data;
+	struct aml_v4l2_vpp_buf *vpp_buf = NULL;
+	struct vdec_v4l2_buffer *fb = NULL;
+	bool bypass = false;
+	bool eos = false;
+
+	if (!vpp || !vpp->ctx) {
+		pr_err("fatal %s %d vpp:%p\n",
+			__func__, __LINE__, vpp);
+		di_release_keep_buf_wrap(buf);
+		return DI_ERR_UNDEFINED;
+	}
+
+	if (vpp->ctx->is_stream_off) {
+		v4l_dbg(vpp->ctx, V4L_DEBUG_CODEC_EXINFO,
+			"vpp discard submit frame %s %d vpp:%p\n",
+			__func__, __LINE__, vpp);
+		di_release_keep_buf_wrap(buf);
+		return DI_ERR_UNDEFINED;
+	}
+
+	if (!kfifo_get(&vpp->processing, &vpp_buf)) {
+		v4l_dbg(vpp->ctx, V4L_DEBUG_CODEC_EXINFO,
+			"vpp doesn't get output %s %d vpp:%p\n",
+			__func__, __LINE__, vpp);
+		di_release_keep_buf_wrap(buf);
+		return DI_ERR_UNDEFINED;
+	}
+
+	fb	= &vpp_buf->aml_buf->frame_buffer;
+	eos	= (buf->flag & DI_FLAG_EOS);
+	bypass	= (buf->flag & DI_FLAG_BUF_BY_PASS);
+
+	vpp_buf->di_buf.vf->timestamp	= buf->vf->timestamp;
+	vpp_buf->di_buf.private_data	= buf->private_data;
+	vpp_buf->di_buf.vf->vf_ext	= buf->vf;
+	vpp_buf->di_buf.flag		= buf->flag;
+	vpp_buf->di_buf.vf->v4l_mem_handle = (ulong)fb;
+
+	if (!eos && !bypass) {
+		vpp_buf->di_local_buf = buf;
+		vpp_buf->di_buf.vf->vf_ext = buf->vf;
+		vpp_buf->di_buf.vf->flag |= VFRAME_FLAG_CONTAIN_POST_FRAME;
+	}
+
+	kfifo_put(&vpp->out_done_q, vpp_buf);
+
+	if (vpp->is_prog)
+		kfifo_put(&vpp->input, vpp_buf->inbuf);
+
+	v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_BUFMGR,
+		"vpp_output local done: idx:%d, vf:%px, ext vf:%px, idx:%d, flag(vf:%x di:%x) %s %s, ts:%lld, "
+		"in:%d, out:%d, vf:%d, in done:%d, out done:%d\n",
+		fb->buf_idx,
+		vpp_buf->di_buf.vf,
+		vpp_buf->di_buf.vf->vf_ext,
+		vpp_buf->di_buf.vf->index,
+		vpp_buf->di_buf.vf->flag,
+		buf->flag,
+		vpp->is_prog ? "P" : "I",
+		eos ? "eos" : "",
+		vpp_buf->di_buf.vf->timestamp,
+		kfifo_len(&vpp->input),
+		kfifo_len(&vpp->output),
+		kfifo_len(&vpp->frame),
+		kfifo_len(&vpp->in_done_q),
+		kfifo_len(&vpp->out_done_q));
+
+	ATRACE_COUNTER("VC_OUT_VPP-2.lc_submit", fb->buf_idx);
+
+	fb->task->submit(fb->task, TASK_TYPE_VPP);
+
+	vpp->out_num[OUTPUT_PORT]++;
+	vpp->in_num[OUTPUT_PORT]++;
+
+	return DI_ERR_NONE;
+}
+
+static enum DI_ERRORTYPE
+	v4l_vpp_empty_input_done(struct di_buffer *buf)
+{
+	struct aml_v4l2_vpp *vpp = buf->caller_data;
+	struct aml_v4l2_vpp_buf *vpp_buf;
+	struct vdec_v4l2_buffer *fb = NULL;
+	bool eos = false;
+
+	if (!vpp || !vpp->ctx) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"fatal %s %d vpp:%px\n",
+			__func__, __LINE__, vpp);
+		return DI_ERR_UNDEFINED;
+	}
+
+	if (vpp->ctx->is_stream_off) {
+		v4l_dbg(vpp->ctx, V4L_DEBUG_CODEC_EXINFO,
+			"vpp discard recycle frame %s %d vpp:%p\n",
+			__func__, __LINE__, vpp);
+		return DI_ERR_UNDEFINED;
+	}
+
+	vpp_buf	= container_of(buf, struct aml_v4l2_vpp_buf, di_buf);
+	fb 	= &vpp_buf->aml_buf->frame_buffer;
+	eos	= (buf->flag & DI_FLAG_EOS);
+
+	v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_BUFMGR,
+		"vpp_input done: idx:%d, vf:%px, idx: %d, flag(vf:%x di:%x) %s %s, ts:%lld, "
+		"in:%d, out:%d, vf:%d, in done:%d, out done:%d\n",
+		fb->buf_idx,
+		buf->vf,
+		buf->vf->index,
+		buf->vf->flag,
+		buf->flag,
+		vpp->is_prog ? "P" : "I",
+		eos ? "eos" : "",
+		buf->vf->timestamp,
+		kfifo_len(&vpp->input),
+		kfifo_len(&vpp->output),
+		kfifo_len(&vpp->frame),
+		kfifo_len(&vpp->in_done_q),
+		kfifo_len(&vpp->out_done_q));
+
+	if (!vpp->is_prog) {
+		/* recycle vf only in non-bypass mode */
+		fb->task->recycle(fb->task, TASK_TYPE_VPP);
+
+		kfifo_put(&vpp->input, vpp_buf);
+	}
+
+	if (vpp->buffer_mode != BUFFER_MODE_ALLOC_BUF)
+		vpp->in_num[OUTPUT_PORT]++;
+
+	ATRACE_COUNTER("VC_IN_VPP-1.recycle", fb->buf_idx);
+
+	return DI_ERR_NONE;
+}
+
+static enum DI_ERRORTYPE
+	v4l_vpp_fill_output_done(struct di_buffer *buf)
+{
+	struct aml_v4l2_vpp *vpp = buf->caller_data;
+	struct aml_v4l2_vpp_buf *vpp_buf = NULL;
+	struct vdec_v4l2_buffer *fb = NULL;
+	bool bypass = false;
+	bool eos = false;
+
+	if (!vpp || !vpp->ctx) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"fatal %s %d vpp:%px\n",
+			__func__, __LINE__, vpp);
+		return DI_ERR_UNDEFINED;
+	}
+
+	if (vpp->ctx->is_stream_off) {
+		v4l_dbg(vpp->ctx, V4L_DEBUG_CODEC_EXINFO,
+			"vpp discard submit frame %s %d vpp:%p\n",
+			__func__, __LINE__, vpp);
+		return DI_ERR_UNDEFINED;
+	}
+
+	vpp_buf	= container_of(buf, struct aml_v4l2_vpp_buf, di_buf);
+	fb	= &vpp_buf->aml_buf->frame_buffer;
+	eos	= (buf->flag & DI_FLAG_EOS);
+	bypass	= (buf->flag & DI_FLAG_BUF_BY_PASS);
+
+	/* recovery fb handle. */
+	buf->vf->v4l_mem_handle = (ulong)fb;
+
+	kfifo_put(&vpp->out_done_q, vpp_buf);
+
+	v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_BUFMGR,
+		"vpp_output done: idx:%d, vf:%px, idx:%d, flag(vf:%x di:%x) %s %s, ts:%lld, "
+		"in:%d, out:%d, vf:%d, in done:%d, out done:%d\n",
+		fb->buf_idx,
+		buf->vf,
+		buf->vf->index,
+		buf->vf->flag,
+		buf->flag,
+		vpp->is_prog ? "P" : "I",
+		eos ? "eos" : "",
+		buf->vf->timestamp,
+		kfifo_len(&vpp->input),
+		kfifo_len(&vpp->output),
+		kfifo_len(&vpp->frame),
+		kfifo_len(&vpp->in_done_q),
+		kfifo_len(&vpp->out_done_q));
+
+	ATRACE_COUNTER("VC_OUT_VPP-2.submit", fb->buf_idx);
+
+	fb->task->submit(fb->task, TASK_TYPE_VPP);
+
+	vpp->out_num[OUTPUT_PORT]++;
+
+	/* count for bypass nr */
+	if (vpp->buffer_mode == BUFFER_MODE_ALLOC_BUF)
+		vpp->in_num[OUTPUT_PORT]++;
+
+	return DI_ERR_NONE;
+}
+
+static void vpp_vf_get(void *caller, struct vframe_s **vf_out)
+{
+	struct aml_v4l2_vpp *vpp = (struct aml_v4l2_vpp *)caller;
+	struct aml_v4l2_vpp_buf *vpp_buf = NULL;
+	struct vdec_v4l2_buffer *fb = NULL;
+	struct di_buffer *buf = NULL;
+	struct vframe_s *vf = NULL;
+	bool bypass = false;
+	bool eos = false;
+
+	if (!vpp || !vpp->ctx) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"fatal %s %d vpp:%px\n",
+			__func__, __LINE__, vpp);
+		return;
+	}
+
+	if (kfifo_get(&vpp->out_done_q, &vpp_buf)) {
+		fb	= &vpp_buf->aml_buf->frame_buffer;
+		buf	= &vpp_buf->di_buf;
+		eos	= (buf->flag & DI_FLAG_EOS);
+		bypass	= (buf->flag & DI_FLAG_BUF_BY_PASS);
+		vf	= buf->vf;
+
+		if (eos) {
+			v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_DETAIL,
+				"%s %d got eos\n",
+				__func__, __LINE__);
+			vf->type |= VIDTYPE_V4L_EOS;
+			vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+		}
+
+		if (!eos && !bypass) {
+			if (vpp->buffer_mode == BUFFER_MODE_ALLOC_BUF) {
+				attach_DI_buffer(vpp_buf);
+			}
+		}
+
+		*vf_out = vf;
+
+		ATRACE_COUNTER("VC_OUT_VPP-3.vf_get", fb->buf_idx);
+
+		v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_BUFMGR,
+			"%s: vf:%px, index:%d, flag(vf:%x di:%x), ts:%lld\n",
+			__func__, vf,
+			vf->index,
+			vf->flag,
+			buf->flag,
+			vf->timestamp);
+	}
+}
+
+static void vpp_vf_put(void *caller, struct vframe_s *vf)
+{
+	struct aml_v4l2_vpp *vpp = (struct aml_v4l2_vpp *)caller;
+	struct vdec_v4l2_buffer *fb = NULL;
+	struct aml_video_dec_buf *aml_buf = NULL;
+	struct aml_v4l2_vpp_buf *vpp_buf = NULL;
+	struct di_buffer *buf = NULL;
+	bool bypass = false;
+	bool eos = false;
+
+	fb	= (struct vdec_v4l2_buffer *) vf->v4l_mem_handle;
+	aml_buf	= container_of(fb, struct aml_video_dec_buf, frame_buffer);
+
+
+	vpp_buf	= (struct aml_v4l2_vpp_buf *) aml_buf->vpp_buf_handle;
+	buf	= &vpp_buf->di_buf;
+	eos	= (buf->flag & DI_FLAG_EOS);
+	bypass	= (buf->flag & DI_FLAG_BUF_BY_PASS);
+
+	v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_BUFMGR,
+		"%s: vf:%px, index:%d, flag(vf:%x di:%x), ts:%lld\n",
+		__func__, vf,
+		vf->index,
+		vf->flag,
+		buf->flag,
+		vf->timestamp);
+
+	ATRACE_COUNTER("VC_IN_VPP-0.vf_put", fb->buf_idx);
+
+	if (vpp->is_prog) {
+		ATRACE_COUNTER("VC_IN_VPP-1.recycle", fb->buf_idx);
+		fb->task->recycle(fb->task, TASK_TYPE_VPP);
+	}
+
+	if (!eos && !bypass) {
+		if (vpp->buffer_mode == BUFFER_MODE_ALLOC_BUF) {
+			detach_DI_buffer(vpp_buf);
+		}
+	}
+
+	mutex_lock(&vpp->output_lock);
+	kfifo_put(&vpp->frame, vf);
+	kfifo_put(&vpp->output, vpp_buf);
+	mutex_unlock(&vpp->output_lock);
+	up(&vpp->sem_out);
+}
+
+static int aml_v4l2_vpp_thread(void* param)
+{
+	struct aml_v4l2_vpp* vpp = param;
+	struct aml_vcodec_ctx *ctx = vpp->ctx;
+
+	v4l_dbg(ctx, V4L_DEBUG_VPP_DETAIL, "enter vpp thread\n");
+	while (vpp->running) {
+		struct aml_v4l2_vpp_buf *in_buf;
+		struct aml_v4l2_vpp_buf *out_buf = NULL;
+		struct vframe_s *vf_out = NULL;
+		struct vdec_v4l2_buffer *fb;
+
+		if (down_interruptible(&vpp->sem_in))
+			goto exit;
+retry:
+		if (!vpp->running)
+			break;
+
+		if (kfifo_is_empty(&vpp->output)) {
+			if (down_interruptible(&vpp->sem_out))
+				goto exit;
+			goto retry;
+		}
+
+		if ((vpp->buffer_mode == BUFFER_MODE_ALLOC_BUF) &&
+			(is_di_input_buff_full(vpp) || is_di_output_buff_full(vpp))) {
+			usleep_range(500, 550);
+			goto retry;
+		}
+
+		mutex_lock(&vpp->output_lock);
+		if (!kfifo_get(&vpp->output, &out_buf)) {
+			mutex_unlock(&vpp->output_lock);
+			v4l_dbg(ctx, 0, "vpp can not get output\n");
+			goto exit;
+		}
+		mutex_unlock(&vpp->output_lock);
+
+		/* bind v4l2 buffers */
+		if (!vpp->is_prog && !out_buf->aml_buf) {
+			struct vdec_v4l2_buffer *out;
+
+			if (!ctx->fb_ops.query(&ctx->fb_ops, &vpp->fb_token)) {
+				usleep_range(500, 550);
+				mutex_lock(&vpp->output_lock);
+				kfifo_put(&vpp->output, out_buf);
+				mutex_unlock(&vpp->output_lock);
+				goto retry;
+			}
+
+			if (ctx->fb_ops.alloc(&ctx->fb_ops, vpp->fb_token, &out, AML_FB_REQ_VPP)) {
+				usleep_range(5000, 5500);
+				mutex_lock(&vpp->output_lock);
+				kfifo_put(&vpp->output, out_buf);
+				mutex_unlock(&vpp->output_lock);
+				goto retry;
+			}
+
+			out_buf->aml_buf = container_of(out,
+				struct aml_video_dec_buf, frame_buffer);
+			out_buf->aml_buf->vpp_buf_handle = (ulong) out_buf;
+			v4l_dbg(ctx, V4L_DEBUG_VPP_BUFMGR,
+				"vpp bind buf:%d to vpp_buf:%px\n",
+				VPP_BUF_GET_IDX(out_buf), out_buf);
+
+			out->m.mem[0].bytes_used = out->m.mem[0].size;
+			out->m.mem[1].bytes_used = out->m.mem[1].size;
+		}
+
+		/* safe to pop in_buf */
+		if (!kfifo_get(&vpp->in_done_q, &in_buf)) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"vpp can not get input\n");
+			goto exit;
+		}
+
+		mutex_lock(&vpp->output_lock);
+		if (!kfifo_get(&vpp->frame, &vf_out)) {
+			mutex_unlock(&vpp->output_lock);
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"vpp can not get frame\n");
+			goto exit;
+		}
+		mutex_unlock(&vpp->output_lock);
+
+		if (!vpp->is_prog) {
+			/* submit I to DI. */
+			fb = &out_buf->aml_buf->frame_buffer;
+			fb->status = FB_ST_VPP;
+
+			memcpy(vf_out, in_buf->di_buf.vf, sizeof(*vf_out));
+			memcpy(vf_out->canvas0_config,
+				in_buf->di_buf.vf->canvas0_config,
+				2 * sizeof(struct canvas_config_s));
+
+			vf_out->canvas0_config[0].phy_addr = fb->m.mem[0].addr;
+			if (fb->num_planes == 1)
+				vf_out->canvas0_config[1].phy_addr =
+					fb->m.mem[0].addr + fb->m.mem[0].offset;
+			else
+				vf_out->canvas0_config[1].phy_addr =
+					fb->m.mem[1].addr;
+
+			if (in_buf->di_buf.flag & DI_FLAG_EOS)
+				memset(vf_out, 0, sizeof(*vf_out));
+
+			vf_out->meta_data_size = in_buf->di_buf.vf->meta_data_size;
+			vf_out->meta_data_buf = in_buf->di_buf.vf->meta_data_buf;
+		} else {
+			/* submit P to DI. */
+			out_buf->aml_buf = in_buf->aml_buf;
+			out_buf->aml_buf->vpp_buf_handle = (ulong) out_buf;
+
+			memcpy(vf_out, in_buf->di_buf.vf, sizeof(*vf_out));
+		}
+
+		/* fill outbuf parms. */
+		out_buf->di_buf.vf	= vf_out;
+		out_buf->di_buf.flag	= 0;
+		out_buf->di_local_buf	= NULL;
+		out_buf->di_buf.caller_data = vpp;
+
+		/* fill inbuf parms. */
+		in_buf->di_buf.caller_data = vpp;
+
+		/*
+		 * HWC or SF should hold di buffres refcnt after resolution changed
+		 * that might cause stuck, thus sumbit 10 frames from dec to display directly.
+		 * then frames will be pushed out from these buffer queuen and
+		 * recycle local buffers to DI module.
+		 */
+		if (/*(ctx->vpp_cfg.res_chg) && */(vpp->is_prog) &&
+			(vpp->buffer_mode == BUFFER_MODE_ALLOC_BUF)) {
+			if (vpp->in_num[INPUT_PORT] < vpp_bypass_frames) {
+				vpp->is_bypass_p = true;
+			} else {
+				vpp->is_bypass_p = false;
+				ctx->vpp_cfg.res_chg = false;
+			}
+		}
+
+		v4l_dbg(ctx, V4L_DEBUG_VPP_BUFMGR,
+			"vpp_handle start: idx:(%d, %d), dec vf:%px/%d, vpp vf:%px/%d, iphy:%lx/%lx %dx%d ophy:%lx/%lx %dx%d, %s %s "
+			"in:%d, out:%d, vf:%d, in done:%d, out done:%d",
+			in_buf->aml_buf->frame_buffer.buf_idx,
+			out_buf->aml_buf->frame_buffer.buf_idx,
+			in_buf->di_buf.vf, in_buf->di_buf.vf->index,
+			out_buf->di_buf.vf, VPP_BUF_GET_IDX(out_buf),
+			in_buf->di_buf.vf->canvas0_config[0].phy_addr,
+			in_buf->di_buf.vf->canvas0_config[1].phy_addr,
+			in_buf->di_buf.vf->canvas0_config[0].width,
+			in_buf->di_buf.vf->canvas0_config[0].height,
+			vf_out->canvas0_config[0].phy_addr,
+			vf_out->canvas0_config[1].phy_addr,
+			vf_out->canvas0_config[0].width,
+			vf_out->canvas0_config[0].height,
+			vpp->is_prog ? "P" : "",
+			vpp->is_bypass_p ? "bypass-prog" : "",
+			kfifo_len(&vpp->input),
+			kfifo_len(&vpp->output),
+			kfifo_len(&vpp->frame),
+			kfifo_len(&vpp->in_done_q),
+			kfifo_len(&vpp->out_done_q));
+
+		if (vpp->is_bypass_p) {
+			ATRACE_COUNTER("V4L_OUT_VPP-1.direct_handle_start",
+				in_buf->aml_buf->frame_buffer.buf_idx);
+			out_buf->di_buf.flag = in_buf->di_buf.flag;
+			out_buf->di_buf.vf->vf_ext = in_buf->di_buf.vf;
+
+			v4l_vpp_fill_output_done(&out_buf->di_buf);
+			v4l_vpp_empty_input_done(&in_buf->di_buf);
+		} else {
+			if (vpp->buffer_mode == BUFFER_MODE_ALLOC_BUF) {
+				/*
+				 * the flow of DI local buffer:
+				 * empty input -> output done cb -> fetch processing fifo.
+				 */
+				ATRACE_COUNTER("VC_OUT_VPP-1.lc_handle_start",
+					in_buf->aml_buf->frame_buffer.buf_idx);
+				out_buf->inbuf = in_buf;
+				kfifo_put(&vpp->processing, out_buf);
+
+				di_empty_input_buffer(vpp->di_handle, &in_buf->di_buf);
+			} else {
+				ATRACE_COUNTER("VC_OUT_VPP-1.fill_output_start",
+					out_buf->aml_buf->frame_buffer.buf_idx);
+				di_fill_output_buffer(vpp->di_handle, &out_buf->di_buf);
+
+				ATRACE_COUNTER("VC_OUT_VPP-1.empty_input_start",
+					in_buf->aml_buf->frame_buffer.buf_idx);
+				di_empty_input_buffer(vpp->di_handle, &in_buf->di_buf);
+			}
+		}
+		vpp->in_num[INPUT_PORT]++;
+		vpp->out_num[INPUT_PORT]++;
+	}
+exit:
+	while (!kthread_should_stop()) {
+		usleep_range(1000, 2000);
+	}
+
+	v4l_dbg(ctx, V4L_DEBUG_VPP_DETAIL, "exit vpp thread\n");
+
+	return 0;
+}
+
+int aml_v4l2_vpp_get_buf_num(u32 mode)
+{
+	if ((mode == VPP_MODE_DI) ||
+		(mode == VPP_MODE_COLOR_CONV) ||
+		(mode == VPP_MODE_NOISE_REDUC)) {
+		return 4;
+	}
+	//TODO: support more modes
+	return 2;
+}
+
+int aml_v4l2_vpp_reset(struct aml_v4l2_vpp *vpp)
+{
+	int i;
+	struct sched_param param =
+		{ .sched_priority = MAX_RT_PRIO - 1 };
+
+	vpp->running = false;
+	up(&vpp->sem_in);
+	up(&vpp->sem_out);
+	kthread_stop(vpp->task);
+
+	kfifo_reset(&vpp->input);
+	kfifo_reset(&vpp->output);
+	kfifo_reset(&vpp->frame);
+	kfifo_reset(&vpp->out_done_q);
+	kfifo_reset(&vpp->in_done_q);
+	kfifo_reset(&vpp->processing);
+
+	for (i = 0 ; i < VPP_FRAME_SIZE ; i++) {
+		memset(&vpp->ivbpool[i], 0, sizeof(struct aml_v4l2_vpp_buf));
+
+		kfifo_put(&vpp->input, &vpp->ivbpool[i]);
+	}
+
+	for (i = 0 ; i < vpp->buf_size ; i++) {
+		memset(&vpp->ovbpool[i], 0, sizeof(struct aml_v4l2_vpp_buf));
+		memset(&vpp->vfpool[i], 0, sizeof(struct vframe_s));
+
+		kfifo_put(&vpp->output, &vpp->ovbpool[i]);
+		kfifo_put(&vpp->frame, &vpp->vfpool[i]);
+	}
+
+	vpp->in_num[0]	= 0;
+	vpp->in_num[1]	= 0;
+	vpp->out_num[0]	= 0;
+	vpp->out_num[1]	= 0;
+	vpp->fb_token	= 0;
+	sema_init(&vpp->sem_in, 0);
+	sema_init(&vpp->sem_out, 0);
+
+	vpp->running = true;
+	vpp->task = kthread_run(aml_v4l2_vpp_thread, vpp,
+		"%s", "aml-v4l2-vpp");
+	if (IS_ERR(vpp->task)) {
+		return PTR_ERR(vpp->task);
+	}
+
+	sched_setscheduler_nocheck(vpp->task, SCHED_FIFO, &param);
+
+	v4l_dbg(vpp->ctx, V4L_DEBUG_CODEC_PRINFO, "vpp wrapper reset.\n");
+
+	return 0;
+
+}
+EXPORT_SYMBOL(aml_v4l2_vpp_reset);
+
+int aml_v4l2_vpp_init(
+		struct aml_vcodec_ctx *ctx,
+		struct aml_vpp_cfg_infos *cfg,
+		struct aml_v4l2_vpp** vpp_handle)
+{
+	struct di_init_parm init;
+	u32 buf_size;
+	int i, ret;
+	struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+	struct aml_v4l2_vpp *vpp;
+	u32 work_mode = cfg->mode;
+
+	if (!cfg || work_mode > VPP_MODE_MAX || !ctx || !vpp_handle)
+		return -EINVAL;
+	if (cfg->fmt != V4L2_PIX_FMT_NV12 && cfg->fmt != V4L2_PIX_FMT_NV12M &&
+		cfg->fmt != V4L2_PIX_FMT_NV21 && cfg->fmt != V4L2_PIX_FMT_NV21M)
+		return -EINVAL;
+
+	vpp = kzalloc(sizeof(*vpp), GFP_KERNEL);
+	if (!vpp)
+		return -ENOMEM;
+
+	vpp->work_mode = work_mode;
+	if (vpp->work_mode >= VPP_MODE_DI_LOCAL &&
+		vpp->work_mode <= VPP_MODE_NOISE_REDUC_LOCAL)
+		vpp->buffer_mode = BUFFER_MODE_ALLOC_BUF;
+	else
+		vpp->buffer_mode = BUFFER_MODE_USE_BUF;
+
+	init.work_mode			= WORK_MODE_PRE_POST;
+	init.buffer_mode		= vpp->buffer_mode;
+	init.ops.fill_output_done	= v4l_vpp_fill_output_done;
+	init.ops.empty_input_done	= v4l_vpp_empty_input_done;
+	init.caller_data		= (void *)vpp;
+
+	if (vpp->buffer_mode == BUFFER_MODE_ALLOC_BUF) {
+		init.ops.fill_output_done =
+			v4l_vpp_fill_output_done_alloc_buffer;
+	}
+
+	if (vpp->buffer_mode == BUFFER_MODE_ALLOC_BUF)
+		init.output_format = DI_OUTPUT_BY_DI_DEFINE;
+	else if ((vpp->buffer_mode == BUFFER_MODE_USE_BUF) &&
+		((cfg->fmt == V4L2_PIX_FMT_NV21M) || (cfg->fmt == V4L2_PIX_FMT_NV21)))
+		init.output_format = DI_OUTPUT_NV21 | DI_OUTPUT_LINEAR;
+	else if ((vpp->buffer_mode == BUFFER_MODE_USE_BUF) &&
+		((cfg->fmt == V4L2_PIX_FMT_NV12M) || (cfg->fmt == V4L2_PIX_FMT_NV12)))
+		init.output_format = DI_OUTPUT_NV12 | DI_OUTPUT_LINEAR;
+	else /* AFBC deocde case, NV12 as default */
+		init.output_format = DI_OUTPUT_NV12 | DI_OUTPUT_LINEAR;
+
+	if (cfg->is_drm)
+		init.output_format |= DI_OUTPUT_TVP;
+
+	vpp->di_handle = di_create_instance(init);
+	if (vpp->di_handle < 0) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"di_create_instance fail\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	INIT_KFIFO(vpp->input);
+	INIT_KFIFO(vpp->output);
+	INIT_KFIFO(vpp->frame);
+	INIT_KFIFO(vpp->out_done_q);
+	INIT_KFIFO(vpp->in_done_q);
+	INIT_KFIFO(vpp->processing);
+
+	vpp->ctx = ctx;
+	vpp->is_prog = cfg->is_prog;
+	vpp->is_bypass_p = cfg->is_bypass_p;
+
+	buf_size = vpp->is_prog ? 16 : cfg->buf_size;
+	vpp->buf_size = buf_size;
+
+	/* setup output fifo */
+	ret = kfifo_alloc(&vpp->output, buf_size, GFP_KERNEL);
+	if (ret) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"alloc output fifo fail.\n");
+		ret = -ENOMEM;
+		goto error2;
+	}
+
+	vpp->ovbpool = vzalloc(buf_size * sizeof(*vpp->ovbpool));
+	if (!vpp->ovbpool) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"alloc output vb pool fail.\n");
+		ret = -ENOMEM;
+		goto error3;
+	}
+
+	/* setup vframe fifo */
+	ret = kfifo_alloc(&vpp->frame, buf_size, GFP_KERNEL);
+	if (ret) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"alloc vpp vframe fifo fail.\n");
+		ret = -ENOMEM;
+		goto error4;
+	}
+
+	vpp->vfpool = vzalloc(buf_size * sizeof(*vpp->vfpool));
+	if (!vpp->vfpool) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"alloc vf pool fail.\n");
+		ret = -ENOMEM;
+		goto error5;
+	}
+
+	/* setup processing fifo */
+	ret = kfifo_alloc(&vpp->processing, buf_size, GFP_KERNEL);
+	if (ret) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"alloc processing fifo fail.\n");
+		ret = -ENOMEM;
+		goto error6;
+	}
+
+	ret = kfifo_alloc(&vpp->input, VPP_FRAME_SIZE, GFP_KERNEL);
+	if (ret) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"alloc input fifo fail.\n");
+		ret = -ENOMEM;
+		goto error7;
+	}
+
+	vpp->ivbpool = vzalloc(VPP_FRAME_SIZE * sizeof(*vpp->ivbpool));
+	if (!vpp->ivbpool) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"alloc input vb pool fail.\n");
+		ret = -ENOMEM;
+		goto error8;
+	}
+
+	for (i = 0 ; i < VPP_FRAME_SIZE ; i++) {
+		kfifo_put(&vpp->input, &vpp->ivbpool[i]);
+	}
+
+	for (i = 0 ; i < buf_size ; i++) {
+		kfifo_put(&vpp->output, &vpp->ovbpool[i]);
+		kfifo_put(&vpp->frame, &vpp->vfpool[i]);
+	}
+
+	mutex_init(&vpp->output_lock);
+	sema_init(&vpp->sem_in, 0);
+	sema_init(&vpp->sem_out, 0);
+
+	vpp->running = true;
+	vpp->task = kthread_run(aml_v4l2_vpp_thread, vpp,
+		"aml-%s", "aml-v4l2-vpp");
+	if (IS_ERR(vpp->task)) {
+		ret = PTR_ERR(vpp->task);
+		goto error9;
+	}
+	sched_setscheduler_nocheck(vpp->task, SCHED_FIFO, &param);
+
+	vpp->di_ibuf_num = di_get_input_buffer_num(vpp->di_handle);
+	vpp->di_obuf_num = di_get_output_buffer_num(vpp->di_handle);
+
+	*vpp_handle = vpp;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
+		"vpp_wrapper init bsize:%d, di(i:%d, o:%d), wkm:%x, bm:%x, fmt:%x, drm:%d, prog:%d, byp:%d, local:%d, NR:%d\n",
+		vpp->buf_size,
+		vpp->di_ibuf_num,
+		vpp->di_obuf_num,
+		vpp->work_mode,
+		vpp->buffer_mode,
+		init.output_format,
+		cfg->is_drm,
+		cfg->is_prog,
+		cfg->is_bypass_p,
+		cfg->enable_local_buf,
+		cfg->enable_nr);
+
+	return 0;
+
+error9:
+	vfree(vpp->ivbpool);
+error8:
+	kfifo_free(&vpp->input);
+error7:
+	kfifo_free(&vpp->processing);
+error6:
+	vfree(vpp->vfpool);
+error5:
+	kfifo_free(&vpp->frame);
+error4:
+	vfree(vpp->ovbpool);
+error3:
+	kfifo_free(&vpp->output);
+error2:
+	di_destroy_instance(vpp->di_handle);
+error:
+	kfree(vpp);
+	return ret;
+}
+EXPORT_SYMBOL(aml_v4l2_vpp_init);
+
+int aml_v4l2_vpp_destroy(struct aml_v4l2_vpp* vpp)
+{
+	v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_DETAIL,
+		"vpp destroy begin\n");
+	vpp->running = false;
+	up(&vpp->sem_in);
+	up(&vpp->sem_out);
+	kthread_stop(vpp->task);
+
+	di_destroy_instance(vpp->di_handle);
+	/* no more vpp callback below this line */
+
+	if (vpp->buffer_mode == BUFFER_MODE_ALLOC_BUF)
+		release_DI_buff(vpp);
+
+	kfifo_free(&vpp->processing);
+	kfifo_free(&vpp->frame);
+	vfree(vpp->vfpool);
+	kfifo_free(&vpp->output);
+	vfree(vpp->ovbpool);
+	kfifo_free(&vpp->input);
+	vfree(vpp->ivbpool);
+	mutex_destroy(&vpp->output_lock);
+	v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_DETAIL,
+		"vpp_wrapper destroy done\n");
+	kfree(vpp);
+
+	return 0;
+}
+EXPORT_SYMBOL(aml_v4l2_vpp_destroy);
+
+static int aml_v4l2_vpp_push_vframe(struct aml_v4l2_vpp* vpp, struct vframe_s *vf)
+{
+	struct aml_v4l2_vpp_buf *in_buf;
+	struct vdec_v4l2_buffer *fb = NULL;
+
+	if (!vpp)
+		return -EINVAL;
+
+	if (!kfifo_get(&vpp->input, &in_buf)) {
+		v4l_dbg(vpp->ctx, V4L_DEBUG_CODEC_ERROR,
+			"cat not get free input buffer.\n");
+		return -1;
+	}
+
+#if 0 //to debug di by frame
+	if (vpp->in_num[INPUT_PORT] > 2)
+		return 0;
+	if (vpp->in_num[INPUT_PORT] == 2)
+		vf->type |= VIDTYPE_V4L_EOS;
+#endif
+
+	in_buf->di_buf.vf = vf;
+	in_buf->di_buf.flag = 0;
+	if (vf->type & VIDTYPE_V4L_EOS) {
+		u32 dw_mode = VDEC_DW_NO_AFBC;
+
+		in_buf->di_buf.flag |= DI_FLAG_EOS;
+
+		if (vdec_if_get_param(vpp->ctx, GET_PARAM_DW_MODE, &dw_mode))
+			return -1;
+
+		vf->type |= vpp->ctx->vpp_cfg.is_prog ?
+			VIDTYPE_PROGRESSIVE :
+			VIDTYPE_INTERLACE;
+
+		if (dw_mode != VDEC_DW_NO_AFBC)
+			vf->type |= VIDTYPE_COMPRESS;
+	}
+
+	fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
+	in_buf->aml_buf = container_of(fb, struct aml_video_dec_buf, frame_buffer);
+
+	if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) {
+		if (vf->canvas0_config[0].block_mode == CANVAS_BLKMODE_LINEAR) {
+			if ((vpp->ctx->output_pix_fmt != V4L2_PIX_FMT_H264) &&
+				(vpp->ctx->output_pix_fmt != V4L2_PIX_FMT_MPEG1) &&
+				(vpp->ctx->output_pix_fmt != V4L2_PIX_FMT_MPEG2) &&
+				(vpp->ctx->output_pix_fmt != V4L2_PIX_FMT_MPEG4) &&
+				(vpp->ctx->output_pix_fmt != V4L2_PIX_FMT_MJPEG)) {
+				vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
+			}
+			else {
+				if (fb->status == FB_ST_GE2D)
+					vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
+			}
+		}
+	} else {
+		if (vf->canvas0_config[0].block_mode == CANVAS_BLKMODE_LINEAR)
+			vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
+	}
+
+	v4l_dbg(vpp->ctx, V4L_DEBUG_VPP_BUFMGR,
+		"vpp_push_vframe: idx:%d, vf:%px, idx:%d, type:%x, ts:%lld\n",
+		fb->buf_idx, vf, vf->index, vf->type, vf->timestamp);
+
+	do {
+		unsigned int dw_mode = VDEC_DW_NO_AFBC;
+		struct file *fp;
+
+		if (!dump_vpp_input || vpp->ctx->is_drm_mode)
+			break;
+		if (vdec_if_get_param(vpp->ctx, GET_PARAM_DW_MODE, &dw_mode))
+			break;
+		if (dw_mode == VDEC_DW_AFBC_ONLY)
+			break;
+
+		fp = filp_open("/data/dec_dump_before.raw",
+				O_CREAT | O_RDWR | O_LARGEFILE | O_APPEND, 0600);
+		if (!IS_ERR(fp)) {
+			struct vb2_buffer *vb = &in_buf->aml_buf->vb.vb2_buf;
+
+			kernel_write(fp,vb2_plane_vaddr(vb, 0),vb->planes[0].length, 0);
+			if (in_buf->aml_buf->frame_buffer.num_planes == 2)
+				kernel_write(fp,vb2_plane_vaddr(vb, 1),
+						vb->planes[1].length, 0);
+			dump_vpp_input--;
+			filp_close(fp, NULL);
+		}
+	} while(0);
+
+	ATRACE_COUNTER("VC_OUT_VPP-0.receive", fb->buf_idx);
+
+	kfifo_put(&vpp->in_done_q, in_buf);
+	up(&vpp->sem_in);
+
+	return 0;
+}
+
+static void fill_vpp_buf_cb(void *v4l_ctx, void *fb_ctx)
+{
+	struct aml_vcodec_ctx *ctx =
+		(struct aml_vcodec_ctx *)v4l_ctx;
+	struct vdec_v4l2_buffer *fb =
+		(struct vdec_v4l2_buffer *)fb_ctx;
+	int ret = -1;
+
+	ret = aml_v4l2_vpp_push_vframe(ctx->vpp, fb->vframe);
+	if (ret < 0) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+			"vpp push vframe err, ret: %d\n", ret);
+	}
+}
+
+static struct task_ops_s vpp_ops = {
+	.type		= TASK_TYPE_VPP,
+	.get_vframe	= vpp_vf_get,
+	.put_vframe	= vpp_vf_put,
+	.fill_buffer	= fill_vpp_buf_cb,
+};
+
+struct task_ops_s *get_vpp_ops(void)
+{
+	return &vpp_ops;
+}
+EXPORT_SYMBOL(get_vpp_ops);
+
diff --git a/drivers/amvdec_ports/aml_vcodec_vpp.h b/drivers/amvdec_ports/aml_vcodec_vpp.h
new file mode 100644
index 0000000..7a5771d
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_vpp.h
@@ -0,0 +1,112 @@
+/*
+* Copyright (C) 2020 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#ifndef _AML_VCODEC_VPP_H_
+#define _AML_VCODEC_VPP_H_
+
+#define SUPPORT_V4L_VPP
+
+#include <linux/kfifo.h>
+#ifdef SUPPORT_V4L_VPP
+#include <linux/amlogic/media/di/di_interface.h>
+#endif
+#include "aml_vcodec_drv.h"
+#include "aml_vcodec_dec.h"
+
+enum vpp_work_mode {
+	VPP_MODE_DI,
+	VPP_MODE_COLOR_CONV,
+	VPP_MODE_NOISE_REDUC,
+	VPP_MODE_DI_LOCAL = 0x81,
+	VPP_MODE_COLOR_CONV_LOCAL = 0x82,
+	VPP_MODE_NOISE_REDUC_LOCAL = 0x83,
+	VPP_MODE_MAX = 0xff
+};
+
+#define VPP_FRAME_SIZE 64
+
+struct aml_v4l2_vpp_buf {
+#ifdef SUPPORT_V4L_VPP
+	struct di_buffer di_buf;
+	struct di_buffer *di_local_buf;
+#endif
+	struct aml_video_dec_buf *aml_buf;
+	struct aml_v4l2_vpp_buf *inbuf;
+};
+
+struct aml_v4l2_vpp {
+	int di_handle; /* handle of DI */
+	struct aml_vcodec_ctx *ctx;
+	u32 buf_size; /* buffer size for vpp */
+	u32 work_mode; /* enum vpp_work_mode */
+	u32 buffer_mode;
+
+	DECLARE_KFIFO_PTR(input, typeof(struct aml_v4l2_vpp_buf*));
+	DECLARE_KFIFO_PTR(output, typeof(struct aml_v4l2_vpp_buf*));
+	DECLARE_KFIFO_PTR(processing, typeof(struct aml_v4l2_vpp_buf*));
+	DECLARE_KFIFO_PTR(frame, typeof(struct vframe_s *));
+	DECLARE_KFIFO(out_done_q, struct aml_v4l2_vpp_buf *, VPP_FRAME_SIZE);
+	DECLARE_KFIFO(in_done_q, struct aml_v4l2_vpp_buf *, VPP_FRAME_SIZE);
+
+	struct vframe_s *vfpool;
+	struct aml_v4l2_vpp_buf *ovbpool;
+	struct aml_v4l2_vpp_buf *ivbpool;
+	struct task_struct *task;
+	bool running;
+	struct semaphore sem_in, sem_out;
+
+	/* In p to i transition, output/frame can be multi writer */
+	struct mutex output_lock;
+
+	/* for debugging */
+	/*
+	 * in[0] --> vpp <-- in[1]
+	 * out[0]<-- vpp --> out[1]
+	 */
+	int in_num[2];
+	int out_num[2];
+	ulong fb_token;
+
+	bool is_prog;
+	bool is_bypass_p;
+	int di_ibuf_num;
+	int di_obuf_num;
+};
+
+struct task_ops_s *get_vpp_ops(void);
+
+#ifdef SUPPORT_V4L_VPP
+/* get number of buffer needed for a working mode */
+int aml_v4l2_vpp_get_buf_num(u32 mode);
+int aml_v4l2_vpp_init(
+		struct aml_vcodec_ctx *ctx,
+		struct aml_vpp_cfg_infos *cfg,
+		struct aml_v4l2_vpp** vpp_handle);
+int aml_v4l2_vpp_destroy(struct aml_v4l2_vpp* vpp);
+int aml_v4l2_vpp_reset(struct aml_v4l2_vpp *vpp);
+#else
+static inline int aml_v4l2_vpp_get_buf_num(u32 mode) { return -1; }
+static inline int aml_v4l2_vpp_init(
+		struct aml_vcodec_ctx *ctx,
+		struct aml_vpp_cfg_infos *cfg,
+		struct aml_v4l2_vpp** vpp_handle) { return -1; }
+static inline int aml_v4l2_vpp_destroy(struct aml_v4l2_vpp* vpp) { return -1; }
+#endif
+
+#endif
diff --git a/drivers/amvdec_ports/decoder/aml_h264_parser.c b/drivers/amvdec_ports/decoder/aml_h264_parser.c
new file mode 100644
index 0000000..d0d0198
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/aml_h264_parser.c
@@ -0,0 +1,713 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+
+#include "aml_h264_parser.h"
+#include "../utils/get_bits.h"
+#include "../utils/put_bits.h"
+#include "../utils/golomb.h"
+#include "../utils/common.h"
+#include "utils.h"
+
+#define MAX_DELAYED_PIC_COUNT	(16)
+#define MAX_LOG2_MAX_FRAME_NUM	(12 + 4)
+#define MIN_LOG2_MAX_FRAME_NUM	(4)
+#define MAX_SPS_COUNT		(32)
+#define EXTENDED_SAR		(255)
+
+static const struct rational h264_pixel_aspect[17] = {
+	{   0,  1 },
+	{   1,  1 },
+	{  12, 11 },
+	{  10, 11 },
+	{  16, 11 },
+	{  40, 33 },
+	{  24, 11 },
+	{  20, 11 },
+	{  32, 11 },
+	{  80, 33 },
+	{  18, 11 },
+	{  15, 11 },
+	{  64, 33 },
+	{ 160, 99 },
+	{   4,  3 },
+	{   3,  2 },
+	{   2,  1 },
+};
+
+/* maximum number of MBs in the DPB for a given level */
+static const int level_max_dpb_mbs[][2] = {
+	{ 10, 396	},
+	{ 11, 900	},
+	{ 12, 2376	},
+	{ 13, 2376	},
+	{ 20, 2376	},
+	{ 21, 4752	},
+	{ 22, 8100	},
+	{ 30, 8100	},
+	{ 31, 18000 	},
+	{ 32, 20480 	},
+	{ 40, 32768 	},
+	{ 41, 32768 	},
+	{ 42, 34816 	},
+	{ 50, 110400	},
+	{ 51, 184320	},
+	{ 52, 184320	},
+};
+
+static const u8 default_scaling4[2][16] = {
+	{  6, 13, 20, 28, 13, 20, 28, 32,
+	  20, 28, 32, 37, 28, 32, 37, 42},
+	{ 10, 14, 20, 24, 14, 20, 24, 27,
+	  20, 24, 27, 30, 24, 27, 30, 34 }
+};
+
+static const u8 default_scaling8[2][64] = {
+	{  6, 10, 13, 16, 18, 23, 25, 27,
+	  10, 11, 16, 18, 23, 25, 27, 29,
+	  13, 16, 18, 23, 25, 27, 29, 31,
+	  16, 18, 23, 25, 27, 29, 31, 33,
+	  18, 23, 25, 27, 29, 31, 33, 36,
+	  23, 25, 27, 29, 31, 33, 36, 38,
+	  25, 27, 29, 31, 33, 36, 38, 40,
+	  27, 29, 31, 33, 36, 38, 40, 42 },
+	{  9, 13, 15, 17, 19, 21, 22, 24,
+	  13, 13, 17, 19, 21, 22, 24, 25,
+	  15, 17, 19, 21, 22, 24, 25, 27,
+	  17, 19, 21, 22, 24, 25, 27, 28,
+	  19, 21, 22, 24, 25, 27, 28, 30,
+	  21, 22, 24, 25, 27, 28, 30, 32,
+	  22, 24, 25, 27, 28, 30, 32, 33,
+	  24, 25, 27, 28, 30, 32, 33, 35 }
+};
+
+extern const u8 ff_zigzag_scan[16 + 1];
+extern const u8 ff_zigzag_direct[64];
+
+static int decode_scaling_list(struct get_bits_context *gb,
+	u8 *factors, int size,
+	const u8 *jvt_list,
+	const u8 *fallback_list)
+{
+	int i, last = 8, next = 8;
+	const u8 *scan = size == 16 ? ff_zigzag_scan : ff_zigzag_direct;
+
+	if (!get_bits1(gb)) /* matrix not written, we use the predicted one */
+		memcpy(factors, fallback_list, size * sizeof(u8));
+	else
+		for (i = 0; i < size; i++) {
+			if (next) {
+				int v = get_se_golomb(gb);
+				/*if (v < -128 || v > 127) { //JM19 has not check.
+					pr_err( "delta scale %d is invalid\n", v);
+					return -1;
+				}*/
+				next = (last + v) & 0xff;
+			}
+			if (!i && !next) { /* matrix not written, we use the preset one */
+				memcpy(factors, jvt_list, size * sizeof(u8));
+				break;
+			}
+			last = factors[scan[i]] = next ? next : last;
+		}
+	return 0;
+}
+
+/* returns non zero if the provided SPS scaling matrix has been filled */
+static int decode_scaling_matrices(struct get_bits_context *gb,
+	const struct h264_SPS_t *sps,
+	const struct h264_PPS_t *pps, int is_sps,
+	u8(*scaling_matrix4)[16],
+	u8(*scaling_matrix8)[64])
+{
+	int ret = 0;
+	int fallback_sps = !is_sps && sps->scaling_matrix_present;
+	const u8 *fallback[4] = {
+		fallback_sps ? sps->scaling_matrix4[0] : default_scaling4[0],
+		fallback_sps ? sps->scaling_matrix4[3] : default_scaling4[1],
+		fallback_sps ? sps->scaling_matrix8[0] : default_scaling8[0],
+		fallback_sps ? sps->scaling_matrix8[3] : default_scaling8[1]
+	};
+
+	if (get_bits1(gb)) {
+		ret |= decode_scaling_list(gb, scaling_matrix4[0], 16, default_scaling4[0], fallback[0]);        // Intra, Y
+		ret |= decode_scaling_list(gb, scaling_matrix4[1], 16, default_scaling4[0], scaling_matrix4[0]); // Intra, Cr
+		ret |= decode_scaling_list(gb, scaling_matrix4[2], 16, default_scaling4[0], scaling_matrix4[1]); // Intra, Cb
+		ret |= decode_scaling_list(gb, scaling_matrix4[3], 16, default_scaling4[1], fallback[1]);        // Inter, Y
+		ret |= decode_scaling_list(gb, scaling_matrix4[4], 16, default_scaling4[1], scaling_matrix4[3]); // Inter, Cr
+		ret |= decode_scaling_list(gb, scaling_matrix4[5], 16, default_scaling4[1], scaling_matrix4[4]); // Inter, Cb
+		if (is_sps || pps->transform_8x8_mode) {
+			ret |= decode_scaling_list(gb, scaling_matrix8[0], 64, default_scaling8[0], fallback[2]); // Intra, Y
+			ret |= decode_scaling_list(gb, scaling_matrix8[3], 64, default_scaling8[1], fallback[3]); // Inter, Y
+			if (sps->chroma_format_idc == 3) {
+				ret |= decode_scaling_list(gb, scaling_matrix8[1], 64, default_scaling8[0], scaling_matrix8[0]); // Intra, Cr
+				ret |= decode_scaling_list(gb, scaling_matrix8[4], 64, default_scaling8[1], scaling_matrix8[3]); // Inter, Cr
+				ret |= decode_scaling_list(gb, scaling_matrix8[2], 64, default_scaling8[0], scaling_matrix8[1]); // Intra, Cb
+				ret |= decode_scaling_list(gb, scaling_matrix8[5], 64, default_scaling8[1], scaling_matrix8[4]); // Inter, Cb
+			}
+		}
+		if (!ret)
+			ret = is_sps;
+	}
+
+	return ret;
+}
+
+static int decode_hrd_parameters(struct get_bits_context *gb,
+	struct h264_SPS_t *sps)
+{
+	int cpb_count, i;
+
+	cpb_count = get_ue_golomb_31(gb) + 1;
+	if (cpb_count > 32U) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"cpb_count %d invalid\n", cpb_count);
+		return -1;
+	}
+
+	get_bits(gb, 4); /* bit_rate_scale */
+	get_bits(gb, 4); /* cpb_size_scale */
+	for (i = 0; i < cpb_count; i++) {
+		get_ue_golomb_long(gb); /* bit_rate_value_minus1 */
+		get_ue_golomb_long(gb); /* cpb_size_value_minus1 */
+		get_bits1(gb);		/* cbr_flag */
+	}
+
+	sps->initial_cpb_removal_delay_length = get_bits(gb, 5) + 1;
+	sps->cpb_removal_delay_length	  = get_bits(gb, 5) + 1;
+	sps->dpb_output_delay_length	  = get_bits(gb, 5) + 1;
+	sps->time_offset_length		  = get_bits(gb, 5);
+	sps->cpb_cnt			  = cpb_count;
+
+	return 0;
+}
+
+static int decode_vui_parameters(struct get_bits_context *gb,  struct h264_SPS_t *sps)
+{
+	int aspect_ratio_info_present_flag;
+	u32 aspect_ratio_idc;
+
+	aspect_ratio_info_present_flag = get_bits1(gb);
+
+	if (aspect_ratio_info_present_flag) {
+		aspect_ratio_idc = get_bits(gb, 8);
+		if (aspect_ratio_idc == EXTENDED_SAR) {
+			sps->sar.num = get_bits(gb, 16);
+			sps->sar.den = get_bits(gb, 16);
+		} else if (aspect_ratio_idc < ARRAY_SIZE(h264_pixel_aspect)) {
+			sps->sar = h264_pixel_aspect[aspect_ratio_idc];
+		} else {
+			return -1;
+		}
+	} else {
+		sps->sar.num =
+		sps->sar.den = 0;
+	}
+
+	if (get_bits1(gb))      /* overscan_info_present_flag */
+		get_bits1(gb);  /* overscan_appropriate_flag */
+
+	sps->video_signal_type_present_flag = get_bits1(gb);
+	if (sps->video_signal_type_present_flag) {
+		get_bits(gb, 3);                 /* video_format */
+		sps->full_range = get_bits1(gb); /* video_full_range_flag */
+
+		sps->colour_description_present_flag = get_bits1(gb);
+		if (sps->colour_description_present_flag) {
+			sps->color_primaries = get_bits(gb, 8); /* colour_primaries */
+			sps->color_trc       = get_bits(gb, 8); /* transfer_characteristics */
+			sps->colorspace      = get_bits(gb, 8); /* matrix_coefficients */
+
+			// Set invalid values to "unspecified"
+			if (!av_color_primaries_name(sps->color_primaries))
+				sps->color_primaries = AVCOL_PRI_UNSPECIFIED;
+			if (!av_color_transfer_name(sps->color_trc))
+				sps->color_trc = AVCOL_TRC_UNSPECIFIED;
+			if (!av_color_space_name(sps->colorspace))
+				sps->colorspace = AVCOL_SPC_UNSPECIFIED;
+		}
+	}
+
+	/* chroma_location_info_present_flag */
+	if (get_bits1(gb)) {
+		/* chroma_sample_location_type_top_field */
+		//avctx->chroma_sample_location = get_ue_golomb(gb) + 1;
+		get_ue_golomb(gb);  /* chroma_sample_location_type_bottom_field */
+	}
+
+	if (show_bits1(gb) && get_bits_left(gb) < 10) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Truncated VUI\n");
+		return 0;
+	}
+
+	sps->timing_info_present_flag = get_bits1(gb);
+	if (sps->timing_info_present_flag) {
+		unsigned num_units_in_tick = get_bits_long(gb, 32);
+		unsigned time_scale        = get_bits_long(gb, 32);
+		if (!num_units_in_tick || !time_scale) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_PARSER,
+				"time_scale/num_units_in_tick invalid or unsupported (%u/%u)\n",
+				time_scale, num_units_in_tick);
+			sps->timing_info_present_flag = 0;
+		} else {
+			sps->num_units_in_tick = num_units_in_tick;
+			sps->time_scale = time_scale;
+		}
+		sps->fixed_frame_rate_flag = get_bits1(gb);
+	}
+
+	sps->nal_hrd_parameters_present_flag = get_bits1(gb);
+	if (sps->nal_hrd_parameters_present_flag)
+		if (decode_hrd_parameters(gb, sps) < 0)
+			return -1;
+	sps->vcl_hrd_parameters_present_flag = get_bits1(gb);
+	if (sps->vcl_hrd_parameters_present_flag)
+		if (decode_hrd_parameters(gb, sps) < 0)
+			return -1;
+	if (sps->nal_hrd_parameters_present_flag ||
+		sps->vcl_hrd_parameters_present_flag)
+		get_bits1(gb);     /* low_delay_hrd_flag */
+	sps->pic_struct_present_flag = get_bits1(gb);
+	if (!get_bits_left(gb))
+		return 0;
+	sps->bitstream_restriction_flag = get_bits1(gb);
+	if (sps->bitstream_restriction_flag) {
+		get_bits1(gb);     /* motion_vectors_over_pic_boundaries_flag */
+		get_ue_golomb(gb); /* max_bytes_per_pic_denom */
+		get_ue_golomb(gb); /* max_bits_per_mb_denom */
+		get_ue_golomb(gb); /* log2_max_mv_length_horizontal */
+		get_ue_golomb(gb); /* log2_max_mv_length_vertical */
+		sps->num_reorder_frames = get_ue_golomb(gb);
+		sps->max_dec_frame_buffering = get_ue_golomb(gb); /*max_dec_frame_buffering*/
+
+		if (get_bits_left(gb) < 0) {
+			sps->num_reorder_frames         = 0;
+			sps->bitstream_restriction_flag = 0;
+		}
+
+		if (sps->num_reorder_frames > 16U
+			/* max_dec_frame_buffering || max_dec_frame_buffering > 16 */) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+				"Clipping illegal num_reorder_frames %d\n",
+				sps->num_reorder_frames);
+				sps->num_reorder_frames = 16;
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int aml_h264_parser_sps(struct get_bits_context *gb, struct h264_SPS_t *sps)
+{
+	int ret;
+	u32 sps_id;
+	int profile_idc, level_idc, constraint_set_flags = 0;
+	int i, log2_max_frame_num_minus4;
+
+	profile_idc		= get_bits(gb, 8);
+	constraint_set_flags	|= get_bits1(gb) << 0;	// constraint_set0_flag
+	constraint_set_flags	|= get_bits1(gb) << 1;	// constraint_set1_flag
+	constraint_set_flags	|= get_bits1(gb) << 2;	// constraint_set2_flag
+	constraint_set_flags	|= get_bits1(gb) << 3;	// constraint_set3_flag
+	constraint_set_flags	|= get_bits1(gb) << 4;	// constraint_set4_flag
+	constraint_set_flags	|= get_bits1(gb) << 5;	// constraint_set5_flag
+	skip_bits(gb, 2); 				// reserved_zero_2bits
+	level_idc	= get_bits(gb, 8);
+	sps_id		= get_ue_golomb_31(gb);
+
+	if (sps_id >= MAX_SPS_COUNT) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"sps_id %u out of range\n", sps_id);
+		goto fail;
+	}
+
+	sps->sps_id			= sps_id;
+	sps->time_offset_length		= 24;
+	sps->profile_idc		= profile_idc;
+	sps->constraint_set_flags	= constraint_set_flags;
+	sps->level_idc			= level_idc;
+	sps->full_range			= -1;
+
+	memset(sps->scaling_matrix4, 16, sizeof(sps->scaling_matrix4));
+	memset(sps->scaling_matrix8, 16, sizeof(sps->scaling_matrix8));
+	sps->scaling_matrix_present = 0;
+	sps->colorspace = 2; //AVCOL_SPC_UNSPECIFIED
+
+	if (sps->profile_idc == 100 ||  // High profile
+		sps->profile_idc == 110 ||  // High10 profile
+		sps->profile_idc == 122 ||  // High422 profile
+		sps->profile_idc == 244 ||  // High444 Predictive profile
+		sps->profile_idc ==  44 ||  // Cavlc444 profile
+		sps->profile_idc ==  83 ||  // Scalable Constrained High profile (SVC)
+		sps->profile_idc ==  86 ||  // Scalable High Intra profile (SVC)
+		sps->profile_idc == 118 ||  // Stereo High profile (MVC)
+		sps->profile_idc == 128 ||  // Multiview High profile (MVC)
+		sps->profile_idc == 138 ||  // Multiview Depth High profile (MVCD)
+		sps->profile_idc == 144) {  // old High444 profile
+		sps->chroma_format_idc = get_ue_golomb_31(gb);
+
+		if (sps->chroma_format_idc > 3U) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+				"chroma_format_idc %u\n", sps->chroma_format_idc);
+			goto fail;
+		} else if (sps->chroma_format_idc == 3) {
+			sps->residual_color_transform_flag = get_bits1(gb);
+			if (sps->residual_color_transform_flag) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+					"separate color planes are not supported\n");
+				goto fail;
+			}
+		}
+
+		sps->bit_depth_luma	= get_ue_golomb(gb) + 8;
+		sps->bit_depth_chroma	= get_ue_golomb(gb) + 8;
+		if (sps->bit_depth_chroma != sps->bit_depth_luma) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+				"Different chroma and luma bit depth\n");
+			goto fail;
+		}
+
+		if (sps->bit_depth_luma	< 8 || sps->bit_depth_luma > 14 ||
+			sps->bit_depth_chroma < 8 || sps->bit_depth_chroma > 14) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+				"illegal bit depth value (%d, %d)\n",
+				sps->bit_depth_luma, sps->bit_depth_chroma);
+			goto fail;
+		}
+
+		sps->transform_bypass = get_bits1(gb);
+		ret = decode_scaling_matrices(gb, sps, NULL, 1,
+			sps->scaling_matrix4, sps->scaling_matrix8);
+		if (ret < 0)
+			goto fail;
+		sps->scaling_matrix_present |= ret;
+	} else {
+		sps->chroma_format_idc	= 1;
+		sps->bit_depth_luma	= 8;
+		sps->bit_depth_chroma	= 8;
+	}
+
+	log2_max_frame_num_minus4 = get_ue_golomb(gb);
+	if (log2_max_frame_num_minus4 < MIN_LOG2_MAX_FRAME_NUM - 4 ||
+		log2_max_frame_num_minus4 > MAX_LOG2_MAX_FRAME_NUM - 4) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"log2_max_frame_num_minus4 out of range (0-12): %d\n",
+			log2_max_frame_num_minus4);
+		goto fail;
+	}
+	sps->log2_max_frame_num = log2_max_frame_num_minus4 + 4;
+
+	sps->poc_type = get_ue_golomb_31(gb);
+	if (sps->poc_type == 0) { // FIXME #define
+		u32 t = get_ue_golomb(gb);
+		if (t > 12) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+				"log2_max_poc_lsb (%d) is out of range\n", t);
+			goto fail;
+		}
+		sps->log2_max_poc_lsb = t + 4;
+	} else if (sps->poc_type == 1) { // FIXME #define
+		sps->delta_pic_order_always_zero_flag	= get_bits1(gb);
+		sps->offset_for_non_ref_pic		= get_se_golomb_long(gb);
+		sps->offset_for_top_to_bottom_field	= get_se_golomb_long(gb);
+
+		sps->poc_cycle_length = get_ue_golomb(gb);
+		if ((u32)sps->poc_cycle_length >= ARRAY_SIZE(sps->offset_for_ref_frame)) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+				"poc_cycle_length overflow %d\n", sps->poc_cycle_length);
+			goto fail;
+		}
+
+		for (i = 0; i < sps->poc_cycle_length; i++)
+			sps->offset_for_ref_frame[i] = get_se_golomb_long(gb);
+	} else if (sps->poc_type != 2) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"illegal POC type %d\n", sps->poc_type);
+		goto fail;
+	}
+
+	sps->ref_frame_count = get_ue_golomb_31(gb);
+	if (sps->ref_frame_count > MAX_DELAYED_PIC_COUNT) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"too many reference frames %d\n", sps->ref_frame_count);
+		goto fail;
+	}
+	sps->gaps_in_frame_num_allowed_flag = get_bits1(gb);
+	sps->mb_width	= get_ue_golomb(gb) + 1;
+	sps->mb_height	= get_ue_golomb(gb) + 1;
+
+	sps->frame_mbs_only_flag = get_bits1(gb);
+
+	if (sps->mb_height >= INT_MAX / 2U) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "height overflow\n");
+		goto fail;
+	}
+	sps->mb_height *= 2 - sps->frame_mbs_only_flag;
+
+	if (!sps->frame_mbs_only_flag)
+		sps->mb_aff = get_bits1(gb);
+	else
+		sps->mb_aff = 0;
+
+	if ((u32)sps->mb_width  >= INT_MAX / 16 ||
+		(u32)sps->mb_height >= INT_MAX / 16) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"mb_width/height overflow\n");
+		goto fail;
+	}
+
+	sps->direct_8x8_inference_flag = get_bits1(gb);
+
+	sps->crop = get_bits1(gb);
+	if (sps->crop) {
+		u32 crop_left	= get_ue_golomb(gb);
+		u32 crop_right	= get_ue_golomb(gb);
+		u32 crop_top	= get_ue_golomb(gb);
+		u32 crop_bottom	= get_ue_golomb(gb);
+		int width	= 16 * sps->mb_width;
+		int height	= 16 * sps->mb_height;
+		int vsub	= (sps->chroma_format_idc == 1) ? 1 : 0;
+		int hsub	= (sps->chroma_format_idc == 1 || sps->chroma_format_idc == 2) ? 1 : 0;
+		int step_x	= 1 << hsub;
+		int step_y	= (2 - sps->frame_mbs_only_flag) << vsub;
+
+		if (crop_left > (u32)INT_MAX / 4 / step_x ||
+			crop_right > (u32)INT_MAX / 4 / step_x ||
+			crop_top > (u32)INT_MAX / 4 / step_y ||
+			crop_bottom > (u32)INT_MAX / 4 / step_y ||
+			(crop_left + crop_right ) * step_x >= width ||
+			(crop_top + crop_bottom) * step_y >= height) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+				"crop values invalid %u %u %u %u / %d %d\n",
+				crop_left, crop_right, crop_top, crop_bottom, width, height);
+			goto fail;
+		}
+
+		sps->crop_left	= crop_left * step_x;
+		sps->crop_right	= crop_right * step_x;
+		sps->crop_top	= crop_top * step_y;
+		sps->crop_bottom = crop_bottom * step_y;
+	} else {
+		sps->crop_left	=
+		sps->crop_right	=
+		sps->crop_top	=
+		sps->crop_bottom =
+		sps->crop	= 0;
+	}
+
+	sps->vui_parameters_present_flag = get_bits1(gb);
+	if (sps->vui_parameters_present_flag) {
+		int ret = decode_vui_parameters(gb,  sps);
+		if (ret < 0)
+			goto fail;
+	}
+
+	if (get_bits_left(gb) < 0) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"Overread %s by %d bits\n",
+			sps->vui_parameters_present_flag ? "VUI" : "SPS", -get_bits_left(gb));
+		/*goto out;*/
+	}
+
+#if 0
+	/* if the maximum delay is not stored in the SPS, derive it based on the level */
+	if (!sps->bitstream_restriction_flag && sps->ref_frame_count) {
+		sps->num_reorder_frames = MAX_DELAYED_PIC_COUNT - 1;
+		for (i = 0; i < ARRAY_SIZE(level_max_dpb_mbs); i++) {
+			if (level_max_dpb_mbs[i][0] == sps->level_idc) {
+				sps->num_reorder_frames =
+					MIN(level_max_dpb_mbs[i][1] / (sps->mb_width * sps->mb_height),
+						sps->num_reorder_frames);
+				break;
+			}
+		}
+	}
+#endif
+
+	sps->num_reorder_frames = MAX_DELAYED_PIC_COUNT - 1;
+	for (i = 0; i < ARRAY_SIZE(level_max_dpb_mbs); i++) {
+		if (level_max_dpb_mbs[i][0] == sps->level_idc) {
+			sps->num_reorder_frames =
+				MIN(level_max_dpb_mbs[i][1] / (sps->mb_width * sps->mb_height),
+					sps->num_reorder_frames);
+			sps->num_reorder_frames += 1;
+			if (sps->max_dec_frame_buffering > sps->num_reorder_frames)
+				sps->num_reorder_frames = sps->max_dec_frame_buffering;
+			break;
+		}
+	}
+
+	if ((sps->bitstream_restriction_flag) &&
+		(sps->max_dec_frame_buffering <
+		sps->num_reorder_frames)) {
+		sps->num_reorder_frames = sps->max_dec_frame_buffering;
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER,
+			"set reorder_pic_num to %d\n",
+			sps->num_reorder_frames);
+	}
+
+	if (!sps->sar.den)
+		sps->sar.den = 1;
+/*out:*/
+	if (1) {
+		static const char csp[4][5] = { "Gray", "420", "422", "444" };
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER,
+			"sps:%u profile:%d/%d poc:%d ref:%d %dx%d %s %s crop:%u/%u/%u/%u %s %s %d/%d b%d reo:%d\n",
+			sps_id, sps->profile_idc, sps->level_idc,
+			sps->poc_type,
+			sps->ref_frame_count,
+			sps->mb_width, sps->mb_height,
+			sps->frame_mbs_only_flag ? "FRM" : (sps->mb_aff ? "MB-AFF" : "PIC-AFF"),
+			sps->direct_8x8_inference_flag ? "8B8" : "",
+			sps->crop_left, sps->crop_right,
+			sps->crop_top, sps->crop_bottom,
+			sps->vui_parameters_present_flag ? "VUI" : "",
+			csp[sps->chroma_format_idc],
+			sps->timing_info_present_flag ? sps->num_units_in_tick : 0,
+			sps->timing_info_present_flag ? sps->time_scale : 0,
+			sps->bit_depth_luma,
+			sps->bitstream_restriction_flag ? sps->num_reorder_frames : -1);
+	}
+
+	return 0;
+
+fail:
+	return -1;
+}
+
+static const char *h264_nal_type_name[32] = {
+	"Unspecified 0", //H264_NAL_UNSPECIFIED
+	"Coded slice of a non-IDR picture", // H264_NAL_SLICE
+	"Coded slice data partition A", // H264_NAL_DPA
+	"Coded slice data partition B", // H264_NAL_DPB
+	"Coded slice data partition C", // H264_NAL_DPC
+	"IDR", // H264_NAL_IDR_SLICE
+	"SEI", // H264_NAL_SEI
+	"SPS", // H264_NAL_SPS
+	"PPS", // H264_NAL_PPS
+	"AUD", // H264_NAL_AUD
+	"End of sequence", // H264_NAL_END_SEQUENCE
+	"End of stream", // H264_NAL_END_STREAM
+	"Filler data", // H264_NAL_FILLER_DATA
+	"SPS extension", // H264_NAL_SPS_EXT
+	"Prefix", // H264_NAL_PREFIX
+	"Subset SPS", // H264_NAL_SUB_SPS
+	"Depth parameter set", // H264_NAL_DPS
+	"Reserved 17", // H264_NAL_RESERVED17
+	"Reserved 18", // H264_NAL_RESERVED18
+	"Auxiliary coded picture without partitioning", // H264_NAL_AUXILIARY_SLICE
+	"Slice extension", // H264_NAL_EXTEN_SLICE
+	"Slice extension for a depth view or a 3D-AVC texture view", // H264_NAL_DEPTH_EXTEN_SLICE
+	"Reserved 22", // H264_NAL_RESERVED22
+	"Reserved 23", // H264_NAL_RESERVED23
+	"Unspecified 24", // H264_NAL_UNSPECIFIED24
+	"Unspecified 25", // H264_NAL_UNSPECIFIED25
+	"Unspecified 26", // H264_NAL_UNSPECIFIED26
+	"Unspecified 27", // H264_NAL_UNSPECIFIED27
+	"Unspecified 28", // H264_NAL_UNSPECIFIED28
+	"Unspecified 29", // H264_NAL_UNSPECIFIED29
+	"Unspecified 30", // H264_NAL_UNSPECIFIED30
+	"Unspecified 31", // H264_NAL_UNSPECIFIED31
+};
+
+static const char *h264_nal_unit_name(int nal_type)
+{
+	return h264_nal_type_name[nal_type];
+}
+
+static int decode_extradata_ps(u8 *data, int size, struct h264_param_sets *ps)
+{
+	int ret = 0;
+	struct get_bits_context gb;
+	u32 src_len, rbsp_size = 0;
+	u8 *rbsp_buf = NULL;
+	int ref_idc, nalu_pos;
+	u32 nal_type;
+	u8 *p = data;
+	u32 len = size;
+
+	nalu_pos = find_start_code(p, len);
+	if (nalu_pos < 0)
+		return -1;
+
+	src_len = calc_nal_len(p + nalu_pos, size - nalu_pos);
+	rbsp_buf = nal_unit_extract_rbsp(p + nalu_pos, src_len, &rbsp_size);
+	if (rbsp_buf == NULL)
+		return -ENOMEM;
+
+	ret = init_get_bits8(&gb, rbsp_buf, rbsp_size);
+	if (ret < 0)
+		goto out;
+
+	if (get_bits1(&gb) != 0) {
+		ret = -1;
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"invalid h264 data,return!\n");
+		goto out;
+	}
+
+	ref_idc	 = get_bits(&gb, 2);
+	nal_type = get_bits(&gb, 5);
+
+	v4l_dbg(0, V4L_DEBUG_CODEC_PARSER,
+		"nal_unit_type: %d(%s), nal_ref_idc: %d\n",
+		nal_type, h264_nal_unit_name(nal_type), ref_idc);
+
+	switch (nal_type) {
+	case H264_NAL_SPS:
+		ret = aml_h264_parser_sps(&gb, &ps->sps);
+		if (ret < 0)
+			goto out;
+		ps->sps_parsed = true;
+		break;
+	/*case H264_NAL_PPS:
+		ret = ff_h264_decode_picture_parameter_set(&gb, &ps->pps, rbsp_size);
+		if (ret < 0)
+			goto fail;
+		ps->pps_parsed = true;
+		break;*/
+	default:
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"Unsupport parser nal type (%s).\n",
+			h264_nal_unit_name(nal_type));
+		break;
+	}
+
+out:
+	vfree(rbsp_buf);
+
+	return ret;
+}
+
+int h264_decode_extradata_ps(u8 *buf, int size, struct h264_param_sets *ps)
+{
+	int ret = 0, i = 0, j = 0;
+	u8 *p = buf;
+	int len = size;
+
+	for (i = 4; i < size; i++) {
+		j = find_start_code(p, len);
+		if (j > 0) {
+			len = size - (p - buf);
+			ret = decode_extradata_ps(p, len, ps);
+			if (ret) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+					"parse extra data failed. err: %d\n", ret);
+				return ret;
+			}
+
+			if (ps->sps_parsed)
+				break;
+
+			p += j;
+		}
+		p++;
+	}
+
+	return ret;
+}
+
+
diff --git a/drivers/amvdec_ports/decoder/aml_h264_parser.h b/drivers/amvdec_ports/decoder/aml_h264_parser.h
new file mode 100644
index 0000000..def00dd
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/aml_h264_parser.h
@@ -0,0 +1,210 @@
+/*
+ * drivers/amvdec_ports/decoder/aml_h264_parser.h
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef AML_H264_PARSER_H
+#define AML_H264_PARSER_H
+
+#include "../aml_vcodec_drv.h"
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+#include "../utils/pixfmt.h"
+#endif
+
+#define QP_MAX_NUM (51 + 6 * 6)           // The maximum supported qp
+
+/* NAL unit types */
+enum {
+	H264_NAL_SLICE           = 1,
+	H264_NAL_DPA             = 2,
+	H264_NAL_DPB             = 3,
+	H264_NAL_DPC             = 4,
+	H264_NAL_IDR_SLICE       = 5,
+	H264_NAL_SEI             = 6,
+	H264_NAL_SPS             = 7,
+	H264_NAL_PPS             = 8,
+	H264_NAL_AUD             = 9,
+	H264_NAL_END_SEQUENCE    = 10,
+	H264_NAL_END_STREAM      = 11,
+	H264_NAL_FILLER_DATA     = 12,
+	H264_NAL_SPS_EXT         = 13,
+	H264_NAL_AUXILIARY_SLICE = 19,
+};
+
+enum {
+	// 7.4.2.1.1: seq_parameter_set_id is in [0, 31].
+	H264_MAX_SPS_COUNT = 32,
+	// 7.4.2.2: pic_parameter_set_id is in [0, 255].
+	H264_MAX_PPS_COUNT = 256,
+
+	// A.3: MaxDpbFrames is bounded above by 16.
+	H264_MAX_DPB_FRAMES = 16,
+	// 7.4.2.1.1: max_num_ref_frames is in [0, MaxDpbFrames], and
+	// each reference frame can have two fields.
+	H264_MAX_REFS       = 2 * H264_MAX_DPB_FRAMES,
+
+	// 7.4.3.1: modification_of_pic_nums_idc is not equal to 3 at most
+	// num_ref_idx_lN_active_minus1 + 1 times (that is, once for each
+	// possible reference), then equal to 3 once.
+	H264_MAX_RPLM_COUNT = H264_MAX_REFS + 1,
+
+	// 7.4.3.3: in the worst case, we begin with a full short-term
+	// reference picture list.  Each picture in turn is moved to the
+	// long-term list (type 3) and then discarded from there (type 2).
+	// Then, we set the length of the long-term list (type 4), mark
+	// the current picture as long-term (type 6) and terminate the
+	// process (type 0).
+	H264_MAX_MMCO_COUNT = H264_MAX_REFS * 2 + 3,
+
+	// A.2.1, A.2.3: profiles supporting FMO constrain
+	// num_slice_groups_minus1 to be in [0, 7].
+	H264_MAX_SLICE_GROUPS = 8,
+
+	// E.2.2: cpb_cnt_minus1 is in [0, 31].
+	H264_MAX_CPB_CNT = 32,
+
+	// A.3: in table A-1 the highest level allows a MaxFS of 139264.
+	H264_MAX_MB_PIC_SIZE = 139264,
+	// A.3.1, A.3.2: PicWidthInMbs and PicHeightInMbs are constrained
+	// to be not greater than sqrt(MaxFS * 8).  Hence height/width are
+	// bounded above by sqrt(139264 * 8) = 1055.5 macroblocks.
+	H264_MAX_MB_WIDTH    = 1055,
+	H264_MAX_MB_HEIGHT   = 1055,
+	H264_MAX_WIDTH       = H264_MAX_MB_WIDTH  * 16,
+	H264_MAX_HEIGHT      = H264_MAX_MB_HEIGHT * 16,
+};
+
+/**
+ * Rational number (pair of numerator and denominator).
+ */
+struct rational{
+	int num; ///< Numerator
+	int den; ///< Denominator
+};
+
+/**
+ * Sequence parameter set
+ */
+struct h264_SPS_t {
+	u32 sps_id;
+	int profile_idc;
+	int level_idc;
+	int chroma_format_idc;
+	int transform_bypass;              ///< qpprime_y_zero_transform_bypass_flag
+	int log2_max_frame_num;            ///< log2_max_frame_num_minus4 + 4
+	int poc_type;                      ///< pic_order_cnt_type
+	int log2_max_poc_lsb;              ///< log2_max_pic_order_cnt_lsb_minus4
+	int delta_pic_order_always_zero_flag;
+	int offset_for_non_ref_pic;
+	int offset_for_top_to_bottom_field;
+	int poc_cycle_length;              ///< num_ref_frames_in_pic_order_cnt_cycle
+	int ref_frame_count;               ///< num_ref_frames
+	int gaps_in_frame_num_allowed_flag;
+	int mb_width;                      ///< pic_width_in_mbs_minus1 + 1
+	///< (pic_height_in_map_units_minus1 + 1) * (2 - frame_mbs_only_flag)
+	int mb_height;
+	int frame_mbs_only_flag;
+	int mb_aff;                        ///< mb_adaptive_frame_field_flag
+	int direct_8x8_inference_flag;
+	int crop;                          ///< frame_cropping_flag
+
+	/* those 4 are already in luma samples */
+	u32 crop_left;            ///< frame_cropping_rect_left_offset
+	u32 crop_right;           ///< frame_cropping_rect_right_offset
+	u32 crop_top;             ///< frame_cropping_rect_top_offset
+	u32 crop_bottom;          ///< frame_cropping_rect_bottom_offset
+	int vui_parameters_present_flag;
+	struct rational sar;
+	int video_signal_type_present_flag;
+	int full_range;
+	int colour_description_present_flag;
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+	enum AVColorPrimaries color_primaries;
+	enum AVColorTransferCharacteristic color_trc;
+	enum AVColorSpace colorspace;
+#endif
+	int timing_info_present_flag;
+	u32 num_units_in_tick;
+	u32 time_scale;
+	int fixed_frame_rate_flag;
+	int32_t offset_for_ref_frame[256];
+	int bitstream_restriction_flag;
+	int num_reorder_frames;
+	int max_dec_frame_buffering;
+	int scaling_matrix_present;
+	u8 scaling_matrix4[6][16];
+	u8 scaling_matrix8[6][64];
+	int nal_hrd_parameters_present_flag;
+	int vcl_hrd_parameters_present_flag;
+	int pic_struct_present_flag;
+	int time_offset_length;
+	int cpb_cnt;                          ///< See H.264 E.1.2
+	int initial_cpb_removal_delay_length; ///< initial_cpb_removal_delay_length_minus1 + 1
+	int cpb_removal_delay_length;         ///< cpb_removal_delay_length_minus1 + 1
+	int dpb_output_delay_length;          ///< dpb_output_delay_length_minus1 + 1
+	int bit_depth_luma;                   ///< bit_depth_luma_minus8 + 8
+	int bit_depth_chroma;                 ///< bit_depth_chroma_minus8 + 8
+	int residual_color_transform_flag;    ///< residual_colour_transform_flag
+	int constraint_set_flags;             ///< constraint_set[0-3]_flag
+} ;
+
+/**
+ * Picture parameter set
+ */
+struct h264_PPS_t {
+	u32 sps_id;
+	int cabac;                  ///< entropy_coding_mode_flag
+	int pic_order_present;      ///< pic_order_present_flag
+	int slice_group_count;      ///< num_slice_groups_minus1 + 1
+	int mb_slice_group_map_type;
+	u32 ref_count[2];  ///< num_ref_idx_l0/1_active_minus1 + 1
+	int weighted_pred;          ///< weighted_pred_flag
+	int weighted_bipred_idc;
+	int init_qp;                ///< pic_init_qp_minus26 + 26
+	int init_qs;                ///< pic_init_qs_minus26 + 26
+	int chroma_qp_index_offset[2];
+	int deblocking_filter_parameters_present; ///< deblocking_filter_parameters_present_flag
+	int constrained_intra_pred;     ///< constrained_intra_pred_flag
+	int redundant_pic_cnt_present;  ///< redundant_pic_cnt_present_flag
+	int transform_8x8_mode;         ///< transform_8x8_mode_flag
+	u8 scaling_matrix4[6][16];
+	u8 scaling_matrix8[6][64];
+	u8 chroma_qp_table[2][87+1];  ///< pre-scaled (with chroma_qp_index_offset) version of qp_table
+	int chroma_qp_diff;
+	u8 data[4096];
+	int data_size;
+
+	u32 dequant4_buffer[6][87 + 1][16];
+	u32 dequant8_buffer[6][87 + 1][64];
+	u32(*dequant4_coeff[6])[16];
+	u32(*dequant8_coeff[6])[64];
+} ;
+
+struct h264_param_sets {
+	bool sps_parsed;
+	bool pps_parsed;
+	struct h264_SPS_t sps;
+	struct h264_PPS_t pps;
+};
+
+
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+int h264_decode_extradata_ps(u8 *data, int size, struct h264_param_sets *ps);
+#else
+inline int h264_decode_extradata_ps(u8 *data, int size, struct h264_param_sets *ps) { return -1; }
+#endif
+
+#endif /* AML_H264_PARSER_H */
+
diff --git a/drivers/amvdec_ports/decoder/aml_hevc_parser.c b/drivers/amvdec_ports/decoder/aml_hevc_parser.c
new file mode 100644
index 0000000..24977a8
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/aml_hevc_parser.c
@@ -0,0 +1,1282 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+
+#include "aml_hevc_parser.h"
+#include "../utils/get_bits.h"
+#include "../utils/put_bits.h"
+#include "../utils/golomb.h"
+#include "../utils/common.h"
+#include "utils.h"
+
+const u8 ff_hevc_diag_scan4x4_x[16] = {
+	0, 0, 1, 0,
+	1, 2, 0, 1,
+	2, 3, 1, 2,
+	3, 2, 3, 3,
+};
+
+const u8 ff_hevc_diag_scan4x4_y[16] = {
+	0, 1, 0, 2,
+	1, 0, 3, 2,
+	1, 0, 3, 2,
+	1, 3, 2, 3,
+};
+
+const u8 ff_hevc_diag_scan8x8_x[64] = {
+	0, 0, 1, 0,
+	1, 2, 0, 1,
+	2, 3, 0, 1,
+	2, 3, 4, 0,
+	1, 2, 3, 4,
+	5, 0, 1, 2,
+	3, 4, 5, 6,
+	0, 1, 2, 3,
+	4, 5, 6, 7,
+	1, 2, 3, 4,
+	5, 6, 7, 2,
+	3, 4, 5, 6,
+	7, 3, 4, 5,
+	6, 7, 4, 5,
+	6, 7, 5, 6,
+	7, 6, 7, 7,
+};
+
+const u8 ff_hevc_diag_scan8x8_y[64] = {
+	0, 1, 0, 2,
+	1, 0, 3, 2,
+	1, 0, 4, 3,
+	2, 1, 0, 5,
+	4, 3, 2, 1,
+	0, 6, 5, 4,
+	3, 2, 1, 0,
+	7, 6, 5, 4,
+	3, 2, 1, 0,
+	7, 6, 5, 4,
+	3, 2, 1, 7,
+	6, 5, 4, 3,
+	2, 7, 6, 5,
+	4, 3, 7, 6,
+	5, 4, 7, 6,
+	5, 7, 6, 7,
+};
+
+static const u8 default_scaling_list_intra[] = {
+	16, 16, 16, 16, 17, 18, 21, 24,
+	16, 16, 16, 16, 17, 19, 22, 25,
+	16, 16, 17, 18, 20, 22, 25, 29,
+	16, 16, 18, 21, 24, 27, 31, 36,
+	17, 17, 20, 24, 30, 35, 41, 47,
+	18, 19, 22, 27, 35, 44, 54, 65,
+	21, 22, 25, 31, 41, 54, 70, 88,
+	24, 25, 29, 36, 47, 65, 88, 115
+};
+
+static const u8 default_scaling_list_inter[] = {
+	16, 16, 16, 16, 17, 18, 20, 24,
+	16, 16, 16, 17, 18, 20, 24, 25,
+	16, 16, 17, 18, 20, 24, 25, 28,
+	16, 17, 18, 20, 24, 25, 28, 33,
+	17, 18, 20, 24, 25, 28, 33, 41,
+	18, 20, 24, 25, 28, 33, 41, 54,
+	20, 24, 25, 28, 33, 41, 54, 71,
+	24, 25, 28, 33, 41, 54, 71, 91
+};
+
+static const struct AVRational vui_sar[] = {
+	{  0,   1 },
+	{  1,   1 },
+	{ 12,  11 },
+	{ 10,  11 },
+	{ 16,  11 },
+	{ 40,  33 },
+	{ 24,  11 },
+	{ 20,  11 },
+	{ 32,  11 },
+	{ 80,  33 },
+	{ 18,  11 },
+	{ 15,  11 },
+	{ 64,  33 },
+	{ 160, 99 },
+	{  4,   3 },
+	{  3,   2 },
+	{  2,   1 },
+};
+
+static const u8 hevc_sub_width_c[] = {
+	1, 2, 2, 1
+};
+
+static const u8 hevc_sub_height_c[] = {
+	1, 2, 1, 1
+};
+
+static int decode_profile_tier_level(struct get_bits_context *gb, struct PTLCommon *ptl)
+{
+	int i;
+
+	if (get_bits_left(gb) < 2+1+5 + 32 + 4 + 16 + 16 + 12)
+		return -1;
+
+	ptl->profile_space = get_bits(gb, 2);
+	ptl->tier_flag     = get_bits1(gb);
+	ptl->profile_idc   = get_bits(gb, 5);
+	if (ptl->profile_idc == FF_PROFILE_HEVC_MAIN)
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Main profile bitstream\n");
+	else if (ptl->profile_idc == FF_PROFILE_HEVC_MAIN_10)
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Main 10 profile bitstream\n");
+	else if (ptl->profile_idc == FF_PROFILE_HEVC_MAIN_STILL_PICTURE)
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Main Still Picture profile bitstream\n");
+	else if (ptl->profile_idc == FF_PROFILE_HEVC_REXT)
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Range Extension profile bitstream\n");
+	else
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Unknown HEVC profile: %d\n", ptl->profile_idc);
+
+	for (i = 0; i < 32; i++) {
+		ptl->profile_compatibility_flag[i] = get_bits1(gb);
+
+		if (ptl->profile_idc == 0 && i > 0 && ptl->profile_compatibility_flag[i])
+			ptl->profile_idc = i;
+	}
+	ptl->progressive_source_flag    = get_bits1(gb);
+	ptl->interlaced_source_flag     = get_bits1(gb);
+	ptl->non_packed_constraint_flag = get_bits1(gb);
+	ptl->frame_only_constraint_flag = get_bits1(gb);
+
+	skip_bits(gb, 16); // XXX_reserved_zero_44bits[0..15]
+	skip_bits(gb, 16); // XXX_reserved_zero_44bits[16..31]
+	skip_bits(gb, 12); // XXX_reserved_zero_44bits[32..43]
+
+	return 0;
+}
+
+static int parse_ptl(struct get_bits_context *gb, struct PTL *ptl, int max_num_sub_layers)
+{
+	int i;
+	if (decode_profile_tier_level(gb, &ptl->general_ptl) < 0 ||
+		get_bits_left(gb) < 8 + (8*2 * (max_num_sub_layers - 1 > 0))) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "PTL information too short\n");
+		return -1;
+	}
+
+	ptl->general_ptl.level_idc = get_bits(gb, 8);
+
+	for (i = 0; i < max_num_sub_layers - 1; i++) {
+		ptl->sub_layer_profile_present_flag[i] = get_bits1(gb);
+		ptl->sub_layer_level_present_flag[i]   = get_bits1(gb);
+	}
+
+	if (max_num_sub_layers - 1> 0)
+		for (i = max_num_sub_layers - 1; i < 8; i++)
+			skip_bits(gb, 2); // reserved_zero_2bits[i]
+	for (i = 0; i < max_num_sub_layers - 1; i++) {
+		if (ptl->sub_layer_profile_present_flag[i] &&
+			decode_profile_tier_level(gb, &ptl->sub_layer_ptl[i]) < 0) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "PTL information for sublayer %i too short\n", i);
+			return -1;
+		}
+		if (ptl->sub_layer_level_present_flag[i]) {
+			if (get_bits_left(gb) < 8) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Not enough data for sublayer %i level_idc\n", i);
+				return -1;
+			} else
+				ptl->sub_layer_ptl[i].level_idc = get_bits(gb, 8);
+		}
+	}
+
+	return 0;
+}
+
+static void decode_sublayer_hrd(struct get_bits_context *gb,
+	u32 nb_cpb, int subpic_params_present)
+{
+	int i;
+
+	for (i = 0; i < nb_cpb; i++) {
+		get_ue_golomb_long(gb); // bit_rate_value_minus1
+		get_ue_golomb_long(gb); // cpb_size_value_minus1
+
+		if (subpic_params_present) {
+			get_ue_golomb_long(gb); // cpb_size_du_value_minus1
+			get_ue_golomb_long(gb); // bit_rate_du_value_minus1
+		}
+		skip_bits1(gb); // cbr_flag
+	}
+}
+
+static int decode_hrd(struct get_bits_context *gb,
+	int common_inf_present, int max_sublayers)
+{
+	int nal_params_present = 0, vcl_params_present = 0;
+	int subpic_params_present = 0;
+	int i;
+
+	if (common_inf_present) {
+		nal_params_present = get_bits1(gb);
+		vcl_params_present = get_bits1(gb);
+
+		if (nal_params_present || vcl_params_present) {
+			subpic_params_present = get_bits1(gb);
+
+			if (subpic_params_present) {
+				skip_bits(gb, 8); // tick_divisor_minus2
+				skip_bits(gb, 5); // du_cpb_removal_delay_increment_length_minus1
+				skip_bits(gb, 1); // sub_pic_cpb_params_in_pic_timing_sei_flag
+				skip_bits(gb, 5); // dpb_output_delay_du_length_minus1
+			}
+
+			skip_bits(gb, 4); // bit_rate_scale
+			skip_bits(gb, 4); // cpb_size_scale
+
+			if (subpic_params_present)
+				skip_bits(gb, 4);  // cpb_size_du_scale
+
+			skip_bits(gb, 5); // initial_cpb_removal_delay_length_minus1
+			skip_bits(gb, 5); // au_cpb_removal_delay_length_minus1
+			skip_bits(gb, 5); // dpb_output_delay_length_minus1
+		}
+	}
+
+	for (i = 0; i < max_sublayers; i++) {
+		int low_delay = 0;
+		u32 nb_cpb = 1;
+		int fixed_rate = get_bits1(gb);
+
+		if (!fixed_rate)
+			fixed_rate = get_bits1(gb);
+
+		if (fixed_rate)
+			get_ue_golomb_long(gb);  // elemental_duration_in_tc_minus1
+		else
+			low_delay = get_bits1(gb);
+
+		if (!low_delay) {
+			nb_cpb = get_ue_golomb_long(gb) + 1;
+			if (nb_cpb < 1 || nb_cpb > 32) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "nb_cpb %d invalid\n", nb_cpb);
+				return -1;
+			}
+		}
+
+		if (nal_params_present)
+			decode_sublayer_hrd(gb, nb_cpb, subpic_params_present);
+		if (vcl_params_present)
+			decode_sublayer_hrd(gb, nb_cpb, subpic_params_present);
+	}
+	return 0;
+}
+
+int ff_hevc_parse_vps(struct get_bits_context *gb, struct h265_VPS_t *vps)
+{
+	int i,j;
+	int vps_id = 0;
+
+	v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Decoding VPS\n");
+
+	vps_id = get_bits(gb, 4);
+	if (vps_id >= HEVC_MAX_VPS_COUNT) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "VPS id out of range: %d\n", vps_id);
+		goto err;
+	}
+
+	if (get_bits(gb, 2) != 3) { // vps_reserved_three_2bits
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "vps_reserved_three_2bits is not three\n");
+		goto err;
+	}
+
+	vps->vps_max_layers	= get_bits(gb, 6) + 1;
+	vps->vps_max_sub_layers	= get_bits(gb, 3) + 1;
+	vps->vps_temporal_id_nesting_flag = get_bits1(gb);
+
+	if (get_bits(gb, 16) != 0xffff) { // vps_reserved_ffff_16bits
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "vps_reserved_ffff_16bits is not 0xffff\n");
+		goto err;
+	}
+
+	if (vps->vps_max_sub_layers > HEVC_MAX_SUB_LAYERS) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "vps_max_sub_layers out of range: %d\n",
+			vps->vps_max_sub_layers);
+		goto err;
+	}
+
+	if (parse_ptl(gb, &vps->ptl, vps->vps_max_sub_layers) < 0)
+		goto err;
+
+	vps->vps_sub_layer_ordering_info_present_flag = get_bits1(gb);
+
+	i = vps->vps_sub_layer_ordering_info_present_flag ? 0 : vps->vps_max_sub_layers - 1;
+	for (; i < vps->vps_max_sub_layers; i++) {
+		vps->vps_max_dec_pic_buffering[i]	= get_ue_golomb_long(gb) + 1;
+		vps->vps_num_reorder_pics[i]		= get_ue_golomb_long(gb);
+		vps->vps_max_latency_increase[i]	= get_ue_golomb_long(gb) - 1;
+
+		if (vps->vps_max_dec_pic_buffering[i] > HEVC_MAX_DPB_SIZE || !vps->vps_max_dec_pic_buffering[i]) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "vps_max_dec_pic_buffering_minus1 out of range: %d\n",
+				vps->vps_max_dec_pic_buffering[i] - 1);
+			goto err;
+		}
+		if (vps->vps_num_reorder_pics[i] > vps->vps_max_dec_pic_buffering[i] - 1) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "vps_max_num_reorder_pics out of range: %d\n",
+				vps->vps_num_reorder_pics[i]);
+			goto err;
+		}
+	}
+
+	vps->vps_max_layer_id   = get_bits(gb, 6);
+	vps->vps_num_layer_sets = get_ue_golomb_long(gb) + 1;
+	if (vps->vps_num_layer_sets < 1 || vps->vps_num_layer_sets > 1024 ||
+		(vps->vps_num_layer_sets - 1LL) * (vps->vps_max_layer_id + 1LL) > get_bits_left(gb)) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "too many layer_id_included_flags\n");
+		goto err;
+	}
+
+	for (i = 1; i < vps->vps_num_layer_sets; i++)
+		for (j = 0; j <= vps->vps_max_layer_id; j++)
+			skip_bits(gb, 1);  // layer_id_included_flag[i][j]
+
+	vps->vps_timing_info_present_flag = get_bits1(gb);
+	if (vps->vps_timing_info_present_flag) {
+		vps->vps_num_units_in_tick	= get_bits_long(gb, 32);
+		vps->vps_time_scale		= get_bits_long(gb, 32);
+		vps->vps_poc_proportional_to_timing_flag = get_bits1(gb);
+		if (vps->vps_poc_proportional_to_timing_flag)
+			vps->vps_num_ticks_poc_diff_one = get_ue_golomb_long(gb) + 1;
+		vps->vps_num_hrd_parameters = get_ue_golomb_long(gb);
+		if (vps->vps_num_hrd_parameters > (u32)vps->vps_num_layer_sets) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "vps_num_hrd_parameters %d is invalid\n", vps->vps_num_hrd_parameters);
+			goto err;
+		}
+		for (i = 0; i < vps->vps_num_hrd_parameters; i++) {
+			int common_inf_present = 1;
+
+			get_ue_golomb_long(gb); // hrd_layer_set_idx
+			if (i)
+				common_inf_present = get_bits1(gb);
+			decode_hrd(gb, common_inf_present, vps->vps_max_sub_layers);
+		}
+	}
+	get_bits1(gb); /* vps_extension_flag */
+
+	if (get_bits_left(gb) < 0) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Overread VPS by %d bits\n", -get_bits_left(gb));
+		goto err;
+	}
+
+	return 0;
+err:
+	return -1;
+}
+
+static int map_pixel_format(struct h265_SPS_t *sps)
+{
+	/*const AVPixFmtDescriptor *desc;*/
+	switch (sps->bit_depth) {
+	case 8:
+		if (sps->chroma_format_idc == 0) sps->pix_fmt = AV_PIX_FMT_GRAY8;
+		if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P;
+		if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P;
+		if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P;
+		break;
+	case 9:
+		if (sps->chroma_format_idc == 0) sps->pix_fmt = AV_PIX_FMT_GRAY9;
+		if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P9;
+		if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P9;
+		if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P9;
+		break;
+	case 10:
+		if (sps->chroma_format_idc == 0) sps->pix_fmt = AV_PIX_FMT_GRAY10;
+		if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P10;
+		if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P10;
+		if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P10;
+		break;
+	case 12:
+		if (sps->chroma_format_idc == 0) sps->pix_fmt = AV_PIX_FMT_GRAY12;
+		if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P12;
+		if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P12;
+		if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P12;
+		break;
+	default:
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "The following bit-depths are currently specified: 8, 9, 10 and 12 bits, "
+			"chroma_format_idc is %d, depth is %d\n",
+			sps->chroma_format_idc, sps->bit_depth);
+		return -1;
+	}
+
+	/*desc = av_pix_fmt_desc_get(sps->pix_fmt);
+	if (!desc)
+		return AVERROR(EINVAL);
+
+	sps->hshift[0] = sps->vshift[0] = 0;
+	sps->hshift[2] = sps->hshift[1] = desc->log2_chroma_w;
+	sps->vshift[2] = sps->vshift[1] = desc->log2_chroma_h;*/
+
+	sps->pixel_shift = sps->bit_depth > 8;
+
+	return 0;
+}
+
+static void set_default_scaling_list_data(struct ScalingList *sl)
+{
+	int matrixId;
+
+	for (matrixId = 0; matrixId < 6; matrixId++) {
+		// 4x4 default is 16
+		memset(sl->sl[0][matrixId], 16, 16);
+		sl->sl_dc[0][matrixId] = 16; // default for 16x16
+		sl->sl_dc[1][matrixId] = 16; // default for 32x32
+	}
+	memcpy(sl->sl[1][0], default_scaling_list_intra, 64);
+	memcpy(sl->sl[1][1], default_scaling_list_intra, 64);
+	memcpy(sl->sl[1][2], default_scaling_list_intra, 64);
+	memcpy(sl->sl[1][3], default_scaling_list_inter, 64);
+	memcpy(sl->sl[1][4], default_scaling_list_inter, 64);
+	memcpy(sl->sl[1][5], default_scaling_list_inter, 64);
+	memcpy(sl->sl[2][0], default_scaling_list_intra, 64);
+	memcpy(sl->sl[2][1], default_scaling_list_intra, 64);
+	memcpy(sl->sl[2][2], default_scaling_list_intra, 64);
+	memcpy(sl->sl[2][3], default_scaling_list_inter, 64);
+	memcpy(sl->sl[2][4], default_scaling_list_inter, 64);
+	memcpy(sl->sl[2][5], default_scaling_list_inter, 64);
+	memcpy(sl->sl[3][0], default_scaling_list_intra, 64);
+	memcpy(sl->sl[3][1], default_scaling_list_intra, 64);
+	memcpy(sl->sl[3][2], default_scaling_list_intra, 64);
+	memcpy(sl->sl[3][3], default_scaling_list_inter, 64);
+	memcpy(sl->sl[3][4], default_scaling_list_inter, 64);
+	memcpy(sl->sl[3][5], default_scaling_list_inter, 64);
+}
+
+static int scaling_list_data(struct get_bits_context *gb,
+	struct ScalingList *sl, struct h265_SPS_t *sps)
+{
+	u8 scaling_list_pred_mode_flag;
+	int scaling_list_dc_coef[2][6];
+	int size_id, matrix_id, pos;
+	int i;
+
+	for (size_id = 0; size_id < 4; size_id++)
+		for (matrix_id = 0; matrix_id < 6; matrix_id += ((size_id == 3) ? 3 : 1)) {
+			scaling_list_pred_mode_flag = get_bits1(gb);
+			if (!scaling_list_pred_mode_flag) {
+				u32 delta = get_ue_golomb_long(gb);
+				/* Only need to handle non-zero delta. Zero means default,
+				* which should already be in the arrays. */
+				if (delta) {
+					// Copy from previous array.
+					delta *= (size_id == 3) ? 3 : 1;
+					if (matrix_id < delta) {
+						v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid delta in scaling list data: %d.\n", delta);
+						return -1;
+					}
+
+					memcpy(sl->sl[size_id][matrix_id],
+						sl->sl[size_id][matrix_id - delta],
+						size_id > 0 ? 64 : 16);
+					if (size_id > 1)
+						sl->sl_dc[size_id - 2][matrix_id] = sl->sl_dc[size_id - 2][matrix_id - delta];
+				}
+			} else {
+				int next_coef, coef_num;
+				int scaling_list_delta_coef;
+
+				next_coef = 8;
+				coef_num = FFMIN(64, 1 << (4 + (size_id << 1)));
+				if (size_id > 1) {
+					scaling_list_dc_coef[size_id - 2][matrix_id] = get_se_golomb(gb) + 8;
+					next_coef = scaling_list_dc_coef[size_id - 2][matrix_id];
+					sl->sl_dc[size_id - 2][matrix_id] = next_coef;
+				}
+				for (i = 0; i < coef_num; i++) {
+					if (size_id == 0)
+						pos = 4 * ff_hevc_diag_scan4x4_y[i] +
+							ff_hevc_diag_scan4x4_x[i];
+					else
+						pos = 8 * ff_hevc_diag_scan8x8_y[i] +
+							ff_hevc_diag_scan8x8_x[i];
+
+					scaling_list_delta_coef = get_se_golomb(gb);
+					next_coef = (next_coef + 256U + scaling_list_delta_coef) % 256;
+					sl->sl[size_id][matrix_id][pos] = next_coef;
+				}
+			}
+		}
+
+	if (sps->chroma_format_idc == 3) {
+		for (i = 0; i < 64; i++) {
+			sl->sl[3][1][i] = sl->sl[2][1][i];
+			sl->sl[3][2][i] = sl->sl[2][2][i];
+			sl->sl[3][4][i] = sl->sl[2][4][i];
+			sl->sl[3][5][i] = sl->sl[2][5][i];
+		}
+		sl->sl_dc[1][1] = sl->sl_dc[0][1];
+		sl->sl_dc[1][2] = sl->sl_dc[0][2];
+		sl->sl_dc[1][4] = sl->sl_dc[0][4];
+		sl->sl_dc[1][5] = sl->sl_dc[0][5];
+	}
+
+	return 0;
+}
+
+int ff_hevc_decode_short_term_rps(struct get_bits_context *gb,
+	struct ShortTermRPS *rps, const struct h265_SPS_t *sps, int is_slice_header)
+{
+	u8 rps_predict = 0;
+	int delta_poc;
+	int k0 = 0;
+	int k1 = 0;
+	int k  = 0;
+	int i;
+
+	if (rps != sps->st_rps && sps->nb_st_rps)
+		rps_predict = get_bits1(gb);
+
+	if (rps_predict) {
+		const struct ShortTermRPS *rps_ridx;
+		int delta_rps;
+		u32 abs_delta_rps;
+		u8 use_delta_flag = 0;
+		u8 delta_rps_sign;
+
+		if (is_slice_header) {
+			u32 delta_idx = get_ue_golomb_long(gb) + 1;
+			if (delta_idx > sps->nb_st_rps) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid value of delta_idx in slice header RPS: %d > %d.\n",
+					delta_idx, sps->nb_st_rps);
+				return -1;
+			}
+			rps_ridx = &sps->st_rps[sps->nb_st_rps - delta_idx];
+			rps->rps_idx_num_delta_pocs = rps_ridx->num_delta_pocs;
+		} else
+			rps_ridx = &sps->st_rps[rps - sps->st_rps - 1];
+
+		delta_rps_sign = get_bits1(gb);
+		abs_delta_rps  = get_ue_golomb_long(gb) + 1;
+		if (abs_delta_rps < 1 || abs_delta_rps > 32768) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid value of abs_delta_rps: %d\n",
+				abs_delta_rps);
+			return -1;
+		}
+		delta_rps = (1 - (delta_rps_sign << 1)) * abs_delta_rps;
+		for (i = 0; i <= rps_ridx->num_delta_pocs; i++) {
+			int used = rps->used[k] = get_bits1(gb);
+
+			if (!used)
+				use_delta_flag = get_bits1(gb);
+
+			if (used || use_delta_flag) {
+				if (i < rps_ridx->num_delta_pocs)
+					delta_poc = delta_rps + rps_ridx->delta_poc[i];
+				else
+					delta_poc = delta_rps;
+				rps->delta_poc[k] = delta_poc;
+				if (delta_poc < 0)
+					k0++;
+				else
+					k1++;
+				k++;
+			}
+		}
+
+		if (k >= ARRAY_SIZE(rps->used)) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid num_delta_pocs: %d\n", k);
+			return -1;
+		}
+
+		rps->num_delta_pocs	= k;
+		rps->num_negative_pics	= k0;
+		// sort in increasing order (smallest first)
+		if (rps->num_delta_pocs != 0) {
+			int used, tmp;
+			for (i = 1; i < rps->num_delta_pocs; i++) {
+				delta_poc	= rps->delta_poc[i];
+				used		= rps->used[i];
+				for (k = i - 1; k >= 0; k--) {
+				tmp = rps->delta_poc[k];
+					if (delta_poc < tmp) {
+						rps->delta_poc[k + 1]	= tmp;
+						rps->used[k + 1]	= rps->used[k];
+						rps->delta_poc[k]	= delta_poc;
+						rps->used[k]		= used;
+					}
+				}
+			}
+		}
+		if ((rps->num_negative_pics >> 1) != 0) {
+			int used;
+			k = rps->num_negative_pics - 1;
+			// flip the negative values to largest first
+			for (i = 0; i < rps->num_negative_pics >> 1; i++) {
+				delta_poc	= rps->delta_poc[i];
+				used		= rps->used[i];
+				rps->delta_poc[i] = rps->delta_poc[k];
+				rps->used[i]	= rps->used[k];
+				rps->delta_poc[k] = delta_poc;
+				rps->used[k]	= used;
+				k--;
+			}
+		}
+	} else {
+		u32 prev, nb_positive_pics;
+		rps->num_negative_pics	= get_ue_golomb_long(gb);
+		nb_positive_pics	= get_ue_golomb_long(gb);
+
+		if (rps->num_negative_pics >= HEVC_MAX_REFS ||
+			nb_positive_pics >= HEVC_MAX_REFS) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Too many refs in a short term RPS.\n");
+			return -1;
+		}
+
+		rps->num_delta_pocs = rps->num_negative_pics + nb_positive_pics;
+		if (rps->num_delta_pocs) {
+			prev = 0;
+			for (i = 0; i < rps->num_negative_pics; i++) {
+				delta_poc = get_ue_golomb_long(gb) + 1;
+				if (delta_poc < 1 || delta_poc > 32768) {
+					v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid value of delta_poc: %d\n",
+						delta_poc);
+					return -1;
+				}
+				prev -= delta_poc;
+				rps->delta_poc[i] = prev;
+				rps->used[i] = get_bits1(gb);
+			}
+			prev = 0;
+			for (i = 0; i < nb_positive_pics; i++) {
+				delta_poc = get_ue_golomb_long(gb) + 1;
+				if (delta_poc < 1 || delta_poc > 32768) {
+					v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid value of delta_poc: %d\n",
+						delta_poc);
+					return -1;
+				}
+				prev += delta_poc;
+				rps->delta_poc[rps->num_negative_pics + i] = prev;
+				rps->used[rps->num_negative_pics + i] = get_bits1(gb);
+			}
+		}
+	}
+	return 0;
+}
+
+static void decode_vui(struct get_bits_context *gb, struct h265_SPS_t *sps)
+{
+	struct VUI backup_vui, *vui = &sps->vui;
+	struct get_bits_context backup;
+	int sar_present, alt = 0;
+
+	v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Decoding VUI\n");
+
+	sar_present = get_bits1(gb);
+	if (sar_present) {
+		u8 sar_idx = get_bits(gb, 8);
+		if (sar_idx < ARRAY_SIZE(vui_sar))
+			vui->sar = vui_sar[sar_idx];
+		else if (sar_idx == 255) {
+			vui->sar.num = get_bits(gb, 16);
+			vui->sar.den = get_bits(gb, 16);
+		} else
+			v4l_dbg(0, V4L_DEBUG_CODEC_PARSER,
+				"Unknown SAR index: %u.\n", sar_idx);
+	}
+
+	vui->overscan_info_present_flag = get_bits1(gb);
+	if (vui->overscan_info_present_flag)
+		vui->overscan_appropriate_flag = get_bits1(gb);
+
+	vui->video_signal_type_present_flag = get_bits1(gb);
+	if (vui->video_signal_type_present_flag) {
+		vui->video_format		= get_bits(gb, 3);
+		vui->video_full_range_flag	= get_bits1(gb);
+		vui->colour_description_present_flag = get_bits1(gb);
+		if (vui->video_full_range_flag && sps->pix_fmt == AV_PIX_FMT_YUV420P)
+			sps->pix_fmt = AV_PIX_FMT_YUVJ420P;
+		if (vui->colour_description_present_flag) {
+			vui->colour_primaries		= get_bits(gb, 8);
+			vui->transfer_characteristic	= get_bits(gb, 8);
+			vui->matrix_coeffs		= get_bits(gb, 8);
+
+			// Set invalid values to "unspecified"
+			if (!av_color_primaries_name(vui->colour_primaries))
+				vui->colour_primaries = AVCOL_PRI_UNSPECIFIED;
+			if (!av_color_transfer_name(vui->transfer_characteristic))
+				vui->transfer_characteristic = AVCOL_TRC_UNSPECIFIED;
+			if (!av_color_space_name(vui->matrix_coeffs))
+				vui->matrix_coeffs = AVCOL_SPC_UNSPECIFIED;
+			if (vui->matrix_coeffs == AVCOL_SPC_RGB) {
+				switch (sps->pix_fmt) {
+				case AV_PIX_FMT_YUV444P:
+					sps->pix_fmt = AV_PIX_FMT_GBRP;
+					break;
+				case AV_PIX_FMT_YUV444P10:
+					sps->pix_fmt = AV_PIX_FMT_GBRP10;
+					break;
+				case AV_PIX_FMT_YUV444P12:
+					sps->pix_fmt = AV_PIX_FMT_GBRP12;
+					break;
+				}
+			}
+		}
+	}
+
+	vui->chroma_loc_info_present_flag = get_bits1(gb);
+	if (vui->chroma_loc_info_present_flag) {
+		vui->chroma_sample_loc_type_top_field    = get_ue_golomb_long(gb);
+		vui->chroma_sample_loc_type_bottom_field = get_ue_golomb_long(gb);
+	}
+
+	vui->neutra_chroma_indication_flag	= get_bits1(gb);
+	vui->field_seq_flag			= get_bits1(gb);
+	vui->frame_field_info_present_flag	= get_bits1(gb);
+
+	// Backup context in case an alternate header is detected
+	memcpy(&backup, gb, sizeof(backup));
+	memcpy(&backup_vui, vui, sizeof(backup_vui));
+	if (get_bits_left(gb) >= 68 && show_bits_long(gb, 21) == 0x100000) {
+		vui->default_display_window_flag = 0;
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Invalid default display window\n");
+	} else
+		vui->default_display_window_flag = get_bits1(gb);
+
+	if (vui->default_display_window_flag) {
+		int vert_mult  = hevc_sub_height_c[sps->chroma_format_idc];
+		int horiz_mult = hevc_sub_width_c[sps->chroma_format_idc];
+		vui->def_disp_win.left_offset	= get_ue_golomb_long(gb) * horiz_mult;
+		vui->def_disp_win.right_offset	= get_ue_golomb_long(gb) * horiz_mult;
+		vui->def_disp_win.top_offset	= get_ue_golomb_long(gb) *  vert_mult;
+		vui->def_disp_win.bottom_offset	= get_ue_golomb_long(gb) *  vert_mult;
+	}
+
+timing_info:
+	vui->vui_timing_info_present_flag = get_bits1(gb);
+
+	if (vui->vui_timing_info_present_flag) {
+		if (get_bits_left(gb) < 66 && !alt) {
+			// The alternate syntax seem to have timing info located
+			// at where def_disp_win is normally located
+			v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Strange VUI timing information, retrying...\n");
+			memcpy(vui, &backup_vui, sizeof(backup_vui));
+			memcpy(gb, &backup, sizeof(backup));
+			alt = 1;
+			goto timing_info;
+		}
+		vui->vui_num_units_in_tick	= get_bits_long(gb, 32);
+		vui->vui_time_scale		= get_bits_long(gb, 32);
+		if (alt) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Retry got %u/%u fps\n",
+			vui->vui_time_scale, vui->vui_num_units_in_tick);
+		}
+		vui->vui_poc_proportional_to_timing_flag = get_bits1(gb);
+		if (vui->vui_poc_proportional_to_timing_flag)
+			vui->vui_num_ticks_poc_diff_one_minus1 = get_ue_golomb_long(gb);
+		vui->vui_hrd_parameters_present_flag = get_bits1(gb);
+		if (vui->vui_hrd_parameters_present_flag)
+			decode_hrd(gb, 1, sps->max_sub_layers);
+	}
+
+	vui->bitstream_restriction_flag = get_bits1(gb);
+	if (vui->bitstream_restriction_flag) {
+		if (get_bits_left(gb) < 8 && !alt) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Strange VUI bitstream restriction information, retrying"
+				" from timing information...\n");
+			memcpy(vui, &backup_vui, sizeof(backup_vui));
+			memcpy(gb, &backup, sizeof(backup));
+			alt = 1;
+			goto timing_info;
+		}
+		vui->tiles_fixed_structure_flag		= get_bits1(gb);
+		vui->motion_vectors_over_pic_boundaries_flag = get_bits1(gb);
+		vui->restricted_ref_pic_lists_flag	= get_bits1(gb);
+		vui->min_spatial_segmentation_idc	= get_ue_golomb_long(gb);
+		vui->max_bytes_per_pic_denom		= get_ue_golomb_long(gb);
+		vui->max_bits_per_min_cu_denom		= get_ue_golomb_long(gb);
+		vui->log2_max_mv_length_horizontal	= get_ue_golomb_long(gb);
+		vui->log2_max_mv_length_vertical	= get_ue_golomb_long(gb);
+	}
+
+	if (get_bits_left(gb) < 1 && !alt) {
+		// XXX: Alternate syntax when sps_range_extension_flag != 0?
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Overread in VUI, retrying from timing information...\n");
+		memcpy(vui, &backup_vui, sizeof(backup_vui));
+		memcpy(gb, &backup, sizeof(backup));
+		alt = 1;
+		goto timing_info;
+	}
+}
+
+int ff_hevc_parse_sps(struct get_bits_context *gb, struct h265_SPS_t *sps)
+{
+	int i, ret = 0;
+	int log2_diff_max_min_transform_block_size;
+	int bit_depth_chroma, start, vui_present, sublayer_ordering_info;
+	struct HEVCWindow *ow;
+
+	sps->vps_id = get_bits(gb, 4);
+	if (sps->vps_id >= HEVC_MAX_VPS_COUNT) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "VPS id out of range: %d\n", sps->vps_id);
+		return -1;
+	}
+
+	sps->max_sub_layers = get_bits(gb, 3) + 1;
+		if (sps->max_sub_layers > HEVC_MAX_SUB_LAYERS) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "sps_max_sub_layers out of range: %d\n",
+				sps->max_sub_layers);
+		return -1;
+	}
+
+	sps->temporal_id_nesting_flag = get_bits(gb, 1);
+
+	if ((ret = parse_ptl(gb, &sps->ptl, sps->max_sub_layers)) < 0)
+		return ret;
+
+	sps->sps_id = get_ue_golomb_long(gb);
+	if (sps->sps_id >= HEVC_MAX_SPS_COUNT) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "SPS id out of range: %d\n", sps->sps_id);
+		return -1;
+	}
+
+	sps->chroma_format_idc = get_ue_golomb_long(gb);
+	if (sps->chroma_format_idc > 3U) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "chroma_format_idc %d is invalid\n", sps->chroma_format_idc);
+		return -1;
+	}
+
+	if (sps->chroma_format_idc == 3)
+		sps->separate_colour_plane_flag = get_bits1(gb);
+
+	if (sps->separate_colour_plane_flag)
+		sps->chroma_format_idc = 0;
+
+	sps->width	= get_ue_golomb_long(gb);
+	sps->height	= get_ue_golomb_long(gb);
+	if (sps->width > 8192 || sps->height > 8192) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "width or height oversize.\n");
+		return -1;
+	}
+
+	if (get_bits1(gb)) { // pic_conformance_flag
+		int vert_mult  = hevc_sub_height_c[sps->chroma_format_idc];
+		int horiz_mult = hevc_sub_width_c[sps->chroma_format_idc];
+		sps->pic_conf_win.left_offset	= get_ue_golomb_long(gb) * horiz_mult;
+		sps->pic_conf_win.right_offset	= get_ue_golomb_long(gb) * horiz_mult;
+		sps->pic_conf_win.top_offset	= get_ue_golomb_long(gb) *  vert_mult;
+		sps->pic_conf_win.bottom_offset = get_ue_golomb_long(gb) *  vert_mult;
+		sps->output_window = sps->pic_conf_win;
+	}
+
+	sps->bit_depth   = get_ue_golomb_long(gb) + 8;
+	bit_depth_chroma = get_ue_golomb_long(gb) + 8;
+	if (sps->chroma_format_idc && bit_depth_chroma != sps->bit_depth) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Luma bit depth (%d) is different from chroma bit depth (%d), this is unsupported.\n",
+			sps->bit_depth, bit_depth_chroma);
+		return -1;
+	}
+	sps->bit_depth_chroma = bit_depth_chroma;
+
+	ret = map_pixel_format(sps);
+	if (ret < 0)
+		return ret;
+
+	sps->log2_max_poc_lsb = get_ue_golomb_long(gb) + 4;
+		if (sps->log2_max_poc_lsb > 16) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "log2_max_pic_order_cnt_lsb_minus4 out range: %d\n",
+				sps->log2_max_poc_lsb - 4);
+		return -1;
+	}
+
+	sublayer_ordering_info = get_bits1(gb);
+	start = sublayer_ordering_info ? 0 : sps->max_sub_layers - 1;
+	for (i = start; i < sps->max_sub_layers; i++) {
+		sps->temporal_layer[i].max_dec_pic_buffering = get_ue_golomb_long(gb) + 1;
+		sps->temporal_layer[i].num_reorder_pics      = get_ue_golomb_long(gb);
+		sps->temporal_layer[i].max_latency_increase  = get_ue_golomb_long(gb) - 1;
+		if (sps->temporal_layer[i].max_dec_pic_buffering > (u32)HEVC_MAX_DPB_SIZE) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "sps_max_dec_pic_buffering_minus1 out of range: %d\n",
+				sps->temporal_layer[i].max_dec_pic_buffering - 1U);
+			return -1;
+		}
+		if (sps->temporal_layer[i].num_reorder_pics > sps->temporal_layer[i].max_dec_pic_buffering - 1) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "sps_max_num_reorder_pics out of range: %d\n",
+				sps->temporal_layer[i].num_reorder_pics);
+			if (sps->temporal_layer[i].num_reorder_pics > HEVC_MAX_DPB_SIZE - 1) {
+				return -1;
+			}
+			sps->temporal_layer[i].max_dec_pic_buffering = sps->temporal_layer[i].num_reorder_pics + 1;
+		}
+	}
+
+	if (!sublayer_ordering_info) {
+		for (i = 0; i < start; i++) {
+			sps->temporal_layer[i].max_dec_pic_buffering = sps->temporal_layer[start].max_dec_pic_buffering;
+			sps->temporal_layer[i].num_reorder_pics	 = sps->temporal_layer[start].num_reorder_pics;
+			sps->temporal_layer[i].max_latency_increase  = sps->temporal_layer[start].max_latency_increase;
+		}
+	}
+
+	sps->log2_min_cb_size		= get_ue_golomb_long(gb) + 3;
+	sps->log2_diff_max_min_coding_block_size = get_ue_golomb_long(gb);
+	sps->log2_min_tb_size		= get_ue_golomb_long(gb) + 2;
+	log2_diff_max_min_transform_block_size = get_ue_golomb_long(gb);
+	sps->log2_max_trafo_size	= log2_diff_max_min_transform_block_size + sps->log2_min_tb_size;
+
+	if (sps->log2_min_cb_size < 3 || sps->log2_min_cb_size > 30) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid value %d for log2_min_cb_size", sps->log2_min_cb_size);
+		return -1;
+	}
+
+	if (sps->log2_diff_max_min_coding_block_size > 30) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid value %d for log2_diff_max_min_coding_block_size", sps->log2_diff_max_min_coding_block_size);
+		return -1;
+	}
+
+	if (sps->log2_min_tb_size >= sps->log2_min_cb_size || sps->log2_min_tb_size < 2) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid value for log2_min_tb_size");
+		return -1;
+	}
+
+	if (log2_diff_max_min_transform_block_size < 0 || log2_diff_max_min_transform_block_size > 30) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid value %d for log2_diff_max_min_transform_block_size", log2_diff_max_min_transform_block_size);
+		return -1;
+	}
+
+	sps->max_transform_hierarchy_depth_inter = get_ue_golomb_long(gb);
+	sps->max_transform_hierarchy_depth_intra = get_ue_golomb_long(gb);
+
+	sps->scaling_list_enable_flag = get_bits1(gb);
+	if (sps->scaling_list_enable_flag) {
+		set_default_scaling_list_data(&sps->scaling_list);
+
+		if (get_bits1(gb)) {
+			ret = scaling_list_data(gb, &sps->scaling_list, sps);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	sps->amp_enabled_flag	= get_bits1(gb);
+	sps->sao_enabled	= get_bits1(gb);
+
+	sps->pcm_enabled_flag	= get_bits1(gb);
+	if (sps->pcm_enabled_flag) {
+		sps->pcm.bit_depth = get_bits(gb, 4) + 1;
+		sps->pcm.bit_depth_chroma = get_bits(gb, 4) + 1;
+		sps->pcm.log2_min_pcm_cb_size = get_ue_golomb_long(gb) + 3;
+		sps->pcm.log2_max_pcm_cb_size = sps->pcm.log2_min_pcm_cb_size +
+			get_ue_golomb_long(gb);
+		if (FFMAX(sps->pcm.bit_depth, sps->pcm.bit_depth_chroma) > sps->bit_depth) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "PCM bit depth (%d, %d) is greater than normal bit depth (%d)\n",
+				sps->pcm.bit_depth, sps->pcm.bit_depth_chroma, sps->bit_depth);
+			return -1;
+		}
+
+		sps->pcm.loop_filter_disable_flag = get_bits1(gb);
+	}
+
+	sps->nb_st_rps = get_ue_golomb_long(gb);
+	if (sps->nb_st_rps > HEVC_MAX_SHORT_TERM_REF_PIC_SETS) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Too many short term RPS: %d.\n", sps->nb_st_rps);
+		return -1;
+	}
+	for (i = 0; i < sps->nb_st_rps; i++) {
+		if ((ret = ff_hevc_decode_short_term_rps(gb, &sps->st_rps[i], sps, 0)) < 0)
+			return ret;
+	}
+
+	sps->long_term_ref_pics_present_flag = get_bits1(gb);
+	if (sps->long_term_ref_pics_present_flag) {
+		sps->num_long_term_ref_pics_sps = get_ue_golomb_long(gb);
+		if (sps->num_long_term_ref_pics_sps > HEVC_MAX_LONG_TERM_REF_PICS) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Too many long term ref pics: %d.\n",
+				sps->num_long_term_ref_pics_sps);
+			return -1;
+		}
+		for (i = 0; i < sps->num_long_term_ref_pics_sps; i++) {
+			sps->lt_ref_pic_poc_lsb_sps[i] = get_bits(gb, sps->log2_max_poc_lsb);
+			sps->used_by_curr_pic_lt_sps_flag[i] = get_bits1(gb);
+		}
+	}
+
+	sps->sps_temporal_mvp_enabled_flag = get_bits1(gb);
+	sps->sps_strong_intra_smoothing_enable_flag = get_bits1(gb);
+	sps->vui.sar = (struct AVRational){0, 1};
+	vui_present = get_bits1(gb);
+	if (vui_present)
+		decode_vui(gb, sps);
+
+	if (get_bits1(gb)) { // sps_extension_flag
+		sps->sps_range_extension_flag = get_bits1(gb);
+		skip_bits(gb, 7); //sps_extension_7bits = get_bits(gb, 7);
+		if (sps->sps_range_extension_flag) {
+			sps->transform_skip_rotation_enabled_flag = get_bits1(gb);
+			sps->transform_skip_context_enabled_flag  = get_bits1(gb);
+			sps->implicit_rdpcm_enabled_flag = get_bits1(gb);
+			sps->explicit_rdpcm_enabled_flag = get_bits1(gb);
+			sps->extended_precision_processing_flag = get_bits1(gb);
+			if (sps->extended_precision_processing_flag)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "extended_precision_processing_flag not yet implemented\n");
+
+			sps->intra_smoothing_disabled_flag = get_bits1(gb);
+			sps->high_precision_offsets_enabled_flag = get_bits1(gb);
+			if (sps->high_precision_offsets_enabled_flag)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "high_precision_offsets_enabled_flag not yet implemented\n");
+
+			sps->persistent_rice_adaptation_enabled_flag = get_bits1(gb);
+			sps->cabac_bypass_alignment_enabled_flag  = get_bits1(gb);
+			if (sps->cabac_bypass_alignment_enabled_flag)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "cabac_bypass_alignment_enabled_flag not yet implemented\n");
+		}
+	}
+
+	ow = &sps->output_window;
+	if (ow->left_offset >= INT_MAX - ow->right_offset	  ||
+		ow->top_offset	>= INT_MAX - ow->bottom_offset	  ||
+		ow->left_offset + ow->right_offset  >= sps->width ||
+		ow->top_offset	+ ow->bottom_offset >= sps->height) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid cropping offsets: %u/%u/%u/%u\n",
+			ow->left_offset, ow->right_offset, ow->top_offset, ow->bottom_offset);
+		return -1;
+	}
+
+	// Inferred parameters
+	sps->log2_ctb_size = sps->log2_min_cb_size +
+	sps->log2_diff_max_min_coding_block_size;
+	sps->log2_min_pu_size = sps->log2_min_cb_size - 1;
+
+	if (sps->log2_ctb_size > HEVC_MAX_LOG2_CTB_SIZE) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "CTB size out of range: 2^%d\n", sps->log2_ctb_size);
+		return -1;
+	}
+	if (sps->log2_ctb_size < 4) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "log2_ctb_size %d differs from the bounds of any known profile\n", sps->log2_ctb_size);
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "log2_ctb_size %d", sps->log2_ctb_size);
+		return -1;
+	}
+
+	sps->ctb_width  = (sps->width  + (1 << sps->log2_ctb_size) - 1) >> sps->log2_ctb_size;
+	sps->ctb_height = (sps->height + (1 << sps->log2_ctb_size) - 1) >> sps->log2_ctb_size;
+	sps->ctb_size   = sps->ctb_width * sps->ctb_height;
+
+	sps->min_cb_width  = sps->width  >> sps->log2_min_cb_size;
+	sps->min_cb_height = sps->height >> sps->log2_min_cb_size;
+	sps->min_tb_width  = sps->width  >> sps->log2_min_tb_size;
+	sps->min_tb_height = sps->height >> sps->log2_min_tb_size;
+	sps->min_pu_width  = sps->width  >> sps->log2_min_pu_size;
+	sps->min_pu_height = sps->height >> sps->log2_min_pu_size;
+	sps->tb_mask       = (1 << (sps->log2_ctb_size - sps->log2_min_tb_size)) - 1;
+	sps->qp_bd_offset = 6 * (sps->bit_depth - 8);
+
+	if (av_mod_uintp2(sps->width, sps->log2_min_cb_size) ||
+		av_mod_uintp2(sps->height, sps->log2_min_cb_size)) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid coded frame dimensions.\n");
+		return -1;
+	}
+
+	if (sps->max_transform_hierarchy_depth_inter > sps->log2_ctb_size - sps->log2_min_tb_size) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "max_transform_hierarchy_depth_inter out of range: %d\n",
+			sps->max_transform_hierarchy_depth_inter);
+		return -1;
+	}
+	if (sps->max_transform_hierarchy_depth_intra > sps->log2_ctb_size - sps->log2_min_tb_size) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "max_transform_hierarchy_depth_intra out of range: %d\n",
+			sps->max_transform_hierarchy_depth_intra);
+		return -1;
+	}
+	if (sps->log2_max_trafo_size > FFMIN(sps->log2_ctb_size, 5)) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "max transform block size out of range: %d\n",
+			sps->log2_max_trafo_size);
+			return -1;
+	}
+
+	if (get_bits_left(gb) < 0) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Overread SPS by %d bits\n", -get_bits_left(gb));
+		return -1;
+	}
+
+	v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Parsed SPS: id %d; ref: %d, coded wxh: %dx%d, cropped wxh: %dx%d; pix_fmt: %d.\n",
+	       sps->sps_id, sps->temporal_layer[0].num_reorder_pics, sps->width, sps->height,
+	       sps->width - (sps->output_window.left_offset + sps->output_window.right_offset),
+	       sps->height - (sps->output_window.top_offset + sps->output_window.bottom_offset),
+	       sps->pix_fmt);
+
+	return 0;
+}
+
+const char *hevc_nal_type_name[64] = {
+	"TRAIL_N", // HEVC_NAL_TRAIL_N
+	"TRAIL_R", // HEVC_NAL_TRAIL_R
+	"TSA_N", // HEVC_NAL_TSA_N
+	"TSA_R", // HEVC_NAL_TSA_R
+	"STSA_N", // HEVC_NAL_STSA_N
+	"STSA_R", // HEVC_NAL_STSA_R
+	"RADL_N", // HEVC_NAL_RADL_N
+	"RADL_R", // HEVC_NAL_RADL_R
+	"RASL_N", // HEVC_NAL_RASL_N
+	"RASL_R", // HEVC_NAL_RASL_R
+	"RSV_VCL_N10", // HEVC_NAL_VCL_N10
+	"RSV_VCL_R11", // HEVC_NAL_VCL_R11
+	"RSV_VCL_N12", // HEVC_NAL_VCL_N12
+	"RSV_VLC_R13", // HEVC_NAL_VCL_R13
+	"RSV_VCL_N14", // HEVC_NAL_VCL_N14
+	"RSV_VCL_R15", // HEVC_NAL_VCL_R15
+	"BLA_W_LP", // HEVC_NAL_BLA_W_LP
+	"BLA_W_RADL", // HEVC_NAL_BLA_W_RADL
+	"BLA_N_LP", // HEVC_NAL_BLA_N_LP
+	"IDR_W_RADL", // HEVC_NAL_IDR_W_RADL
+	"IDR_N_LP", // HEVC_NAL_IDR_N_LP
+	"CRA_NUT", // HEVC_NAL_CRA_NUT
+	"IRAP_IRAP_VCL22", // HEVC_NAL_IRAP_VCL22
+	"IRAP_IRAP_VCL23", // HEVC_NAL_IRAP_VCL23
+	"RSV_VCL24", // HEVC_NAL_RSV_VCL24
+	"RSV_VCL25", // HEVC_NAL_RSV_VCL25
+	"RSV_VCL26", // HEVC_NAL_RSV_VCL26
+	"RSV_VCL27", // HEVC_NAL_RSV_VCL27
+	"RSV_VCL28", // HEVC_NAL_RSV_VCL28
+	"RSV_VCL29", // HEVC_NAL_RSV_VCL29
+	"RSV_VCL30", // HEVC_NAL_RSV_VCL30
+	"RSV_VCL31", // HEVC_NAL_RSV_VCL31
+	"VPS", // HEVC_NAL_VPS
+	"SPS", // HEVC_NAL_SPS
+	"PPS", // HEVC_NAL_PPS
+	"AUD", // HEVC_NAL_AUD
+	"EOS_NUT", // HEVC_NAL_EOS_NUT
+	"EOB_NUT", // HEVC_NAL_EOB_NUT
+	"FD_NUT", // HEVC_NAL_FD_NUT
+	"SEI_PREFIX", // HEVC_NAL_SEI_PREFIX
+	"SEI_SUFFIX", // HEVC_NAL_SEI_SUFFIX
+	"RSV_NVCL41", // HEVC_NAL_RSV_NVCL41
+	"RSV_NVCL42", // HEVC_NAL_RSV_NVCL42
+	"RSV_NVCL43", // HEVC_NAL_RSV_NVCL43
+	"RSV_NVCL44", // HEVC_NAL_RSV_NVCL44
+	"RSV_NVCL45", // HEVC_NAL_RSV_NVCL45
+	"RSV_NVCL46", // HEVC_NAL_RSV_NVCL46
+	"RSV_NVCL47", // HEVC_NAL_RSV_NVCL47
+	"UNSPEC48", // HEVC_NAL_UNSPEC48
+	"UNSPEC49", // HEVC_NAL_UNSPEC49
+	"UNSPEC50", // HEVC_NAL_UNSPEC50
+	"UNSPEC51", // HEVC_NAL_UNSPEC51
+	"UNSPEC52", // HEVC_NAL_UNSPEC52
+	"UNSPEC53", // HEVC_NAL_UNSPEC53
+	"UNSPEC54", // HEVC_NAL_UNSPEC54
+	"UNSPEC55", // HEVC_NAL_UNSPEC55
+	"UNSPEC56", // HEVC_NAL_UNSPEC56
+	"UNSPEC57", // HEVC_NAL_UNSPEC57
+	"UNSPEC58", // HEVC_NAL_UNSPEC58
+	"UNSPEC59", // HEVC_NAL_UNSPEC59
+	"UNSPEC60", // HEVC_NAL_UNSPEC60
+	"UNSPEC61", // HEVC_NAL_UNSPEC61
+	"UNSPEC62", // HEVC_NAL_UNSPEC62
+	"UNSPEC63", // HEVC_NAL_UNSPEC63
+};
+
+static const char *hevc_nal_unit_name(int nal_type)
+{
+	return hevc_nal_type_name[nal_type];
+}
+
+/**
+* Parse NAL units of found picture and decode some basic information.
+*
+* @param s parser context.
+* @param avctx codec context.
+* @param buf buffer with field/frame data.
+* @param buf_size size of the buffer.
+*/
+static int decode_extradata_ps(u8 *data, int size, struct h265_param_sets *ps)
+{
+	int ret = 0;
+	struct get_bits_context gb;
+	u32 src_len, rbsp_size = 0;
+	u8 *rbsp_buf = NULL;
+	int nalu_pos, nuh_layer_id, temporal_id;
+	u32 nal_type;
+	u8 *p = data;
+	u32 len = size;
+
+	nalu_pos = find_start_code(p, len);
+	if (nalu_pos < 0)
+		return -1;
+
+	src_len = calc_nal_len(p + nalu_pos, size - nalu_pos);
+	rbsp_buf = nal_unit_extract_rbsp(p + nalu_pos, src_len, &rbsp_size);
+	if (rbsp_buf == NULL)
+		return -ENOMEM;
+
+	ret = init_get_bits8(&gb, rbsp_buf, rbsp_size);
+	if (ret < 0)
+		goto out;
+
+	if (get_bits1(&gb) != 0) {
+		ret = -1;
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "invalid data, return!\n");
+		goto out;
+	}
+
+	nal_type	= get_bits(&gb, 6);
+	nuh_layer_id	= get_bits(&gb, 6);
+	temporal_id	= get_bits(&gb, 3) - 1;
+	if (temporal_id < 0) {
+		ret = -1;
+		goto out;
+	}
+
+	/*pr_info("nal_unit_type: %d(%s), nuh_layer_id: %d, temporal_id: %d\n",
+		nal_type, hevc_nal_unit_name(nal_type),
+		nuh_layer_id, temporal_id);*/
+
+	switch (nal_type) {
+	case HEVC_NAL_VPS:
+		ret = ff_hevc_parse_vps(&gb, &ps->vps);
+		if (ret < 0)
+			goto out;
+		ps->vps_parsed = true;
+		break;
+	case HEVC_NAL_SPS:
+		ret = ff_hevc_parse_sps(&gb, &ps->sps);
+		if (ret < 0)
+			goto out;
+		ps->sps_parsed = true;
+		break;
+	/*case HEVC_NAL_PPS:
+		ret = ff_hevc_decode_nal_pps(&gb, NULL, ps);
+		if (ret < 0)
+			goto out;
+		ps->pps_parsed = true;
+		break;*/
+	default:
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Unsupport parser nal type (%s).\n",
+			hevc_nal_unit_name(nal_type));
+		break;
+	}
+
+out:
+	vfree(rbsp_buf);
+
+	return ret;
+}
+
+int h265_decode_extradata_ps(u8 *buf, int size, struct h265_param_sets *ps)
+{
+	int ret = 0, i = 0, j = 0;
+	u8 *p = buf;
+	int len = size;
+
+	for (i = 4; i < size; i++) {
+		j = find_start_code(p, len);
+		if (j > 0) {
+			len = size - (p - buf);
+			ret = decode_extradata_ps(p, len, ps);
+			if (ret) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "parse extra data failed. err: %d\n", ret);
+				return ret;
+			}
+
+			if (ps->sps_parsed)
+				break;
+
+			p += j;
+		}
+		p++;
+	}
+
+	return ret;
+}
+
diff --git a/drivers/amvdec_ports/decoder/aml_hevc_parser.h b/drivers/amvdec_ports/decoder/aml_hevc_parser.h
new file mode 100644
index 0000000..9223639
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/aml_hevc_parser.h
@@ -0,0 +1,562 @@
+/*
+ * drivers/amvdec_ports/decoder/aml_hevc_parser.h
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+
+#ifndef AML_HEVC_PARSER_H
+#define AML_HEVC_PARSER_H
+
+#include "../aml_vcodec_drv.h"
+#include "../utils/common.h"
+
+#define MAX_DPB_SIZE				16 // A.4.1
+#define MAX_REFS				16
+
+#define MAX_NB_THREADS				16
+#define SHIFT_CTB_WPP				2
+
+/**
+ * 7.4.2.1
+ */
+#define MAX_SUB_LAYERS				7
+#define MAX_VPS_COUNT				16
+#define MAX_SPS_COUNT				32
+#define MAX_PPS_COUNT				256
+#define MAX_SHORT_TERM_RPS_COUNT 		64
+#define MAX_CU_SIZE				128
+
+//TODO: check if this is really the maximum
+#define MAX_TRANSFORM_DEPTH			5
+
+#define MAX_TB_SIZE				32
+#define MAX_PB_SIZE				64
+#define MAX_LOG2_CTB_SIZE			6
+#define MAX_QP					51
+#define DEFAULT_INTRA_TC_OFFSET			2
+
+#define HEVC_CONTEXTS				183
+
+#define MRG_MAX_NUM_CANDS			5
+
+#define L0					0
+#define L1					1
+
+#define EPEL_EXTRA_BEFORE			1
+#define EPEL_EXTRA_AFTER			2
+#define EPEL_EXTRA				3
+
+#define FF_PROFILE_HEVC_MAIN			1
+#define FF_PROFILE_HEVC_MAIN_10			2
+#define FF_PROFILE_HEVC_MAIN_STILL_PICTURE	3
+#define FF_PROFILE_HEVC_REXT			4
+
+/**
+ * Value of the luma sample at position (x, y) in the 2D array tab.
+ */
+#define SAMPLE(tab, x, y) ((tab)[(y) * s->sps->width + (x)])
+#define SAMPLE_CTB(tab, x, y) ((tab)[(y) * min_cb_width + (x)])
+#define SAMPLE_CBF(tab, x, y) ((tab)[((y) & ((1<<log2_trafo_size)-1)) * MAX_CU_SIZE + ((x) & ((1<<log2_trafo_size)-1))])
+
+#define IS_IDR(s) (s->nal_unit_type == NAL_IDR_W_RADL || s->nal_unit_type == NAL_IDR_N_LP)
+#define IS_BLA(s) (s->nal_unit_type == NAL_BLA_W_RADL || s->nal_unit_type == NAL_BLA_W_LP || \
+                   s->nal_unit_type == NAL_BLA_N_LP)
+#define IS_IRAP(s) (s->nal_unit_type >= 16 && s->nal_unit_type <= 23)
+
+/**
+ * Table 7-3: NAL unit type codes
+ */
+enum HEVCNALUnitType {
+	HEVC_NAL_TRAIL_N    = 0,
+	HEVC_NAL_TRAIL_R    = 1,
+	HEVC_NAL_TSA_N      = 2,
+	HEVC_NAL_TSA_R      = 3,
+	HEVC_NAL_STSA_N     = 4,
+	HEVC_NAL_STSA_R     = 5,
+	HEVC_NAL_RADL_N     = 6,
+	HEVC_NAL_RADL_R     = 7,
+	HEVC_NAL_RASL_N     = 8,
+	HEVC_NAL_RASL_R     = 9,
+	HEVC_NAL_VCL_N10    = 10,
+	HEVC_NAL_VCL_R11    = 11,
+	HEVC_NAL_VCL_N12    = 12,
+	HEVC_NAL_VCL_R13    = 13,
+	HEVC_NAL_VCL_N14    = 14,
+	HEVC_NAL_VCL_R15    = 15,
+	HEVC_NAL_BLA_W_LP   = 16,
+	HEVC_NAL_BLA_W_RADL = 17,
+	HEVC_NAL_BLA_N_LP   = 18,
+	HEVC_NAL_IDR_W_RADL = 19,
+	HEVC_NAL_IDR_N_LP   = 20,
+	HEVC_NAL_CRA_NUT    = 21,
+	HEVC_NAL_IRAP_VCL22 = 22,
+	HEVC_NAL_IRAP_VCL23 = 23,
+	HEVC_NAL_RSV_VCL24  = 24,
+	HEVC_NAL_RSV_VCL25  = 25,
+	HEVC_NAL_RSV_VCL26  = 26,
+	HEVC_NAL_RSV_VCL27  = 27,
+	HEVC_NAL_RSV_VCL28  = 28,
+	HEVC_NAL_RSV_VCL29  = 29,
+	HEVC_NAL_RSV_VCL30  = 30,
+	HEVC_NAL_RSV_VCL31  = 31,
+	HEVC_NAL_VPS        = 32,
+	HEVC_NAL_SPS        = 33,
+	HEVC_NAL_PPS        = 34,
+	HEVC_NAL_AUD        = 35,
+	HEVC_NAL_EOS_NUT    = 36,
+	HEVC_NAL_EOB_NUT    = 37,
+	HEVC_NAL_FD_NUT     = 38,
+	HEVC_NAL_SEI_PREFIX = 39,
+	HEVC_NAL_SEI_SUFFIX = 40,
+};
+
+enum HEVCSliceType {
+	HEVC_SLICE_B = 0,
+	HEVC_SLICE_P = 1,
+	HEVC_SLICE_I = 2,
+};
+
+enum {
+	// 7.4.3.1: vps_max_layers_minus1 is in [0, 62].
+	HEVC_MAX_LAYERS     = 63,
+	// 7.4.3.1: vps_max_sub_layers_minus1 is in [0, 6].
+	HEVC_MAX_SUB_LAYERS = 7,
+	// 7.4.3.1: vps_num_layer_sets_minus1 is in [0, 1023].
+	HEVC_MAX_LAYER_SETS = 1024,
+
+	// 7.4.2.1: vps_video_parameter_set_id is u(4).
+	HEVC_MAX_VPS_COUNT = 16,
+	// 7.4.3.2.1: sps_seq_parameter_set_id is in [0, 15].
+	HEVC_MAX_SPS_COUNT = 16,
+	// 7.4.3.3.1: pps_pic_parameter_set_id is in [0, 63].
+	HEVC_MAX_PPS_COUNT = 64,
+
+	// A.4.2: MaxDpbSize is bounded above by 16.
+	HEVC_MAX_DPB_SIZE = 16,
+	// 7.4.3.1: vps_max_dec_pic_buffering_minus1[i] is in [0, MaxDpbSize - 1].
+	HEVC_MAX_REFS     = HEVC_MAX_DPB_SIZE,
+
+	// 7.4.3.2.1: num_short_term_ref_pic_sets is in [0, 64].
+	HEVC_MAX_SHORT_TERM_REF_PIC_SETS = 64,
+	// 7.4.3.2.1: num_long_term_ref_pics_sps is in [0, 32].
+	HEVC_MAX_LONG_TERM_REF_PICS      = 32,
+
+	// A.3: all profiles require that CtbLog2SizeY is in [4, 6].
+	HEVC_MIN_LOG2_CTB_SIZE = 4,
+	HEVC_MAX_LOG2_CTB_SIZE = 6,
+
+	// E.3.2: cpb_cnt_minus1[i] is in [0, 31].
+	HEVC_MAX_CPB_CNT = 32,
+
+	// A.4.1: in table A.6 the highest level allows a MaxLumaPs of 35 651 584.
+	HEVC_MAX_LUMA_PS = 35651584,
+	// A.4.1: pic_width_in_luma_samples and pic_height_in_luma_samples are
+	// constrained to be not greater than sqrt(MaxLumaPs * 8).  Hence height/
+	// width are bounded above by sqrt(8 * 35651584) = 16888.2 samples.
+	HEVC_MAX_WIDTH  = 16888,
+	HEVC_MAX_HEIGHT = 16888,
+
+	// A.4.1: table A.6 allows at most 22 tile rows for any level.
+	HEVC_MAX_TILE_ROWS    = 22,
+	// A.4.1: table A.6 allows at most 20 tile columns for any level.
+	HEVC_MAX_TILE_COLUMNS = 20,
+
+	// 7.4.7.1: in the worst case (tiles_enabled_flag and
+	// entropy_coding_sync_enabled_flag are both set), entry points can be
+	// placed at the beginning of every Ctb row in every tile, giving an
+	// upper bound of (num_tile_columns_minus1 + 1) * PicHeightInCtbsY - 1.
+	// Only a stream with very high resolution and perverse parameters could
+	// get near that, though, so set a lower limit here with the maximum
+	// possible value for 4K video (at most 135 16x16 Ctb rows).
+	HEVC_MAX_ENTRY_POINT_OFFSETS = HEVC_MAX_TILE_COLUMNS * 135,
+};
+
+struct ShortTermRPS {
+	u32 num_negative_pics;
+	int num_delta_pocs;
+	int rps_idx_num_delta_pocs;
+	int delta_poc[32];
+	u8 used[32];
+};
+
+struct LongTermRPS {
+	int poc[32];
+	u8 used[32];
+	u8 nb_refs;
+};
+
+struct SliceHeader {
+	u32 pps_id;
+
+	///< address (in raster order) of the first block in the current slice segment
+	u32   slice_segment_addr;
+	///< address (in raster order) of the first block in the current slice
+	u32   slice_addr;
+
+	enum HEVCSliceType slice_type;
+
+	int pic_order_cnt_lsb;
+
+	u8 first_slice_in_pic_flag;
+	u8 dependent_slice_segment_flag;
+	u8 pic_output_flag;
+	u8 colour_plane_id;
+
+	///< RPS coded in the slice header itself is stored here
+	int short_term_ref_pic_set_sps_flag;
+	int short_term_ref_pic_set_size;
+	struct ShortTermRPS slice_rps;
+	const struct ShortTermRPS *short_term_rps;
+	int long_term_ref_pic_set_size;
+	struct LongTermRPS long_term_rps;
+	u32 list_entry_lx[2][32];
+
+	u8 rpl_modification_flag[2];
+	u8 no_output_of_prior_pics_flag;
+	u8 slice_temporal_mvp_enabled_flag;
+
+	u32 nb_refs[2];
+
+	u8 slice_sample_adaptive_offset_flag[3];
+	u8 mvd_l1_zero_flag;
+
+	u8 cabac_init_flag;
+	u8 disable_deblocking_filter_flag; ///< slice_header_disable_deblocking_filter_flag
+	u8 slice_loop_filter_across_slices_enabled_flag;
+	u8 collocated_list;
+
+	u32 collocated_ref_idx;
+
+	int slice_qp_delta;
+	int slice_cb_qp_offset;
+	int slice_cr_qp_offset;
+
+	u8 cu_chroma_qp_offset_enabled_flag;
+
+	int beta_offset;    ///< beta_offset_div2 * 2
+	int tc_offset;      ///< tc_offset_div2 * 2
+
+	u32 max_num_merge_cand; ///< 5 - 5_minus_max_num_merge_cand
+
+	u8 *entry_point_offset;
+	int * offset;
+	int * size;
+	int num_entry_point_offsets;
+
+	char slice_qp;
+
+	u8 luma_log2_weight_denom;
+	s16 chroma_log2_weight_denom;
+
+	s16 luma_weight_l0[16];
+	s16 chroma_weight_l0[16][2];
+	s16 chroma_weight_l1[16][2];
+	s16 luma_weight_l1[16];
+
+	s16 luma_offset_l0[16];
+	s16 chroma_offset_l0[16][2];
+
+	s16 luma_offset_l1[16];
+	s16 chroma_offset_l1[16][2];
+
+	int slice_ctb_addr_rs;
+};
+
+struct HEVCWindow {
+	u32 left_offset;
+	u32 right_offset;
+	u32 top_offset;
+	u32 bottom_offset;
+};
+
+struct VUI {
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+	struct AVRational sar;
+#endif
+	int overscan_info_present_flag;
+	int overscan_appropriate_flag;
+
+	int video_signal_type_present_flag;
+	int video_format;
+	int video_full_range_flag;
+	int colour_description_present_flag;
+	u8 colour_primaries;
+	u8 transfer_characteristic;
+	u8 matrix_coeffs;
+
+	int chroma_loc_info_present_flag;
+	int chroma_sample_loc_type_top_field;
+	int chroma_sample_loc_type_bottom_field;
+	int neutra_chroma_indication_flag;
+
+	int field_seq_flag;
+	int frame_field_info_present_flag;
+
+	int default_display_window_flag;
+	struct HEVCWindow def_disp_win;
+
+	int vui_timing_info_present_flag;
+	u32 vui_num_units_in_tick;
+	u32 vui_time_scale;
+	int vui_poc_proportional_to_timing_flag;
+	int vui_num_ticks_poc_diff_one_minus1;
+	int vui_hrd_parameters_present_flag;
+
+	int bitstream_restriction_flag;
+	int tiles_fixed_structure_flag;
+	int motion_vectors_over_pic_boundaries_flag;
+	int restricted_ref_pic_lists_flag;
+	int min_spatial_segmentation_idc;
+	int max_bytes_per_pic_denom;
+	int max_bits_per_min_cu_denom;
+	int log2_max_mv_length_horizontal;
+	int log2_max_mv_length_vertical;
+};
+
+struct PTLCommon {
+    u8 profile_space;
+    u8 tier_flag;
+    u8 profile_idc;
+    u8 profile_compatibility_flag[32];
+    u8 level_idc;
+    u8 progressive_source_flag;
+    u8 interlaced_source_flag;
+    u8 non_packed_constraint_flag;
+    u8 frame_only_constraint_flag;
+};
+
+struct PTL {
+    struct PTLCommon general_ptl;
+    struct PTLCommon sub_layer_ptl[HEVC_MAX_SUB_LAYERS];
+
+    u8 sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS];
+    u8 sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS];
+};
+
+struct h265_VPS_t {
+	u8 vps_temporal_id_nesting_flag;
+	int vps_max_layers;
+	int vps_max_sub_layers; ///< vps_max_temporal_layers_minus1 + 1
+
+	struct PTL ptl;
+	int vps_sub_layer_ordering_info_present_flag;
+	u32 vps_max_dec_pic_buffering[HEVC_MAX_SUB_LAYERS];
+	u32 vps_num_reorder_pics[HEVC_MAX_SUB_LAYERS];
+	u32 vps_max_latency_increase[HEVC_MAX_SUB_LAYERS];
+	int vps_max_layer_id;
+	int vps_num_layer_sets; ///< vps_num_layer_sets_minus1 + 1
+	u8 vps_timing_info_present_flag;
+	u32 vps_num_units_in_tick;
+	u32 vps_time_scale;
+	u8 vps_poc_proportional_to_timing_flag;
+	int vps_num_ticks_poc_diff_one; ///< vps_num_ticks_poc_diff_one_minus1 + 1
+	int vps_num_hrd_parameters;
+};
+
+struct ScalingList {
+	/* This is a little wasteful, since sizeID 0 only needs 8 coeffs,
+	* and size ID 3 only has 2 arrays, not 6. */
+	u8 sl[4][6][64];
+	u8 sl_dc[2][6];
+};
+
+struct h265_SPS_t {
+	u8 vps_id;
+	u8 sps_id;
+	int chroma_format_idc;
+	u8 separate_colour_plane_flag;
+
+	struct HEVCWindow output_window;
+	struct HEVCWindow pic_conf_win;
+
+	int bit_depth;
+	int bit_depth_chroma;
+	int pixel_shift;
+	int pix_fmt;
+
+	u32 log2_max_poc_lsb;
+	int pcm_enabled_flag;
+
+	int max_sub_layers;
+	struct {
+		int max_dec_pic_buffering;
+		int num_reorder_pics;
+		int max_latency_increase;
+	} temporal_layer[HEVC_MAX_SUB_LAYERS];
+	u8 temporal_id_nesting_flag;
+
+	struct VUI vui;
+	struct PTL ptl;
+
+	u8 scaling_list_enable_flag;
+	struct ScalingList scaling_list;
+
+	u32 nb_st_rps;
+	struct ShortTermRPS st_rps[HEVC_MAX_SHORT_TERM_REF_PIC_SETS];
+
+	u8 amp_enabled_flag;
+	u8 sao_enabled;
+
+	u8 long_term_ref_pics_present_flag;
+	u16 lt_ref_pic_poc_lsb_sps[HEVC_MAX_LONG_TERM_REF_PICS];
+	u8 used_by_curr_pic_lt_sps_flag[HEVC_MAX_LONG_TERM_REF_PICS];
+	u8 num_long_term_ref_pics_sps;
+
+	struct {
+		u8 bit_depth;
+		u8 bit_depth_chroma;
+		u32 log2_min_pcm_cb_size;
+		u32 log2_max_pcm_cb_size;
+		u8 loop_filter_disable_flag;
+	} pcm;
+	u8 sps_temporal_mvp_enabled_flag;
+	u8 sps_strong_intra_smoothing_enable_flag;
+
+	u32 log2_min_cb_size;
+	u32 log2_diff_max_min_coding_block_size;
+	u32 log2_min_tb_size;
+	u32 log2_max_trafo_size;
+	u32 log2_ctb_size;
+	u32 log2_min_pu_size;
+
+	int max_transform_hierarchy_depth_inter;
+	int max_transform_hierarchy_depth_intra;
+
+	int sps_range_extension_flag;
+	int transform_skip_rotation_enabled_flag;
+	int transform_skip_context_enabled_flag;
+	int implicit_rdpcm_enabled_flag;
+	int explicit_rdpcm_enabled_flag;
+	int extended_precision_processing_flag;
+	int intra_smoothing_disabled_flag;
+	int high_precision_offsets_enabled_flag;
+	int persistent_rice_adaptation_enabled_flag;
+	int cabac_bypass_alignment_enabled_flag;
+
+	///< coded frame dimension in various units
+	int width;
+	int height;
+	int ctb_width;
+	int ctb_height;
+	int ctb_size;
+	int min_cb_width;
+	int min_cb_height;
+	int min_tb_width;
+	int min_tb_height;
+	int min_pu_width;
+	int min_pu_height;
+	int tb_mask;
+
+	int hshift[3];
+	int vshift[3];
+
+	int qp_bd_offset;
+
+	u8 data[4096];
+	int data_size;
+};
+
+struct h265_PPS_t {
+	u32 sps_id; ///< seq_parameter_set_id
+
+	u8 sign_data_hiding_flag;
+
+	u8 cabac_init_present_flag;
+
+	int num_ref_idx_l0_default_active; ///< num_ref_idx_l0_default_active_minus1 + 1
+	int num_ref_idx_l1_default_active; ///< num_ref_idx_l1_default_active_minus1 + 1
+	int pic_init_qp_minus26;
+
+	u8 constrained_intra_pred_flag;
+	u8 transform_skip_enabled_flag;
+
+	u8 cu_qp_delta_enabled_flag;
+	int diff_cu_qp_delta_depth;
+
+	int cb_qp_offset;
+	int cr_qp_offset;
+	u8 pic_slice_level_chroma_qp_offsets_present_flag;
+	u8 weighted_pred_flag;
+	u8 weighted_bipred_flag;
+	u8 output_flag_present_flag;
+	u8 transquant_bypass_enable_flag;
+
+	u8 dependent_slice_segments_enabled_flag;
+	u8 tiles_enabled_flag;
+	u8 entropy_coding_sync_enabled_flag;
+
+	int num_tile_columns;   ///< num_tile_columns_minus1 + 1
+	int num_tile_rows;      ///< num_tile_rows_minus1 + 1
+	u8 uniform_spacing_flag;
+	u8 loop_filter_across_tiles_enabled_flag;
+
+	u8 seq_loop_filter_across_slices_enabled_flag;
+
+	u8 deblocking_filter_control_present_flag;
+	u8 deblocking_filter_override_enabled_flag;
+	u8 disable_dbf;
+	int beta_offset;    ///< beta_offset_div2 * 2
+	int tc_offset;      ///< tc_offset_div2 * 2
+
+	u8 scaling_list_data_present_flag;
+	struct ScalingList scaling_list;
+
+	u8 lists_modification_present_flag;
+	int log2_parallel_merge_level; ///< log2_parallel_merge_level_minus2 + 2
+	int num_extra_slice_header_bits;
+	u8 slice_header_extension_present_flag;
+	u8 log2_max_transform_skip_block_size;
+	u8 cross_component_prediction_enabled_flag;
+	u8 chroma_qp_offset_list_enabled_flag;
+	u8 diff_cu_chroma_qp_offset_depth;
+	u8 chroma_qp_offset_list_len_minus1;
+	char  cb_qp_offset_list[6];
+	char  cr_qp_offset_list[6];
+	u8 log2_sao_offset_scale_luma;
+	u8 log2_sao_offset_scale_chroma;
+
+	// Inferred parameters
+	u32 *column_width;  ///< ColumnWidth
+	u32 *row_height;    ///< RowHeight
+	u32 *col_bd;        ///< ColBd
+	u32 *row_bd;        ///< RowBd
+	int *col_idxX;
+
+	int *ctb_addr_rs_to_ts; ///< CtbAddrRSToTS
+	int *ctb_addr_ts_to_rs; ///< CtbAddrTSToRS
+	int *tile_id;           ///< TileId
+	int *tile_pos_rs;       ///< TilePosRS
+	int *min_tb_addr_zs;    ///< MinTbAddrZS
+	int *min_tb_addr_zs_tab;///< MinTbAddrZS
+};
+
+struct h265_param_sets {
+	bool vps_parsed;
+	bool sps_parsed;
+	bool pps_parsed;
+	/* currently active parameter sets */
+	struct h265_VPS_t vps;
+	struct h265_SPS_t sps;
+	struct h265_PPS_t pps;
+};
+
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+int h265_decode_extradata_ps(u8 *data, int size, struct h265_param_sets *ps);
+#else
+inline int h265_decode_extradata_ps(u8 *data, int size, struct h265_param_sets *ps) { return -1; }
+#endif
+
+#endif /* AML_HEVC_PARSER_H */
+
diff --git a/drivers/amvdec_ports/decoder/aml_mjpeg_parser.c b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.c
new file mode 100644
index 0000000..c582ab0
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.c
@@ -0,0 +1,397 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+
+#include "aml_mjpeg_parser.h"
+#include "../utils/get_bits.h"
+#include "../utils/put_bits.h"
+#include "../utils/golomb.h"
+#include "../utils/common.h"
+#include "utils.h"
+
+/* return the 8 bit start code value and update the search
+state. Return -1 if no start code found */
+static int find_marker(const u8 **pbuf_ptr, const u8 *buf_end)
+{
+	const u8 *buf_ptr;
+	u32 v, v2;
+	int val;
+	int skipped = 0;
+
+	buf_ptr = *pbuf_ptr;
+	while (buf_end - buf_ptr > 1) {
+		v  = *buf_ptr++;
+		v2 = *buf_ptr;
+		if ((v == 0xff) && (v2 >= 0xc0) && (v2 <= 0xfe) && buf_ptr < buf_end) {
+			val = *buf_ptr++;
+			goto found;
+		}
+		skipped++;
+	}
+	buf_ptr = buf_end;
+	val = -1;
+found:
+	v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "find_marker skipped %d bytes\n", skipped);
+	*pbuf_ptr = buf_ptr;
+
+	return val;
+}
+
+int ff_mjpeg_find_marker(struct MJpegDecodeContext *s,
+	const u8 **buf_ptr, const u8 *buf_end,
+	const u8 **unescaped_buf_ptr,
+	int *unescaped_buf_size)
+{
+	int start_code;
+
+	start_code = find_marker(buf_ptr, buf_end);
+
+	/* unescape buffer of SOS, use special treatment for JPEG-LS */
+	if (start_code == SOS && !s->ls) {
+		const u8 *src = *buf_ptr;
+		const u8 *ptr = src;
+		u8 *dst = s->buffer;
+
+		#define copy_data_segment(skip) do {			\
+				int length = (ptr - src) - (skip);	\
+				if (length > 0) {			\
+					memcpy(dst, src, length);	\
+					dst += length;			\
+					src = ptr;			\
+				}					\
+			} while (0)
+
+
+		while (ptr < buf_end) {
+			u8 x = *(ptr++);
+
+			if (x == 0xff) {
+				int skip = 0;
+				while (ptr < buf_end && x == 0xff) {
+					x = *(ptr++);
+					skip++;
+				}
+
+				/* 0xFF, 0xFF, ... */
+				if (skip > 1) {
+					copy_data_segment(skip);
+
+					/* decrement src as it is equal to ptr after the
+					* copy_data_segment macro and we might want to
+					* copy the current value of x later on */
+					src--;
+				}
+
+				if (x < 0xd0 || x > 0xd7) {
+					copy_data_segment(1);
+					if (x)
+						break;
+				}
+			}
+			if (src < ptr)
+				copy_data_segment(0);
+		}
+		#undef copy_data_segment
+
+		*unescaped_buf_ptr  = s->buffer;
+		*unescaped_buf_size = dst - s->buffer;
+		memset(s->buffer + *unescaped_buf_size, 0,
+			AV_INPUT_BUFFER_PADDING_SIZE);
+
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "escaping removed %d bytes\n",
+			(int)((buf_end - *buf_ptr) - (dst - s->buffer)));
+	} else if (start_code == SOS && s->ls) {
+		const u8 *src = *buf_ptr;
+		u8 *dst  = s->buffer;
+		int bit_count = 0;
+		int t = 0, b = 0;
+		struct put_bits_context pb;
+
+		/* find marker */
+		while (src + t < buf_end) {
+			u8 x = src[t++];
+			if (x == 0xff) {
+				while ((src + t < buf_end) && x == 0xff)
+					x = src[t++];
+				if (x & 0x80) {
+					t -= FFMIN(2, t);
+					break;
+				}
+			}
+		}
+		bit_count = t * 8;
+		init_put_bits(&pb, dst, t);
+
+		/* unescape bitstream */
+		while (b < t) {
+			u8 x = src[b++];
+			put_bits(&pb, 8, x);
+			if (x == 0xFF && b < t) {
+				x = src[b++];
+				if (x & 0x80) {
+					v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid escape sequence\n");
+					x &= 0x7f;
+				}
+				put_bits(&pb, 7, x);
+				bit_count--;
+			}
+		}
+		flush_put_bits(&pb);
+
+		*unescaped_buf_ptr	= dst;
+		*unescaped_buf_size = (bit_count + 7) >> 3;
+		memset(s->buffer + *unescaped_buf_size, 0,
+			AV_INPUT_BUFFER_PADDING_SIZE);
+	} else {
+		*unescaped_buf_ptr	= *buf_ptr;
+		*unescaped_buf_size = buf_end - *buf_ptr;
+	}
+
+	return start_code;
+}
+
+
+int ff_mjpeg_decode_sof(struct MJpegDecodeContext *s)
+{
+	int len, nb_components, i, width, height, bits, size_change;
+	int h_count[MAX_COMPONENTS] = { 0 };
+	int v_count[MAX_COMPONENTS] = { 0 };
+
+	s->cur_scan = 0;
+	memset(s->upscale_h, 0, sizeof(s->upscale_h));
+	memset(s->upscale_v, 0, sizeof(s->upscale_v));
+
+	/* XXX: verify len field validity */
+	len     = get_bits(&s->gb, 16);
+	bits    = get_bits(&s->gb, 8);
+
+	if (bits > 16 || bits < 1) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "bits %d is invalid\n", bits);
+		return -1;
+	}
+
+	height = get_bits(&s->gb, 16);
+	width  = get_bits(&s->gb, 16);
+
+	v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "sof0: picture: %dx%d\n", width, height);
+
+	nb_components = get_bits(&s->gb, 8);
+	if (nb_components <= 0 ||
+		nb_components > MAX_COMPONENTS)
+		return -1;
+
+	s->nb_components = nb_components;
+	s->h_max         = 1;
+	s->v_max         = 1;
+	for (i = 0; i < nb_components; i++) {
+		/* component id */
+		s->component_id[i] = get_bits(&s->gb, 8) - 1;
+		h_count[i]         = get_bits(&s->gb, 4);
+		v_count[i]         = get_bits(&s->gb, 4);
+		/* compute hmax and vmax (only used in interleaved case) */
+		if (h_count[i] > s->h_max)
+			s->h_max = h_count[i];
+		if (v_count[i] > s->v_max)
+			s->v_max = v_count[i];
+		s->quant_index[i] = get_bits(&s->gb, 8);
+		if (s->quant_index[i] >= 4) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "quant_index is invalid\n");
+			return -1;
+		}
+		if (!h_count[i] || !v_count[i]) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid sampling factor in component %d %d:%d\n",
+				i, h_count[i], v_count[i]);
+			return -1;
+		}
+
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "component %d %d:%d id: %d quant:%d\n",
+			i, h_count[i], v_count[i],
+		s->component_id[i], s->quant_index[i]);
+	}
+	if (nb_components == 4
+		&& s->component_id[0] == 'C' - 1
+		&& s->component_id[1] == 'M' - 1
+		&& s->component_id[2] == 'Y' - 1
+		&& s->component_id[3] == 'K' - 1)
+		s->adobe_transform = 0;
+
+	/* if different size, realloc/alloc picture */
+	if (width != s->width || height != s->height || bits != s->bits ||
+		memcmp(s->h_count, h_count, sizeof(h_count))                ||
+		memcmp(s->v_count, v_count, sizeof(v_count))) {
+		size_change = 1;
+
+		s->width      = width;
+		s->height     = height;
+		s->bits       = bits;
+		memcpy(s->h_count, h_count, sizeof(h_count));
+		memcpy(s->v_count, v_count, sizeof(v_count));
+		s->interlaced = 0;
+		s->got_picture = 0;
+	} else {
+		size_change = 0;
+	}
+
+	return 0;
+}
+
+static int ff_mjpeg_decode_frame(u8 *buf, int buf_size, struct MJpegDecodeContext *s)
+{
+	const u8 *buf_end, *buf_ptr;
+	const u8 *unescaped_buf_ptr;
+	int unescaped_buf_size;
+	int start_code;
+	int ret = 0;
+
+	buf_ptr = buf;
+	buf_end = buf + buf_size;
+	while (buf_ptr < buf_end) {
+		/* find start next marker */
+		start_code = ff_mjpeg_find_marker(s, &buf_ptr, buf_end,
+						&unescaped_buf_ptr,
+						&unescaped_buf_size);
+		/* EOF */
+		if (start_code < 0) {
+			break;
+		} else if (unescaped_buf_size > INT_MAX / 8) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "MJPEG packet 0x%x too big (%d/%d), corrupt data?\n",
+				start_code, unescaped_buf_size, buf_size);
+			return -1;
+		}
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "marker=%x avail_size_in_buf=%d\n",
+			start_code, (int)(buf_end - buf_ptr));
+
+		ret = init_get_bits8(&s->gb, unescaped_buf_ptr, unescaped_buf_size);
+		if (ret < 0) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "invalid buffer\n");
+			goto fail;
+		}
+
+		s->start_code = start_code;
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "startcode: %X\n", start_code);
+
+		switch (start_code) {
+		case SOF0:
+		case SOF1:
+		case SOF2:
+		case SOF3:
+		case SOF48:
+		case SOI:
+		case SOS:
+		case EOI:
+			break;
+		default:
+			goto skip;
+		}
+
+		switch (start_code) {
+		case SOI:
+			s->restart_interval = 0;
+			s->restart_count    = 0;
+			s->raw_image_buffer      = buf_ptr;
+			s->raw_image_buffer_size = buf_end - buf_ptr;
+			/* nothing to do on SOI */
+			break;
+		case SOF0:
+		case SOF1:
+			if (start_code == SOF0)
+				s->profile = FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT;
+			else
+				s->profile = FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT;
+			s->lossless    = 0;
+			s->ls          = 0;
+			s->progressive = 0;
+			if ((ret = ff_mjpeg_decode_sof(s)) < 0)
+				goto fail;
+			break;
+		case SOF2:
+			s->profile = FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT;
+			s->lossless    = 0;
+			s->ls          = 0;
+			s->progressive = 1;
+			if ((ret = ff_mjpeg_decode_sof(s)) < 0)
+				goto fail;
+			break;
+		case SOF3:
+			s->profile     = FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS;
+			s->properties |= FF_CODEC_PROPERTY_LOSSLESS;
+			s->lossless    = 1;
+			s->ls          = 0;
+			s->progressive = 0;
+			if ((ret = ff_mjpeg_decode_sof(s)) < 0)
+				goto fail;
+			break;
+		case SOF48:
+			s->profile     = FF_PROFILE_MJPEG_JPEG_LS;
+			s->properties |= FF_CODEC_PROPERTY_LOSSLESS;
+			s->lossless    = 1;
+			s->ls          = 1;
+			s->progressive = 0;
+			if ((ret = ff_mjpeg_decode_sof(s)) < 0)
+				goto fail;
+			break;
+		case EOI:
+			goto the_end;
+		case DHT:
+		case LSE:
+		case SOS:
+		case DRI:
+		case SOF5:
+		case SOF6:
+		case SOF7:
+		case SOF9:
+		case SOF10:
+		case SOF11:
+		case SOF13:
+		case SOF14:
+		case SOF15:
+		case JPG:
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "mjpeg: unsupported coding type (%x)\n", start_code);
+			break;
+		}
+skip:
+		/* eof process start code */
+		buf_ptr += (get_bits_count(&s->gb) + 7) / 8;
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "marker parser used %d bytes (%d bits)\n",
+			(get_bits_count(&s->gb) + 7) / 8, get_bits_count(&s->gb));
+	}
+
+	v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "No JPEG data found in image\n");
+	return -1;
+fail:
+	s->got_picture = 0;
+	return ret;
+the_end:
+	v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "decode frame unused %d bytes\n", (int)(buf_end - buf_ptr));
+
+	return 0;
+}
+
+int mjpeg_decode_extradata_ps(u8 *buf, int size, struct mjpeg_param_sets *ps)
+{
+	int ret;
+
+	ps->head_parsed = false;
+
+	ps->dec_ps.buf_size = size;
+	ps->dec_ps.buffer = vzalloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
+	if (!ps->dec_ps.buffer)
+	    return -1;
+
+	ret = ff_mjpeg_decode_frame(buf, size, &ps->dec_ps);
+	if (ret) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "parse extra data failed. err: %d\n", ret);
+		vfree(ps->dec_ps.buffer);
+		return ret;
+	}
+
+	if (ps->dec_ps.width && ps->dec_ps.height)
+		ps->head_parsed = true;
+
+	vfree(ps->dec_ps.buffer);
+
+	return 0;
+}
+
diff --git a/drivers/amvdec_ports/decoder/aml_mjpeg_parser.h b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.h
new file mode 100644
index 0000000..4704ba0
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.h
@@ -0,0 +1,170 @@
+#ifndef AML_MJPEG_PARSER_H
+#define AML_MJPEG_PARSER_H
+
+#include "../aml_vcodec_drv.h"
+#include "../utils/common.h"
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+#include "../utils/get_bits.h"
+#endif
+
+#define FF_PROFILE_MJPEG_HUFFMAN_BASELINE_DCT            0xc0
+#define FF_PROFILE_MJPEG_HUFFMAN_EXTENDED_SEQUENTIAL_DCT 0xc1
+#define FF_PROFILE_MJPEG_HUFFMAN_PROGRESSIVE_DCT         0xc2
+#define FF_PROFILE_MJPEG_HUFFMAN_LOSSLESS                0xc3
+#define FF_PROFILE_MJPEG_JPEG_LS                         0xf7
+
+#define FF_CODEC_PROPERTY_LOSSLESS        0x00000001
+#define FF_CODEC_PROPERTY_CLOSED_CAPTIONS 0x00000002
+
+#define MAX_COMPONENTS 4
+
+/* JPEG marker codes */
+enum JpegMarker {
+    /* start of frame */
+    SOF0  = 0xc0,       /* baseline */
+    SOF1  = 0xc1,       /* extended sequential, huffman */
+    SOF2  = 0xc2,       /* progressive, huffman */
+    SOF3  = 0xc3,       /* lossless, huffman */
+
+    SOF5  = 0xc5,       /* differential sequential, huffman */
+    SOF6  = 0xc6,       /* differential progressive, huffman */
+    SOF7  = 0xc7,       /* differential lossless, huffman */
+    JPG   = 0xc8,       /* reserved for JPEG extension */
+    SOF9  = 0xc9,       /* extended sequential, arithmetic */
+    SOF10 = 0xca,       /* progressive, arithmetic */
+    SOF11 = 0xcb,       /* lossless, arithmetic */
+
+    SOF13 = 0xcd,       /* differential sequential, arithmetic */
+    SOF14 = 0xce,       /* differential progressive, arithmetic */
+    SOF15 = 0xcf,       /* differential lossless, arithmetic */
+
+    DHT   = 0xc4,       /* define huffman tables */
+
+    DAC   = 0xcc,       /* define arithmetic-coding conditioning */
+
+    /* restart with modulo 8 count "m" */
+    RST0  = 0xd0,
+    RST1  = 0xd1,
+    RST2  = 0xd2,
+    RST3  = 0xd3,
+    RST4  = 0xd4,
+    RST5  = 0xd5,
+    RST6  = 0xd6,
+    RST7  = 0xd7,
+
+    SOI   = 0xd8,       /* start of image */
+    EOI   = 0xd9,       /* end of image */
+    SOS   = 0xda,       /* start of scan */
+    DQT   = 0xdb,       /* define quantization tables */
+    DNL   = 0xdc,       /* define number of lines */
+    DRI   = 0xdd,       /* define restart interval */
+    DHP   = 0xde,       /* define hierarchical progression */
+    EXP   = 0xdf,       /* expand reference components */
+
+    APP0  = 0xe0,
+    APP1  = 0xe1,
+    APP2  = 0xe2,
+    APP3  = 0xe3,
+    APP4  = 0xe4,
+    APP5  = 0xe5,
+    APP6  = 0xe6,
+    APP7  = 0xe7,
+    APP8  = 0xe8,
+    APP9  = 0xe9,
+    APP10 = 0xea,
+    APP11 = 0xeb,
+    APP12 = 0xec,
+    APP13 = 0xed,
+    APP14 = 0xee,
+    APP15 = 0xef,
+
+    JPG0  = 0xf0,
+    JPG1  = 0xf1,
+    JPG2  = 0xf2,
+    JPG3  = 0xf3,
+    JPG4  = 0xf4,
+    JPG5  = 0xf5,
+    JPG6  = 0xf6,
+    SOF48 = 0xf7,       ///< JPEG-LS
+    LSE   = 0xf8,       ///< JPEG-LS extension parameters
+    JPG9  = 0xf9,
+    JPG10 = 0xfa,
+    JPG11 = 0xfb,
+    JPG12 = 0xfc,
+    JPG13 = 0xfd,
+
+    COM   = 0xfe,       /* comment */
+
+    TEM   = 0x01,       /* temporary private use for arithmetic coding */
+
+    /* 0x02 -> 0xbf reserved */
+};
+
+struct VLC {
+	int bits;
+	short (*table)[2]; ///< code, bits
+	int table_size, table_allocated;
+};
+
+struct MJpegDecodeContext {
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+	struct get_bits_context gb;
+#endif
+	int buf_size;
+
+	int start_code; /* current start code */
+	int buffer_size;
+	u8 *buffer;
+
+	u16 quant_matrixes[4][64];
+	struct VLC vlcs[3][4];
+	int qscale[4];      ///< quantizer scale calculated from quant_matrixes
+
+	int first_picture;    /* true if decoding first picture */
+	int interlaced;     /* true if interlaced */
+	int bottom_field;   /* true if bottom field */
+	int lossless;
+	int ls;
+	int progressive;
+	u8 upscale_h[4];
+	u8 upscale_v[4];
+	int bits;           /* bits per component */
+	int adobe_transform;
+
+	int width, height;
+	int mb_width, mb_height;
+	int nb_components;
+	int block_stride[MAX_COMPONENTS];
+	int component_id[MAX_COMPONENTS];
+	int h_count[MAX_COMPONENTS]; /* horizontal and vertical count for each component */
+	int v_count[MAX_COMPONENTS];
+	int h_scount[MAX_COMPONENTS];
+	int v_scount[MAX_COMPONENTS];
+	int h_max, v_max; /* maximum h and v counts */
+	int quant_index[4];   /* quant table index for each component */
+	int got_picture;                                ///< we found a SOF and picture is valid, too.
+	int restart_interval;
+	int restart_count;
+	int cur_scan; /* current scan, used by JPEG-LS */
+
+	// Raw stream data for hwaccel use.
+	const u8 *raw_image_buffer;
+	int raw_image_buffer_size;
+
+	int profile;
+	u32 properties;
+};
+
+struct mjpeg_param_sets {
+	bool head_parsed;
+	/* currently active parameter sets */
+	struct MJpegDecodeContext dec_ps;
+};
+
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+int mjpeg_decode_extradata_ps(u8 *buf, int size, struct mjpeg_param_sets *ps);
+#else
+inline int mjpeg_decode_extradata_ps(u8 *buf, int size, struct mjpeg_param_sets *ps) { return -1; }
+#endif
+
+#endif
diff --git a/drivers/amvdec_ports/decoder/aml_mpeg12_parser.c b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.c
new file mode 100644
index 0000000..748a83f
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.c
@@ -0,0 +1,198 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+
+#include "aml_mpeg12_parser.h"
+#include "../utils/get_bits.h"
+#include "../utils/put_bits.h"
+#include "../utils/golomb.h"
+#include "../utils/common.h"
+#include "utils.h"
+
+const struct AVRational ff_mpeg12_frame_rate_tab[16] = {
+	{    0,    0},
+	{24000, 1001},
+	{   24,    1},
+	{   25,    1},
+	{30000, 1001},
+	{   30,    1},
+	{   50,    1},
+	{60000, 1001},
+	{   60,    1},
+	// Xing's 15fps: (9)
+	{   15,    1},
+	// libmpeg3's "Unofficial economy rates": (10-13)
+	{    5,    1},
+	{   10,    1},
+	{   12,    1},
+	{   15,    1},
+	{    0,    0},
+};
+
+const u8 *avpriv_find_start_code(const u8 *p, const u8 *end, u32 *state)
+{
+	int i;
+
+	if (p >= end)
+		return end;
+
+	for (i = 0; i < 3; i++) {
+		u32 tmp = *state << 8;
+		*state = tmp + *(p++);
+		if (tmp == 0x100 || p == end)
+			return p;
+	}
+
+	while (p < end) {
+		if      (p[-1] > 1      ) p += 3;
+		else if (p[-2]          ) p += 2;
+		else if (p[-3]|(p[-1]-1)) p++;
+		else {
+			p++;
+			break;
+		}
+	}
+
+	p = FFMIN(p, end) - 4;
+	*state = AV_RB32(p);
+
+	return p + 4;
+}
+
+static void mpegvideo_extract_headers(const u8 *buf, int buf_size,
+	struct mpeg12_param_sets *ps)
+{
+	struct MpvParseContext *pc = &ps->dec_ps;
+	const u8 *buf_end = buf + buf_size;
+	u32 start_code;
+	int frame_rate_index, ext_type, bytes_left;
+	int frame_rate_ext_n, frame_rate_ext_d;
+	int top_field_first, repeat_first_field, progressive_frame;
+	int horiz_size_ext, vert_size_ext, bit_rate_ext;
+	int bit_rate = 0;
+	int vbv_delay = 0;
+	int chroma_format;
+	enum AVPixelFormat pix_fmt = AV_PIX_FMT_NONE;
+	//FIXME replace the crap with get_bits()
+	pc->repeat_pict = 0;
+
+	while (buf < buf_end) {
+		start_code= -1;
+		buf= avpriv_find_start_code(buf, buf_end, &start_code);
+		bytes_left = buf_end - buf;
+		switch (start_code) {
+		case PICTURE_START_CODE:
+			if (bytes_left >= 2) {
+				pc->pict_type = (buf[1] >> 3) & 7;
+				if (bytes_left >= 4)
+					vbv_delay = ((buf[1] & 0x07) << 13) | (buf[2] << 5) | (buf[3] >> 3);
+			}
+			break;
+		case SEQ_START_CODE:
+			if (bytes_left >= 7) {
+				pc->width  = (buf[0] << 4) | (buf[1] >> 4);
+				pc->height = ((buf[1] & 0x0f) << 8) | buf[2];
+
+				pix_fmt = AV_PIX_FMT_YUV420P;
+				frame_rate_index = buf[3] & 0xf;
+				pc->frame_rate = ff_mpeg12_frame_rate_tab[frame_rate_index];
+				bit_rate = (buf[4]<<10) | (buf[5]<<2) | (buf[6]>>6);
+				pc->ticks_per_frame = 1;
+			}
+			break;
+		case EXT_START_CODE:
+			if (bytes_left >= 1) {
+				ext_type = (buf[0] >> 4);
+				switch (ext_type) {
+				case 0x1: /* sequence extension */
+					if (bytes_left >= 6) {
+						horiz_size_ext = ((buf[1] & 1) << 1) | (buf[2] >> 7);
+						vert_size_ext = (buf[2] >> 5) & 3;
+						bit_rate_ext = ((buf[2] & 0x1F)<<7) | (buf[3]>>1);
+						frame_rate_ext_n = (buf[5] >> 5) & 3;
+						frame_rate_ext_d = (buf[5] & 0x1f);
+						pc->progressive_sequence = buf[1] & (1 << 3);
+						pc->has_b_frames= !(buf[5] >> 7);
+
+						chroma_format = (buf[1] >> 1) & 3;
+						switch (chroma_format) {
+						case 1: pix_fmt = AV_PIX_FMT_YUV420P; break;
+						case 2: pix_fmt = AV_PIX_FMT_YUV422P; break;
+						case 3: pix_fmt = AV_PIX_FMT_YUV444P; break;
+						}
+
+						pc->width  = (pc->width & 0xFFF) | (horiz_size_ext << 12);
+						pc->height = (pc->height& 0xFFF) | ( vert_size_ext << 12);
+						bit_rate = (bit_rate&0x3FFFF) | (bit_rate_ext << 18);
+						//if(did_set_size)
+						//set_dim_ret = ff_set_dimensions(avctx, pc->width, pc->height);
+						pc->framerate.num = pc->frame_rate.num * (frame_rate_ext_n + 1);
+						pc->framerate.den = pc->frame_rate.den * (frame_rate_ext_d + 1);
+						pc->ticks_per_frame = 2;
+					}
+					break;
+				case 0x8: /* picture coding extension */
+					if (bytes_left >= 5) {
+						top_field_first = buf[3] & (1 << 7);
+						repeat_first_field = buf[3] & (1 << 1);
+						progressive_frame = buf[4] & (1 << 7);
+
+						/* check if we must repeat the frame */
+						pc->repeat_pict = 1;
+						if (repeat_first_field) {
+							if (pc->progressive_sequence) {
+								if (top_field_first)
+									pc->repeat_pict = 5;
+								else
+									pc->repeat_pict = 3;
+							} else if (progressive_frame) {
+								pc->repeat_pict = 2;
+							}
+						}
+
+						if (!pc->progressive_sequence && !progressive_frame) {
+							if (top_field_first)
+								pc->field_order = AV_FIELD_TT;
+							else
+								pc->field_order = AV_FIELD_BB;
+						} else
+							pc->field_order = AV_FIELD_PROGRESSIVE;
+					}
+					break;
+				}
+			}
+			break;
+		case -1:
+			goto the_end;
+		default:
+			/* we stop parsing when we encounter a slice. It ensures
+			that this function takes a negligible amount of time */
+			if (start_code >= SLICE_MIN_START_CODE &&
+				start_code <= SLICE_MAX_START_CODE)
+				goto the_end;
+			break;
+		}
+	}
+the_end:
+
+	if (pix_fmt != AV_PIX_FMT_NONE) {
+		pc->format = pix_fmt;
+		pc->coded_width  = ALIGN(pc->width,  16);
+		pc->coded_height = ALIGN(pc->height, 16);
+	}
+}
+
+int mpeg12_decode_extradata_ps(u8 *buf, int size, struct mpeg12_param_sets *ps)
+{
+	ps->head_parsed = false;
+
+	mpegvideo_extract_headers(buf, size, ps);
+
+	if (ps->dec_ps.width && ps->dec_ps.height)
+		ps->head_parsed = true;
+
+	return 0;
+}
+
diff --git a/drivers/amvdec_ports/decoder/aml_mpeg12_parser.h b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.h
new file mode 100644
index 0000000..c06d632
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.h
@@ -0,0 +1,81 @@
+#ifndef AML_MPEG12_PARSER_H
+#define AML_MPEG12_PARSER_H
+
+#include "../aml_vcodec_drv.h"
+#include "../utils/common.h"
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+#include "../utils/pixfmt.h"
+#endif
+
+/* Start codes. */
+#define SEQ_END_CODE            0x000001b7
+#define SEQ_START_CODE          0x000001b3
+#define GOP_START_CODE          0x000001b8
+#define PICTURE_START_CODE      0x00000100
+#define SLICE_MIN_START_CODE    0x00000101
+#define SLICE_MAX_START_CODE    0x000001af
+#define EXT_START_CODE          0x000001b5
+#define USER_START_CODE         0x000001b2
+#define SLICE_START_CODE        0x000001b7
+
+enum AVFieldOrder {
+	AV_FIELD_UNKNOWN,
+	AV_FIELD_PROGRESSIVE,
+	AV_FIELD_TT,          //< Top coded_first, top displayed first
+	AV_FIELD_BB,          //< Bottom coded first, bottom displayed first
+	AV_FIELD_TB,          //< Top coded first, bottom displayed first
+	AV_FIELD_BT,          //< Bottom coded first, top displayed first
+};
+
+struct MpvParseContext {
+	struct AVRational frame_rate;
+	int progressive_sequence;
+	int width, height;
+
+	int repeat_pict; /* XXX: Put it back in AVCodecContext. */
+	int pict_type; /* XXX: Put it back in AVCodecContext. */
+	enum AVFieldOrder field_order;
+	int format;
+	/**
+	* Dimensions of the coded video.
+	*/
+	int coded_width;
+	int coded_height;
+	/**
+	* For some codecs, the time base is closer to the field rate than the frame rate.
+	* Most notably, H.264 and MPEG-2 specify time_base as half of frame duration
+	* if no telecine is used ...
+	*
+	* Set to time_base ticks per frame. Default 1, e.g., H.264/MPEG-2 set it to 2.
+	*/
+	int ticks_per_frame;
+	/**
+	* Size of the frame reordering buffer in the decoder.
+	* For MPEG-2 it is 1 IPB or 0 low delay IP.
+	* - encoding: Set by libavcodec.
+	* - decoding: Set by libavcodec.
+	*/
+	int has_b_frames;
+	/**
+	* - decoding: For codecs that store a framerate value in the compressed
+	*             bitstream, the decoder may export it here. { 0, 1} when
+	*             unknown.
+	* - encoding: May be used to signal the framerate of CFR content to an
+	*             encoder.
+	*/
+	struct AVRational framerate;
+};
+
+struct mpeg12_param_sets {
+	bool head_parsed;
+	/* currently active parameter sets */
+	struct MpvParseContext dec_ps;
+};
+
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+int mpeg12_decode_extradata_ps(u8 *buf, int size, struct mpeg12_param_sets *ps);
+#else
+inline int mpeg12_decode_extradata_ps(u8 *buf, int size, struct mpeg12_param_sets *ps) { return -1; }
+#endif
+
+#endif
diff --git a/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c
new file mode 100644
index 0000000..9c47c08
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c
@@ -0,0 +1,1231 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+
+#include "aml_mpeg4_parser.h"
+#include "../utils/get_bits.h"
+#include "../utils/put_bits.h"
+#include "../utils/golomb.h"
+#include "../utils/common.h"
+#include "utils.h"
+
+const u8 ff_mpeg4_dc_threshold[8]={
+    99, 13, 15, 17, 19, 21, 23, 0
+};
+
+/* these matrixes will be permuted for the idct */
+const int16_t ff_mpeg4_default_intra_matrix[64] = {
+	 8, 17, 18, 19, 21, 23, 25, 27,
+	17, 18, 19, 21, 23, 25, 27, 28,
+	20, 21, 22, 23, 24, 26, 28, 30,
+	21, 22, 23, 24, 26, 28, 30, 32,
+	22, 23, 24, 26, 28, 30, 32, 35,
+	23, 24, 26, 28, 30, 32, 35, 38,
+	25, 26, 28, 30, 32, 35, 38, 41,
+	27, 28, 30, 32, 35, 38, 41, 45,
+};
+
+const int16_t ff_mpeg4_default_non_intra_matrix[64] = {
+	16, 17, 18, 19, 20, 21, 22, 23,
+	17, 18, 19, 20, 21, 22, 23, 24,
+	18, 19, 20, 21, 22, 23, 24, 25,
+	19, 20, 21, 22, 23, 24, 26, 27,
+	20, 21, 22, 23, 25, 26, 27, 28,
+	21, 22, 23, 24, 26, 27, 28, 30,
+	22, 23, 24, 26, 27, 28, 30, 31,
+	23, 24, 25, 27, 28, 30, 31, 33,
+};
+
+const struct AVRational ff_h263_pixel_aspect[16] = {
+	{  0,  1 },
+	{  1,  1 },
+	{ 12, 11 },
+	{ 10, 11 },
+	{ 16, 11 },
+	{ 40, 33 },
+	{  0,  1 },
+	{  0,  1 },
+	{  0,  1 },
+	{  0,  1 },
+	{  0,  1 },
+	{  0,  1 },
+	{  0,  1 },
+	{  0,  1 },
+	{  0,  1 },
+	{  0,  1 },
+};
+
+/* As per spec, studio start code search isn't the same as the old type of start code */
+static void next_start_code_studio(struct get_bits_context *gb)
+{
+	align_get_bits(gb);
+
+	while (get_bits_left(gb) >= 24 && show_bits_long(gb, 24) != 0x1) {
+		get_bits(gb, 8);
+	}
+}
+
+static int read_quant_matrix_ext(struct MpegEncContext *s, struct get_bits_context *gb)
+{
+	int i, /*j,*/ v;
+
+	if (get_bits1(gb)) {
+		if (get_bits_left(gb) < 64*8)
+			return -1;
+		/* intra_quantiser_matrix */
+		for (i = 0; i < 64; i++) {
+			v = get_bits(gb, 8);
+			//j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+			//s->intra_matrix[j]        = v;
+			//s->chroma_intra_matrix[j] = v;
+		}
+	}
+
+	if (get_bits1(gb)) {
+		if (get_bits_left(gb) < 64*8)
+			return -1;
+		/* non_intra_quantiser_matrix */
+		for (i = 0; i < 64; i++) {
+			get_bits(gb, 8);
+		}
+	}
+
+	if (get_bits1(gb)) {
+		if (get_bits_left(gb) < 64*8)
+			return -1;
+		/* chroma_intra_quantiser_matrix */
+		for (i = 0; i < 64; i++) {
+			v = get_bits(gb, 8);
+			//j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+			//s->chroma_intra_matrix[j] = v;
+		}
+	}
+
+	if (get_bits1(gb)) {
+		if (get_bits_left(gb) < 64*8)
+			return -1;
+		/* chroma_non_intra_quantiser_matrix */
+		for (i = 0; i < 64; i++) {
+			get_bits(gb, 8);
+		}
+	}
+
+	next_start_code_studio(gb);
+	return 0;
+}
+
+static void extension_and_user_data(struct MpegEncContext *s, struct get_bits_context *gb, int id)
+{
+	u32 startcode;
+	u8 extension_type;
+
+	startcode = show_bits_long(gb, 32);
+	if (startcode == USER_DATA_STARTCODE || startcode == EXT_STARTCODE) {
+		if ((id == 2 || id == 4) && startcode == EXT_STARTCODE) {
+			skip_bits_long(gb, 32);
+			extension_type = get_bits(gb, 4);
+			if (extension_type == QUANT_MATRIX_EXT_ID)
+				read_quant_matrix_ext(s, gb);
+		}
+	}
+}
+
+
+static int decode_studio_vol_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+	struct MpegEncContext *s = &ctx->m;
+	int width, height;
+	int bits_per_raw_sample;
+
+	// random_accessible_vol and video_object_type_indication have already
+	// been read by the caller decode_vol_header()
+	skip_bits(gb, 4); /* video_object_layer_verid */
+	ctx->shape = get_bits(gb, 2); /* video_object_layer_shape */
+	skip_bits(gb, 4); /* video_object_layer_shape_extension */
+	skip_bits1(gb); /* progressive_sequence */
+	if (ctx->shape != BIN_ONLY_SHAPE) {
+		ctx->rgb = get_bits1(gb); /* rgb_components */
+		s->chroma_format = get_bits(gb, 2); /* chroma_format */
+		if (!s->chroma_format) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "illegal chroma format\n");
+			return -1;
+		}
+
+		bits_per_raw_sample = get_bits(gb, 4); /* bit_depth */
+		if (bits_per_raw_sample == 10) {
+			if (ctx->rgb) {
+				ctx->pix_fmt = AV_PIX_FMT_GBRP10;
+			} else {
+				ctx->pix_fmt = s->chroma_format == CHROMA_422 ? AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_YUV444P10;
+			}
+		}
+		else {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "MPEG-4 Studio profile bit-depth %u", bits_per_raw_sample);
+			return -1;
+		}
+		ctx->bits_per_raw_sample = bits_per_raw_sample;
+	}
+	if (ctx->shape == RECT_SHAPE) {
+		check_marker(gb, "before video_object_layer_width");
+		width = get_bits(gb, 14); /* video_object_layer_width */
+		check_marker(gb, "before video_object_layer_height");
+		height = get_bits(gb, 14); /* video_object_layer_height */
+		check_marker(gb, "after video_object_layer_height");
+
+		/* Do the same check as non-studio profile */
+		if (width && height) {
+			if (s->width && s->height &&
+				(s->width != width || s->height != height))
+				s->context_reinit = 1;
+			s->width  = width;
+			s->height = height;
+		}
+	}
+	s->aspect_ratio_info = get_bits(gb, 4);
+	if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) {
+		ctx->sample_aspect_ratio.num = get_bits(gb, 8);  // par_width
+		ctx->sample_aspect_ratio.den = get_bits(gb, 8);  // par_height
+	} else {
+		ctx->sample_aspect_ratio = ff_h263_pixel_aspect[s->aspect_ratio_info];
+	}
+	skip_bits(gb, 4); /* frame_rate_code */
+	skip_bits(gb, 15); /* first_half_bit_rate */
+	check_marker(gb, "after first_half_bit_rate");
+	skip_bits(gb, 15); /* latter_half_bit_rate */
+	check_marker(gb, "after latter_half_bit_rate");
+	skip_bits(gb, 15); /* first_half_vbv_buffer_size */
+	check_marker(gb, "after first_half_vbv_buffer_size");
+	skip_bits(gb, 3); /* latter_half_vbv_buffer_size */
+	skip_bits(gb, 11); /* first_half_vbv_buffer_size */
+	check_marker(gb, "after first_half_vbv_buffer_size");
+	skip_bits(gb, 15); /* latter_half_vbv_occupancy */
+	check_marker(gb, "after latter_half_vbv_occupancy");
+	s->low_delay = get_bits1(gb);
+	s->mpeg_quant = get_bits1(gb); /* mpeg2_stream */
+
+	next_start_code_studio(gb);
+	extension_and_user_data(s, gb, 2);
+
+	return 0;
+}
+
+static int decode_vol_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+	struct MpegEncContext *s = &ctx->m;
+	int width, height, vo_ver_id;
+
+	/* vol header */
+	skip_bits(gb, 1);                   /* random access */
+	s->vo_type = get_bits(gb, 8);
+
+	/* If we are in studio profile (per vo_type), check if its all consistent
+	* and if so continue pass control to decode_studio_vol_header().
+	* elIf something is inconsistent, error out
+	* else continue with (non studio) vol header decpoding.
+	*/
+	if (s->vo_type == CORE_STUDIO_VO_TYPE ||
+		s->vo_type == SIMPLE_STUDIO_VO_TYPE) {
+		if (ctx->profile != FF_PROFILE_UNKNOWN && ctx->profile != FF_PROFILE_MPEG4_SIMPLE_STUDIO)
+			return -1;
+		s->studio_profile = 1;
+		ctx->profile = FF_PROFILE_MPEG4_SIMPLE_STUDIO;
+		return decode_studio_vol_header(ctx, gb);
+	} else if (s->studio_profile) {
+		return -1;
+	}
+
+	if (get_bits1(gb) != 0) {           /* is_ol_id */
+		vo_ver_id = get_bits(gb, 4);    /* vo_ver_id */
+		skip_bits(gb, 3);               /* vo_priority */
+	} else {
+		vo_ver_id = 1;
+	}
+	s->aspect_ratio_info = get_bits(gb, 4);
+	if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) {
+		ctx->sample_aspect_ratio.num = get_bits(gb, 8);  // par_width
+		ctx->sample_aspect_ratio.den = get_bits(gb, 8);  // par_height
+	} else {
+		ctx->sample_aspect_ratio = ff_h263_pixel_aspect[s->aspect_ratio_info];
+	}
+
+	if ((ctx->vol_control_parameters = get_bits1(gb))) { /* vol control parameter */
+		int chroma_format = get_bits(gb, 2);
+		if (chroma_format != CHROMA_420)
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "illegal chroma format\n");
+
+		s->low_delay = get_bits1(gb);
+		if (get_bits1(gb)) {    /* vbv parameters */
+			get_bits(gb, 15);   /* first_half_bitrate */
+			check_marker(gb, "after first_half_bitrate");
+			get_bits(gb, 15);   /* latter_half_bitrate */
+			check_marker(gb, "after latter_half_bitrate");
+			get_bits(gb, 15);   /* first_half_vbv_buffer_size */
+			check_marker(gb, "after first_half_vbv_buffer_size");
+			get_bits(gb, 3);    /* latter_half_vbv_buffer_size */
+			get_bits(gb, 11);   /* first_half_vbv_occupancy */
+			check_marker(gb, "after first_half_vbv_occupancy");
+			get_bits(gb, 15);   /* latter_half_vbv_occupancy */
+			check_marker(gb, "after latter_half_vbv_occupancy");
+		}
+	} else {
+		/* is setting low delay flag only once the smartest thing to do?
+		* low delay detection will not be overridden. */
+		if (s->picture_number == 0) {
+			switch (s->vo_type) {
+			case SIMPLE_VO_TYPE:
+			case ADV_SIMPLE_VO_TYPE:
+				s->low_delay = 1;
+				break;
+			default:
+				s->low_delay = 0;
+			}
+		}
+	}
+
+	ctx->shape = get_bits(gb, 2); /* vol shape */
+	if (ctx->shape != RECT_SHAPE)
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "only rectangular vol supported\n");
+	if (ctx->shape == GRAY_SHAPE && vo_ver_id != 1) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Gray shape not supported\n");
+		skip_bits(gb, 4);  /* video_object_layer_shape_extension */
+	}
+
+	check_marker(gb, "before time_increment_resolution");
+
+	ctx->framerate.num = get_bits(gb, 16);
+	if (!ctx->framerate.num) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "framerate==0\n");
+		return -1;
+	}
+
+	ctx->time_increment_bits = av_log2(ctx->framerate.num - 1) + 1;
+	if (ctx->time_increment_bits < 1)
+		ctx->time_increment_bits = 1;
+
+	check_marker(gb, "before fixed_vop_rate");
+
+	if (get_bits1(gb) != 0)     /* fixed_vop_rate  */
+		ctx->framerate.den = get_bits(gb, ctx->time_increment_bits);
+	else
+		ctx->framerate.den = 1;
+
+	//ctx->time_base = av_inv_q(av_mul_q(ctx->framerate, (AVRational){ctx->ticks_per_frame, 1}));
+
+	ctx->t_frame = 0;
+
+	if (ctx->shape != BIN_ONLY_SHAPE) {
+		if (ctx->shape == RECT_SHAPE) {
+			check_marker(gb, "before width");
+			width = get_bits(gb, 13);
+			check_marker(gb, "before height");
+			height = get_bits(gb, 13);
+			check_marker(gb, "after height");
+			if (width && height &&  /* they should be non zero but who knows */
+			!(s->width && s->codec_tag == AV_RL32("MP4S"))) {
+				if (s->width && s->height &&
+				(s->width != width || s->height != height))
+				s->context_reinit = 1;
+				s->width  = width;
+				s->height = height;
+			}
+		}
+
+		s->progressive_sequence  =
+		s->progressive_frame     = get_bits1(gb) ^ 1;
+		s->interlaced_dct        = 0;
+		if (!get_bits1(gb)) /* OBMC Disable */
+			v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "MPEG-4 OBMC not supported (very likely buggy encoder)\n");
+		if (vo_ver_id == 1)
+			ctx->vol_sprite_usage = get_bits1(gb);    /* vol_sprite_usage */
+		else
+			ctx->vol_sprite_usage = get_bits(gb, 2);  /* vol_sprite_usage */
+
+		if (ctx->vol_sprite_usage == STATIC_SPRITE)
+			v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Static Sprites not supported\n");
+		if (ctx->vol_sprite_usage == STATIC_SPRITE ||
+			ctx->vol_sprite_usage == GMC_SPRITE) {
+		if (ctx->vol_sprite_usage == STATIC_SPRITE) {
+			skip_bits(gb, 13); // sprite_width
+			check_marker(gb, "after sprite_width");
+			skip_bits(gb, 13); // sprite_height
+			check_marker(gb, "after sprite_height");
+			skip_bits(gb, 13); // sprite_left
+			check_marker(gb, "after sprite_left");
+			skip_bits(gb, 13); // sprite_top
+			check_marker(gb, "after sprite_top");
+		}
+		ctx->num_sprite_warping_points = get_bits(gb, 6);
+		if (ctx->num_sprite_warping_points > 3) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "%d sprite_warping_points\n",
+				ctx->num_sprite_warping_points);
+			ctx->num_sprite_warping_points = 0;
+			return -1;
+		}
+		s->sprite_warping_accuracy  = get_bits(gb, 2);
+		ctx->sprite_brightness_change = get_bits1(gb);
+		if (ctx->vol_sprite_usage == STATIC_SPRITE)
+			skip_bits1(gb); // low_latency_sprite
+		}
+		// FIXME sadct disable bit if verid!=1 && shape not rect
+
+		if (get_bits1(gb) == 1) {                   /* not_8_bit */
+				s->quant_precision = get_bits(gb, 4);   /* quant_precision */
+			if (get_bits(gb, 4) != 8)               /* bits_per_pixel */
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "N-bit not supported\n");
+			if (s->quant_precision != 5)
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "quant precision %d\n", s->quant_precision);
+			if (s->quant_precision<3 || s->quant_precision>9) {
+				s->quant_precision = 5;
+			}
+		} else {
+			s->quant_precision = 5;
+		}
+
+		// FIXME a bunch of grayscale shape things
+
+		if ((s->mpeg_quant = get_bits1(gb))) { /* vol_quant_type */
+			int i, v;
+
+			//mpeg4_load_default_matrices(s);
+
+			/* load custom intra matrix */
+			if (get_bits1(gb)) {
+				int last = 0;
+			for (i = 0; i < 64; i++) {
+				//int j;
+				if (get_bits_left(gb) < 8) {
+					v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "insufficient data for custom matrix\n");
+					return -1;
+				}
+				v = get_bits(gb, 8);
+				if (v == 0)
+					break;
+
+				last = v;
+				//j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+				//s->intra_matrix[j]        = last;
+				//s->chroma_intra_matrix[j] = last;
+			}
+
+			/* replicate last value */
+			//for (; i < 64; i++) {
+				//int j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+				//s->intra_matrix[j]        = last;
+				//s->chroma_intra_matrix[j] = last;
+			//}
+			}
+
+			/* load custom non intra matrix */
+			if (get_bits1(gb)) {
+				int last = 0;
+				for (i = 0; i < 64; i++) {
+					//int j;
+					if (get_bits_left(gb) < 8) {
+						v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "insufficient data for custom matrix\n");
+						return -1;
+					}
+					v = get_bits(gb, 8);
+					if (v == 0)
+						break;
+
+					last = v;
+					//j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+					//s->inter_matrix[j]        = v;
+					//s->chroma_inter_matrix[j] = v;
+				}
+
+				/* replicate last value */
+				//for (; i < 64; i++) {
+					//int j = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+					//s->inter_matrix[j]        = last;
+					//s->chroma_inter_matrix[j] = last;
+				//}
+			}
+
+			// FIXME a bunch of grayscale shape things
+		}
+
+		if (vo_ver_id != 1)
+			s->quarter_sample = get_bits1(gb);
+		else
+			s->quarter_sample = 0;
+
+		if (get_bits_left(gb) < 4) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "VOL Header truncated\n");
+			return -1;
+		}
+
+		if (!get_bits1(gb)) {
+			int pos               = get_bits_count(gb);
+			int estimation_method = get_bits(gb, 2);
+			if (estimation_method < 2) {
+				if (!get_bits1(gb)) {
+					ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* opaque */
+					ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* transparent */
+					ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* intra_cae */
+					ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* inter_cae */
+					ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* no_update */
+					ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* upsampling */
+				}
+				if (!get_bits1(gb)) {
+					ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* intra_blocks */
+					ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* inter_blocks */
+					ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* inter4v_blocks */
+					ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* not coded blocks */
+				}
+				if (!check_marker(gb, "in complexity estimation part 1")) {
+					skip_bits_long(gb, pos - get_bits_count(gb));
+					goto no_cplx_est;
+				}
+				if (!get_bits1(gb)) {
+					ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* dct_coeffs */
+					ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* dct_lines */
+					ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* vlc_syms */
+					ctx->cplx_estimation_trash_i += 4 * get_bits1(gb);  /* vlc_bits */
+				}
+				if (!get_bits1(gb)) {
+					ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* apm */
+					ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* npm */
+					ctx->cplx_estimation_trash_b += 8 * get_bits1(gb);  /* interpolate_mc_q */
+					ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* forwback_mc_q */
+					ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* halfpel2 */
+					ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* halfpel4 */
+				}
+				if (!check_marker(gb, "in complexity estimation part 2")) {
+					skip_bits_long(gb, pos - get_bits_count(gb));
+					goto no_cplx_est;
+				}
+				if (estimation_method == 1) {
+					ctx->cplx_estimation_trash_i += 8 * get_bits1(gb);  /* sadct */
+					ctx->cplx_estimation_trash_p += 8 * get_bits1(gb);  /* qpel */
+				}
+			} else
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid Complexity estimation method %d\n",
+				estimation_method);
+		} else {
+
+no_cplx_est:
+			ctx->cplx_estimation_trash_i =
+			ctx->cplx_estimation_trash_p =
+			ctx->cplx_estimation_trash_b = 0;
+		}
+
+		ctx->resync_marker = !get_bits1(gb); /* resync_marker_disabled */
+
+		s->data_partitioning = get_bits1(gb);
+		if (s->data_partitioning)
+			ctx->rvlc = get_bits1(gb);
+
+		if (vo_ver_id != 1) {
+			ctx->new_pred = get_bits1(gb);
+		if (ctx->new_pred) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "new pred not supported\n");
+			skip_bits(gb, 2); /* requested upstream message type */
+			skip_bits1(gb);   /* newpred segment type */
+		}
+		if (get_bits1(gb)) // reduced_res_vop
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "reduced resolution VOP not supported\n");
+		} else {
+			ctx->new_pred = 0;
+		}
+
+		ctx->scalability = get_bits1(gb);
+
+		if (ctx->scalability) {
+			struct get_bits_context bak = *gb;
+			int h_sampling_factor_n;
+			int h_sampling_factor_m;
+			int v_sampling_factor_n;
+			int v_sampling_factor_m;
+
+			skip_bits1(gb);    // hierarchy_type
+			skip_bits(gb, 4);  /* ref_layer_id */
+			skip_bits1(gb);    /* ref_layer_sampling_dir */
+			h_sampling_factor_n = get_bits(gb, 5);
+			h_sampling_factor_m = get_bits(gb, 5);
+			v_sampling_factor_n = get_bits(gb, 5);
+			v_sampling_factor_m = get_bits(gb, 5);
+			ctx->enhancement_type = get_bits1(gb);
+
+			if (h_sampling_factor_n == 0 || h_sampling_factor_m == 0 ||
+				v_sampling_factor_n == 0 || v_sampling_factor_m == 0) {
+				/* illegal scalability header (VERY broken encoder),
+				* trying to workaround */
+				ctx->scalability = 0;
+				*gb            = bak;
+			} else
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "scalability not supported\n");
+
+			// bin shape stuff FIXME
+		}
+	}
+
+	if (1) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "tb %d/%d, tincrbits:%d, qp_prec:%d, ps:%d, low_delay:%d  %s%s%s%s\n",
+			ctx->framerate.den, ctx->framerate.num,
+			ctx->time_increment_bits,
+			s->quant_precision,
+			s->progressive_sequence,
+			s->low_delay,
+			ctx->scalability ? "scalability " :"" , s->quarter_sample ? "qpel " : "",
+			s->data_partitioning ? "partition " : "", ctx->rvlc ? "rvlc " : "");
+	}
+
+	return 0;
+}
+
+
+/**
+ * Decode the user data stuff in the header.
+ * Also initializes divx/xvid/lavc_version/build.
+ */
+static int decode_user_data(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+	struct MpegEncContext *s = &ctx->m;
+	char buf[256];
+	int i;
+	int e;
+	int ver = 0, build = 0, ver2 = 0, ver3 = 0;
+	char last;
+
+	for (i = 0; i < 255 && get_bits_count(gb) < gb->size_in_bits; i++) {
+		if (show_bits(gb, 23) == 0)
+		break;
+		buf[i] = get_bits(gb, 8);
+	}
+	buf[i] = 0;
+
+	/* divx detection */
+	e = sscanf(buf, "DivX%dBuild%d%c", &ver, &build, &last);
+	if (e < 2)
+		e = sscanf(buf, "DivX%db%d%c", &ver, &build, &last);
+	if (e >= 2) {
+		ctx->divx_version = ver;
+		ctx->divx_build   = build;
+		s->divx_packed  = e == 3 && last == 'p';
+	}
+
+	/* libavcodec detection */
+	e = sscanf(buf, "FFmpe%*[^b]b%d", &build) + 3;
+	if (e != 4)
+		e = sscanf(buf, "FFmpeg v%d.%d.%d / libavcodec build: %d", &ver, &ver2, &ver3, &build);
+	if (e != 4) {
+		e = sscanf(buf, "Lavc%d.%d.%d", &ver, &ver2, &ver3) + 1;
+		if (e > 1) {
+			if (ver > 0xFFU || ver2 > 0xFFU || ver3 > 0xFFU) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Unknown Lavc version string encountered, %d.%d.%d; "
+					"clamping sub-version values to 8-bits.\n",
+					ver, ver2, ver3);
+			}
+			build = ((ver & 0xFF) << 16) + ((ver2 & 0xFF) << 8) + (ver3 & 0xFF);
+		}
+	}
+	if (e != 4) {
+		if (strcmp(buf, "ffmpeg") == 0)
+			ctx->lavc_build = 4600;
+	}
+	if (e == 4)
+		ctx->lavc_build = build;
+
+	/* Xvid detection */
+	e = sscanf(buf, "XviD%d", &build);
+	if (e == 1)
+		ctx->xvid_build = build;
+
+	return 0;
+}
+
+
+static int mpeg4_decode_gop_header(struct MpegEncContext *s, struct get_bits_context *gb)
+{
+	int hours, minutes, seconds;
+
+	if (!show_bits(gb, 23)) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "GOP header invalid\n");
+		return -1;
+	}
+
+	hours   = get_bits(gb, 5);
+	minutes = get_bits(gb, 6);
+	check_marker(gb, "in gop_header");
+	seconds = get_bits(gb, 6);
+
+	s->time_base = seconds + 60*(minutes + 60*hours);
+
+	skip_bits1(gb);
+	skip_bits1(gb);
+
+	return 0;
+}
+
+
+static int mpeg4_decode_profile_level(struct MpegEncContext *s, struct get_bits_context *gb, int *profile, int *level)
+{
+
+	*profile = get_bits(gb, 4);
+	*level   = get_bits(gb, 4);
+
+	// for Simple profile, level 0
+	if (*profile == 0 && *level == 8) {
+		*level = 0;
+	}
+
+	return 0;
+}
+
+
+static int decode_studiovisualobject(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+	struct MpegEncContext *s = &ctx->m;
+	int visual_object_type;
+
+	skip_bits(gb, 4); /* visual_object_verid */
+	visual_object_type = get_bits(gb, 4);
+	if (visual_object_type != VOT_VIDEO_ID) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "VO type %u", visual_object_type);
+		return -1;
+	}
+
+	next_start_code_studio(gb);
+	extension_and_user_data(s, gb, 1);
+
+	return 0;
+}
+
+
+static int mpeg4_decode_visual_object(struct MpegEncContext *s, struct get_bits_context *gb)
+{
+	int visual_object_type;
+	int is_visual_object_identifier = get_bits1(gb);
+
+	if (is_visual_object_identifier) {
+		skip_bits(gb, 4+3);
+	}
+	visual_object_type = get_bits(gb, 4);
+
+	if (visual_object_type == VOT_VIDEO_ID ||
+	visual_object_type == VOT_STILL_TEXTURE_ID) {
+		int video_signal_type = get_bits1(gb);
+		if (video_signal_type) {
+			int video_range, color_description;
+			skip_bits(gb, 3); // video_format
+			video_range = get_bits1(gb);
+			color_description = get_bits1(gb);
+
+			s->ctx->color_range = video_range ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG;
+
+			if (color_description) {
+				s->ctx->color_primaries = get_bits(gb, 8);
+				s->ctx->color_trc       = get_bits(gb, 8);
+				s->ctx->colorspace      = get_bits(gb, 8);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void decode_smpte_tc(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+	skip_bits(gb, 16); /* Time_code[63..48] */
+	check_marker(gb, "after Time_code[63..48]");
+	skip_bits(gb, 16); /* Time_code[47..32] */
+	check_marker(gb, "after Time_code[47..32]");
+	skip_bits(gb, 16); /* Time_code[31..16] */
+	check_marker(gb, "after Time_code[31..16]");
+	skip_bits(gb, 16); /* Time_code[15..0] */
+	check_marker(gb, "after Time_code[15..0]");
+	skip_bits(gb, 4); /* reserved_bits */
+}
+
+static void reset_studio_dc_predictors(struct MpegEncContext *s)
+{
+	/* Reset DC Predictors */
+	s->last_dc[0] =
+	s->last_dc[1] =
+	s->last_dc[2] = 1 << (s->ctx->bits_per_raw_sample + s->dct_precision + s->intra_dc_precision - 1);
+}
+
+/**
+ * Decode the next studio vop header.
+ * @return <0 if something went wrong
+ */
+static int decode_studio_vop_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+	struct MpegEncContext *s = &ctx->m;
+
+	if (get_bits_left(gb) <= 32)
+		return 0;
+
+	//s->decode_mb = mpeg4_decode_studio_mb;
+
+	decode_smpte_tc(ctx, gb);
+
+	skip_bits(gb, 10); /* temporal_reference */
+	skip_bits(gb, 2); /* vop_structure */
+	s->pict_type = get_bits(gb, 2) + AV_PICTURE_TYPE_I; /* vop_coding_type */
+	if (get_bits1(gb)) { /* vop_coded */
+		skip_bits1(gb); /* top_field_first */
+		skip_bits1(gb); /* repeat_first_field */
+		s->progressive_frame = get_bits1(gb) ^ 1; /* progressive_frame */
+	}
+
+	if (s->pict_type == AV_PICTURE_TYPE_I) {
+		if (get_bits1(gb))
+			reset_studio_dc_predictors(s);
+	}
+
+	if (ctx->shape != BIN_ONLY_SHAPE) {
+		s->alternate_scan = get_bits1(gb);
+		s->frame_pred_frame_dct = get_bits1(gb);
+		s->dct_precision = get_bits(gb, 2);
+		s->intra_dc_precision = get_bits(gb, 2);
+		s->q_scale_type = get_bits1(gb);
+	}
+
+	//if (s->alternate_scan) {    }
+
+	//mpeg4_load_default_matrices(s);
+
+	next_start_code_studio(gb);
+	extension_and_user_data(s, gb, 4);
+
+	return 0;
+}
+
+static int decode_new_pred(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+	int len = FFMIN(ctx->time_increment_bits + 3, 15);
+
+	get_bits(gb, len);
+	if (get_bits1(gb))
+		get_bits(gb, len);
+	check_marker(gb, "after new_pred");
+
+	return 0;
+}
+
+static int decode_vop_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+	struct MpegEncContext *s = &ctx->m;
+	int time_incr, time_increment;
+	int64_t pts;
+
+	s->mcsel       = 0;
+	s->pict_type = get_bits(gb, 2) + AV_PICTURE_TYPE_I;        /* pict type: I = 0 , P = 1 */
+	if (s->pict_type == AV_PICTURE_TYPE_B && s->low_delay &&
+		ctx->vol_control_parameters == 0) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "low_delay flag set incorrectly, clearing it\n");
+		s->low_delay = 0;
+	}
+
+	s->partitioned_frame = s->data_partitioning && s->pict_type != AV_PICTURE_TYPE_B;
+	/*if (s->partitioned_frame)
+		s->decode_mb = mpeg4_decode_partitioned_mb;
+	else
+		s->decode_mb = mpeg4_decode_mb;*/
+
+	time_incr = 0;
+	while (get_bits1(gb) != 0)
+		time_incr++;
+
+	check_marker(gb, "before time_increment");
+
+	if (ctx->time_increment_bits == 0 ||
+		!(show_bits(gb, ctx->time_increment_bits + 1) & 1)) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "time_increment_bits %d is invalid in relation to the current bitstream, this is likely caused by a missing VOL header\n", ctx->time_increment_bits);
+
+		for (ctx->time_increment_bits = 1;
+			ctx->time_increment_bits < 16;
+			ctx->time_increment_bits++) {
+			if (s->pict_type == AV_PICTURE_TYPE_P ||
+				(s->pict_type == AV_PICTURE_TYPE_S &&
+				ctx->vol_sprite_usage == GMC_SPRITE)) {
+				if ((show_bits(gb, ctx->time_increment_bits + 6) & 0x37) == 0x30)
+					break;
+			} else if ((show_bits(gb, ctx->time_increment_bits + 5) & 0x1F) == 0x18)
+				break;
+		}
+
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "time_increment_bits set to %d bits, based on bitstream analysis\n", ctx->time_increment_bits);
+		if (ctx->framerate.num && 4*ctx->framerate.num < 1<<ctx->time_increment_bits) {
+			ctx->framerate.num = 1<<ctx->time_increment_bits;
+			//ctx->time_base = av_inv_q(av_mul_q(ctx->framerate, (AVRational){ctx->ticks_per_frame, 1}));
+		}
+	}
+
+	if (IS_3IV1)
+		time_increment = get_bits1(gb);        // FIXME investigate further
+	else
+		time_increment = get_bits(gb, ctx->time_increment_bits);
+
+	if (s->pict_type != AV_PICTURE_TYPE_B) {
+		s->last_time_base = s->time_base;
+		s->time_base     += time_incr;
+		s->time = s->time_base * (int64_t)ctx->framerate.num + time_increment;
+		//if (s->workaround_bugs & FF_BUG_UMP4) { }
+		s->pp_time         = s->time - s->last_non_b_time;
+		s->last_non_b_time = s->time;
+	} else {
+		s->time    = (s->last_time_base + time_incr) * (int64_t)ctx->framerate.num + time_increment;
+		s->pb_time = s->pp_time - (s->last_non_b_time - s->time);
+		if (s->pp_time <= s->pb_time ||
+			s->pp_time <= s->pp_time - s->pb_time ||
+			s->pp_time <= 0) {
+			/* messed up order, maybe after seeking? skipping current B-frame */
+			return FRAME_SKIPPED;
+		}
+		//ff_mpeg4_init_direct_mv(s);
+
+			if (ctx->t_frame == 0)
+		ctx->t_frame = s->pb_time;
+		if (ctx->t_frame == 0)
+			ctx->t_frame = 1;  // 1/0 protection
+		s->pp_field_time = (ROUNDED_DIV(s->last_non_b_time, ctx->t_frame) -
+		ROUNDED_DIV(s->last_non_b_time - s->pp_time, ctx->t_frame)) * 2;
+		s->pb_field_time = (ROUNDED_DIV(s->time, ctx->t_frame) -
+		ROUNDED_DIV(s->last_non_b_time - s->pp_time, ctx->t_frame)) * 2;
+		if (s->pp_field_time <= s->pb_field_time || s->pb_field_time <= 1) {
+			s->pb_field_time = 2;
+			s->pp_field_time = 4;
+			if (!s->progressive_sequence)
+				return FRAME_SKIPPED;
+		}
+	}
+
+	if (ctx->framerate.den)
+		pts = ROUNDED_DIV(s->time, ctx->framerate.den);
+	else
+		pts = AV_NOPTS_VALUE;
+	v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "MPEG4 PTS: %lld\n", pts);
+
+	check_marker(gb, "before vop_coded");
+
+	/* vop coded */
+	if (get_bits1(gb) != 1) {
+		if (1)
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "vop not coded\n");
+		return FRAME_SKIPPED;
+	}
+	if (ctx->new_pred)
+		decode_new_pred(ctx, gb);
+
+	if (ctx->shape != BIN_ONLY_SHAPE &&
+		(s->pict_type == AV_PICTURE_TYPE_P ||
+		(s->pict_type == AV_PICTURE_TYPE_S &&
+		ctx->vol_sprite_usage == GMC_SPRITE))) {
+		/* rounding type for motion estimation */
+		s->no_rounding = get_bits1(gb);
+	} else {
+		s->no_rounding = 0;
+	}
+	// FIXME reduced res stuff
+
+	if (ctx->shape != RECT_SHAPE) {
+		if (ctx->vol_sprite_usage != 1 || s->pict_type != AV_PICTURE_TYPE_I) {
+			skip_bits(gb, 13);  /* width */
+			check_marker(gb, "after width");
+			skip_bits(gb, 13);  /* height */
+			check_marker(gb, "after height");
+			skip_bits(gb, 13);  /* hor_spat_ref */
+			check_marker(gb, "after hor_spat_ref");
+			skip_bits(gb, 13);  /* ver_spat_ref */
+		}
+		skip_bits1(gb);         /* change_CR_disable */
+
+		if (get_bits1(gb) != 0)
+			skip_bits(gb, 8);   /* constant_alpha_value */
+	}
+
+	// FIXME complexity estimation stuff
+
+	if (ctx->shape != BIN_ONLY_SHAPE) {
+		skip_bits_long(gb, ctx->cplx_estimation_trash_i);
+		if (s->pict_type != AV_PICTURE_TYPE_I)
+			skip_bits_long(gb, ctx->cplx_estimation_trash_p);
+		if (s->pict_type == AV_PICTURE_TYPE_B)
+			skip_bits_long(gb, ctx->cplx_estimation_trash_b);
+
+		if (get_bits_left(gb) < 3) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Header truncated\n");
+			return -1;
+		}
+		ctx->intra_dc_threshold = ff_mpeg4_dc_threshold[get_bits(gb, 3)];
+		if (!s->progressive_sequence) {
+			s->top_field_first = get_bits1(gb);
+			s->alternate_scan  = get_bits1(gb);
+		} else
+			s->alternate_scan = 0;
+	}
+
+	/*if (s->alternate_scan) { } */
+
+	if (s->pict_type == AV_PICTURE_TYPE_S) {
+		if((ctx->vol_sprite_usage == STATIC_SPRITE ||
+			ctx->vol_sprite_usage == GMC_SPRITE)) {
+			//if (mpeg4_decode_sprite_trajectory(ctx, gb) < 0)
+				//return -1;
+			if (ctx->sprite_brightness_change)
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "sprite_brightness_change not supported\n");
+			if (ctx->vol_sprite_usage == STATIC_SPRITE)
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "static sprite not supported\n");
+		} else {
+			memset(s->sprite_offset, 0, sizeof(s->sprite_offset));
+			memset(s->sprite_delta, 0, sizeof(s->sprite_delta));
+		}
+	}
+
+	if (ctx->shape != BIN_ONLY_SHAPE) {
+		s->chroma_qscale = s->qscale = get_bits(gb, s->quant_precision);
+		if (s->qscale == 0) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Error, header damaged or not MPEG-4 header (qscale=0)\n");
+			return -1;  // makes no sense to continue, as there is nothing left from the image then
+		}
+
+		if (s->pict_type != AV_PICTURE_TYPE_I) {
+			s->f_code = get_bits(gb, 3);        /* fcode_for */
+			if (s->f_code == 0) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Error, header damaged or not MPEG-4 header (f_code=0)\n");
+					s->f_code = 1;
+				return -1;  // makes no sense to continue, as there is nothing left from the image then
+			}
+		} else
+			s->f_code = 1;
+
+		if (s->pict_type == AV_PICTURE_TYPE_B) {
+			s->b_code = get_bits(gb, 3);
+			if (s->b_code == 0) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Error, header damaged or not MPEG4 header (b_code=0)\n");
+					s->b_code=1;
+				return -1; // makes no sense to continue, as the MV decoding will break very quickly
+			}
+		} else
+			s->b_code = 1;
+
+		if (1) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "qp:%d fc:%d,%d %s size:%d pro:%d alt:%d top:%d %spel part:%d resync:%d w:%d a:%d rnd:%d vot:%d%s dc:%d ce:%d/%d/%d time:%ld tincr:%d\n",
+				s->qscale, s->f_code, s->b_code,
+				s->pict_type == AV_PICTURE_TYPE_I ? "I" : (s->pict_type == AV_PICTURE_TYPE_P ? "P" : (s->pict_type == AV_PICTURE_TYPE_B ? "B" : "S")),
+				gb->size_in_bits,s->progressive_sequence, s->alternate_scan,
+				s->top_field_first, s->quarter_sample ? "q" : "h",
+				s->data_partitioning, ctx->resync_marker,
+				ctx->num_sprite_warping_points, s->sprite_warping_accuracy,
+				1 - s->no_rounding, s->vo_type,
+				ctx->vol_control_parameters ? " VOLC" : " ", ctx->intra_dc_threshold,
+				ctx->cplx_estimation_trash_i, ctx->cplx_estimation_trash_p,
+				ctx->cplx_estimation_trash_b,
+				s->time,
+				time_increment);
+		}
+
+		if (!ctx->scalability) {
+			if (ctx->shape != RECT_SHAPE && s->pict_type != AV_PICTURE_TYPE_I)
+				skip_bits1(gb);  // vop shape coding type
+		} else {
+			if (ctx->enhancement_type) {
+				int load_backward_shape = get_bits1(gb);
+				if (load_backward_shape)
+					v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "load backward shape isn't supported\n");
+			}
+			skip_bits(gb, 2);  // ref_select_code
+		}
+	}
+	/* detect buggy encoders which don't set the low_delay flag
+	* (divx4/xvid/opendivx). Note we cannot detect divx5 without B-frames
+	* easily (although it's buggy too) */
+	if (s->vo_type == 0 && ctx->vol_control_parameters == 0 &&
+		ctx->divx_version == -1 && s->picture_number == 0) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "looks like this file was encoded with (divx4/(old)xvid/opendivx) -> forcing low_delay flag\n");
+			s->low_delay = 1;
+	}
+
+	s->picture_number++;  // better than pic number==0 always ;)
+
+	// FIXME add short header support
+	//s->y_dc_scale_table = ff_mpeg4_y_dc_scale_table;
+	//s->c_dc_scale_table = ff_mpeg4_c_dc_scale_table;
+
+	return 0;
+}
+
+/**
+ * Decode MPEG-4 headers.
+ * @return <0 if no VOP found (or a damaged one)
+ *         FRAME_SKIPPED if a not coded VOP is found
+ *         0 if a VOP is found
+ */
+int ff_mpeg4_decode_picture_header(struct mpeg4_dec_param *ctx, struct get_bits_context *gb)
+{
+	struct MpegEncContext *s = &ctx->m;
+
+	unsigned startcode, v;
+	int ret;
+	int vol = 0;
+	int bits_per_raw_sample = 0;
+
+	s->ctx = ctx;
+
+	/* search next start code */
+	align_get_bits(gb);
+
+	// If we have not switched to studio profile than we also did not switch bps
+	// that means something else (like a previous instance) outside set bps which
+	// would be inconsistant with the currect state, thus reset it
+	if (!s->studio_profile && bits_per_raw_sample != 8)
+		bits_per_raw_sample = 0;
+
+	if (show_bits(gb, 24) == 0x575630) {
+		skip_bits(gb, 24);
+		if (get_bits(gb, 8) == 0xF0)
+			goto end;
+	}
+
+	startcode = 0xff;
+	for (;;) {
+		if (get_bits_count(gb) >= gb->size_in_bits) {
+			if (gb->size_in_bits == 8) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "frame skip %d\n", gb->size_in_bits);
+				return FRAME_SKIPPED;  // divx bug
+			} else
+				return -1;  // end of stream
+		}
+
+		/* use the bits after the test */
+		v = get_bits(gb, 8);
+		startcode = ((startcode << 8) | v) & 0xffffffff;
+
+		if ((startcode & 0xFFFFFF00) != 0x100)
+			continue;  // no startcode
+
+		if (1) { //debug
+			v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "startcode: %3X \n", startcode);
+			if (startcode <= 0x11F)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Video Object Start\n");
+			else if (startcode <= 0x12F)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Video Object Layer Start\n");
+			else if (startcode <= 0x13F)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Reserved\n");
+			else if (startcode <= 0x15F)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "FGS bp start\n");
+			else if (startcode <= 0x1AF)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Reserved\n");
+			else if (startcode == 0x1B0)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Visual Object Seq Start\n");
+			else if (startcode == 0x1B1)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Visual Object Seq End\n");
+			else if (startcode == 0x1B2)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "User Data\n");
+			else if (startcode == 0x1B3)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Group of VOP start\n");
+			else if (startcode == 0x1B4)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Video Session Error\n");
+			else if (startcode == 0x1B5)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Visual Object Start\n");
+			else if (startcode == 0x1B6)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Video Object Plane start\n");
+			else if (startcode == 0x1B7)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "slice start\n");
+			else if (startcode == 0x1B8)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "extension start\n");
+			else if (startcode == 0x1B9)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "fgs start\n");
+			else if (startcode == 0x1BA)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "FBA Object start\n");
+			else if (startcode == 0x1BB)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "FBA Object Plane start\n");
+			else if (startcode == 0x1BC)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Mesh Object start\n");
+			else if (startcode == 0x1BD)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Mesh Object Plane start\n");
+			else if (startcode == 0x1BE)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Still Texture Object start\n");
+			else if (startcode == 0x1BF)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Texture Spatial Layer start\n");
+			else if (startcode == 0x1C0)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Texture SNR Layer start\n");
+			else if (startcode == 0x1C1)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Texture Tile start\n");
+			else if (startcode == 0x1C2)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "Texture Shape Layer start\n");
+			else if (startcode == 0x1C3)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "stuffing start\n");
+			else if (startcode <= 0x1C5)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "reserved\n");
+			else if (startcode <= 0x1FF)
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "System start\n");
+		}
+
+		if (startcode >= 0x120 && startcode <= 0x12F) {
+			if (vol) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Ignoring multiple VOL headers\n");
+				continue;
+			}
+			vol++;
+			if ((ret = decode_vol_header(ctx, gb)) < 0)
+				return ret;
+		} else if (startcode == USER_DATA_STARTCODE) {
+			decode_user_data(ctx, gb);
+		} else if (startcode == GOP_STARTCODE) {
+			mpeg4_decode_gop_header(s, gb);
+		} else if (startcode == VOS_STARTCODE) {
+		int profile, level;
+		mpeg4_decode_profile_level(s, gb, &profile, &level);
+		if (profile == FF_PROFILE_MPEG4_SIMPLE_STUDIO &&
+			(level > 0 && level < 9)) {
+				s->studio_profile = 1;
+				next_start_code_studio(gb);
+				extension_and_user_data(s, gb, 0);
+			} else if (s->studio_profile) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Mixes studio and non studio profile\n");
+				return -1;
+			}
+			ctx->profile = profile;
+			ctx->level   = level;
+		} else if (startcode == VISUAL_OBJ_STARTCODE) {
+			if (s->studio_profile) {
+				if ((ret = decode_studiovisualobject(ctx, gb)) < 0)
+					return ret;
+			} else
+			mpeg4_decode_visual_object(s, gb);
+		} else if (startcode == VOP_STARTCODE) {
+			break;
+		}
+
+		align_get_bits(gb);
+		startcode = 0xff;
+	}
+
+end:
+	if (s->studio_profile) {
+		if (!bits_per_raw_sample) {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Missing VOL header\n");
+			return -1;
+		}
+		return decode_studio_vop_header(ctx, gb);
+	} else
+		return decode_vop_header(ctx, gb);
+}
+
+int mpeg4_decode_extradata_ps(u8 *buf, int size, struct mpeg4_param_sets *ps)
+{
+	int ret = 0;
+	struct get_bits_context gb;
+
+	ps->head_parsed = false;
+
+	init_get_bits8(&gb, buf, size);
+
+	ret = ff_mpeg4_decode_picture_header(&ps->dec_ps, &gb);
+	if (ret < -1) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Failed to parse extradata\n");
+		return ret;
+	}
+
+	if (ps->dec_ps.m.width && ps->dec_ps.m.height)
+		ps->head_parsed = true;
+
+	return 0;
+}
+
diff --git a/drivers/amvdec_ports/decoder/aml_mpeg4_parser.h b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.h
new file mode 100644
index 0000000..f9b71cf
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.h
@@ -0,0 +1,259 @@
+#ifndef AVCODEC_MPEG4VIDEO_H
+#define AVCODEC_MPEG4VIDEO_H
+
+#include "../aml_vcodec_drv.h"
+#include "../utils/common.h"
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+#include "../utils/pixfmt.h"
+#endif
+
+//mpeg4 profile
+#define FF_PROFILE_MPEG4_SIMPLE                     0
+#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE            1
+#define FF_PROFILE_MPEG4_CORE                       2
+#define FF_PROFILE_MPEG4_MAIN                       3
+#define FF_PROFILE_MPEG4_N_BIT                      4
+#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE           5
+#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION      6
+#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE     7
+#define FF_PROFILE_MPEG4_HYBRID                     8
+#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME         9
+#define FF_PROFILE_MPEG4_CORE_SCALABLE             10
+#define FF_PROFILE_MPEG4_ADVANCED_CODING           11
+#define FF_PROFILE_MPEG4_ADVANCED_CORE             12
+#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13
+#define FF_PROFILE_MPEG4_SIMPLE_STUDIO             14
+#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE           15
+
+// shapes
+#define RECT_SHAPE       0
+#define BIN_SHAPE        1
+#define BIN_ONLY_SHAPE   2
+#define GRAY_SHAPE       3
+
+#define SIMPLE_VO_TYPE           1
+#define CORE_VO_TYPE             3
+#define MAIN_VO_TYPE             4
+#define NBIT_VO_TYPE             5
+#define ARTS_VO_TYPE            10
+#define ACE_VO_TYPE             12
+#define SIMPLE_STUDIO_VO_TYPE   14
+#define CORE_STUDIO_VO_TYPE     15
+#define ADV_SIMPLE_VO_TYPE      17
+
+#define VOT_VIDEO_ID 1
+#define VOT_STILL_TEXTURE_ID 2
+
+#define FF_PROFILE_UNKNOWN -99
+#define FF_PROFILE_RESERVED -100
+
+// aspect_ratio_info
+#define EXTENDED_PAR 15
+
+//vol_sprite_usage / sprite_enable
+#define STATIC_SPRITE 1
+#define GMC_SPRITE 2
+
+#define MOTION_MARKER 0x1F001
+#define DC_MARKER     0x6B001
+
+#define VOS_STARTCODE        0x1B0
+#define USER_DATA_STARTCODE  0x1B2
+#define GOP_STARTCODE        0x1B3
+#define VISUAL_OBJ_STARTCODE 0x1B5
+#define VOP_STARTCODE        0x1B6
+#define SLICE_STARTCODE      0x1B7
+#define EXT_STARTCODE        0x1B8
+
+#define QUANT_MATRIX_EXT_ID  0x3
+
+/* smaller packets likely don't contain a real frame */
+#define MAX_NVOP_SIZE 19
+
+#define IS_3IV1 0
+
+#define CHROMA_420 1
+#define CHROMA_422 2
+#define CHROMA_444 3
+
+#define FF_ASPECT_EXTENDED 15
+
+#define AV_NOPTS_VALUE          (LONG_MIN)
+
+/**
+ * Return value for header parsers if frame is not coded.
+ * */
+#define FRAME_SKIPPED 100
+
+enum AVPictureType {
+    AV_PICTURE_TYPE_NONE = 0, ///< Undefined
+    AV_PICTURE_TYPE_I,     ///< Intra
+    AV_PICTURE_TYPE_P,     ///< Predicted
+    AV_PICTURE_TYPE_B,     ///< Bi-dir predicted
+    AV_PICTURE_TYPE_S,     ///< S(GMC)-VOP MPEG-4
+    AV_PICTURE_TYPE_SI,    ///< Switching Intra
+    AV_PICTURE_TYPE_SP,    ///< Switching Predicted
+    AV_PICTURE_TYPE_BI,    ///< BI type
+};
+
+struct VLC {
+	int bits;
+	short (*table)[2]; ///< code, bits
+	int table_size, table_allocated;
+};
+
+/**
+ * MpegEncContext.
+ */
+struct MpegEncContext {
+	struct mpeg4_dec_param *ctx;
+
+	/* the following parameters must be initialized before encoding */
+	int width, height;///< picture size. must be a multiple of 16
+	int codec_tag;             ///< internal codec_tag upper case converted from avctx codec_tag
+	int picture_number;       //FIXME remove, unclear definition
+
+	/** matrix transmitted in the bitstream */
+	u16 intra_matrix[64];
+	u16 chroma_intra_matrix[64];
+	u16 inter_matrix[64];
+	u16 chroma_inter_matrix[64];
+
+	/* MPEG-4 specific */
+	int studio_profile;
+	int time_base;                  ///< time in seconds of last I,P,S Frame
+	int quant_precision;
+	int quarter_sample;              ///< 1->qpel, 0->half pel ME/MC
+	int aspect_ratio_info; //FIXME remove
+	int sprite_warping_accuracy;
+	int data_partitioning;           ///< data partitioning flag from header
+	int low_delay;                   ///< no reordering needed / has no B-frames
+	int vo_type;
+	int mpeg_quant;
+
+	/* divx specific, used to workaround (many) bugs in divx5 */
+	int divx_packed;
+
+	/* MPEG-2-specific - I wished not to have to support this mess. */
+	int progressive_sequence;
+
+	int progressive_frame;
+	int interlaced_dct;
+
+	int h_edge_pos, v_edge_pos;///< horizontal / vertical position of the right/bottom edge (pixel replication)
+	const u8 *y_dc_scale_table;     ///< qscale -> y_dc_scale table
+	const u8 *c_dc_scale_table;     ///< qscale -> c_dc_scale table
+	int qscale;		    ///< QP
+	int chroma_qscale;	    ///< chroma QP
+	int pict_type;		    ///< AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, ...
+	int f_code;		    ///< forward MV resolution
+	int b_code;		    ///< backward MV resolution for B-frames (MPEG-4)
+	int no_rounding;  /**< apply no rounding to motion compensation (MPEG-4, msmpeg4, ...)
+	    for B-frames rounding mode is always 0 */
+	int last_time_base;
+	long time;		    ///< time of current frame
+	long last_non_b_time;
+	u16 pp_time;		    ///< time distance between the last 2 p,s,i frames
+	u16 pb_time;		    ///< time distance between the last b and p,s,i frame
+	u16 pp_field_time;
+	u16 pb_field_time;	    ///< like above, just for interlaced
+	int real_sprite_warping_points;
+	int sprite_offset[2][2];	     ///< sprite offset[isChroma][isMVY]
+	int sprite_delta[2][2];	     ///< sprite_delta [isY][isMVY]
+	int mcsel;
+	int partitioned_frame;	     ///< is current frame partitioned
+	int top_field_first;
+	int alternate_scan;
+	int last_dc[3];                ///< last DC values for MPEG-1
+	int dct_precision;
+	int intra_dc_precision;
+	int frame_pred_frame_dct;
+	int q_scale_type;
+	int context_reinit;
+	int chroma_format;
+};
+
+struct mpeg4_dec_param {
+	struct MpegEncContext m;
+
+	/// number of bits to represent the fractional part of time
+	int time_increment_bits;
+	int shape;
+	int vol_sprite_usage;
+	int sprite_brightness_change;
+	int num_sprite_warping_points;
+	/// sprite trajectory points
+	u16 sprite_traj[4][2];
+	/// sprite shift [isChroma]
+	int sprite_shift[2];
+
+	// reversible vlc
+	int rvlc;
+	/// could this stream contain resync markers
+	int resync_marker;
+	/// time distance of first I -> B, used for interlaced B-frames
+	int t_frame;
+
+	int new_pred;
+	int enhancement_type;
+	int scalability;
+	int use_intra_dc_vlc;
+
+	/// QP above which the ac VLC should be used for intra dc
+	int intra_dc_threshold;
+
+	/* bug workarounds */
+	int divx_version;
+	int divx_build;
+	int xvid_build;
+	int lavc_build;
+
+	/// flag for having shown the warning about invalid Divx B-frames
+	int showed_packed_warning;
+	/** does the stream contain the low_delay flag,
+	*  used to work around buggy encoders. */
+	int vol_control_parameters;
+	int cplx_estimation_trash_i;
+	int cplx_estimation_trash_p;
+	int cplx_estimation_trash_b;
+
+	struct VLC studio_intra_tab[12];
+	struct VLC studio_luma_dc;
+	struct VLC studio_chroma_dc;
+
+	int rgb;
+
+	struct AVRational time_base;
+	int ticks_per_frame;
+	struct AVRational sample_aspect_ratio;
+	enum AVColorPrimaries color_primaries;
+	enum AVColorTransferCharacteristic color_trc;
+	enum AVColorSpace colorspace;
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+	enum AVPixelFormat pix_fmt;
+	enum AVColorRange color_range;
+	enum AVChromaLocation chroma_sample_location;
+#endif
+	int err_recognition;
+	int idct_algo;
+	int bits_per_raw_sample;
+	int profile;
+	int level;
+	struct AVRational framerate;
+	int flags;
+};
+
+struct mpeg4_param_sets {
+	bool head_parsed;
+	/* currently active parameter sets */
+	struct mpeg4_dec_param dec_ps;
+};
+
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+int mpeg4_decode_extradata_ps(u8 *buf, int size, struct mpeg4_param_sets *ps);
+#else
+inline int mpeg4_decode_extradata_ps(u8 *buf, int size, struct mpeg4_param_sets *ps) { return -1; }
+#endif
+
+#endif
+
diff --git a/drivers/amvdec_ports/decoder/aml_vp9_parser.c b/drivers/amvdec_ports/decoder/aml_vp9_parser.c
new file mode 100644
index 0000000..21d5283
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/aml_vp9_parser.c
@@ -0,0 +1,299 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+
+#include "aml_vp9_parser.h"
+#include "../utils/get_bits.h"
+#include "../utils/put_bits.h"
+#include "../utils/golomb.h"
+#include "../utils/common.h"
+#include "utils.h"
+
+#define VP9_SYNCCODE 0x498342
+
+static int read_colorspace_details(struct VP9Context *s, int profile)
+{
+	static const enum AVColorSpace colorspaces[8] = {
+		AVCOL_SPC_UNSPECIFIED, AVCOL_SPC_BT470BG, AVCOL_SPC_BT709, AVCOL_SPC_SMPTE170M,
+		AVCOL_SPC_SMPTE240M, AVCOL_SPC_BT2020_NCL, AVCOL_SPC_RESERVED, AVCOL_SPC_RGB,
+	};
+
+	enum AVColorSpace colorspace;
+	int color_range;
+	int bits = profile <= 1 ? 0 : 1 + get_bits1(&s->gb); // 0:8, 1:10, 2:12
+
+	s->bpp_index = bits;
+	s->s.h.bpp = 8 + bits * 2;
+	s->bytesperpixel = (7 + s->s.h.bpp) >> 3;
+	colorspace = colorspaces[get_bits(&s->gb, 3)];
+	if (colorspace == AVCOL_SPC_RGB) { // RGB = profile 1
+		if (profile & 1) {
+			if (get_bits1(&s->gb)) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Reserved bit set in RGB\n");
+				return -1;
+			}
+		} else {
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "RGB not supported in profile %d\n", profile);
+			return -1;
+		}
+	} else {
+		static const enum AVPixelFormat pix_fmt_for_ss[3][2 /* v */][2 /* h */] = {
+			{ { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P },
+			{ AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV420P } },
+			{ { AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10 },
+			{ AV_PIX_FMT_YUV440P10, AV_PIX_FMT_YUV420P10 } },
+			{ { AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12 },
+			{ AV_PIX_FMT_YUV440P12, AV_PIX_FMT_YUV420P12 } }};
+		color_range = get_bits1(&s->gb) ? 2 : 1;
+		if (profile & 1) {
+			s->ss_h = get_bits1(&s->gb);
+			s->ss_v = get_bits1(&s->gb);
+			s->pix_fmt = pix_fmt_for_ss[bits][s->ss_v][s->ss_h];
+			if (s->pix_fmt == AV_PIX_FMT_YUV420P) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "YUV 4:2:0 not supported in profile %d\n", profile);
+				return -1;
+			} else if (get_bits1(&s->gb)) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Profile %d color details reserved bit set\n", profile);
+				return -1;
+			}
+		} else {
+			s->ss_h = s->ss_v = 1;
+			s->pix_fmt = pix_fmt_for_ss[bits][1][1];
+		}
+	}
+
+	return 0;
+}
+
+int decode_frame_header(const u8 *data, int size, struct VP9Context *s, int *ref)
+{
+	int ret, last_invisible, profile;
+
+	/* general header */
+	if ((ret = init_get_bits8(&s->gb, data, size)) < 0) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Failed to initialize bitstream reader\n");
+		return ret;
+	}
+
+	if (get_bits(&s->gb, 2) != 0x2) { // frame marker
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid frame marker\n");
+		return -1;
+	}
+
+	profile  = get_bits1(&s->gb);
+	profile |= get_bits1(&s->gb) << 1;
+	if (profile == 3)
+		profile += get_bits1(&s->gb);
+
+	if (profile > 3) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Profile %d is not yet supported\n", profile);
+		return -1;
+	}
+
+	s->s.h.profile = profile;
+	if (get_bits1(&s->gb)) {
+		*ref = get_bits(&s->gb, 3);
+		return 0;
+	}
+
+	s->last_keyframe  = s->s.h.keyframe;
+	s->s.h.keyframe   = !get_bits1(&s->gb);
+
+	last_invisible   = s->s.h.invisible;
+	s->s.h.invisible = !get_bits1(&s->gb);
+	s->s.h.errorres  = get_bits1(&s->gb);
+	s->s.h.use_last_frame_mvs = !s->s.h.errorres && !last_invisible;
+
+	if (s->s.h.keyframe) {
+		if (get_bits_long(&s->gb, 24) != VP9_SYNCCODE) { // synccode
+			v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid sync code\n");
+			return -1;
+		}
+		if ((ret = read_colorspace_details(s,profile)) < 0)
+			return ret;
+		// for profile 1, here follows the subsampling bits
+		s->s.h.refreshrefmask = 0xff;
+		s->width = get_bits(&s->gb, 16) + 1;
+		s->height = get_bits(&s->gb, 16) + 1;
+		if (get_bits1(&s->gb)) { // has scaling
+			s->render_width = get_bits(&s->gb, 16) + 1;
+			s->render_height = get_bits(&s->gb, 16) + 1;
+		} else {
+			s->render_width = s->width;
+			s->render_height = s->height;
+		}
+		/*pr_info("keyframe res: (%d x %d), render size: (%d x %d)\n",
+			s->width, s->height, s->render_width, s->render_height);*/
+	} else {
+		s->s.h.intraonly = s->s.h.invisible ? get_bits1(&s->gb) : 0;
+		s->s.h.resetctx  = s->s.h.errorres ? 0 : get_bits(&s->gb, 2);
+		if (s->s.h.intraonly) {
+			if (get_bits_long(&s->gb, 24) != VP9_SYNCCODE) { // synccode
+				v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid sync code\n");
+				return -1;
+			}
+			if (profile >= 1) {
+				if ((ret = read_colorspace_details(s, profile)) < 0)
+					return ret;
+			} else {
+				s->ss_h = s->ss_v = 1;
+				s->s.h.bpp = 8;
+				s->bpp_index = 0;
+				s->bytesperpixel = 1;
+				s->pix_fmt = AV_PIX_FMT_YUV420P;
+			}
+			s->s.h.refreshrefmask = get_bits(&s->gb, 8);
+			s->width = get_bits(&s->gb, 16) + 1;
+			s->height = get_bits(&s->gb, 16) + 1;
+			if (get_bits1(&s->gb)) { // has scaling
+				s->render_width = get_bits(&s->gb, 16) + 1;
+				s->render_height = get_bits(&s->gb, 16) + 1;
+			} else {
+				s->render_width = s->width;
+				s->render_height = s->height;
+			}
+			v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "intra res: (%d x %d), render size: (%d x %d)\n",
+				s->width, s->height, s->render_width, s->render_height);
+		} else {
+			s->s.h.refreshrefmask = get_bits(&s->gb, 8);
+			s->s.h.refidx[0]      = get_bits(&s->gb, 3);
+			s->s.h.signbias[0]    = get_bits1(&s->gb) && !s->s.h.errorres;
+			s->s.h.refidx[1]      = get_bits(&s->gb, 3);
+			s->s.h.signbias[1]    = get_bits1(&s->gb) && !s->s.h.errorres;
+			s->s.h.refidx[2]      = get_bits(&s->gb, 3);
+			s->s.h.signbias[2]    = get_bits1(&s->gb) && !s->s.h.errorres;
+
+			/*refresh_frame_flags;
+			for (i = 0; i < REFS_PER_FRAME; ++i) {
+				frame_refs[i];
+				ref_frame_sign_biases[i];
+			}
+			frame_size_from_refs();
+			high_precision_mv;
+			interp_filter();*/
+
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int vp9_superframe_split_filter(struct vp9_superframe_split *s)
+{
+	int i, j, ret, marker;
+	bool is_superframe = false;
+	int *prefix = (int *)s->data;
+
+	if (!s->data)
+		return -1;
+
+	#define AML_PREFIX ('V' << 24 | 'L' << 16 | 'M' << 8 | 'A')
+	if (prefix[3] == AML_PREFIX) {
+		s->prefix_size = 16;
+		/*pr_info("the frame data has beed added header\n");*/
+	}
+
+	marker = s->data[s->data_size - 1];
+	if ((marker & 0xe0) == 0xc0) {
+		int length_size = 1 + ((marker >> 3) & 0x3);
+		int   nb_frames = 1 + (marker & 0x7);
+		int    idx_size = 2 + nb_frames * length_size;
+
+		if (s->data_size >= idx_size &&
+			s->data[s->data_size - idx_size] == marker) {
+			s64 total_size = 0;
+			int idx = s->data_size + 1 - idx_size;
+
+			for (i = 0; i < nb_frames; i++) {
+				int frame_size = 0;
+				for (j = 0; j < length_size; j++)
+					frame_size |= s->data[idx++] << (j * 8);
+
+				total_size += frame_size;
+				if (frame_size < 0 ||
+					total_size > s->data_size - idx_size) {
+					v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid frame size in a sframe: %d\n",
+						frame_size);
+					ret = -EINVAL;
+					goto fail;
+				}
+				s->sizes[i] = frame_size;
+			}
+
+			s->nb_frames         = nb_frames;
+			s->size              = total_size;
+			s->next_frame        = 0;
+			s->next_frame_offset = 0;
+			is_superframe        = true;
+		}
+	}else {
+		s->nb_frames = 1;
+		s->sizes[0]  = s->data_size;
+		s->size      = s->data_size;
+	}
+
+	/*pr_info("sframe: %d, frames: %d, IN: %x, OUT: %x\n",
+		is_superframe, s->nb_frames,
+		s->data_size, s->size);*/
+
+	/* parse uncompressed header. */
+	if (is_superframe) {
+		/* bitstream profile. */
+		/* frame type. (intra or inter) */
+		/* colorspace descriptor */
+		/* ... */
+
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "the frame is a superframe.\n");
+	}
+
+	/*pr_err("in: %x, %d, out: %x, sizes %d,%d,%d,%d,%d,%d,%d,%d\n",
+		s->data_size,
+		s->nb_frames,
+		s->size,
+		s->sizes[0],
+		s->sizes[1],
+		s->sizes[2],
+		s->sizes[3],
+		s->sizes[4],
+		s->sizes[5],
+		s->sizes[6],
+		s->sizes[7]);*/
+
+	return 0;
+fail:
+	return ret;
+}
+
+int vp9_decode_extradata_ps(u8 *data, int size, struct vp9_param_sets *ps)
+{
+	int i, ref = -1, ret = 0;
+	struct vp9_superframe_split s = {0};
+
+	/*parse superframe.*/
+	s.data = data;
+	s.data_size = size;
+	ret = vp9_superframe_split_filter(&s);
+	if (ret) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "parse frames failed.\n");
+		return ret;
+	}
+
+	for (i = 0; i < s.nb_frames; i++) {
+		u32 len = s.sizes[i] - s.prefix_size;
+		u8 *buf = s.data + s.next_frame_offset + s.prefix_size;
+
+		ret = decode_frame_header(buf, len, &ps->ctx, &ref);
+		if (!ret) {
+			ps->head_parsed = ref < 0 ? true : false;
+			return 0;
+		}
+
+		s.next_frame_offset = len + s.prefix_size;
+	}
+
+	return ret;
+}
+
diff --git a/drivers/amvdec_ports/decoder/aml_vp9_parser.h b/drivers/amvdec_ports/decoder/aml_vp9_parser.h
new file mode 100644
index 0000000..ddeddec
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/aml_vp9_parser.h
@@ -0,0 +1,184 @@
+/*
+ * drivers/amvdec_ports/decoder/aml_vp9_parser.h
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef AML_VP9_PARSER_H
+#define AML_VP9_PARSER_H
+
+#include "../aml_vcodec_drv.h"
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+#include "../utils/pixfmt.h"
+#include "../utils/get_bits.h"
+#endif
+
+#define MAX_SEGMENT	8
+
+struct VP9BitstreamHeader {
+	// bitstream header
+	u8 profile;
+	u8 bpp;
+	u8 keyframe;
+	u8 invisible;
+	u8 errorres;
+	u8 intraonly;
+	u8 resetctx;
+	u8 refreshrefmask;
+	u8 highprecisionmvs;
+	u8 allowcompinter;
+	u8 refreshctx;
+	u8 parallelmode;
+	u8 framectxid;
+	u8 use_last_frame_mvs;
+	u8 refidx[3];
+	u8 signbias[3];
+	u8 fixcompref;
+	u8 varcompref[2];
+	struct {
+		u8 level;
+		char sharpness;
+	} filter;
+	struct {
+		u8 enabled;
+		u8 updated;
+		char mode[2];
+		char ref[4];
+	} lf_delta;
+	u8 yac_qi;
+	char ydc_qdelta, uvdc_qdelta, uvac_qdelta;
+	u8 lossless;
+	struct {
+		u8 enabled;
+		u8 temporal;
+		u8 absolute_vals;
+		u8 update_map;
+		u8 prob[7];
+		u8 pred_prob[3];
+		struct {
+			u8 q_enabled;
+			u8 lf_enabled;
+			u8 ref_enabled;
+			u8 skip_enabled;
+			u8 ref_val;
+			int16_t q_val;
+			char lf_val;
+			int16_t qmul[2][2];
+			u8 lflvl[4][2];
+		} feat[MAX_SEGMENT];
+	} segmentation;
+	struct {
+		u32 log2_tile_cols, log2_tile_rows;
+		u32 tile_cols, tile_rows;
+	} tiling;
+
+	int uncompressed_header_size;
+	int compressed_header_size;
+};
+
+struct VP9SharedContext {
+	struct VP9BitstreamHeader h;
+
+	//struct ThreadFrame refs[8];
+#define CUR_FRAME 0
+#define REF_FRAME_MVPAIR 1
+#define REF_FRAME_SEGMAP 2
+	//struct VP9Frame frames[3];
+};
+
+struct VP9Context {
+	struct VP9SharedContext s;
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+	struct get_bits_context gb;
+#endif
+	int pass, active_tile_cols;
+
+	u8 ss_h, ss_v;
+	u8 last_bpp, bpp_index, bytesperpixel;
+	u8 last_keyframe;
+	// sb_cols/rows, rows/cols and last_fmt are used for allocating all internal
+	// arrays, and are thus per-thread. w/h and gf_fmt are synced between threads
+	// and are therefore per-stream. pix_fmt represents the value in the header
+	// of the currently processed frame.
+	int width;
+	int height;
+
+	int render_width;
+	int render_height;
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+	enum AVPixelFormat pix_fmt, last_fmt, gf_fmt;
+#endif
+	u32 sb_cols, sb_rows, rows, cols;
+
+	struct {
+		u8 lim_lut[64];
+		u8 mblim_lut[64];
+	} filter_lut;
+	struct {
+		u8 coef[4][2][2][6][6][3];
+	} prob_ctx[4];
+	struct {
+		u8 coef[4][2][2][6][6][11];
+	} prob;
+
+	// contextual (above) cache
+	u8 *above_partition_ctx;
+	u8 *above_mode_ctx;
+	// FIXME maybe merge some of the below in a flags field?
+	u8 *above_y_nnz_ctx;
+	u8 *above_uv_nnz_ctx[2];
+	u8 *above_skip_ctx; // 1bit
+	u8 *above_txfm_ctx; // 2bit
+	u8 *above_segpred_ctx; // 1bit
+	u8 *above_intra_ctx; // 1bit
+	u8 *above_comp_ctx; // 1bit
+	u8 *above_ref_ctx; // 2bit
+	u8 *above_filter_ctx;
+
+	// whole-frame cache
+	u8 *intra_pred_data[3];
+
+	// block reconstruction intermediates
+	int block_alloc_using_2pass;
+	uint16_t mvscale[3][2];
+	u8 mvstep[3][2];
+};
+
+struct vp9_superframe_split {
+	/*in data*/
+	u8 *data;
+	u32 data_size;
+
+	/*out data*/
+	int nb_frames;
+	int size;
+	int next_frame;
+	u32 next_frame_offset;
+	int prefix_size;
+	int sizes[8];
+};
+
+struct vp9_param_sets {
+	bool head_parsed;
+	struct VP9Context ctx;
+};
+
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+int vp9_superframe_split_filter(struct vp9_superframe_split *s);
+int vp9_decode_extradata_ps(u8 *data, int size, struct vp9_param_sets *ps);
+#else
+inline int vp9_decode_extradata_ps(u8 *data, int size, struct vp9_param_sets *ps) { return -1; }
+#endif
+
+#endif //AML_VP9_PARSER_H
diff --git a/drivers/amvdec_ports/decoder/utils.h b/drivers/amvdec_ports/decoder/utils.h
new file mode 100644
index 0000000..26b1552
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/utils.h
@@ -0,0 +1,31 @@
+/*
+ * drivers/amlogic/media_modules/amvdec_ports/decoder/utils.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _UTILS_H
+#define _UTILS_H
+
+#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
+#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
+#define CLAMP(x, low, high) \
+	(((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
+#define BITAT(x, n) ((x & (1 << n)) == (1 << n))
+
+typedef unsigned char uint8_t;
+typedef int int32_t;
+typedef unsigned int uint32_t;
+
+#endif //_UTILS_H
diff --git a/drivers/amvdec_ports/decoder/vdec_av1_if.c b/drivers/amvdec_ports/decoder/vdec_av1_if.c
new file mode 100644
index 0000000..c28ca10
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/vdec_av1_if.c
@@ -0,0 +1,1374 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <uapi/linux/swab.h>
+#include "../vdec_drv_if.h"
+#include "../aml_vcodec_util.h"
+#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_drv.h"
+#include "../aml_vcodec_adapt.h"
+#include "../vdec_drv_base.h"
+#include "../utils/common.h"
+
+#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2
+#include <trace/events/meson_atrace.h>
+
+#define PREFIX_SIZE	(16)
+
+#define HEADER_BUFFER_SIZE			(32 * 1024)
+#define SYNC_CODE				(0x498342)
+
+extern int av1_need_prefix;
+
+/**
+ * struct av1_fb - av1 decode frame buffer information
+ * @vdec_fb_va  : virtual address of struct vdec_fb
+ * @y_fb_dma    : dma address of Y frame buffer (luma)
+ * @c_fb_dma    : dma address of C frame buffer (chroma)
+ * @poc         : picture order count of frame buffer
+ * @reserved    : for 8 bytes alignment
+ */
+struct av1_fb {
+	uint64_t vdec_fb_va;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	int32_t poc;
+	uint32_t reserved;
+};
+
+/**
+ * struct vdec_av1_dec_info - decode information
+ * @dpb_sz		: decoding picture buffer size
+ * @resolution_changed  : resoltion change happen
+ * @reserved		: for 8 bytes alignment
+ * @bs_dma		: Input bit-stream buffer dma address
+ * @y_fb_dma		: Y frame buffer dma address
+ * @c_fb_dma		: C frame buffer dma address
+ * @vdec_fb_va		: VDEC frame buffer struct virtual address
+ */
+struct vdec_av1_dec_info {
+	uint32_t dpb_sz;
+	uint32_t resolution_changed;
+	uint32_t reserved;
+	uint64_t bs_dma;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	uint64_t vdec_fb_va;
+};
+
+/**
+ * struct vdec_av1_vsi - shared memory for decode information exchange
+ *                        between VPU and Host.
+ *                        The memory is allocated by VPU then mapping to Host
+ *                        in vpu_dec_init() and freed in vpu_dec_deinit()
+ *                        by VPU.
+ *                        AP-W/R : AP is writer/reader on this item
+ *                        VPU-W/R: VPU is write/reader on this item
+ * @hdr_buf      : Header parsing buffer (AP-W, VPU-R)
+ * @list_free    : free frame buffer ring list (AP-W/R, VPU-W)
+ * @list_disp    : display frame buffer ring list (AP-R, VPU-W)
+ * @dec          : decode information (AP-R, VPU-W)
+ * @pic          : picture information (AP-R, VPU-W)
+ * @crop         : crop information (AP-R, VPU-W)
+ */
+struct vdec_av1_vsi {
+	char *header_buf;
+	int sps_size;
+	int pps_size;
+	int sei_size;
+	int head_offset;
+	struct vdec_av1_dec_info dec;
+	struct vdec_pic_info pic;
+	struct vdec_pic_info cur_pic;
+	struct v4l2_rect crop;
+	bool is_combine;
+	int nalu_pos;
+};
+
+/**
+ * struct vdec_av1_inst - av1 decoder instance
+ * @num_nalu : how many nalus be decoded
+ * @ctx      : point to aml_vcodec_ctx
+ * @vsi      : VPU shared information
+ */
+struct vdec_av1_inst {
+	unsigned int num_nalu;
+	struct aml_vcodec_ctx *ctx;
+	struct aml_vdec_adapt vdec;
+	struct vdec_av1_vsi *vsi;
+	struct aml_dec_params parms;
+	struct completion comp;
+	struct vdec_comp_buf_info comp_info;
+};
+
+/*!\brief OBU types. */
+enum OBU_TYPE {
+	OBU_SEQUENCE_HEADER = 1,
+	OBU_TEMPORAL_DELIMITER = 2,
+	OBU_FRAME_HEADER = 3,
+	OBU_TILE_GROUP = 4,
+	OBU_METADATA = 5,
+	OBU_FRAME = 6,
+	OBU_REDUNDANT_FRAME_HEADER = 7,
+	OBU_TILE_LIST = 8,
+	OBU_PADDING = 15,
+};
+
+/*!\brief OBU metadata types. */
+enum OBU_METADATA_TYPE {
+	OBU_METADATA_TYPE_RESERVED_0 = 0,
+	OBU_METADATA_TYPE_HDR_CLL = 1,
+	OBU_METADATA_TYPE_HDR_MDCV = 2,
+	OBU_METADATA_TYPE_SCALABILITY = 3,
+	OBU_METADATA_TYPE_ITUT_T35 = 4,
+	OBU_METADATA_TYPE_TIMECODE = 5,
+};
+
+struct ObuHeader {
+	size_t size;  // Size (1 or 2 bytes) of the OBU header (including the
+			// optional OBU extension header) in the bitstream.
+	enum OBU_TYPE type;
+	int has_size_field;
+	int has_extension;
+	// The following fields come from the OBU extension header and therefore are
+	// only used if has_extension is true.
+	int temporal_layer_id;
+	int spatial_layer_id;
+};
+
+static const size_t kMaximumLeb128Size = 8;
+static const u8 kLeb128ByteMask = 0x7f;  // Binary: 01111111
+
+// Disallow values larger than 32-bits to ensure consistent behavior on 32 and
+// 64 bit targets: value is typically used to determine buffer allocation size
+// when decoded.
+static const u64 kMaximumLeb128Value = ULONG_MAX;
+
+char obu_type_name[16][32] = {
+	"UNKNOWN",
+	"OBU_SEQUENCE_HEADER",
+	"OBU_TEMPORAL_DELIMITER",
+	"OBU_FRAME_HEADER",
+	"OBU_TILE_GROUP",
+	"OBU_METADATA",
+	"OBU_FRAME",
+	"OBU_REDUNDANT_FRAME_HEADER",
+	"OBU_TILE_LIST",
+	"UNKNOWN",
+	"UNKNOWN",
+	"UNKNOWN",
+	"UNKNOWN",
+	"UNKNOWN",
+	"UNKNOWN",
+	"OBU_PADDING"
+};
+
+char meta_type_name[6][32] = {
+	"OBU_METADATA_TYPE_RESERVED_0",
+	"OBU_METADATA_TYPE_HDR_CLL",
+	"OBU_METADATA_TYPE_HDR_MDCV",
+	"OBU_METADATA_TYPE_SCALABILITY",
+	"OBU_METADATA_TYPE_ITUT_T35",
+	"OBU_METADATA_TYPE_TIMECODE"
+};
+
+struct read_bit_buffer {
+	const u8 *bit_buffer;
+	const u8 *bit_buffer_end;
+	u32 bit_offset;
+};
+
+struct DataBuffer {
+	const u8 *data;
+	size_t size;
+};
+
+static int vdec_write_nalu(struct vdec_av1_inst *inst,
+	u8 *buf, u32 size, u64 ts);
+static int vdec_get_dw_mode(struct vdec_av1_inst *inst, int dw_mode);
+
+static void get_pic_info(struct vdec_av1_inst *inst,
+			 struct vdec_pic_info *pic)
+{
+	*pic = inst->vsi->pic;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"pic(%d, %d), buf(%d, %d)\n",
+		 pic->visible_width, pic->visible_height,
+		 pic->coded_width, pic->coded_height);
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"Y(%d, %d), C(%d, %d)\n",
+		pic->y_bs_sz, pic->y_len_sz,
+		pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_crop_info(struct vdec_av1_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = inst->vsi->crop.left;
+	cr->top = inst->vsi->crop.top;
+	cr->width = inst->vsi->crop.width;
+	cr->height = inst->vsi->crop.height;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"l=%d, t=%d, w=%d, h=%d\n",
+		 cr->left, cr->top, cr->width, cr->height);
+}
+
+static void get_dpb_size(struct vdec_av1_inst *inst, unsigned int *dpb_sz)
+{
+	*dpb_sz = inst->vsi->dec.dpb_sz;
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, "sz=%d\n", *dpb_sz);
+}
+
+static u32 vdec_config_default_parms(u8 *parm)
+{
+	u8 *pbuf = parm;
+
+	pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+	pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
+	pbuf += sprintf(pbuf, "av1_double_write_mode:1;");
+	pbuf += sprintf(pbuf, "av1_buf_width:1920;");
+	pbuf += sprintf(pbuf, "av1_buf_height:1088;");
+	pbuf += sprintf(pbuf, "av1_max_pic_w:4096;");
+	pbuf += sprintf(pbuf, "av1_max_pic_h:2304;");
+	pbuf += sprintf(pbuf, "save_buffer_mode:0;");
+	pbuf += sprintf(pbuf, "no_head:0;");
+	pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
+	pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;");
+
+	return parm - pbuf;
+}
+
+static void vdec_parser_parms(struct vdec_av1_inst *inst)
+{
+	struct aml_vcodec_ctx *ctx = inst->ctx;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+		"%s:parms_status = 0x%x, present_flag = %d\n",
+		__func__, ctx->config.parm.dec.parms_status,
+		ctx->config.parm.dec.hdr.color_parms.present_flag);
+	if (ctx->config.parm.dec.parms_status &
+		V4L2_CONFIG_PARM_DECODE_CFGINFO) {
+		u8 *pbuf = ctx->config.buf;
+
+		pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+		pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
+			ctx->config.parm.dec.cfg.ref_buf_margin);
+		pbuf += sprintf(pbuf, "av1_double_write_mode:%d;",
+			ctx->config.parm.dec.cfg.double_write_mode);
+		pbuf += sprintf(pbuf, "av1_buf_width:1920;");
+		pbuf += sprintf(pbuf, "av1_buf_height:1088;");
+		pbuf += sprintf(pbuf, "save_buffer_mode:0;");
+		pbuf += sprintf(pbuf, "no_head:0;");
+		pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
+			ctx->config.parm.dec.cfg.canvas_mem_mode);
+		pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;",
+			ctx->config.parm.dec.cfg.canvas_mem_endian);
+		pbuf += sprintf(pbuf, "parm_v4l_low_latency_mode:%d;",
+			ctx->config.parm.dec.cfg.low_latency_mode);
+		pbuf += sprintf(pbuf, "parm_v4l_duration:%d;",
+			ctx->config.parm.dec.cfg.duration);
+		ctx->config.length = pbuf - ctx->config.buf;
+	} else {
+		ctx->config.parm.dec.cfg.double_write_mode = 1;
+		ctx->config.parm.dec.cfg.ref_buf_margin = 7;
+		ctx->config.length = vdec_config_default_parms(ctx->config.buf);
+	}
+
+	if ((ctx->config.parm.dec.parms_status &
+		V4L2_CONFIG_PARM_DECODE_HDRINFO) &&
+		ctx->config.parm.dec.hdr.color_parms.present_flag) {
+		u8 *pbuf = ctx->config.buf + ctx->config.length;
+
+		pbuf += sprintf(pbuf, "HDRStaticInfo:%d;", 1);
+		pbuf += sprintf(pbuf, "signal_type:%d;",
+			ctx->config.parm.dec.hdr.signal_type);
+		pbuf += sprintf(pbuf, "mG.x:%d;",
+			ctx->config.parm.dec.hdr.color_parms.primaries[0][0]);
+		pbuf += sprintf(pbuf, "mG.y:%d;",
+			ctx->config.parm.dec.hdr.color_parms.primaries[0][1]);
+		pbuf += sprintf(pbuf, "mB.x:%d;",
+			ctx->config.parm.dec.hdr.color_parms.primaries[1][0]);
+		pbuf += sprintf(pbuf, "mB.y:%d;",
+			ctx->config.parm.dec.hdr.color_parms.primaries[1][1]);
+		pbuf += sprintf(pbuf, "mR.x:%d;",
+			ctx->config.parm.dec.hdr.color_parms.primaries[2][0]);
+		pbuf += sprintf(pbuf, "mR.y:%d;",
+			ctx->config.parm.dec.hdr.color_parms.primaries[2][1]);
+		pbuf += sprintf(pbuf, "mW.x:%d;",
+			ctx->config.parm.dec.hdr.color_parms.white_point[0]);
+		pbuf += sprintf(pbuf, "mW.y:%d;",
+			ctx->config.parm.dec.hdr.color_parms.white_point[1]);
+		pbuf += sprintf(pbuf, "mMaxDL:%d;",
+			ctx->config.parm.dec.hdr.color_parms.luminance[0] * 1000);
+		pbuf += sprintf(pbuf, "mMinDL:%d;",
+			ctx->config.parm.dec.hdr.color_parms.luminance[1]);
+		pbuf += sprintf(pbuf, "mMaxCLL:%d;",
+			ctx->config.parm.dec.hdr.color_parms.content_light_level.max_content);
+		pbuf += sprintf(pbuf, "mMaxFALL:%d;",
+			ctx->config.parm.dec.hdr.color_parms.content_light_level.max_pic_average);
+		ctx->config.length	= pbuf - ctx->config.buf;
+		inst->parms.hdr		= ctx->config.parm.dec.hdr;
+		inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_HDRINFO;
+	}
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+		"config.buf = %s\n", ctx->config.buf);
+
+	inst->vdec.config	= ctx->config;
+	inst->parms.cfg		= ctx->config.parm.dec.cfg;
+	inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO;
+}
+
+static int vdec_av1_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_av1_inst *inst = NULL;
+	int ret = -1;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->vdec.frm_name	= "AV1";
+	inst->vdec.video_type	= VFORMAT_AV1;
+	inst->vdec.filp		= ctx->dev->filp;
+	inst->vdec.ctx		= ctx;
+	inst->ctx		= ctx;
+
+	vdec_parser_parms(inst);
+
+	/* set play mode.*/
+	if (ctx->is_drm_mode)
+		inst->vdec.port.flag |= PORT_FLAG_DRM;
+
+	/* to eable av1 hw.*/
+	inst->vdec.port.type	= PORT_TYPE_HEVC;
+
+	/* probe info from the stream */
+	inst->vsi = kzalloc(sizeof(struct vdec_av1_vsi), GFP_KERNEL);
+	if (!inst->vsi) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* alloc the header buffer to be used cache sps or spp etc.*/
+	inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
+	if (!inst->vsi->header_buf) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	init_completion(&inst->comp);
+
+	ctx->ada_ctx	= &inst->vdec;
+	*h_vdec		= (unsigned long)inst;
+
+	/* init decoder. */
+	ret = video_decoder_init(&inst->vdec);
+	if (ret) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"vdec_av1 init err=%d\n", ret);
+		goto err;
+	}
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"av1 Instance >> %lx\n", (ulong) inst);
+
+	return 0;
+err:
+	if (inst && inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+	if (inst && inst->vsi)
+		kfree(inst->vsi);
+	if (inst)
+		kfree(inst);
+	*h_vdec = 0;
+
+	return ret;
+}
+
+static int parse_stream_ucode(struct vdec_av1_inst *inst,
+			      u8 *buf, u32 size, u64 timestamp)
+{
+	int ret = 0;
+
+	ret = vdec_write_nalu(inst, buf, size, timestamp);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write data failed. size: %d, err: %d\n", size, ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_ucode_dma(struct vdec_av1_inst *inst,
+	ulong buf, u32 size, u64 timestamp, u32 handle)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+		vdec_vframe_input_free, inst->ctx);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write frame data failed. err: %d\n", ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_cpu(struct vdec_av1_inst *inst, u8 *buf, u32 size)
+{
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+		"can not suppport parse stream by cpu.\n");
+
+	return -1;
+}
+
+static int vdec_av1_probe(unsigned long h_vdec,
+	struct aml_vcodec_mem *bs, void *out)
+{
+	struct vdec_av1_inst *inst =
+		(struct vdec_av1_inst *)h_vdec;
+	u8 *buf = (u8 *)bs->vaddr;
+	u32 size = bs->size;
+	int ret = 0;
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if ((s->magic != AML_VIDEO_MAGIC) &&
+				(s->type != V4L_STREAM_TYPE_MATEDATA))
+				return -1;
+
+			if (inst->ctx->param_sets_from_ucode) {
+				ret = parse_stream_ucode(inst, s->data,
+					s->len, bs->timestamp);
+			} else {
+				ret = parse_stream_cpu(inst, s->data, s->len);
+			}
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = parse_stream_ucode_dma(inst, bs->addr, size,
+				bs->timestamp, BUFF_IDX(bs, bs->index));
+		}
+	} else {
+		if (inst->ctx->param_sets_from_ucode) {
+			ret = parse_stream_ucode(inst, buf, size, bs->timestamp);
+		} else {
+			ret = parse_stream_cpu(inst, buf, size);
+		}
+	}
+
+	inst->vsi->cur_pic = inst->vsi->pic;
+
+	return ret;
+}
+
+static void vdec_av1_deinit(unsigned long h_vdec)
+{
+	struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec;
+	struct aml_vcodec_ctx *ctx = inst->ctx;
+
+	video_decoder_release(&inst->vdec);
+
+	if (inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+
+	if (inst->vsi)
+		kfree(inst->vsi);
+
+	kfree(inst);
+
+	ctx->drv_handle = 0;
+}
+
+// Returns 1 when OBU type is valid, and 0 otherwise.
+static int valid_obu_type(int obu_type)
+{
+	int valid_type = 0;
+
+	switch (obu_type) {
+	case OBU_SEQUENCE_HEADER:
+	case OBU_TEMPORAL_DELIMITER:
+	case OBU_FRAME_HEADER:
+	case OBU_TILE_GROUP:
+	case OBU_METADATA:
+	case OBU_FRAME:
+	case OBU_REDUNDANT_FRAME_HEADER:
+	case OBU_TILE_LIST:
+	case OBU_PADDING:
+		valid_type = 1;
+		break;
+	default:
+		break;
+	}
+
+	return valid_type;
+}
+
+size_t uleb_size_in_bytes(u64 value)
+{
+	size_t size = 0;
+
+	do {
+		++size;
+	} while ((value >>= 7) != 0);
+
+	return size;
+}
+
+int uleb_decode(const u8 *buffer, size_t available,
+	u64 *value, size_t *length)
+{
+	int i;
+
+	if (buffer && value) {
+		*value = 0;
+
+		for (i = 0; i < kMaximumLeb128Size && i < available; ++i) {
+			const u8 decoded_byte = *(buffer + i) & kLeb128ByteMask;
+
+			*value |= ((u64)decoded_byte) << (i * 7);
+			if ((*(buffer + i) >> 7) == 0) {
+				if (length) {
+					*length = i + 1;
+				}
+
+				// Fail on values larger than 32-bits to ensure consistent behavior on
+				// 32 and 64 bit targets: value is typically used to determine buffer
+				// allocation size.
+				if (*value > ULONG_MAX)
+					return -1;
+
+				return 0;
+			}
+		}
+	}
+
+	// If we get here, either the buffer/value pointers were invalid,
+	// or we ran over the available space
+	return -1;
+}
+
+int uleb_encode(u64 value, size_t available,
+	u8 *coded_value, size_t *coded_size)
+{
+	int i;
+	const size_t leb_size = uleb_size_in_bytes(value);
+
+	if (value > kMaximumLeb128Value || leb_size > kMaximumLeb128Size ||
+		leb_size > available || !coded_value || !coded_size) {
+		return -1;
+	}
+
+	for (i = 0; i < leb_size; ++i) {
+		u8 byte = value & 0x7f;
+
+		value >>= 7;
+		if (value != 0) byte |= 0x80;  // Signal that more bytes follow.
+
+		*(coded_value + i) = byte;
+	}
+
+	*coded_size = leb_size;
+
+	return 0;
+}
+
+static int rb_read_bit(struct read_bit_buffer *rb)
+{
+	const u32 off = rb->bit_offset;
+	const u32 p = off >> 3;
+	const int q = 7 - (int)(off & 0x7);
+
+	if (rb->bit_buffer + p < rb->bit_buffer_end) {
+		const int bit = (rb->bit_buffer[p] >> q) & 1;
+
+		rb->bit_offset = off + 1;
+		return bit;
+	} else {
+		return 0;
+	}
+}
+
+static int rb_read_literal(struct read_bit_buffer *rb, int bits)
+{
+	int value = 0, bit;
+
+	for (bit = bits - 1; bit >= 0; bit--)
+		value |= rb_read_bit(rb) << bit;
+
+	return value;
+}
+
+static int read_obu_size(const u8 *data,
+	size_t bytes_available,
+	size_t *const obu_size,
+	size_t *const length_field_size)
+{
+	u64 u_obu_size = 0;
+
+	if (uleb_decode(data, bytes_available, &u_obu_size, length_field_size) != 0) {
+		return -1;
+	}
+
+	if (u_obu_size > ULONG_MAX)
+		return -1;
+
+	*obu_size = (size_t) u_obu_size;
+
+	return 0;
+}
+
+// Parses OBU header and stores values in 'header'.
+static int read_obu_header(struct read_bit_buffer *rb,
+	int is_annexb, struct ObuHeader *header)
+{
+	const int bit_buffer_byte_length =
+		rb->bit_buffer_end - rb->bit_buffer;
+
+	if (!rb || !header)
+		return -1;
+
+	if (bit_buffer_byte_length < 1)
+		return -1;
+
+	header->size = 1;
+
+	if (rb_read_bit(rb) != 0) {
+		// Forbidden bit. Must not be set.
+		return -1;
+	}
+
+	header->type = (enum OBU_TYPE) rb_read_literal(rb, 4);
+	if (!valid_obu_type(header->type))
+		return -1;
+
+	header->has_extension = rb_read_bit(rb);
+	header->has_size_field = rb_read_bit(rb);
+
+	if (!header->has_size_field && !is_annexb) {
+		// section 5 obu streams must have obu_size field set.
+		return -1;
+	}
+
+	if (rb_read_bit(rb) != 0) {
+		// obu_reserved_1bit must be set to 0.
+		return -1;
+	}
+
+	if (header->has_extension) {
+		if (bit_buffer_byte_length == 1)
+			return -1;
+
+		header->size += 1;
+		header->temporal_layer_id = rb_read_literal(rb, 3);
+		header->spatial_layer_id = rb_read_literal(rb, 2);
+		if (rb_read_literal(rb, 3) != 0) {
+			// extension_header_reserved_3bits must be set to 0.
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int read_obu_header_and_size(const u8 *data,
+	size_t bytes_available,
+	int is_annexb,
+	struct ObuHeader *obu_header,
+	size_t *const payload_size,
+	size_t *const bytes_read)
+{
+	size_t length_field_size_obu = 0;
+	size_t length_field_size_payload = 0;
+	size_t obu_size = 0;
+	int status = 0;
+	struct read_bit_buffer rb = { data + length_field_size_obu,
+		data + bytes_available, 0};
+
+	if (is_annexb) {
+		// Size field comes before the OBU header, and includes the OBU header
+		status = read_obu_size(data, bytes_available, &obu_size, &length_field_size_obu);
+		if (status != 0)
+			return status;
+	}
+
+	status = read_obu_header(&rb, is_annexb, obu_header);
+	if (status != 0)
+		return status;
+
+	if (!obu_header->has_size_field) {
+		// Derive the payload size from the data we've already read
+		if (obu_size < obu_header->size)
+			return -1;
+
+		*payload_size = obu_size - obu_header->size;
+	} else {
+		// Size field comes after the OBU header, and is just the payload size
+		status = read_obu_size(data + length_field_size_obu + obu_header->size,
+			bytes_available - length_field_size_obu - obu_header->size,
+			payload_size, &length_field_size_payload);
+		if (status != 0)
+			return status;
+	}
+
+	*bytes_read = length_field_size_obu + obu_header->size + length_field_size_payload;
+
+	return 0;
+}
+
+int parser_frame(int is_annexb, u8 *data, const u8 *data_end,
+	u8 *dst_data, u32 *frame_len, u8 *meta_buf, u32 *meta_len)
+{
+	int frame_decoding_finished = 0;
+	u32 obu_size = 0;
+	int seen_frame_header = 0;
+	int next_start_tile = 0;
+	struct DataBuffer obu_size_hdr;
+	u8 header[20] = {0};
+	u8 *p = NULL;
+	u32 rpu_size = 0;
+	struct ObuHeader obu_header;
+
+	memset(&obu_header, 0, sizeof(obu_header));
+
+	// decode frame as a series of OBUs
+	while (!frame_decoding_finished) {
+		//	struct read_bit_buffer rb;
+		size_t payload_size = 0;
+		size_t header_size = 0;
+		size_t bytes_read = 0;
+		const size_t bytes_available = data_end - data;
+		enum OBU_METADATA_TYPE meta_type;
+		int status;
+		u64 type;
+		u32 i;
+
+		if (bytes_available == 0 && !seen_frame_header) {
+			break;
+		}
+
+		status = read_obu_header_and_size(data, bytes_available, is_annexb,
+			&obu_header, &payload_size, &bytes_read);
+		if (status != 0) {
+			return -1;
+		}
+
+		// Record obu size header information.
+		obu_size_hdr.data = data + obu_header.size;
+		obu_size_hdr.size = bytes_read - obu_header.size;
+
+		// Note: read_obu_header_and_size() takes care of checking that this
+		// doesn't cause 'data' to advance past 'data_end'.
+
+		if ((size_t)(data_end - data - bytes_read) < payload_size) {
+			return -1;
+		}
+
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "obu %s len %zu+%zu\n",
+			obu_type_name[obu_header.type],
+			bytes_read, payload_size);
+
+		if (!is_annexb) {
+			obu_size = bytes_read + payload_size + 4;
+			header_size = 20;
+		} else {
+			obu_size = bytes_read + payload_size;
+			header_size = 16;
+		}
+
+		header[0] = ((obu_size + 4) >> 24) & 0xff;
+		header[1] = ((obu_size + 4) >> 16) & 0xff;
+		header[2] = ((obu_size + 4) >> 8) & 0xff;
+		header[3] = ((obu_size + 4) >> 0) & 0xff;
+		header[4] = header[0] ^ 0xff;
+		header[5] = header[1] ^ 0xff;
+		header[6] = header[2] ^ 0xff;
+		header[7] = header[3] ^ 0xff;
+		header[8] = 0;
+		header[9] = 0;
+		header[10] = 0;
+		header[11] = 1;
+		header[12] = 'A';
+		header[13] = 'M';
+		header[14] = 'L';
+		header[15] = 'V';
+
+		// put new size to here as annexb
+		header[16] = (obu_size & 0xff) | 0x80;
+		header[17] = ((obu_size >> 7) & 0xff) | 0x80;
+		header[18] = ((obu_size >> 14) & 0xff) | 0x80;
+		header[19] = ((obu_size >> 21) & 0xff) | 0x00;
+
+		memcpy(dst_data, header, header_size);
+		dst_data += header_size;
+		memcpy(dst_data, data, bytes_read + payload_size);
+		dst_data += (bytes_read + payload_size);
+
+		data += bytes_read;
+		*frame_len += (header_size + bytes_read + payload_size);
+
+		switch (obu_header.type) {
+		case OBU_TEMPORAL_DELIMITER:
+			seen_frame_header = 0;
+			next_start_tile = 0;
+			break;
+		case OBU_SEQUENCE_HEADER:
+			// The sequence header should not change in the middle of a frame.
+			if (seen_frame_header) {
+				return -1;
+			}
+			break;
+		case OBU_FRAME_HEADER:
+			if (data_end == data + payload_size) {
+				frame_decoding_finished = 1;
+			} else {
+				seen_frame_header = 1;
+			}
+			break;
+		case OBU_REDUNDANT_FRAME_HEADER:
+		case OBU_FRAME:
+			if (obu_header.type == OBU_REDUNDANT_FRAME_HEADER) {
+				if (!seen_frame_header) {
+					return -1;
+				}
+			} else {
+				// OBU_FRAME_HEADER or OBU_FRAME.
+				if (seen_frame_header) {
+					return -1;
+				}
+			}
+			if (obu_header.type == OBU_FRAME) {
+				if (data_end == data + payload_size) {
+					frame_decoding_finished = 1;
+					seen_frame_header = 0;
+				}
+			}
+			break;
+		case OBU_TILE_GROUP:
+			if (!seen_frame_header) {
+				return -1;
+			}
+			if (data + payload_size == data_end)
+				frame_decoding_finished = 1;
+			if (frame_decoding_finished)
+				seen_frame_header = 0;
+			break;
+		case OBU_METADATA:
+			uleb_decode(data, 8, &type, &bytes_read);
+			if (type < 6)
+				meta_type = type;
+			else
+				meta_type = 0;
+			p = data + bytes_read;
+			v4l_dbg(0, V4L_DEBUG_CODEC_PARSER,
+				"meta type %s %zu+%zu\n",
+				meta_type_name[type],
+				bytes_read,
+				payload_size - bytes_read);
+
+			if (meta_type == OBU_METADATA_TYPE_ITUT_T35) {
+#if 0 /* for dumping original obu payload */
+				for (i = 0; i < payload_size - bytes_read; i++) {
+					pr_info("%02x ", p[i]);
+					if (i % 16 == 15)
+						pr_info("\n");
+				}
+				if (i % 16 != 0)
+					pr_info("\n");
+#endif
+				if ((p[0] == 0xb5) /* country code */
+					&& ((p[1] == 0x00) && (p[2] == 0x3b)) /* terminal_provider_code */
+					&& ((p[3] == 0x00) && (p[4] == 0x00) && (p[5] == 0x08) && (p[6] == 0x00))) { /* terminal_provider_oriented_code */
+					v4l_dbg(0, V4L_DEBUG_CODEC_PARSER,
+						"dolbyvison rpu\n");
+					meta_buf[0] = meta_buf[1] = meta_buf[2] = 0;
+					meta_buf[3] = 0x01;
+					meta_buf[4] = 0x19;
+
+					if (p[11] & 0x10) {
+						rpu_size = 0x100;
+						rpu_size |= (p[11] & 0x0f) << 4;
+						rpu_size |= (p[12] >> 4) & 0x0f;
+						if (p[12] & 0x08) {
+							v4l_dbg(0, V4L_DEBUG_CODEC_PARSER,
+								"meta rpu in obu exceed 512 bytes\n");
+							break;
+						}
+						for (i = 0; i < rpu_size; i++) {
+							meta_buf[5 + i] = (p[12 + i] & 0x07) << 5;
+							meta_buf[5 + i] |= (p[13 + i] >> 3) & 0x1f;
+						}
+						rpu_size += 5;
+					} else {
+						rpu_size = (p[10] & 0x1f) << 3;
+						rpu_size |= (p[11] >> 5) & 0x07;
+						for (i = 0; i < rpu_size; i++) {
+							meta_buf[5 + i] = (p[11 + i] & 0x0f) << 4;
+							meta_buf[5 + i] |= (p[12 + i] >> 4) & 0x0f;
+						}
+						rpu_size += 5;
+					}
+					*meta_len = rpu_size;
+				}
+			} else if (meta_type == OBU_METADATA_TYPE_HDR_CLL) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "hdr10 cll:\n");
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "max_cll = %x\n", (p[0] << 8) | p[1]);
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "max_fall = %x\n", (p[2] << 8) | p[3]);
+			} else if (meta_type == OBU_METADATA_TYPE_HDR_MDCV) {
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "hdr10 primaries[r,g,b] = \n");
+				for (i = 0; i < 3; i++) {
+					v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, " %x, %x\n",
+						(p[i * 4] << 8) | p[i * 4 + 1],
+						(p[i * 4 + 2] << 8) | p[i * 4 + 3]);
+				}
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER,
+					"white point = %x, %x\n", (p[12] << 8) | p[13], (p[14] << 8) | p[15]);
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER,
+					"maxl = %x\n", (p[16] << 24) | (p[17] << 16) | (p[18] << 8) | p[19]);
+				v4l_dbg(0, V4L_DEBUG_CODEC_PARSER,
+					"minl = %x\n", (p[20] << 24) | (p[21] << 16) | (p[22] << 8) | p[23]);
+			}
+			break;
+		case OBU_TILE_LIST:
+			break;
+		case OBU_PADDING:
+			break;
+		default:
+			// Skip unrecognized OBUs
+			break;
+		}
+
+		data += payload_size;
+	}
+
+	return 0;
+}
+
+static int vdec_write_nalu(struct vdec_av1_inst *inst,
+	u8 *buf, u32 size, u64 ts)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+	u8 *data = NULL;
+	u32 length = 0;
+	bool need_prefix = av1_need_prefix;
+
+	if (need_prefix) {
+		u8 meta_buffer[1024] = {0};
+		u32 meta_size = 0;
+		u8 *src = buf;
+
+		data = vzalloc(size + 0x1000);
+		if (!data)
+			return -ENOMEM;
+
+		parser_frame(0, src, src + size, data, &length, meta_buffer, &meta_size);
+
+		if (length)
+			ret = vdec_vframe_write(vdec, data, length, ts, 0);
+		else
+			ret = -1;
+
+		vfree(data);
+	} else {
+		ret = vdec_vframe_write(vdec, buf, size, ts, 0);
+	}
+
+	return ret;
+}
+
+static bool monitor_res_change(struct vdec_av1_inst *inst, u8 *buf, u32 size)
+{
+	int ret = -1;
+	u8 *p = buf;
+	int len = size;
+	u32 synccode = av1_need_prefix ?
+		((p[1] << 16) | (p[2] << 8) | p[3]) :
+		((p[17] << 16) | (p[18] << 8) | p[19]);
+
+	if (synccode == SYNC_CODE) {
+		ret = parse_stream_cpu(inst, p, len);
+		if (!ret && (inst->vsi->cur_pic.coded_width !=
+			inst->vsi->pic.coded_width ||
+			inst->vsi->cur_pic.coded_height !=
+			inst->vsi->pic.coded_height)) {
+			inst->vsi->cur_pic = inst->vsi->pic;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static int vdec_av1_decode(unsigned long h_vdec,
+			   struct aml_vcodec_mem *bs, bool *res_chg)
+{
+	struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+	u8 *buf = (u8 *) bs->vaddr;
+	u32 size = bs->size;
+	int ret = -1;
+
+	if (bs == NULL)
+		return -1;
+
+	if (vdec_input_full(vdec)) {
+		return -EAGAIN;
+	}
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if (s->magic != AML_VIDEO_MAGIC)
+				return -1;
+
+			if (!inst->ctx->param_sets_from_ucode &&
+				(s->type == V4L_STREAM_TYPE_MATEDATA)) {
+				if ((*res_chg = monitor_res_change(inst,
+					s->data, s->len)))
+				return 0;
+			}
+
+			ret = vdec_vframe_write(vdec,
+				s->data,
+				s->len,
+				bs->timestamp,
+				0);
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = vdec_vframe_write_with_dma(vdec,
+				bs->addr, size, bs->timestamp,
+				BUFF_IDX(bs, bs->index),
+				vdec_vframe_input_free, inst->ctx);
+		}
+	} else {
+		/*checked whether the resolution changes.*/
+		if ((!inst->ctx->param_sets_from_ucode) &&
+			(*res_chg = monitor_res_change(inst, buf, size)))
+			return 0;
+
+		ret = vdec_write_nalu(inst, buf, size, bs->timestamp);
+	}
+
+	return ret;
+}
+
+ static void get_param_config_info(struct vdec_av1_inst *inst,
+	struct aml_dec_params *parms)
+ {
+	 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO) {
+		/* dw use v4l cfg */
+		inst->parms.cfg.double_write_mode =
+			inst->ctx->config.parm.dec.cfg.double_write_mode;
+		parms->cfg = inst->parms.cfg;
+	 }
+	 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO)
+		 parms->ps = inst->parms.ps;
+	 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO)
+		 parms->hdr = inst->parms.hdr;
+	 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO)
+		 parms->cnt = inst->parms.cnt;
+
+	 parms->parms_status |= inst->parms.parms_status;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"parms status: %u\n", parms->parms_status);
+ }
+
+static void get_param_comp_buf_info(struct vdec_av1_inst *inst,
+		struct vdec_comp_buf_info *params)
+{
+	memcpy(params, &inst->comp_info, sizeof(*params));
+}
+
+static int vdec_av1_get_param(unsigned long h_vdec,
+			       enum vdec_get_param_type type, void *out)
+{
+	int ret = 0;
+	struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the av1 inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+
+	case GET_PARAM_DPB_SIZE:
+		get_dpb_size(inst, out);
+		break;
+
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+
+	case GET_PARAM_CONFIG_INFO:
+		get_param_config_info(inst, out);
+		break;
+
+	case GET_PARAM_DW_MODE:
+	{
+		u32 *mode = out;
+		u32 m = inst->ctx->config.parm.dec.cfg.double_write_mode;
+		if (m <= 16)
+			*mode = inst->ctx->config.parm.dec.cfg.double_write_mode;
+		else
+			*mode = vdec_get_dw_mode(inst, 0);
+		break;
+	}
+	case GET_PARAM_COMP_BUF_INFO:
+		get_param_comp_buf_info(inst, out);
+		break;
+
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"invalid get parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void set_param_write_sync(struct vdec_av1_inst *inst)
+{
+	complete(&inst->comp);
+}
+
+static int vdec_get_dw_mode(struct vdec_av1_inst *inst, int dw_mode)
+{
+	u32 valid_dw_mode = inst->ctx->config.parm.dec.cfg.double_write_mode;
+	int w = inst->vsi->pic.coded_width;
+	int h = inst->vsi->pic.coded_height;
+	u32 dw = 0x1; /*1:1*/
+
+	switch (valid_dw_mode) {
+	case 0x100:
+		if (w > 1920 && h > 1088)
+			dw = 0x4; /*1:2*/
+		break;
+	case 0x200:
+		if (w > 1920 && h > 1088)
+			dw = 0x2; /*1:4*/
+		break;
+	case 0x300:
+		if (w > 1280 && h > 720)
+			dw = 0x4; /*1:2*/
+		break;
+	default:
+		dw = valid_dw_mode;
+		break;
+	}
+
+	return dw;
+}
+
+static int vdec_pic_scale(struct vdec_av1_inst *inst, int length, int dw_mode)
+{
+	int ret = 64;
+
+	switch (vdec_get_dw_mode(inst, dw_mode)) {
+	case 0x0: /* only afbc, output afbc */
+	case 0x21: /* only afbc, output afbc */
+		ret = 64;
+		break;
+	case 0x1: /* afbc and (w x h), output YUV420 */
+		ret = length;
+		break;
+	case 0x2: /* afbc and (w/4 x h/4), output YUV420 */
+	case 0x3: /* afbc and (w/4 x h/4), output afbc and YUV420 */
+		ret = length >> 2;
+		break;
+	case 0x4: /* afbc and (w/2 x h/2), output YUV420 */
+		ret = length >> 1;
+		break;
+	case 0x10: /* (w x h), output YUV420-8bit) */
+	default:
+		ret = length;
+		break;
+	}
+
+	return ret;
+}
+
+static void set_param_ps_info(struct vdec_av1_inst *inst,
+	struct aml_vdec_ps_infos *ps)
+{
+	struct vdec_pic_info *pic = &inst->vsi->pic;
+	struct vdec_av1_dec_info *dec = &inst->vsi->dec;
+	struct v4l2_rect *rect = &inst->vsi->crop;
+	int dw = inst->parms.cfg.double_write_mode;
+
+	/* fill visible area size that be used for EGL. */
+	pic->visible_width	= ps->visible_width;
+	pic->visible_height	= ps->visible_height;
+
+	/* calc visible ares. */
+	rect->left		= 0;
+	rect->top		= 0;
+	rect->width		= pic->visible_width;
+	rect->height		= pic->visible_height;
+
+	/* config canvas size that be used for decoder. */
+	pic->coded_width	= ps->coded_width;
+	pic->coded_height	= ps->coded_height;
+
+	pic->y_len_sz		= ALIGN(vdec_pic_scale(inst, pic->coded_width, dw), 64) *
+				  ALIGN(vdec_pic_scale(inst, pic->coded_height, dw), 64);
+	pic->c_len_sz		= pic->y_len_sz >> 1;
+
+	/* calc DPB size */
+	pic->dpb_frames		= ps->dpb_frames;
+	pic->dpb_margin		= ps->dpb_margin;
+	pic->vpp_margin		= ps->dpb_margin;
+	dec->dpb_sz		= ps->dpb_size;
+	pic->field		= ps->field;
+
+	inst->parms.ps 	= *ps;
+	inst->parms.parms_status |=
+		V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+	/*wake up*/
+	complete(&inst->comp);
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Parse from ucode, visible(%d x %d), coded(%d x %d)\n",
+		ps->visible_width, ps->visible_height,
+		ps->coded_width, ps->coded_height);
+}
+
+static void set_param_comp_buf_info(struct vdec_av1_inst *inst,
+		struct vdec_comp_buf_info *info)
+{
+	memcpy(&inst->comp_info, info, sizeof(*info));
+}
+
+static void set_param_hdr_info(struct vdec_av1_inst *inst,
+	struct aml_vdec_hdr_infos *hdr)
+{
+	if (hdr->signal_type != 0) {
+		inst->parms.hdr = *hdr;
+		inst->parms.parms_status |=
+			V4L2_CONFIG_PARM_DECODE_HDRINFO;
+		aml_vdec_dispatch_event(inst->ctx,
+			V4L2_EVENT_SRC_CH_HDRINFO);
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+			"av1 set HDR infos\n");
+	}
+}
+
+static void set_param_post_event(struct vdec_av1_inst *inst, u32 *event)
+{
+		aml_vdec_dispatch_event(inst->ctx, *event);
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+			"av1 post event: %d\n", *event);
+}
+
+static void set_pic_info(struct vdec_av1_inst *inst,
+	struct vdec_pic_info *pic)
+{
+	inst->vsi->pic = *pic;
+}
+
+static int vdec_av1_set_param(unsigned long h_vdec,
+	enum vdec_set_param_type type, void *in)
+{
+	int ret = 0;
+	struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the av1 inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case SET_PARAM_WRITE_FRAME_SYNC:
+		set_param_write_sync(inst);
+		break;
+
+	case SET_PARAM_PS_INFO:
+		set_param_ps_info(inst, in);
+		break;
+
+	case SET_PARAM_COMP_BUF_INFO:
+		set_param_comp_buf_info(inst, in);
+		break;
+
+	case SET_PARAM_HDR_INFO:
+		set_param_hdr_info(inst, in);
+		break;
+
+	case SET_PARAM_POST_EVENT:
+		set_param_post_event(inst, in);
+		break;
+
+	case SET_PARAM_PIC_INFO:
+		set_pic_info(inst, in);
+		break;
+
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"invalid set parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static struct vdec_common_if vdec_av1_if = {
+	.init		= vdec_av1_init,
+	.probe		= vdec_av1_probe,
+	.decode		= vdec_av1_decode,
+	.get_param	= vdec_av1_get_param,
+	.set_param	= vdec_av1_set_param,
+	.deinit		= vdec_av1_deinit,
+};
+
+struct vdec_common_if *get_av1_dec_comm_if(void);
+
+struct vdec_common_if *get_av1_dec_comm_if(void)
+{
+	return &vdec_av1_if;
+}
+
diff --git a/drivers/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amvdec_ports/decoder/vdec_h264_if.c
new file mode 100644
index 0000000..911c91d
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/vdec_h264_if.c
@@ -0,0 +1,1066 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <uapi/linux/swab.h>
+
+#include "../vdec_drv_if.h"
+#include "../aml_vcodec_util.h"
+#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_drv.h"
+#include "../aml_vcodec_adapt.h"
+#include "../vdec_drv_base.h"
+#include "aml_h264_parser.h"
+#include "../utils/common.h"
+
+/* h264 NALU type */
+#define NAL_NON_IDR_SLICE			0x01
+#define NAL_IDR_SLICE				0x05
+#define NAL_H264_SEI				0x06
+#define NAL_H264_SPS				0x07
+#define NAL_H264_PPS				0x08
+#define NAL_H264_AUD				0x09
+
+#define AVC_NAL_TYPE(value)				((value) & 0x1F)
+
+#define BUF_PREDICTION_SZ			(64 * 1024)//(32 * 1024)
+
+#define MB_UNIT_LEN				16
+
+/* motion vector size (bytes) for every macro block */
+#define HW_MB_STORE_SZ				64
+
+#define H264_MAX_FB_NUM				17
+#define HDR_PARSING_BUF_SZ			1024
+
+#define HEADER_BUFFER_SIZE			(128 * 1024)
+
+/**
+ * struct h264_fb - h264 decode frame buffer information
+ * @vdec_fb_va  : virtual address of struct vdec_fb
+ * @y_fb_dma    : dma address of Y frame buffer (luma)
+ * @c_fb_dma    : dma address of C frame buffer (chroma)
+ * @poc         : picture order count of frame buffer
+ * @reserved    : for 8 bytes alignment
+ */
+struct h264_fb {
+	uint64_t vdec_fb_va;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	int32_t poc;
+	uint32_t reserved;
+};
+
+/**
+ * struct h264_ring_fb_list - ring frame buffer list
+ * @fb_list   : frame buffer arrary
+ * @read_idx  : read index
+ * @write_idx : write index
+ * @count     : buffer count in list
+ */
+struct h264_ring_fb_list {
+	struct h264_fb fb_list[H264_MAX_FB_NUM];
+	unsigned int read_idx;
+	unsigned int write_idx;
+	unsigned int count;
+	unsigned int reserved;
+};
+
+/**
+ * struct vdec_h264_dec_info - decode information
+ * @dpb_sz		: decoding picture buffer size
+ * @realloc_mv_buf	: flag to notify driver to re-allocate mv buffer
+ * @reserved		: for 8 bytes alignment
+ * @bs_dma		: Input bit-stream buffer dma address
+ * @y_fb_dma		: Y frame buffer dma address
+ * @c_fb_dma		: C frame buffer dma address
+ * @vdec_fb_va		: VDEC frame buffer struct virtual address
+ */
+struct vdec_h264_dec_info {
+	uint32_t dpb_sz;
+	uint32_t realloc_mv_buf;
+	uint32_t reserved;
+	uint64_t bs_dma;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	uint64_t vdec_fb_va;
+};
+
+/**
+ * struct vdec_h264_vsi - shared memory for decode information exchange
+ *                        between VPU and Host.
+ *                        The memory is allocated by VPU then mapping to Host
+ *                        in vpu_dec_init() and freed in vpu_dec_deinit()
+ *                        by VPU.
+ *                        AP-W/R : AP is writer/reader on this item
+ *                        VPU-W/R: VPU is write/reader on this item
+ * @dec          : decode information (AP-R, VPU-W)
+ * @pic          : picture information (AP-R, VPU-W)
+ * @crop         : crop information (AP-R, VPU-W)
+ */
+struct vdec_h264_vsi {
+	unsigned char hdr_buf[HDR_PARSING_BUF_SZ];
+	char *header_buf;
+	int sps_size;
+	int pps_size;
+	int sei_size;
+	int head_offset;
+	struct vdec_h264_dec_info dec;
+	struct vdec_pic_info pic;
+	struct vdec_pic_info cur_pic;
+	struct v4l2_rect crop;
+	bool is_combine;
+	int nalu_pos;
+};
+
+/**
+ * struct vdec_h264_inst - h264 decoder instance
+ * @num_nalu : how many nalus be decoded
+ * @ctx      : point to aml_vcodec_ctx
+ * @pred_buf : HW working predication buffer
+ * @mv_buf   : HW working motion vector buffer
+ * @vpu      : VPU instance
+ * @vsi      : VPU shared information
+ */
+struct vdec_h264_inst {
+	unsigned int num_nalu;
+	struct aml_vcodec_ctx *ctx;
+	struct aml_vcodec_mem pred_buf;
+	struct aml_vcodec_mem mv_buf[H264_MAX_FB_NUM];
+	struct aml_vdec_adapt vdec;
+	struct vdec_h264_vsi *vsi;
+	struct aml_dec_params parms;
+	struct completion comp;
+};
+
+#if 0
+#define DUMP_FILE_NAME "/data/dump/dump.tmp"
+static struct file *filp;
+static loff_t file_pos;
+
+void dump_write(const char __user *buf, size_t count)
+{
+	mm_segment_t old_fs;
+
+	if (!filp)
+		return;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	if (count != vfs_write(filp, buf, count, &file_pos))
+		pr_err("Failed to write file\n");
+
+	set_fs(old_fs);
+}
+
+void dump_init(void)
+{
+	filp = filp_open(DUMP_FILE_NAME, O_CREAT | O_RDWR, 0644);
+	if (IS_ERR(filp)) {
+		pr_err("open dump file failed\n");
+		filp = NULL;
+	}
+}
+
+void dump_deinit(void)
+{
+	if (filp) {
+		filp_close(filp, current->files);
+		filp = NULL;
+		file_pos = 0;
+	}
+}
+
+void swap_uv(void *uv, int size)
+{
+	int i;
+	__u16 *p = uv;
+
+	size /= 2;
+
+	for (i = 0; i < size; i++, p++)
+		*p = __swab16(*p);
+}
+#endif
+
+static void get_pic_info(struct vdec_h264_inst *inst,
+			 struct vdec_pic_info *pic)
+{
+	*pic = inst->vsi->pic;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"pic(%d, %d), buf(%d, %d)\n",
+		 pic->visible_width, pic->visible_height,
+		 pic->coded_width, pic->coded_height);
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"Y(%d, %d), C(%d, %d)\n", pic->y_bs_sz,
+		 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_crop_info(struct vdec_h264_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = inst->vsi->crop.left;
+	cr->top = inst->vsi->crop.top;
+	cr->width = inst->vsi->crop.width;
+	cr->height = inst->vsi->crop.height;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"l=%d, t=%d, w=%d, h=%d\n",
+		 cr->left, cr->top, cr->width, cr->height);
+}
+
+static void get_dpb_size(struct vdec_h264_inst *inst, unsigned int *dpb_sz)
+{
+	*dpb_sz = inst->vsi->dec.dpb_sz;
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, "sz=%d\n", *dpb_sz);
+}
+
+static void skip_aud_data(u8 **data, u32 *size)
+{
+	int i;
+
+	i = find_start_code(*data, *size);
+	if (i > 0 && (*data)[i++] == 0x9 && (*data)[i++] == 0xf0) {
+		*size -= i;
+		*data += i;
+	}
+}
+
+static u32 vdec_config_default_parms(u8 *parm)
+{
+	u8 *pbuf = parm;
+
+	pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+	pbuf += sprintf(pbuf, "mh264_double_write_mode:16;");
+	pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
+	pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
+	pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;");
+
+	return parm - pbuf;
+}
+
+static void vdec_parser_parms(struct vdec_h264_inst *inst)
+{
+	struct aml_vcodec_ctx *ctx = inst->ctx;
+
+	if (ctx->config.parm.dec.parms_status &
+		V4L2_CONFIG_PARM_DECODE_CFGINFO) {
+		u8 *pbuf = ctx->config.buf;
+
+		pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+		pbuf += sprintf(pbuf, "mh264_double_write_mode:%d;",
+			ctx->config.parm.dec.cfg.double_write_mode);
+		pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
+			ctx->config.parm.dec.cfg.ref_buf_margin);
+		pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
+			ctx->config.parm.dec.cfg.canvas_mem_mode);
+		pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;",
+			ctx->config.parm.dec.cfg.canvas_mem_endian);
+		pbuf += sprintf(pbuf, "parm_v4l_low_latency_mode:%d;",
+			ctx->config.parm.dec.cfg.low_latency_mode);
+		pbuf += sprintf(pbuf, "parm_v4l_metadata_config_flag:%d;",
+			ctx->config.parm.dec.cfg.metadata_config_flag);
+		pbuf += sprintf(pbuf, "parm_v4l_duration:%d;",
+			ctx->config.parm.dec.cfg.duration);
+		ctx->config.length = pbuf - ctx->config.buf;
+	} else {
+		ctx->config.parm.dec.cfg.double_write_mode = 16;
+		ctx->config.parm.dec.cfg.ref_buf_margin = 7;
+		ctx->config.length = vdec_config_default_parms(ctx->config.buf);
+	}
+
+	inst->vdec.config	= ctx->config;
+	inst->parms.cfg		= ctx->config.parm.dec.cfg;
+	inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO;
+}
+
+static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_h264_inst *inst = NULL;
+	int ret = -1;
+
+	inst = vzalloc(sizeof(*inst));
+	if (!inst)
+		return -ENOMEM;
+
+	inst->vdec.frm_name	= "H.264";
+	inst->vdec.video_type	= VFORMAT_H264;
+	inst->vdec.filp		= ctx->dev->filp;
+	inst->vdec.ctx		= ctx;
+	inst->ctx		= ctx;
+
+	vdec_parser_parms(inst);
+
+	/* set play mode.*/
+	if (ctx->is_drm_mode)
+		inst->vdec.port.flag |= PORT_FLAG_DRM;
+
+	/* probe info from the stream */
+	inst->vsi = vzalloc(sizeof(struct vdec_h264_vsi));
+	if (!inst->vsi) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* alloc the header buffer to be used cache sps or spp etc.*/
+	inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
+	if (!inst->vsi->header_buf) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	init_completion(&inst->comp);
+
+	ctx->ada_ctx	= &inst->vdec;
+	*h_vdec		= (unsigned long)inst;
+
+	ret = video_decoder_init(&inst->vdec);
+	if (ret) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"vdec_h264 init err=%d\n", ret);
+		goto err;
+	}
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"H264 Instance >> %lx", (ulong) inst);
+
+	return 0;
+err:
+	if (inst && inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+	if (inst && inst->vsi)
+		vfree(inst->vsi);
+	if (inst)
+		vfree(inst);
+	*h_vdec = 0;
+
+	return ret;
+}
+
+#if 0
+static int refer_buffer_num(int level_idc, int max_poc_cnt,
+	int mb_width, int mb_height)
+{
+	int size;
+	int pic_size = mb_width * mb_height * 384;
+
+	switch (level_idc) {
+	case 9:
+		size = 152064;
+		break;
+	case 10:
+		size = 152064;
+		break;
+	case 11:
+		size = 345600;
+		break;
+	case 12:
+		size = 912384;
+		break;
+	case 13:
+		size = 912384;
+		break;
+	case 20:
+		size = 912384;
+		break;
+	case 21:
+		size = 1824768;
+		break;
+	case 22:
+		size = 3110400;
+		break;
+	case 30:
+		size = 3110400;
+		break;
+	case 31:
+		size = 6912000;
+		break;
+	case 32:
+		size = 7864320;
+		break;
+	case 40:
+		size = 12582912;
+		break;
+	case 41:
+		size = 12582912;
+		break;
+	case 42:
+		size = 13369344;
+		break;
+	case 50:
+		size = 42393600;
+		break;
+	case 51:
+	case 52:
+	default:
+		size = 70778880;
+		break;
+	}
+
+	size /= pic_size;
+	size = size + 1; /* need more buffers */
+
+	if (size > max_poc_cnt)
+		size = max_poc_cnt;
+
+	return size;
+}
+#endif
+
+static void vdec_config_dw_mode(struct vdec_pic_info *pic, int dw_mode)
+{
+	switch (dw_mode) {
+	case 0x1: /* (w x h) + (w/2 x h) */
+		pic->coded_width	+= pic->coded_width >> 1;
+		pic->y_len_sz		= pic->coded_width * pic->coded_height;
+		pic->c_len_sz		= pic->y_len_sz >> 1;
+		break;
+	case 0x2: /* (w x h) + (w/2 x h/2) */
+		pic->coded_width	+= pic->coded_width >> 1;
+		pic->coded_height	+= pic->coded_height >> 1;
+		pic->y_len_sz		= pic->coded_width * pic->coded_height;
+		pic->c_len_sz		= pic->y_len_sz >> 1;
+		break;
+	default: /* nothing to do */
+		break;
+	}
+}
+
+static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps)
+{
+	struct vdec_pic_info *pic = &inst->vsi->pic;
+	struct vdec_h264_dec_info *dec = &inst->vsi->dec;
+	struct v4l2_rect *rect = &inst->vsi->crop;
+	int dw = inst->parms.cfg.double_write_mode;
+	int margin = inst->parms.cfg.ref_buf_margin;
+	u32 mb_w, mb_h, width, height;
+
+	mb_w = sps->mb_width;
+	mb_h = sps->mb_height;
+
+	width  = mb_w << 4;
+	height = mb_h << 4;
+
+	width  -= (sps->crop_left + sps->crop_right);
+	height -= (sps->crop_top + sps->crop_bottom);
+
+	/* fill visible area size that be used for EGL. */
+	pic->visible_width	= width;
+	pic->visible_height	= height;
+
+	/* calc visible ares. */
+	rect->left		= 0;
+	rect->top		= 0;
+	rect->width		= pic->visible_width;
+	rect->height		= pic->visible_height;
+
+	/* config canvas size that be used for decoder. */
+	pic->coded_width	= ALIGN(mb_w, 4) << 4;
+	pic->coded_height	= ALIGN(mb_h, 4) << 4;
+	pic->y_len_sz		= pic->coded_width * pic->coded_height;
+	pic->c_len_sz		= pic->y_len_sz >> 1;
+	pic->profile_idc	= sps->profile_idc;
+	/* calc DPB size */
+	dec->dpb_sz		= sps->num_reorder_frames + margin;
+
+	inst->parms.ps.visible_width	= pic->visible_width;
+	inst->parms.ps.visible_height	= pic->visible_height;
+	inst->parms.ps.coded_width	= pic->coded_width;
+	inst->parms.ps.coded_height	= pic->coded_height;
+	inst->parms.ps.profile		= sps->profile_idc;
+	inst->parms.ps.mb_width		= sps->mb_width;
+	inst->parms.ps.mb_height	= sps->mb_height;
+	inst->parms.ps.ref_frames	= sps->ref_frame_count;
+	inst->parms.ps.dpb_frames	= sps->num_reorder_frames;
+	inst->parms.ps.dpb_size		= dec->dpb_sz;
+	inst->parms.parms_status	|= V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+	vdec_config_dw_mode(pic, dw);
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
+		dw, pic->coded_width, pic->coded_height,
+		pic->visible_width, pic->visible_height,
+		dec->dpb_sz - margin, margin);
+}
+
+static bool check_frame_combine(u8 *buf, u32 size, int *pos)
+{
+	bool combine = false;
+	int i = 0, j = 0, cnt = 0;
+	u8 *p = buf;
+
+	for (i = 4; i < size; i++) {
+		j = find_start_code(p, 7);
+		if (j > 0) {
+			if (++cnt > 1) {
+				combine = true;
+				break;
+			}
+
+			*pos = p - buf + j;
+			p += j;
+			i += j;
+		}
+		p++;
+	}
+
+	//pr_info("nal pos: %d, is_combine: %d\n",*pos, *is_combine);
+	return combine;
+}
+
+static int vdec_search_startcode(u8 *buf, u32 range)
+{
+	int pos = -1;
+	int i = 0, j = 0;
+	u8 *p = buf;
+
+	for (i = 4; i < range; i++) {
+		j = find_start_code(p, 7);
+		if (j > 0) {
+			pos = p - buf + j;
+			break;
+		}
+		p++;
+	}
+
+	return pos;
+}
+
+static int parse_stream_ucode(struct vdec_h264_inst *inst,
+			      u8 *buf, u32 size, u64 timestamp)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write(vdec, buf, size, timestamp, 0);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write frame data failed. err: %d\n", ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_ucode_dma(struct vdec_h264_inst *inst,
+	ulong buf, u32 size, u64 timestamp, u32 handle)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+		vdec_vframe_input_free, inst->ctx);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write frame data failed. err: %d\n", ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_cpu(struct vdec_h264_inst *inst, u8 *buf, u32 size)
+{
+	int ret = 0;
+	struct h264_param_sets *ps;
+	int nal_idx = 0;
+	bool is_combine = false;
+
+	is_combine = check_frame_combine(buf, size, &nal_idx);
+	if (nal_idx < 0)
+		return -1;
+
+	/* if the st compose from csd + slice that is the combine data. */
+	inst->vsi->is_combine = is_combine;
+	inst->vsi->nalu_pos = nal_idx;
+
+	ps = vzalloc(sizeof(struct h264_param_sets));
+	if (ps == NULL)
+		return -ENOMEM;
+
+	ret = h264_decode_extradata_ps(buf, size, ps);
+	if (ret) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"parse extra data failed. err: %d\n", ret);
+		goto out;
+	}
+
+	if (ps->sps_parsed)
+		fill_vdec_params(inst, &ps->sps);
+
+	ret = ps->sps_parsed ? 0 : -1;
+out:
+	vfree(ps);
+
+	return ret;
+}
+
+static int vdec_h264_probe(unsigned long h_vdec,
+	struct aml_vcodec_mem *bs, void *out)
+{
+	struct vdec_h264_inst *inst =
+		(struct vdec_h264_inst *)h_vdec;
+	u8 *buf = (u8 *) bs->vaddr;
+	u32 size = bs->size;
+	int ret = 0;
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if ((s->magic != AML_VIDEO_MAGIC) &&
+				(s->type != V4L_STREAM_TYPE_MATEDATA))
+				return -1;
+
+			if (inst->ctx->param_sets_from_ucode) {
+				ret = parse_stream_ucode(inst, s->data,
+					s->len, bs->timestamp);
+			} else {
+				skip_aud_data((u8 **)&s->data, &s->len);
+				ret = parse_stream_cpu(inst, s->data, s->len);
+			}
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = parse_stream_ucode_dma(inst, bs->addr, size,
+				bs->timestamp, BUFF_IDX(bs, bs->index));
+		}
+	} else {
+		if (inst->ctx->param_sets_from_ucode) {
+			ret = parse_stream_ucode(inst, buf, size, bs->timestamp);
+		} else {
+			skip_aud_data(&buf, &size);
+			ret = parse_stream_cpu(inst, buf, size);
+		}
+	}
+
+	inst->vsi->cur_pic = inst->vsi->pic;
+
+	return ret;
+}
+
+static void vdec_h264_deinit(unsigned long h_vdec)
+{
+	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+	struct aml_vcodec_ctx *ctx = inst->ctx;
+
+	video_decoder_release(&inst->vdec);
+
+	if (inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+
+	if (inst->vsi)
+		vfree(inst->vsi);
+
+	vfree(inst);
+
+	ctx->drv_handle = 0;
+}
+
+static int vdec_write_nalu(struct vdec_h264_inst *inst,
+	u8 *buf, u32 size, u64 ts)
+{
+	int ret = -1;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+	bool is_combine = inst->vsi->is_combine;
+	int nalu_pos;
+	u32 nal_type;
+
+	/*print_hex_debug(buf, size, 32);*/
+
+	nalu_pos = vdec_search_startcode(buf, 16);
+	if (nalu_pos < 0)
+		goto err;
+
+	nal_type = AVC_NAL_TYPE(buf[nalu_pos]);
+	//v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "NALU type: %d, size: %u\n", nal_type, size);
+
+	if (nal_type == NAL_H264_SPS && !is_combine) {
+		if (inst->vsi->head_offset + size > HEADER_BUFFER_SIZE) {
+			ret = -EILSEQ;
+			goto err;
+		}
+		inst->vsi->sps_size = size;
+		memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, size);
+		inst->vsi->head_offset += inst->vsi->sps_size;
+		ret = size;
+	} else if (nal_type == NAL_H264_PPS && !is_combine) {
+			//buf_sz -= nal_start_idx;
+		if (inst->vsi->head_offset + size > HEADER_BUFFER_SIZE) {
+			ret = -EILSEQ;
+			goto err;
+		}
+		inst->vsi->pps_size = size;
+		memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, size);
+		inst->vsi->head_offset += inst->vsi->pps_size;
+		ret = size;
+	} else if (nal_type == NAL_H264_SEI && !is_combine) {
+		if (inst->vsi->head_offset + size > HEADER_BUFFER_SIZE) {
+			ret = -EILSEQ;
+			goto err;
+		}
+		inst->vsi->sei_size = size;
+		memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, size);
+		inst->vsi->head_offset += inst->vsi->sei_size;
+		ret = size;
+	} else if (inst->vsi->head_offset == 0) {
+		ret = vdec_vframe_write(vdec, buf, size, ts, 0);
+	} else {
+		char *write_buf = vmalloc(inst->vsi->head_offset + size);
+		if (!write_buf) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		memcpy(write_buf, inst->vsi->header_buf, inst->vsi->head_offset);
+		memcpy(write_buf + inst->vsi->head_offset, buf, size);
+
+		ret = vdec_vframe_write(vdec, write_buf,
+			inst->vsi->head_offset + size, ts, 0);
+
+		memset(inst->vsi->header_buf, 0, HEADER_BUFFER_SIZE);
+		inst->vsi->head_offset = 0;
+		inst->vsi->sps_size = 0;
+		inst->vsi->pps_size = 0;
+		inst->vsi->sei_size = 0;
+
+		vfree(write_buf);
+	}
+
+	return ret;
+err:
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR, "err(%d)", ret);
+	return ret;
+}
+
+static bool monitor_res_change(struct vdec_h264_inst *inst, u8 *buf, u32 size)
+{
+	int ret = 0, i = 0, j = 0;
+	u8 *p = buf;
+	int len = size;
+	u32 type;
+
+	for (i = 4; i < size; i++) {
+		j = find_start_code(p, len);
+		if (j > 0) {
+			len = size - (p - buf);
+			type = AVC_NAL_TYPE(p[j]);
+			if (type != NAL_H264_AUD &&
+				(type > NAL_H264_PPS || type < NAL_H264_SEI))
+				break;
+
+			if (type == NAL_H264_SPS) {
+				ret = parse_stream_cpu(inst, p, len);
+				if (ret)
+					break;
+			}
+			p += j;
+		}
+		p++;
+	}
+
+	if (!ret && ((inst->vsi->cur_pic.coded_width !=
+		inst->vsi->pic.coded_width ||
+		inst->vsi->cur_pic.coded_height !=
+		inst->vsi->pic.coded_height) ||
+		(inst->vsi->pic.profile_idc !=
+		inst->vsi->cur_pic.profile_idc))) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "res change\n");
+		inst->vsi->cur_pic = inst->vsi->pic;
+		return true;
+	}
+
+	return false;
+}
+
+static int vdec_h264_decode(unsigned long h_vdec,
+			    struct aml_vcodec_mem *bs, bool *res_chg)
+{
+	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+	u8 *buf = (u8 *) bs->vaddr;
+	u32 size = bs->size;
+	int ret = -1;
+
+	if (bs == NULL)
+		return -1;
+
+	if (vdec_input_full(vdec))
+		return -EAGAIN;
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if (s->magic != AML_VIDEO_MAGIC)
+				return -1;
+
+			if (!inst->ctx->param_sets_from_ucode &&
+				(s->type == V4L_STREAM_TYPE_MATEDATA)) {
+				if ((*res_chg = monitor_res_change(inst,
+					s->data, s->len)))
+					return 0;
+			}
+
+			ret = vdec_vframe_write(vdec,
+				s->data,
+				s->len,
+				bs->timestamp,
+				0);
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = vdec_vframe_write_with_dma(vdec,
+				bs->addr, size, bs->timestamp,
+				BUFF_IDX(bs, bs->index),
+				vdec_vframe_input_free, inst->ctx);
+		}
+	} else {
+		if (inst->ctx->param_sets_from_ucode) {
+			int nal_idx = 0;
+			/* if the st compose from csd + slice that is the combine data. */
+			inst->vsi->is_combine = check_frame_combine(buf, size, &nal_idx);
+			/*if (nal_idx < 0)
+				return -1;*/
+		} else {
+			/*checked whether the resolution changes.*/
+			if ((*res_chg = monitor_res_change(inst, buf, size))) {
+				return 0;
+			}
+		}
+		ret = vdec_write_nalu(inst, buf, size, bs->timestamp);
+	}
+
+	return ret;
+}
+
+static void get_param_config_info(struct vdec_h264_inst *inst,
+	struct aml_dec_params *parms)
+{
+	if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO)
+		parms->cfg = inst->parms.cfg;
+	if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO)
+		parms->ps = inst->parms.ps;
+	if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO)
+		parms->hdr = inst->parms.hdr;
+	if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO)
+		parms->cnt = inst->parms.cnt;
+
+	parms->parms_status |= inst->parms.parms_status;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"parms status: %u\n", parms->parms_status);
+}
+
+static int vdec_h264_get_param(unsigned long h_vdec,
+			       enum vdec_get_param_type type, void *out)
+{
+	int ret = 0;
+	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the h264 inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+
+	case GET_PARAM_DPB_SIZE:
+		get_dpb_size(inst, out);
+		break;
+
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+
+	case GET_PARAM_CONFIG_INFO:
+		get_param_config_info(inst, out);
+		break;
+
+	case GET_PARAM_DW_MODE:
+	{
+		unsigned int* mode = out;
+		*mode = inst->ctx->config.parm.dec.cfg.double_write_mode;
+		break;
+	}
+
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"invalid get parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void set_param_write_sync(struct vdec_h264_inst *inst)
+{
+	complete(&inst->comp);
+}
+
+static void set_param_ps_info(struct vdec_h264_inst *inst,
+	struct aml_vdec_ps_infos *ps)
+{
+	struct vdec_pic_info *pic = &inst->vsi->pic;
+	struct vdec_h264_dec_info *dec = &inst->vsi->dec;
+	struct v4l2_rect *rect = &inst->vsi->crop;
+	int dw = inst->parms.cfg.double_write_mode;
+
+	/* fill visible area size that be used for EGL. */
+	pic->visible_width	= ps->visible_width;
+	pic->visible_height	= ps->visible_height;
+
+	/* calc visible ares. */
+	rect->left		= 0;
+	rect->top		= 0;
+	rect->width		= pic->visible_width;
+	rect->height		= pic->visible_height;
+
+	/* config canvas size that be used for decoder. */
+	pic->coded_width	= ps->coded_width;
+	pic->coded_height	= ps->coded_height;
+	pic->y_len_sz		= pic->coded_width * pic->coded_height;
+	pic->c_len_sz		= pic->y_len_sz >> 1;
+	pic->profile_idc	= ps->profile;
+	pic->field		= ps->field;
+	pic->dpb_frames		= ps->dpb_frames;
+	pic->dpb_margin		= ps->dpb_margin;
+	pic->vpp_margin		= ps->dpb_margin;
+	dec->dpb_sz		= ps->dpb_size;
+
+	inst->parms.ps 	= *ps;
+	inst->parms.parms_status |=
+		V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+	vdec_config_dw_mode(pic, dw);
+
+	/*wake up*/
+	complete(&inst->comp);
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Parse from ucode, visible(%d x %d), coded(%d x %d), scan:%s\n",
+		ps->visible_width, ps->visible_height,
+		ps->coded_width, ps->coded_height,
+		ps->field == V4L2_FIELD_NONE ? "P" : "I");
+}
+
+static void set_param_hdr_info(struct vdec_h264_inst *inst,
+	struct aml_vdec_hdr_infos *hdr)
+{
+	inst->parms.hdr = *hdr;
+	if (!(inst->parms.parms_status &
+		V4L2_CONFIG_PARM_DECODE_HDRINFO)) {
+		inst->parms.hdr = *hdr;
+		inst->parms.parms_status |=
+			V4L2_CONFIG_PARM_DECODE_HDRINFO;
+		aml_vdec_dispatch_event(inst->ctx,
+			V4L2_EVENT_SRC_CH_HDRINFO);
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+			"H264 set HDR infos\n");
+	}
+}
+
+static void set_pic_info(struct vdec_h264_inst *inst,
+	struct vdec_pic_info *pic)
+{
+	inst->vsi->pic = *pic;
+}
+
+static void set_param_post_event(struct vdec_h264_inst *inst, u32 *event)
+{
+	aml_vdec_dispatch_event(inst->ctx, *event);
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"H264 post event: %d\n", *event);
+}
+
+static int vdec_h264_set_param(unsigned long h_vdec,
+	enum vdec_set_param_type type, void *in)
+{
+	int ret = 0;
+	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the h264 inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case SET_PARAM_WRITE_FRAME_SYNC:
+		set_param_write_sync(inst);
+		break;
+
+	case SET_PARAM_PS_INFO:
+		set_param_ps_info(inst, in);
+		break;
+
+	case SET_PARAM_HDR_INFO:
+		set_param_hdr_info(inst, in);
+		break;
+
+	case SET_PARAM_POST_EVENT:
+		set_param_post_event(inst, in);
+		break;
+
+	case SET_PARAM_PIC_INFO:
+		set_pic_info(inst, in);
+		break;
+
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"invalid set parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static struct vdec_common_if vdec_h264_if = {
+	.init		= vdec_h264_init,
+	.probe		= vdec_h264_probe,
+	.decode		= vdec_h264_decode,
+	.get_param	= vdec_h264_get_param,
+	.set_param	= vdec_h264_set_param,
+	.deinit		= vdec_h264_deinit,
+};
+
+struct vdec_common_if *get_h264_dec_comm_if(void);
+
+struct vdec_common_if *get_h264_dec_comm_if(void)
+{
+	return &vdec_h264_if;
+}
diff --git a/drivers/amvdec_ports/decoder/vdec_hevc_if.c b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
new file mode 100644
index 0000000..56d492a
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
@@ -0,0 +1,866 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <uapi/linux/swab.h>
+#include "../vdec_drv_if.h"
+#include "../aml_vcodec_util.h"
+#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_drv.h"
+#include "../aml_vcodec_adapt.h"
+#include "../vdec_drv_base.h"
+#include "aml_hevc_parser.h"
+
+#define HEVC_NAL_TYPE(value)				((value >> 1) & 0x3F)
+#define HEADER_BUFFER_SIZE			(32 * 1024)
+
+/**
+ * struct hevc_fb - hevc decode frame buffer information
+ * @vdec_fb_va  : virtual address of struct vdec_fb
+ * @y_fb_dma    : dma address of Y frame buffer (luma)
+ * @c_fb_dma    : dma address of C frame buffer (chroma)
+ * @poc         : picture order count of frame buffer
+ * @reserved    : for 8 bytes alignment
+ */
+struct hevc_fb {
+	uint64_t vdec_fb_va;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	int32_t poc;
+	uint32_t reserved;
+};
+
+/**
+ * struct vdec_hevc_dec_info - decode information
+ * @dpb_sz		: decoding picture buffer size
+ * @resolution_changed  : resoltion change happen
+ * @reserved		: for 8 bytes alignment
+ * @bs_dma		: Input bit-stream buffer dma address
+ * @y_fb_dma		: Y frame buffer dma address
+ * @c_fb_dma		: C frame buffer dma address
+ * @vdec_fb_va		: VDEC frame buffer struct virtual address
+ */
+struct vdec_hevc_dec_info {
+	uint32_t dpb_sz;
+	uint32_t resolution_changed;
+	uint32_t reserved;
+	uint64_t bs_dma;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	uint64_t vdec_fb_va;
+};
+
+/**
+ * struct vdec_hevc_vsi - shared memory for decode information exchange
+ *                        between VPU and Host.
+ *                        The memory is allocated by VPU then mapping to Host
+ *                        in vpu_dec_init() and freed in vpu_dec_deinit()
+ *                        by VPU.
+ *                        AP-W/R : AP is writer/reader on this item
+ *                        VPU-W/R: VPU is write/reader on this item
+ * @hdr_buf      : Header parsing buffer (AP-W, VPU-R)
+ * @list_free    : free frame buffer ring list (AP-W/R, VPU-W)
+ * @list_disp    : display frame buffer ring list (AP-R, VPU-W)
+ * @dec          : decode information (AP-R, VPU-W)
+ * @pic          : picture information (AP-R, VPU-W)
+ * @crop         : crop information (AP-R, VPU-W)
+ */
+struct vdec_hevc_vsi {
+	char *header_buf;
+	int sps_size;
+	int pps_size;
+	int sei_size;
+	int head_offset;
+	struct vdec_hevc_dec_info dec;
+	struct vdec_pic_info pic;
+	struct vdec_pic_info cur_pic;
+	struct v4l2_rect crop;
+	bool is_combine;
+	int nalu_pos;
+	struct h265_param_sets ps;
+};
+
+/**
+ * struct vdec_hevc_inst - hevc decoder instance
+ * @num_nalu : how many nalus be decoded
+ * @ctx      : point to aml_vcodec_ctx
+ * @vsi      : VPU shared information
+ */
+struct vdec_hevc_inst {
+	unsigned int num_nalu;
+	struct aml_vcodec_ctx *ctx;
+	struct aml_vdec_adapt vdec;
+	struct vdec_hevc_vsi *vsi;
+	struct aml_dec_params parms;
+	struct completion comp;
+	struct vdec_comp_buf_info comp_info;
+};
+
+static void get_pic_info(struct vdec_hevc_inst *inst,
+			 struct vdec_pic_info *pic)
+{
+	*pic = inst->vsi->pic;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"pic(%d, %d), buf(%d, %d)\n",
+		 pic->visible_width, pic->visible_height,
+		 pic->coded_width, pic->coded_height);
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"Y(%d, %d), C(%d, %d)\n", pic->y_bs_sz,
+		 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_crop_info(struct vdec_hevc_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = inst->vsi->crop.left;
+	cr->top = inst->vsi->crop.top;
+	cr->width = inst->vsi->crop.width;
+	cr->height = inst->vsi->crop.height;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"l=%d, t=%d, w=%d, h=%d\n",
+		 cr->left, cr->top, cr->width, cr->height);
+}
+
+static void get_dpb_size(struct vdec_hevc_inst *inst, unsigned int *dpb_sz)
+{
+	*dpb_sz = inst->vsi->dec.dpb_sz;
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, "sz=%d\n", *dpb_sz);
+}
+
+static u32 vdec_config_default_parms(u8 *parm)
+{
+	u8 *pbuf = parm;
+
+	pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+	pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
+	pbuf += sprintf(pbuf, "hevc_double_write_mode:1;");
+	pbuf += sprintf(pbuf, "hevc_buf_width:4096;");
+	pbuf += sprintf(pbuf, "hevc_buf_height:2304;");
+	pbuf += sprintf(pbuf, "save_buffer_mode:0;");
+	pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
+	pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;");
+
+	return parm - pbuf;
+}
+
+static void vdec_parser_parms(struct vdec_hevc_inst *inst)
+{
+	struct aml_vcodec_ctx *ctx = inst->ctx;
+
+	if (ctx->config.parm.dec.parms_status &
+		V4L2_CONFIG_PARM_DECODE_CFGINFO) {
+		u8 *pbuf = ctx->config.buf;
+
+		pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+		pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
+			ctx->config.parm.dec.cfg.ref_buf_margin);
+		pbuf += sprintf(pbuf, "hevc_double_write_mode:%d;",
+			ctx->config.parm.dec.cfg.double_write_mode);
+		pbuf += sprintf(pbuf, "hevc_buf_width:4096;");
+		pbuf += sprintf(pbuf, "hevc_buf_height:2304;");
+		pbuf += sprintf(pbuf, "save_buffer_mode:0;");
+		pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
+			ctx->config.parm.dec.cfg.canvas_mem_mode);
+		pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;",
+			ctx->config.parm.dec.cfg.canvas_mem_endian);
+		pbuf += sprintf(pbuf, "parm_v4l_low_latency_mode:%d;",
+			ctx->config.parm.dec.cfg.low_latency_mode);
+		pbuf += sprintf(pbuf, "parm_v4l_metadata_config_flag:%d;",
+			ctx->config.parm.dec.cfg.metadata_config_flag);
+		pbuf += sprintf(pbuf, "parm_v4l_duration:%d;",
+			ctx->config.parm.dec.cfg.duration);
+		ctx->config.length = pbuf - ctx->config.buf;
+	} else {
+		ctx->config.parm.dec.cfg.double_write_mode = 1;
+		ctx->config.parm.dec.cfg.ref_buf_margin = 7;
+		ctx->config.length = vdec_config_default_parms(ctx->config.buf);
+	}
+
+	inst->vdec.config	= ctx->config;
+	inst->parms.cfg		= ctx->config.parm.dec.cfg;
+	inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO;
+}
+
+static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_hevc_inst *inst = NULL;
+	int ret = -1;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->vdec.frm_name	= "H.265";
+	inst->vdec.video_type	= VFORMAT_HEVC;
+	inst->vdec.filp		= ctx->dev->filp;
+	inst->vdec.ctx		= ctx;
+	inst->ctx		= ctx;
+
+	vdec_parser_parms(inst);
+
+	/* set play mode.*/
+	if (ctx->is_drm_mode)
+		inst->vdec.port.flag |= PORT_FLAG_DRM;
+
+	/* to eable hevc hw.*/
+	inst->vdec.port.type = PORT_TYPE_HEVC;
+
+	/* probe info from the stream */
+	inst->vsi = kzalloc(sizeof(struct vdec_hevc_vsi), GFP_KERNEL);
+	if (!inst->vsi) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* alloc the header buffer to be used cache sps or spp etc.*/
+	inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
+	if (!inst->vsi->header_buf) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	init_completion(&inst->comp);
+
+	ctx->ada_ctx	= &inst->vdec;
+	*h_vdec		= (unsigned long)inst;
+
+	ret = video_decoder_init(&inst->vdec);
+	if (ret) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"vdec_hevc init err=%d\n", ret);
+		goto err;
+	}
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"hevc Instance >> %lx\n", (ulong) inst);
+
+	return 0;
+err:
+	if (inst && inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+	if (inst && inst->vsi)
+		kfree(inst->vsi);
+	if (inst)
+		kfree(inst);
+	*h_vdec = 0;
+
+	return ret;
+}
+
+
+static int refer_buffer_num(struct h265_SPS_t *sps)
+{
+	int used_buf_num = 0;
+	int sps_pic_buf_diff = 0;
+
+	if ((!sps->temporal_layer[0].num_reorder_pics) &&
+		(sps->temporal_layer[0].max_dec_pic_buffering)) {
+		/* the range of sps_num_reorder_pics_0 is in
+		[0, sps_max_dec_pic_buffering_minus1_0] */
+		used_buf_num = sps->temporal_layer[0].max_dec_pic_buffering;
+	} else
+		used_buf_num = sps->temporal_layer[0].num_reorder_pics;
+
+	sps_pic_buf_diff = sps->temporal_layer[0].max_dec_pic_buffering -
+		sps->temporal_layer[0].num_reorder_pics - 1;
+
+	if (sps_pic_buf_diff >= 4)
+		used_buf_num += 1;
+
+	/*need one more for multi instance, as
+	apply_ref_pic_set() has no chanch to run to
+	to clear referenced flag in some case */
+	used_buf_num++;
+
+	/* for eos add more buffer to flush.*/
+	used_buf_num++;
+
+	return used_buf_num;
+}
+
+static int vdec_get_dw_mode(struct vdec_hevc_inst *inst, int dw_mode)
+{
+	u32 valid_dw_mode = inst->parms.cfg.double_write_mode;
+	int w = inst->vsi->pic.coded_width;
+	int h = inst->vsi->pic.coded_height;
+	u32 dw = 0x1; /*1:1*/
+
+	switch (valid_dw_mode) {
+	case 0x100:
+		if (w > 1920 && h > 1088)
+			dw = 0x4; /*1:2*/
+		break;
+	case 0x200:
+		if (w > 1920 && h > 1088)
+			dw = 0x2; /*1:4*/
+		break;
+	case 0x300:
+		if (w > 1280 && h > 720)
+			dw = 0x4; /*1:2*/
+		break;
+	default:
+		dw = valid_dw_mode;
+		break;
+	}
+
+	return dw;
+}
+
+static int vdec_pic_scale(struct vdec_hevc_inst *inst, int length, int dw_mode)
+{
+	int ret = 64;
+
+	switch (vdec_get_dw_mode(inst, dw_mode)) {
+	case 0x0: /* only afbc, output afbc */
+		ret = 64;
+		break;
+	case 0x1: /* afbc and (w x h), output YUV420 */
+		ret = length;
+		break;
+	case 0x2: /* afbc and (w/4 x h/4), output YUV420 */
+	case 0x3: /* afbc and (w/4 x h/4), output afbc and YUV420 */
+		ret = length >> 2;
+		break;
+	case 0x4: /* afbc and (w/2 x h/2), output YUV420 */
+		ret = length >> 1;
+		break;
+	case 0x10: /* (w x h), output YUV420-8bit)*/
+	default:
+		ret = length;
+		break;
+	}
+
+	return ret;
+}
+
+static void fill_vdec_params(struct vdec_hevc_inst *inst, struct h265_SPS_t *sps)
+{
+	struct vdec_pic_info *pic = &inst->vsi->pic;
+	struct vdec_hevc_dec_info *dec = &inst->vsi->dec;
+	struct v4l2_rect *rect = &inst->vsi->crop;
+	int dw = inst->parms.cfg.double_write_mode;
+	int margin = inst->parms.cfg.ref_buf_margin;
+
+	/* fill visible area size that be used for EGL. */
+	pic->visible_width = sps->width - (sps->output_window.left_offset +
+		sps->output_window.right_offset);
+	pic->visible_height = sps->height - (sps->output_window.top_offset +
+		sps->output_window.bottom_offset);
+	pic->visible_width = vdec_pic_scale(inst, pic->visible_width, dw);
+	pic->visible_height = vdec_pic_scale(inst, pic->visible_height, dw);
+
+	/* calc visible ares. */
+	rect->left		= 0;
+	rect->top		= 0;
+	rect->width		= pic->visible_width;
+	rect->height		= pic->visible_height;
+
+	/* config canvas size that be used for decoder. */
+	pic->coded_width	= vdec_pic_scale(inst, ALIGN(sps->width, 32), dw);
+	pic->coded_height	= vdec_pic_scale(inst, ALIGN(sps->height, 32), dw);
+
+	pic->y_len_sz		= pic->coded_width * pic->coded_height;
+	pic->c_len_sz		= pic->y_len_sz >> 1;
+
+	/* calc DPB size */
+	dec->dpb_sz		= refer_buffer_num(sps) + margin;
+
+	inst->parms.ps.visible_width	= pic->visible_width;
+	inst->parms.ps.visible_height	= pic->visible_height;
+	inst->parms.ps.coded_width	= pic->coded_width;
+	inst->parms.ps.coded_height	= pic->coded_height;
+	inst->parms.ps.dpb_size		= dec->dpb_sz;
+	inst->parms.parms_status	|= V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
+		dw, pic->coded_width, pic->coded_height,
+		pic->visible_width, pic->visible_height,
+		dec->dpb_sz - margin, margin);
+}
+
+static int parse_stream_ucode(struct vdec_hevc_inst *inst,
+			      u8 *buf, u32 size, u64 timestamp)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write(vdec, buf, size, timestamp, 0);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write frame data failed. err: %d\n", ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_ucode_dma(struct vdec_hevc_inst *inst,
+	ulong buf, u32 size, u64 timestamp, u32 handle)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+		vdec_vframe_input_free, inst->ctx);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write frame data failed. err: %d\n", ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_cpu(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
+{
+	int ret = 0;
+	struct h265_param_sets *ps = NULL;
+
+	ps = vzalloc(sizeof(struct h265_param_sets));
+	if (ps == NULL)
+		return -ENOMEM;
+
+	ret = h265_decode_extradata_ps(buf, size, ps);
+	if (ret) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"parse extra data failed. err: %d\n", ret);
+		goto out;
+	}
+
+	if (ps->sps_parsed)
+		fill_vdec_params(inst, &ps->sps);
+
+	ret = ps->sps_parsed ? 0 : -1;
+out:
+	vfree(ps);
+
+	return ret;
+}
+
+static int vdec_hevc_probe(unsigned long h_vdec,
+	struct aml_vcodec_mem *bs, void *out)
+{
+	struct vdec_hevc_inst *inst =
+		(struct vdec_hevc_inst *)h_vdec;
+	u8 *buf = (u8 *)bs->vaddr;
+	u32 size = bs->size;
+	int ret = 0;
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if ((s->magic != AML_VIDEO_MAGIC) &&
+				(s->type != V4L_STREAM_TYPE_MATEDATA))
+				return -1;
+
+			if (inst->ctx->param_sets_from_ucode) {
+				ret = parse_stream_ucode(inst, s->data,
+					s->len, bs->timestamp);
+			} else {
+				ret = parse_stream_cpu(inst, s->data, s->len);
+			}
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = parse_stream_ucode_dma(inst, bs->addr, size,
+				bs->timestamp, BUFF_IDX(bs, bs->index));
+		}
+	} else {
+		if (inst->ctx->param_sets_from_ucode) {
+			ret = parse_stream_ucode(inst, buf, size, bs->timestamp);
+		} else {
+			ret = parse_stream_cpu(inst, buf, size);
+		}
+	}
+
+	inst->vsi->cur_pic = inst->vsi->pic;
+
+	return ret;
+}
+
+static void vdec_hevc_deinit(unsigned long h_vdec)
+{
+	struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
+	struct aml_vcodec_ctx *ctx = inst->ctx;
+
+	video_decoder_release(&inst->vdec);
+
+	if (inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+
+	if (inst->vsi)
+		kfree(inst->vsi);
+
+	kfree(inst);
+
+	ctx->drv_handle = 0;
+}
+
+static int vdec_write_nalu(struct vdec_hevc_inst *inst,
+	u8 *buf, u32 size, u64 ts)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write(vdec, buf, size, ts, 0);
+
+	return ret;
+}
+
+static bool monitor_res_change(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
+{
+	int ret = 0, i = 0, j = 0;
+	u8 *p = buf;
+	int len = size;
+	u32 type;
+
+	for (i = 4; i < size; i++) {
+		j = find_start_code(p, len);
+		if (j > 0) {
+			len = size - (p - buf);
+			type = HEVC_NAL_TYPE(p[j]);
+			if (type != HEVC_NAL_AUD &&
+				(type > HEVC_NAL_PPS || type < HEVC_NAL_VPS))
+				break;
+
+			if (type == HEVC_NAL_SPS) {
+				ret = parse_stream_cpu(inst, p, len);
+				if (ret)
+					break;
+			}
+			p += j;
+		}
+		p++;
+	}
+
+	if (!ret && (inst->vsi->cur_pic.coded_width !=
+		inst->vsi->pic.coded_width ||
+		inst->vsi->cur_pic.coded_height !=
+		inst->vsi->pic.coded_height)) {
+		inst->vsi->cur_pic = inst->vsi->pic;
+		return true;
+	}
+
+	return false;
+}
+
+static int vdec_hevc_decode(unsigned long h_vdec,
+			    struct aml_vcodec_mem *bs, bool *res_chg)
+{
+	struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+	u8 *buf = (u8 *) bs->vaddr;
+	u32 size = bs->size;
+	int ret = -1;
+
+	if (bs == NULL)
+		return -1;
+
+	if (vdec_input_full(vdec))
+		return -EAGAIN;
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if (s->magic != AML_VIDEO_MAGIC)
+				return -1;
+
+			if (!inst->ctx->param_sets_from_ucode &&
+				(s->type == V4L_STREAM_TYPE_MATEDATA)) {
+				if ((*res_chg = monitor_res_change(inst,
+					s->data, s->len)))
+					return 0;
+			}
+
+			ret = vdec_vframe_write(vdec,
+				s->data,
+				s->len,
+				bs->timestamp,
+				0);
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = vdec_vframe_write_with_dma(vdec,
+				bs->addr, size, bs->timestamp,
+				BUFF_IDX(bs, bs->index),
+				vdec_vframe_input_free, inst->ctx);
+		}
+	} else {
+		if (!inst->ctx->param_sets_from_ucode) {
+			/*checked whether the resolution changes.*/
+			if ((*res_chg = monitor_res_change(inst, buf, size)))
+				return 0;
+		}
+		ret = vdec_write_nalu(inst, buf, size, bs->timestamp);
+	}
+
+	return ret;
+}
+
+ static void get_param_config_info(struct vdec_hevc_inst *inst,
+	struct aml_dec_params *parms)
+ {
+	 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO)
+		 parms->cfg = inst->parms.cfg;
+	 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO)
+		 parms->ps = inst->parms.ps;
+	 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO)
+		 parms->hdr = inst->parms.hdr;
+	 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO)
+		 parms->cnt = inst->parms.cnt;
+
+	 parms->parms_status |= inst->parms.parms_status;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"parms status: %u\n", parms->parms_status);
+ }
+
+static void get_param_comp_buf_info(struct vdec_hevc_inst *inst,
+		struct vdec_comp_buf_info *params)
+{
+	memcpy(params, &inst->comp_info, sizeof(*params));
+}
+
+static int vdec_hevc_get_param(unsigned long h_vdec,
+			       enum vdec_get_param_type type, void *out)
+{
+	int ret = 0;
+	struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the hevc inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+
+	case GET_PARAM_DPB_SIZE:
+		get_dpb_size(inst, out);
+		break;
+
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+
+	case GET_PARAM_CONFIG_INFO:
+		get_param_config_info(inst, out);
+		break;
+
+	case GET_PARAM_DW_MODE:
+	{
+		u32 *mode = out;
+		u32 m = inst->ctx->config.parm.dec.cfg.double_write_mode;
+		if (m <= 16)
+			*mode = inst->ctx->config.parm.dec.cfg.double_write_mode;
+		else
+			*mode = vdec_get_dw_mode(inst, 0);
+		break;
+	}
+	case GET_PARAM_COMP_BUF_INFO:
+		get_param_comp_buf_info(inst, out);
+		break;
+
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"invalid get parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void set_param_write_sync(struct vdec_hevc_inst *inst)
+{
+	complete(&inst->comp);
+}
+
+static void set_param_ps_info(struct vdec_hevc_inst *inst,
+	struct aml_vdec_ps_infos *ps)
+{
+	struct vdec_pic_info *pic = &inst->vsi->pic;
+	struct vdec_hevc_dec_info *dec = &inst->vsi->dec;
+	struct v4l2_rect *rect = &inst->vsi->crop;
+	int dw = inst->parms.cfg.double_write_mode;
+
+	/* fill visible area size that be used for EGL. */
+	pic->visible_width	= ps->visible_width;
+	pic->visible_height	= ps->visible_height;
+
+	/* calc visible ares. */
+	rect->left		= 0;
+	rect->top		= 0;
+	rect->width		= pic->visible_width;
+	rect->height		= pic->visible_height;
+
+	/* config canvas size that be used for decoder. */
+
+	pic->coded_width 	= ps->coded_width;
+	pic->coded_height 	= ps->coded_height;
+
+	pic->y_len_sz		= ALIGN(vdec_pic_scale(inst, pic->coded_width, dw), 64) *
+				  ALIGN(vdec_pic_scale(inst, pic->coded_height, dw), 64);
+	pic->c_len_sz		= pic->y_len_sz >> 1;
+
+	pic->dpb_frames		= ps->dpb_frames;
+	pic->dpb_margin		= ps->dpb_margin;
+	pic->vpp_margin		= ps->dpb_margin;
+	dec->dpb_sz		= ps->dpb_size;
+	pic->field		= ps->field;
+
+	inst->parms.ps		= *ps;
+	inst->parms.parms_status |=
+		V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+	/*wake up*/
+	complete(&inst->comp);
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Parse from ucode, visible(%d x %d), coded(%d x %d), scan:%s\n",
+		pic->visible_width, pic->visible_height,
+		pic->coded_width, pic->coded_height,
+		pic->field == V4L2_FIELD_NONE ? "P" : "I");
+}
+
+static void set_cfg_info(struct vdec_hevc_inst *inst,
+	struct aml_vdec_cfg_infos *cfg)
+{
+	memcpy(&inst->ctx->config.parm.dec.cfg,
+		cfg, sizeof(struct aml_vdec_cfg_infos));
+	memcpy(&inst->parms.cfg,
+		cfg, sizeof(struct aml_vdec_cfg_infos));
+}
+
+static void set_param_comp_buf_info(struct vdec_hevc_inst *inst,
+		struct vdec_comp_buf_info *info)
+{
+	memcpy(&inst->comp_info, info, sizeof(*info));
+}
+
+static void set_param_hdr_info(struct vdec_hevc_inst *inst,
+	struct aml_vdec_hdr_infos *hdr)
+{
+	if (!(inst->parms.parms_status &
+		V4L2_CONFIG_PARM_DECODE_HDRINFO)) {
+		inst->parms.hdr = *hdr;
+		inst->parms.parms_status |=
+			V4L2_CONFIG_PARM_DECODE_HDRINFO;
+		aml_vdec_dispatch_event(inst->ctx,
+			V4L2_EVENT_SRC_CH_HDRINFO);
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+			"H265 set HDR infos\n");
+	}
+}
+
+static void set_param_post_event(struct vdec_hevc_inst *inst, u32 *event)
+{
+	aml_vdec_dispatch_event(inst->ctx, *event);
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"H265 post event: %d\n", *event);
+}
+
+static void set_pic_info(struct vdec_hevc_inst *inst,
+	struct vdec_pic_info *pic)
+{
+	inst->vsi->pic = *pic;
+}
+
+static int vdec_hevc_set_param(unsigned long h_vdec,
+	enum vdec_set_param_type type, void *in)
+{
+	int ret = 0;
+	struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the hevc inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case SET_PARAM_WRITE_FRAME_SYNC:
+		set_param_write_sync(inst);
+		break;
+
+	case SET_PARAM_CFG_INFO:
+		set_cfg_info(inst, in);
+		break;
+
+	case SET_PARAM_PS_INFO:
+		set_param_ps_info(inst, in);
+		break;
+
+	case SET_PARAM_COMP_BUF_INFO:
+		set_param_comp_buf_info(inst, in);
+		break;
+
+	case SET_PARAM_HDR_INFO:
+		set_param_hdr_info(inst, in);
+		break;
+
+	case SET_PARAM_POST_EVENT:
+		set_param_post_event(inst, in);
+		break;
+
+	case SET_PARAM_PIC_INFO:
+		set_pic_info(inst, in);
+		break;
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"invalid set parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static struct vdec_common_if vdec_hevc_if = {
+	.init		= vdec_hevc_init,
+	.probe		= vdec_hevc_probe,
+	.decode		= vdec_hevc_decode,
+	.get_param	= vdec_hevc_get_param,
+	.set_param	= vdec_hevc_set_param,
+	.deinit		= vdec_hevc_deinit,
+};
+
+struct vdec_common_if *get_hevc_dec_comm_if(void);
+
+struct vdec_common_if *get_hevc_dec_comm_if(void)
+{
+	return &vdec_hevc_if;
+}
diff --git a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
new file mode 100644
index 0000000..8332956
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
@@ -0,0 +1,620 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <uapi/linux/swab.h>
+#include "../vdec_drv_if.h"
+#include "../aml_vcodec_util.h"
+#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_adapt.h"
+#include "../vdec_drv_base.h"
+#include "aml_mjpeg_parser.h"
+#include <media/v4l2-mem2mem.h>
+
+#define NAL_TYPE(value)				((value) & 0x1F)
+#define HEADER_BUFFER_SIZE			(32 * 1024)
+
+/**
+ * struct mjpeg_fb - mjpeg decode frame buffer information
+ * @vdec_fb_va  : virtual address of struct vdec_fb
+ * @y_fb_dma    : dma address of Y frame buffer (luma)
+ * @c_fb_dma    : dma address of C frame buffer (chroma)
+ * @poc         : picture order count of frame buffer
+ * @reserved    : for 8 bytes alignment
+ */
+struct mjpeg_fb {
+	uint64_t vdec_fb_va;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	int32_t poc;
+	uint32_t reserved;
+};
+
+/**
+ * struct vdec_mjpeg_dec_info - decode information
+ * @dpb_sz		: decoding picture buffer size
+ * @resolution_changed  : resoltion change happen
+ * @reserved		: for 8 bytes alignment
+ * @bs_dma		: Input bit-stream buffer dma address
+ * @y_fb_dma		: Y frame buffer dma address
+ * @c_fb_dma		: C frame buffer dma address
+ * @vdec_fb_va		: VDEC frame buffer struct virtual address
+ */
+struct vdec_mjpeg_dec_info {
+	uint32_t dpb_sz;
+	uint32_t resolution_changed;
+	uint32_t reserved;
+	uint64_t bs_dma;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	uint64_t vdec_fb_va;
+};
+
+/**
+ * struct vdec_mjpeg_vsi - shared memory for decode information exchange
+ *                        between VPU and Host.
+ *                        The memory is allocated by VPU then mapping to Host
+ *                        in vpu_dec_init() and freed in vpu_dec_deinit()
+ *                        by VPU.
+ *                        AP-W/R : AP is writer/reader on this item
+ *                        VPU-W/R: VPU is write/reader on this item
+ * @hdr_buf      : Header parsing buffer (AP-W, VPU-R)
+ * @list_free    : free frame buffer ring list (AP-W/R, VPU-W)
+ * @list_disp    : display frame buffer ring list (AP-R, VPU-W)
+ * @dec          : decode information (AP-R, VPU-W)
+ * @pic          : picture information (AP-R, VPU-W)
+ * @crop         : crop information (AP-R, VPU-W)
+ */
+struct vdec_mjpeg_vsi {
+	char *header_buf;
+	int sps_size;
+	int pps_size;
+	int sei_size;
+	int head_offset;
+	struct vdec_mjpeg_dec_info dec;
+	struct vdec_pic_info pic;
+	struct vdec_pic_info cur_pic;
+	struct v4l2_rect crop;
+	bool is_combine;
+	int nalu_pos;
+	//struct mjpeg_param_sets ps;
+};
+
+/**
+ * struct vdec_mjpeg_inst - mjpeg decoder instance
+ * @num_nalu : how many nalus be decoded
+ * @ctx      : point to aml_vcodec_ctx
+ * @vsi      : VPU shared information
+ */
+struct vdec_mjpeg_inst {
+	unsigned int num_nalu;
+	struct aml_vcodec_ctx *ctx;
+	struct aml_vdec_adapt vdec;
+	struct vdec_mjpeg_vsi *vsi;
+	struct aml_dec_params parms;
+	struct completion comp;
+};
+
+static void get_pic_info(struct vdec_mjpeg_inst *inst,
+			 struct vdec_pic_info *pic)
+{
+	*pic = inst->vsi->pic;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"pic(%d, %d), buf(%d, %d)\n",
+		 pic->visible_width, pic->visible_height,
+		 pic->coded_width, pic->coded_height);
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"Y(%d, %d), C(%d, %d)\n",
+		pic->y_bs_sz, pic->y_len_sz,
+		pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_crop_info(struct vdec_mjpeg_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = inst->vsi->crop.left;
+	cr->top = inst->vsi->crop.top;
+	cr->width = inst->vsi->crop.width;
+	cr->height = inst->vsi->crop.height;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"l=%d, t=%d, w=%d, h=%d\n",
+		 cr->left, cr->top, cr->width, cr->height);
+}
+
+static void get_dpb_size(struct vdec_mjpeg_inst *inst, unsigned int *dpb_sz)
+{
+	*dpb_sz = inst->vsi->dec.dpb_sz;
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"sz=%d\n", *dpb_sz);
+}
+
+static u32 vdec_config_default_parms(u8 *parm)
+{
+	u8 *pbuf = parm;
+
+	pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+	pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
+	pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:0;");
+	pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;");
+
+	return pbuf - parm;
+}
+
+static void vdec_parser_parms(struct vdec_mjpeg_inst *inst)
+{
+	struct aml_vcodec_ctx *ctx = inst->ctx;
+
+	if (ctx->config.parm.dec.parms_status &
+		V4L2_CONFIG_PARM_DECODE_CFGINFO) {
+		u8 *pbuf = ctx->config.buf;
+
+		pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+		pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
+			ctx->config.parm.dec.cfg.canvas_mem_mode);
+		pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
+			ctx->config.parm.dec.cfg.ref_buf_margin);
+		pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;",
+			ctx->config.parm.dec.cfg.canvas_mem_endian);
+		pbuf += sprintf(pbuf, "parm_v4l_duration:%d;",
+			ctx->config.parm.dec.cfg.duration);
+		ctx->config.length = pbuf - ctx->config.buf;
+	} else {
+		ctx->config.length = vdec_config_default_parms(ctx->config.buf);
+	}
+
+	inst->vdec.config	= ctx->config;
+	inst->parms.cfg		= ctx->config.parm.dec.cfg;
+	inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO;
+}
+
+
+static int vdec_mjpeg_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_mjpeg_inst *inst = NULL;
+	int ret = -1;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->vdec.frm_name	= "MJPEG";
+	inst->vdec.video_type	= VFORMAT_MJPEG;
+	inst->vdec.filp		= ctx->dev->filp;
+	inst->vdec.config	= ctx->config;
+	inst->vdec.ctx		= ctx;
+	inst->ctx		= ctx;
+
+	vdec_parser_parms(inst);
+	/* set play mode.*/
+	if (ctx->is_drm_mode)
+		inst->vdec.port.flag |= PORT_FLAG_DRM;
+
+	/* to eable mjpeg hw.*/
+	inst->vdec.port.type = PORT_TYPE_VIDEO;
+
+	/* probe info from the stream */
+	inst->vsi = kzalloc(sizeof(struct vdec_mjpeg_vsi), GFP_KERNEL);
+	if (!inst->vsi) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* alloc the header buffer to be used cache sps or spp etc.*/
+	inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
+	if (!inst->vsi->header_buf) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	init_completion(&inst->comp);
+	ctx->ada_ctx	= &inst->vdec;
+	*h_vdec		= (unsigned long)inst;
+
+	ret = video_decoder_init(&inst->vdec);
+	if (ret) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"vdec_mjpeg init err=%d\n", ret);
+		goto err;
+	}
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"mjpeg Instance >> %lx\n", (ulong) inst);
+
+	return 0;
+
+err:
+	if (inst && inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+	if (inst && inst->vsi)
+		kfree(inst->vsi);
+	if (inst)
+		kfree(inst);
+	*h_vdec = 0;
+
+	return ret;
+}
+
+#if 0
+static int refer_buffer_num(int level_idc, int poc_cnt,
+	int mb_width, int mb_height)
+{
+	return 20;
+}
+#endif
+
+static void fill_vdec_params(struct vdec_mjpeg_inst *inst,
+	struct MJpegDecodeContext *ps)
+{
+	struct vdec_pic_info *pic = &inst->vsi->pic;
+	struct vdec_mjpeg_dec_info *dec = &inst->vsi->dec;
+	struct v4l2_rect *rect = &inst->vsi->crop;
+
+	/* fill visible area size that be used for EGL. */
+	pic->visible_width	= ps->width;
+	pic->visible_height	= ps->height;
+
+	/* calc visible ares. */
+	rect->left		= 0;
+	rect->top		= 0;
+	rect->width		= pic->visible_width;
+	rect->height		= pic->visible_height;
+
+	/* config canvas size that be used for decoder. */
+	pic->coded_width	= ALIGN(ps->width, 64);
+	pic->coded_height	= ALIGN(ps->height, 64);
+
+	pic->y_len_sz		= pic->coded_width * pic->coded_height;
+	pic->c_len_sz		= pic->y_len_sz;
+
+	/*8(DECODE_BUFFER_NUM_DEF) */
+	dec->dpb_sz = 8;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"The stream infos, coded:(%d x %d), visible:(%d x %d)\n",
+		pic->coded_width, pic->coded_height,
+		pic->visible_width, pic->visible_height);
+}
+
+static int parse_stream_ucode(struct vdec_mjpeg_inst *inst,
+			      u8 *buf, u32 size, u64 timestamp)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write(vdec, buf, size, timestamp, 0);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write frame data failed. err: %d\n", ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_ucode_dma(struct vdec_mjpeg_inst *inst,
+	ulong buf, u32 size, u64 timestamp, u32 handle)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+		vdec_vframe_input_free, inst->ctx);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write frame data failed. err: %d\n", ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_cpu(struct vdec_mjpeg_inst *inst, u8 *buf, u32 size)
+{
+	int ret = 0;
+	struct mjpeg_param_sets *ps = NULL;
+
+	ps = kzalloc(sizeof(struct mjpeg_param_sets), GFP_KERNEL);
+	if (ps == NULL)
+		return -ENOMEM;
+
+	ret = mjpeg_decode_extradata_ps(buf, size, ps);
+	if (ret) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"parse extra data failed. err: %d\n", ret);
+		goto out;
+	}
+
+	if (ps->head_parsed)
+		fill_vdec_params(inst, &ps->dec_ps);
+
+	ret = ps->head_parsed ? 0 : -1;
+out:
+	kfree(ps);
+
+	return ret;
+}
+
+static int vdec_mjpeg_probe(unsigned long h_vdec,
+	struct aml_vcodec_mem *bs, void *out)
+{
+	struct vdec_mjpeg_inst *inst =
+		(struct vdec_mjpeg_inst *)h_vdec;
+	u8 *buf = (u8 *)bs->vaddr;
+	u32 size = bs->size;
+	int ret = 0;
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if ((s->magic != AML_VIDEO_MAGIC) &&
+				(s->type != V4L_STREAM_TYPE_MATEDATA))
+				return -1;
+
+			if (inst->ctx->param_sets_from_ucode) {
+				ret = parse_stream_ucode(inst, s->data,
+					s->len, bs->timestamp);
+			} else {
+				ret = parse_stream_cpu(inst, s->data, s->len);
+			}
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = parse_stream_ucode_dma(inst, bs->addr, size,
+				bs->timestamp, BUFF_IDX(bs, bs->index));
+		}
+	} else {
+		if (inst->ctx->param_sets_from_ucode) {
+			ret = parse_stream_ucode(inst, buf, size, bs->timestamp);
+		} else {
+			ret = parse_stream_cpu(inst, buf, size);
+		}
+	}
+
+	inst->vsi->cur_pic = inst->vsi->pic;
+
+	return ret;
+}
+
+static void vdec_mjpeg_deinit(unsigned long h_vdec)
+{
+	struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec;
+
+	if (!inst)
+		return;
+
+	video_decoder_release(&inst->vdec);
+
+	if (inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+
+	if (inst->vsi)
+		kfree(inst->vsi);
+
+	kfree(inst);
+}
+
+static int vdec_write_nalu(struct vdec_mjpeg_inst *inst,
+	u8 *buf, u32 size, u64 ts)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write(vdec, buf, size, ts, 0);
+
+	return ret;
+}
+
+static int vdec_mjpeg_decode(unsigned long h_vdec,
+			     struct aml_vcodec_mem *bs, bool *res_chg)
+{
+	struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+	u8 *buf = (u8 *) bs->vaddr;
+	u32 size = bs->size;
+	int ret = -1;
+
+	if (vdec_input_full(vdec))
+		return -EAGAIN;
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if (s->magic != AML_VIDEO_MAGIC)
+				return -1;
+
+			ret = vdec_vframe_write(vdec,
+				s->data,
+				s->len,
+				bs->timestamp,
+				0);
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = vdec_vframe_write_with_dma(vdec,
+				bs->addr, size, bs->timestamp,
+				BUFF_IDX(bs, bs->index),
+				vdec_vframe_input_free, inst->ctx);
+		}
+	} else {
+		ret = vdec_write_nalu(inst, buf, size, bs->timestamp);
+	}
+
+	return ret;
+}
+
+static int vdec_mjpeg_get_param(unsigned long h_vdec,
+			       enum vdec_get_param_type type, void *out)
+{
+	int ret = 0;
+	struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the mjpeg inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+
+	case GET_PARAM_DPB_SIZE:
+		get_dpb_size(inst, out);
+		break;
+
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+
+	case GET_PARAM_DW_MODE:
+	{
+		unsigned int* mode = out;
+		*mode = VDEC_DW_NO_AFBC;
+		break;
+	}
+
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"invalid get parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void set_param_ps_info(struct vdec_mjpeg_inst *inst,
+	struct aml_vdec_ps_infos *ps)
+{
+	struct vdec_pic_info *pic = &inst->vsi->pic;
+	struct vdec_mjpeg_dec_info *dec = &inst->vsi->dec;
+	struct v4l2_rect *rect = &inst->vsi->crop;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "%s in\n", __func__);
+	/* fill visible area size that be used for EGL. */
+	pic->visible_width	= ps->visible_width;
+	pic->visible_height	= ps->visible_height;
+
+	/* calc visible ares. */
+	rect->left		= 0;
+	rect->top		= 0;
+	rect->width		= pic->visible_width;
+	rect->height		= pic->visible_height;
+
+	/* config canvas size that be used for decoder. */
+	pic->coded_width	= ps->coded_width;
+	pic->coded_height	= ps->coded_height;
+	pic->y_len_sz		= pic->coded_width * pic->coded_height;
+	pic->c_len_sz		= pic->y_len_sz >> 1;
+
+	pic->dpb_frames		= ps->dpb_frames;
+	pic->dpb_margin		= ps->dpb_margin;
+	pic->vpp_margin		= ps->dpb_margin;
+	dec->dpb_sz		= ps->dpb_size;
+	pic->field		= ps->field;
+
+	inst->parms.ps 	= *ps;
+	inst->parms.parms_status |=
+		V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+	/*wake up*/
+	complete(&inst->comp);
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Parse from ucode, visible(%d x %d), coded(%d x %d), scan:%s\n",
+		ps->visible_width, ps->visible_height,
+		ps->coded_width, ps->coded_height,
+		pic->field == V4L2_FIELD_NONE ? "P" : "I");
+}
+
+static void set_param_write_sync(struct vdec_mjpeg_inst *inst)
+{
+	complete(&inst->comp);
+}
+
+static void set_pic_info(struct vdec_mjpeg_inst *inst,
+	struct vdec_pic_info *pic)
+{
+	inst->vsi->pic = *pic;
+}
+
+static int vdec_mjpeg_set_param(unsigned long h_vdec,
+	enum vdec_set_param_type type, void *in)
+{
+	int ret = 0;
+	struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the mjpeg inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case SET_PARAM_WRITE_FRAME_SYNC:
+		set_param_write_sync(inst);
+		break;
+
+	case SET_PARAM_PS_INFO:
+		set_param_ps_info(inst, in);
+		break;
+
+	case SET_PARAM_PIC_INFO:
+		set_pic_info(inst, in);
+		break;
+
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"invalid set parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static struct vdec_common_if vdec_mjpeg_if = {
+	.init		= vdec_mjpeg_init,
+	.probe		= vdec_mjpeg_probe,
+	.decode		= vdec_mjpeg_decode,
+	.get_param	= vdec_mjpeg_get_param,
+	.set_param	= vdec_mjpeg_set_param,
+	.deinit		= vdec_mjpeg_deinit,
+};
+
+struct vdec_common_if *get_mjpeg_dec_comm_if(void);
+
+struct vdec_common_if *get_mjpeg_dec_comm_if(void)
+{
+	return &vdec_mjpeg_if;
+}
diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
new file mode 100644
index 0000000..2472ac1
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
@@ -0,0 +1,645 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <uapi/linux/swab.h>
+#include "../vdec_drv_if.h"
+#include "../aml_vcodec_util.h"
+#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_adapt.h"
+#include "../vdec_drv_base.h"
+#include "aml_mpeg12_parser.h"
+
+#define NAL_TYPE(value)				((value) & 0x1F)
+#define HEADER_BUFFER_SIZE			(32 * 1024)
+
+/**
+ * struct mpeg12_fb - mpeg12 decode frame buffer information
+ * @vdec_fb_va  : virtual address of struct vdec_fb
+ * @y_fb_dma    : dma address of Y frame buffer (luma)
+ * @c_fb_dma    : dma address of C frame buffer (chroma)
+ * @poc         : picture order count of frame buffer
+ * @reserved    : for 8 bytes alignment
+ */
+struct mpeg12_fb {
+	uint64_t vdec_fb_va;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	int32_t poc;
+	uint32_t reserved;
+};
+
+/**
+ * struct vdec_mpeg12_dec_info - decode information
+ * @dpb_sz		: decoding picture buffer size
+ * @resolution_changed  : resoltion change happen
+ * @reserved		: for 8 bytes alignment
+ * @bs_dma		: Input bit-stream buffer dma address
+ * @y_fb_dma		: Y frame buffer dma address
+ * @c_fb_dma		: C frame buffer dma address
+ * @vdec_fb_va		: VDEC frame buffer struct virtual address
+ */
+struct vdec_mpeg12_dec_info {
+	uint32_t dpb_sz;
+	uint32_t resolution_changed;
+	uint32_t reserved;
+	uint64_t bs_dma;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	uint64_t vdec_fb_va;
+};
+
+/**
+ * struct vdec_mpeg12_vsi - shared memory for decode information exchange
+ *                        between VPU and Host.
+ *                        The memory is allocated by VPU then mapping to Host
+ *                        in vpu_dec_init() and freed in vpu_dec_deinit()
+ *                        by VPU.
+ *                        AP-W/R : AP is writer/reader on this item
+ *                        VPU-W/R: VPU is write/reader on this item
+ * @hdr_buf      : Header parsing buffer (AP-W, VPU-R)
+ * @list_free    : free frame buffer ring list (AP-W/R, VPU-W)
+ * @list_disp    : display frame buffer ring list (AP-R, VPU-W)
+ * @dec          : decode information (AP-R, VPU-W)
+ * @pic          : picture information (AP-R, VPU-W)
+ * @crop         : crop information (AP-R, VPU-W)
+ */
+struct vdec_mpeg12_vsi {
+	char *header_buf;
+	int sps_size;
+	int pps_size;
+	int sei_size;
+	int head_offset;
+	struct vdec_mpeg12_dec_info dec;
+	struct vdec_pic_info pic;
+	struct vdec_pic_info cur_pic;
+	struct v4l2_rect crop;
+	bool is_combine;
+	int nalu_pos;
+	//struct mpeg12_param_sets ps;
+};
+
+/**
+ * struct vdec_mpeg12_inst - mpeg12 decoder instance
+ * @num_nalu : how many nalus be decoded
+ * @ctx      : point to aml_vcodec_ctx
+ * @vsi      : VPU shared information
+ */
+struct vdec_mpeg12_inst {
+	unsigned int num_nalu;
+	struct aml_vcodec_ctx *ctx;
+	struct aml_vdec_adapt vdec;
+	struct vdec_mpeg12_vsi *vsi;
+	struct aml_dec_params parms;
+	struct completion comp;
+};
+
+static void get_pic_info(struct vdec_mpeg12_inst *inst,
+			 struct vdec_pic_info *pic)
+{
+	*pic = inst->vsi->pic;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"pic(%d, %d), buf(%d, %d)\n",
+		 pic->visible_width, pic->visible_height,
+		 pic->coded_width, pic->coded_height);
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"Y(%d, %d), C(%d, %d)\n",
+		pic->y_bs_sz, pic->y_len_sz,
+		pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_crop_info(struct vdec_mpeg12_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = inst->vsi->crop.left;
+	cr->top = inst->vsi->crop.top;
+	cr->width = inst->vsi->crop.width;
+	cr->height = inst->vsi->crop.height;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"l=%d, t=%d, w=%d, h=%d\n",
+		 cr->left, cr->top, cr->width, cr->height);
+}
+
+static void get_dpb_size(struct vdec_mpeg12_inst *inst, unsigned int *dpb_sz)
+{
+	*dpb_sz = inst->vsi->dec.dpb_sz;
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, "sz=%d\n", *dpb_sz);
+}
+
+static u32 vdec_config_default_parms(u8 *parm)
+{
+	u8 *pbuf = parm;
+
+	pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+	pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
+	pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:0;");
+
+	return pbuf - parm;
+}
+
+static void vdec_parser_parms(struct vdec_mpeg12_inst *inst)
+{
+	struct aml_vcodec_ctx *ctx = inst->ctx;
+
+	if (ctx->config.parm.dec.parms_status &
+		V4L2_CONFIG_PARM_DECODE_CFGINFO) {
+		u8 *pbuf = ctx->config.buf;
+
+		pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+		pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
+			ctx->config.parm.dec.cfg.canvas_mem_mode);
+		pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
+			ctx->config.parm.dec.cfg.ref_buf_margin);
+		pbuf += sprintf(pbuf, "parm_v4l_metadata_config_flag:%d;",
+			ctx->config.parm.dec.cfg.metadata_config_flag);
+		pbuf += sprintf(pbuf, "parm_v4l_duration:%d;",
+			ctx->config.parm.dec.cfg.duration);
+		ctx->config.length = pbuf - ctx->config.buf;
+	} else {
+		ctx->config.length = vdec_config_default_parms(ctx->config.buf);
+	}
+
+	inst->vdec.config	= ctx->config;
+	inst->parms.cfg		= ctx->config.parm.dec.cfg;
+	inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO;
+}
+
+static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_mpeg12_inst *inst = NULL;
+	int ret = -1;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->vdec.frm_name	= "MPEG2";
+	inst->vdec.video_type	= VFORMAT_MPEG12;
+	inst->vdec.filp		= ctx->dev->filp;
+	inst->vdec.config	= ctx->config;
+	inst->vdec.ctx		= ctx;
+	inst->ctx		= ctx;
+
+	vdec_parser_parms(inst);
+
+	/* set play mode.*/
+	if (ctx->is_drm_mode)
+		inst->vdec.port.flag |= PORT_FLAG_DRM;
+
+	/* to eable mpeg12 hw.*/
+	inst->vdec.port.type = PORT_TYPE_VIDEO;
+
+	/* probe info from the stream */
+	inst->vsi = kzalloc(sizeof(struct vdec_mpeg12_vsi), GFP_KERNEL);
+	if (!inst->vsi) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* alloc the header buffer to be used cache sps or spp etc.*/
+	inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
+	if (!inst->vsi->header_buf) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	init_completion(&inst->comp);
+	ctx->ada_ctx	= &inst->vdec;
+	*h_vdec		= (unsigned long)inst;
+
+	ret = video_decoder_init(&inst->vdec);
+	if (ret) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"vdec_mpeg12 init err=%d\n", ret);
+		goto err;
+	}
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"mpeg12 Instance >> %lx\n", (ulong) inst);
+
+	return 0;
+
+err:
+	if (inst && inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+	if (inst && inst->vsi)
+		kfree(inst->vsi);
+	if (inst)
+		kfree(inst);
+	*h_vdec = 0;
+
+	return ret;
+}
+
+static void fill_vdec_params(struct vdec_mpeg12_inst *inst,
+	struct MpvParseContext *dec_ps)
+{
+	struct vdec_pic_info *pic = &inst->vsi->pic;
+	struct vdec_mpeg12_dec_info *dec = &inst->vsi->dec;
+	struct v4l2_rect *rect = &inst->vsi->crop;
+
+	/* fill visible area size that be used for EGL. */
+	pic->visible_width	= dec_ps->width;
+	pic->visible_height	= dec_ps->height;
+
+	/* calc visible ares. */
+	rect->left		= 0;
+	rect->top		= 0;
+	rect->width		= pic->visible_width;
+	rect->height		= pic->visible_height;
+
+	/* config canvas size that be used for decoder. */
+	pic->coded_width	= ALIGN(dec_ps->coded_width, 64);
+	pic->coded_height	= ALIGN(dec_ps->coded_height, 32);
+
+	pic->y_len_sz		= pic->coded_width * pic->coded_height;
+	pic->c_len_sz		= pic->y_len_sz >> 1;
+
+	/*7(parm_v4l_buffer_margin) + 8(DECODE_BUFFER_NUM_DEF)*/
+	dec->dpb_sz = 15;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
+		pic->coded_width, pic->coded_height,
+		pic->visible_width, pic->visible_height, dec->dpb_sz);
+}
+
+static int parse_stream_ucode(struct vdec_mpeg12_inst *inst,
+			      u8 *buf, u32 size, u64 timestamp)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write(vdec, buf, size, timestamp, 0);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write frame data failed. err: %d\n", ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_ucode_dma(struct vdec_mpeg12_inst *inst,
+	ulong buf, u32 size, u64 timestamp, u32 handle)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+		vdec_vframe_input_free, inst->ctx);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write frame data failed. err: %d\n", ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_cpu(struct vdec_mpeg12_inst *inst, u8 *buf, u32 size)
+{
+	int ret = 0;
+	struct mpeg12_param_sets *ps = NULL;
+
+	ps = kzalloc(sizeof(struct mpeg12_param_sets), GFP_KERNEL);
+	if (ps == NULL)
+		return -ENOMEM;
+
+	ret = mpeg12_decode_extradata_ps(buf, size, ps);
+	if (ret) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"parse extra data failed. err: %d\n", ret);
+		goto out;
+	}
+
+	if (ps->head_parsed)
+		fill_vdec_params(inst, &ps->dec_ps);
+
+	ret = ps->head_parsed ? 0 : -1;
+out:
+	kfree(ps);
+
+	return ret;
+}
+
+static int vdec_mpeg12_probe(unsigned long h_vdec,
+	struct aml_vcodec_mem *bs, void *out)
+{
+	struct vdec_mpeg12_inst *inst =
+		(struct vdec_mpeg12_inst *)h_vdec;
+	u8 *buf = (u8 *)bs->vaddr;
+	u32 size = bs->size;
+	int ret = 0;
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if ((s->magic != AML_VIDEO_MAGIC) &&
+				(s->type != V4L_STREAM_TYPE_MATEDATA))
+				return -1;
+
+			if (inst->ctx->param_sets_from_ucode) {
+				ret = parse_stream_ucode(inst, s->data,
+					s->len, bs->timestamp);
+			} else {
+				ret = parse_stream_cpu(inst, s->data, s->len);
+			}
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = parse_stream_ucode_dma(inst, bs->addr, size,
+				bs->timestamp, BUFF_IDX(bs, bs->index));
+		}
+	} else {
+		if (inst->ctx->param_sets_from_ucode) {
+			ret = parse_stream_ucode(inst, buf, size, bs->timestamp);
+		} else {
+			ret = parse_stream_cpu(inst, buf, size);
+		}
+	}
+
+	inst->vsi->cur_pic = inst->vsi->pic;
+
+	return ret;
+}
+
+static void vdec_mpeg12_deinit(unsigned long h_vdec)
+{
+	struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec;
+
+	if (!inst)
+		return;
+
+	video_decoder_release(&inst->vdec);
+
+	if (inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+
+	if (inst->vsi)
+		kfree(inst->vsi);
+
+	kfree(inst);
+}
+
+static int vdec_write_nalu(struct vdec_mpeg12_inst *inst,
+	u8 *buf, u32 size, u64 ts)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write(vdec, buf, size, ts, 0);
+
+	return ret;
+}
+
+static int vdec_mpeg12_decode(unsigned long h_vdec,
+			      struct aml_vcodec_mem *bs, bool *res_chg)
+{
+	struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+	u8 *buf = (u8 *) bs->vaddr;
+	u32 size = bs->size;
+	int ret = -1;
+
+	if (vdec_input_full(vdec))
+		return -EAGAIN;
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if (s->magic != AML_VIDEO_MAGIC)
+				return -1;
+
+			ret = vdec_vframe_write(vdec,
+				s->data,
+				s->len,
+				bs->timestamp,
+				0);
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = vdec_vframe_write_with_dma(vdec,
+				bs->addr, size, bs->timestamp,
+				BUFF_IDX(bs, bs->index),
+				vdec_vframe_input_free, inst->ctx);
+		}
+	} else {
+		ret = vdec_write_nalu(inst, buf, size, bs->timestamp);
+	}
+
+	return ret;
+}
+
+static void get_param_config_info(struct vdec_mpeg12_inst *inst,
+  struct aml_dec_params *parms)
+{
+
+	if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO)
+		parms->hdr = inst->parms.hdr;
+
+	parms->parms_status |= inst->parms.parms_status;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"parms status: %u\n", parms->parms_status);
+}
+
+static int vdec_mpeg12_get_param(unsigned long h_vdec,
+			       enum vdec_get_param_type type, void *out)
+{
+	int ret = 0;
+	struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the mpeg12 inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+
+	case GET_PARAM_DPB_SIZE:
+		get_dpb_size(inst, out);
+		break;
+
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+
+	case GET_PARAM_CONFIG_INFO:
+		get_param_config_info(inst, out);
+		break;
+
+	case GET_PARAM_DW_MODE:
+	{
+		unsigned int* mode = out;
+		*mode = VDEC_DW_NO_AFBC;
+		break;
+	}
+
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"invalid get parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void set_param_write_sync(struct vdec_mpeg12_inst *inst)
+{
+	complete(&inst->comp);
+}
+
+static void set_pic_info(struct vdec_mpeg12_inst *inst,
+	struct vdec_pic_info *pic)
+{
+	inst->vsi->pic = *pic;
+}
+
+static void set_param_ps_info(struct vdec_mpeg12_inst *inst,
+	struct aml_vdec_ps_infos *ps)
+{
+	struct vdec_pic_info *pic = &inst->vsi->pic;
+	struct vdec_mpeg12_dec_info *dec = &inst->vsi->dec;
+	struct v4l2_rect *rect = &inst->vsi->crop;
+
+	/* fill visible area size that be used for EGL. */
+	pic->visible_width	= ps->visible_width;
+	pic->visible_height	= ps->visible_height;
+
+	/* calc visible ares. */
+	rect->left		= 0;
+	rect->top		= 0;
+	rect->width		= pic->visible_width;
+	rect->height		= pic->visible_height;
+
+	/* config canvas size that be used for decoder. */
+	pic->coded_width	= ps->coded_width;
+	pic->coded_height	= ps->coded_height;
+	pic->y_len_sz		= pic->coded_width * pic->coded_height;
+	pic->c_len_sz		= pic->y_len_sz >> 1;
+
+	pic->dpb_frames		= ps->dpb_frames;
+	pic->dpb_margin		= ps->dpb_margin;
+	pic->vpp_margin		= ps->dpb_margin;
+	dec->dpb_sz		= ps->dpb_size;
+	pic->field		= ps->field;
+
+	inst->parms.ps 	= *ps;
+	inst->parms.parms_status |=
+		V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+	/*wake up*/
+	complete(&inst->comp);
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Parse from ucode, visible(%d x %d), coded(%d x %d), scan:%s\n",
+		ps->visible_width, ps->visible_height,
+		ps->coded_width, ps->coded_height,
+		pic->field == V4L2_FIELD_NONE ? "P" : "I");
+}
+
+static void set_param_hdr_info(struct vdec_mpeg12_inst *inst,
+	struct aml_vdec_hdr_infos *hdr)
+{
+	inst->parms.hdr = *hdr;
+	if (!(inst->parms.parms_status &
+		V4L2_CONFIG_PARM_DECODE_HDRINFO)) {
+		inst->parms.hdr = *hdr;
+		inst->parms.parms_status |=
+			V4L2_CONFIG_PARM_DECODE_HDRINFO;
+		aml_vdec_dispatch_event(inst->ctx,
+			V4L2_EVENT_SRC_CH_HDRINFO);
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+			"mpeg12 set HDR infos\n");
+	}
+}
+
+static int vdec_mpeg12_set_param(unsigned long h_vdec,
+	enum vdec_set_param_type type, void *in)
+{
+	int ret = 0;
+	struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the mpeg12 inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case SET_PARAM_WRITE_FRAME_SYNC:
+		set_param_write_sync(inst);
+		break;
+
+	case SET_PARAM_HDR_INFO:
+		set_param_hdr_info(inst, in);
+		break;
+
+	case SET_PARAM_PS_INFO:
+		set_param_ps_info(inst, in);
+		break;
+
+	case SET_PARAM_PIC_INFO:
+		set_pic_info(inst, in);
+		break;
+
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"invalid set parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static struct vdec_common_if vdec_mpeg12_if = {
+	.init		= vdec_mpeg12_init,
+	.probe		= vdec_mpeg12_probe,
+	.decode		= vdec_mpeg12_decode,
+	.get_param	= vdec_mpeg12_get_param,
+	.set_param	= vdec_mpeg12_set_param,
+	.deinit		= vdec_mpeg12_deinit,
+};
+
+struct vdec_common_if *get_mpeg12_dec_comm_if(void);
+
+struct vdec_common_if *get_mpeg12_dec_comm_if(void)
+{
+	return &vdec_mpeg12_if;
+}
diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
new file mode 100644
index 0000000..bc0af24
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
@@ -0,0 +1,615 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <uapi/linux/swab.h>
+#include "../vdec_drv_if.h"
+#include "../aml_vcodec_util.h"
+#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_adapt.h"
+#include "../vdec_drv_base.h"
+#include "aml_mpeg4_parser.h"
+
+#define NAL_TYPE(value)				((value) & 0x1F)
+#define HEADER_BUFFER_SIZE			(32 * 1024)
+
+/**
+ * struct mpeg4_fb - mpeg4 decode frame buffer information
+ * @vdec_fb_va  : virtual address of struct vdec_fb
+ * @y_fb_dma    : dma address of Y frame buffer (luma)
+ * @c_fb_dma    : dma address of C frame buffer (chroma)
+ * @poc         : picture order count of frame buffer
+ * @reserved    : for 8 bytes alignment
+ */
+struct mpeg4_fb {
+	uint64_t vdec_fb_va;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	int32_t poc;
+	uint32_t reserved;
+};
+
+/**
+ * struct vdec_mpeg4_dec_info - decode information
+ * @dpb_sz		: decoding picture buffer size
+ * @resolution_changed  : resoltion change happen
+ * @reserved		: for 8 bytes alignment
+ * @bs_dma		: Input bit-stream buffer dma address
+ * @y_fb_dma		: Y frame buffer dma address
+ * @c_fb_dma		: C frame buffer dma address
+ * @vdec_fb_va		: VDEC frame buffer struct virtual address
+ */
+struct vdec_mpeg4_dec_info {
+	uint32_t dpb_sz;
+	uint32_t resolution_changed;
+	uint32_t reserved;
+	uint64_t bs_dma;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	uint64_t vdec_fb_va;
+};
+
+/**
+ * struct vdec_mpeg4_vsi - shared memory for decode information exchange
+ *                        between VPU and Host.
+ *                        The memory is allocated by VPU then mapping to Host
+ *                        in vpu_dec_init() and freed in vpu_dec_deinit()
+ *                        by VPU.
+ *                        AP-W/R : AP is writer/reader on this item
+ *                        VPU-W/R: VPU is write/reader on this item
+ * @hdr_buf      : Header parsing buffer (AP-W, VPU-R)
+ * @list_free    : free frame buffer ring list (AP-W/R, VPU-W)
+ * @list_disp    : display frame buffer ring list (AP-R, VPU-W)
+ * @dec          : decode information (AP-R, VPU-W)
+ * @pic          : picture information (AP-R, VPU-W)
+ * @crop         : crop information (AP-R, VPU-W)
+ */
+struct vdec_mpeg4_vsi {
+	char *header_buf;
+	int sps_size;
+	int pps_size;
+	int sei_size;
+	int head_offset;
+	struct vdec_mpeg4_dec_info dec;
+	struct vdec_pic_info pic;
+	struct vdec_pic_info cur_pic;
+	struct v4l2_rect crop;
+	bool is_combine;
+	int nalu_pos;
+	//struct mpeg4ParamSets ps;
+};
+
+/**
+ * struct vdec_mpeg4_inst - mpeg4 decoder instance
+ * @num_nalu : how many nalus be decoded
+ * @ctx      : point to aml_vcodec_ctx
+ * @vsi      : VPU shared information
+ */
+struct vdec_mpeg4_inst {
+	unsigned int num_nalu;
+	struct aml_vcodec_ctx *ctx;
+	struct aml_vdec_adapt vdec;
+	struct vdec_mpeg4_vsi *vsi;
+	struct aml_dec_params parms;
+	struct completion comp;
+};
+
+static void get_pic_info(struct vdec_mpeg4_inst *inst,
+			 struct vdec_pic_info *pic)
+{
+	*pic = inst->vsi->pic;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"pic(%d, %d), buf(%d, %d)\n",
+		 pic->visible_width, pic->visible_height,
+		 pic->coded_width, pic->coded_height);
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"Y(%d, %d), C(%d, %d)\n",
+		pic->y_bs_sz, pic->y_len_sz,
+		pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_crop_info(struct vdec_mpeg4_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = inst->vsi->crop.left;
+	cr->top = inst->vsi->crop.top;
+	cr->width = inst->vsi->crop.width;
+	cr->height = inst->vsi->crop.height;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"l=%d, t=%d, w=%d, h=%d\n",
+		 cr->left, cr->top, cr->width, cr->height);
+}
+
+static void get_dpb_size(struct vdec_mpeg4_inst *inst, unsigned int *dpb_sz)
+{
+	*dpb_sz = inst->vsi->dec.dpb_sz;
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, "sz=%d\n", *dpb_sz);
+}
+
+static u32 vdec_config_default_parms(u8 *parm)
+{
+	u8 *pbuf = parm;
+
+	pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+	pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
+	pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:0;");
+
+	return pbuf - parm;
+}
+
+static void vdec_parser_parms(struct vdec_mpeg4_inst *inst)
+{
+	struct aml_vcodec_ctx *ctx = inst->ctx;
+
+	if (ctx->config.parm.dec.parms_status &
+		V4L2_CONFIG_PARM_DECODE_CFGINFO) {
+		u8 *pbuf = ctx->config.buf;
+
+		pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+		pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
+			ctx->config.parm.dec.cfg.canvas_mem_mode);
+		pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
+			ctx->config.parm.dec.cfg.ref_buf_margin);
+		pbuf += sprintf(pbuf, "parm_v4l_duration:%d;",
+			ctx->config.parm.dec.cfg.duration);
+		ctx->config.length = pbuf - ctx->config.buf;
+	} else {
+		ctx->config.length = vdec_config_default_parms(ctx->config.buf);
+	}
+
+	inst->vdec.config	= ctx->config;
+	inst->parms.cfg		= ctx->config.parm.dec.cfg;
+	inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO;
+}
+
+
+static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_mpeg4_inst *inst = NULL;
+	int ret = -1;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->vdec.frm_name	= "MPEG4";
+	inst->vdec.video_type	= VFORMAT_MPEG4;
+	inst->vdec.format	= VIDEO_DEC_FORMAT_MPEG4_5;
+	inst->vdec.filp		= ctx->dev->filp;
+	inst->vdec.config	= ctx->config;
+	inst->vdec.ctx		= ctx;
+	inst->ctx		= ctx;
+
+	vdec_parser_parms(inst);
+	/* set play mode.*/
+	if (ctx->is_drm_mode)
+		inst->vdec.port.flag |= PORT_FLAG_DRM;
+
+	/* to eable mpeg4 hw.*/
+	inst->vdec.port.type	= PORT_TYPE_VIDEO;
+
+	/* probe info from the stream */
+	inst->vsi = kzalloc(sizeof(struct vdec_mpeg4_vsi), GFP_KERNEL);
+	if (!inst->vsi) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* alloc the header buffer to be used cache sps or spp etc.*/
+	inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
+	if (!inst->vsi->header_buf) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	init_completion(&inst->comp);
+	ctx->ada_ctx	= &inst->vdec;
+	*h_vdec		= (unsigned long)inst;
+
+	ret = video_decoder_init(&inst->vdec);
+	if (ret) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"vdec_mpeg4 init err=%d\n", ret);
+		goto err;
+	}
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"mpeg4 Instance >> %lx\n", (ulong) inst);
+
+	return 0;
+
+err:
+	if (inst && inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+	if (inst && inst->vsi)
+		kfree(inst->vsi);
+	if (inst)
+		kfree(inst);
+	*h_vdec = 0;
+
+	return ret;
+}
+
+#if 0
+static int refer_buffer_num(int level_idc, int poc_cnt,
+	int mb_width, int mb_height)
+{
+	return 20;
+}
+#endif
+
+static void fill_vdec_params(struct vdec_mpeg4_inst *inst,
+	struct mpeg4_dec_param *dec_ps)
+{
+	struct vdec_pic_info *pic = &inst->vsi->pic;
+	struct vdec_mpeg4_dec_info *dec = &inst->vsi->dec;
+	struct v4l2_rect *rect = &inst->vsi->crop;
+
+	/* fill visible area size that be used for EGL. */
+	pic->visible_width	= dec_ps->m.width;
+	pic->visible_height	= dec_ps->m.height;
+
+	/* calc visible ares. */
+	rect->left		= 0;
+	rect->top		= 0;
+	rect->width		= pic->visible_width;
+	rect->height		= pic->visible_height;
+
+	/* config canvas size that be used for decoder. */
+	pic->coded_width	= ALIGN(dec_ps->m.width, 64);
+	pic->coded_height	= ALIGN(dec_ps->m.height, 64);
+
+	pic->y_len_sz		= pic->coded_width * pic->coded_height;
+	pic->c_len_sz		= pic->y_len_sz >> 1;
+
+	/*8(DECODE_BUFFER_NUM_DEF) */
+	dec->dpb_sz = 8;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
+		pic->coded_width, pic->coded_height,
+		pic->visible_width, pic->visible_height, dec->dpb_sz);
+}
+
+static int parse_stream_ucode(struct vdec_mpeg4_inst *inst,
+			     u8 *buf, u32 size, u64 timestamp)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write(vdec, buf, size, timestamp, 0);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write frame data failed. err: %d\n", ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_ucode_dma(struct vdec_mpeg4_inst *inst,
+	ulong buf, u32 size, u64 timestamp, u32 handle)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+		vdec_vframe_input_free, inst->ctx);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write frame data failed. err: %d\n", ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_cpu(struct vdec_mpeg4_inst *inst, u8 *buf, u32 size)
+{
+	int ret = 0;
+	struct mpeg4_param_sets *ps = NULL;
+
+	ps = kzalloc(sizeof(struct mpeg4_param_sets), GFP_KERNEL);
+	if (ps == NULL)
+		return -ENOMEM;
+
+	ret = mpeg4_decode_extradata_ps(buf, size, ps);
+	if (ret) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"parse extra data failed. err: %d\n", ret);
+		goto out;
+	}
+
+	if (ps->head_parsed)
+		fill_vdec_params(inst, &ps->dec_ps);
+
+	ret = ps->head_parsed ? 0 : -1;
+out:
+	kfree(ps);
+
+	return ret;
+}
+
+static int vdec_mpeg4_probe(unsigned long h_vdec,
+	struct aml_vcodec_mem *bs, void *out)
+{
+	struct vdec_mpeg4_inst *inst =
+		(struct vdec_mpeg4_inst *)h_vdec;
+	u8 *buf = (u8 *)bs->vaddr;
+	u32 size = bs->size;
+	int ret = 0;
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if ((s->magic != AML_VIDEO_MAGIC) &&
+				(s->type != V4L_STREAM_TYPE_MATEDATA))
+				return -1;
+
+			if (inst->ctx->param_sets_from_ucode) {
+				ret = parse_stream_ucode(inst, s->data,
+					s->len, bs->timestamp);
+			} else {
+				ret = parse_stream_cpu(inst, s->data, s->len);
+			}
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = parse_stream_ucode_dma(inst, bs->addr, size,
+				bs->timestamp, BUFF_IDX(bs, bs->index));
+		}
+	} else {
+		if (inst->ctx->param_sets_from_ucode) {
+			ret = parse_stream_ucode(inst, buf, size, bs->timestamp);
+		} else {
+			ret = parse_stream_cpu(inst, buf, size);
+		}
+	}
+
+	inst->vsi->cur_pic = inst->vsi->pic;
+
+	return ret;
+}
+
+static void vdec_mpeg4_deinit(unsigned long h_vdec)
+{
+	struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
+
+	if (!inst)
+		return;
+
+	video_decoder_release(&inst->vdec);
+
+	if (inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+
+	if (inst->vsi)
+		kfree(inst->vsi);
+
+	kfree(inst);
+}
+
+static int vdec_write_nalu(struct vdec_mpeg4_inst *inst,
+	u8 *buf, u32 size, u64 ts)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write(vdec, buf, size, ts, 0);
+
+	return ret;
+}
+
+static int vdec_mpeg4_decode(unsigned long h_vdec,
+			     struct aml_vcodec_mem *bs, bool *res_chg)
+{
+	struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+	u8 *buf = (u8 *) bs->vaddr;
+	u32 size = bs->size;
+	int ret = -1;
+
+	if (vdec_input_full(vdec))
+		return -EAGAIN;
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if (s->magic != AML_VIDEO_MAGIC)
+				return -1;
+
+			ret = vdec_vframe_write(vdec,
+				s->data,
+				s->len,
+				bs->timestamp,
+				0);
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = vdec_vframe_write_with_dma(vdec,
+				bs->addr, size, bs->timestamp,
+				BUFF_IDX(bs, bs->index),
+				vdec_vframe_input_free, inst->ctx);
+		}
+	} else {
+		ret = vdec_write_nalu(inst, buf, size, bs->timestamp);
+	}
+
+	return ret;
+}
+
+static int vdec_mpeg4_get_param(unsigned long h_vdec,
+			       enum vdec_get_param_type type, void *out)
+{
+	int ret = 0;
+	struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the mpeg4 inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+
+	case GET_PARAM_DPB_SIZE:
+		get_dpb_size(inst, out);
+		break;
+
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+	case GET_PARAM_DW_MODE:
+	{
+		unsigned int* mode = out;
+		*mode = VDEC_DW_NO_AFBC;
+		break;
+	}
+
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+			"invalid get parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void set_param_ps_info(struct vdec_mpeg4_inst *inst,
+	struct aml_vdec_ps_infos *ps)
+{
+	struct vdec_pic_info *pic = &inst->vsi->pic;
+	struct vdec_mpeg4_dec_info *dec = &inst->vsi->dec;
+	struct v4l2_rect *rect = &inst->vsi->crop;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "%s in\n", __func__);
+	/* fill visible area size that be used for EGL. */
+	pic->visible_width	= ps->visible_width;
+	pic->visible_height	= ps->visible_height;
+
+	/* calc visible ares. */
+	rect->left		= 0;
+	rect->top		= 0;
+	rect->width		= pic->visible_width;
+	rect->height		= pic->visible_height;
+
+	/* config canvas size that be used for decoder. */
+	pic->coded_width	= ps->coded_width;
+	pic->coded_height	= ps->coded_height;
+	pic->y_len_sz		= pic->coded_width * pic->coded_height;
+	pic->c_len_sz		= pic->y_len_sz >> 1;
+
+	pic->dpb_frames		= ps->dpb_frames;
+	pic->dpb_margin		= ps->dpb_margin;
+	pic->vpp_margin		= ps->dpb_margin;
+	dec->dpb_sz		= ps->dpb_size;
+	pic->field		= ps->field;
+
+	inst->parms.ps 	= *ps;
+	inst->parms.parms_status |=
+		V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+	/*wake up*/
+	complete(&inst->comp);
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Parse from ucode, visible(%d x %d), coded(%d x %d), scan:%s\n",
+		ps->visible_width, ps->visible_height,
+		ps->coded_width, ps->coded_height,
+		pic->field == V4L2_FIELD_NONE ? "P" : "I");
+}
+
+static void set_param_write_sync(struct vdec_mpeg4_inst *inst)
+{
+	complete(&inst->comp);
+}
+
+static void set_pic_info(struct vdec_mpeg4_inst *inst,
+	struct vdec_pic_info *pic)
+{
+	inst->vsi->pic = *pic;
+}
+
+static int vdec_mpeg4_set_param(unsigned long h_vdec,
+	enum vdec_set_param_type type, void *in)
+{
+	int ret = 0;
+	struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the mpeg4 inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case SET_PARAM_WRITE_FRAME_SYNC:
+		set_param_write_sync(inst);
+		break;
+
+	case SET_PARAM_PS_INFO:
+		set_param_ps_info(inst, in);
+		break;
+
+	case SET_PARAM_PIC_INFO:
+		set_pic_info(inst, in);
+		break;
+
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"invalid set parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static struct vdec_common_if vdec_mpeg4_if = {
+	.init		= vdec_mpeg4_init,
+	.probe		= vdec_mpeg4_probe,
+	.decode		= vdec_mpeg4_decode,
+	.get_param	= vdec_mpeg4_get_param,
+	.set_param	= vdec_mpeg4_set_param,
+	.deinit		= vdec_mpeg4_deinit,
+};
+
+struct vdec_common_if *get_mpeg4_dec_comm_if(void);
+
+struct vdec_common_if *get_mpeg4_dec_comm_if(void)
+{
+	return &vdec_mpeg4_if;
+}
diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_if.c b/drivers/amvdec_ports/decoder/vdec_vp9_if.c
new file mode 100644
index 0000000..fe81ddd
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/vdec_vp9_if.c
@@ -0,0 +1,1065 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <uapi/linux/swab.h>
+#include "../vdec_drv_if.h"
+#include "../aml_vcodec_util.h"
+#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_drv.h"
+#include "../aml_vcodec_adapt.h"
+#include "../vdec_drv_base.h"
+#include "aml_vp9_parser.h"
+#include "vdec_vp9_trigger.h"
+
+#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2
+#include <trace/events/meson_atrace.h>
+
+#define PREFIX_SIZE	(16)
+
+#define NAL_TYPE(value)				((value) & 0x1F)
+#define HEADER_BUFFER_SIZE			(32 * 1024)
+#define SYNC_CODE				(0x498342)
+
+extern int vp9_need_prefix;
+bool need_trigger;
+int dump_cnt = 0;
+
+/**
+ * struct vp9_fb - vp9 decode frame buffer information
+ * @vdec_fb_va  : virtual address of struct vdec_fb
+ * @y_fb_dma    : dma address of Y frame buffer (luma)
+ * @c_fb_dma    : dma address of C frame buffer (chroma)
+ * @poc         : picture order count of frame buffer
+ * @reserved    : for 8 bytes alignment
+ */
+struct vp9_fb {
+	uint64_t vdec_fb_va;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	int32_t poc;
+	uint32_t reserved;
+};
+
+/**
+ * struct vdec_vp9_dec_info - decode information
+ * @dpb_sz		: decoding picture buffer size
+ * @resolution_changed  : resoltion change happen
+ * @reserved		: for 8 bytes alignment
+ * @bs_dma		: Input bit-stream buffer dma address
+ * @y_fb_dma		: Y frame buffer dma address
+ * @c_fb_dma		: C frame buffer dma address
+ * @vdec_fb_va		: VDEC frame buffer struct virtual address
+ */
+struct vdec_vp9_dec_info {
+	uint32_t dpb_sz;
+	uint32_t resolution_changed;
+	uint32_t reserved;
+	uint64_t bs_dma;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	uint64_t vdec_fb_va;
+};
+
+/**
+ * struct vdec_vp9_vsi - shared memory for decode information exchange
+ *                        between VPU and Host.
+ *                        The memory is allocated by VPU then mapping to Host
+ *                        in vpu_dec_init() and freed in vpu_dec_deinit()
+ *                        by VPU.
+ *                        AP-W/R : AP is writer/reader on this item
+ *                        VPU-W/R: VPU is write/reader on this item
+ * @hdr_buf      : Header parsing buffer (AP-W, VPU-R)
+ * @list_free    : free frame buffer ring list (AP-W/R, VPU-W)
+ * @list_disp    : display frame buffer ring list (AP-R, VPU-W)
+ * @dec          : decode information (AP-R, VPU-W)
+ * @pic          : picture information (AP-R, VPU-W)
+ * @crop         : crop information (AP-R, VPU-W)
+ */
+struct vdec_vp9_vsi {
+	char *header_buf;
+	int sps_size;
+	int pps_size;
+	int sei_size;
+	int head_offset;
+	struct vdec_vp9_dec_info dec;
+	struct vdec_pic_info pic;
+	struct vdec_pic_info cur_pic;
+	struct v4l2_rect crop;
+	bool is_combine;
+	int nalu_pos;
+	struct vp9_param_sets ps;
+};
+
+/**
+ * struct vdec_vp9_inst - vp9 decoder instance
+ * @num_nalu : how many nalus be decoded
+ * @ctx      : point to aml_vcodec_ctx
+ * @vsi      : VPU shared information
+ */
+struct vdec_vp9_inst {
+	unsigned int num_nalu;
+	struct aml_vcodec_ctx *ctx;
+	struct aml_vdec_adapt vdec;
+	struct vdec_vp9_vsi *vsi;
+	struct aml_dec_params parms;
+	struct completion comp;
+	struct vdec_comp_buf_info comp_info;
+};
+
+static int vdec_write_nalu(struct vdec_vp9_inst *inst,
+	u8 *buf, u32 size, u64 ts, ulong meta_ptr);
+
+static void get_pic_info(struct vdec_vp9_inst *inst,
+			 struct vdec_pic_info *pic)
+{
+	*pic = inst->vsi->pic;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"pic(%d, %d), buf(%d, %d)\n",
+		 pic->visible_width, pic->visible_height,
+		 pic->coded_width, pic->coded_height);
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"Y(%d, %d), C(%d, %d)\n",
+		pic->y_bs_sz, pic->y_len_sz,
+		pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_crop_info(struct vdec_vp9_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = inst->vsi->crop.left;
+	cr->top = inst->vsi->crop.top;
+	cr->width = inst->vsi->crop.width;
+	cr->height = inst->vsi->crop.height;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"l=%d, t=%d, w=%d, h=%d\n",
+		 cr->left, cr->top, cr->width, cr->height);
+}
+
+static void get_dpb_size(struct vdec_vp9_inst *inst, unsigned int *dpb_sz)
+{
+	*dpb_sz = inst->vsi->dec.dpb_sz;
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, "sz=%d\n", *dpb_sz);
+}
+
+static u32 vdec_config_default_parms(u8 *parm)
+{
+	u8 *pbuf = parm;
+
+	pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+	pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
+	pbuf += sprintf(pbuf, "vp9_double_write_mode:1;");
+	pbuf += sprintf(pbuf, "vp9_buf_width:1920;");
+	pbuf += sprintf(pbuf, "vp9_buf_height:1088;");
+	pbuf += sprintf(pbuf, "vp9_max_pic_w:4096;");
+	pbuf += sprintf(pbuf, "vp9_max_pic_h:2304;");
+	pbuf += sprintf(pbuf, "save_buffer_mode:0;");
+	pbuf += sprintf(pbuf, "no_head:0;");
+	pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
+	pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;");
+
+	return parm - pbuf;
+}
+
+static void vdec_parser_parms(struct vdec_vp9_inst *inst)
+{
+	struct aml_vcodec_ctx *ctx = inst->ctx;
+
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+		"%s:parms_status = 0x%x, present_flag = %d\n",
+		__func__, ctx->config.parm.dec.parms_status,
+		ctx->config.parm.dec.hdr.color_parms.present_flag);
+	if (ctx->config.parm.dec.parms_status &
+		V4L2_CONFIG_PARM_DECODE_CFGINFO) {
+		u8 *pbuf = ctx->config.buf;
+
+		pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+		pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
+			ctx->config.parm.dec.cfg.ref_buf_margin);
+		pbuf += sprintf(pbuf, "vp9_double_write_mode:%d;",
+			ctx->config.parm.dec.cfg.double_write_mode);
+		pbuf += sprintf(pbuf, "vp9_buf_width:%d;",
+			ctx->config.parm.dec.cfg.init_width);
+		pbuf += sprintf(pbuf, "vp9_buf_height:%d;",
+			ctx->config.parm.dec.cfg.init_height);
+		pbuf += sprintf(pbuf, "save_buffer_mode:0;");
+		pbuf += sprintf(pbuf, "no_head:0;");
+		pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
+			ctx->config.parm.dec.cfg.canvas_mem_mode);
+		pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;",
+			ctx->config.parm.dec.cfg.canvas_mem_endian);
+		pbuf += sprintf(pbuf, "parm_v4l_low_latency_mode:%d;",
+			ctx->config.parm.dec.cfg.low_latency_mode);
+		pbuf += sprintf(pbuf, "parm_v4l_duration:%d;",
+			ctx->config.parm.dec.cfg.duration);
+		ctx->config.length = pbuf - ctx->config.buf;
+	} else {
+		ctx->config.parm.dec.cfg.double_write_mode = 1;
+		ctx->config.parm.dec.cfg.ref_buf_margin = 7;
+		ctx->config.length = vdec_config_default_parms(ctx->config.buf);
+	}
+
+	if ((ctx->config.parm.dec.parms_status &
+		V4L2_CONFIG_PARM_DECODE_HDRINFO) &&
+		ctx->config.parm.dec.hdr.color_parms.present_flag) {
+		u8 *pbuf = ctx->config.buf + ctx->config.length;
+
+		pbuf += sprintf(pbuf, "HDRStaticInfo:%d;", 1);
+		pbuf += sprintf(pbuf, "signal_type:%d;",
+			ctx->config.parm.dec.hdr.signal_type);
+		pbuf += sprintf(pbuf, "mG.x:%d;",
+			ctx->config.parm.dec.hdr.color_parms.primaries[0][0]);
+		pbuf += sprintf(pbuf, "mG.y:%d;",
+			ctx->config.parm.dec.hdr.color_parms.primaries[0][1]);
+		pbuf += sprintf(pbuf, "mB.x:%d;",
+			ctx->config.parm.dec.hdr.color_parms.primaries[1][0]);
+		pbuf += sprintf(pbuf, "mB.y:%d;",
+			ctx->config.parm.dec.hdr.color_parms.primaries[1][1]);
+		pbuf += sprintf(pbuf, "mR.x:%d;",
+			ctx->config.parm.dec.hdr.color_parms.primaries[2][0]);
+		pbuf += sprintf(pbuf, "mR.y:%d;",
+			ctx->config.parm.dec.hdr.color_parms.primaries[2][1]);
+		pbuf += sprintf(pbuf, "mW.x:%d;",
+			ctx->config.parm.dec.hdr.color_parms.white_point[0]);
+		pbuf += sprintf(pbuf, "mW.y:%d;",
+			ctx->config.parm.dec.hdr.color_parms.white_point[1]);
+		pbuf += sprintf(pbuf, "mMaxDL:%d;",
+			ctx->config.parm.dec.hdr.color_parms.luminance[0] * 10000);
+		pbuf += sprintf(pbuf, "mMinDL:%d;",
+			ctx->config.parm.dec.hdr.color_parms.luminance[1]);
+		pbuf += sprintf(pbuf, "mMaxCLL:%d;",
+			ctx->config.parm.dec.hdr.color_parms.content_light_level.max_content);
+		pbuf += sprintf(pbuf, "mMaxFALL:%d;",
+			ctx->config.parm.dec.hdr.color_parms.content_light_level.max_pic_average);
+		ctx->config.length	= pbuf - ctx->config.buf;
+		inst->parms.hdr		= ctx->config.parm.dec.hdr;
+		inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_HDRINFO;
+	}
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
+		"config.buf = %s\n", ctx->config.buf);
+
+	inst->vdec.config	= ctx->config;
+	inst->parms.cfg		= ctx->config.parm.dec.cfg;
+	inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO;
+}
+
+static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_vp9_inst *inst = NULL;
+	int ret = -1;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->vdec.frm_name	= "VP9";
+	inst->vdec.video_type	= VFORMAT_VP9;
+	inst->vdec.filp		= ctx->dev->filp;
+	inst->vdec.ctx		= ctx;
+	inst->ctx		= ctx;
+
+	vdec_parser_parms(inst);
+
+	/* set play mode.*/
+	if (ctx->is_drm_mode)
+		inst->vdec.port.flag |= PORT_FLAG_DRM;
+
+	/* to eable vp9 hw.*/
+	inst->vdec.port.type	= PORT_TYPE_HEVC;
+
+	/* probe info from the stream */
+	inst->vsi = kzalloc(sizeof(struct vdec_vp9_vsi), GFP_KERNEL);
+	if (!inst->vsi) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* alloc the header buffer to be used cache sps or spp etc.*/
+	inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
+	if (!inst->vsi->header_buf) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	init_completion(&inst->comp);
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"vp9 Instance >> %lx\n", (ulong) inst);
+
+	ctx->ada_ctx	= &inst->vdec;
+	*h_vdec		= (unsigned long)inst;
+
+	/* init decoder. */
+	ret = video_decoder_init(&inst->vdec);
+	if (ret) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"vdec_vp9 init err=%d\n", ret);
+		goto err;
+	}
+
+	return 0;
+err:
+	if (inst && inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+	if (inst && inst->vsi)
+		kfree(inst->vsi);
+	if (inst)
+		kfree(inst);
+	*h_vdec = 0;
+
+	return ret;
+}
+
+#if 0
+static int refer_buffer_num(int level_idc, int poc_cnt,
+	int mb_width, int mb_height)
+{
+	return 20;
+}
+#endif
+
+static int vdec_get_dw_mode(struct vdec_vp9_inst *inst, int dw_mode)
+{
+	u32 valid_dw_mode = inst->parms.cfg.double_write_mode;
+	int w = inst->vsi->pic.coded_width;
+	int h = inst->vsi->pic.coded_height;
+	u32 dw = 0x1; /*1:1*/
+
+	switch (valid_dw_mode) {
+	case 0x100:
+		if (w > 1920 && h > 1088)
+			dw = 0x4; /*1:2*/
+		break;
+	case 0x200:
+		if (w > 1920 && h > 1088)
+			dw = 0x2; /*1:4*/
+		break;
+	case 0x300:
+		if (w > 1280 && h > 720)
+			dw = 0x4; /*1:2*/
+		break;
+	default:
+		dw = valid_dw_mode;
+		break;
+	}
+
+	return dw;
+}
+
+static int vdec_pic_scale(struct vdec_vp9_inst *inst, int length, int dw_mode)
+{
+	int ret = 64;
+
+	switch (vdec_get_dw_mode(inst, dw_mode)) {
+	case 0x0: /* only afbc, output afbc */
+		ret = 64;
+		break;
+	case 0x1: /* afbc and (w x h), output YUV420 */
+		ret = length;
+		break;
+	case 0x2: /* afbc and (w/4 x h/4), output YUV420 */
+	case 0x3: /* afbc and (w/4 x h/4), output afbc and YUV420 */
+		ret = length >> 2;
+		break;
+	case 0x4: /* afbc and (w/2 x h/2), output YUV420 */
+		ret = length >> 1;
+		break;
+	case 0x10: /* (w x h), output YUV420-8bit) */
+	default:
+		ret = length;
+		break;
+	}
+
+	return ret;
+}
+
+static void fill_vdec_params(struct vdec_vp9_inst *inst,
+	struct VP9Context *vp9_ctx)
+{
+	struct vdec_pic_info *pic = &inst->vsi->pic;
+	struct vdec_vp9_dec_info *dec = &inst->vsi->dec;
+	struct v4l2_rect *rect = &inst->vsi->crop;
+	int dw = inst->parms.cfg.double_write_mode;
+	int margin = inst->parms.cfg.ref_buf_margin;
+
+	/* fill visible area size that be used for EGL. */
+	pic->visible_width	= vdec_pic_scale(inst, vp9_ctx->render_width, dw);
+	pic->visible_height	= vdec_pic_scale(inst, vp9_ctx->render_height, dw);
+
+	/* calc visible ares. */
+	rect->left		= 0;
+	rect->top		= 0;
+	rect->width		= pic->visible_width;
+	rect->height		= pic->visible_height;
+
+	/* config canvas size that be used for decoder. */
+	pic->coded_width	= vdec_pic_scale(inst, ALIGN(vp9_ctx->width, 32), dw);
+	pic->coded_height	= vdec_pic_scale(inst, ALIGN(vp9_ctx->height, 32), dw);
+
+	pic->y_len_sz		= pic->coded_width * pic->coded_height;
+	pic->c_len_sz		= pic->y_len_sz >> 1;
+
+	/* calc DPB size */
+	dec->dpb_sz = 5 + margin;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
+
+	inst->parms.ps.visible_width	= pic->visible_width;
+	inst->parms.ps.visible_height	= pic->visible_height;
+	inst->parms.ps.coded_width	= pic->coded_width;
+	inst->parms.ps.coded_height	= pic->coded_height;
+	inst->parms.ps.dpb_size		= dec->dpb_sz;
+	inst->parms.parms_status	|= V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
+		"The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
+		dw, pic->coded_width, pic->coded_height,
+		pic->visible_width, pic->visible_height,
+		dec->dpb_sz - margin, margin);
+}
+
+static int parse_stream_ucode(struct vdec_vp9_inst *inst,
+			      u8 *buf, u32 size, u64 timestamp, ulong meta_ptr)
+{
+	int ret = 0;
+
+	ret = vdec_write_nalu(inst, buf, size, timestamp, meta_ptr);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write frame data failed. err: %d\n", ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_ucode_dma(struct vdec_vp9_inst *inst,
+	ulong buf, u32 size, u64 timestamp, u32 handle)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+
+	ret = vdec_vframe_write_with_dma(vdec, buf, size, timestamp, handle,
+		vdec_vframe_input_free, inst->ctx);
+	if (ret < 0) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write frame data failed. err: %d\n", ret);
+		return ret;
+	}
+
+	/* wait ucode parse ending. */
+	wait_for_completion_timeout(&inst->comp,
+		msecs_to_jiffies(1000));
+
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
+}
+
+static int parse_stream_cpu(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
+{
+	int ret = 0;
+	struct vp9_param_sets *ps = NULL;
+
+	ps = vzalloc(sizeof(struct vp9_param_sets));
+	if (ps == NULL)
+		return -ENOMEM;
+
+	ret = vp9_decode_extradata_ps(buf, size, ps);
+	if (ret) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"parse extra data failed. err: %d\n", ret);
+		goto out;
+	}
+
+	if (ps->head_parsed)
+		fill_vdec_params(inst, &ps->ctx);
+
+	ret = ps->head_parsed ? 0 : -1;
+out:
+	vfree(ps);
+
+	return ret;
+}
+
+static int vdec_vp9_probe(unsigned long h_vdec,
+	struct aml_vcodec_mem *bs, void *out)
+{
+	struct vdec_vp9_inst *inst =
+		(struct vdec_vp9_inst *)h_vdec;
+	u8 *buf = (u8 *)bs->vaddr;
+	u32 size = bs->size;
+	int ret = 0;
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if ((s->magic != AML_VIDEO_MAGIC) &&
+				(s->type != V4L_STREAM_TYPE_MATEDATA))
+				return -1;
+
+			if (inst->ctx->param_sets_from_ucode) {
+				ret = parse_stream_ucode(inst, s->data,
+					s->len, bs->timestamp, 0);
+			} else {
+				ret = parse_stream_cpu(inst, s->data, s->len);
+			}
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = parse_stream_ucode_dma(inst, bs->addr, size,
+				bs->timestamp, BUFF_IDX(bs, bs->index));
+		}
+	} else {
+		if (inst->ctx->param_sets_from_ucode) {
+			ret = parse_stream_ucode(inst, buf, size, bs->timestamp, bs->meta_ptr);
+		} else {
+			ret = parse_stream_cpu(inst, buf, size);
+		}
+	}
+
+	inst->vsi->cur_pic = inst->vsi->pic;
+
+	return ret;
+}
+
+static void vdec_vp9_deinit(unsigned long h_vdec)
+{
+	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+	struct aml_vcodec_ctx *ctx = inst->ctx;
+
+	video_decoder_release(&inst->vdec);
+
+	if (inst->vsi && inst->vsi->header_buf)
+		vfree(inst->vsi->header_buf);
+
+	if (inst->vsi)
+		kfree(inst->vsi);
+
+	kfree(inst);
+
+	ctx->drv_handle = 0;
+
+	need_trigger = false;
+	dump_cnt = 0;
+}
+
+static void add_prefix_data(struct vp9_superframe_split *s,
+	u8 **out, u32 *out_size)
+{
+	int i;
+	u8 *p = NULL;
+	u32 length;
+
+	length = s->size + s->nb_frames * PREFIX_SIZE;
+	if (!length)
+		return;
+	p = vzalloc(length);
+	if (!p) {
+		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+			"alloc size %d failed.\n" ,length);
+		return;
+	}
+
+	memcpy(p, s->data, s->size);
+	p += s->size;
+
+	for (i = s->nb_frames; i > 0; i--) {
+		u32 frame_size = s->sizes[i - 1];
+		u8 *prefix = NULL;
+
+		p -= frame_size;
+		memmove(p + PREFIX_SIZE * i, p, frame_size);
+		prefix = p + PREFIX_SIZE * (i - 1);
+
+		/*add amlogic frame headers.*/
+		frame_size += 16;
+		prefix[0]  = (frame_size >> 24) & 0xff;
+		prefix[1]  = (frame_size >> 16) & 0xff;
+		prefix[2]  = (frame_size >> 8 ) & 0xff;
+		prefix[3]  = (frame_size >> 0 ) & 0xff;
+		prefix[4]  = ((frame_size >> 24) & 0xff) ^ 0xff;
+		prefix[5]  = ((frame_size >> 16) & 0xff) ^ 0xff;
+		prefix[6]  = ((frame_size >> 8 ) & 0xff) ^ 0xff;
+		prefix[7]  = ((frame_size >> 0 ) & 0xff) ^ 0xff;
+		prefix[8]  = 0;
+		prefix[9]  = 0;
+		prefix[10] = 0;
+		prefix[11] = 1;
+		prefix[12] = 'A';
+		prefix[13] = 'M';
+		prefix[14] = 'L';
+		prefix[15] = 'V';
+		frame_size -= 16;
+	}
+
+	*out = p;
+	*out_size = length;
+}
+
+#ifndef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+static int vp9_superframe_split_filter(struct vp9_superframe_split *s)
+{
+	int i, j, ret, marker;
+	bool is_superframe = false;
+	int *prefix = (int *)s->data;
+
+	if (!s->data)
+		return -1;
+
+#define AML_PREFIX ('V' << 24 | 'L' << 16 | 'M' << 8 | 'A')
+	if (prefix[3] == AML_PREFIX) {
+		s->prefix_size = 16;
+		/*pr_info("the frame data has beed added header\n");*/
+	}
+
+	marker = s->data[s->data_size - 1];
+	if ((marker & 0xe0) == 0xc0) {
+		int length_size = 1 + ((marker >> 3) & 0x3);
+		int   nb_frames = 1 + (marker & 0x7);
+		int    idx_size = 2 + nb_frames * length_size;
+
+		if (s->data_size >= idx_size &&
+			s->data[s->data_size - idx_size] == marker) {
+			s64 total_size = 0;
+			int idx = s->data_size + 1 - idx_size;
+
+			for (i = 0; i < nb_frames; i++) {
+				int frame_size = 0;
+				for (j = 0; j < length_size; j++)
+					frame_size |= s->data[idx++] << (j * 8);
+
+				total_size += frame_size;
+				if (frame_size < 0 ||
+					total_size > s->data_size - idx_size) {
+					v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "Invalid frame size in a sframe: %d\n",
+						frame_size);
+					ret = -EINVAL;
+					goto fail;
+				}
+				s->sizes[i] = frame_size;
+			}
+
+			s->nb_frames	     = nb_frames;
+			s->size 	     = total_size;
+			s->next_frame	     = 0;
+			s->next_frame_offset = 0;
+			is_superframe	     = true;
+		}
+	}else {
+		s->nb_frames = 1;
+		s->sizes[0]  = s->data_size;
+		s->size      = s->data_size;
+	}
+
+	/*pr_info("sframe: %d, frames: %d, IN: %x, OUT: %x\n",
+		is_superframe, s->nb_frames,
+		s->data_size, s->size);*/
+
+	/* parse uncompressed header. */
+	if (is_superframe) {
+		/* bitstream profile. */
+		/* frame type. (intra or inter) */
+		/* colorspace descriptor */
+		/* ... */
+
+		v4l_dbg(0, V4L_DEBUG_CODEC_PARSER, "the frame is a superframe.\n");
+	}
+
+	/*pr_err("in: %x, %d, out: %x, sizes %d,%d,%d,%d,%d,%d,%d,%d\n",
+		s->data_size,
+		s->nb_frames,
+		s->size,
+		s->sizes[0],
+		s->sizes[1],
+		s->sizes[2],
+		s->sizes[3],
+		s->sizes[4],
+		s->sizes[5],
+		s->sizes[6],
+		s->sizes[7]);*/
+
+	return 0;
+fail:
+	return ret;
+}
+#endif
+
+static void trigger_decoder(struct aml_vdec_adapt *vdec)
+{
+	int i, ret;
+	u32 frame_size = 0;
+	u8 *p = vp9_trigger_header;
+
+	for (i = 0; i < ARRAY_SIZE(vp9_trigger_framesize); i++) {
+		frame_size = vp9_trigger_framesize[i];
+		ret = vdec_vframe_write(vdec, p,
+			frame_size, 0, 0);
+		v4l_dbg(vdec->ctx, V4L_DEBUG_CODEC_ERROR,
+			"write trigger frame %d\n", ret);
+		p += frame_size;
+	}
+}
+
+static int vdec_write_nalu(struct vdec_vp9_inst *inst,
+	u8 *buf, u32 size, u64 ts, ulong meta_ptr)
+{
+	int ret = 0;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+	struct vp9_superframe_split s;
+	u8 *data = NULL;
+	u32 length = 0;
+	bool need_prefix = vp9_need_prefix;
+
+	memset(&s, 0, sizeof(s));
+
+	/*trigger.*/
+	if (0 && !need_trigger) {
+		trigger_decoder(vdec);
+		need_trigger = true;
+	}
+
+	if (need_prefix) {
+		/*parse superframe.*/
+		s.data = buf;
+		s.data_size = size;
+		ret = vp9_superframe_split_filter(&s);
+		if (ret) {
+			v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+				"parse frames failed.\n");
+			return ret;
+		}
+
+		/*add headers.*/
+		add_prefix_data(&s, &data, &length);
+		ret = vdec_vframe_write(vdec, data, length, ts, 0);
+		vfree(data);
+	} else {
+		ret = vdec_vframe_write(vdec, buf, size, ts, meta_ptr);
+	}
+
+	return ret;
+}
+
+static bool monitor_res_change(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
+{
+	int ret = -1;
+	u8 *p = buf;
+	int len = size;
+	u32 synccode = vp9_need_prefix ?
+		((p[1] << 16) | (p[2] << 8) | p[3]) :
+		((p[17] << 16) | (p[18] << 8) | p[19]);
+
+	if (synccode == SYNC_CODE) {
+		ret = parse_stream_cpu(inst, p, len);
+		if (!ret && (inst->vsi->cur_pic.coded_width !=
+			inst->vsi->pic.coded_width ||
+			inst->vsi->cur_pic.coded_height !=
+			inst->vsi->pic.coded_height)) {
+			inst->vsi->cur_pic = inst->vsi->pic;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static int vdec_vp9_decode(unsigned long h_vdec,
+			   struct aml_vcodec_mem *bs, bool *res_chg)
+{
+	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+	struct aml_vdec_adapt *vdec = &inst->vdec;
+	u8 *buf = (u8 *) bs->vaddr;
+	u32 size = bs->size;
+	int ret = -1;
+
+	if (bs == NULL)
+		return -1;
+
+	if (vdec_input_full(vdec)) {
+		return -EAGAIN;
+	}
+
+	if (inst->ctx->is_drm_mode) {
+		if (bs->model == VB2_MEMORY_MMAP) {
+			struct aml_video_stream *s =
+				(struct aml_video_stream *) buf;
+
+			if (s->magic != AML_VIDEO_MAGIC)
+				return -1;
+
+			if (!inst->ctx->param_sets_from_ucode &&
+				(s->type == V4L_STREAM_TYPE_MATEDATA)) {
+				if ((*res_chg = monitor_res_change(inst,
+					s->data, s->len)))
+				return 0;
+			}
+
+			ret = vdec_vframe_write(vdec,
+				s->data,
+				s->len,
+				bs->timestamp,
+				0);
+		} else if (bs->model == VB2_MEMORY_DMABUF ||
+			bs->model == VB2_MEMORY_USERPTR) {
+			ret = vdec_vframe_write_with_dma(vdec,
+				bs->addr, size, bs->timestamp,
+				BUFF_IDX(bs, bs->index),
+				vdec_vframe_input_free, inst->ctx);
+		}
+	} else {
+		/*checked whether the resolution changes.*/
+		if ((!inst->ctx->param_sets_from_ucode) &&
+			(*res_chg = monitor_res_change(inst, buf, size)))
+			return 0;
+		ret = vdec_write_nalu(inst, buf, size, bs->timestamp, bs->meta_ptr);
+	}
+
+	return ret;
+}
+
+ static void get_param_config_info(struct vdec_vp9_inst *inst,
+	struct aml_dec_params *parms)
+ {
+	 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO)
+		 parms->cfg = inst->parms.cfg;
+	 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO)
+		 parms->ps = inst->parms.ps;
+	 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO)
+		 parms->hdr = inst->parms.hdr;
+	 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO)
+		 parms->cnt = inst->parms.cnt;
+
+	 parms->parms_status |= inst->parms.parms_status;
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+		"parms status: %u\n", parms->parms_status);
+ }
+
+static void get_param_comp_buf_info(struct vdec_vp9_inst *inst,
+		struct vdec_comp_buf_info *params)
+{
+	memcpy(params, &inst->comp_info, sizeof(*params));
+}
+
+static int vdec_vp9_get_param(unsigned long h_vdec,
+			       enum vdec_get_param_type type, void *out)
+{
+	int ret = 0;
+	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the vp9 inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+
+	case GET_PARAM_DPB_SIZE:
+		get_dpb_size(inst, out);
+		break;
+
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+
+	case GET_PARAM_CONFIG_INFO:
+		get_param_config_info(inst, out);
+		break;
+
+	case GET_PARAM_DW_MODE:
+	{
+		u32 *mode = out;
+		u32 m = inst->ctx->config.parm.dec.cfg.double_write_mode;
+		if (m <= 16)
+			*mode = inst->ctx->config.parm.dec.cfg.double_write_mode;
+		else
+			*mode = vdec_get_dw_mode(inst, 0);
+		break;
+	}
+	case GET_PARAM_COMP_BUF_INFO:
+		get_param_comp_buf_info(inst, out);
+		break;
+
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"invalid get parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static void set_param_write_sync(struct vdec_vp9_inst *inst)
+{
+	complete(&inst->comp);
+}
+
+static void set_param_ps_info(struct vdec_vp9_inst *inst,
+	struct aml_vdec_ps_infos *ps)
+{
+	struct vdec_pic_info *pic = &inst->vsi->pic;
+	struct vdec_vp9_dec_info *dec = &inst->vsi->dec;
+	struct v4l2_rect *rect = &inst->vsi->crop;
+	int dw = inst->parms.cfg.double_write_mode;
+
+	/* fill visible area size that be used for EGL. */
+	pic->visible_width	= ps->visible_width;
+	pic->visible_height	= ps->visible_height;
+
+	/* calc visible ares. */
+	rect->left		= 0;
+	rect->top		= 0;
+	rect->width		= pic->visible_width;
+	rect->height		= pic->visible_height;
+
+	/* config canvas size that be used for decoder. */
+	pic->coded_width	= ps->coded_width;
+	pic->coded_height	= ps->coded_height;
+
+	pic->y_len_sz		= ALIGN(vdec_pic_scale(inst, pic->coded_width, dw), 64) *
+				  ALIGN(vdec_pic_scale(inst, pic->coded_height, dw), 64);
+	pic->c_len_sz		= pic->y_len_sz >> 1;
+
+	/* calc DPB size */
+	pic->dpb_frames		= ps->dpb_frames;
+	pic->dpb_margin		= ps->dpb_margin;
+	pic->vpp_margin		= ps->dpb_margin;
+	dec->dpb_sz		= ps->dpb_size;
+	pic->field		= ps->field;
+
+	inst->parms.ps 	= *ps;
+	inst->parms.parms_status |=
+		V4L2_CONFIG_PARM_DECODE_PSINFO;
+
+	/*wake up*/
+	complete(&inst->comp);
+
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"Parse from ucode, visible(%d x %d), coded(%d x %d)\n",
+		pic->visible_width, pic->visible_height,
+		pic->coded_width, pic->coded_height);
+}
+
+static void set_param_comp_buf_info(struct vdec_vp9_inst *inst,
+		struct vdec_comp_buf_info *info)
+{
+	memcpy(&inst->comp_info, info, sizeof(*info));
+}
+
+static void set_param_hdr_info(struct vdec_vp9_inst *inst,
+	struct aml_vdec_hdr_infos *hdr)
+{
+	if ((inst->parms.parms_status &
+		V4L2_CONFIG_PARM_DECODE_HDRINFO)) {
+		inst->parms.hdr = *hdr;
+		inst->parms.parms_status |=
+			V4L2_CONFIG_PARM_DECODE_HDRINFO;
+		aml_vdec_dispatch_event(inst->ctx,
+			V4L2_EVENT_SRC_CH_HDRINFO);
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+			"VP9 set HDR infos\n");
+	}
+}
+
+static void set_param_post_event(struct vdec_vp9_inst *inst, u32 *event)
+{
+		aml_vdec_dispatch_event(inst->ctx, *event);
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+			"VP9 post event: %d\n", *event);
+}
+
+static void set_pic_info(struct vdec_vp9_inst *inst,
+	struct vdec_pic_info *pic)
+{
+	inst->vsi->pic = *pic;
+}
+
+static int vdec_vp9_set_param(unsigned long h_vdec,
+	enum vdec_set_param_type type, void *in)
+{
+	int ret = 0;
+	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+
+	if (!inst) {
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"the vp9 inst of dec is invalid.\n");
+		return -1;
+	}
+
+	switch (type) {
+	case SET_PARAM_WRITE_FRAME_SYNC:
+		set_param_write_sync(inst);
+		break;
+
+	case SET_PARAM_PS_INFO:
+		set_param_ps_info(inst, in);
+		break;
+
+	case SET_PARAM_COMP_BUF_INFO:
+		set_param_comp_buf_info(inst, in);
+		break;
+
+	case SET_PARAM_HDR_INFO:
+		set_param_hdr_info(inst, in);
+		break;
+
+	case SET_PARAM_POST_EVENT:
+		set_param_post_event(inst, in);
+		break;
+
+	case SET_PARAM_PIC_INFO:
+		set_pic_info(inst, in);
+		break;
+
+	default:
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+			"invalid set parameter type=%d\n", type);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static struct vdec_common_if vdec_vp9_if = {
+	.init		= vdec_vp9_init,
+	.probe		= vdec_vp9_probe,
+	.decode		= vdec_vp9_decode,
+	.get_param	= vdec_vp9_get_param,
+	.set_param	= vdec_vp9_set_param,
+	.deinit		= vdec_vp9_deinit,
+};
+
+struct vdec_common_if *get_vp9_dec_comm_if(void);
+
+struct vdec_common_if *get_vp9_dec_comm_if(void)
+{
+	return &vdec_vp9_if;
+}
+
diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_trigger.h b/drivers/amvdec_ports/decoder/vdec_vp9_trigger.h
new file mode 100644
index 0000000..0097690
--- /dev/null
+++ b/drivers/amvdec_ports/decoder/vdec_vp9_trigger.h
@@ -0,0 +1,860 @@
+/*
+ * drivers/amvdec_ports/decoder/vdec_vp9_trigger.h
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _VDEC_VP9_TRIG_
+#define _VDEC_VP9_TRIG_
+
+#define VP9_USE_TRIGGER_BIG_SIZE 1
+
+static u8 vp9_trigger_header[] = {
+#if VP9_USE_TRIGGER_BIG_SIZE
+                0x00, 0x00, 0x15, 0x29, 0xff, 0xff, 0xea, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x4c, 0x56,
+                0x82, 0x49, 0x83, 0x42, 0x00, 0x0c, 0x30, 0x0c, 0x34, 0x24, 0x38, 0x24, 0x1c, 0x19, 0x28, 0x00,
+                0x02, 0x90, 0x7c, 0x52, 0xff, 0x19, 0x05, 0xfa, 0xbe, 0xa9, 0xed, 0x30, 0x72, 0xdd, 0x1b, 0xad,
+                0xe8, 0xdd, 0xdc, 0xe2, 0x39, 0xb2, 0xb7, 0xd3, 0x37, 0xea, 0x4b, 0xe7, 0xd1, 0xfe, 0x57, 0xf0,
+                0x7a, 0x9f, 0x51, 0xa4, 0x5e, 0xb7, 0x18, 0x80, 0x77, 0x60, 0x00, 0x7f, 0xdb, 0x4d, 0xea, 0xbb,
+                0x00, 0x92, 0xed, 0xbc, 0xf6, 0x6e, 0x24, 0x2b, 0x3f, 0xd0, 0xb8, 0x09, 0x77, 0x11, 0x43, 0x65,
+                0x62, 0x94, 0xed, 0x33, 0xe1, 0x6e, 0xe8, 0x1a, 0xd0, 0x4e, 0xb1, 0x72, 0x34, 0x8e, 0x24, 0xe5,
+                0x1b, 0x26, 0x58, 0xdf, 0x19, 0x8d, 0x59, 0x82, 0x19, 0xae, 0xea, 0x12, 0x63, 0x6c, 0x89, 0x9c,
+                0x7f, 0xc2, 0x67, 0x40, 0xed, 0xf2, 0x8c, 0xaa, 0x9f, 0xe1, 0x1e, 0x27, 0x12, 0xdb, 0x01, 0x86,
+                0xcc, 0x47, 0xee, 0xaf, 0x5b, 0xaf, 0x44, 0x3d, 0x8e, 0x67, 0x2c, 0x57, 0xd9, 0xb9, 0xb5, 0x7a,
+                0x83, 0x28, 0xab, 0xf4, 0xe0, 0x86, 0xf0, 0x14, 0xd0, 0x5d, 0xa4, 0x73, 0x28, 0x04, 0x3e, 0x99,
+                0xa3, 0xd7, 0xb5, 0xc6, 0xf7, 0xb1, 0xd9, 0x11, 0x06, 0x34, 0x1b, 0x91, 0x6d, 0x31, 0xee, 0x26,
+                0x95, 0xde, 0x0e, 0x55, 0x8f, 0xf1, 0x59, 0xe5, 0xc8, 0xb7, 0x74, 0x8a, 0x56, 0x99, 0xe5, 0xf7,
+                0x04, 0x49, 0xa5, 0x66, 0xa2, 0x15, 0xaf, 0x3c, 0xe5, 0xce, 0x26, 0xb0, 0x66, 0x63, 0xae, 0x7b,
+                0xf1, 0x09, 0xd2, 0x62, 0xb5, 0xe1, 0x4f, 0x0c, 0x54, 0xad, 0xe5, 0x00, 0x86, 0x14, 0x4b, 0x06,
+                0x82, 0xad, 0x62, 0x95, 0x6d, 0x3a, 0x99, 0x67, 0x1d, 0x1b, 0x85, 0xf6, 0xe7, 0x69, 0xd8, 0x00,
+                0xde, 0x63, 0xb5, 0x35, 0xf1, 0x44, 0x42, 0x21, 0xd3, 0xf3, 0xc9, 0x07, 0x23, 0x67, 0xe5, 0xea,
+                0x5e, 0xd2, 0x63, 0x78, 0xb9, 0x7b, 0xeb, 0xd7, 0x2d, 0x4c, 0x5e, 0x44, 0x6a, 0x46, 0x68, 0xeb,
+                0x5d, 0x61, 0xaa, 0xc7, 0xce, 0xb5, 0xe3, 0x01, 0xc8, 0x24, 0xca, 0x72, 0xcc, 0xdf, 0x89, 0x34,
+                0xb6, 0xab, 0xfd, 0x7b, 0xb9, 0xbd, 0xef, 0x33, 0xb0, 0x2b, 0x1e, 0xd3, 0x20, 0xa4, 0xcd, 0x8a,
+                0x51, 0x2e, 0x9d, 0x2e, 0x5c, 0xc7, 0x52, 0xed, 0xb8, 0x29, 0x68, 0x5d, 0x63, 0xe1, 0x79, 0x98,
+                0x2d, 0xb1, 0xf4, 0xa0, 0x01, 0x30, 0x2d, 0x10, 0xec, 0xe4, 0x6c, 0xed, 0x55, 0xb1, 0xf9, 0x0f,
+                0xd4, 0xae, 0x0f, 0x75, 0x5d, 0x81, 0x76, 0xfe, 0x94, 0x44, 0x1c, 0xcc, 0x8c, 0x7e, 0x0f, 0x4c,
+                0xda, 0x88, 0x61, 0x6a, 0x17, 0x70, 0x14, 0xf5, 0x0d, 0x7c, 0xd1, 0xf8, 0x0f, 0x19, 0xa2, 0x05,
+                0xe3, 0x98, 0xdc, 0xe1, 0xb4, 0x6a, 0x74, 0xa0, 0x8f, 0x1b, 0xc8, 0x12, 0xb4, 0xde, 0x62, 0x88,
+                0xd4, 0x0d, 0xed, 0x0b, 0x76, 0xae, 0xe0, 0x92, 0xa2, 0x13, 0x70, 0x03, 0x08, 0x26, 0x8f, 0xed,
+                0xa7, 0x5c, 0x5a, 0x55, 0x6e, 0x92, 0x76, 0xd0, 0xc2, 0x9c, 0x24, 0x77, 0x78, 0x9b, 0x33, 0xe5,
+                0x88, 0xc6, 0x08, 0x8a, 0x28, 0x46, 0x9f, 0xb4, 0xd9, 0xd7, 0x86, 0x82, 0xe4, 0xba, 0x97, 0x3d,
+                0x36, 0xd5, 0x31, 0x61, 0x7f, 0x8e, 0xb9, 0xa1, 0xab, 0x68, 0xa6, 0x8c, 0xa8, 0x47, 0x8d, 0x5c,
+                0x97, 0xe9, 0xf0, 0x8f, 0xa4, 0xe8, 0x13, 0x2b, 0x9c, 0x4d, 0xff, 0x95, 0x8e, 0x98, 0x08, 0x75,
+                0xd4, 0xed, 0x5e, 0x86, 0xe5, 0x68, 0x4b, 0x01, 0x0b, 0xd2, 0x13, 0xb0, 0x94, 0xd1, 0x28, 0x22,
+                0x13, 0x6b, 0x95, 0x30, 0x79, 0xb6, 0xd9, 0x55, 0x2e, 0x3b, 0x36, 0x18, 0xef, 0x39, 0x16, 0x97,
+                0x1e, 0xc4, 0x03, 0xb4, 0x75, 0xbe, 0xfd, 0x04, 0x2e, 0xd5, 0xac, 0x95, 0xac, 0x70, 0x40, 0xb3,
+                0x1a, 0x61, 0x03, 0x9a, 0x9f, 0xbf, 0x93, 0x14, 0xcc, 0xc0, 0x28, 0xf8, 0x93, 0xa6, 0x7f, 0x07,
+                0x12, 0xe1, 0xc2, 0x86, 0xe3, 0x87, 0x0d, 0x4d, 0x20, 0x75, 0xf7, 0xa0, 0x14, 0x49, 0x6f, 0x52,
+                0xc6, 0x6e, 0x9d, 0xa8, 0x8e, 0x14, 0x3a, 0x9f, 0xa6, 0xac, 0xdc, 0x56, 0x9c, 0xdf, 0xf4, 0x75,
+                0x6a, 0x31, 0x94, 0x50, 0x9c, 0x43, 0xd5, 0x6b, 0x20, 0xe4, 0xbc, 0x20, 0xd0, 0x9a, 0x7f, 0x84,
+                0x6e, 0xd5, 0x7c, 0x2e, 0x93, 0xf8, 0x25, 0x50, 0x4f, 0xcb, 0x13, 0x74, 0x78, 0x08, 0x82, 0x0d,
+                0xd0, 0x39, 0xaf, 0x4c, 0x6e, 0x9e, 0x25, 0x37, 0xbf, 0x7d, 0xe3, 0x93, 0xbd, 0x91, 0xb9, 0x52,
+                0xac, 0x6d, 0xa6, 0xcd, 0x78, 0x50, 0x78, 0x3a, 0xc0, 0xc4, 0x13, 0xc0, 0x4e, 0xa5, 0x09, 0x09,
+                0x80, 0xd8, 0x08, 0xfc, 0x63, 0xd4, 0x28, 0x3d, 0xef, 0xfd, 0xf8, 0x30, 0x3e, 0x09, 0x3a, 0x56,
+                0xf8, 0x11, 0xa3, 0x67, 0xdd, 0x51, 0x15, 0xde, 0x20, 0x8d, 0xd8, 0x66, 0xac, 0x08, 0x70, 0x9c,
+                0x8e, 0xb2, 0xff, 0x26, 0x5a, 0x82, 0x14, 0x1d, 0xf5, 0xf3, 0x1c, 0xf9, 0x6a, 0x00, 0x25, 0x84,
+                0x94, 0xc9, 0x6f, 0x16, 0x75, 0xf6, 0xd2, 0x13, 0xa2, 0x70, 0xe0, 0x94, 0x4b, 0xe7, 0xe4, 0x6d,
+                0xf1, 0xd2, 0xa3, 0x94, 0x65, 0x25, 0x38, 0xb4, 0x31, 0x8b, 0xdf, 0x1c, 0xb6, 0x22, 0x2b, 0x4b,
+                0x03, 0xd2, 0x92, 0xcc, 0xa1, 0xcf, 0xb6, 0xf5, 0x28, 0x02, 0xb8, 0xe0, 0x44, 0x69, 0x34, 0xa8,
+                0xb3, 0xaa, 0xea, 0x48, 0x6e, 0xf0, 0x67, 0x39, 0x0e, 0xbd, 0xfd, 0x20, 0x9d, 0x8d, 0xc8, 0x0b,
+                0xa3, 0x7e, 0x66, 0x5b, 0xde, 0x21, 0xcc, 0x19, 0xae, 0xfd, 0x82, 0x73, 0x75, 0x09, 0x35, 0x2f,
+                0xbf, 0x91, 0xaa, 0xfa, 0x1d, 0xa4, 0x44, 0x7b, 0xf9, 0xac, 0xa9, 0x02, 0xb4, 0x39, 0xf8, 0x96,
+                0x90, 0x01, 0xff, 0x73, 0xe6, 0x52, 0xa1, 0x22, 0xfe, 0x04, 0xe3, 0x3e, 0x8a, 0x6d, 0xa0, 0x19,
+                0x4e, 0x11, 0x90, 0x9a, 0x05, 0xb2, 0x7a, 0x8d, 0x98, 0xfc, 0xda, 0x1c, 0x5f, 0x86, 0x94, 0x7f,
+                0x58, 0x20, 0xdf, 0xb6, 0xc0, 0x11, 0xd0, 0x8c, 0xc2, 0x11, 0x61, 0x75, 0x47, 0xbe, 0xec, 0x92,
+                0x82, 0xa3, 0xfe, 0xcd, 0x13, 0xdd, 0xe0, 0xe6, 0x5a, 0x0a, 0xc1, 0x9f, 0x31, 0x6d, 0x78, 0x31,
+                0xb6, 0x60, 0xbe, 0x0b, 0xd5, 0x81, 0x24, 0xe6, 0xc7, 0xe7, 0xe8, 0x08, 0x53, 0x27, 0xf3, 0x9a,
+                0xf2, 0x7e, 0xb7, 0xc8, 0xd9, 0x74, 0x72, 0x45, 0xe6, 0xf8, 0xba, 0xb9, 0x40, 0xff, 0xa4, 0xfb,
+                0x6a, 0xd0, 0x98, 0x4d, 0x4d, 0xcc, 0x4a, 0x38, 0xcb, 0xa0, 0xf0, 0x08, 0x7d, 0xd7, 0x70, 0xca,
+                0xdf, 0xe6, 0x16, 0xa2, 0xd1, 0x9d, 0xaf, 0xcc, 0xd7, 0x6c, 0x5a, 0xfd, 0xac, 0x42, 0xab, 0x16,
+                0x33, 0xc0, 0x2a, 0x68, 0xdd, 0x58, 0xb2, 0x41, 0xc5, 0x05, 0x61, 0x09, 0x60, 0xc8, 0x72, 0x29,
+                0xb8, 0x1c, 0x90, 0xc5, 0x02, 0x76, 0xdc, 0xcb, 0x45, 0x5c, 0x6c, 0x16, 0x37, 0xe6, 0x11, 0xce,
+                0x4e, 0x2e, 0xfa, 0xf4, 0x2c, 0x4f, 0x80, 0x64, 0x85, 0xf4, 0xbd, 0x03, 0x03, 0xd2, 0x86, 0x3e,
+                0x97, 0xbb, 0x07, 0x22, 0x82, 0x3f, 0xc8, 0xc5, 0xc4, 0x8d, 0x4f, 0x66, 0x18, 0xc7, 0x74, 0xe6,
+                0x19, 0x5e, 0xe7, 0xc8, 0xc8, 0xfd, 0xb1, 0xc5, 0x51, 0xc4, 0x25, 0xec, 0x2d, 0x0b, 0xed, 0xd0,
+                0x53, 0x5b, 0x5d, 0x80, 0x2c, 0x28, 0xd0, 0x19, 0xe2, 0x1d, 0xd8, 0x25, 0x1b, 0xb1, 0xb2, 0x99,
+                0x26, 0x93, 0xec, 0x08, 0x14, 0x16, 0x60, 0x28, 0xeb, 0x88, 0x0a, 0x84, 0x2d, 0xde, 0x41, 0xe3,
+                0x67, 0x0f, 0x74, 0x7c, 0xf9, 0xcc, 0x38, 0xea, 0xf8, 0xa7, 0x13, 0x53, 0xfb, 0xea, 0x8b, 0x50,
+                0x9c, 0x37, 0xff, 0x23, 0x4a, 0xdf, 0xc5, 0xe0, 0x04, 0x72, 0x8d, 0x2b, 0xca, 0x1c, 0x2c, 0x33,
+                0x7a, 0x3d, 0x25, 0xa3, 0x76, 0x15, 0xcb, 0x8d, 0xb8, 0x24, 0xa4, 0xa3, 0xf8, 0xc2, 0x69, 0x33,
+                0x27, 0x58, 0x51, 0xd9, 0x3c, 0x4c, 0x3b, 0x4a, 0xd7, 0x4e, 0x0b, 0xb5, 0xe2, 0x68, 0xeb, 0xa3,
+                0xf8, 0x93, 0xc1, 0x92, 0x58, 0xf4, 0xc2, 0xf6, 0x1e, 0x7d, 0xa3, 0x13, 0x20, 0x50, 0x5b, 0xb3,
+                0x3f, 0x07, 0xb3, 0x7e, 0xf5, 0x71, 0x1e, 0xf0, 0x23, 0x97, 0x95, 0x64, 0x70, 0xc2, 0xb9, 0x4a,
+                0x16, 0x9b, 0xbb, 0xaf, 0xd2, 0x1d, 0xc6, 0xae, 0x3f, 0xa2, 0x7e, 0x23, 0x55, 0xdc, 0x68, 0x64,
+                0x56, 0x33, 0xf8, 0xd4, 0x4e, 0xf4, 0x94, 0x0c, 0x09, 0xea, 0xae, 0xaf, 0xfb, 0x12, 0x31, 0x72,
+                0xda, 0xc1, 0x23, 0x72, 0xb7, 0x69, 0xe6, 0x2b, 0x36, 0x8b, 0xe5, 0xdc, 0xd5, 0xcd, 0x3e, 0xdd,
+                0x2c, 0x8e, 0x72, 0x23, 0xc8, 0x1f, 0x52, 0xea, 0x95, 0x21, 0xeb, 0xc6, 0x19, 0x9b, 0x6d, 0x80,
+                0x4e, 0x3a, 0x5b, 0x2f, 0x3b, 0x81, 0x91, 0x12, 0xed, 0xbc, 0x45, 0x4f, 0x93, 0x5c, 0xdf, 0xf0,
+                0xb7, 0x5a, 0xfd, 0x35, 0x54, 0xea, 0x68, 0x70, 0x4d, 0x4c, 0xb3, 0x56, 0x6c, 0x38, 0xbf, 0xaa,
+                0x29, 0xe6, 0x9c, 0x78, 0x7f, 0x5e, 0x7b, 0xa3, 0x04, 0xeb, 0x3d, 0x25, 0xce, 0x56, 0x5e, 0x62,
+                0x69, 0x87, 0xee, 0x7d, 0xf1, 0x1d, 0xb6, 0x1d, 0x7b, 0x4f, 0x47, 0x70, 0x5e, 0x06, 0x7b, 0x48,
+                0x02, 0x1d, 0x01, 0xfd, 0xbb, 0xa6, 0xa3, 0x6f, 0x90, 0xe3, 0xb2, 0x10, 0xa1, 0xc9, 0x40, 0x96,
+                0x6c, 0x4e, 0x35, 0x47, 0x71, 0x22, 0x80, 0x40, 0x52, 0xa8, 0x8f, 0x02, 0x62, 0x6a, 0xb5, 0x72,
+                0xa0, 0x65, 0x55, 0xdc, 0x69, 0x63, 0x2e, 0xae, 0x9f, 0xcd, 0xa7, 0x3a, 0x32, 0x4a, 0x76, 0x03,
+                0xc7, 0xf4, 0x7a, 0xde, 0x29, 0x1d, 0x7c, 0xad, 0x46, 0xe9, 0x90, 0x3b, 0xff, 0x4f, 0xa3, 0xe1,
+                0x40, 0xe1, 0xe7, 0x2a, 0xd6, 0x2d, 0x6b, 0x23, 0x42, 0x1b, 0xe8, 0xdf, 0x76, 0xe6, 0x11, 0x7d,
+                0xb2, 0xbe, 0xd1, 0x83, 0x81, 0x86, 0xb6, 0x5d, 0xc2, 0x29, 0xdf, 0xf4, 0xfe, 0x82, 0x14, 0x81,
+                0xed, 0xe3, 0x77, 0xbc, 0xe3, 0x42, 0xba, 0x14, 0x82, 0x85, 0x84, 0xca, 0x00, 0x37, 0x0e, 0xbc,
+                0x88, 0xa6, 0xa9, 0x63, 0x67, 0x3b, 0x9f, 0x42, 0xa2, 0x7a, 0xe4, 0x71, 0x11, 0xd0, 0x0a, 0xd8,
+                0x2e, 0xcb, 0x95, 0xe9, 0x8f, 0xb3, 0x85, 0x17, 0x78, 0x4e, 0xa7, 0xce, 0x0d, 0xc4, 0x56, 0xf0,
+                0x22, 0x0b, 0x65, 0xc0, 0xf4, 0x13, 0x55, 0x89, 0x00, 0x99, 0x7f, 0x19, 0xba, 0xa6, 0xe0, 0xa6,
+                0xa0, 0x60, 0x27, 0xd0, 0x24, 0xb7, 0x69, 0x33, 0x95, 0xc8, 0x9b, 0x18, 0x38, 0x62, 0xc8, 0xde,
+                0xef, 0xbe, 0x88, 0x5f, 0x21, 0x42, 0x0b, 0x59, 0x10, 0x0c, 0x9e, 0x9e, 0x66, 0x4a, 0xb7, 0xd6,
+                0x4f, 0x7a, 0xa8, 0xcd, 0x20, 0x6a, 0x70, 0x3a, 0x3e, 0xc9, 0x3c, 0x4d, 0x35, 0xfe, 0xaa, 0xad,
+                0x4f, 0x15, 0x77, 0x39, 0x29, 0x20, 0xac, 0x8a, 0x19, 0xdc, 0xd5, 0x61, 0x24, 0x59, 0x2a, 0x33,
+                0xa5, 0xdb, 0x05, 0xcf, 0x93, 0x70, 0x77, 0xb3, 0x0e, 0xdf, 0xeb, 0x58, 0x78, 0xd4, 0x6c, 0xc3,
+                0xe0, 0x7a, 0x09, 0xcf, 0xaa, 0x09, 0xaf, 0xbd, 0x2c, 0x01, 0x09, 0x11, 0x20, 0x00, 0x57, 0x8a,
+                0x32, 0xd7, 0xf9, 0x20, 0x19, 0xe8, 0x80, 0xf6, 0x96, 0xcf, 0xad, 0xf9, 0x2c, 0xe8, 0x4d, 0x6d,
+                0xe3, 0xd4, 0xfc, 0x2e, 0x8a, 0xce, 0x4a, 0x06, 0x51, 0x20, 0x23, 0x58, 0xe5, 0x8a, 0xcb, 0xa1,
+                0xcc, 0x12, 0x9f, 0x34, 0x17, 0x1e, 0x69, 0x66, 0x02, 0xeb, 0x2e, 0x71, 0x6b, 0x25, 0xde, 0x7c,
+                0x96, 0x17, 0xca, 0xac, 0x43, 0x41, 0x22, 0x3b, 0x87, 0xb9, 0x46, 0x85, 0x20, 0xac, 0x75, 0xbb,
+                0x0b, 0x48, 0x6c, 0x7f, 0xfe, 0x1b, 0xa5, 0x6c, 0x98, 0xfd, 0xb5, 0x8d, 0x93, 0x7a, 0xfb, 0x5b,
+                0x22, 0x26, 0x25, 0xda, 0x92, 0x96, 0x41, 0xe7, 0x75, 0xaf, 0xf0, 0x32, 0xea, 0xaa, 0xad, 0xc1,
+                0x5a, 0xb0, 0x78, 0xa7, 0x03, 0xdf, 0x57, 0xaf, 0xac, 0x69, 0xb3, 0xa3, 0xa9, 0x02, 0x9f, 0x31,
+                0xd5, 0xcf, 0x39, 0xc0, 0xc4, 0x83, 0xda, 0xc2, 0xa4, 0x5f, 0x9a, 0x31, 0x90, 0xc8, 0xd6, 0x29,
+                0x57, 0xf8, 0x31, 0xa6, 0x4a, 0x51, 0x80, 0x70, 0x12, 0x7f, 0x5d, 0xc0, 0x6f, 0x0e, 0x62, 0x99,
+                0xc0, 0x03, 0xdb, 0x16, 0x0a, 0x06, 0x79, 0x9a, 0xd2, 0x84, 0xc5, 0x4e, 0xb9, 0x05, 0x0b, 0xb5,
+                0x2a, 0xd2, 0x98, 0x8c, 0xf0, 0xd3, 0x43, 0xc6, 0xfd, 0x73, 0x3d, 0x96, 0x28, 0xe3, 0x18, 0xbc,
+                0x6c, 0x2f, 0xfd, 0x10, 0x9a, 0x90, 0x13, 0x8c, 0x17, 0xfe, 0xe1, 0xec, 0xb8, 0x44, 0xe7, 0xed,
+                0xcf, 0x01, 0xbb, 0x47, 0x08, 0xc1, 0x0c, 0x49, 0x22, 0xc4, 0x8b, 0x2a, 0xe8, 0x89, 0x6d, 0x01,
+                0x17, 0xdc, 0x58, 0x94, 0x1c, 0x52, 0xa7, 0x7f, 0x19, 0xda, 0x79, 0x92, 0x40, 0xdb, 0x28, 0x93,
+                0x1b, 0xdf, 0xdb, 0x4f, 0xc0, 0x10, 0x95, 0x6d, 0x81, 0x62, 0x8d, 0x0a, 0xbe, 0x3e, 0x3b, 0x53,
+                0x59, 0xca, 0x9f, 0x70, 0xc8, 0x32, 0xc3, 0x39, 0xbe, 0x44, 0x99, 0x96, 0x02, 0x46, 0xa9, 0xa9,
+                0xe4, 0xe2, 0xa6, 0x1f, 0xce, 0xf0, 0x3a, 0xdc, 0x42, 0xae, 0x6b, 0xa7, 0x95, 0xa1, 0x2a, 0x1f,
+                0xa2, 0xd5, 0x44, 0x2a, 0x85, 0xd4, 0x43, 0x0d, 0xf6, 0xa6, 0xbd, 0xcc, 0xb0, 0xab, 0xd0, 0xf6,
+                0x2f, 0xac, 0x2c, 0x61, 0xb0, 0x52, 0xba, 0xcf, 0x3f, 0xb5, 0xea, 0xdf, 0x9f, 0x46, 0xbf, 0x58,
+                0x1b, 0xf9, 0x16, 0xdb, 0x60, 0xce, 0xea, 0xf5, 0x72, 0xc2, 0x74, 0x32, 0xae, 0x7b, 0x41, 0x4d,
+                0xa2, 0x33, 0x88, 0xf8, 0x7b, 0x89, 0xe0, 0x18, 0xe4, 0x7d, 0x6c, 0xab, 0xce, 0x9e, 0xb4, 0xcd,
+                0xd2, 0x9a, 0xa5, 0x55, 0xfb, 0x83, 0x05, 0x9b, 0x06, 0x5a, 0xcf, 0xb7, 0x1a, 0xbe, 0xb9, 0x6a,
+                0xe1, 0x0a, 0x48, 0x98, 0x25, 0xcd, 0xb8, 0xa6, 0x7e, 0x95, 0x22, 0xb4, 0x55, 0x2c, 0x21, 0x1c,
+                0x07, 0xe7, 0x94, 0xe4, 0x78, 0x92, 0x09, 0x89, 0x05, 0xec, 0xf0, 0xce, 0x3f, 0x4f, 0x31, 0x30,
+                0xb5, 0x61, 0x38, 0xce, 0x55, 0x54, 0x96, 0xf6, 0x5e, 0x42, 0xa0, 0xd7, 0xd4, 0x41, 0xd6, 0x4f,
+                0x71, 0xc0, 0xc7, 0x45, 0x12, 0x89, 0x2c, 0x0d, 0x7e, 0xd2, 0xf9, 0x43, 0xaa, 0xa9, 0xeb, 0xc2,
+                0x46, 0xa4, 0x97, 0xd9, 0x16, 0xb6, 0xa4, 0xd2, 0xeb, 0xfe, 0xbd, 0xcd, 0x62, 0xab, 0xbc, 0xc2,
+                0xc4, 0x39, 0x07, 0x9f, 0x03, 0xed, 0x5c, 0x13, 0x5e, 0x92, 0x7c, 0x1a, 0xf3, 0xa6, 0x7f, 0x9a,
+                0x07, 0x5a, 0xff, 0xa6, 0xbf, 0x57, 0xf9, 0xeb, 0xd2, 0x56, 0x78, 0x3f, 0x74, 0xb3, 0x2d, 0xbe,
+                0xc9, 0x2d, 0xb2, 0x52, 0x5b, 0x7b, 0x79, 0x32, 0xb8, 0xfb, 0x5f, 0xfc, 0x3f, 0x62, 0x90, 0xe6,
+                0x22, 0xe8, 0x5e, 0xed, 0x41, 0x4c, 0xb0, 0xf9, 0xe4, 0x7d, 0x6e, 0x96, 0x97, 0x8c, 0xa7, 0xf4,
+                0xf1, 0xad, 0x3c, 0xa2, 0xdb, 0xa7, 0x8f, 0x81, 0xc0, 0xe5, 0xf6, 0x06, 0xd7, 0xae, 0xf5, 0x8b,
+                0x66, 0xf9, 0x84, 0xec, 0x3f, 0xe6, 0x76, 0xce, 0x91, 0x64, 0xce, 0x1d, 0x78, 0x8b, 0x3e, 0x85,
+                0xa5, 0x75, 0xd7, 0xcd, 0x6c, 0x57, 0x28, 0xd5, 0x6f, 0x62, 0x3d, 0x03, 0x47, 0x9e, 0xb5, 0xf8,
+                0x12, 0x83, 0xdb, 0xf7, 0x3b, 0xf2, 0x8d, 0x03, 0x1e, 0x70, 0x53, 0x9e, 0x62, 0x54, 0x9d, 0xf6,
+                0x94, 0x46, 0xdf, 0x68, 0xb8, 0xaa, 0x02, 0x19, 0xad, 0xfd, 0x3b, 0xf9, 0xdc, 0xb7, 0xe0, 0x78,
+                0xf8, 0x83, 0x18, 0x1a, 0x42, 0x8c, 0x5b, 0x5e, 0x64, 0x28, 0x0c, 0xe5, 0xa7, 0x80, 0x8b, 0x07,
+                0xdd, 0x93, 0x39, 0x76, 0x5b, 0x4a, 0x5c, 0x92, 0xab, 0xa6, 0xf6, 0xf4, 0x1e, 0x22, 0xc9, 0xb3,
+                0x94, 0x55, 0x81, 0x32, 0xc2, 0xe0, 0x19, 0x64, 0x14, 0xe0, 0xd5, 0x4a, 0xb8, 0x0c, 0x21, 0xd1,
+                0x7b, 0x38, 0x4b, 0x99, 0xff, 0x8e, 0xbb, 0x1d, 0xbb, 0xcc, 0xa4, 0xb7, 0x64, 0x30, 0xc7, 0x2b,
+                0x11, 0x8f, 0xfc, 0xba, 0xb6, 0xae, 0xf1, 0xbc, 0x24, 0x1b, 0x0e, 0x7e, 0x06, 0xd6, 0xbc, 0x27,
+                0x3b, 0x7e, 0x3b, 0x08, 0xcb, 0xbb, 0x23, 0x51, 0x0a, 0x6e, 0xce, 0xf6, 0x07, 0x0b, 0xd1, 0x1a,
+                0x04, 0xfc, 0x88, 0xb5, 0xf3, 0x01, 0x17, 0xfc, 0x99, 0xef, 0x2c, 0x20, 0x2f, 0x50, 0x9f, 0xd0,
+                0xe6, 0xec, 0x46, 0x9e, 0xf2, 0x25, 0xed, 0x99, 0x84, 0x26, 0x64, 0xce, 0xca, 0xb9, 0x2e, 0xf3,
+                0x45, 0xe7, 0x1e, 0x56, 0x87, 0x1a, 0x1f, 0x40, 0xd2, 0x5f, 0x9c, 0x46, 0x6a, 0x0b, 0xda, 0x6a,
+                0x57, 0xbd, 0x74, 0x76, 0x0b, 0xbf, 0x5b, 0x5b, 0xcd, 0x6c, 0x4a, 0x34, 0x73, 0x18, 0x57, 0xa3,
+                0x1b, 0x32, 0x44, 0xd9, 0x76, 0x53, 0x5b, 0xde, 0x92, 0x2d, 0xb4, 0xab, 0x90, 0xa3, 0x58, 0xc2,
+                0x1e, 0x7d, 0xdf, 0x9e, 0x98, 0xdf, 0x70, 0x66, 0x88, 0xa5, 0x1c, 0xc7, 0xb8, 0x65, 0x12, 0x62,
+                0x3e, 0x7f, 0x00, 0x14, 0xf9, 0x3f, 0x70, 0x90, 0xfa, 0x94, 0x4c, 0x6e, 0x32, 0x26, 0xc3, 0x97,
+                0x98, 0xe2, 0xa5, 0x33, 0xb9, 0xa8, 0xec, 0x9e, 0x41, 0x16, 0xf6, 0xa4, 0x8b, 0x14, 0x61, 0x35,
+                0xf2, 0xc5, 0xb4, 0xca, 0x90, 0xd1, 0xac, 0xef, 0x9a, 0x4c, 0x24, 0x19, 0x5d, 0x9b, 0x15, 0xa5,
+                0xca, 0xd7, 0x1c, 0x7e, 0x8e, 0xc5, 0x50, 0x86, 0x64, 0x13, 0xbc, 0x2c, 0xf3, 0x77, 0xb2, 0x59,
+                0xa8, 0x6e, 0x3f, 0x75, 0xb4, 0x8d, 0x1c, 0xad, 0xad, 0xf5, 0x76, 0x54, 0xc6, 0x00, 0x76, 0x94,
+                0xfc, 0x88, 0x71, 0x33, 0xbc, 0xf4, 0xed, 0xa4, 0x31, 0x76, 0x66, 0x7f, 0x05, 0x57, 0xeb, 0xe8,
+                0xb9, 0x25, 0xc0, 0x30, 0x2b, 0x0f, 0xe7, 0xa0, 0x96, 0xaf, 0x7e, 0x6a, 0xc4, 0x5a, 0x39, 0x4a,
+                0xbc, 0x14, 0x7c, 0x6e, 0x00, 0xdf, 0x53, 0x8d, 0x97, 0x5a, 0xe2, 0x49, 0xe9, 0x89, 0x74, 0xff,
+                0xec, 0x94, 0x22, 0xa5, 0x3a, 0xc5, 0xae, 0x14, 0xcd, 0xc3, 0x46, 0xf6, 0x17, 0x53, 0x2c, 0xcd,
+                0x59, 0x94, 0xc7, 0x3c, 0xad, 0xdb, 0x43, 0xb0, 0x1d, 0x8e, 0x0d, 0xae, 0x1a, 0x04, 0xad, 0xa2,
+                0x94, 0xe4, 0x90, 0x5c, 0x80, 0xa1, 0x42, 0xa2, 0x08, 0x61, 0xe3, 0x5a, 0x9e, 0x7c, 0xc4, 0x4d,
+                0x18, 0x1b, 0x8d, 0x0f, 0x61, 0x09, 0x78, 0xbb, 0xc5, 0x98, 0xb1, 0xe0, 0x1d, 0x8d, 0x09, 0x74,
+                0x7d, 0x26, 0xcb, 0x13, 0x21, 0x2d, 0x13, 0x2b, 0xd1, 0xc8, 0x05, 0x2b, 0xf8, 0x29, 0x27, 0xb0,
+                0xf9, 0x94, 0xbb, 0xa4, 0xaf, 0xf7, 0xea, 0x51, 0x47, 0x04, 0x86, 0x4e, 0x14, 0x01, 0xdb, 0xfa,
+                0x9b, 0xee, 0x0c, 0x9f, 0x77, 0x8d, 0xb2, 0x2d, 0xb6, 0x30, 0x02, 0x91, 0x6e, 0x8f, 0x53, 0xe0,
+                0x44, 0x8f, 0xee, 0xd8, 0x35, 0x0b, 0x94, 0xa1, 0x6a, 0x8b, 0xf5, 0xd3, 0x2c, 0xd1, 0x3d, 0xe3,
+                0xfb, 0x56, 0xb9, 0x02, 0x7a, 0x85, 0xc7, 0x3d, 0x64, 0x64, 0x46, 0x47, 0x14, 0x5c, 0xe4, 0xcc,
+                0xb0, 0x16, 0xb3, 0x0d, 0xa7, 0x8d, 0xf5, 0xc9, 0xa5, 0x83, 0xc9, 0x66, 0x64, 0x19, 0x0d, 0x32,
+                0x3d, 0x10, 0xc2, 0xc0, 0x8b, 0x12, 0xb3, 0x90, 0xf4, 0x6c, 0x34, 0x39, 0x24, 0x89, 0x93, 0x26,
+                0x49, 0x79, 0xd8, 0x9f, 0x6c, 0x44, 0x02, 0x8f, 0xd8, 0x22, 0x1b, 0x6f, 0xf3, 0xb7, 0xf1, 0x8b,
+                0x99, 0x90, 0x0f, 0x95, 0xb8, 0x92, 0x23, 0x1a, 0x20, 0xa3, 0x74, 0x6f, 0x40, 0x8a, 0xaf, 0x6a,
+                0x33, 0xf1, 0xf0, 0x5a, 0xe9, 0x50, 0x58, 0x0b, 0x76, 0x87, 0xe7, 0x42, 0x34, 0x3a, 0x50, 0xff,
+                0x10, 0x0d, 0x91, 0xc2, 0x63, 0x35, 0x51, 0xde, 0x67, 0xaa, 0x41, 0xdc, 0x0d, 0x0a, 0x6a, 0xf4,
+                0x07, 0xe6, 0xd8, 0xe1, 0xff, 0x01, 0x33, 0x10, 0x7f, 0xc8, 0x1d, 0x30, 0x3a, 0xc5, 0xce, 0x72,
+                0xcb, 0x05, 0x9d, 0x2f, 0xcb, 0x48, 0xf2, 0xc5, 0x7d, 0xfb, 0x4c, 0xe5, 0x64, 0x63, 0x26, 0x18,
+                0x95, 0x6c, 0x87, 0x13, 0xcd, 0x44, 0x26, 0x9b, 0x31, 0x02, 0xcf, 0xee, 0x65, 0xf6, 0x1c, 0x49,
+                0x1e, 0xd3, 0xb5, 0x91, 0xc1, 0x1e, 0xe9, 0xf2, 0x81, 0x87, 0x55, 0x6c, 0x18, 0xaf, 0xaf, 0x93,
+                0x8b, 0x86, 0xf2, 0xe9, 0x69, 0x13, 0xe2, 0x25, 0x1f, 0x32, 0xc4, 0x36, 0xa2, 0xfd, 0xdb, 0x6b,
+                0x93, 0x2d, 0x15, 0xec, 0x80, 0x55, 0xa8, 0x58, 0x4f, 0x1f, 0xd8, 0xbe, 0x2b, 0x8e, 0x26, 0x06,
+                0xf3, 0x73, 0x2a, 0xae, 0x87, 0xe4, 0x95, 0x7b, 0xb3, 0x8b, 0xb1, 0x0f, 0xe3, 0x9d, 0x47, 0x67,
+                0x4f, 0x1d, 0xae, 0xd8, 0xe0, 0x76, 0x1a, 0xc2, 0x0b, 0x3e, 0x89, 0x22, 0x62, 0xdc, 0x15, 0x05,
+                0x15, 0x51, 0x22, 0x2c, 0xce, 0x2f, 0xe2, 0x99, 0x74, 0x75, 0xc3, 0x7e, 0xcd, 0x66, 0x4e, 0xdf,
+                0x97, 0x95, 0xea, 0xfa, 0x54, 0xae, 0x01, 0x58, 0x4a, 0xa6, 0x90, 0xfe, 0x6a, 0xe5, 0xf8, 0xce,
+                0x78, 0x13, 0x1b, 0x20, 0x55, 0x33, 0xaf, 0xc7, 0x0a, 0x96, 0x14, 0x99, 0xb4, 0x22, 0xec, 0xcf,
+                0x3c, 0x6a, 0x5c, 0x9d, 0x46, 0x92, 0x81, 0xee, 0x72, 0x7a, 0x6c, 0x5c, 0xe5, 0xa1, 0xcc, 0x5c,
+                0x7b, 0x99, 0xae, 0x53, 0x3d, 0x05, 0xaf, 0x21, 0xf2, 0x4b, 0x6a, 0xf8, 0xd6, 0xc5, 0xce, 0xf9,
+                0x15, 0xce, 0xc8, 0xa5, 0x37, 0x58, 0x3c, 0xe1, 0x83, 0xd4, 0xbe, 0x3e, 0x1e, 0x7a, 0x6e, 0x9e,
+                0x6a, 0x94, 0x03, 0xa7, 0x25, 0x9c, 0x1c, 0x26, 0x84, 0x8e, 0xc4, 0xf1, 0x52, 0x8d, 0xc7, 0x76,
+                0xd7, 0xa4, 0x7f, 0xc2, 0x52, 0x5c, 0x6b, 0x3a, 0xb3, 0xb2, 0xa9, 0x9a, 0x4b, 0xff, 0xc1, 0x89,
+                0x99, 0xc5, 0x77, 0xac, 0x0d, 0x09, 0x69, 0xde, 0x50, 0x49, 0x03, 0xd2, 0xf7, 0x7a, 0xc9, 0xe9,
+                0x48, 0x9f, 0x66, 0xa3, 0x91, 0x0d, 0x8e, 0x4f, 0xe1, 0x70, 0xc8, 0x74, 0x93, 0xd8, 0x76, 0x2b,
+                0x9f, 0x4f, 0x15, 0xd5, 0xff, 0xb0, 0x5a, 0x4f, 0x06, 0xaa, 0xe0, 0xca, 0xdd, 0x0b, 0xd7, 0x6d,
+                0x28, 0xa7, 0x20, 0x32, 0x6b, 0x20, 0x57, 0x51, 0x15, 0xbc, 0xc0, 0xc7, 0xa2, 0x21, 0xfa, 0x92,
+                0x45, 0xf0, 0x24, 0x88, 0xc3, 0x22, 0x65, 0x32, 0x27, 0x45, 0x96, 0x1b, 0x6f, 0xdb, 0x8b, 0x22,
+                0x17, 0x78, 0xa0, 0x78, 0xe1, 0xd5, 0x6a, 0x9e, 0x6a, 0xc9, 0xde, 0xe3, 0x71, 0x1b, 0x9d, 0x31,
+                0x27, 0xb2, 0x25, 0x80, 0xfd, 0x47, 0x85, 0xa7, 0xb7, 0xcd, 0x63, 0xb3, 0x54, 0xc7, 0xf2, 0x53,
+                0xbf, 0x22, 0x58, 0x95, 0xc4, 0x39, 0x19, 0x9d, 0xce, 0xbe, 0x54, 0xd5, 0x58, 0x68, 0x01, 0xf8,
+                0x0d, 0x28, 0xaa, 0xf8, 0x27, 0x71, 0x68, 0x3b, 0x13, 0x53, 0x07, 0xd4, 0x42, 0xb0, 0x02, 0x66,
+                0x35, 0x2b, 0xec, 0x62, 0x84, 0x85, 0x2b, 0x2c, 0xe7, 0x09, 0xa5, 0xe6, 0x1a, 0x77, 0x18, 0x28,
+                0x94, 0xff, 0x1b, 0x3e, 0xcf, 0xdd, 0x21, 0x2a, 0xe2, 0x49, 0xa4, 0x27, 0xcf, 0x3a, 0x72, 0xcc,
+                0x3e, 0xbe, 0x24, 0x61, 0xe2, 0x43, 0x4b, 0x3e, 0xcb, 0xe5, 0x18, 0x63, 0xfc, 0xd0, 0xb3, 0x49,
+                0xcc, 0xd1, 0xce, 0xd5, 0x1d, 0x38, 0x72, 0x07, 0xbc, 0xa5, 0x68, 0xa5, 0xb1, 0x30, 0xc7, 0x5b,
+                0xfc, 0x15, 0xcf, 0xf5, 0xa0, 0xf7, 0xe9, 0x38, 0x7d, 0xd3, 0xcb, 0xc0, 0x77, 0x16, 0x2a, 0x37,
+                0xff, 0x62, 0x09, 0x5c, 0xe7, 0x5e, 0x5b, 0xfc, 0xaf, 0xcc, 0xe4, 0xcf, 0x63, 0x13, 0xb0, 0x53,
+                0xbf, 0xf2, 0x94, 0x76, 0xb5, 0xd3, 0x60, 0x72, 0x0c, 0xf1, 0x71, 0x43, 0xa0, 0x04, 0xaa, 0xe5,
+                0x87, 0x8c, 0x57, 0x66, 0x20, 0xe2, 0x9c, 0x39, 0xb4, 0xc0, 0xb4, 0x40, 0x55, 0x34, 0xe6, 0x31,
+                0x75, 0x03, 0xdf, 0xf3, 0x5c, 0xd8, 0x15, 0x16, 0x35, 0x40, 0xc5, 0xcf, 0xc7, 0x51, 0x3b, 0x03,
+                0xb4, 0x8f, 0x21, 0x96, 0x3d, 0x4f, 0x32, 0xb8, 0x05, 0xdf, 0x66, 0xb4, 0xcd, 0x42, 0xd4, 0x36,
+                0x2e, 0x2d, 0x73, 0x76, 0xc5, 0x59, 0x92, 0xe7, 0x0f, 0xe6, 0x42, 0x1f, 0x34, 0xc6, 0x9c, 0x28,
+                0x5e, 0xee, 0x14, 0x24, 0xd6, 0x66, 0xa9, 0x1a, 0xd0, 0xd5, 0x60, 0xa2, 0xc0, 0x73, 0x30, 0x1a,
+                0x40, 0xc3, 0xf3, 0x77, 0x8b, 0x96, 0xef, 0xcb, 0x30, 0x83, 0x09, 0x62, 0x08, 0x1e, 0x50, 0x2d,
+                0x26, 0xde, 0xaa, 0xa4, 0x74, 0x85, 0x5b, 0xd3, 0x4d, 0xbe, 0x70, 0x03, 0x26, 0xf6, 0x59, 0x0c,
+                0x3e, 0x06, 0x5a, 0xfb, 0xfb, 0xd1, 0x3b, 0x32, 0xc9, 0x71, 0x67, 0x89, 0x38, 0x07, 0xce, 0x24,
+                0xe3, 0x9e, 0x26, 0x06, 0x66, 0x06, 0xbb, 0x90, 0x1e, 0x67, 0xd5, 0x00, 0x3e, 0x8b, 0xeb, 0x49,
+                0xce, 0xdf, 0x3d, 0xb6, 0x54, 0x4c, 0xef, 0xd2, 0x98, 0x7c, 0x49, 0x49, 0xd9, 0xb8, 0x06, 0xac,
+                0x89, 0xa8, 0x94, 0x78, 0xe5, 0x83, 0x04, 0x49, 0xfb, 0x5a, 0x87, 0x7d, 0x10, 0x9c, 0x56, 0x3f,
+                0x42, 0xd6, 0x6f, 0x97, 0x66, 0xe1, 0x18, 0xbc, 0x71, 0xc1, 0x03, 0x24, 0xaf, 0xdf, 0x36, 0x04,
+                0x66, 0x02, 0x55, 0xd8, 0xae, 0x19, 0x96, 0x48, 0xc5, 0x6f, 0x4c, 0x7c, 0x34, 0x2c, 0x01, 0x24,
+                0xd0, 0x49, 0xf5, 0x85, 0x76, 0xcc, 0x69, 0x56, 0x7a, 0x2f, 0x57, 0x3c, 0x5c, 0x81, 0x76, 0x73,
+                0x13, 0x84, 0xa5, 0xd7, 0x3a, 0xfa, 0x3c, 0x84, 0x67, 0x3e, 0x11, 0x1d, 0x34, 0xe9, 0x33, 0x0b,
+                0x47, 0x96, 0x02, 0x92, 0x4e, 0x43, 0x0b, 0xab, 0x56, 0x64, 0x53, 0xdf, 0x1d, 0x37, 0x1a, 0x57,
+                0x00, 0x7d, 0x0d, 0x99, 0x1a, 0x7c, 0x6d, 0x68, 0xf7, 0xb2, 0x7e, 0x07, 0xeb, 0x65, 0xf4, 0x4c,
+                0xbb, 0x2d, 0xe7, 0xd9, 0xc7, 0xa7, 0x52, 0x58, 0x36, 0x27, 0x2a, 0x51, 0xd9, 0x0e, 0x6b, 0x70,
+                0xfe, 0xb9, 0xa2, 0x34, 0x41, 0x72, 0x68, 0xc5, 0x9c, 0xcc, 0xd4, 0x7a, 0x90, 0xf0, 0x62, 0xa0,
+                0xf6, 0x05, 0x4b, 0xd6, 0x70, 0x9c, 0x04, 0xd9, 0x76, 0xde, 0xb6, 0x09, 0xb4, 0xc5, 0x24, 0x4b,
+                0x8e, 0x79, 0x11, 0x91, 0xaf, 0x89, 0x10, 0x68, 0x8c, 0xed, 0xb5, 0xf2, 0x39, 0x8d, 0xe8, 0x0d,
+                0xed, 0xb9, 0x22, 0x20, 0xe0, 0x45, 0x8a, 0xc2, 0x7d, 0x23, 0xb2, 0xb0, 0xb2, 0xde, 0xdb, 0x0f,
+                0xa1, 0x6b, 0x8b, 0xf0, 0x94, 0x8b, 0xa5, 0x40, 0x1b, 0x2b, 0xcb, 0x41, 0x35, 0x39, 0x28, 0x3d,
+                0x4e, 0x13, 0x6b, 0x2c, 0xbf, 0xa7, 0x6d, 0xd0, 0x11, 0xdf, 0x43, 0xd6, 0xf3, 0xc5, 0x54, 0x79,
+                0x86, 0x07, 0x7c, 0xef, 0x1a, 0x51, 0xc3, 0xb2, 0xc6, 0xaa, 0x04, 0x68, 0xfb, 0xcb, 0xf0, 0x1b,
+                0x1f, 0xf3, 0x45, 0xe0, 0x6e, 0x6d, 0xab, 0xb7, 0x7c, 0x42, 0x58, 0xc9, 0xbb, 0x35, 0xd9, 0x1f,
+                0x9a, 0x88, 0x26, 0x12, 0x54, 0xda, 0x1d, 0x0d, 0xc4, 0x3e, 0x50, 0xd5, 0x17, 0x00, 0x08, 0x54,
+                0xd3, 0x11, 0x01, 0xea, 0xb4, 0x47, 0xd7, 0x5c, 0x8f, 0x7a, 0x58, 0xfb, 0x07, 0x2a, 0xb7, 0x53,
+                0xd6, 0x2b, 0x59, 0x13, 0xaf, 0x78, 0x22, 0x70, 0x1f, 0x10, 0xe3, 0x48, 0xae, 0x4f, 0xda, 0x98,
+                0xca, 0xdd, 0x53, 0xab, 0xb8, 0x02, 0xa5, 0x95, 0xc8, 0xe0, 0x1c, 0x99, 0xf6, 0x9c, 0x18, 0x55,
+                0x18, 0xcf, 0x67, 0x91, 0x46, 0xbb, 0x21, 0x1b, 0xea, 0x26, 0xbd, 0x5f, 0x90, 0x00, 0x7b, 0xbc,
+                0xe5, 0x6f, 0xa0, 0xaf, 0xd8, 0xe6, 0xcd, 0x18, 0x75, 0x50, 0x3c, 0x08, 0x98, 0x56, 0x67, 0xfd,
+                0x1a, 0x58, 0x64, 0xc0, 0x89, 0x11, 0xf0, 0x39, 0x65, 0x8a, 0x5f, 0x8c, 0x04, 0xd3, 0x93, 0x83,
+                0xf0, 0x7d, 0xd8, 0xdf, 0xee, 0x0a, 0x2e, 0x8b, 0xc2, 0x12, 0x0e, 0x21, 0xe0, 0x75, 0xe2, 0x1d,
+                0x6c, 0x22, 0x08, 0x5a, 0xaf, 0xdb, 0x17, 0x5a, 0x29, 0xc7, 0x76, 0xa8, 0xfc, 0x9a, 0x74, 0x1a,
+                0xbd, 0xfe, 0x89, 0xc6, 0x23, 0xf8, 0x09, 0x58, 0xfe, 0xf2, 0x9d, 0xf0, 0xc3, 0x3e, 0xa9, 0x06,
+                0x57, 0x2d, 0x5f, 0x41, 0x76, 0xd7, 0xa9, 0xec, 0x3b, 0x08, 0xac, 0x3d, 0x62, 0x0e, 0x66, 0x25,
+                0xca, 0x2f, 0x10, 0xc5, 0xc7, 0x47, 0x2b, 0xc2, 0x3a, 0xda, 0x69, 0x55, 0xe6, 0x88, 0xb6, 0x4d,
+                0x82, 0x0e, 0xe7, 0x40, 0x95, 0x2e, 0xe6, 0x6b, 0x4f, 0xb3, 0xc3, 0x30, 0x1e, 0x90, 0x44, 0x42,
+                0xef, 0x46, 0x53, 0xf2, 0x46, 0xe7, 0xb5, 0x3b, 0x12, 0xae, 0x20, 0x99, 0xa0, 0xfc, 0x65, 0x3c,
+                0x80, 0xec, 0x5c, 0xf5, 0x56, 0x9c, 0x94, 0x15, 0xb1, 0xa8, 0xe3, 0xa1, 0xde, 0xd7, 0xdc, 0x67,
+                0xa0, 0x89, 0x4a, 0x04, 0x00, 0x4f, 0x8f, 0xb4, 0xe6, 0x81, 0xb5, 0x4f, 0x36, 0xcb, 0xa8, 0x71,
+                0xcd, 0x33, 0xc6, 0x16, 0x0c, 0x9e, 0xa8, 0x2e, 0x4b, 0x56, 0x04, 0x5f, 0x24, 0x6b, 0x0a, 0x02,
+                0x92, 0x36, 0x67, 0xa2, 0x01, 0xb8, 0xde, 0x46, 0x20, 0x27, 0x69, 0x1c, 0x3c, 0x96, 0x82, 0x60,
+                0x01, 0xda, 0xa7, 0x19, 0xfd, 0x00, 0xab, 0x54, 0x9b, 0x66, 0xf8, 0xa8, 0xe3, 0x7d, 0xe8, 0x94,
+                0x5e, 0xc4, 0xc2, 0x34, 0x5d, 0xa9, 0x91, 0x41, 0x7e, 0xa6, 0xe5, 0x84, 0xcb, 0x3d, 0x10, 0xbf,
+                0xab, 0x02, 0xd1, 0x9d, 0xc3, 0xae, 0xe3, 0x0b, 0x03, 0x08, 0x19, 0x77, 0x4e, 0xb5, 0x55, 0x35,
+                0x42, 0xc1, 0x03, 0x99, 0x3c, 0xd6, 0x33, 0x7a, 0x58, 0xb9, 0xcc, 0x23, 0x71, 0x3c, 0x67, 0xab,
+                0x33, 0x26, 0xf5, 0x68, 0xe6, 0xb2, 0x23, 0x89, 0x1b, 0xd9, 0xb6, 0xf3, 0x5b, 0xba, 0xea, 0x41,
+                0xb1, 0xd9, 0x7b, 0xc5, 0xe9, 0xeb, 0xec, 0x45, 0x09, 0x4b, 0x1f, 0x6c, 0x17, 0x54, 0x3f, 0x2a,
+                0x68, 0xf5, 0xe9, 0xdb, 0xcb, 0xa4, 0x99, 0x0a, 0xae, 0x4b, 0xe4, 0x9f, 0x09, 0x84, 0xd1, 0x82,
+                0x79, 0xf3, 0x8c, 0xd5, 0x10, 0x6d, 0x79, 0xc9, 0x2d, 0xe3, 0x47, 0xfd, 0x81, 0x6a, 0x9a, 0x38,
+                0x3d, 0x7b, 0x25, 0x5d, 0x96, 0x35, 0x3a, 0x59, 0xbb, 0xb3, 0x6b, 0x31, 0x03, 0x43, 0xf0, 0x9b,
+                0x72, 0xe5, 0xed, 0x2a, 0x18, 0x2f, 0xb4, 0x5f, 0x87, 0x54, 0x0e, 0x06, 0xc4, 0x58, 0x85, 0x80,
+                0x29, 0xda, 0x85, 0x21, 0x2f, 0x11, 0x8b, 0x3c, 0x9f, 0xde, 0xb3, 0x53, 0x7e, 0x12, 0x19, 0x01,
+                0xc9, 0xb7, 0x51, 0x35, 0x7d, 0x79, 0x38, 0x0e, 0xc2, 0xc6, 0x66, 0xab, 0x14, 0xba, 0x94, 0xff,
+                0x64, 0x0b, 0xa7, 0x0e, 0x92, 0x6c, 0x55, 0x0a, 0xd0, 0x7a, 0xae, 0x88, 0x99, 0xaa, 0x52, 0x06,
+                0x43, 0x3b, 0xa6, 0xef, 0x2b, 0x4e, 0xa1, 0xc9, 0xdf, 0x47, 0x26, 0xc1, 0x62, 0x7d, 0xe3, 0x66,
+                0x40, 0x9c, 0x87, 0x2f, 0xf8, 0xd6, 0xe9, 0x3a, 0x51, 0xff, 0xd6, 0x68, 0xf8, 0x72, 0xf1, 0xcc,
+                0xb7, 0x37, 0x95, 0x19, 0xdf, 0x4e, 0x39, 0x6f, 0x5a, 0x73, 0xe6, 0xc5, 0x37, 0x94, 0xc9, 0xb3,
+                0xf1, 0x39, 0xfa, 0x1b, 0x15, 0x28, 0xd6, 0x25, 0xaf, 0x71, 0x5f, 0x51, 0x65, 0x3a, 0xd1, 0xc6,
+                0xa4, 0x87, 0x88, 0x9d, 0xee, 0x9c, 0x56, 0x8a, 0xd5, 0xe2, 0xd6, 0x40, 0x4a, 0xfb, 0x2b, 0x7c,
+                0xb4, 0x6f, 0xef, 0x21, 0x5d, 0x40, 0x74, 0x0b, 0xee, 0x59, 0x53, 0xa3, 0x45, 0x5e, 0x33, 0x97,
+                0x59, 0xec, 0x8c, 0x6b, 0x97, 0xf8, 0xa3, 0x4c, 0xb4, 0xea, 0x0c, 0x27, 0x04, 0xc9, 0xb7, 0xb6,
+                0xe2, 0x1b, 0xd6, 0x6a, 0xec, 0x60, 0x89, 0x10, 0xc2, 0xd1, 0x77, 0xc1, 0x26, 0xd6, 0xf5, 0x15,
+                0xa2, 0x5c, 0x83, 0xbd, 0xe2, 0x92, 0x29, 0x18, 0x51, 0xc8, 0x2c, 0x61, 0xef, 0x90, 0x9c, 0xfa,
+                0x2c, 0xd2, 0xee, 0x4b, 0x9f, 0x4b, 0xea, 0x13, 0x06, 0xde, 0x84, 0x43, 0x83, 0x4e, 0x65, 0xbf,
+                0x12, 0x02, 0x54, 0xf5, 0xb8, 0x7e, 0x87, 0x6a, 0x98, 0xd9, 0xb3, 0x0d, 0xd9, 0xd1, 0x87, 0x96,
+                0x9a, 0xaa, 0x93, 0x05, 0xc6, 0x13, 0x9b, 0xba, 0x23, 0x63, 0x41, 0x80, 0xf9, 0x91, 0x3b, 0xa2,
+                0xfd, 0xd7, 0xa3, 0x0c, 0x33, 0x7c, 0x3b, 0xc9, 0x34, 0x54, 0x74, 0xf4, 0xb5, 0x9e, 0xd5, 0x2b,
+                0xb1, 0xaa, 0x0f, 0x86, 0x53, 0x1c, 0x66, 0x6f, 0x6a, 0x38, 0x3d, 0x02, 0x20, 0xb7, 0xab, 0x9e,
+                0x53, 0x15, 0x19, 0x2e, 0xdd, 0xd3, 0x82, 0xf5, 0xb5, 0x69, 0x6a, 0x97, 0x47, 0xe9, 0x04, 0xea,
+                0x34, 0x2d, 0x67, 0xec, 0x82, 0x0f, 0x36, 0xd1, 0x79, 0x96, 0x89, 0xa1, 0x4d, 0x73, 0x1c, 0x7a,
+                0x78, 0xf5, 0xe9, 0x62, 0x9d, 0x87, 0x93, 0x50, 0x00, 0x97, 0x75, 0x46, 0xc1, 0x9c, 0x66, 0x16,
+                0x72, 0xab, 0x67, 0x22, 0xb2, 0x6b, 0x0c, 0x23, 0x88, 0x01, 0xcc, 0xc3, 0xf0, 0x1e, 0xf0, 0x9d,
+                0x9e, 0x5a, 0xd3, 0xe2, 0x0f, 0x59, 0x18, 0x38, 0xb5, 0x38, 0x6d, 0x9c, 0x5c, 0xf8, 0xe0, 0xa9,
+                0x2d, 0x1a, 0x72, 0x38, 0x35, 0xf3, 0x8a, 0x92, 0x4a, 0xc7, 0xba, 0x5a, 0xf1, 0x5a, 0x85, 0x2f,
+                0x13, 0x2a, 0x93, 0xaf, 0x12, 0xd3, 0x83, 0xcb, 0xb0, 0x40, 0x3d, 0xee, 0x3b, 0x6a, 0x6e, 0x3e,
+                0xb2, 0xd2, 0x7e, 0xb7, 0x07, 0x1e, 0x54, 0xc8, 0x8e, 0xc0, 0xf7, 0x23, 0xb1, 0xa0, 0xbd, 0x78,
+                0xb7, 0x8b, 0x83, 0x59, 0x2d, 0xd5, 0x3b, 0x5f, 0x44, 0x3a, 0x63, 0x8b, 0x88, 0x84, 0x69, 0x3c,
+                0x7b, 0xae, 0xfe, 0x21, 0xe8, 0xff, 0x03, 0xd8, 0x23, 0xc3, 0x83, 0x31, 0x06, 0xe2, 0x3f, 0x8a,
+                0x21, 0x14, 0xee, 0x4b, 0xd3, 0xca, 0xb1, 0x0a, 0xd9, 0xc7, 0x31, 0xbf, 0xbc, 0xab, 0x35, 0x16,
+                0x0e, 0x13, 0x5d, 0x40, 0xc2, 0xb1, 0xe5, 0xd3, 0xb2, 0x76, 0xc5, 0x38, 0x48, 0x49, 0xcc, 0x97,
+                0x70, 0x35, 0xa1, 0x0d, 0x6e, 0xc6, 0xa8, 0x29, 0xe6, 0xaa, 0xc2, 0xe1, 0x63, 0x95, 0x5b, 0x77,
+                0x63, 0x7f, 0x09, 0xf5, 0x66, 0xd1, 0xe7, 0x60, 0x97, 0x53, 0x05, 0x22, 0x1d, 0x77, 0x07, 0xc6,
+                0x30, 0xa0, 0x9e, 0x78, 0x7f, 0x92, 0xd2, 0x76, 0x9c, 0x63, 0x9d, 0xf3, 0xa3, 0x6f, 0xb0, 0xb8,
+                0x30, 0x73, 0xda, 0xbd, 0x50, 0xad, 0xa8, 0x30, 0xa4, 0x17, 0x38, 0x6d, 0x57, 0x17, 0x9d, 0x09,
+                0xa6, 0x7c, 0x4a, 0x30, 0xcc, 0xcc, 0x89, 0x16, 0x11, 0x81, 0x61, 0x29, 0x9b, 0x61, 0x07, 0x89,
+                0x82, 0x28, 0x1c, 0xc9, 0x6b, 0xca, 0x75, 0x83, 0x55, 0xe8, 0x30, 0xe1, 0x63, 0xab, 0xa8, 0x7e,
+                0x6e, 0x6a, 0xa8, 0xdc, 0x89, 0x03, 0x57, 0xfe, 0x32, 0x0a, 0xfa, 0xdd, 0x87, 0xa3, 0xc2, 0x1d,
+                0x41, 0xc7, 0x55, 0x94, 0x38, 0x5d, 0xec, 0x4c, 0x06, 0xf8, 0xd5, 0x29, 0xa6, 0x64, 0x4b, 0x93,
+                0x38, 0x14, 0x63, 0x51, 0x53, 0x03, 0x09, 0x4b, 0x67, 0x74, 0x3d, 0x41, 0xc6, 0x5d, 0x69, 0xc9,
+                0xd2, 0x76, 0xba, 0x1a, 0x07, 0x6f, 0x72, 0x85, 0xb1, 0xb2, 0x1a, 0x9c, 0xe7, 0xed, 0xf5, 0x1e,
+                0xd6, 0xe7, 0x5f, 0xc7, 0x7d, 0x64, 0x35, 0xc7, 0x10, 0xc7, 0xae, 0x93, 0x87, 0x54, 0x49, 0xdb,
+                0x1e, 0x7d, 0xaa, 0x94, 0x3e, 0x5b, 0xf3, 0x79, 0x72, 0xcf, 0xba, 0xa2, 0x59, 0x42, 0x7c, 0xad,
+                0x0f, 0x19, 0x6b, 0xe8, 0xef, 0xa7, 0x01, 0x98, 0xce, 0x34, 0xf6, 0xf0, 0xfc, 0x8d, 0xef, 0x32,
+                0x10, 0x57, 0x25, 0xdc, 0xb6, 0x43, 0x46, 0xd3, 0xf7, 0xf4, 0x5c, 0xd1, 0x6c, 0xc8, 0x64, 0xc5,
+                0x44, 0x55, 0x28, 0x10, 0x3d, 0x19, 0x40, 0xf1, 0xba, 0xd2, 0x47, 0x9d, 0xf0, 0x8e, 0x0a, 0x61,
+                0x04, 0x71, 0x2f, 0x32, 0xec, 0x9b, 0x91, 0xa9, 0x6a, 0x73, 0x1c, 0xc5, 0xd7, 0x25, 0x07, 0xaf,
+                0x8e, 0x6e, 0x98, 0x09, 0xd4, 0xa7, 0xa7, 0xf7, 0x27, 0x55, 0x42, 0xe3, 0xf7, 0xf5, 0xf1, 0x15,
+                0x3b, 0x3c, 0x0e, 0x4d, 0x99, 0x86, 0xb1, 0xd4, 0x9c, 0x2e, 0x28, 0x6a, 0xb5, 0xa9, 0xe1, 0x92,
+                0xfe, 0x9d, 0xb7, 0x4f, 0x86, 0x4b, 0x21, 0x75, 0xee, 0xb8, 0xc6, 0xff, 0xe5, 0x0a, 0x9b, 0x1b,
+                0x1e, 0xf6, 0x8a, 0x9b, 0x6d, 0xb1, 0x76, 0x93, 0x2d, 0x8c, 0xf7, 0x61, 0x51, 0x34, 0x14, 0x16,
+                0xd3, 0xb9, 0xde, 0x38, 0x50, 0x03, 0xc2, 0x3c, 0x5d, 0xf9, 0xc2, 0xac, 0x27, 0x14, 0x65, 0x4f,
+                0xbd, 0x56, 0x67, 0xc5, 0x1a, 0xe6, 0xb4, 0x95, 0x1a, 0x73, 0x1f, 0x44, 0x4d, 0xc1, 0x96, 0xba,
+                0xef, 0x59, 0x2d, 0x05, 0x7c, 0xda, 0xbc, 0x3d, 0x4d, 0x34, 0x5d, 0x2f, 0xfb, 0xa3, 0x9e, 0xe9,
+                0xa8, 0x76, 0x86, 0x05, 0xbd, 0xa2, 0xdc, 0xca, 0x83, 0x01, 0xf5, 0xb7, 0x6f, 0x50, 0xf9, 0xa7,
+                0xbe, 0xc1, 0xe1, 0xb4, 0x24, 0x1e, 0x42, 0xdd, 0xb2, 0xc2, 0x35, 0x12, 0xb4, 0xab, 0x60, 0x20,
+                0x9e, 0x10, 0x22, 0x98, 0xc6, 0xdf, 0x87, 0xcb, 0xd8, 0x9b, 0xab, 0xae, 0x9d, 0xd9, 0xa8, 0x63,
+                0x51, 0x29, 0x17, 0xdb, 0x28, 0xe5, 0x89, 0xc9, 0x9f, 0x3d, 0x8b, 0xbe, 0x4f, 0x54, 0xf2, 0xf0,
+                0xfd, 0xa5, 0x61, 0xa7, 0x06, 0x69, 0xe4, 0x37, 0x12, 0x86, 0x5a, 0x37, 0x3a, 0x1f, 0x04, 0xb1,
+                0x2e, 0xa3, 0x8b, 0x03, 0x5f, 0xfa, 0xc1, 0xdd, 0x4c, 0xf8, 0x64, 0xa7, 0x9e, 0xb6, 0x45, 0x6a,
+                0x93, 0xb2, 0xc0, 0x0f, 0x60, 0x31, 0x1d, 0xe7, 0xf5, 0xf6, 0x2d, 0x38, 0xf6, 0x72, 0xe5, 0xcf,
+                0x2d, 0xe7, 0x44, 0x96, 0x74, 0x19, 0xd9, 0x70, 0x9e, 0x76, 0x7b, 0x74, 0x8a, 0x8b, 0x5a, 0x88,
+                0xf1, 0x85, 0xc3, 0x87, 0x87, 0x27, 0x0e, 0x24, 0x03, 0x09, 0x15, 0x30, 0x8c, 0x15, 0x09, 0x5f,
+                0x80, 0x4f, 0xdb, 0xa7, 0x93, 0x6c, 0x8b, 0x26, 0xba, 0x6e, 0xc6, 0xba, 0xf8, 0x68, 0x2b, 0xe6,
+                0x52, 0x34, 0x00, 0x40, 0x9e, 0xe2, 0x33, 0xdf, 0xb6, 0xd2, 0xac, 0x24, 0x02, 0x72, 0x3b, 0xc6,
+                0xbc, 0xeb, 0xf8, 0x2c, 0x95, 0x07, 0x65, 0x76, 0xda, 0xd9, 0x0c, 0x02, 0x72, 0xa8, 0xdb, 0x16,
+                0x12, 0x5a, 0xb1, 0x51, 0x73, 0x5d, 0x76, 0x37, 0xd8, 0xdb, 0x60, 0x4f, 0xa2, 0x8e, 0x90, 0x96,
+                0xe4, 0x78, 0x96, 0xcb, 0x67, 0xd2, 0x32, 0xca, 0xf7, 0x2f, 0x66, 0xbf, 0x82, 0x0f, 0x2a, 0x17,
+                0x68, 0xb3, 0x95, 0x38, 0x4c, 0x08, 0x86, 0x00, 0xb4, 0x66, 0xa0, 0x20, 0xa4, 0x02, 0x97, 0x71,
+                0x8c, 0x59, 0x04, 0xe9, 0x98, 0xba, 0x08, 0xf2, 0xd9, 0xcf, 0xaf, 0x73, 0x2e, 0x88, 0xb1, 0x68,
+                0x30, 0x06, 0xdd, 0x05, 0xf4, 0x1f, 0x55, 0x13, 0x04, 0xe6, 0xb1, 0x40, 0x1f, 0xcf, 0x46, 0x83,
+                0x26, 0x96, 0x8f, 0x41, 0x20, 0xec, 0x1c, 0x00, 0x78, 0x1d, 0xb4, 0x8c, 0x25, 0xb3, 0xe4, 0x2f,
+                0x94, 0x2f, 0xfe, 0x98, 0x92, 0x3a, 0x12, 0xaf, 0x34, 0x37, 0xee, 0xaa, 0x51, 0x60, 0x6e, 0x9c,
+                0x0a, 0x1f, 0xa9, 0x38, 0x00, 0x01, 0x17, 0xdd, 0x4c, 0x60, 0xbf, 0x0d, 0x08, 0x6f, 0xd3, 0xcf,
+                0x4a, 0x23, 0x81, 0x5f, 0x3b, 0xca, 0x66, 0x4f, 0xf1, 0xf8, 0x15, 0x51, 0xf7, 0xe1, 0x6d, 0x9f,
+                0x55, 0xd3, 0xd8, 0xb2, 0xb3, 0x94, 0x67, 0xa1, 0x24, 0xda, 0xfe, 0x60, 0xe9, 0x73, 0xf6, 0x93,
+                0x49, 0x22, 0x51, 0x4a, 0xaf, 0x47, 0x77, 0xfa, 0xce, 0x03, 0x69, 0xb1, 0x65, 0x8c, 0xce, 0x48,
+                0x62, 0xcc, 0x88, 0x61, 0xfb, 0x07, 0xcc, 0xdb, 0x4d, 0x01, 0x9d, 0x21, 0x65, 0x33, 0x1a, 0x72,
+                0x93, 0x67, 0x90, 0xff, 0x45, 0xa1, 0x50, 0x33, 0x74, 0xaf, 0x62, 0xf3, 0x61, 0xcf, 0xdb, 0x7a,
+                0xd5, 0x78, 0xce, 0x56, 0xbf, 0xee, 0xd6, 0x6b, 0x03, 0xd2, 0x7d, 0x69, 0xcd, 0x89, 0x81, 0xb1,
+                0xc1, 0xb2, 0x21, 0xf5, 0xd8, 0xcf, 0x15, 0x79, 0xfb, 0xbd, 0x56, 0xf6, 0x06, 0x90, 0xa1, 0x98,
+                0xc1, 0x6a, 0xb8, 0x70, 0xa7, 0xee, 0xbc, 0x02, 0xe3, 0x8a, 0xda, 0xac, 0x1f, 0x2b, 0x42, 0xa8,
+                0xc4, 0x39, 0xcc, 0xa8, 0x2d, 0x6d, 0x62, 0x5b, 0xa7, 0x55, 0x83, 0x4a, 0x7f, 0x1c, 0xbd, 0x16,
+                0xec, 0x9c, 0x03, 0x4d, 0xfb, 0x63, 0x33, 0x90, 0xab, 0x65, 0x2d, 0xa8, 0x7c, 0x55, 0x8b, 0xc8,
+                0x89, 0x97, 0x97, 0x8a, 0x33, 0x26, 0x03, 0xe2, 0x97, 0x42, 0x87, 0xf5, 0xc9, 0x6d, 0xae, 0x00,
+                0x00, 0x10, 0xc4, 0xc4, 0x6b, 0xfd, 0xcd, 0xb7, 0x58, 0x00, 0xee, 0xca, 0x51, 0x3d, 0x6d, 0x04,
+                0xb0, 0x7d, 0x36, 0x2f, 0x54, 0xf2, 0xa6, 0xd5, 0x35, 0xf9, 0xa4, 0x28, 0x56, 0xfd, 0x08, 0xc6,
+                0x7b, 0xd8, 0x0e, 0x38, 0x28, 0xd2, 0x67, 0x66, 0x51, 0x30, 0x06, 0x4f, 0x51, 0xcc, 0xa3, 0x46,
+                0x8e, 0xcb, 0x95, 0xee, 0x48, 0x2f, 0xac, 0xd0, 0x31, 0x5b, 0xbe, 0xb1, 0xf0, 0xf1, 0x78, 0x13,
+                0xd2, 0x2c, 0x16, 0x48, 0x18, 0x59, 0xe4, 0xee, 0x40, 0x7a, 0x4d, 0x9b, 0x10, 0x68, 0x0c, 0x89,
+                0xc5, 0x0c, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x02, 0x43, 0xff, 0xff, 0xfd, 0xbc, 0x00, 0x00, 0x00,
+                0x01, 0x41, 0x4d, 0x4c, 0x56, 0x86, 0x00, 0x40, 0x92, 0xe1, 0x81, 0x56, 0x00, 0x00, 0x18, 0x70,
+                0x5a, 0x9a, 0x74, 0x00, 0x00, 0x7f, 0xe8, 0x2b, 0xfc, 0x0c, 0x29, 0x71, 0x4d, 0x17, 0x17, 0xe7,
+                0xd9, 0x45, 0x16, 0x69, 0x89, 0x6b, 0x68, 0x73, 0xfe, 0x3a, 0xe9, 0x08, 0x96, 0xe2, 0x0f, 0xc5,
+                0x5d, 0x8c, 0xb1, 0x77, 0xec, 0x64, 0x9e, 0xce, 0x03, 0x26, 0x59, 0xee, 0x37, 0xe8, 0xc1, 0x2a,
+                0x2a, 0xdc, 0xfa, 0xa1, 0xb2, 0x5a, 0x4b, 0x59, 0xde, 0xa6, 0x91, 0xd1, 0x63, 0xa0, 0xa1, 0x81,
+                0xb1, 0x8d, 0xab, 0x38, 0xb0, 0xa5, 0x45, 0xcf, 0x41, 0xe5, 0x6c, 0x54, 0x13, 0xac, 0x85, 0x72,
+                0xd3, 0x7a, 0x0c, 0x7d, 0x47, 0xd0, 0xe5, 0x6c, 0xd5, 0x81, 0xb7, 0xf6, 0x8e, 0x53, 0x81, 0x42,
+                0x9e, 0x74, 0xb0, 0x3b, 0x1c, 0x7d, 0xbc, 0x04, 0xfe, 0x15, 0xc6, 0x00, 0x01, 0x9c, 0x05, 0x97,
+                0x44, 0x0e, 0xd6, 0xf0, 0x85, 0x0f, 0x28, 0x5b, 0x4d, 0x4b, 0x67, 0x07, 0x25, 0x16, 0xfe, 0x59,
+                0x69, 0xe2, 0x28, 0x42, 0xc6, 0xd0, 0xb4, 0x2c, 0x4e, 0xcf, 0x78, 0x8c, 0x9c, 0x85, 0x02, 0x09,
+                0xa3, 0x53, 0x53, 0xed, 0x0a, 0x52, 0xa7, 0x00, 0x48, 0x46, 0x12, 0x0f, 0x17, 0x7c, 0x6d, 0x99,
+                0x0f, 0x06, 0x14, 0xac, 0x68, 0xa4, 0x09, 0x01, 0x1d, 0x97, 0x7d, 0x2b, 0x81, 0xc2, 0x02, 0xad,
+                0x6e, 0x10, 0x82, 0xed, 0x3c, 0x51, 0xae, 0x23, 0xc6, 0xfb, 0x77, 0x54, 0x42, 0x7d, 0x46, 0x7e,
+                0x71, 0xfa, 0xa9, 0x63, 0xda, 0x8b, 0x4b, 0xc7, 0x85, 0x61, 0x9a, 0x5e, 0x08, 0xab, 0x74, 0x27,
+                0x35, 0x63, 0x21, 0x19, 0x09, 0xf4, 0xa3, 0x40, 0x19, 0x1a, 0xbd, 0x87, 0x00, 0x99, 0xd7, 0xd7,
+                0xda, 0xcf, 0x01, 0xdf, 0xc2, 0x9b, 0x35, 0xd8, 0x89, 0x58, 0xdb, 0xf5, 0x0c, 0xfb, 0x67, 0xb1,
+                0x54, 0x6f, 0x16, 0xc2, 0xed, 0x20, 0x2d, 0x67, 0xbb, 0xb7, 0xb5, 0x0b, 0xb7, 0xde, 0x2c, 0xfa,
+                0xa9, 0xe5, 0x0f, 0xf1, 0x10, 0x0e, 0x80, 0x7f, 0x2d, 0x25, 0x79, 0x3a, 0xd2, 0x80, 0x23, 0x07,
+                0x85, 0xc2, 0x80, 0x4f, 0x4f, 0x99, 0x6e, 0xf5, 0xd4, 0x4d, 0x9a, 0x23, 0x61, 0xa9, 0xe7, 0x6c,
+                0x8e, 0x3d, 0xc1, 0x34, 0x7d, 0xbc, 0x47, 0xea, 0x7d, 0x36, 0x9d, 0x92, 0x7f, 0xe8, 0x10, 0xf0,
+                0x6b, 0x63, 0x72, 0xee, 0xe7, 0x46, 0x35, 0xa6, 0xfc, 0xeb, 0x32, 0x27, 0xbe, 0x8e, 0x13, 0x58,
+                0x6e, 0xa9, 0xe1, 0x71, 0x9f, 0x1a, 0xf5, 0xb1, 0x5e, 0x3e, 0x08, 0xdb, 0xb8, 0x61, 0xef, 0xdd,
+                0xbb, 0x5c, 0x1b, 0x61, 0xe0, 0x12, 0xb6, 0xea, 0xfe, 0xfe, 0x75, 0xae, 0x71, 0x4f, 0x71, 0x97,
+                0x3e, 0x04, 0x02, 0x2e, 0x7a, 0xfd, 0xbf, 0x2d, 0x36, 0xd5, 0x45, 0x57, 0x80, 0xd0, 0xe6, 0xc8,
+                0x36, 0x63, 0x22, 0xda, 0x89, 0xc5, 0x90, 0xb3, 0x44, 0xff, 0x75, 0x4f, 0x25, 0xa7, 0xc1, 0xa9,
+                0x0a, 0xe6, 0x0b, 0x3d, 0x7c, 0x90, 0xfa, 0x59, 0x11, 0x7b, 0xd1, 0xbb, 0xa0, 0x1e, 0x38, 0x7e,
+                0xdd, 0xd2, 0x9a, 0xa5, 0xfb, 0x59, 0x63, 0x2a, 0x37, 0xc6, 0x06, 0x70, 0x54, 0x9e, 0x83, 0x35,
+                0xc5, 0xfb, 0xa4, 0x7f, 0xa4, 0xb7, 0x48, 0xf3, 0x16, 0xe1, 0x4c, 0xc6, 0x66, 0x9f, 0x8d, 0xb4,
+                0x3a, 0xb2, 0x8b, 0xb2, 0x9a, 0x88, 0x2f, 0xb7, 0x57, 0xd3, 0x91, 0xd1, 0x94, 0x1f, 0xfb, 0x85,
+                0x0d, 0x86, 0x39, 0x65, 0xcd, 0xfa, 0xa3, 0x25, 0x32, 0x54, 0x81, 0xdf, 0x1e, 0x3c, 0xcf, 0x9e,
+                0xe8, 0x74, 0xb1, 0x94, 0xdf, 0xae, 0x01, 0x10, 0x52, 0x43, 0xa4, 0x2c, 0xe7, 0xdd, 0x7f, 0x82,
+                0x18, 0xbf, 0xc3, 0x8c, 0xb8, 0xf2, 0xab, 0x16, 0xe8, 0xe9, 0xc5, 0x1d, 0xe2, 0xc1, 0x58, 0xdc,
+                0x93, 0x4e, 0x2e, 0x19, 0xc5, 0x83, 0x0f, 0xf7, 0x25, 0x28, 0x70, 0x1b, 0x70, 0xca, 0x53, 0x86,
+                0xed, 0x59, 0x96, 0xf0, 0x04, 0xba, 0x47, 0x26, 0xe8, 0xae, 0x5a, 0xa8, 0xc8, 0x6b, 0x4a, 0xe4,
+                0x46, 0xaf, 0x51, 0xf5, 0x2f, 0xb9, 0x03, 0xc5, 0xdb, 0x85, 0x28, 0x4f, 0xa2, 0xa9, 0x5c, 0xc4,
+                0x4d, 0xc7, 0x58, 0xce, 0x6f, 0xc9, 0xa9, 0x21, 0x04, 0x57, 0x91, 0x61, 0x7f, 0x6b, 0xb5, 0x61,
+                0x36, 0xd7, 0x90, 0x00, 0x00, 0x00, 0x03, 0x13, 0xff, 0xff, 0xfc, 0xec, 0x00, 0x00, 0x00, 0x01,
+                0x41, 0x4d, 0x4c, 0x56, 0x86, 0x00, 0x40, 0x92, 0xe1, 0x81, 0x56, 0x00, 0x00, 0x14, 0x70, 0x12,
+                0x20, 0x00, 0x00, 0x7f, 0xdb, 0xf4, 0x80, 0x58, 0xaf, 0x60, 0x9f, 0x03, 0x27, 0x50, 0xe2, 0x89,
+                0x62, 0x11, 0xa5, 0x5a, 0x21, 0x51, 0x4f, 0xdb, 0x8c, 0x95, 0x4f, 0xfd, 0xec, 0x37, 0xd3, 0x3b,
+                0x6e, 0x73, 0x15, 0x60, 0x6e, 0xfa, 0x66, 0xcd, 0x61, 0xff, 0xb3, 0xc7, 0x3d, 0x0e, 0xd5, 0x61,
+                0x3e, 0xe1, 0x5b, 0x03, 0x7f, 0x08, 0xb7, 0x66, 0x6b, 0x57, 0xab, 0x77, 0x0c, 0x84, 0xed, 0xc7,
+                0x81, 0xfe, 0x20, 0x80, 0x1f, 0x11, 0xf2, 0x02, 0x8d, 0x5c, 0x91, 0x5c, 0xeb, 0x61, 0x46, 0xe6,
+                0x06, 0x2d, 0x90, 0x43, 0x76, 0xca, 0x4b, 0x01, 0x8f, 0x02, 0x01, 0x41, 0x07, 0x9a, 0xee, 0x97,
+                0x99, 0x88, 0x5d, 0xa2, 0xbf, 0x93, 0x02, 0x8a, 0x02, 0x8a, 0x61, 0x08, 0x4f, 0xbc, 0xc4, 0x7e,
+                0x40, 0x15, 0x8e, 0xaa, 0x14, 0x7e, 0xbe, 0xdb, 0x86, 0x18, 0xf1, 0xcc, 0xd8, 0x56, 0x50, 0xe5,
+                0x14, 0xa0, 0x2c, 0x6b, 0x06, 0x30, 0xc4, 0x9f, 0x45, 0xe0, 0x8b, 0x33, 0x18, 0xe2, 0x47, 0x12,
+                0x5a, 0x22, 0xb4, 0x68, 0x33, 0x8a, 0xe6, 0x75, 0x41, 0x5a, 0xcf, 0x0f, 0xc8, 0xed, 0xa7, 0x4e,
+                0x90, 0xd0, 0x38, 0xe8, 0x51, 0x14, 0x37, 0x9c, 0x8e, 0x96, 0xe0, 0x22, 0x0a, 0xf8, 0xab, 0x63,
+                0x67, 0xaa, 0x96, 0x47, 0x55, 0xbd, 0x86, 0x33, 0x0f, 0x57, 0x07, 0x3b, 0xae, 0x42, 0x44, 0x84,
+                0x59, 0x36, 0x33, 0x4f, 0x41, 0xc7, 0x89, 0x35, 0x81, 0xba, 0x58, 0xc4, 0xd3, 0x97, 0x9b, 0xe6,
+                0x48, 0x92, 0xf3, 0x5f, 0xf9, 0xe3, 0xd5, 0xa4, 0xfd, 0x35, 0x47, 0x9c, 0xdd, 0x68, 0xca, 0xbd,
+                0x59, 0x36, 0xd5, 0x40, 0x65, 0xd7, 0xfa, 0x19, 0x6a, 0xcc, 0x17, 0xc0, 0x11, 0x2c, 0x72, 0x69,
+                0x0a, 0x7a, 0x0f, 0x27, 0x21, 0x21, 0xca, 0xc7, 0x7f, 0x59, 0x27, 0x21, 0x87, 0x64, 0x8d, 0xc4,
+                0xfd, 0x3b, 0x12, 0xfa, 0x96, 0xbe, 0x66, 0xd9, 0x4a, 0xf8, 0xa3, 0xd4, 0x32, 0x47, 0x81, 0x70,
+                0xe1, 0x6c, 0x99, 0xe4, 0xec, 0xac, 0x2c, 0xc5, 0xb8, 0x7e, 0x2a, 0x61, 0x31, 0x1b, 0x5e, 0xfb,
+                0x44, 0xbc, 0xab, 0x4c, 0x41, 0x32, 0xb1, 0xfc, 0xfa, 0x39, 0x04, 0xa9, 0x4a, 0x40, 0x50, 0x74,
+                0xa3, 0x6f, 0x90, 0x1e, 0x60, 0x71, 0xb0, 0xfd, 0x6e, 0x51, 0x6b, 0xef, 0xea, 0x2f, 0xe7, 0xba,
+                0x30, 0xa6, 0xe4, 0x29, 0x8b, 0x0b, 0xa2, 0xe4, 0xbf, 0x54, 0xc7, 0x38, 0xbf, 0x59, 0xab, 0x19,
+                0xf2, 0xe4, 0x92, 0x88, 0x9c, 0x22, 0x4b, 0x20, 0x69, 0x83, 0x17, 0xee, 0x7b, 0x10, 0x19, 0x92,
+                0xcf, 0x24, 0xd4, 0x01, 0xb5, 0x36, 0x9e, 0x93, 0x96, 0xe9, 0xe8, 0x5d, 0x77, 0x1a, 0x24, 0x9e,
+                0x79, 0xef, 0x3e, 0x63, 0xe5, 0x53, 0xa7, 0x57, 0xdd, 0xab, 0x0e, 0x62, 0xa2, 0x8e, 0xc7, 0xb4,
+                0xfb, 0xab, 0xa0, 0x9a, 0xdd, 0xb9, 0xe0, 0x1b, 0x66, 0x3c, 0x12, 0x9e, 0xb1, 0x9f, 0xf0, 0x5d,
+                0xe0, 0x53, 0xd4, 0xb2, 0xd3, 0xeb, 0x6c, 0x86, 0xed, 0xdc, 0xe8, 0xbb, 0xa8, 0xf9, 0x92, 0x63,
+                0xb2, 0xe7, 0xd9, 0x6e, 0x7b, 0x17, 0x0e, 0x7e, 0x6b, 0x84, 0x6f, 0x7d, 0x3c, 0x37, 0xe5, 0x50,
+                0xef, 0x16, 0x87, 0xf5, 0xb1, 0x92, 0x9b, 0x58, 0x03, 0xef, 0x99, 0x6e, 0x3b, 0x79, 0x16, 0xb2,
+                0x6c, 0x10, 0xb2, 0xa9, 0xcd, 0x6b, 0x0b, 0x71, 0x23, 0x95, 0xa9, 0xe3, 0xa7, 0x6e, 0x34, 0x31,
+                0x29, 0xec, 0x0d, 0x72, 0x3d, 0xa7, 0xb9, 0x01, 0xd4, 0xcb, 0xbb, 0x11, 0xda, 0x71, 0xd1, 0xbe,
+                0xbd, 0x3e, 0x53, 0xe6, 0xf8, 0x87, 0x0f, 0x2e, 0x63, 0xfe, 0x24, 0x46, 0xa9, 0x19, 0x94, 0xf5,
+                0x4a, 0xdc, 0x65, 0x61, 0x7b, 0x8b, 0xce, 0xf7, 0x07, 0x3b, 0x25, 0xa3, 0x4c, 0x5c, 0x01, 0x88,
+                0xd1, 0x3f, 0x5f, 0x21, 0x33, 0x26, 0xe9, 0xcd, 0x87, 0xb9, 0x69, 0xee, 0x8e, 0x45, 0xf1, 0x03,
+                0x7d, 0xb5, 0x73, 0x97, 0x62, 0x9a, 0x3e, 0x80, 0xf1, 0x84, 0xdd, 0xea, 0xaa, 0x8b, 0xfd, 0x30,
+                0x0e, 0x4c, 0xbb, 0xff, 0xfa, 0x74, 0x86, 0xe4, 0x35, 0x9f, 0x12, 0x04, 0x4f, 0xf7, 0x37, 0x14,
+                0x05, 0xef, 0x9f, 0x56, 0xba, 0x9b, 0xb7, 0x75, 0xb5, 0x63, 0x6b, 0xa8, 0x8f, 0x75, 0x63, 0x01,
+                0x10, 0x19, 0xb0, 0xea, 0xf7, 0xf4, 0x8f, 0xcb, 0x2c, 0x21, 0x35, 0x19, 0x15, 0x8d, 0xef, 0x10,
+                0x4a, 0x61, 0xec, 0x09, 0xa3, 0xe0, 0xe5, 0x8b, 0x60, 0xa1, 0x04, 0xf5, 0x11, 0xe6, 0xc6, 0xba,
+                0x66, 0x75, 0xa7, 0xe2, 0xed, 0x60, 0x7f, 0x53, 0xb4, 0xa7, 0x0a, 0xeb, 0x94, 0xa7, 0x33, 0x99,
+                0x22, 0x36, 0xa7, 0xc1, 0xef, 0x0d, 0xfe, 0xde, 0x0d, 0x3c, 0xa6, 0x9e, 0xe7, 0x89, 0x94, 0xfd,
+                0x2f, 0x40, 0xbf, 0x44, 0x42, 0xc3, 0x05, 0xcd, 0x3c, 0x8d, 0x4b, 0x70, 0xa2, 0x0a, 0x1f, 0x64,
+                0x7c, 0x5e, 0x34, 0xb2, 0x49, 0x2d, 0xd2, 0x3c, 0xac, 0x6a, 0xcd, 0x8e, 0x4c, 0x1e, 0x23, 0xc6,
+                0x71, 0x1d, 0x10, 0xcb, 0x61, 0x9b, 0xe8, 0xcb, 0xc8, 0x48, 0xb2, 0x7d, 0xf5, 0x0d, 0xa5, 0x6f,
+                0x37, 0x2c, 0x98, 0xa6, 0x78, 0xa3, 0x87, 0x39, 0xd4, 0x19, 0x4e, 0x22, 0xb5, 0x7c, 0x09, 0xed,
+                0xbe, 0x06, 0x33, 0x88, 0x57, 0xd8, 0x23, 0x25, 0xbb, 0xb4, 0xa0, 0xf2, 0xbb, 0x72, 0xa0, 0x96,
+                0x25, 0xb7, 0xa1, 0x45, 0x34, 0x8c, 0x8d, 0x9d, 0x5c, 0x8f, 0xb1, 0x14, 0x88, 0x1d, 0x5c, 0xdf,
+                0x7f, 0xfb, 0xa2, 0xae, 0x9c, 0x3a, 0x02, 0x92, 0xeb, 0x01, 0xf4, 0x0a, 0x55, 0x32, 0xb3, 0xdb,
+                0xaa, 0xb2, 0x00, 0x42, 0xb4, 0xd7, 0x9b, 0x55, 0x64, 0x26, 0x07, 0xe9, 0x2c, 0x55, 0x88, 0xd2,
+                0xea, 0x00, 0x00, 0x00, 0x00, 0x02, 0x83, 0xff, 0xff, 0xfd, 0x7c, 0x00, 0x00, 0x00, 0x01, 0x41,
+                0x4d, 0x4c, 0x56, 0x86, 0x00, 0x40, 0x92, 0xe1, 0xa1, 0x56, 0x00, 0x00, 0x0c, 0x70, 0x00, 0x00,
+                0x7b, 0xfb, 0xea, 0x59, 0x62, 0x8e, 0xaa, 0x5d, 0x87, 0x99, 0x92, 0xc1, 0xf4, 0x5b, 0xb2, 0xe7,
+                0x85, 0x2b, 0xe7, 0x5d, 0x58, 0x57, 0xe1, 0x4e, 0xd8, 0xf4, 0xd2, 0x03, 0x54, 0x5a, 0x28, 0x1a,
+                0x87, 0x5e, 0x10, 0xbb, 0x88, 0x87, 0x33, 0xba, 0x96, 0x1d, 0x8b, 0x44, 0x44, 0x27, 0x97, 0xaa,
+                0x34, 0xe0, 0x4f, 0x25, 0x70, 0x75, 0x42, 0x8c, 0x03, 0x31, 0x68, 0xf4, 0x81, 0xc3, 0xb7, 0x6f,
+                0x49, 0xf6, 0x75, 0xa0, 0x46, 0x0c, 0x6b, 0xb7, 0x62, 0x82, 0xda, 0xb5, 0xbf, 0x7a, 0xb7, 0xd6,
+                0x3b, 0x77, 0x71, 0x44, 0xfd, 0xc2, 0xad, 0x8d, 0xfb, 0xba, 0xad, 0xab, 0xd8, 0x5c, 0x47, 0x1e,
+                0x62, 0x4f, 0xfc, 0x8b, 0x02, 0xe6, 0x1a, 0x68, 0x88, 0xcc, 0x07, 0xb1, 0x56, 0xb8, 0x97, 0xba,
+                0xd8, 0x66, 0x7e, 0xf1, 0xc0, 0x97, 0x20, 0xdf, 0x1d, 0x3f, 0xbc, 0xff, 0x59, 0xd5, 0xc8, 0xd6,
+                0xec, 0xfe, 0xe1, 0xd8, 0x09, 0x10, 0xc4, 0x9d, 0xbf, 0x70, 0x6e, 0xe8, 0xeb, 0xa3, 0xef, 0xee,
+                0xf4, 0x40, 0x70, 0x73, 0xe0, 0x16, 0x9c, 0x31, 0x3d, 0x86, 0xc8, 0x08, 0x37, 0x30, 0x4c, 0x80,
+                0xf5, 0x6d, 0x57, 0x74, 0xb9, 0xd7, 0xda, 0x11, 0xa2, 0xd1, 0x1c, 0xf8, 0x04, 0xc0, 0xbc, 0x2e,
+                0x51, 0x0e, 0xbb, 0xe8, 0x4b, 0x4e, 0xf8, 0xc2, 0xb1, 0xa4, 0x00, 0x93, 0xd1, 0x3f, 0xa1, 0x04,
+                0x98, 0xcc, 0x12, 0xbf, 0x72, 0xa3, 0x2d, 0x27, 0x02, 0x17, 0x36, 0xc9, 0x90, 0x27, 0x91, 0xb4,
+                0xe0, 0x40, 0xe0, 0xd4, 0x1d, 0xd1, 0x6b, 0xc0, 0x55, 0x9a, 0xc6, 0xdf, 0xed, 0x7c, 0x12, 0xc6,
+                0x3a, 0xda, 0x65, 0xf8, 0xd3, 0x3b, 0x14, 0x02, 0xc4, 0x80, 0x9e, 0x9c, 0xed, 0x6c, 0xee, 0x1f,
+                0x09, 0x9b, 0x32, 0x6b, 0xd7, 0x04, 0x06, 0xd4, 0xec, 0xcc, 0xf9, 0xf8, 0x06, 0xd7, 0xf7, 0x5a,
+                0xfa, 0x24, 0x72, 0x8b, 0xd3, 0xfc, 0x2d, 0x9e, 0xea, 0x7a, 0xc2, 0x4c, 0xfc, 0xd2, 0xd0, 0x0f,
+                0x49, 0x5a, 0x34, 0xf3, 0x25, 0xde, 0xaa, 0x99, 0xad, 0xba, 0x55, 0xcd, 0xa9, 0x5d, 0x15, 0x85,
+                0xc1, 0x3f, 0x5a, 0x7c, 0x00, 0xe6, 0x26, 0x9a, 0x99, 0xa5, 0xad, 0x8f, 0xe3, 0x6a, 0xbc, 0xb4,
+                0xae, 0x28, 0xa6, 0x9f, 0x66, 0xd2, 0x92, 0xb8, 0x9a, 0x16, 0x54, 0x8b, 0x9e, 0x50, 0xd6, 0xde,
+                0xbd, 0x63, 0x75, 0x5c, 0x46, 0x69, 0xe1, 0x84, 0xa6, 0x8a, 0x78, 0x18, 0x9d, 0xbc, 0x3f, 0xeb,
+                0xe9, 0x9f, 0xe2, 0x27, 0xd8, 0x1d, 0x99, 0x6e, 0xc4, 0x55, 0x2c, 0x48, 0x57, 0x84, 0xf0, 0x86,
+                0x6c, 0x65, 0x05, 0x3c, 0xcb, 0x56, 0x0e, 0x68, 0xed, 0x71, 0x70, 0x98, 0x74, 0x6d, 0x2f, 0xf7,
+                0xcf, 0x30, 0x2d, 0x48, 0x65, 0x9f, 0x06, 0xcc, 0x24, 0xe6, 0x3a, 0x3a, 0x36, 0x8d, 0xd0, 0xcd,
+                0x2c, 0xd3, 0x63, 0x52, 0x83, 0x54, 0xf2, 0xe9, 0x7b, 0x89, 0x62, 0xe5, 0x3a, 0x3f, 0x54, 0xa4,
+                0x2f, 0x08, 0xff, 0xae, 0x20, 0xf1, 0xae, 0xb6, 0xb2, 0xb0, 0x7b, 0xbc, 0x50, 0xda, 0xd9, 0xb7,
+                0xed, 0x9b, 0xf0, 0xc7, 0xd2, 0x9d, 0xb9, 0x29, 0x9e, 0x11, 0x99, 0x4f, 0xa0, 0xce, 0x21, 0x47,
+                0x2e, 0x79, 0x60, 0x1c, 0x17, 0x54, 0xbd, 0x54, 0xa4, 0x6f, 0xcb, 0x77, 0x39, 0x9b, 0x20, 0xc5,
+                0x6b, 0x92, 0xae, 0x6d, 0x8b, 0xce, 0xb2, 0x1f, 0x75, 0x7e, 0x7a, 0x55, 0x9f, 0x42, 0xa4, 0xb1,
+                0x02, 0xf2, 0xbc, 0x5a, 0x5b, 0x9c, 0xe2, 0xf1, 0x91, 0x93, 0x2f, 0x48, 0xeb, 0x46, 0x9c, 0xa1,
+                0xa0, 0x27, 0x32, 0xde, 0xa3, 0x00, 0xfa, 0x6a, 0x1d, 0x7c, 0x56, 0x40, 0x37, 0xa7, 0xec, 0x1d,
+                0xff, 0x12, 0x9a, 0xc4, 0xe8, 0xce, 0xfc, 0x57, 0xae, 0xeb, 0x17, 0x09, 0xe9, 0xab, 0xb8, 0x37,
+                0x61, 0x30, 0x6d, 0xd4, 0xad, 0xa2, 0x47, 0xc1, 0x97, 0xd4, 0xd5, 0x94, 0x1a, 0x39, 0x3e, 0x45,
+                0x43, 0x47, 0x8a, 0x67, 0xf4, 0x12, 0x5d, 0x52, 0xf1, 0xbf, 0x53, 0x55, 0x69, 0x82, 0x0f, 0x0a,
+                0x05, 0xa5, 0x79, 0x57, 0xd4, 0xd5, 0x12, 0x26, 0x7e, 0xa5, 0xe6, 0x3c, 0xc1, 0x09, 0x31, 0x28,
+                0x3e, 0x5c, 0xea, 0x0e, 0x95, 0xb3, 0x22, 0xc0, 0x0d, 0x37, 0x3f, 0x2b, 0x19, 0xc4, 0xe0, 0xab,
+                0x66, 0xc9, 0x40, 0x02, 0x77, 0x6e, 0x99, 0x69, 0xdd, 0x70, 0x67, 0x83, 0xc9, 0x28, 0xe4, 0xb1,
+                0x24, 0xf9, 0xb3, 0x5b, 0x43, 0x54, 0xa0, 0xac, 0x6f, 0x97, 0x8e, 0x5e, 0x22, 0x81, 0x4b, 0xb8,
+                0xcb, 0x68, 0x3d, 0xda, 0xa1, 0xde, 0xa1, 0x67, 0x2a, 0x1b, 0x79, 0xc1, 0xdd, 0x70, 0x5c, 0x0a,
+                0xd4, 0x00, 0x00, 0x00, 0x02, 0x83, 0xff, 0xff, 0xfd, 0x7c, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d,
+                0x4c, 0x56, 0x86, 0x00, 0x40, 0x92, 0xe1, 0x91, 0x56, 0x00, 0x00, 0x0c, 0x70, 0x00, 0x00, 0x7f,
+                0xd3, 0x15, 0x8a, 0x8a, 0xcd, 0xb2, 0xee, 0x76, 0x8b, 0xe2, 0x04, 0x22, 0xe9, 0x74, 0xee, 0x1d,
+                0x6e, 0x7f, 0xa1, 0x7f, 0x27, 0x4e, 0xa8, 0x2c, 0x9a, 0xb9, 0x53, 0x00, 0x68, 0xcc, 0xf9, 0xb3,
+                0xf8, 0xb6, 0xea, 0xfc, 0xe9, 0x7b, 0xac, 0x1f, 0x96, 0x4e, 0x4f, 0xdc, 0x18, 0x70, 0xfc, 0x16,
+                0x66, 0x5d, 0x74, 0x5b, 0xe6, 0x5e, 0x28, 0x76, 0xbe, 0xb8, 0xc8, 0xaf, 0x1d, 0x9a, 0xa4, 0x55,
+                0x26, 0x71, 0x80, 0x88, 0x5f, 0x0c, 0xbd, 0x88, 0xd5, 0x8d, 0x91, 0x54, 0x8f, 0xcb, 0xeb, 0x24,
+                0xb4, 0x39, 0x99, 0xaa, 0xf2, 0x0a, 0x90, 0xe4, 0x41, 0x69, 0xe8, 0xf4, 0xce, 0x21, 0x67, 0xcc,
+                0xdf, 0x86, 0x29, 0x47, 0x26, 0xf0, 0xf2, 0x5a, 0x81, 0x32, 0xe9, 0xc3, 0x86, 0x4d, 0xc9, 0xef,
+                0xd6, 0x77, 0x51, 0xcc, 0x6b, 0x79, 0x45, 0x9c, 0xda, 0x96, 0x07, 0xa5, 0x0d, 0x03, 0x04, 0x43,
+                0x07, 0x54, 0x56, 0xde, 0xb3, 0x6a, 0xf9, 0xbb, 0x3f, 0xf3, 0xf2, 0x8b, 0xb9, 0x2f, 0x98, 0x69,
+                0xc8, 0xd3, 0x50, 0x2c, 0x3d, 0xdd, 0xab, 0x5c, 0x8c, 0x56, 0xc7, 0x61, 0xaf, 0xbd, 0x55, 0xe1,
+                0x2e, 0xe2, 0x6f, 0x0f, 0x4b, 0x10, 0x07, 0xc1, 0x13, 0x14, 0xd6, 0x8a, 0xab, 0x6f, 0x9a, 0x52,
+                0x6a, 0x41, 0x91, 0x30, 0xf3, 0x45, 0xce, 0x47, 0xf0, 0x16, 0x90, 0xb3, 0x06, 0xc6, 0xf7, 0x23,
+                0x9c, 0x61, 0xad, 0xc6, 0x07, 0x5f, 0xef, 0x64, 0x2f, 0x73, 0x47, 0x4e, 0xe1, 0x23, 0xa7, 0xf6,
+                0xa8, 0x3a, 0x79, 0xa1, 0x5f, 0xd5, 0x6e, 0xdb, 0x40, 0x6b, 0x26, 0xb9, 0x7e, 0x15, 0xc1, 0xf1,
+                0x1b, 0xeb, 0x3c, 0x10, 0xbd, 0x53, 0xa6, 0x27, 0xdf, 0xb9, 0x8c, 0x09, 0xd2, 0x8d, 0x1d, 0x67,
+                0xfd, 0xfb, 0xee, 0x5c, 0x9b, 0x4b, 0xc7, 0x68, 0x08, 0x02, 0x5d, 0x3d, 0xf2, 0xab, 0x8f, 0xf9,
+                0x32, 0xac, 0x2c, 0x85, 0x14, 0x17, 0xae, 0x95, 0x7d, 0xea, 0x92, 0xf8, 0x45, 0x28, 0xa3, 0x84,
+                0x93, 0x7a, 0xe2, 0x03, 0x07, 0x2f, 0x80, 0x18, 0xc7, 0x4f, 0xf0, 0x23, 0xe8, 0x1f, 0x20, 0x25,
+                0x1d, 0xa3, 0x2b, 0x9b, 0xde, 0x0f, 0x35, 0x1b, 0x59, 0x93, 0x06, 0xab, 0x8a, 0xbf, 0x30, 0x04,
+                0xae, 0xfb, 0xfa, 0x65, 0x4f, 0xab, 0x65, 0xe1, 0x9c, 0x57, 0x4e, 0x2f, 0xd7, 0x37, 0xfc, 0x95,
+                0x64, 0xf4, 0x02, 0x84, 0xa0, 0x51, 0xae, 0xd4, 0x54, 0xff, 0xae, 0x16, 0x9d, 0xa5, 0x68, 0x94,
+                0x15, 0xf2, 0xe1, 0xca, 0x57, 0x80, 0x83, 0x89, 0xcf, 0xfe, 0x66, 0x73, 0x26, 0x0c, 0x8e, 0xdc,
+                0xad, 0x93, 0xa6, 0x98, 0x96, 0xf0, 0xe7, 0xcd, 0xeb, 0xc2, 0x78, 0x33, 0x05, 0x05, 0x98, 0x28,
+                0xf5, 0x81, 0xba, 0xb6, 0xe7, 0xa7, 0x41, 0x9c, 0xb9, 0x96, 0xf1, 0xa4, 0x13, 0xb1, 0xbc, 0xd8,
+                0x77, 0x1b, 0x98, 0x60, 0x35, 0x45, 0xb8, 0x54, 0x6c, 0x36, 0xb4, 0x38, 0xe2, 0xaa, 0xb9, 0x39,
+                0x99, 0xbc, 0x59, 0x65, 0xfe, 0x01, 0x21, 0x15, 0x65, 0x8d, 0x2c, 0x88, 0x08, 0x5f, 0x7f, 0x38,
+                0x73, 0x55, 0x7e, 0x3e, 0x06, 0x81, 0xf6, 0xa0, 0x5c, 0xa3, 0xfd, 0xce, 0xe2, 0x40, 0x42, 0xdf,
+                0x8a, 0x9e, 0x72, 0x13, 0xe6, 0xd1, 0x71, 0x4e, 0x1c, 0x96, 0x59, 0x0a, 0x5c, 0xeb, 0xc9, 0x79,
+                0x79, 0xc9, 0x5e, 0xfc, 0xd9, 0x65, 0xad, 0x55, 0x5f, 0x19, 0xd1, 0xe7, 0x20, 0x10, 0xe2, 0xb7,
+                0x54, 0x46, 0x96, 0x92, 0x64, 0x79, 0x85, 0xc9, 0xb9, 0xdb, 0x02, 0x4b, 0xb3, 0xc6, 0x2c, 0xf0,
+                0x0f, 0xc9, 0x2d, 0xa7, 0x8b, 0x32, 0x20, 0x30, 0xfd, 0xbd, 0x65, 0x1b, 0x86, 0xaf, 0x27, 0xc7,
+                0x3c, 0xb0, 0xdb, 0xd1, 0x60, 0x94, 0xc2, 0x99, 0xa7, 0x37, 0xfb, 0x6a, 0x92, 0x21, 0x22, 0x61,
+                0x7e, 0x59, 0xb1, 0x74, 0xe2, 0xcd, 0x98, 0x90, 0x2c, 0xf2, 0x48, 0x51, 0x3c, 0xec, 0xfa, 0xf7,
+                0x7c, 0xd1, 0xa1, 0x00, 0x98, 0x30, 0x33, 0x02, 0x6d, 0xf3, 0xfd, 0x2a, 0x92, 0x8a, 0x76, 0x55,
+                0x84, 0x99, 0x9d, 0xd1, 0x23, 0x80, 0x40, 0xde, 0x90, 0x0a, 0x57, 0xfe, 0x48, 0x05, 0x6e, 0x47,
+                0x51, 0xa6, 0xd4, 0x7e, 0xd0, 0x43, 0x6f, 0x61, 0x18, 0xea, 0x05, 0xe3, 0x66, 0x6e, 0xdc, 0xed,
+                0x48, 0x4d, 0x53, 0xfa, 0x3d, 0x27, 0xb6, 0xbb, 0x54, 0xb0, 0x14, 0xe7, 0xde, 0xb8, 0x02, 0xe2,
+                0xf2, 0x75, 0x2e, 0xee, 0x47, 0x2b, 0x9e, 0xe6, 0x8a, 0xb6, 0x77, 0x95, 0xbb, 0xf1, 0x67, 0x0f,
+                0x96, 0xbc, 0x06, 0x46, 0x0b, 0xa0, 0x4b, 0xef, 0x76, 0x84, 0x16, 0x14, 0x0c, 0x74, 0xd6, 0xf1,
+                0x00, 0x00, 0x00, 0x02, 0x7b, 0xff, 0xff, 0xfd, 0x84, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x4c,
+                0x56, 0x86, 0x00, 0x40, 0x92, 0xe1, 0x91, 0x56, 0x00, 0x00, 0x0c, 0x70, 0x00, 0x00, 0x7f, 0x76,
+                0x8b, 0xd1, 0xc9, 0x38, 0x2b, 0x3f, 0xac, 0xf0, 0xee, 0x99, 0x34, 0xcc, 0x6e, 0xcb, 0x35, 0x6b,
+                0xd1, 0xb6, 0x68, 0x0f, 0x76, 0x12, 0x2d, 0x32, 0x86, 0xce, 0x9b, 0x22, 0xaa, 0xe8, 0x2c, 0x54,
+                0xe3, 0x30, 0xf3, 0x0a, 0xbe, 0xbb, 0x1c, 0x43, 0x8a, 0x4f, 0x5c, 0x89, 0xd0, 0x18, 0x0b, 0x74,
+                0xc9, 0xf6, 0xe5, 0x16, 0xb8, 0xb5, 0x47, 0x23, 0x64, 0xb8, 0x38, 0xa8, 0x9d, 0xb8, 0x3f, 0xe5,
+                0xa3, 0x36, 0xd0, 0x62, 0x2a, 0xd7, 0x6e, 0x5b, 0xff, 0x4c, 0x4a, 0xc8, 0xfa, 0x76, 0xc3, 0xe1,
+                0x8c, 0x7b, 0xdd, 0xa8, 0xe8, 0x24, 0xbf, 0x2b, 0x9b, 0xcd, 0x6c, 0xa0, 0x82, 0x17, 0xef, 0x2c,
+                0xf4, 0xb2, 0x97, 0xee, 0x99, 0x29, 0xd7, 0x0e, 0x54, 0x6a, 0xfe, 0xe1, 0x88, 0x3a, 0x16, 0x9c,
+                0x1f, 0x1d, 0x91, 0xe4, 0x6f, 0xfc, 0xa4, 0x5a, 0xfd, 0x24, 0x57, 0x3d, 0x2d, 0x42, 0xb6, 0x64,
+                0xda, 0x55, 0xfd, 0x28, 0x5c, 0x93, 0x2b, 0x8c, 0xa0, 0x0e, 0x2b, 0x93, 0x42, 0x2a, 0xe1, 0xcd,
+                0xee, 0x10, 0xc1, 0x03, 0xdc, 0xa4, 0xc0, 0xf5, 0xf9, 0x7f, 0x33, 0xe2, 0xf4, 0x90, 0x27, 0x92,
+                0x11, 0x20, 0xa1, 0x14, 0x42, 0xe4, 0xff, 0x0d, 0x07, 0x28, 0x6e, 0xbc, 0x3b, 0xbc, 0xe8, 0x72,
+                0xe2, 0xe5, 0xbe, 0xa6, 0x27, 0x5b, 0x02, 0x5c, 0xcf, 0x9c, 0x09, 0x32, 0x25, 0xca, 0xf8, 0x03,
+                0x94, 0xbd, 0x5c, 0x6f, 0x41, 0xff, 0x6d, 0x29, 0x8e, 0xfa, 0x05, 0xfe, 0xf0, 0x42, 0x2e, 0xa8,
+                0xfa, 0x30, 0x4a, 0x22, 0x13, 0x21, 0x5e, 0xc5, 0xa0, 0x9e, 0xfe, 0xb2, 0x93, 0xb5, 0x6a, 0xb3,
+                0x44, 0xf7, 0x51, 0x22, 0xdf, 0x02, 0x01, 0x0a, 0x28, 0xd8, 0x9f, 0xae, 0xf0, 0x9e, 0x89, 0x82,
+                0x7b, 0x94, 0x3c, 0x50, 0x43, 0x5a, 0xc5, 0xbe, 0x43, 0x4e, 0x3e, 0xa3, 0xe0, 0x33, 0xa0, 0x99,
+                0x7c, 0x4e, 0x3b, 0x5a, 0x85, 0x06, 0x94, 0xc7, 0xfd, 0xe8, 0x6a, 0x7d, 0xa2, 0x8b, 0x4d, 0x14,
+                0xd9, 0xd8, 0xbf, 0x86, 0x53, 0xc0, 0xa0, 0x3d, 0xe3, 0x0f, 0x85, 0xa6, 0xe0, 0xc2, 0xc3, 0x73,
+                0x6e, 0x27, 0xff, 0xbe, 0x30, 0x53, 0x3f, 0x76, 0x2d, 0x85, 0xb9, 0xf4, 0x39, 0x51, 0xb7, 0xae,
+                0x4c, 0x08, 0x08, 0x5b, 0xd8, 0xe1, 0x6d, 0x8f, 0x01, 0x0f, 0x98, 0x70, 0xdb, 0x49, 0x21, 0x18,
+                0x15, 0x4e, 0xce, 0xc4, 0xb6, 0xd5, 0xa0, 0x72, 0xc6, 0x4b, 0x6b, 0x82, 0x8b, 0x7b, 0x85, 0x39,
+                0xdb, 0x97, 0xf2, 0xd4, 0x03, 0x07, 0x44, 0xc5, 0xbd, 0x9d, 0xc3, 0xb6, 0x86, 0x76, 0xca, 0xd1,
+                0xd6, 0x5a, 0xf8, 0x41, 0x68, 0xe3, 0xa8, 0x5a, 0xa2, 0xe8, 0x0d, 0xf8, 0x3e, 0xcd, 0x28, 0x7d,
+                0x5f, 0x9c, 0x38, 0x4d, 0x7c, 0x63, 0xd3, 0x8e, 0xa7, 0x5a, 0xa7, 0x21, 0x1f, 0xc4, 0xde, 0x64,
+                0xf0, 0x7f, 0x05, 0xf5, 0xa8, 0xdd, 0x6c, 0xd5, 0x4f, 0x8c, 0x14, 0x65, 0x9b, 0xe9, 0x3e, 0xcb,
+                0x0c, 0xf4, 0x94, 0x3b, 0x12, 0xb1, 0xec, 0xf5, 0x15, 0x22, 0x1e, 0x47, 0x02, 0x6d, 0xa4, 0x8f,
+                0x08, 0xe1, 0x84, 0x2a, 0x26, 0xec, 0x95, 0x29, 0x7a, 0xf3, 0xcd, 0x48, 0x61, 0x65, 0xb0, 0xff,
+                0xba, 0x0e, 0xd8, 0x56, 0x6b, 0x5f, 0x5e, 0xdd, 0xdc, 0x43, 0x12, 0x54, 0x1f, 0xa6, 0xea, 0x27,
+                0x5d, 0x97, 0x5c, 0xfe, 0xd6, 0xb3, 0xaa, 0xc1, 0xd6, 0x37, 0x19, 0xdc, 0xa8, 0xfc, 0x76, 0xdb,
+                0x81, 0x54, 0x10, 0xa6, 0xb7, 0xc1, 0xb1, 0xb9, 0x42, 0x54, 0xb8, 0x69, 0xd6, 0x5b, 0xdf, 0x8c,
+                0xd2, 0x85, 0x4b, 0xdf, 0x80, 0x36, 0x1e, 0x31, 0x4d, 0xa1, 0x1a, 0x56, 0xb8, 0x2a, 0x6c, 0x59,
+                0x33, 0x11, 0x1c, 0xe6, 0x36, 0x1b, 0xba, 0x6b, 0x55, 0x82, 0x8c, 0x69, 0x89, 0xe2, 0x7a, 0xf6,
+                0x95, 0x53, 0xd9, 0x29, 0xd0, 0x06, 0xfb, 0x38, 0xf2, 0x38, 0xf6, 0x12, 0x8e, 0x54, 0x16, 0xd8,
+                0x3b, 0xfa, 0x5a, 0x7e, 0x63, 0x01, 0xd7, 0x98, 0x7e, 0x74, 0xdf, 0x47, 0xc7, 0x84, 0x72, 0x2d,
+                0x5d, 0x0a, 0xff, 0xac, 0xdf, 0x7f, 0x31, 0xa7, 0x6b, 0xf8, 0x63, 0x95, 0x4a, 0xfe, 0x81, 0x06,
+                0x3a, 0x23, 0xba, 0x30, 0x9d, 0x2f, 0x00, 0x27, 0xd7, 0x54, 0xa3, 0xbd, 0xfa, 0x9f, 0xc8, 0x35,
+                0x1d, 0x1f, 0x63, 0x1c, 0xe7, 0x67, 0xf2, 0xf4, 0xf2, 0x47, 0x7d, 0x9d, 0xce, 0xa5, 0xe6, 0x28,
+                0x7d, 0x93, 0x5a, 0x85, 0xdc, 0x51, 0x4c, 0x63, 0x52, 0xfe, 0xe9, 0x46, 0x87, 0x42, 0x6f, 0xe2,
+                0x59, 0x85, 0xb2, 0x51, 0xda, 0x55, 0x40, 0x00, 0x00, 0x00, 0x02, 0xf5, 0xff, 0xff, 0xfd, 0x0a,
+                0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x4c, 0x56, 0x86, 0x00, 0x40, 0x92, 0xe1, 0x41, 0x56, 0x00,
+                0x00, 0x0c, 0x70, 0x00, 0x00, 0x7f, 0x5f, 0x5a, 0x76, 0xc1, 0xa8, 0xce, 0xa1, 0x96, 0xe3, 0x34,
+                0xa0, 0x35, 0x06, 0xd0, 0xd8, 0x43, 0x47, 0xf4, 0xe8, 0xed, 0xe6, 0xea, 0x69, 0xfa, 0xaa, 0x31,
+                0xab, 0x53, 0x27, 0x82, 0x67, 0xc4, 0x30, 0xff, 0x82, 0xcf, 0xaa, 0xb8, 0x66, 0x4d, 0xdb, 0xd9,
+                0xe4, 0xf1, 0x55, 0x11, 0x36, 0x9f, 0xa8, 0x11, 0x6a, 0xcb, 0x50, 0xdd, 0x95, 0x67, 0xf5, 0xba,
+                0x2c, 0x69, 0x04, 0xb0, 0xb0, 0x11, 0xad, 0x21, 0xc6, 0xec, 0x3e, 0x2e, 0xe5, 0x28, 0x7f, 0x53,
+                0x06, 0xd2, 0x5d, 0x66, 0x5e, 0x81, 0x21, 0x13, 0xa7, 0x62, 0x12, 0x84, 0x3d, 0x1e, 0xcc, 0x49,
+                0x1c, 0x99, 0xb4, 0x33, 0xcf, 0xfb, 0xb1, 0x41, 0x5e, 0x88, 0x26, 0x2f, 0xd3, 0xbf, 0xcf, 0x2e,
+                0x9d, 0x1c, 0x81, 0x9d, 0xbe, 0xcc, 0x8c, 0x0d, 0x5b, 0xd0, 0xb2, 0xb7, 0xc0, 0xb8, 0x53, 0xb0,
+                0x7d, 0x3a, 0xb7, 0x63, 0x66, 0xa2, 0xc0, 0xd8, 0x08, 0x76, 0x26, 0xc7, 0xe0, 0x85, 0x98, 0x2b,
+                0x39, 0xa6, 0x65, 0xe5, 0x1c, 0xad, 0xe4, 0x9e, 0x82, 0xa4, 0x7c, 0x71, 0x31, 0x07, 0xca, 0xec,
+                0x47, 0xb4, 0x75, 0x3e, 0x2b, 0x65, 0x0c, 0x9b, 0x1c, 0x2d, 0xcc, 0xa3, 0x40, 0x40, 0xd6, 0xdd,
+                0x21, 0xa1, 0x10, 0x76, 0x35, 0x13, 0xb3, 0x1a, 0xd3, 0x43, 0x87, 0xf2, 0xbc, 0x28, 0xde, 0x82,
+                0x59, 0x4c, 0x3d, 0xad, 0x33, 0x8d, 0xc5, 0x96, 0x25, 0x86, 0xa3, 0x33, 0x95, 0x36, 0x85, 0x08,
+                0xb1, 0x95, 0xd5, 0xb6, 0x5a, 0xaa, 0xb3, 0x77, 0xf9, 0xbd, 0xd0, 0xb4, 0x4a, 0xc7, 0x7c, 0x00,
+                0x38, 0x72, 0x90, 0x37, 0xc8, 0x40, 0x00, 0xc8, 0xbb, 0x51, 0x0e, 0x77, 0x71, 0x48, 0x4f, 0xf9,
+                0x92, 0x54, 0x01, 0xc9, 0x02, 0xe2, 0x36, 0xac, 0x41, 0x54, 0x64, 0xcd, 0xc5, 0x16, 0x64, 0x2e,
+                0x6c, 0x8e, 0x63, 0xe8, 0xea, 0x48, 0x61, 0x74, 0x6a, 0xcb, 0xb6, 0x11, 0x97, 0x19, 0x68, 0xc3,
+                0x86, 0x18, 0x8e, 0x1e, 0x28, 0x21, 0xe7, 0xa3, 0x4c, 0xed, 0x23, 0x3f, 0xbc, 0x26, 0xe5, 0x92,
+                0xda, 0xc1, 0x9b, 0x63, 0xab, 0xda, 0xd9, 0xa3, 0x5a, 0x17, 0x48, 0xbd, 0x89, 0xd2, 0x3e, 0x14,
+                0x3b, 0x1b, 0xc0, 0x6d, 0xe7, 0x3d, 0x86, 0x85, 0x45, 0xe2, 0x9e, 0x7f, 0xff, 0x63, 0x07, 0xe6,
+                0x12, 0x23, 0xa9, 0x1c, 0x53, 0x24, 0xc8, 0xe1, 0x89, 0xee, 0xe7, 0x72, 0x07, 0x04, 0x11, 0x8c,
+                0xcb, 0x66, 0x61, 0x23, 0x6d, 0x68, 0xe2, 0xaa, 0xb7, 0xf8, 0xb6, 0xd8, 0xb4, 0x6c, 0x13, 0xc4,
+                0xd6, 0xba, 0x08, 0xa0, 0x05, 0x23, 0xdc, 0xad, 0xed, 0xff, 0x6d, 0x1b, 0x03, 0x3e, 0xf2, 0x1c,
+                0xf6, 0xdd, 0x2a, 0xf1, 0x18, 0x76, 0x2e, 0x82, 0x38, 0xa4, 0xb7, 0x3e, 0xab, 0x74, 0x24, 0x79,
+                0x83, 0x0b, 0x2e, 0x8e, 0x0b, 0x19, 0x05, 0x52, 0x20, 0x78, 0x9a, 0xe8, 0x57, 0x77, 0xde, 0xd5,
+                0x36, 0xab, 0x60, 0x2b, 0xd5, 0x58, 0x6b, 0xf8, 0x64, 0xdf, 0xeb, 0x52, 0xad, 0x4b, 0xe5, 0x8b,
+                0x05, 0x6a, 0x90, 0xcc, 0x72, 0x8a, 0x3a, 0x95, 0xd0, 0x31, 0xa5, 0x75, 0x3a, 0xdd, 0x08, 0xf5,
+                0xd5, 0x3f, 0x76, 0x9e, 0x29, 0x7d, 0x4e, 0xb7, 0x93, 0x75, 0xc3, 0xd5, 0x38, 0xdf, 0x97, 0x7c,
+                0xf0, 0x15, 0x4a, 0x5c, 0x52, 0x64, 0x3a, 0xf6, 0x1e, 0x26, 0x2f, 0xc6, 0xc8, 0xa3, 0x5a, 0x9f,
+                0x40, 0x53, 0x7a, 0x4b, 0x5c, 0x94, 0xe2, 0x79, 0x07, 0x23, 0x06, 0x3e, 0xe5, 0xee, 0x4f, 0xed,
+                0x0f, 0x37, 0x19, 0xd8, 0x84, 0xdb, 0x02, 0x69, 0x20, 0x57, 0x4d, 0x08, 0x81, 0xf9, 0x44, 0x13,
+                0x41, 0x02, 0x79, 0x4b, 0x3f, 0xc9, 0x07, 0x16, 0xe2, 0xb1, 0x73, 0x43, 0x9d, 0x04, 0xea, 0x8c,
+                0xda, 0x4f, 0x85, 0x30, 0x12, 0xc4, 0x87, 0xb4, 0x18, 0x0a, 0x18, 0x32, 0x0c, 0x77, 0xc4, 0x1e,
+                0xa2, 0x23, 0xfa, 0xcf, 0xbd, 0x8b, 0x35, 0xf4, 0x4c, 0x4e, 0x75, 0x1a, 0x80, 0xf9, 0x2c, 0xc5,
+                0x0b, 0x81, 0x7a, 0x40, 0x36, 0xa0, 0x58, 0x86, 0xf3, 0xdd, 0x2d, 0x71, 0xc7, 0x8f, 0x05, 0xd0,
+                0x81, 0xf2, 0xb9, 0xb2, 0x7e, 0xd9, 0x65, 0x73, 0x4f, 0x8d, 0x1c, 0xed, 0x09, 0x9b, 0xcd, 0xdd,
+                0xdd, 0x9a, 0xa0, 0x22, 0x5c, 0x5b, 0xc5, 0xf5, 0xda, 0x8d, 0x01, 0x87, 0x8e, 0x01, 0xe3, 0x12,
+                0x5c, 0xb2, 0x23, 0x2a, 0x94, 0x65, 0xa6, 0x9a, 0x87, 0xf8, 0x63, 0x5f, 0x4c, 0xf0, 0x18, 0xe2,
+                0x0c, 0xb8, 0x8d, 0xdc, 0x4d, 0x7c, 0x50, 0xa2, 0xe1, 0x87, 0x49, 0x86, 0xb4, 0x38, 0xec, 0xd3,
+                0x5d, 0x22, 0x27, 0x42, 0xdc, 0xae, 0x8b, 0x7f, 0xbe, 0x4e, 0x1d, 0xad, 0x06, 0xc9, 0xd0, 0x98,
+                0x1f, 0x67, 0x2a, 0x22, 0x19, 0x90, 0xbb, 0x8f, 0xef, 0x42, 0x23, 0xc1, 0xd2, 0x51, 0xd1, 0x9c,
+                0x5b, 0xa0, 0x3a, 0x56, 0xae, 0x94, 0x4e, 0x0c, 0x17, 0x5e, 0x82, 0xe7, 0x21, 0xfd, 0x0e, 0xa6,
+                0x66, 0xb7, 0x8e, 0x9c, 0x8d, 0x4b, 0x02, 0x63, 0xdf, 0x1c, 0x7a, 0x0c, 0xd9, 0xca, 0x24, 0xc5,
+                0x1d, 0xb3, 0x29, 0xff, 0x48, 0x16, 0x48, 0x3d, 0x75, 0xd2, 0xb9, 0x44, 0x00, 0xdc, 0x3e, 0xcb,
+                0x37, 0xd9, 0xee, 0x16, 0xce, 0xb7, 0x50, 0x10, 0xad, 0xa8, 0x1f, 0xa0, 0xdb, 0x2f, 0x57, 0xd1,
+                0xb6, 0x44, 0x87, 0x00, 0x79, 0xc2, 0x25, 0x03, 0xa8, 0x7a, 0x94, 0xea, 0x02, 0x6b, 0x56, 0x6c,
+                0x1c, 0x77, 0x35, 0xd8, 0x85, 0x82, 0xbb, 0x6e, 0x80, 0x00, 0x00, 0x03, 0x2a, 0xff, 0xff, 0xfc,
+                0xd5, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x4c, 0x56, 0x86, 0x00, 0x40, 0x92, 0xe1, 0x81, 0x56,
+                0x00, 0x00, 0x14, 0x70, 0x96, 0xc0, 0x00, 0x00, 0x7f, 0xfa, 0x45, 0x6a, 0x6e, 0xe1, 0x2e, 0x61,
+                0x4a, 0x49, 0x88, 0x35, 0x59, 0x20, 0x91, 0xb6, 0x0d, 0xe2, 0xdf, 0xa8, 0xab, 0xf2, 0xb1, 0xb8,
+                0xf6, 0x9c, 0x9e, 0xc6, 0x50, 0x06, 0xec, 0x2f, 0x9a, 0x9e, 0x91, 0x94, 0x36, 0x4d, 0x13, 0x75,
+                0xf0, 0x4e, 0x63, 0xdc, 0x85, 0xa1, 0xdc, 0x3f, 0x09, 0x4a, 0x4b, 0xd4, 0x08, 0x70, 0x94, 0xc9,
+                0x73, 0x5b, 0x50, 0x71, 0xa3, 0x32, 0x65, 0xe6, 0x9e, 0xe5, 0xd7, 0xc5, 0x4d, 0xa5, 0x02, 0x5a,
+                0x00, 0x75, 0xd9, 0x80, 0xc9, 0x95, 0x79, 0x47, 0xb1, 0x30, 0xac, 0x8b, 0xf0, 0x3c, 0xd1, 0x57,
+                0xe1, 0xf3, 0x6f, 0x39, 0xe0, 0x5c, 0x6c, 0x89, 0x7c, 0x80, 0x78, 0x32, 0x0e, 0x2a, 0x95, 0xf0,
+                0x52, 0x88, 0x63, 0x30, 0xfc, 0x2f, 0xe2, 0x2d, 0x0a, 0xb6, 0x1e, 0xa4, 0xd5, 0x59, 0x32, 0x99,
+                0x82, 0xc4, 0x2c, 0x77, 0x89, 0x5d, 0x28, 0xab, 0x0f, 0x07, 0xed, 0xa3, 0x02, 0xc2, 0x0c, 0x95,
+                0x45, 0xdc, 0x0b, 0x2e, 0xa6, 0x96, 0x1d, 0x2a, 0x36, 0x90, 0xa9, 0x03, 0xcd, 0x09, 0x2e, 0xc9,
+                0x95, 0x28, 0x73, 0xf2, 0x1b, 0x2b, 0x3a, 0x5e, 0x66, 0xf0, 0xf8, 0x50, 0xac, 0xf5, 0x23, 0x98,
+                0xa0, 0xb2, 0xc0, 0xe7, 0x0b, 0xc4, 0x93, 0x97, 0x0a, 0xbe, 0x83, 0x82, 0x56, 0x4c, 0xa9, 0xd9,
+                0x32, 0x0f, 0x88, 0xc5, 0xd8, 0x30, 0xac, 0x6f, 0x92, 0x42, 0x94, 0x64, 0xb1, 0x33, 0x95, 0x27,
+                0x0b, 0x3a, 0x69, 0x4a, 0xbd, 0x60, 0x75, 0x9d, 0xb5, 0xc5, 0x82, 0x15, 0xa7, 0x0d, 0x27, 0xe9,
+                0x5b, 0xf0, 0x1e, 0x40, 0x6c, 0x6b, 0x6d, 0x48, 0xff, 0x77, 0x4e, 0xfc, 0x58, 0x33, 0xc0, 0x00,
+                0x58, 0x62, 0xfc, 0xe3, 0x0e, 0xa2, 0xc5, 0xf7, 0xd9, 0x38, 0x5d, 0xbb, 0x80, 0x4b, 0x1d, 0x36,
+                0x3d, 0x63, 0xf0, 0x3c, 0xaa, 0x83, 0x9f, 0x12, 0x7b, 0x48, 0x98, 0xad, 0x67, 0xda, 0x18, 0x4a,
+                0x4e, 0x79, 0x7c, 0xd9, 0xb9, 0xda, 0x2d, 0x32, 0xe3, 0x6a, 0x6b, 0x5c, 0xf4, 0xbb, 0xfe, 0x52,
+                0x3e, 0xee, 0xe6, 0x37, 0xc3, 0x10, 0xfc, 0xd5, 0xf2, 0x7d, 0xca, 0xef, 0x60, 0x25, 0xa0, 0x0e,
+                0x3e, 0xe2, 0xb3, 0x26, 0xba, 0xac, 0xea, 0x87, 0x66, 0xd8, 0xa6, 0xe6, 0x2d, 0x3b, 0x77, 0x25,
+                0xe2, 0x84, 0x32, 0x85, 0x27, 0x7d, 0x20, 0x97, 0xd5, 0x5c, 0x49, 0x71, 0x16, 0x95, 0x10, 0x30,
+                0x27, 0x67, 0xa3, 0xd4, 0x5e, 0x5a, 0x8c, 0xcf, 0x56, 0x37, 0xa9, 0x04, 0xb1, 0xec, 0xd8, 0x69,
+                0x90, 0xca, 0x37, 0x0d, 0x4f, 0x82, 0x91, 0x58, 0x0e, 0xf6, 0xfe, 0x84, 0xa5, 0x7b, 0xa8, 0xac,
+                0x99, 0x23, 0x01, 0xa6, 0x37, 0x8a, 0x50, 0x0e, 0x27, 0x47, 0x96, 0x37, 0xb6, 0x13, 0x47, 0xb1,
+                0x6f, 0xe9, 0xb1, 0xeb, 0xe6, 0x73, 0x6b, 0xf2, 0xd8, 0x5a, 0x3c, 0x55, 0xb4, 0x87, 0x3f, 0x1c,
+                0x96, 0x94, 0x84, 0xd9, 0x3d, 0x6f, 0x51, 0xc6, 0x06, 0xc6, 0x40, 0x5f, 0xde, 0x9a, 0x4a, 0x72,
+                0x9b, 0x8d, 0x3e, 0x1e, 0x1d, 0x7d, 0xb7, 0x46, 0x90, 0x48, 0x7b, 0x30, 0x38, 0xef, 0x6b, 0x02,
+                0x92, 0x10, 0x94, 0x81, 0x15, 0x66, 0x9b, 0xc3, 0xb0, 0x62, 0xab, 0xd6, 0x6c, 0xd8, 0xbd, 0x04,
+                0xad, 0x69, 0x93, 0xb9, 0x0a, 0xd2, 0xc5, 0x39, 0xb7, 0xde, 0x20, 0xa6, 0x27, 0x58, 0x0a, 0x79,
+                0x4a, 0xd5, 0xb0, 0xa9, 0x0a, 0x9f, 0x5d, 0x05, 0x20, 0xdd, 0x11, 0xa8, 0x8d, 0x82, 0xb3, 0xa9,
+                0x28, 0x5f, 0xb7, 0x13, 0xa6, 0x7d, 0xf5, 0x48, 0x09, 0x5c, 0xdb, 0x4d, 0x92, 0xb7, 0x68, 0x57,
+                0xd0, 0x0c, 0x94, 0x03, 0x99, 0xe4, 0xae, 0xb3, 0x5c, 0x9d, 0xe7, 0x73, 0x36, 0x16, 0x4e, 0x9f,
+                0xea, 0x2e, 0x8c, 0x83, 0xfd, 0x7a, 0xb4, 0xef, 0xdd, 0x5d, 0x60, 0x24, 0x70, 0xa4, 0x1d, 0x11,
+                0xd7, 0x44, 0xa1, 0x51, 0x18, 0x12, 0x78, 0x20, 0xf7, 0x22, 0x68, 0x32, 0xd8, 0x50, 0xd9, 0x73,
+                0xa2, 0x00, 0xc8, 0x52, 0xfe, 0xb6, 0x06, 0x03, 0x05, 0xd3, 0xa0, 0x47, 0xc4, 0x2c, 0x9a, 0x7f,
+                0x6a, 0x8f, 0xdc, 0x03, 0x7a, 0x4a, 0x96, 0x16, 0x86, 0x8b, 0x09, 0x73, 0x90, 0x22, 0x99, 0x9e,
+                0x79, 0x01, 0xf9, 0xe8, 0x26, 0xcb, 0x80, 0x7e, 0x2f, 0xf7, 0x92, 0x56, 0xfa, 0xa1, 0x22, 0xd3,
+                0x5d, 0x64, 0xa6, 0xe1, 0x14, 0x73, 0x3e, 0xa1, 0x67, 0x34, 0xc5, 0xc9, 0xac, 0xd4, 0xef, 0xd5,
+                0x09, 0xc4, 0x9d, 0x38, 0xa8, 0xe9, 0x7a, 0xdd, 0xfc, 0x3c, 0xb8, 0x5d, 0x84, 0x55, 0xcc, 0x75,
+                0xfd, 0x11, 0x12, 0x72, 0xe1, 0x46, 0x06, 0xd9, 0x8e, 0x6a, 0xee, 0xa3, 0xbd, 0xa3, 0xc5, 0x89,
+                0x9e, 0x9b, 0x56, 0xb2, 0xe7, 0xd6, 0x13, 0x44, 0x96, 0xbd, 0x01, 0xae, 0xbb, 0xf6, 0xe5, 0x56,
+                0x8d, 0xc0, 0x75, 0xd1, 0x7f, 0x85, 0x25, 0xb3, 0x98, 0xee, 0x97, 0xbf, 0xa2, 0x50, 0x47, 0x5a,
+                0x2b, 0x31, 0x32, 0x42, 0x08, 0x80, 0x72, 0x70, 0x52, 0xb9, 0xb9, 0x76, 0x71, 0x02, 0x18, 0x3b,
+                0xa0, 0xc3, 0xee, 0xbb, 0x44, 0x38, 0x4d, 0x25, 0xcb, 0xc9, 0x54, 0xfa, 0x26, 0x3c, 0xff, 0x5d,
+                0xac, 0xa7, 0x30, 0x56, 0xfd, 0x81, 0xd7, 0xbb, 0x7c, 0x44, 0xf1, 0x48, 0x51, 0xc0, 0x09, 0x00,
+                0x15, 0xdd, 0xf6, 0x4d, 0xbb, 0x59, 0x8a, 0x19, 0xb7, 0xab, 0x6b, 0x95, 0xb9, 0x46, 0x35, 0x03,
+                0x38, 0x95, 0x51, 0x42, 0x9c, 0x10, 0x31, 0x98, 0xfd, 0x84, 0x65, 0xf0, 0xa7, 0x67, 0x51, 0xea,
+                0x02, 0x20, 0xf8, 0xd0, 0xc1, 0x5a, 0x2c, 0xcc, 0x04, 0x1f, 0xf5, 0x2d, 0x58, 0x75, 0xe4, 0x56,
+                0xda, 0xc5, 0x90, 0xd2, 0xc3, 0x08, 0x64, 0x4e, 0x3f, 0x48, 0x60, 0xf3, 0xa6, 0x52, 0x66, 0xec,
+                0x77, 0xac, 0xf5, 0x0a, 0xae, 0xd0, 0x86, 0x9f, 0x28, 0x5f, 0x10, 0x95, 0xf3, 0xf4, 0x80, 0x00,
+                0x00, 0x03, 0x57, 0xff, 0xff, 0xfc, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x4c, 0x56, 0x86,
+                0x00, 0x40, 0x92, 0xe1, 0x61, 0x56, 0x00, 0x00, 0x0c, 0x70, 0x00, 0x00, 0x7f, 0xdf, 0xbf, 0x28,
+                0xf1, 0xca, 0x4e, 0xe8, 0xe2, 0x0b, 0xc7, 0x0d, 0xe4, 0x38, 0xbe, 0xfa, 0xb0, 0xd9, 0x0f, 0x0f,
+                0x63, 0x4f, 0x57, 0x00, 0x2b, 0x01, 0x35, 0x8f, 0xe1, 0x82, 0xaf, 0xbd, 0x69, 0x53, 0x0c, 0x2d,
+                0x6b, 0x68, 0xab, 0x4b, 0xf4, 0x60, 0xae, 0x73, 0x82, 0x1c, 0xe8, 0x95, 0x84, 0xed, 0xc2, 0x4e,
+                0x81, 0x9a, 0xe5, 0xf5, 0x8e, 0x3f, 0xe2, 0x55, 0x6a, 0x1e, 0x18, 0xb5, 0x1b, 0xf5, 0xea, 0x3f,
+                0x94, 0x82, 0xce, 0xbf, 0x35, 0xea, 0xd6, 0x8d, 0xb0, 0xaf, 0x9a, 0xf9, 0xdd, 0x4f, 0xff, 0xea,
+                0x07, 0x63, 0x93, 0x8d, 0x17, 0x65, 0x54, 0xd3, 0x1d, 0x45, 0x70, 0x68, 0xf2, 0xbc, 0x40, 0x84,
+                0xac, 0x8b, 0xff, 0x42, 0xa1, 0xa1, 0x29, 0x77, 0xc9, 0xc6, 0x81, 0xf9, 0x46, 0x45, 0xf7, 0x10,
+                0x50, 0x85, 0x67, 0xe6, 0xab, 0xd6, 0x1e, 0xe0, 0xa9, 0xeb, 0x1b, 0x9f, 0x1a, 0xe3, 0xc2, 0x41,
+                0x87, 0x71, 0x97, 0xc4, 0xc8, 0x6a, 0x2d, 0x64, 0xde, 0x4d, 0x02, 0x33, 0x42, 0xf7, 0xa9, 0xc2,
+                0x6e, 0x20, 0x7f, 0xf3, 0x1a, 0xd3, 0x33, 0x92, 0x3e, 0xd8, 0xe3, 0x77, 0x24, 0x5f, 0x70, 0x4d,
+                0x50, 0x0d, 0xc7, 0x18, 0x82, 0x82, 0x65, 0x1d, 0xe4, 0x49, 0x3e, 0x9f, 0x8e, 0xec, 0xd8, 0x29,
+                0x8c, 0xd4, 0x67, 0xbf, 0xe6, 0x51, 0xc3, 0x66, 0x74, 0x0f, 0x8a, 0x8c, 0xae, 0xd4, 0x8f, 0xab,
+                0xc3, 0x37, 0xee, 0xbe, 0xec, 0x81, 0x24, 0x77, 0x73, 0x4b, 0x84, 0x7e, 0x24, 0x62, 0x62, 0x6d,
+                0x79, 0x5d, 0x68, 0x64, 0x3f, 0x98, 0xdd, 0x7e, 0x82, 0xa8, 0x0f, 0x45, 0x0e, 0x93, 0xcd, 0x3d,
+                0x1d, 0x50, 0x16, 0xf5, 0xf5, 0x53, 0x29, 0xc0, 0xbb, 0xbb, 0xd6, 0x68, 0x87, 0x47, 0x5d, 0xda,
+                0xdf, 0xe4, 0x84, 0xfe, 0x40, 0x21, 0xd4, 0x0b, 0xf0, 0x3d, 0x19, 0x32, 0x03, 0x85, 0x1b, 0xa8,
+                0xa7, 0xea, 0x6f, 0xd9, 0xf5, 0x54, 0x58, 0xa3, 0xdc, 0xd7, 0xc0, 0xd5, 0x26, 0x2d, 0x39, 0xed,
+                0xcc, 0xb7, 0xfb, 0x36, 0xeb, 0xc6, 0x21, 0x58, 0xe4, 0x52, 0xea, 0x81, 0xa0, 0xa2, 0x63, 0x8a,
+                0xae, 0x0c, 0xb1, 0x1d, 0x79, 0xb9, 0xcd, 0x49, 0xb8, 0x31, 0x88, 0xe5, 0xe2, 0x5c, 0xbd, 0x7a,
+                0xbe, 0xcc, 0x74, 0x47, 0xe7, 0x65, 0x2d, 0x3d, 0xe9, 0x41, 0x64, 0x67, 0x01, 0x76, 0xc8, 0x41,
+                0x3b, 0x7e, 0xde, 0x3c, 0x65, 0xc6, 0x36, 0x8a, 0xeb, 0xe1, 0x77, 0xe8, 0x4b, 0x8f, 0x6b, 0xb0,
+                0x09, 0x8b, 0xc3, 0xf9, 0x9e, 0x9c, 0xdb, 0x26, 0x45, 0x00, 0x52, 0x4d, 0xc1, 0xfb, 0x33, 0x0f,
+                0xfc, 0x01, 0x31, 0xe1, 0x1a, 0x92, 0x5c, 0x57, 0x5d, 0xce, 0x65, 0x51, 0x16, 0x62, 0xa0, 0x4b,
+                0x4f, 0x86, 0xf4, 0x7d, 0xb4, 0x3c, 0x01, 0x19, 0x32, 0x7a, 0x88, 0x4a, 0x50, 0x96, 0xbd, 0x99,
+                0xe7, 0x3c, 0x9e, 0x38, 0xd8, 0x08, 0x42, 0x03, 0xae, 0xbc, 0x19, 0xf1, 0x2b, 0xe1, 0x7f, 0x2f,
+                0xd6, 0x1e, 0xda, 0x8f, 0xf2, 0x0e, 0x88, 0x9e, 0x07, 0x76, 0x6a, 0xd8, 0xde, 0xfa, 0xac, 0x08,
+                0x06, 0x34, 0x15, 0x18, 0xf4, 0x09, 0x47, 0x4e, 0x76, 0x91, 0xfc, 0x53, 0x03, 0xed, 0xc7, 0x53,
+                0x9e, 0xbc, 0xc7, 0x5e, 0x17, 0xd4, 0x18, 0x29, 0x04, 0xb6, 0xe9, 0x57, 0x97, 0x5a, 0x36, 0x61,
+                0xf7, 0x3a, 0x47, 0x62, 0x24, 0xb8, 0x53, 0x44, 0x41, 0x22, 0xb8, 0x4d, 0x75, 0x89, 0xe2, 0xce,
+                0x01, 0x3a, 0xce, 0x33, 0xd0, 0xa6, 0x18, 0xd4, 0x3e, 0x51, 0x02, 0xbc, 0x02, 0x01, 0x26, 0x8e,
+                0x44, 0x97, 0xa6, 0x2a, 0xd3, 0xe1, 0x43, 0xbb, 0xa6, 0xea, 0x15, 0x3b, 0xeb, 0xab, 0xf6, 0xfe,
+                0x5d, 0xe7, 0x4c, 0x8f, 0x16, 0x47, 0xdd, 0xf6, 0xdd, 0xe4, 0x5a, 0x47, 0x8c, 0x6d, 0x1c, 0x66,
+                0xfb, 0x6c, 0x00, 0xe2, 0xf6, 0x79, 0xae, 0x35, 0x4e, 0x81, 0xc8, 0xdd, 0xd6, 0xb8, 0x31, 0x52,
+                0x4d, 0xee, 0x6b, 0x66, 0xf1, 0x17, 0x1c, 0x34, 0xa2, 0x9c, 0x1b, 0x9d, 0x0f, 0x29, 0x23, 0x9e,
+                0xf1, 0xa8, 0x4a, 0x44, 0x5d, 0x8d, 0x6d, 0x75, 0x15, 0xe6, 0x29, 0x3d, 0xf9, 0x10, 0x7d, 0x2c,
+                0x02, 0xb3, 0x42, 0x28, 0xfe, 0x70, 0x3d, 0x0f, 0x5a, 0xac, 0x5d, 0x81, 0x6e, 0xea, 0xb9, 0x05,
+                0x94, 0x2a, 0xaf, 0xc5, 0x6a, 0x0d, 0x90, 0x72, 0xbf, 0x17, 0x34, 0x28, 0x4c, 0x92, 0x3b, 0xcf,
+                0xbc, 0x45, 0xc1, 0xb5, 0xac, 0x1d, 0x60, 0x6f, 0xce, 0x7c, 0xe6, 0x81, 0x33, 0x5c, 0x30, 0xdf,
+                0xae, 0x80, 0x8d, 0x1d, 0xc3, 0x66, 0x96, 0xf4, 0x59, 0x08, 0x15, 0x13, 0x09, 0x28, 0x3b, 0x15,
+                0x42, 0x78, 0x15, 0xa7, 0x14, 0x73, 0x25, 0x98, 0xe5, 0x1d, 0x93, 0xf0, 0xa2, 0x7e, 0x3d, 0xdf,
+                0x53, 0xcc, 0x32, 0xb1, 0x54, 0x55, 0xe1, 0xb5, 0x88, 0x46, 0x75, 0xcc, 0x61, 0x71, 0x71, 0x11,
+                0xd5, 0x74, 0x99, 0x2c, 0xf9, 0x67, 0x4a, 0x7d, 0x70, 0xfb, 0xa4, 0x8b, 0x0e, 0xa8, 0x4d, 0x0b,
+                0x5b, 0xd5, 0x8d, 0xa5, 0xb3, 0xb8, 0xda, 0x2d, 0x36, 0xf4, 0x80, 0x3c, 0xde, 0xbd, 0x29, 0xa2,
+                0xe6, 0x57, 0xc7, 0x0b, 0x2a, 0x8f, 0x67, 0x37, 0xfb, 0xd6, 0x5f, 0xcb, 0xde, 0xb5, 0x4e, 0x2b,
+                0x4b, 0x1a, 0x1b, 0x67, 0xdc, 0x4b, 0x3e, 0xd5, 0x2b, 0x3f, 0x96, 0x57, 0x00, 0xa3, 0xb4, 0x5a,
+                0x30, 0x5d, 0x25, 0x1a, 0xa6, 0x49, 0x3e, 0xd6, 0xd5, 0x4e, 0x18, 0x9d, 0xe0, 0x88, 0xe7, 0xd1,
+                0xc0, 0x09, 0x98, 0x2d, 0x1a, 0x7b, 0xee, 0xda, 0xc4, 0x35, 0xba, 0x60, 0x66, 0x72, 0x20, 0x1f,
+                0x16, 0x9f, 0xa7, 0xc3, 0x96, 0x94, 0x22, 0x70, 0x05, 0x1e, 0x08, 0x63, 0x8f, 0xd8, 0x85, 0x71,
+                0x94, 0xb4, 0x26, 0x4d, 0x7c, 0xcd, 0x46, 0x90, 0x6a, 0x07, 0x2c, 0x08, 0xe5, 0xa7, 0x04, 0x05,
+                0xed, 0x2d, 0xea, 0x0e, 0xc1, 0x69, 0x6a, 0xa5, 0x57, 0x41, 0xb0, 0x91, 0xdf, 0xe2, 0x52, 0xad,
+                0x68, 0x19, 0xef, 0x2f, 0x8f, 0x4b, 0x65, 0xea, 0x4a, 0xe7, 0x00, 0x2e, 0xfd, 0x7c, 0xd8, 0x0b,
+                0xf9, 0x1e, 0x98, 0x44, 0x1b, 0xdc, 0x7e, 0x5e, 0xfe, 0xf3, 0x3d, 0xa5, 0xba, 0x5f, 0x3b, 0x37,
+                0x64, 0x80, 0x00, 0x00, 0x03, 0xa5, 0xff, 0xff, 0xfc, 0x5a, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d,
+                0x4c, 0x56, 0x86, 0x00, 0x40, 0x92, 0xe1, 0x41, 0x56, 0x00, 0x00, 0x0c, 0x70, 0x00, 0x00, 0x7d,
+                0x9c, 0xe1, 0xf6, 0x1d, 0x70, 0x67, 0xf6, 0xf6, 0xf8, 0xc3, 0xff, 0x6e, 0xea, 0xb7, 0x4e, 0x1d,
+                0xa0, 0xf6, 0xa7, 0x65, 0x73, 0x97, 0xd9, 0xd1, 0xdc, 0x5f, 0xc1, 0x5a, 0xf3, 0x6c, 0x5b, 0xf9,
+                0x6a, 0x5a, 0x87, 0xdc, 0xd5, 0x6d, 0x6c, 0xd6, 0x48, 0x29, 0x2a, 0x94, 0x99, 0xea, 0xc9, 0xd0,
+                0xf7, 0x06, 0x13, 0xf7, 0xcd, 0xda, 0x03, 0xc2, 0x95, 0x2e, 0x8c, 0xa8, 0x4c, 0xf3, 0xd5, 0x11,
+                0x38, 0x31, 0x6f, 0xd8, 0x16, 0xeb, 0xd5, 0x72, 0xac, 0x62, 0xc2, 0xd9, 0xf7, 0x6f, 0xbb, 0xfc,
+                0x4b, 0x12, 0x46, 0xd7, 0xc6, 0x23, 0x00, 0xb4, 0x2a, 0xe4, 0x18, 0x45, 0xa6, 0xf2, 0x0a, 0x1c,
+                0xa6, 0x8a, 0xc7, 0x30, 0x3d, 0x73, 0xa1, 0xfb, 0x47, 0x07, 0x18, 0xf4, 0x63, 0x33, 0x44, 0xa7,
+                0x7e, 0xdb, 0xd6, 0x25, 0xd5, 0x1b, 0x5a, 0x67, 0x46, 0x6b, 0x8d, 0x91, 0x09, 0x7d, 0xf4, 0x2c,
+                0xc7, 0x45, 0xa1, 0xce, 0x6e, 0x90, 0x0f, 0x36, 0xa4, 0x57, 0x49, 0x7c, 0x03, 0x1b, 0x62, 0x33,
+                0x09, 0x05, 0x59, 0xca, 0xdd, 0xfb, 0x13, 0x4a, 0x58, 0xfc, 0xdc, 0x8f, 0x5e, 0xda, 0x20, 0x7d,
+                0x1f, 0x6a, 0x80, 0x01, 0x01, 0xea, 0x4d, 0xfc, 0xe4, 0x8d, 0x90, 0xb0, 0xf1, 0xa1, 0x16, 0x47,
+                0x19, 0x4f, 0xab, 0x4f, 0x38, 0x32, 0xc8, 0x17, 0xb2, 0x99, 0xed, 0x71, 0x5b, 0x5c, 0x72, 0xda,
+                0x64, 0x6e, 0xc5, 0x13, 0x5b, 0x51, 0xf3, 0x46, 0x04, 0x26, 0xcc, 0x47, 0xa0, 0x44, 0x91, 0x4c,
+                0x75, 0x57, 0xbe, 0xb6, 0x88, 0x49, 0x6c, 0x4a, 0xec, 0xd0, 0x65, 0x3f, 0xf0, 0xc2, 0x15, 0x28,
+                0x51, 0x28, 0x83, 0xfd, 0xfc, 0x86, 0x0f, 0x6b, 0xc1, 0x20, 0x60, 0x57, 0xbb, 0x15, 0x4c, 0x01,
+                0x07, 0xc9, 0x2f, 0x8e, 0x19, 0xc1, 0xef, 0x73, 0x65, 0x3a, 0x9e, 0x00, 0x4f, 0x03, 0x88, 0x7c,
+                0xc3, 0x04, 0x2b, 0x16, 0xee, 0xf1, 0x37, 0x42, 0x6e, 0x05, 0x93, 0x98, 0x65, 0x51, 0xef, 0x5b,
+                0xb3, 0xe6, 0x0a, 0x08, 0xad, 0x02, 0xc2, 0xfa, 0xfc, 0xc7, 0x0e, 0x39, 0x74, 0x54, 0xef, 0xf0,
+                0xdc, 0x7b, 0x19, 0xce, 0x35, 0x74, 0xe0, 0x35, 0x5c, 0xf3, 0x23, 0xe8, 0xc5, 0x71, 0x9f, 0x63,
+                0x4c, 0x3f, 0xb9, 0x64, 0xcd, 0x37, 0x7d, 0x59, 0x28, 0x37, 0x83, 0x06, 0xcb, 0x4f, 0x22, 0xf9,
+                0x03, 0x85, 0x2a, 0x18, 0xc7, 0xb0, 0xb7, 0x27, 0x3e, 0xc4, 0x8a, 0xa1, 0xbe, 0xf6, 0xe0, 0x31,
+                0x75, 0x4b, 0xfe, 0x70, 0x96, 0x82, 0x8e, 0xfe, 0x82, 0x8c, 0xd6, 0x64, 0x02, 0x96, 0xed, 0xdf,
+                0x14, 0x04, 0x27, 0xa2, 0x7b, 0x2c, 0xe0, 0xd4, 0x1e, 0x61, 0x0e, 0x0f, 0x2d, 0x5f, 0x93, 0xfc,
+                0x89, 0xf1, 0xfe, 0xaf, 0xa4, 0xda, 0x53, 0x18, 0x12, 0xc4, 0x0c, 0xd9, 0x15, 0x47, 0x60, 0x31,
+                0xc8, 0xea, 0x9d, 0x33, 0x78, 0x91, 0xbf, 0xe3, 0xc9, 0xe1, 0xdc, 0x26, 0xe9, 0xf8, 0x70, 0x55,
+                0x8f, 0x2b, 0xa8, 0x5b, 0x4c, 0x11, 0x7d, 0xd1, 0xa1, 0xe2, 0xd0, 0xba, 0xe6, 0x62, 0x36, 0x67,
+                0xe9, 0x5f, 0x01, 0x05, 0x71, 0x29, 0xba, 0x31, 0x36, 0xbe, 0x4b, 0xc0, 0x43, 0xa4, 0xb2, 0x9f,
+                0x09, 0xa6, 0xc4, 0x9b, 0xfd, 0x1f, 0x46, 0x3c, 0x44, 0x48, 0x3c, 0xc7, 0x58, 0x34, 0x7e, 0xfa,
+                0x8b, 0x73, 0xee, 0x0e, 0x04, 0x9e, 0x01, 0x10, 0x0a, 0xe1, 0x9f, 0x15, 0x92, 0xb3, 0x8b, 0x9c,
+                0x10, 0x2f, 0xfa, 0xb3, 0x8d, 0x21, 0x48, 0x4d, 0x82, 0x45, 0x0b, 0x89, 0x47, 0xa1, 0xd2, 0x7c,
+                0xeb, 0x30, 0x44, 0x51, 0xdd, 0x64, 0xb8, 0x7e, 0x3c, 0xce, 0xc9, 0x5b, 0xf1, 0x8a, 0xf9, 0xad,
+                0x62, 0xe9, 0x7f, 0x06, 0x56, 0x31, 0xb3, 0xae, 0xb3, 0x7d, 0x8e, 0x11, 0xa4, 0x4e, 0xbd, 0x46,
+                0xc3, 0x01, 0xce, 0x13, 0xb0, 0x3c, 0x2d, 0x6c, 0x7c, 0xbd, 0xa3, 0x00, 0x1e, 0x59, 0x1f, 0x92,
+                0x49, 0x16, 0xbd, 0x4b, 0x1e, 0x24, 0x23, 0x4c, 0x91, 0xb9, 0xb5, 0xf2, 0x58, 0x76, 0x2f, 0xcb,
+                0xda, 0xd4, 0xe4, 0xe0, 0x5b, 0x32, 0x93, 0x53, 0x40, 0x94, 0xe1, 0x7b, 0x12, 0xb7, 0xaa, 0xba,
+                0x70, 0x93, 0x26, 0x93, 0x7d, 0x68, 0x5f, 0xda, 0x4f, 0x33, 0xac, 0xc4, 0xf9, 0x4b, 0xcb, 0xb0,
+                0x8e, 0x7a, 0xda, 0x65, 0xdf, 0x5f, 0x31, 0xbb, 0x36, 0x0d, 0xdf, 0xd4, 0x8c, 0xf0, 0xd5, 0xa8,
+                0x9d, 0x3c, 0x89, 0x3d, 0x1c, 0x0e, 0x25, 0x8e, 0x5a, 0xc9, 0x68, 0x38, 0xcd, 0x74, 0x5c, 0x2a,
+                0xb7, 0x06, 0x7b, 0x8f, 0x0c, 0x11, 0x43, 0x9e, 0x13, 0x61, 0xdc, 0x72, 0x09, 0x92, 0x3e, 0x5f,
+                0x9e, 0xaf, 0x5f, 0x5d, 0x69, 0x25, 0xf5, 0x23, 0x74, 0x74, 0xab, 0xc2, 0x2f, 0x94, 0xac, 0xa9,
+                0xef, 0xcd, 0xf6, 0x48, 0x77, 0x91, 0xbb, 0x4f, 0xc8, 0x57, 0x8f, 0x1c, 0xc6, 0x09, 0xde, 0xcb,
+                0x4f, 0xdc, 0x6f, 0xf9, 0xcc, 0xcc, 0xd1, 0xce, 0x9a, 0xb6, 0x4a, 0x16, 0xeb, 0x5c, 0x54, 0x26,
+                0x48, 0xe8, 0x85, 0x9a, 0x53, 0xdf, 0xb3, 0xad, 0x9d, 0x59, 0x77, 0xdc, 0xca, 0xa7, 0x1d, 0xc2,
+                0x39, 0x60, 0xd3, 0xb8, 0xb9, 0xd9, 0x51, 0xf8, 0x34, 0x26, 0xce, 0x87, 0xb8, 0x87, 0x9a, 0xb0,
+                0xa6, 0x6f, 0xba, 0xe6, 0xff, 0xa0, 0xff, 0x57, 0x4b, 0xde, 0x20, 0x5f, 0x71, 0xad, 0xc3, 0xad,
+                0xd5, 0x12, 0xee, 0xad, 0xd3, 0x3b, 0xdf, 0x6e, 0xa3, 0x38, 0xc0, 0x87, 0x39, 0x3e, 0xce, 0xfe,
+                0xfe, 0x72, 0x84, 0x1c, 0xe7, 0xfd, 0xac, 0x88, 0xab, 0x79, 0x73, 0x97, 0xc4, 0x2d, 0x2b, 0xf3,
+                0xa3, 0x69, 0x55, 0x64, 0x25, 0x1a, 0x32, 0xe0, 0x57, 0xc1, 0x10, 0x18, 0x0d, 0xdb, 0x20, 0x6c,
+                0xa2, 0x3d, 0xc9, 0xbf, 0x93, 0x2e, 0x6a, 0x6f, 0xac, 0xa3, 0x9a, 0xc9, 0xe8, 0x6a, 0xd3, 0xfe,
+                0x43, 0x05, 0x9d, 0xa0, 0x21, 0xa9, 0xbe, 0xe9, 0x87, 0x06, 0x75, 0xe3, 0x9e, 0xee, 0x40, 0x93,
+                0x9d, 0x21, 0xec, 0xe9, 0xdc, 0x17, 0x62, 0xf4, 0xfc, 0x74, 0x4f, 0xf2, 0xf2, 0x5b, 0xed, 0x73,
+                0x93, 0x79, 0x66, 0xf8, 0x6b, 0x38, 0xb1, 0xbe, 0x29, 0x11, 0x3f, 0x52, 0x78, 0x7c, 0xab, 0xb7,
+                0x9a, 0x9e, 0x0a, 0xfa, 0x29, 0x0f, 0x41, 0x44, 0xd2, 0xd6, 0x38, 0xbb, 0x11, 0x83, 0x25, 0xf9,
+                0xf8, 0x2a, 0x7c, 0x4a, 0x72, 0xa1, 0x42, 0x54, 0x41, 0xbd, 0x3a, 0x6f, 0x7e, 0x3a, 0xc6, 0xee,
+                0x45, 0xf0, 0x90, 0xe5, 0x86, 0x6e, 0x91, 0xbc, 0x35, 0x21, 0x47, 0xa0, 0x0a, 0x2d, 0xd2, 0x5c,
+                0xbc, 0x83, 0x21, 0x8b, 0x74, 0xb1, 0x11, 0x86, 0x60, 0x00, 0xab, 0x5b, 0x4f, 0x08, 0x26, 0xce,
+                0xce, 0xe5, 0x36, 0x02, 0x0d, 0x42, 0x35, 0x1e, 0x4d, 0x28, 0x6e, 0xc0, 0xe4, 0x4a, 0x1c, 0x2c,
+                0x7b, 0x93, 0x80
+#else
+                0x00, 0x00, 0x01, 0x34, 0xff, 0xff, 0xfe, 0xcb, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x4c, 0x56,
+                0x82, 0x49, 0x83, 0x42, 0x00, 0x04, 0x10, 0x04, 0x14, 0x0e, 0x38, 0x24, 0x1c, 0x19, 0xba, 0x00,
+                0x00, 0x90, 0x7c, 0x11, 0xb4, 0xcc, 0x7e, 0x19, 0x86, 0x00, 0x00, 0x7f, 0xc3, 0xb6, 0x35, 0x54,
+                0x45, 0x38, 0x12, 0xe2, 0xd7, 0xa9, 0x1b, 0x49, 0xef, 0xc6, 0xfc, 0x14, 0x34, 0x41, 0xc7, 0xa3,
+                0x91, 0xf4, 0x76, 0x8a, 0x19, 0x6b, 0xb0, 0xa4, 0xa0, 0x04, 0x13, 0xb0, 0xbe, 0x10, 0x72, 0x80,
+                0x0a, 0x58, 0xbc, 0x18, 0xf2, 0xd0, 0x4f, 0x62, 0x1b, 0xea, 0xc2, 0x0b, 0xba, 0xfc, 0x7b, 0xbc,
+                0xb3, 0x6a, 0x97, 0x15, 0x1f, 0x3c, 0x21, 0x4e, 0x3f, 0xa2, 0xe9, 0xe9, 0xfc, 0x92, 0xc3, 0xe7,
+                0x7d, 0xb2, 0x08, 0x87, 0x98, 0x8e, 0x77, 0x0f, 0x09, 0x7b, 0xa7, 0x41, 0x42, 0xff, 0x14, 0xa1,
+                0x0e, 0xf3, 0x28, 0x2d, 0xe1, 0x13, 0x73, 0x49, 0x26, 0xed, 0x88, 0x22, 0x82, 0x6a, 0x02, 0x87,
+                0xa5, 0xbe, 0x9c, 0xe5, 0x3f, 0xc7, 0xb5, 0x65, 0x3f, 0x7e, 0xa2, 0x82, 0x3e, 0x22, 0xa1, 0x03,
+                0xe1, 0xcd, 0x89, 0xe6, 0xf0, 0x47, 0x62, 0x81, 0x89, 0xaa, 0x7e, 0xbc, 0x4a, 0xc1, 0x7c, 0x26,
+                0xe4, 0xc0, 0xd4, 0xbc, 0xb8, 0xcc, 0xb8, 0x44, 0x07, 0x51, 0xb4, 0xb3, 0xb9, 0xf5, 0x04, 0xaf,
+                0x3f, 0x41, 0x49, 0x56, 0x6a, 0x87, 0x46, 0x95, 0xa1, 0xe7, 0x69, 0xe7, 0x3c, 0x32, 0x06, 0xc2,
+                0xa2, 0x66, 0x48, 0x1f, 0x14, 0x43, 0x81, 0xf0, 0xa0, 0x3c, 0xa4, 0x82, 0x7f, 0x18, 0x9b, 0xe4,
+                0x22, 0x2d, 0x64, 0x2a, 0xd0, 0x4d, 0xb4, 0xfd, 0x14, 0x2d, 0x6d, 0x68, 0xaf, 0x19, 0x7d, 0x0f,
+                0x0f, 0x60, 0xc4, 0x92, 0x73, 0x34, 0xc9, 0x51, 0x9a, 0xb6, 0xac, 0x06, 0x90, 0xaf, 0x11, 0x21,
+                0x0c, 0xb0, 0x02, 0xd9, 0xd7, 0xd1, 0x06, 0xa0, 0x05, 0xb6, 0x75, 0x70, 0x5d, 0xbc, 0x84, 0x99,
+                0x08, 0xfd, 0x8b, 0x60, 0x33, 0xf5, 0x0f, 0xab, 0x42, 0xab, 0x63, 0x1a, 0x37, 0x1c, 0x5a, 0x89,
+                0xc1, 0x5f, 0x43, 0x5c, 0x65, 0x63, 0x60, 0xc4, 0xca, 0xe9, 0x59, 0x72, 0xea, 0x93, 0xf9, 0xcb,
+                0x0d, 0x96, 0x5e, 0x33, 0x21, 0xa9, 0xe1, 0xf1, 0x37, 0xcc, 0x1b, 0x3c, 0x99, 0x36, 0x78, 0x40,
+                0x00, 0x00, 0x00, 0x76, 0xff, 0xff, 0xff, 0x89, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x4c, 0x56,
+                0x84, 0x00, 0x80, 0x49, 0x72, 0x58, 0xba, 0x00, 0x00, 0x06, 0x70, 0x00, 0x00, 0x7f, 0x0a, 0x55,
+                0x64, 0x1f, 0x77, 0x22, 0x11, 0x64, 0x86, 0x41, 0x2e, 0x75, 0xe3, 0xba, 0x24, 0xf7, 0x02, 0xaa,
+                0x1f, 0x9a, 0x97, 0x84, 0x24, 0x83, 0xa8, 0xa3, 0x92, 0x1c, 0x9c, 0xe7, 0x85, 0x71, 0x18, 0x49,
+                0xc5, 0x09, 0x36, 0xf0, 0x9e, 0x04, 0x84, 0x88, 0xa0, 0xad, 0x9c, 0x8e, 0x75, 0x9d, 0x08, 0xfb,
+                0xab, 0xfd, 0x3d, 0x68, 0xdd, 0x14, 0x93, 0x50, 0xa3, 0x48, 0x96, 0xf7, 0xe6, 0xa4, 0x54, 0x62,
+                0x3b, 0x31, 0x18, 0x57, 0xef, 0x3b, 0xb7, 0x98, 0x8e, 0xe9, 0x3b, 0xdf, 0x63, 0x0c, 0xfa, 0x5d,
+                0x30, 0x51, 0x4e, 0x61, 0x06, 0xf9, 0x1f, 0xe5, 0xc5, 0x90, 0xb0, 0x80, 0x7c, 0xa0, 0x04, 0x98,
+                0x5b, 0x00, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, 0xcf, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d,
+                0x4c, 0x56, 0x86, 0x00, 0x40, 0x96, 0x61, 0xf1, 0x78, 0x00, 0x00, 0x0c, 0x23, 0x18, 0x00, 0x7c,
+                0xc1, 0x46, 0xab, 0x45, 0x25, 0x66, 0x9d, 0x6f, 0xa7, 0x18, 0x82, 0xbc, 0xc3, 0xd5, 0xa0, 0xba,
+                0x42, 0x04, 0x49, 0x7d, 0x20, 0xb3, 0x0f, 0x4c, 0x78, 0x4c, 0xae, 0x9b, 0x20, 0x00, 0x00, 0x00,
+                0x00, 0x29, 0xff, 0xff, 0xff, 0xd6, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x4c, 0x56, 0x86, 0x00,
+                0x40, 0x96, 0x61, 0x21, 0x78, 0x00, 0x00, 0x0c, 0x70, 0x50, 0x40, 0x78, 0xfc, 0x21, 0xff, 0xe1,
+                0x45, 0x85, 0x50, 0x5b, 0xfa, 0x35, 0xc8, 0x10, 0x5f, 0x78, 0x01, 0xb7, 0x6b, 0x58, 0x7e, 0x58,
+                0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xff, 0xff, 0xff, 0xc7, 0x00, 0x00, 0x00, 0x01, 0x41,
+                0x4d, 0x4c, 0x56, 0x86, 0x00, 0x40, 0x96, 0x62, 0x51, 0x78, 0x00, 0x00, 0x0c, 0x60, 0x63, 0x00,
+                0x7e, 0x6c, 0x4b, 0x84, 0x3e, 0x1d, 0xe4, 0x3e, 0x25, 0x9f, 0x3f, 0x5a, 0x2a, 0x19, 0xb6, 0xdd,
+                0x80, 0x97, 0xf7, 0x65, 0x1e, 0xa1, 0x17, 0xe2, 0xff, 0xac, 0xb3, 0x4c, 0x5a, 0xfa, 0x5f, 0x60,
+                0xcf, 0x78, 0xc3, 0x28, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27, 0xff, 0xff, 0xff, 0xd8, 0x00,
+                0x00, 0x00, 0x01, 0x41, 0x4d, 0x4c, 0x56, 0x86, 0x00, 0x40, 0x96, 0x18, 0x70, 0x5e, 0x00, 0x00,
+                0x03, 0x23, 0xa8, 0x00, 0x76, 0x0f, 0xb4, 0x03, 0xdc, 0x4e, 0xaf, 0x53, 0xde, 0xfe, 0x91, 0xd9,
+                0x66, 0x0b, 0xab, 0x76, 0xbb, 0x44, 0x2c, 0xa6, 0x90, 0x80, 0x00, 0x00, 0x00, 0x23, 0xff, 0xff,
+                0xff, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x4c, 0x56, 0x86, 0x00, 0x40, 0x96, 0x18, 0x70,
+                0x5e, 0x00, 0x00, 0x03, 0x23, 0xa8, 0x00, 0x5d, 0xfc, 0x15, 0x9d, 0x57, 0xb5, 0x81, 0x63, 0x84,
+                0xbd, 0x2b, 0xee, 0x37, 0x7c, 0xa0, 0xb6, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x18, 0xff, 0xff, 0xff,
+                0xe7, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x4c, 0x56, 0x86, 0x01, 0x00, 0x96, 0x18, 0x48, 0x5f,
+                0xe0, 0x00, 0x03, 0x20, 0x00, 0x00, 0x46, 0x74, 0x8f, 0xef, 0xb7, 0x09, 0x80, 0x00, 0x00, 0x00,
+                0x31, 0xff, 0xff, 0xff, 0xce, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x4c, 0x56, 0x86, 0x00, 0x41,
+                0x0a, 0x61, 0xa1, 0x78, 0x00, 0x00, 0x0c, 0x20, 0x00, 0x00, 0x72, 0x25, 0x0b, 0x41, 0x5b, 0x2e,
+                0x3e, 0x8d, 0x64, 0x6d, 0xf0, 0x11, 0x8f, 0xd9, 0x9f, 0x4f, 0x28, 0x72, 0xf6, 0xd5, 0x1e, 0x5f,
+                0x92, 0x69, 0xb8, 0xb0, 0xf6, 0xe0, 0xc8, 0xd6, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x3e, 0xff, 0xff,
+                0xff, 0xc1, 0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x4c, 0x56, 0x86, 0x00, 0x41, 0x0a, 0x62, 0x01,
+                0x78, 0x00, 0x00, 0x0c, 0x70, 0x00, 0x00, 0x7d, 0x80, 0x9f, 0xc5, 0x19, 0x81, 0x7a, 0xcd, 0xc4,
+                0xc5, 0x08, 0x1c, 0x79, 0x94, 0xce, 0xb4, 0x6f, 0xc4, 0xd8, 0x8c, 0x45, 0x0a, 0xcf, 0xcb, 0xb2,
+                0x21, 0x84, 0xe2, 0x7e, 0x84, 0xeb, 0x73, 0xd9, 0x4c, 0xad, 0x10, 0x50, 0x48, 0x96, 0xc2, 0x17,
+                0x24, 0xa2, 0x4c, 0x90, 0x00, 0x00, 0x00, 0x45, 0xff, 0xff, 0xff, 0xba, 0x00, 0x00, 0x00, 0x01,
+                0x41, 0x4d, 0x4c, 0x56, 0x86, 0x00, 0x41, 0x0a, 0x62, 0x61, 0x78, 0x00, 0x00, 0x0c, 0x20, 0x00,
+                0x00, 0x7b, 0xea, 0xae, 0x37, 0x81, 0xba, 0xc1, 0x88, 0x4f, 0xbd, 0xf1, 0x0c, 0xc5, 0xf3, 0x80,
+                0x6c, 0x69, 0x9f, 0xee, 0xd1, 0x8d, 0x03, 0x08, 0x49, 0x19, 0x41, 0x50, 0x0f, 0xa8, 0x85, 0xbd,
+                0x27, 0x49, 0xf0, 0xfa, 0x1e, 0x96, 0x3a, 0x4d, 0x54, 0xf6, 0x11, 0xfc, 0x1e, 0x10, 0xe3, 0x75,
+                0x67, 0xe5, 0x33, 0x73, 0xb0
+#endif
+        };
+
+#if VP9_USE_TRIGGER_BIG_SIZE
+        static u32 vp9_trigger_framesize[] = {5429,591,799,655,655,647,769,822,867,945};
+#else
+        static u32 vp9_trigger_framesize[] = {320,130,60,53,68,51,47,36,61,74,81};
+#endif
+
+#endif //_VDEC_VP9_TRIG_
+
diff --git a/drivers/amvdec_ports/test/Android.mk b/drivers/amvdec_ports/test/Android.mk
new file mode 100644
index 0000000..d9652fb
--- /dev/null
+++ b/drivers/amvdec_ports/test/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE		:= vcode_m2m
+LOCAL_MODULE_TAGS	:= optional
+LOCAL_SRC_FILES		:= vcodec_m2m_test.c
+LOCAL_ARM_MODE		:= arm
+
+LOCAL_C_INCLUDES := \
+	$(JNI_H_INCLUDE) \
+	$(BOARD_AML_VENDOR_PATH)/vendor/amlogic/external/ffmpeg
+
+LOCAL_SHARED_LIBRARIES := \
+	libamffmpeg
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_LIBS:= \
+#        libavcodec:ffmpeg/lib/libavcodec.so \
+
+include $(BUILD_MULTI_PREBUILT)
diff --git a/drivers/amvdec_ports/test/vcodec_m2m_test.c b/drivers/amvdec_ports/test/vcodec_m2m_test.c
new file mode 100644
index 0000000..bec040b
--- /dev/null
+++ b/drivers/amvdec_ports/test/vcodec_m2m_test.c
@@ -0,0 +1,343 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <pthread.h>
+
+#define INBUF_SIZE	(4096)
+#define DUMP_DIR	"/data/video_frames"
+static int dump;
+
+typedef struct VcodecCtx {
+	AVFormatContext *fmt_ctx;
+	AVStream *stream;
+	int nb_streams;
+	int vst_idx;
+	char *filename;
+	pthread_t tid;
+	pthread_mutex_t pthread_mutex;
+	pthread_cond_t pthread_cond;
+} VcodecCtx;
+
+static void dump_yuv(AVFrame *frame, char *filename)
+{
+	FILE *f;
+
+	printf("name: %s, resolution: %dx%d, size: %d\n",
+		filename, frame->width, frame->height,
+		frame->buf[0]->size + frame->buf[1]->size);
+
+	f = fopen(filename,"w+");
+
+	fwrite(frame->buf[0]->data, 1, frame->buf[0]->size, f);
+	fwrite(frame->buf[1]->data, 1, frame->buf[1]->size, f);
+
+	fclose(f);
+}
+
+static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt,
+                   const char *filename)
+{
+	char buf[1024];
+	int ret;
+
+	ret = avcodec_send_packet(dec_ctx, pkt);
+	if (ret < 0) {
+		fprintf(stderr, "Error sending a packet for decoding\n");
+		return;
+	}
+
+	while (ret >= 0) {
+		ret = avcodec_receive_frame(dec_ctx, frame);
+		if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+			return;
+		else if (ret < 0) {
+			fprintf(stderr, "Error during decoding, ret: %s\n", av_err2str(ret));
+			break;
+		}
+
+		//fprintf(stderr, "saving frame %3d\n", dec_ctx->frame_number);
+		fflush(stdout);
+
+		/* the picture is allocated by the decoder. no need to free it */
+		snprintf(buf, sizeof(buf), "%s/frame-%d", filename, dec_ctx->frame_number);
+
+		if (dump)
+			dump_yuv(frame, buf);
+	}
+}
+
+static void* read_thread(void *arg)
+{
+	int ret, err;
+	AVFormatContext *ic = NULL;
+	AVCodecContext *dec_ctx = NULL;
+	AVStream *stream = NULL;
+	AVCodec *codec = NULL;
+	AVPacket pkt1, *pkt = &pkt1;
+	AVFrame *frame = NULL;
+	int vst_idx = 0;
+	int has_video = 0;
+	unsigned int st_idx = 0;
+	VcodecCtx *vctx = arg;
+	const char *forced_codec_name = NULL;
+
+	printf("entry read thread, tid: %ld.\n", vctx->tid);
+
+	ic = avformat_alloc_context();
+	if (!ic) {
+		fprintf(stderr, "Could not allocate avformat context.\n");
+		goto out;
+	}
+
+	err = avformat_open_input(&ic, vctx->filename, NULL, NULL);
+	if (err < 0) {
+		fprintf(stderr, "Could not open avformat input.\n");
+		goto out;
+	}
+
+	err = avformat_find_stream_info(ic, NULL);
+	if (err < 0) {
+		fprintf(stderr, "find stream info err.\n");
+		goto out;
+	}
+
+	for (st_idx = 0; st_idx < ic->nb_streams; st_idx++) {
+		AVStream *st = ic->streams[st_idx];
+
+		enum AVMediaType type = st->codecpar->codec_type;
+		st->discard = AVDISCARD_ALL;
+
+		if (type == AVMEDIA_TYPE_VIDEO) {
+			st->discard = AVDISCARD_NONE;
+			vctx->vst_idx = st_idx;
+			has_video = 1;
+			break;
+		}
+	}
+
+	if (!has_video) {
+		fprintf(stderr, "no video stream.\n");
+		goto out;
+	}
+
+	stream = ic->streams[vctx->vst_idx];
+
+	//codec = avcodec_find_decoder(stream->codecpar->codec_id);
+	switch (stream->codecpar->codec_id) {
+		case AV_CODEC_ID_H264:
+			forced_codec_name = "h264_v4l2m2m";
+			break;
+		case AV_CODEC_ID_HEVC:
+			forced_codec_name = "hevc_v4l2m2m";
+			break;
+		case AV_CODEC_ID_VP9:
+			forced_codec_name = "vp9_v4l2m2m";
+			break;
+		case AV_CODEC_ID_MPEG1VIDEO:
+			forced_codec_name = "mpeg1_v4l2m2m";
+			break;
+		case AV_CODEC_ID_MPEG2VIDEO:
+			forced_codec_name = "mpeg2_v4l2m2m";
+			break;
+		case AV_CODEC_ID_VC1:
+			forced_codec_name = "vc1_v4l2m2m";
+			break;
+		case AV_CODEC_ID_H263:
+			forced_codec_name = "h263_v4l2m2m";
+			break;
+		case AV_CODEC_ID_MPEG4:
+			forced_codec_name = "mpeg4_v4l2m2m";
+			break;
+		case AV_CODEC_ID_MJPEG:
+			forced_codec_name = "mjpeg_v4l2m2m";
+			break;
+	}
+
+	codec = avcodec_find_decoder_by_name(forced_codec_name);
+	if (!codec) {
+		fprintf(stderr, "Unsupported codec with id %d for input stream %d\n",
+			stream->codecpar->codec_id, stream->index);
+		goto out;
+	}
+
+	dec_ctx = avcodec_alloc_context3(codec);
+	if (!dec_ctx) {
+		fprintf(stderr, "Could not allocate video codec context\n");
+		goto out;
+	}
+
+	err = avcodec_parameters_to_context(dec_ctx, stream->codecpar);
+	if (err < 0) {
+		fprintf(stderr, "Could not set paras to context\n");
+		goto out;
+	}
+
+	av_codec_set_pkt_timebase(dec_ctx, stream->time_base);
+	dec_ctx->framerate = stream->avg_frame_rate;
+
+	if (avcodec_open2(dec_ctx, codec, NULL) < 0) {
+		fprintf(stderr, "Could not open codec for input stream %d\n",
+			stream->index);
+		goto out;
+	}
+
+	printf("fmt ctx: %p, stream: %p, video st idx: %d, num: %d\n",
+		ic, stream, vst_idx, ic->nb_streams);
+        printf("format: %s\n",ic->iformat->name);
+
+	ic->flags |= AVFMT_FLAG_GENPTS;
+	ic->debug = 0xff;
+
+	//if (ic->pb)
+	//    ic->pb->eof_reached = 0;
+
+	frame = av_frame_alloc();
+	if (!frame) {
+		fprintf(stderr, "Could not allocate video frame\n");
+		goto out;
+	}
+
+	for (;;) {
+		ret = av_read_frame(ic, pkt);
+		if (ret < 0) {
+			if (ret == AVERROR_EOF || avio_feof(ic->pb)) {
+				printf("read data end, ret: %d.\n", ret);
+				break;
+			}
+
+			if (ic->pb && ic->pb->error)
+			    break;
+
+			printf("read data fail, ret: %d.\n", ret);
+			continue;
+		}
+
+		if (pkt->stream_index == vctx->vst_idx) {
+			//packet_queue_put(&is->audioq, pkt);
+			//printf("read video data size: %d.\n", pkt->size);
+			if (pkt->size)
+				decode(dec_ctx, frame, pkt, DUMP_DIR);
+		}
+
+		av_packet_unref(pkt);
+
+		usleep(8 * 1000);
+	}
+
+	/* flush the decoder */
+	decode(dec_ctx, frame, NULL, DUMP_DIR);
+out:
+	if (dec_ctx)
+		avcodec_free_context(&dec_ctx);
+
+	if (frame)
+		av_frame_free(&frame);
+
+	if (ic) {
+	    avformat_close_input(&ic);
+	    avformat_free_context(ic);
+	}
+
+	printf("read thread exit.\n");
+
+	pthread_mutex_lock(&vctx->pthread_mutex);
+	pthread_cond_signal(&vctx->pthread_cond);
+	pthread_mutex_unlock(&vctx->pthread_mutex);
+
+	return NULL;
+}
+
+static int open_input_file(const char *filename)
+{
+	int ret;
+	VcodecCtx *vctx;
+	pthread_t pid = pthread_self();
+
+	vctx = av_mallocz(sizeof(VcodecCtx));
+	if (!vctx)
+	    return -1;
+
+	vctx->filename = av_strdup(filename);
+	if (!vctx->filename) {
+	    av_free(vctx);
+	    return -1;
+	}
+
+	pthread_mutex_init(&vctx->pthread_mutex, NULL);
+	pthread_cond_init(&vctx->pthread_cond, NULL);
+
+	ret = pthread_create(&vctx->tid, NULL, read_thread, (void *)vctx);
+	if (ret == 0) {
+		pthread_setname_np(pid, "read_thread");
+
+		pthread_mutex_lock(&vctx->pthread_mutex);
+		pthread_cond_wait(&vctx->pthread_cond, &vctx->pthread_mutex);
+		pthread_join(vctx->tid, NULL);
+		pthread_mutex_unlock(&vctx->pthread_mutex);
+	}
+
+	av_free(vctx->filename);
+	av_free(vctx);
+
+	printf("creat the read thread, ret: %d.\n", ret);
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	int ret;
+	const char *filename;
+	int log_level = 0;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: %s <input file>\n ==> %s/frame-123\n", argv[0], DUMP_DIR);
+		exit(0);
+	}
+
+	filename = argv[1];
+	if (argv[2]) {
+		if (!strcmp(argv[2], "dump"))
+			dump = 1;
+		else
+			log_level = atoi(argv[2]);
+	}
+
+	mkdir(DUMP_DIR, 0664);
+
+	/*set debug level*/
+	av_log_set_level(log_level); //AV_LOG_DEBUG
+
+	/* register all the codecs */
+	avcodec_register_all();
+
+	ret = open_input_file(filename);
+	if (ret < 0)
+		fprintf(stderr, "open input file fail.\n");
+
+	return 0;
+}
diff --git a/drivers/amvdec_ports/utils/common.c b/drivers/amvdec_ports/utils/common.c
new file mode 100644
index 0000000..67cf93b
--- /dev/null
+++ b/drivers/amvdec_ports/utils/common.c
@@ -0,0 +1,232 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+
+#include "common.h"
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+#include "pixfmt.h"
+#endif
+
+const u8 ff_zigzag_direct[64] = {
+	0,  1,  8, 16, 9, 2, 3, 10,
+	17, 24, 32, 25, 18, 11, 4, 5,
+	12, 19, 26, 33, 40, 48, 41, 34,
+	27, 20, 13, 6, 7, 14, 21, 28,
+	35, 42, 49, 56, 57, 50, 43, 36,
+	29, 22, 15, 23, 30, 37, 44, 51,
+	58, 59, 52, 45, 38, 31, 39, 46,
+	53, 60, 61, 54, 47, 55, 62, 63
+};
+
+const u8 ff_zigzag_scan[16 + 1] = {
+	0 + 0 * 4, 1 + 0 * 4, 0 + 1 * 4, 0 + 2 * 4,
+	1 + 1 * 4, 2 + 0 * 4, 3 + 0 * 4, 2 + 1 * 4,
+	1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4,
+	3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4,
+};
+
+const char * const color_space_names[] = {
+	[AVCOL_SPC_RGB]		= "gbr",
+	[AVCOL_SPC_BT709]	= "bt709",
+	[AVCOL_SPC_UNSPECIFIED]	= "unknown",
+	[AVCOL_SPC_RESERVED]	= "reserved",
+	[AVCOL_SPC_FCC]		= "fcc",
+	[AVCOL_SPC_BT470BG]	= "bt470bg",
+	[AVCOL_SPC_SMPTE170M]	= "smpte170m",
+	[AVCOL_SPC_SMPTE240M]	= "smpte240m",
+	[AVCOL_SPC_YCGCO]	= "ycgco",
+	[AVCOL_SPC_BT2020_NCL]	= "bt2020nc",
+	[AVCOL_SPC_BT2020_CL]	= "bt2020c",
+	[AVCOL_SPC_SMPTE2085]	= "smpte2085",
+	[AVCOL_SPC_CHROMA_DERIVED_NCL] = "chroma-derived-nc",
+	[AVCOL_SPC_CHROMA_DERIVED_CL] = "chroma-derived-c",
+	[AVCOL_SPC_ICTCP]	= "ictcp",
+};
+
+const char *av_color_space_name(enum AVColorSpace space)
+{
+	return (unsigned) space < AVCOL_SPC_NB ?
+		color_space_names[space] : NULL;
+}
+
+const char * const color_primaries_names[AVCOL_PRI_NB] = {
+	[AVCOL_PRI_RESERVED0]	= "reserved",
+	[AVCOL_PRI_BT709]	= "bt709",
+	[AVCOL_PRI_UNSPECIFIED]	= "unknown",
+	[AVCOL_PRI_RESERVED]	= "reserved",
+	[AVCOL_PRI_BT470M]	= "bt470m",
+	[AVCOL_PRI_BT470BG]	= "bt470bg",
+	[AVCOL_PRI_SMPTE170M]	= "smpte170m",
+	[AVCOL_PRI_SMPTE240M]	= "smpte240m",
+	[AVCOL_PRI_FILM]	= "film",
+	[AVCOL_PRI_BT2020]	= "bt2020",
+	[AVCOL_PRI_SMPTE428]	= "smpte428",
+	[AVCOL_PRI_SMPTE431]	= "smpte431",
+	[AVCOL_PRI_SMPTE432]	= "smpte432",
+	[AVCOL_PRI_JEDEC_P22]	= "jedec-p22",
+};
+
+const char *av_color_primaries_name(enum AVColorPrimaries primaries)
+{
+	return (unsigned) primaries < AVCOL_PRI_NB ?
+		color_primaries_names[primaries] : NULL;
+}
+
+const char * const color_transfer_names[] = {
+    [AVCOL_TRC_RESERVED0]	= "reserved",
+    [AVCOL_TRC_BT709]		= "bt709",
+    [AVCOL_TRC_UNSPECIFIED]	= "unknown",
+    [AVCOL_TRC_RESERVED]	= "reserved",
+    [AVCOL_TRC_GAMMA22]		= "bt470m",
+    [AVCOL_TRC_GAMMA28]		= "bt470bg",
+    [AVCOL_TRC_SMPTE170M]	= "smpte170m",
+    [AVCOL_TRC_SMPTE240M]	= "smpte240m",
+    [AVCOL_TRC_LINEAR]		= "linear",
+    [AVCOL_TRC_LOG]		= "log100",
+    [AVCOL_TRC_LOG_SQRT]	= "log316",
+    [AVCOL_TRC_IEC61966_2_4]	= "iec61966-2-4",
+    [AVCOL_TRC_BT1361_ECG]	= "bt1361e",
+    [AVCOL_TRC_IEC61966_2_1]	= "iec61966-2-1",
+    [AVCOL_TRC_BT2020_10]	= "bt2020-10",
+    [AVCOL_TRC_BT2020_12]	= "bt2020-12",
+    [AVCOL_TRC_SMPTE2084]	= "smpte2084",
+    [AVCOL_TRC_SMPTE428]	= "smpte428",
+    [AVCOL_TRC_ARIB_STD_B67]	= "arib-std-b67",
+};
+
+const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer)
+{
+	return (unsigned) transfer < AVCOL_TRC_NB ?
+		color_transfer_names[transfer] : NULL;
+}
+
+//math
+const u8 ff_log2_tab[256]={
+	0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+	5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+	6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+	6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+};
+
+int av_log2(u32 v)
+{
+	int n = 0;
+
+	if (v & 0xffff0000) {
+		v >>= 16;
+		n += 16;
+	}
+	if (v & 0xff00) {
+		v >>= 8;
+		n += 8;
+	}
+		n += ff_log2_tab[v];
+
+	return n;
+}
+
+//bitstream
+int find_start_code(u8 *data, int data_sz)
+{
+	if (data_sz > 3 && data[0] == 0 && data[1] == 0 && data[2] == 1)
+		return 3;
+
+	if (data_sz > 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 && data[3] == 1)
+		return 4;
+
+	return -1;
+}
+
+int calc_nal_len(u8 *data, int len)
+{
+	int i;
+
+	for (i = 0; i < len - 4; i++) {
+		if (data[i])
+			continue;
+
+		if ((data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1) ||
+			(data[i] == 0 && data[i + 1] == 0 &&
+			data[i + 2]==0 && data[i + 3] == 1))
+		 return i;
+	}
+	return len; //Not find the end of nalu
+}
+
+u8 *nal_unit_extract_rbsp(const u8 *src, u32 src_len, u32 *dst_len)
+{
+	u8 *dst;
+	u32 i, len;
+
+	dst = vmalloc(src_len + AV_INPUT_BUFFER_PADDING_SIZE);
+	if (!dst)
+		return NULL;
+
+	/* NAL unit header (2 bytes) */
+	i = len = 0;
+	while (i < 2 && i < src_len)
+		dst[len++] = src[i++];
+
+	while (i + 2 < src_len)
+	if (!src[i] && !src[i + 1] && src[i + 2] == 3) {
+		dst[len++] = src[i++];
+		dst[len++] = src[i++];
+		i++; // remove emulation_prevention_three_byte
+	} else
+		dst[len++] = src[i++];
+
+	while (i < src_len)
+		dst[len++] = src[i++];
+
+	memset(dst + len, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+
+	*dst_len = len;
+
+	return dst;
+}
+
+//debug
+static void _pr_hex(const char *fmt, ...)
+{
+	u8 buf[512];
+	int len = 0;
+
+	va_list args;
+	va_start(args, fmt);
+	vsnprintf(buf + len, 512 - len, fmt, args);
+	printk("%s", buf);
+	va_end(args);
+}
+
+void print_hex_debug(u8 *data, u32 len, int max)
+{
+	int i, l;
+
+	l = len > max ? max : len;
+
+	for (i = 0; i < l; i++) {
+		if ((i & 0xf) == 0)
+			_pr_hex("%06x:", i);
+		_pr_hex("%02x ", data[i]);
+		if ((((i + 1) & 0xf) == 0) || ((i + 1) == l))
+			_pr_hex("\n");
+	}
+
+	_pr_hex("print hex ending. len %d\n\n", l);
+}
+
+bool is_over_size(int w, int h, int size)
+{
+	if (h != 0 && (w > size / h))
+		return true;
+
+	return false;
+}
+
+
diff --git a/drivers/amvdec_ports/utils/common.h b/drivers/amvdec_ports/utils/common.h
new file mode 100644
index 0000000..89ae50b
--- /dev/null
+++ b/drivers/amvdec_ports/utils/common.h
@@ -0,0 +1,155 @@
+#ifndef UTILS_COMMON_H
+#define UTILS_COMMON_H
+
+#ifdef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+#include "pixfmt.h"
+#endif
+
+#define AV_INPUT_BUFFER_PADDING_SIZE	64
+#define MIN_CACHE_BITS			64
+
+#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
+#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c)
+#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
+#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c)
+
+#define AV_WL32(p, val)				\
+	do {					\
+		u32 d = (val);			\
+		((u8*)(p))[0] = (d);		\
+		((u8*)(p))[1] = (d) >> 8;	\
+		((u8*)(p))[2] = (d) >> 16;	\
+		((u8*)(p))[3] = (d) >> 24;	\
+	} while(0)
+
+#define AV_WB32(p, val)				\
+	do { u32 d = (val);			\
+		((u8*)(p))[3] = (d);		\
+		((u8*)(p))[2] = (d) >> 8;	\
+		((u8*)(p))[1] = (d) >> 16;	\
+		((u8*)(p))[0] = (d) >> 24;	\
+	} while(0)
+
+#define AV_RB32(x)				\
+	(((u32)((const u8*)(x))[0] << 24) |	\
+	(((const u8*)(x))[1] << 16) |		\
+	(((const u8*)(x))[2] <<  8) |		\
+	((const u8*)(x))[3])
+
+#define AV_RL32(x)				\
+	(((u32)((const u8*)(x))[3] << 24) |	\
+	(((const u8*)(x))[2] << 16) |		\
+	(((const u8*)(x))[1] <<  8) |		\
+	((const u8*)(x))[0])
+
+#define NEG_SSR32(a, s)   (((int)(a)) >> ((s < 32) ? (32 - (s)) : 0))
+#define NEG_USR32(a, s)   (((u32)(a)) >> ((s < 32) ? (32 - (s)) : 0))
+
+//rounded division & shift
+#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b))
+/* assume b>0 */
+#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))
+
+struct AVRational{
+	int num; ///< numerator
+	int den; ///< denominator
+};
+
+#ifndef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
+/**
+ * YUV colorspace type.
+ * These values match the ones defined by ISO/IEC 23001-8_2013 ¡ì 7.3.
+ */
+enum AVColorSpace {
+	AVCOL_SPC_RGB         = 0,  ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB)
+	AVCOL_SPC_BT709       = 1,  ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B
+	AVCOL_SPC_UNSPECIFIED = 2,
+	AVCOL_SPC_RESERVED    = 3,
+	AVCOL_SPC_FCC         = 4,  ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
+	AVCOL_SPC_BT470BG     = 5,  ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
+	AVCOL_SPC_SMPTE170M   = 6,  ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
+	AVCOL_SPC_SMPTE240M   = 7,  ///< functionally identical to above
+	AVCOL_SPC_YCGCO       = 8,  ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16
+	AVCOL_SPC_YCOCG       = AVCOL_SPC_YCGCO,
+	AVCOL_SPC_BT2020_NCL  = 9,  ///< ITU-R BT2020 non-constant luminance system
+	AVCOL_SPC_BT2020_CL   = 10, ///< ITU-R BT2020 constant luminance system
+	AVCOL_SPC_SMPTE2085   = 11, ///< SMPTE 2085, Y'D'zD'x
+	AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system
+	AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system
+	AVCOL_SPC_ICTCP       = 14, ///< ITU-R BT.2100-0, ICtCp
+	AVCOL_SPC_NB                ///< Not part of ABI
+};
+
+/**
+  * Chromaticity coordinates of the source primaries.
+  * These values match the ones defined by ISO/IEC 23001-8_2013 ¡ì 7.1.
+  */
+enum AVColorPrimaries {
+	AVCOL_PRI_RESERVED0   = 0,
+	AVCOL_PRI_BT709       = 1,  ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B
+	AVCOL_PRI_UNSPECIFIED = 2,
+	AVCOL_PRI_RESERVED    = 3,
+	AVCOL_PRI_BT470M      = 4,  ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
+
+	AVCOL_PRI_BT470BG     = 5,  ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM
+	AVCOL_PRI_SMPTE170M   = 6,  ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
+	AVCOL_PRI_SMPTE240M   = 7,  ///< functionally identical to above
+	AVCOL_PRI_FILM        = 8,  ///< colour filters using Illuminant C
+	AVCOL_PRI_BT2020      = 9,  ///< ITU-R BT2020
+	AVCOL_PRI_SMPTE428    = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ)
+	AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428,
+	AVCOL_PRI_SMPTE431    = 11, ///< SMPTE ST 431-2 (2011) / DCI P3
+	AVCOL_PRI_SMPTE432    = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3
+	AVCOL_PRI_JEDEC_P22   = 22, ///< JEDEC P22 phosphors
+	AVCOL_PRI_NB                ///< Not part of ABI
+};
+
+/**
+ * Color Transfer Characteristic.
+ * These values match the ones defined by ISO/IEC 23001-8_2013 ¡ì 7.2.
+ */
+enum AVColorTransferCharacteristic {
+	AVCOL_TRC_RESERVED0    = 0,
+	AVCOL_TRC_BT709        = 1,  ///< also ITU-R BT1361
+	AVCOL_TRC_UNSPECIFIED  = 2,
+	AVCOL_TRC_RESERVED     = 3,
+	AVCOL_TRC_GAMMA22      = 4,  ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
+	AVCOL_TRC_GAMMA28      = 5,  ///< also ITU-R BT470BG
+	AVCOL_TRC_SMPTE170M    = 6,  ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC
+	AVCOL_TRC_SMPTE240M    = 7,
+	AVCOL_TRC_LINEAR       = 8,  ///< "Linear transfer characteristics"
+	AVCOL_TRC_LOG          = 9,  ///< "Logarithmic transfer characteristic (100:1 range)"
+	AVCOL_TRC_LOG_SQRT     = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)"
+	AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4
+	AVCOL_TRC_BT1361_ECG   = 12, ///< ITU-R BT1361 Extended Colour Gamut
+	AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC)
+	AVCOL_TRC_BT2020_10    = 14, ///< ITU-R BT2020 for 10-bit system
+	AVCOL_TRC_BT2020_12    = 15, ///< ITU-R BT2020 for 12-bit system
+	AVCOL_TRC_SMPTE2084    = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems
+	AVCOL_TRC_SMPTEST2084  = AVCOL_TRC_SMPTE2084,
+	AVCOL_TRC_SMPTE428     = 17, ///< SMPTE ST 428-1
+	AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428,
+	AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma"
+	AVCOL_TRC_NB                 ///< Not part of ABI
+};
+#endif
+
+//fmt
+const char *av_color_space_name(enum AVColorSpace space);
+const char *av_color_primaries_name(enum AVColorPrimaries primaries);
+const char *av_color_transfer_name(enum AVColorTransferCharacteristic transfer);
+
+//math
+int av_log2(u32 v);
+
+//bitstream
+int find_start_code(u8 *data, int data_sz);
+int calc_nal_len(u8 *data, int len);
+u8 *nal_unit_extract_rbsp(const u8 *src, u32 src_len, u32 *dst_len);
+
+//debug
+void print_hex_debug(u8 *data, u32 len, int max);
+
+bool is_over_size(int w, int h, int size);
+
+#endif
\ No newline at end of file
diff --git a/drivers/amvdec_ports/utils/get_bits.h b/drivers/amvdec_ports/utils/get_bits.h
new file mode 100644
index 0000000..bb98ebd
--- /dev/null
+++ b/drivers/amvdec_ports/utils/get_bits.h
@@ -0,0 +1,590 @@
+#ifndef AVCODEC_GET_BITS_H
+#define AVCODEC_GET_BITS_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include "common.h"
+
+/*
+ * Safe bitstream reading:
+ * optionally, the get_bits API can check to ensure that we
+ * don't read past input buffer boundaries. This is protected
+ * with CONFIG_SAFE_BITSTREAM_READER at the global level, and
+ * then below that with UNCHECKED_BITSTREAM_READER at the per-
+ * decoder level. This means that decoders that check internally
+ * can "#define UNCHECKED_BITSTREAM_READER 1" to disable
+ * overread checks.
+ * Boundary checking causes a minor performance penalty so for
+ * applications that won't want/need this, it can be disabled
+ * globally using "#define CONFIG_SAFE_BITSTREAM_READER 0".
+ */
+
+struct get_bits_context {
+	const u8 *buffer;
+	const u8 *buffer_end;
+	int index;
+	int size_in_bits;
+	int size_in_bits_plus8;
+};
+
+/* Bitstream reader API docs:
+ * name
+ *   arbitrary name which is used as prefix for the internal variables
+ *
+ * gb
+ *   struct get_bits_context
+ *
+ * OPEN_READER(name, gb)
+ *   load gb into local variables
+ *
+ * CLOSE_READER(name, gb)
+ *   store local vars in gb
+ *
+ * UPDATE_CACHE(name, gb)
+ *   Refill the internal cache from the bitstream.
+ *   After this call at least MIN_CACHE_BITS will be available.
+ *
+ * GET_CACHE(name, gb)
+ *   Will output the contents of the internal cache,
+ *   next bit is MSB of 32 or 64 bits (FIXME 64 bits).
+ *
+ * SHOW_UBITS(name, gb, num)
+ *   Will return the next num bits.
+ *
+ * SHOW_SBITS(name, gb, num)
+ *   Will return the next num bits and do sign extension.
+ *
+ * SKIP_BITS(name, gb, num)
+ *   Will skip over the next num bits.
+ *   Note, this is equivalent to SKIP_CACHE; SKIP_COUNTER.
+ *
+ * SKIP_CACHE(name, gb, num)
+ *   Will remove the next num bits from the cache (note SKIP_COUNTER
+ *   MUST be called before UPDATE_CACHE / CLOSE_READER).
+ *
+ * SKIP_COUNTER(name, gb, num)
+ *   Will increment the internal bit counter (see SKIP_CACHE & SKIP_BITS).
+ *
+ * LAST_SKIP_BITS(name, gb, num)
+ *   Like SKIP_BITS, to be used if next call is UPDATE_CACHE or CLOSE_READER.
+ *
+ * BITS_LEFT(name, gb)
+ *   Return the number of bits left
+ *
+ * For examples see get_bits, show_bits, skip_bits, get_vlc.
+ */
+
+#define OPEN_READER_NOSIZE(name, gb)		\
+	u32 name ## _index = (gb)->index;	\
+	u32 name ## _cache
+
+#define OPEN_READER(name, gb) OPEN_READER_NOSIZE(name, gb)
+#define BITS_AVAILABLE(name, gb) 1
+
+#define CLOSE_READER(name, gb) (gb)->index = name ## _index
+
+#define UPDATE_CACHE_LE(name, gb) name ##_cache = \
+      AV_RL32((gb)->buffer + (name ## _index >> 3)) >> (name ## _index & 7)
+
+#define UPDATE_CACHE_BE(name, gb) name ## _cache = \
+      AV_RB32((gb)->buffer + (name ## _index >> 3)) << (name ## _index & 7)
+
+#define SKIP_COUNTER(name, gb, num) name ## _index += (num)
+
+#define BITS_LEFT(name, gb) ((int)((gb)->size_in_bits - name ## _index))
+
+#define SKIP_BITS(name, gb, num)		\
+	do {					\
+		SKIP_CACHE(name, gb, num);	\
+		SKIP_COUNTER(name, gb, num);	\
+	} while (0)
+
+#define GET_CACHE(name, gb) ((u32) name ## _cache)
+
+#define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num)
+
+#define SHOW_UBITS_LE(name, gb, num) zero_extend(name ## _cache, num)
+#define SHOW_SBITS_LE(name, gb, num) sign_extend(name ## _cache, num)
+
+#define SHOW_UBITS_BE(name, gb, num) NEG_USR32(name ## _cache, num)
+#define SHOW_SBITS_BE(name, gb, num) NEG_SSR32(name ## _cache, num)
+
+#ifdef BITSTREAM_READER_LE
+#define UPDATE_CACHE(name, gb) UPDATE_CACHE_LE(name, gb)
+#define SKIP_CACHE(name, gb, num) name ## _cache >>= (num)
+
+#define SHOW_UBITS(name, gb, num) SHOW_UBITS_LE(name, gb, num)
+#define SHOW_SBITS(name, gb, num) SHOW_SBITS_LE(name, gb, num)
+#else
+#define UPDATE_CACHE(name, gb) UPDATE_CACHE_BE(name, gb)
+#define SKIP_CACHE(name, gb, num) name ## _cache <<= (num)
+
+#define SHOW_UBITS(name, gb, num) SHOW_UBITS_BE(name, gb, num)
+#define SHOW_SBITS(name, gb, num) SHOW_SBITS_BE(name, gb, num)
+#endif
+
+static inline const int sign_extend(int val, u32 bits)
+{
+	u32 shift = 8 * sizeof(int) - bits;
+
+	union { u32 u; int s; } v = { (u32) val << shift };
+	return v.s >> shift;
+}
+
+static inline u32 zero_extend(u32 val, u32 bits)
+{
+	return (val << ((8 * sizeof(int)) - bits)) >> ((8 * sizeof(int)) - bits);
+}
+
+static inline int get_bits_count(const struct get_bits_context *s)
+{
+	return s->index;
+}
+
+/**
+ * Skips the specified number of bits.
+ * @param n the number of bits to skip,
+ *          For the UNCHECKED_BITSTREAM_READER this must not cause the distance
+ *          from the start to overflow int. Staying within the bitstream + padding
+ *          is sufficient, too.
+ */
+static inline void skip_bits_long(struct get_bits_context *s, int n)
+{
+	s->index += n;
+}
+
+/**
+ * Read MPEG-1 dc-style VLC (sign bit + mantissa with no MSB).
+ * if MSB not set it is negative
+ * @param n length in bits
+ */
+static inline int get_xbits(struct get_bits_context *s, int n)
+{
+	register int sign;
+	register int cache;
+
+	OPEN_READER(re, s);
+	UPDATE_CACHE(re, s);
+	cache = GET_CACHE(re, s);
+	sign  = ~cache >> 31;
+	LAST_SKIP_BITS(re, s, n);
+	CLOSE_READER(re, s);
+
+	return (NEG_USR32(sign ^ cache, n) ^ sign) - sign;
+}
+
+
+static inline int get_xbits_le(struct get_bits_context *s, int n)
+{
+	register int sign;
+	register int cache;
+
+	OPEN_READER(re, s);
+	UPDATE_CACHE_LE(re, s);
+	cache = GET_CACHE(re, s);
+	sign  = sign_extend(~cache, n) >> 31;
+	LAST_SKIP_BITS(re, s, n);
+	CLOSE_READER(re, s);
+
+	return (zero_extend(sign ^ cache, n) ^ sign) - sign;
+}
+
+static inline int get_sbits(struct get_bits_context *s, int n)
+{
+	register int tmp;
+
+	OPEN_READER(re, s);
+	UPDATE_CACHE(re, s);
+	tmp = SHOW_SBITS(re, s, n);
+	LAST_SKIP_BITS(re, s, n);
+	CLOSE_READER(re, s);
+
+	return tmp;
+}
+
+/**
+ * Read 1-25 bits.
+ */
+static inline u32 get_bits(struct get_bits_context *s, int n)
+{
+	register u32 tmp;
+
+	OPEN_READER(re, s);
+	UPDATE_CACHE(re, s);
+	tmp = SHOW_UBITS(re, s, n);
+	LAST_SKIP_BITS(re, s, n);
+	CLOSE_READER(re, s);
+
+	return tmp;
+}
+
+/**
+ * Read 0-25 bits.
+ */
+static inline int get_bitsz(struct get_bits_context *s, int n)
+{
+	return n ? get_bits(s, n) : 0;
+}
+
+static inline u32 get_bits_le(struct get_bits_context *s, int n)
+{
+	register int tmp;
+
+	OPEN_READER(re, s);
+	UPDATE_CACHE_LE(re, s);
+	tmp = SHOW_UBITS_LE(re, s, n);
+	LAST_SKIP_BITS(re, s, n);
+	CLOSE_READER(re, s);
+
+	return tmp;
+}
+
+/**
+ * Show 1-25 bits.
+ */
+static inline u32 show_bits(struct get_bits_context *s, int n)
+{
+	register u32 tmp;
+
+	OPEN_READER_NOSIZE(re, s);
+	UPDATE_CACHE(re, s);
+	tmp = SHOW_UBITS(re, s, n);
+
+	return tmp;
+}
+
+static inline void skip_bits(struct get_bits_context *s, int n)
+{
+	u32 re_index = s->index;
+	LAST_SKIP_BITS(re, s, n);
+	CLOSE_READER(re, s);
+}
+
+static inline u32 get_bits1(struct get_bits_context *s)
+{
+	u32 index = s->index;
+	u8 result = s->buffer[index >> 3];
+
+#ifdef BITSTREAM_READER_LE
+	result >>= index & 7;
+	result  &= 1;
+#else
+	result <<= index & 7;
+	result >>= 8 - 1;
+#endif
+
+	index++;
+	s->index = index;
+
+	return result;
+}
+
+static inline u32 show_bits1(struct get_bits_context *s)
+{
+	return show_bits(s, 1);
+}
+
+static inline void skip_bits1(struct get_bits_context *s)
+{
+	skip_bits(s, 1);
+}
+
+/**
+ * Read 0-32 bits.
+ */
+static inline u32 get_bits_long(struct get_bits_context *s, int n)
+{
+	if (!n) {
+		return 0;
+	} else if (n <= MIN_CACHE_BITS) {
+		return get_bits(s, n);
+	} else {
+#ifdef BITSTREAM_READER_LE
+		u32 ret = get_bits(s, 16);
+		return ret | (get_bits(s, n - 16) << 16);
+#else
+		u32 ret = get_bits(s, 16) << (n - 16);
+		return ret | get_bits(s, n - 16);
+#endif
+	}
+}
+
+/**
+ * Read 0-64 bits.
+ */
+static inline u64 get_bits64(struct get_bits_context *s, int n)
+{
+	if (n <= 32) {
+		return get_bits_long(s, n);
+	} else {
+#ifdef BITSTREAM_READER_LE
+		u64 ret = get_bits_long(s, 32);
+		return ret | (u64) get_bits_long(s, n - 32) << 32;
+#else
+		u64 ret = (u64) get_bits_long(s, n - 32) << 32;
+		return ret | get_bits_long(s, 32);
+#endif
+	}
+}
+
+/**
+ * Read 0-32 bits as a signed integer.
+ */
+static inline int get_sbits_long(struct get_bits_context *s, int n)
+{
+	if (!n)
+		return 0;
+
+	return sign_extend(get_bits_long(s, n), n);
+}
+
+/**
+ * Show 0-32 bits.
+ */
+static inline u32 show_bits_long(struct get_bits_context *s, int n)
+{
+	if (n <= MIN_CACHE_BITS) {
+		return show_bits(s, n);
+	} else {
+		struct get_bits_context gb = *s;
+
+		return get_bits_long(&gb, n);
+	}
+}
+
+static inline int check_marker(struct get_bits_context *s, const char *msg)
+{
+	int bit = get_bits1(s);
+
+	if (!bit)
+		pr_err("Marker bit missing at %d of %d %s\n",
+			get_bits_count(s) - 1, s->size_in_bits, msg);
+	return bit;
+}
+
+static inline int init_get_bits_xe(struct get_bits_context *s,
+	const u8 *buffer, int bit_size, int is_le)
+{
+	int buffer_size;
+	int ret = 0;
+
+	if (bit_size >= INT_MAX - FFMAX(7, AV_INPUT_BUFFER_PADDING_SIZE * 8) ||
+		bit_size < 0 || !buffer) {
+		bit_size    = 0;
+		buffer      = NULL;
+		ret         = -1;
+	}
+
+	buffer_size = (bit_size + 7) >> 3;
+
+	s->buffer             = buffer;
+	s->size_in_bits       = bit_size;
+	s->size_in_bits_plus8 = bit_size + 8;
+	s->buffer_end         = buffer + buffer_size;
+	s->index              = 0;
+
+	return ret;
+}
+
+/**
+ * Initialize struct get_bits_context.
+ * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes
+ *        larger than the actual read bits because some optimized bitstream
+ *        readers read 32 or 64 bit at once and could read over the end
+ * @param bit_size the size of the buffer in bits
+ * @return 0 on success, -1 if the buffer_size would overflow.
+ */
+static inline int init_get_bits(struct get_bits_context *s,
+	const u8 *buffer, int bit_size)
+{
+#ifdef BITSTREAM_READER_LE
+	return init_get_bits_xe(s, buffer, bit_size, 1);
+#else
+	return init_get_bits_xe(s, buffer, bit_size, 0);
+#endif
+}
+
+/**
+ * Initialize struct get_bits_context.
+ * @param buffer bitstream buffer, must be AV_INPUT_BUFFER_PADDING_SIZE bytes
+ *        larger than the actual read bits because some optimized bitstream
+ *        readers read 32 or 64 bit at once and could read over the end
+ * @param byte_size the size of the buffer in bytes
+ * @return 0 on success, -1 if the buffer_size would overflow.
+ */
+static inline int init_get_bits8(struct get_bits_context *s,
+	const u8 *buffer, int byte_size)
+{
+	if (byte_size > INT_MAX / 8 || byte_size < 0)
+		byte_size = -1;
+	return init_get_bits(s, buffer, byte_size * 8);
+}
+
+static inline int init_get_bits8_le(struct get_bits_context *s,
+	const u8 *buffer, int byte_size)
+{
+	if (byte_size > INT_MAX / 8 || byte_size < 0)
+		byte_size = -1;
+	return init_get_bits_xe(s, buffer, byte_size * 8, 1);
+}
+
+static inline const u8 *align_get_bits(struct get_bits_context *s)
+{
+	int n = -get_bits_count(s) & 7;
+
+	if (n)
+		skip_bits(s, n);
+	return s->buffer + (s->index >> 3);
+}
+
+/**
+ * If the vlc code is invalid and max_depth=1, then no bits will be removed.
+ * If the vlc code is invalid and max_depth>1, then the number of bits removed
+ * is undefined.
+ */
+#define GET_VLC(code, name, gb, table, bits, max_depth)         \
+    do {                                                        \
+        int n, nb_bits;                                         \
+        u32 index;                                              \
+                                                                \
+        index = SHOW_UBITS(name, gb, bits);                     \
+        code  = table[index][0];                                \
+        n     = table[index][1];                                \
+                                                                \
+        if (max_depth > 1 && n < 0) {                           \
+            LAST_SKIP_BITS(name, gb, bits);                     \
+            UPDATE_CACHE(name, gb);                             \
+                                                                \
+            nb_bits = -n;                                       \
+                                                                \
+            index = SHOW_UBITS(name, gb, nb_bits) + code;       \
+            code  = table[index][0];                            \
+            n     = table[index][1];                            \
+            if (max_depth > 2 && n < 0) {                       \
+                LAST_SKIP_BITS(name, gb, nb_bits);              \
+                UPDATE_CACHE(name, gb);                         \
+                                                                \
+                nb_bits = -n;                                   \
+                                                                \
+                index = SHOW_UBITS(name, gb, nb_bits) + code;   \
+                code  = table[index][0];                        \
+                n     = table[index][1];                        \
+            }                                                   \
+        }                                                       \
+        SKIP_BITS(name, gb, n);                                 \
+    } while (0)
+
+#define GET_RL_VLC(level, run, name, gb, table, bits,           \
+                   max_depth, need_update)                      \
+    do {                                                        \
+        int n, nb_bits;                                         \
+        u32 index;                                              \
+                                                                \
+        index = SHOW_UBITS(name, gb, bits);                     \
+        level = table[index].level;                             \
+        n     = table[index].len;                               \
+                                                                \
+        if (max_depth > 1 && n < 0) {                           \
+            SKIP_BITS(name, gb, bits);                          \
+            if (need_update) {                                  \
+                UPDATE_CACHE(name, gb);                         \
+            }                                                   \
+                                                                \
+            nb_bits = -n;                                       \
+                                                                \
+            index = SHOW_UBITS(name, gb, nb_bits) + level;      \
+            level = table[index].level;                         \
+            n     = table[index].len;                           \
+            if (max_depth > 2 && n < 0) {                       \
+                LAST_SKIP_BITS(name, gb, nb_bits);              \
+                if (need_update) {                              \
+                    UPDATE_CACHE(name, gb);                     \
+                }                                               \
+                nb_bits = -n;                                   \
+                                                                \
+                index = SHOW_UBITS(name, gb, nb_bits) + level;  \
+                level = table[index].level;                     \
+                n     = table[index].len;                       \
+            }                                                   \
+        }                                                       \
+        run = table[index].run;                                 \
+        SKIP_BITS(name, gb, n);                                 \
+    } while (0)
+
+/* Return the LUT element for the given bitstream configuration. */
+static inline int set_idx(struct get_bits_context *s,
+	int code, int *n, int *nb_bits, int (*table)[2])
+{
+	u32 idx;
+
+	*nb_bits = -*n;
+	idx = show_bits(s, *nb_bits) + code;
+	*n = table[idx][1];
+
+	return table[idx][0];
+}
+
+/**
+ * Parse a vlc code.
+ * @param bits is the number of bits which will be read at once, must be
+ *             identical to nb_bits in init_vlc()
+ * @param max_depth is the number of times bits bits must be read to completely
+ *                  read the longest vlc code
+ *                  = (max_vlc_length + bits - 1) / bits
+ * @returns the code parsed or -1 if no vlc matches
+ */
+static inline int get_vlc2(struct get_bits_context *s,
+	int (*table)[2], int bits, int max_depth)
+{
+	int code;
+
+	OPEN_READER(re, s);
+	UPDATE_CACHE(re, s);
+
+	GET_VLC(code, re, s, table, bits, max_depth);
+
+	CLOSE_READER(re, s);
+
+	return code;
+}
+
+static inline int decode012(struct get_bits_context *gb)
+{
+	int n;
+
+	n = get_bits1(gb);
+	if (n == 0)
+		return 0;
+	else
+		return get_bits1(gb) + 1;
+}
+
+static inline int decode210(struct get_bits_context *gb)
+{
+	if (get_bits1(gb))
+		return 0;
+	else
+		return 2 - get_bits1(gb);
+}
+
+static inline int get_bits_left(struct get_bits_context *gb)
+{
+	return gb->size_in_bits - get_bits_count(gb);
+}
+
+static inline int skip_1stop_8data_bits(struct get_bits_context *gb)
+{
+	if (get_bits_left(gb) <= 0)
+	return -1;
+
+	while (get_bits1(gb)) {
+		skip_bits(gb, 8);
+		if (get_bits_left(gb) <= 0)
+			return -1;
+	}
+
+	return 0;
+}
+
+#endif /* AVCODEC_GET_BITS_H */
+
diff --git a/drivers/amvdec_ports/utils/golomb.c b/drivers/amvdec_ports/utils/golomb.c
new file mode 100644
index 0000000..21fcb6a
--- /dev/null
+++ b/drivers/amvdec_ports/utils/golomb.c
@@ -0,0 +1,147 @@
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+const u8 ff_golomb_vlc_len[512]={
+	19,17,15,15,13,13,13,13,11,11,11,11,11,11,11,11,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+	5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+	5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+	3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+	3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+	3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+	3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
+};
+
+const u8 ff_ue_golomb_vlc_code[512]={
+	32,32,32,32,32,32,32,32,31,32,32,32,32,32,32,32,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
+	 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9,10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13,14,14,14,14,
+	 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+	 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+const char ff_se_golomb_vlc_code[512]={
+	 17, 17, 17, 17, 17, 17, 17, 17, 16, 17, 17, 17, 17, 17, 17, 17,  8, -8,  9, -9, 10,-10, 11,-11, 12,-12, 13,-13, 14,-14, 15,-15,
+	  4,  4,  4,  4, -4, -4, -4, -4,  5,  5,  5,  5, -5, -5, -5, -5,  6,  6,  6,  6, -6, -6, -6, -6,  7,  7,  7,  7, -7, -7, -7, -7,
+	  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
+	  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3,
+	  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+	  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+	 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+};
+
+const u8 ff_ue_golomb_len[256]={
+	 1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,11,
+	11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,
+	13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
+	13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,15,
+	15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+	15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+	15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+	15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,17,
+};
+
+const u8 ff_interleaved_golomb_vlc_len[256]={
+	9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5,
+	9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5,
+	3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+	3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+	9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5,
+	9,9,7,7,9,9,7,7,5,5,5,5,5,5,5,5,
+	3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+	3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+};
+
+const u8 ff_interleaved_ue_golomb_vlc_code[256]={
+	15,16,7, 7, 17,18,8, 8, 3, 3, 3, 3, 3, 3, 3, 3,
+	19,20,9, 9, 21,22,10,10,4, 4, 4, 4, 4, 4, 4, 4,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	23,24,11,11,25,26,12,12,5, 5, 5, 5, 5, 5, 5, 5,
+	27,28,13,13,29,30,14,14,6, 6, 6, 6, 6, 6, 6, 6,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+const char ff_interleaved_se_golomb_vlc_code[256]={
+	8, -8,  4,  4,  9, -9, -4, -4,  2,  2,  2,  2,  2,  2,  2,  2,
+	10,-10,  5,  5, 11,-11, -5, -5, -2, -2, -2, -2, -2, -2, -2, -2,
+	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+	1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+	12,-12,  6,  6, 13,-13, -6, -6,  3,  3,  3,  3,  3,  3,  3,  3,
+	14,-14,  7,  7, 15,-15, -7, -7, -3, -3, -3, -3, -3, -3, -3, -3,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+};
+
+const u8 ff_interleaved_dirac_golomb_vlc_code[256]={
+	0, 1, 0, 0, 2, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+	4, 5, 2, 2, 6, 7, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	8, 9, 4, 4, 10,11,5, 5, 2, 2, 2, 2, 2, 2, 2, 2,
+	12,13,6, 6, 14,15,7, 7, 3, 3, 3, 3, 3, 3, 3, 3,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
diff --git a/drivers/amvdec_ports/utils/golomb.h b/drivers/amvdec_ports/utils/golomb.h
new file mode 100644
index 0000000..d66c182
--- /dev/null
+++ b/drivers/amvdec_ports/utils/golomb.h
@@ -0,0 +1,500 @@
+#ifndef AVCODEC_GOLOMB_H
+#define AVCODEC_GOLOMB_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include "get_bits.h"
+#include "put_bits.h"
+#include "common.h"
+
+#define INVALID_VLC           0x80000000
+
+extern const u8 ff_golomb_vlc_len[512];
+extern const u8 ff_ue_golomb_vlc_code[512];
+extern const char ff_se_golomb_vlc_code[512];
+extern const u8 ff_ue_golomb_len[256];
+
+extern const u8 ff_interleaved_golomb_vlc_len[256];
+extern const u8 ff_interleaved_ue_golomb_vlc_code[256];
+extern const char ff_interleaved_se_golomb_vlc_code[256];
+extern const u8 ff_interleaved_dirac_golomb_vlc_code[256];
+
+/**
+ * Read an u32 Exp-Golomb code in the range 0 to 8190.
+ *
+ * @returns the read value or a negative error code.
+ */
+static inline int get_ue_golomb(struct get_bits_context *gb)
+{
+	u32 buf;
+
+	OPEN_READER(re, gb);
+	UPDATE_CACHE(re, gb);
+	buf = GET_CACHE(re, gb);
+
+	if (buf >= (1 << 27)) {
+		buf >>= 32 - 9;
+		LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]);
+		CLOSE_READER(re, gb);
+
+		return ff_ue_golomb_vlc_code[buf];
+	} else {
+		int log = 2 * av_log2(buf) - 31;
+		LAST_SKIP_BITS(re, gb, 32 - log);
+		CLOSE_READER(re, gb);
+		if (log < 7) {
+			pr_err("Invalid UE golomb code\n");
+			return -1;
+		}
+		buf >>= log;
+		buf--;
+
+		return buf;
+	}
+}
+
+/**
+ * Read an u32 Exp-Golomb code in the range 0 to UINT_MAX-1.
+ */
+static inline u32 get_ue_golomb_long(struct get_bits_context *gb)
+{
+	u32 buf, log;
+
+	buf = show_bits_long(gb, 32);
+	log = 31 - av_log2(buf);
+	skip_bits_long(gb, log);
+
+	return get_bits_long(gb, log + 1) - 1;
+}
+
+/**
+ * read u32 exp golomb code, constraint to a max of 31.
+ * the return value is undefined if the stored value exceeds 31.
+ */
+static inline int get_ue_golomb_31(struct get_bits_context *gb)
+{
+	u32 buf;
+
+	OPEN_READER(re, gb);
+	UPDATE_CACHE(re, gb);
+	buf = GET_CACHE(re, gb);
+
+	buf >>= 32 - 9;
+	LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]);
+	CLOSE_READER(re, gb);
+
+	return ff_ue_golomb_vlc_code[buf];
+}
+
+static inline u32 get_interleaved_ue_golomb(struct get_bits_context *gb)
+{
+	u32 buf;
+
+	OPEN_READER(re, gb);
+	UPDATE_CACHE(re, gb);
+	buf = GET_CACHE(re, gb);
+
+	if (buf & 0xAA800000) {
+		buf >>= 32 - 8;
+		LAST_SKIP_BITS(re, gb, ff_interleaved_golomb_vlc_len[buf]);
+		CLOSE_READER(re, gb);
+
+		return ff_interleaved_ue_golomb_vlc_code[buf];
+	} else {
+		u32 ret = 1;
+
+		do {
+			buf >>= 32 - 8;
+			LAST_SKIP_BITS(re, gb,
+			FFMIN(ff_interleaved_golomb_vlc_len[buf], 8));
+
+			if (ff_interleaved_golomb_vlc_len[buf] != 9) {
+				ret <<= (ff_interleaved_golomb_vlc_len[buf] - 1) >> 1;
+				ret  |= ff_interleaved_dirac_golomb_vlc_code[buf];
+				break;
+			}
+			ret = (ret << 4) | ff_interleaved_dirac_golomb_vlc_code[buf];
+			UPDATE_CACHE(re, gb);
+			buf = GET_CACHE(re, gb);
+		} while (ret<0x8000000U && BITS_AVAILABLE(re, gb));
+
+		CLOSE_READER(re, gb);
+		return ret - 1;
+	}
+}
+
+/**
+ * read u32 truncated exp golomb code.
+ */
+static inline int get_te0_golomb(struct get_bits_context *gb, int range)
+{
+	if (range == 1)
+		return 0;
+	else if (range == 2)
+		return get_bits1(gb) ^ 1;
+	else
+		return get_ue_golomb(gb);
+}
+
+/**
+ * read u32 truncated exp golomb code.
+ */
+static inline int get_te_golomb(struct get_bits_context *gb, int range)
+{
+	if (range == 2)
+		return get_bits1(gb) ^ 1;
+	else
+		return get_ue_golomb(gb);
+}
+
+/**
+ * read signed exp golomb code.
+ */
+static inline int get_se_golomb(struct get_bits_context *gb)
+{
+	u32 buf;
+
+	OPEN_READER(re, gb);
+	UPDATE_CACHE(re, gb);
+	buf = GET_CACHE(re, gb);
+
+	if (buf >= (1 << 27)) {
+		buf >>= 32 - 9;
+		LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]);
+		CLOSE_READER(re, gb);
+
+		return ff_se_golomb_vlc_code[buf];
+	} else {
+		int log = av_log2(buf), sign;
+		LAST_SKIP_BITS(re, gb, 31 - log);
+		UPDATE_CACHE(re, gb);
+		buf = GET_CACHE(re, gb);
+
+		buf >>= log;
+
+		LAST_SKIP_BITS(re, gb, 32 - log);
+		CLOSE_READER(re, gb);
+
+		sign = -(buf & 1);
+		buf  = ((buf >> 1) ^ sign) - sign;
+
+		return buf;
+	}
+}
+
+static inline int get_se_golomb_long(struct get_bits_context *gb)
+{
+	u32 buf = get_ue_golomb_long(gb);
+	int sign = (buf & 1) - 1;
+
+	return ((buf >> 1) ^ sign) + 1;
+}
+
+static inline int get_interleaved_se_golomb(struct get_bits_context *gb)
+{
+	u32 buf;
+
+	OPEN_READER(re, gb);
+	UPDATE_CACHE(re, gb);
+	buf = GET_CACHE(re, gb);
+
+	if (buf & 0xAA800000) {
+		buf >>= 32 - 8;
+		LAST_SKIP_BITS(re, gb, ff_interleaved_golomb_vlc_len[buf]);
+		CLOSE_READER(re, gb);
+
+		return ff_interleaved_se_golomb_vlc_code[buf];
+	} else {
+		int log;
+		LAST_SKIP_BITS(re, gb, 8);
+		UPDATE_CACHE(re, gb);
+		buf |= 1 | (GET_CACHE(re, gb) >> 8);
+
+		if ((buf & 0xAAAAAAAA) == 0)
+			return INVALID_VLC;
+
+		for (log = 31; (buf & 0x80000000) == 0; log--)
+			buf = (buf << 2) - ((buf << log) >> (log - 1)) + (buf >> 30);
+
+		LAST_SKIP_BITS(re, gb, 63 - 2 * log - 8);
+		CLOSE_READER(re, gb);
+		return (signed) (((((buf << log) >> log) - 1) ^ -(buf & 0x1)) + 1) >> 1;
+	}
+}
+
+static inline int dirac_get_se_golomb(struct get_bits_context *gb)
+{
+	u32 ret = get_interleaved_ue_golomb(gb);
+
+	if (ret) {
+		int sign = -get_bits1(gb);
+		ret = (ret ^ sign) - sign;
+	}
+
+	return ret;
+}
+
+/**
+ * read u32 golomb rice code (ffv1).
+ */
+static inline int get_ur_golomb(struct get_bits_context *gb,
+	int k, int limit, int esc_len)
+{
+	u32 buf;
+	int log;
+
+	OPEN_READER(re, gb);
+	UPDATE_CACHE(re, gb);
+	buf = GET_CACHE(re, gb);
+
+	log = av_log2(buf);
+
+	if (log > 31 - limit) {
+		buf >>= log - k;
+		buf  += (30U - log) << k;
+		LAST_SKIP_BITS(re, gb, 32 + k - log);
+		CLOSE_READER(re, gb);
+
+		return buf;
+	} else {
+		LAST_SKIP_BITS(re, gb, limit);
+		UPDATE_CACHE(re, gb);
+
+		buf = SHOW_UBITS(re, gb, esc_len);
+
+		LAST_SKIP_BITS(re, gb, esc_len);
+		CLOSE_READER(re, gb);
+
+		return buf + limit - 1;
+	}
+}
+
+/**
+ * read u32 golomb rice code (jpegls).
+ */
+static inline int get_ur_golomb_jpegls(struct get_bits_context *gb,
+	int k, int limit, int esc_len)
+{
+	u32 buf;
+	int log;
+
+	OPEN_READER(re, gb);
+	UPDATE_CACHE(re, gb);
+	buf = GET_CACHE(re, gb);
+
+	log = av_log2(buf);
+
+	if (log - k >= 32 - MIN_CACHE_BITS + (MIN_CACHE_BITS == 32) &&
+		32 - log < limit) {
+		buf >>= log - k;
+		buf  += (30U - log) << k;
+		LAST_SKIP_BITS(re, gb, 32 + k - log);
+		CLOSE_READER(re, gb);
+
+		return buf;
+	} else {
+		int i;
+		for (i = 0; i + MIN_CACHE_BITS <= limit && SHOW_UBITS(re, gb, MIN_CACHE_BITS) == 0; i += MIN_CACHE_BITS) {
+			if (gb->size_in_bits <= re_index) {
+				CLOSE_READER(re, gb);
+				return -1;
+			}
+			LAST_SKIP_BITS(re, gb, MIN_CACHE_BITS);
+			UPDATE_CACHE(re, gb);
+		}
+		for (; i < limit && SHOW_UBITS(re, gb, 1) == 0; i++) {
+			SKIP_BITS(re, gb, 1);
+		}
+		LAST_SKIP_BITS(re, gb, 1);
+		UPDATE_CACHE(re, gb);
+
+		if (i < limit - 1) {
+			if (k) {
+				if (k > MIN_CACHE_BITS - 1) {
+					buf = SHOW_UBITS(re, gb, 16) << (k-16);
+					LAST_SKIP_BITS(re, gb, 16);
+					UPDATE_CACHE(re, gb);
+					buf |= SHOW_UBITS(re, gb, k-16);
+					LAST_SKIP_BITS(re, gb, k-16);
+				} else {
+					buf = SHOW_UBITS(re, gb, k);
+					LAST_SKIP_BITS(re, gb, k);
+				}
+			} else {
+				buf = 0;
+			}
+			buf += ((u32)i << k);
+		} else if (i == limit - 1) {
+			buf = SHOW_UBITS(re, gb, esc_len);
+			LAST_SKIP_BITS(re, gb, esc_len);
+
+			buf ++;
+		} else {
+			buf = -1;
+		}
+		CLOSE_READER(re, gb);
+		return buf;
+	}
+}
+
+/**
+ * read signed golomb rice code (ffv1).
+ */
+static inline int get_sr_golomb(struct get_bits_context *gb,
+	int k, int limit, int esc_len)
+{
+	u32 v = get_ur_golomb(gb, k, limit, esc_len);
+
+	return (v >> 1) ^ -(v & 1);
+}
+
+/**
+ * read signed golomb rice code (flac).
+ */
+static inline int get_sr_golomb_flac(struct get_bits_context *gb,
+	int k, int limit, int esc_len)
+{
+	u32 v = get_ur_golomb_jpegls(gb, k, limit, esc_len);
+
+	return (v >> 1) ^ -(v & 1);
+}
+
+/**
+ * read u32 golomb rice code (shorten).
+ */
+static inline u32 get_ur_golomb_shorten(struct get_bits_context *gb, int k)
+{
+	return get_ur_golomb_jpegls(gb, k, INT_MAX, 0);
+}
+
+/**
+ * read signed golomb rice code (shorten).
+ */
+static inline int get_sr_golomb_shorten(struct get_bits_context *gb, int k)
+{
+	int uvar = get_ur_golomb_jpegls(gb, k + 1, INT_MAX, 0);
+
+	return (uvar >> 1) ^ -(uvar & 1);
+}
+
+/**
+ * write u32 exp golomb code. 2^16 - 2 at most
+ */
+static inline void set_ue_golomb(struct put_bits_context *pb, int i)
+{
+	if (i < 256)
+		put_bits(pb, ff_ue_golomb_len[i], i + 1);
+	else {
+		int e = av_log2(i + 1);
+		put_bits(pb, 2 * e + 1, i + 1);
+	}
+}
+
+/**
+ * write u32 exp golomb code. 2^32-2 at most.
+ */
+static inline void set_ue_golomb_long(struct put_bits_context *pb, u32 i)
+{
+	if (i < 256)
+		put_bits(pb, ff_ue_golomb_len[i], i + 1);
+	else {
+		int e = av_log2(i + 1);
+		put_bits64(pb, 2 * e + 1, i + 1);
+	}
+}
+
+/**
+ * write truncated u32 exp golomb code.
+ */
+static inline void set_te_golomb(struct put_bits_context *pb, int i, int range)
+{
+	if (range == 2)
+		put_bits(pb, 1, i ^ 1);
+	else
+		set_ue_golomb(pb, i);
+}
+
+/**
+ * write signed exp golomb code. 16 bits at most.
+ */
+static inline void set_se_golomb(struct put_bits_context *pb, int i)
+{
+	i = 2 * i - 1;
+
+	if (i < 0)
+		i ^= -1;    //FIXME check if gcc does the right thing
+	set_ue_golomb(pb, i);
+}
+
+/**
+ * write u32 golomb rice code (ffv1).
+ */
+static inline void set_ur_golomb(struct put_bits_context *pb, int i, int k, int limit,
+                                 int esc_len)
+{
+	int e;
+
+	e = i >> k;
+	if (e < limit)
+		put_bits(pb, e + k + 1, (1 << k) + av_mod_uintp2(i, k));
+	else
+		put_bits(pb, limit + esc_len, i - limit + 1);
+}
+
+/**
+ * write u32 golomb rice code (jpegls).
+ */
+static inline void set_ur_golomb_jpegls(struct put_bits_context *pb,
+	int i, int k, int limit, int esc_len)
+{
+	int e;
+
+	e = (i >> k) + 1;
+	if (e < limit) {
+		while (e > 31) {
+			put_bits(pb, 31, 0);
+			e -= 31;
+		}
+		put_bits(pb, e, 1);
+		if (k)
+			put_sbits(pb, k, i);
+	} else {
+		while (limit > 31) {
+			put_bits(pb, 31, 0);
+			limit -= 31;
+		}
+		put_bits(pb, limit, 1);
+		put_bits(pb, esc_len, i - 1);
+	}
+}
+
+/**
+ * write signed golomb rice code (ffv1).
+ */
+static inline void set_sr_golomb(struct put_bits_context *pb,
+	int i, int k, int limit, int esc_len)
+{
+	int v;
+
+	v  = -2 * i - 1;
+	v ^= (v >> 31);
+
+	set_ur_golomb(pb, v, k, limit, esc_len);
+}
+
+/**
+ * write signed golomb rice code (flac).
+ */
+static inline void set_sr_golomb_flac(struct put_bits_context *pb,
+	int i, int k, int limit, int esc_len)
+{
+	int v;
+
+	v  = -2 * i - 1;
+	v ^= (v >> 31);
+
+	set_ur_golomb_jpegls(pb, v, k, limit, esc_len);
+}
+
+#endif /* AVCODEC_GOLOMB_H */
diff --git a/drivers/amvdec_ports/utils/pixfmt.h b/drivers/amvdec_ports/utils/pixfmt.h
new file mode 100644
index 0000000..f13411e
--- /dev/null
+++ b/drivers/amvdec_ports/utils/pixfmt.h
@@ -0,0 +1,470 @@
+#ifndef AVUTIL_PIXFMT_H
+#define AVUTIL_PIXFMT_H
+
+/**
+ * Pixel format.
+ *
+ * @note
+ * AV_PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA
+ * color is put together as:
+ *  (A << 24) | (R << 16) | (G << 8) | B
+ * This is stored as BGRA on little-endian CPU architectures and ARGB on
+ * big-endian CPUs.
+ *
+ * @note
+ * If the resolution is not a multiple of the chroma subsampling factor
+ * then the chroma plane resolution must be rounded up.
+ *
+ * @par
+ * When the pixel format is palettized RGB32 (AV_PIX_FMT_PAL8), the palettized
+ * image data is stored in AVFrame.data[0]. The palette is transported in
+ * AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is
+ * formatted the same as in AV_PIX_FMT_RGB32 described above (i.e., it is
+ * also endian-specific). Note also that the individual RGB32 palette
+ * components stored in AVFrame.data[1] should be in the range 0..255.
+ * This is important as many custom PAL8 video codecs that were designed
+ * to run on the IBM VGA graphics adapter use 6-bit palette components.
+ *
+ * @par
+ * For all the 8 bits per pixel formats, an RGB32 palette is in data[1] like
+ * for pal8. This palette is filled in automatically by the function
+ * allocating the picture.
+ */
+enum AVPixelFormat {
+    AV_PIX_FMT_NONE = -1,
+    AV_PIX_FMT_YUV420P,   ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
+    AV_PIX_FMT_YUYV422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
+    AV_PIX_FMT_RGB24,     ///< packed RGB 8:8:8, 24bpp, RGBRGB...
+    AV_PIX_FMT_BGR24,     ///< packed RGB 8:8:8, 24bpp, BGRBGR...
+    AV_PIX_FMT_YUV422P,   ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
+    AV_PIX_FMT_YUV444P,   ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
+    AV_PIX_FMT_YUV410P,   ///< planar YUV 4:1:0,  9bpp, (1 Cr & Cb sample per 4x4 Y samples)
+    AV_PIX_FMT_YUV411P,   ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
+    AV_PIX_FMT_GRAY8,     ///<        Y        ,  8bpp
+    AV_PIX_FMT_MONOWHITE, ///<        Y        ,  1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb
+    AV_PIX_FMT_MONOBLACK, ///<        Y        ,  1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb
+    AV_PIX_FMT_PAL8,      ///< 8 bits with AV_PIX_FMT_RGB32 palette
+    AV_PIX_FMT_YUVJ420P,  ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting color_range
+    AV_PIX_FMT_YUVJ422P,  ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting color_range
+    AV_PIX_FMT_YUVJ444P,  ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting color_range
+    AV_PIX_FMT_UYVY422,   ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
+    AV_PIX_FMT_UYYVYY411, ///< packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
+    AV_PIX_FMT_BGR8,      ///< packed RGB 3:3:2,  8bpp, (msb)2B 3G 3R(lsb)
+    AV_PIX_FMT_BGR4,      ///< packed RGB 1:2:1 bitstream,  4bpp, (msb)1B 2G 1R(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
+    AV_PIX_FMT_BGR4_BYTE, ///< packed RGB 1:2:1,  8bpp, (msb)1B 2G 1R(lsb)
+    AV_PIX_FMT_RGB8,      ///< packed RGB 3:3:2,  8bpp, (msb)2R 3G 3B(lsb)
+    AV_PIX_FMT_RGB4,      ///< packed RGB 1:2:1 bitstream,  4bpp, (msb)1R 2G 1B(lsb), a byte contains two pixels, the first pixel in the byte is the one composed by the 4 msb bits
+    AV_PIX_FMT_RGB4_BYTE, ///< packed RGB 1:2:1,  8bpp, (msb)1R 2G 1B(lsb)
+    AV_PIX_FMT_NV12,      ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V)
+    AV_PIX_FMT_NV21,      ///< as above, but U and V bytes are swapped
+
+    AV_PIX_FMT_ARGB,      ///< packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
+    AV_PIX_FMT_RGBA,      ///< packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
+    AV_PIX_FMT_ABGR,      ///< packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
+    AV_PIX_FMT_BGRA,      ///< packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
+
+    AV_PIX_FMT_GRAY16BE,  ///<        Y        , 16bpp, big-endian
+    AV_PIX_FMT_GRAY16LE,  ///<        Y        , 16bpp, little-endian
+    AV_PIX_FMT_YUV440P,   ///< planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
+    AV_PIX_FMT_YUVJ440P,  ///< planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
+    AV_PIX_FMT_YUVA420P,  ///< planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
+    AV_PIX_FMT_RGB48BE,   ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as big-endian
+    AV_PIX_FMT_RGB48LE,   ///< packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, the 2-byte value for each R/G/B component is stored as little-endian
+
+    AV_PIX_FMT_RGB565BE,  ///< packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), big-endian
+    AV_PIX_FMT_RGB565LE,  ///< packed RGB 5:6:5, 16bpp, (msb)   5R 6G 5B(lsb), little-endian
+    AV_PIX_FMT_RGB555BE,  ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian   , X=unused/undefined
+    AV_PIX_FMT_RGB555LE,  ///< packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
+
+    AV_PIX_FMT_BGR565BE,  ///< packed BGR 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), big-endian
+    AV_PIX_FMT_BGR565LE,  ///< packed BGR 5:6:5, 16bpp, (msb)   5B 6G 5R(lsb), little-endian
+    AV_PIX_FMT_BGR555BE,  ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian   , X=unused/undefined
+    AV_PIX_FMT_BGR555LE,  ///< packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined
+
+#ifdef FF_API_VAAPI
+    /** @name Deprecated pixel formats */
+    /**@{*/
+    AV_PIX_FMT_VAAPI_MOCO, ///< HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers
+    AV_PIX_FMT_VAAPI_IDCT, ///< HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers
+    AV_PIX_FMT_VAAPI_VLD,  ///< HW decoding through VA API, Picture.data[3] contains a VASurfaceID
+    /**@}*/
+    AV_PIX_FMT_VAAPI = AV_PIX_FMT_VAAPI_VLD,
+#else
+    /**
+     *  Hardware acceleration through VA-API, data[3] contains a
+     *  VASurfaceID.
+     */
+    AV_PIX_FMT_VAAPI,
+#endif
+
+    AV_PIX_FMT_YUV420P16LE,  ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+    AV_PIX_FMT_YUV420P16BE,  ///< planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+    AV_PIX_FMT_YUV422P16LE,  ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+    AV_PIX_FMT_YUV422P16BE,  ///< planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+    AV_PIX_FMT_YUV444P16LE,  ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+    AV_PIX_FMT_YUV444P16BE,  ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+    AV_PIX_FMT_DXVA2_VLD,    ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer
+
+    AV_PIX_FMT_RGB444LE,  ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), little-endian, X=unused/undefined
+    AV_PIX_FMT_RGB444BE,  ///< packed RGB 4:4:4, 16bpp, (msb)4X 4R 4G 4B(lsb), big-endian,    X=unused/undefined
+    AV_PIX_FMT_BGR444LE,  ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), little-endian, X=unused/undefined
+    AV_PIX_FMT_BGR444BE,  ///< packed BGR 4:4:4, 16bpp, (msb)4X 4B 4G 4R(lsb), big-endian,    X=unused/undefined
+    AV_PIX_FMT_YA8,       ///< 8 bits gray, 8 bits alpha
+
+    AV_PIX_FMT_Y400A = AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8
+    AV_PIX_FMT_GRAY8A= AV_PIX_FMT_YA8, ///< alias for AV_PIX_FMT_YA8
+
+    AV_PIX_FMT_BGR48BE,   ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian
+    AV_PIX_FMT_BGR48LE,   ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian
+
+    /**
+     * The following 12 formats have the disadvantage of needing 1 format for each bit depth.
+     * Notice that each 9/10 bits sample is stored in 16 bits with extra padding.
+     * If you want to support multiple bit depths, then using AV_PIX_FMT_YUV420P16* with the bpp stored separately is better.
+     */
+    AV_PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+    AV_PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+    AV_PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+    AV_PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+    AV_PIX_FMT_YUV422P10BE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+    AV_PIX_FMT_YUV422P10LE,///< planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+    AV_PIX_FMT_YUV444P9BE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+    AV_PIX_FMT_YUV444P9LE, ///< planar YUV 4:4:4, 27bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+    AV_PIX_FMT_YUV444P10BE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+    AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+    AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+    AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+    AV_PIX_FMT_GBRP,      ///< planar GBR 4:4:4 24bpp
+    AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP
+    AV_PIX_FMT_GBRP9BE,   ///< planar GBR 4:4:4 27bpp, big-endian
+    AV_PIX_FMT_GBRP9LE,   ///< planar GBR 4:4:4 27bpp, little-endian
+    AV_PIX_FMT_GBRP10BE,  ///< planar GBR 4:4:4 30bpp, big-endian
+    AV_PIX_FMT_GBRP10LE,  ///< planar GBR 4:4:4 30bpp, little-endian
+    AV_PIX_FMT_GBRP16BE,  ///< planar GBR 4:4:4 48bpp, big-endian
+    AV_PIX_FMT_GBRP16LE,  ///< planar GBR 4:4:4 48bpp, little-endian
+    AV_PIX_FMT_YUVA422P,  ///< planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
+    AV_PIX_FMT_YUVA444P,  ///< planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
+    AV_PIX_FMT_YUVA420P9BE,  ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), big-endian
+    AV_PIX_FMT_YUVA420P9LE,  ///< planar YUV 4:2:0 22.5bpp, (1 Cr & Cb sample per 2x2 Y & A samples), little-endian
+    AV_PIX_FMT_YUVA422P9BE,  ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), big-endian
+    AV_PIX_FMT_YUVA422P9LE,  ///< planar YUV 4:2:2 27bpp, (1 Cr & Cb sample per 2x1 Y & A samples), little-endian
+    AV_PIX_FMT_YUVA444P9BE,  ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), big-endian
+    AV_PIX_FMT_YUVA444P9LE,  ///< planar YUV 4:4:4 36bpp, (1 Cr & Cb sample per 1x1 Y & A samples), little-endian
+    AV_PIX_FMT_YUVA420P10BE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian)
+    AV_PIX_FMT_YUVA420P10LE, ///< planar YUV 4:2:0 25bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian)
+    AV_PIX_FMT_YUVA422P10BE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian)
+    AV_PIX_FMT_YUVA422P10LE, ///< planar YUV 4:2:2 30bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian)
+    AV_PIX_FMT_YUVA444P10BE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian)
+    AV_PIX_FMT_YUVA444P10LE, ///< planar YUV 4:4:4 40bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian)
+    AV_PIX_FMT_YUVA420P16BE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, big-endian)
+    AV_PIX_FMT_YUVA420P16LE, ///< planar YUV 4:2:0 40bpp, (1 Cr & Cb sample per 2x2 Y & A samples, little-endian)
+    AV_PIX_FMT_YUVA422P16BE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, big-endian)
+    AV_PIX_FMT_YUVA422P16LE, ///< planar YUV 4:2:2 48bpp, (1 Cr & Cb sample per 2x1 Y & A samples, little-endian)
+    AV_PIX_FMT_YUVA444P16BE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, big-endian)
+    AV_PIX_FMT_YUVA444P16LE, ///< planar YUV 4:4:4 64bpp, (1 Cr & Cb sample per 1x1 Y & A samples, little-endian)
+
+    AV_PIX_FMT_VDPAU,     ///< HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface
+
+    AV_PIX_FMT_XYZ12LE,      ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as little-endian, the 4 lower bits are set to 0
+    AV_PIX_FMT_XYZ12BE,      ///< packed XYZ 4:4:4, 36 bpp, (msb) 12X, 12Y, 12Z (lsb), the 2-byte value for each X/Y/Z is stored as big-endian, the 4 lower bits are set to 0
+    AV_PIX_FMT_NV16,         ///< interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
+    AV_PIX_FMT_NV20LE,       ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+    AV_PIX_FMT_NV20BE,       ///< interleaved chroma YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+
+    AV_PIX_FMT_RGBA64BE,     ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian
+    AV_PIX_FMT_RGBA64LE,     ///< packed RGBA 16:16:16:16, 64bpp, 16R, 16G, 16B, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian
+    AV_PIX_FMT_BGRA64BE,     ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as big-endian
+    AV_PIX_FMT_BGRA64LE,     ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian
+
+    AV_PIX_FMT_YVYU422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb
+
+    AV_PIX_FMT_YA16BE,       ///< 16 bits gray, 16 bits alpha (big-endian)
+    AV_PIX_FMT_YA16LE,       ///< 16 bits gray, 16 bits alpha (little-endian)
+
+    AV_PIX_FMT_GBRAP,        ///< planar GBRA 4:4:4:4 32bpp
+    AV_PIX_FMT_GBRAP16BE,    ///< planar GBRA 4:4:4:4 64bpp, big-endian
+    AV_PIX_FMT_GBRAP16LE,    ///< planar GBRA 4:4:4:4 64bpp, little-endian
+    /**
+     *  HW acceleration through QSV, data[3] contains a pointer to the
+     *  mfxFrameSurface1 structure.
+     */
+    AV_PIX_FMT_QSV,
+    /**
+     * HW acceleration though MMAL, data[3] contains a pointer to the
+     * MMAL_BUFFER_HEADER_T structure.
+     */
+    AV_PIX_FMT_MMAL,
+
+    AV_PIX_FMT_D3D11VA_VLD,  ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer
+
+    /**
+     * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers
+     * exactly as for system memory frames.
+     */
+    AV_PIX_FMT_CUDA,
+
+    AV_PIX_FMT_0RGB,        ///< packed RGB 8:8:8, 32bpp, XRGBXRGB...   X=unused/undefined
+    AV_PIX_FMT_RGB0,        ///< packed RGB 8:8:8, 32bpp, RGBXRGBX...   X=unused/undefined
+    AV_PIX_FMT_0BGR,        ///< packed BGR 8:8:8, 32bpp, XBGRXBGR...   X=unused/undefined
+    AV_PIX_FMT_BGR0,        ///< packed BGR 8:8:8, 32bpp, BGRXBGRX...   X=unused/undefined
+
+    AV_PIX_FMT_YUV420P12BE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+    AV_PIX_FMT_YUV420P12LE, ///< planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+    AV_PIX_FMT_YUV420P14BE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
+    AV_PIX_FMT_YUV420P14LE, ///< planar YUV 4:2:0,21bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
+    AV_PIX_FMT_YUV422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+    AV_PIX_FMT_YUV422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+    AV_PIX_FMT_YUV422P14BE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
+    AV_PIX_FMT_YUV422P14LE, ///< planar YUV 4:2:2,28bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
+    AV_PIX_FMT_YUV444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+    AV_PIX_FMT_YUV444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+    AV_PIX_FMT_YUV444P14BE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
+    AV_PIX_FMT_YUV444P14LE, ///< planar YUV 4:4:4,42bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
+    AV_PIX_FMT_GBRP12BE,    ///< planar GBR 4:4:4 36bpp, big-endian
+    AV_PIX_FMT_GBRP12LE,    ///< planar GBR 4:4:4 36bpp, little-endian
+    AV_PIX_FMT_GBRP14BE,    ///< planar GBR 4:4:4 42bpp, big-endian
+    AV_PIX_FMT_GBRP14LE,    ///< planar GBR 4:4:4 42bpp, little-endian
+    AV_PIX_FMT_YUVJ411P,    ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV411P and setting color_range
+
+    AV_PIX_FMT_BAYER_BGGR8,    ///< bayer, BGBG..(odd line), GRGR..(even line), 8-bit samples */
+    AV_PIX_FMT_BAYER_RGGB8,    ///< bayer, RGRG..(odd line), GBGB..(even line), 8-bit samples */
+    AV_PIX_FMT_BAYER_GBRG8,    ///< bayer, GBGB..(odd line), RGRG..(even line), 8-bit samples */
+    AV_PIX_FMT_BAYER_GRBG8,    ///< bayer, GRGR..(odd line), BGBG..(even line), 8-bit samples */
+    AV_PIX_FMT_BAYER_BGGR16LE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, little-endian */
+    AV_PIX_FMT_BAYER_BGGR16BE, ///< bayer, BGBG..(odd line), GRGR..(even line), 16-bit samples, big-endian */
+    AV_PIX_FMT_BAYER_RGGB16LE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, little-endian */
+    AV_PIX_FMT_BAYER_RGGB16BE, ///< bayer, RGRG..(odd line), GBGB..(even line), 16-bit samples, big-endian */
+    AV_PIX_FMT_BAYER_GBRG16LE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, little-endian */
+    AV_PIX_FMT_BAYER_GBRG16BE, ///< bayer, GBGB..(odd line), RGRG..(even line), 16-bit samples, big-endian */
+    AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian */
+    AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian */
+
+    AV_PIX_FMT_XVMC,///< XVideo Motion Acceleration via common packet passing
+
+    AV_PIX_FMT_YUV440P10LE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian
+    AV_PIX_FMT_YUV440P10BE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian
+    AV_PIX_FMT_YUV440P12LE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian
+    AV_PIX_FMT_YUV440P12BE, ///< planar YUV 4:4:0,24bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian
+    AV_PIX_FMT_AYUV64LE,    ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), little-endian
+    AV_PIX_FMT_AYUV64BE,    ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), big-endian
+
+    AV_PIX_FMT_VIDEOTOOLBOX, ///< hardware decoding through Videotoolbox
+
+    AV_PIX_FMT_P010LE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, little-endian
+    AV_PIX_FMT_P010BE, ///< like NV12, with 10bpp per component, data in the high bits, zeros in the low bits, big-endian
+
+    AV_PIX_FMT_GBRAP12BE,  ///< planar GBR 4:4:4:4 48bpp, big-endian
+    AV_PIX_FMT_GBRAP12LE,  ///< planar GBR 4:4:4:4 48bpp, little-endian
+
+    AV_PIX_FMT_GBRAP10BE,  ///< planar GBR 4:4:4:4 40bpp, big-endian
+    AV_PIX_FMT_GBRAP10LE,  ///< planar GBR 4:4:4:4 40bpp, little-endian
+
+    AV_PIX_FMT_MEDIACODEC, ///< hardware decoding through MediaCodec
+
+    AV_PIX_FMT_GRAY12BE,   ///<        Y        , 12bpp, big-endian
+    AV_PIX_FMT_GRAY12LE,   ///<        Y        , 12bpp, little-endian
+    AV_PIX_FMT_GRAY10BE,   ///<        Y        , 10bpp, big-endian
+    AV_PIX_FMT_GRAY10LE,   ///<        Y        , 10bpp, little-endian
+
+    AV_PIX_FMT_P016LE, ///< like NV12, with 16bpp per component, little-endian
+    AV_PIX_FMT_P016BE, ///< like NV12, with 16bpp per component, big-endian
+
+    /**
+     * Hardware surfaces for Direct3D11.
+     *
+     * This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11
+     * hwaccel API and filtering support AV_PIX_FMT_D3D11 only.
+     *
+     * data[0] contains a ID3D11Texture2D pointer, and data[1] contains the
+     * texture array index of the frame as intptr_t if the ID3D11Texture2D is
+     * an array texture (or always 0 if it's a normal texture).
+     */
+    AV_PIX_FMT_D3D11,
+
+    AV_PIX_FMT_GRAY9BE,   ///<        Y        , 9bpp, big-endian
+    AV_PIX_FMT_GRAY9LE,   ///<        Y        , 9bpp, little-endian
+
+    AV_PIX_FMT_GBRPF32BE,  ///< IEEE-754 single precision planar GBR 4:4:4,     96bpp, big-endian
+    AV_PIX_FMT_GBRPF32LE,  ///< IEEE-754 single precision planar GBR 4:4:4,     96bpp, little-endian
+    AV_PIX_FMT_GBRAPF32BE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, big-endian
+    AV_PIX_FMT_GBRAPF32LE, ///< IEEE-754 single precision planar GBRA 4:4:4:4, 128bpp, little-endian
+
+    /**
+     * DRM-managed buffers exposed through PRIME buffer sharing.
+     *
+     * data[0] points to an AVDRMFrameDescriptor.
+     */
+    AV_PIX_FMT_DRM_PRIME,
+    /**
+     * Hardware surfaces for OpenCL.
+     *
+     * data[i] contain 2D image objects (typed in C as cl_mem, used
+     * in OpenCL as image2d_t) for each plane of the surface.
+     */
+    AV_PIX_FMT_OPENCL,
+
+    AV_PIX_FMT_GRAY14BE,   ///<        Y        , 14bpp, big-endian
+    AV_PIX_FMT_GRAY14LE,   ///<        Y        , 14bpp, little-endian
+
+    AV_PIX_FMT_GRAYF32BE,  ///< IEEE-754 single precision Y, 32bpp, big-endian
+    AV_PIX_FMT_GRAYF32LE,  ///< IEEE-754 single precision Y, 32bpp, little-endian
+
+    AV_PIX_FMT_YUVA422P12BE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, big-endian
+    AV_PIX_FMT_YUVA422P12LE, ///< planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), 12b alpha, little-endian
+    AV_PIX_FMT_YUVA444P12BE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, big-endian
+    AV_PIX_FMT_YUVA444P12LE, ///< planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), 12b alpha, little-endian
+
+    AV_PIX_FMT_NV24,      ///< planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V)
+    AV_PIX_FMT_NV42,      ///< as above, but U and V bytes are swapped
+
+    AV_PIX_FMT_NB         ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
+};
+
+#ifdef AV_HAVE_BIGENDIAN
+#define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##be
+#else
+#define AV_PIX_FMT_NE(be, le) AV_PIX_FMT_##le
+#endif
+
+#define AV_PIX_FMT_YUV420P10 AV_PIX_FMT_NE(YUV420P10BE, YUV420P10LE)
+#define AV_PIX_FMT_YUV422P10 AV_PIX_FMT_NE(YUV422P10BE, YUV422P10LE)
+#define AV_PIX_FMT_YUV440P10 AV_PIX_FMT_NE(YUV440P10BE, YUV440P10LE)
+#define AV_PIX_FMT_YUV444P10 AV_PIX_FMT_NE(YUV444P10BE, YUV444P10LE)
+#define AV_PIX_FMT_YUV420P12 AV_PIX_FMT_NE(YUV420P12BE, YUV420P12LE)
+#define AV_PIX_FMT_YUV422P12 AV_PIX_FMT_NE(YUV422P12BE, YUV422P12LE)
+#define AV_PIX_FMT_YUV440P12 AV_PIX_FMT_NE(YUV440P12BE, YUV440P12LE)
+#define AV_PIX_FMT_YUV444P12 AV_PIX_FMT_NE(YUV444P12BE, YUV444P12LE)
+
+
+#define AV_PIX_FMT_GBRP9     AV_PIX_FMT_NE(GBRP9BE ,    GBRP9LE)
+#define AV_PIX_FMT_GBRP10    AV_PIX_FMT_NE(GBRP10BE,    GBRP10LE)
+#define AV_PIX_FMT_GBRP12    AV_PIX_FMT_NE(GBRP12BE,    GBRP12LE)
+#define AV_PIX_FMT_GBRP14    AV_PIX_FMT_NE(GBRP14BE,    GBRP14LE)
+#define AV_PIX_FMT_GBRP16    AV_PIX_FMT_NE(GBRP16BE,    GBRP16LE)
+#define AV_PIX_FMT_GBRAP10   AV_PIX_FMT_NE(GBRAP10BE,   GBRAP10LE)
+#define AV_PIX_FMT_GBRAP12   AV_PIX_FMT_NE(GBRAP12BE,   GBRAP12LE)
+#define AV_PIX_FMT_GBRAP16   AV_PIX_FMT_NE(GBRAP16BE,   GBRAP16LE)
+
+#define AV_PIX_FMT_GRAY9  AV_PIX_FMT_NE(GRAY9BE,  GRAY9LE)
+#define AV_PIX_FMT_GRAY10 AV_PIX_FMT_NE(GRAY10BE, GRAY10LE)
+#define AV_PIX_FMT_GRAY12 AV_PIX_FMT_NE(GRAY12BE, GRAY12LE)
+
+#define AV_PIX_FMT_YUV420P9  AV_PIX_FMT_NE(YUV420P9BE , YUV420P9LE)
+#define AV_PIX_FMT_YUV422P9  AV_PIX_FMT_NE(YUV422P9BE , YUV422P9LE)
+#define AV_PIX_FMT_YUV444P9  AV_PIX_FMT_NE(YUV444P9BE , YUV444P9LE)
+
+/**
+  * Chromaticity coordinates of the source primaries.
+  * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.1.
+  */
+enum AVColorPrimaries {
+	AVCOL_PRI_RESERVED0   = 0,
+	AVCOL_PRI_BT709       = 1,  ///< also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B
+	AVCOL_PRI_UNSPECIFIED = 2,
+	AVCOL_PRI_RESERVED    = 3,
+	AVCOL_PRI_BT470M      = 4,  ///< also FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
+
+	AVCOL_PRI_BT470BG     = 5,  ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM
+	AVCOL_PRI_SMPTE170M   = 6,  ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
+	AVCOL_PRI_SMPTE240M   = 7,  ///< functionally identical to above
+	AVCOL_PRI_FILM        = 8,  ///< colour filters using Illuminant C
+	AVCOL_PRI_BT2020      = 9,  ///< ITU-R BT2020
+	AVCOL_PRI_SMPTE428    = 10, ///< SMPTE ST 428-1 (CIE 1931 XYZ)
+	AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428,
+	AVCOL_PRI_SMPTE431    = 11, ///< SMPTE ST 431-2 (2011) / DCI P3
+	AVCOL_PRI_SMPTE432    = 12, ///< SMPTE ST 432-1 (2010) / P3 D65 / Display P3
+	AVCOL_PRI_JEDEC_P22   = 22, ///< JEDEC P22 phosphors
+	AVCOL_PRI_NB                ///< Not part of ABI
+};
+
+/**
+ * Color Transfer Characteristic.
+ * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.2.
+ */
+enum AVColorTransferCharacteristic {
+	AVCOL_TRC_RESERVED0    = 0,
+	AVCOL_TRC_BT709        = 1,  ///< also ITU-R BT1361
+	AVCOL_TRC_UNSPECIFIED  = 2,
+	AVCOL_TRC_RESERVED     = 3,
+	AVCOL_TRC_GAMMA22      = 4,  ///< also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
+	AVCOL_TRC_GAMMA28      = 5,  ///< also ITU-R BT470BG
+	AVCOL_TRC_SMPTE170M    = 6,  ///< also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC
+	AVCOL_TRC_SMPTE240M    = 7,
+	AVCOL_TRC_LINEAR       = 8,  ///< "Linear transfer characteristics"
+	AVCOL_TRC_LOG          = 9,  ///< "Logarithmic transfer characteristic (100:1 range)"
+	AVCOL_TRC_LOG_SQRT     = 10, ///< "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)"
+	AVCOL_TRC_IEC61966_2_4 = 11, ///< IEC 61966-2-4
+	AVCOL_TRC_BT1361_ECG   = 12, ///< ITU-R BT1361 Extended Colour Gamut
+	AVCOL_TRC_IEC61966_2_1 = 13, ///< IEC 61966-2-1 (sRGB or sYCC)
+	AVCOL_TRC_BT2020_10    = 14, ///< ITU-R BT2020 for 10-bit system
+	AVCOL_TRC_BT2020_12    = 15, ///< ITU-R BT2020 for 12-bit system
+	AVCOL_TRC_SMPTE2084    = 16, ///< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems
+	AVCOL_TRC_SMPTEST2084  = AVCOL_TRC_SMPTE2084,
+	AVCOL_TRC_SMPTE428     = 17, ///< SMPTE ST 428-1
+	AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428,
+	AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma"
+	AVCOL_TRC_NB                 ///< Not part of ABI
+};
+
+/**
+ * YUV colorspace type.
+ * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.3.
+ */
+enum AVColorSpace {
+	AVCOL_SPC_RGB         = 0,  ///< order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB)
+	AVCOL_SPC_BT709       = 1,  ///< also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B
+	AVCOL_SPC_UNSPECIFIED = 2,
+	AVCOL_SPC_RESERVED    = 3,
+	AVCOL_SPC_FCC         = 4,  ///< FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
+	AVCOL_SPC_BT470BG     = 5,  ///< also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
+	AVCOL_SPC_SMPTE170M   = 6,  ///< also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
+	AVCOL_SPC_SMPTE240M   = 7,  ///< functionally identical to above
+	AVCOL_SPC_YCGCO       = 8,  ///< Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16
+	AVCOL_SPC_YCOCG       = AVCOL_SPC_YCGCO,
+	AVCOL_SPC_BT2020_NCL  = 9,  ///< ITU-R BT2020 non-constant luminance system
+	AVCOL_SPC_BT2020_CL   = 10, ///< ITU-R BT2020 constant luminance system
+	AVCOL_SPC_SMPTE2085   = 11, ///< SMPTE 2085, Y'D'zD'x
+	AVCOL_SPC_CHROMA_DERIVED_NCL = 12, ///< Chromaticity-derived non-constant luminance system
+	AVCOL_SPC_CHROMA_DERIVED_CL = 13, ///< Chromaticity-derived constant luminance system
+	AVCOL_SPC_ICTCP       = 14, ///< ITU-R BT.2100-0, ICtCp
+	AVCOL_SPC_NB                ///< Not part of ABI
+};
+
+/**
+ * MPEG vs JPEG YUV range.
+ */
+enum AVColorRange {
+	AVCOL_RANGE_UNSPECIFIED = 0,
+	AVCOL_RANGE_MPEG        = 1, ///< the normal 219*2^(n-8) "MPEG" YUV ranges
+	AVCOL_RANGE_JPEG        = 2, ///< the normal     2^n-1   "JPEG" YUV ranges
+	AVCOL_RANGE_NB               ///< Not part of ABI
+};
+
+/**
+ * Location of chroma samples.
+ *
+ * Illustration showing the location of the first (top left) chroma sample of the
+ * image, the left shows only luma, the right
+ * shows the location of the chroma sample, the 2 could be imagined to overlay
+ * each other but are drawn separately due to limitations of ASCII
+ *
+ *                1st 2nd       1st 2nd horizontal luma sample positions
+ *                 v   v         v   v
+ *                 ______        ______
+ *1st luma line > |X   X ...    |3 4 X ...     X are luma samples,
+ *                |             |1 2           1-6 are possible chroma positions
+ *2nd luma line > |X   X ...    |5 6 X ...     0 is undefined/unknown position
+ */
+enum AVChromaLocation {
+	AVCHROMA_LOC_UNSPECIFIED = 0,
+	AVCHROMA_LOC_LEFT        = 1, ///< MPEG-2/4 4:2:0, H.264 default for 4:2:0
+	AVCHROMA_LOC_CENTER      = 2, ///< MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0
+	AVCHROMA_LOC_TOPLEFT     = 3, ///< ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2
+	AVCHROMA_LOC_TOP         = 4,
+	AVCHROMA_LOC_BOTTOMLEFT  = 5,
+	AVCHROMA_LOC_BOTTOM      = 6,
+	AVCHROMA_LOC_NB               ///< Not part of ABI
+};
+
+#endif /* AVUTIL_PIXFMT_H */
+
diff --git a/drivers/amvdec_ports/utils/put_bits.h b/drivers/amvdec_ports/utils/put_bits.h
new file mode 100644
index 0000000..8b2aa15
--- /dev/null
+++ b/drivers/amvdec_ports/utils/put_bits.h
@@ -0,0 +1,323 @@
+#ifndef AVCODEC_PUT_BITS_H
+#define AVCODEC_PUT_BITS_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include "common.h"
+
+struct put_bits_context {
+	u32 bit_buf;
+	int bit_left;
+	u8 *buf;
+	u8 *buf_ptr;
+	u8 *buf_end;
+	int size_in_bits;
+};
+
+/**
+ * Initialize the struct put_bits_context s.
+ *
+ * @param buffer the buffer where to put bits
+ * @param buffer_size the size in bytes of buffer
+ */
+static inline void init_put_bits(struct put_bits_context *s,
+	u8 *buffer, int buffer_size)
+{
+	if (buffer_size < 0) {
+		buffer_size = 0;
+		buffer      = NULL;
+	}
+
+	s->size_in_bits = 8 * buffer_size;
+	s->buf          = buffer;
+	s->buf_end      = s->buf + buffer_size;
+	s->buf_ptr      = s->buf;
+	s->bit_left     = 32;
+	s->bit_buf      = 0;
+}
+
+/**
+ * Rebase the bit writer onto a reallocated buffer.
+ *
+ * @param buffer the buffer where to put bits
+ * @param buffer_size the size in bytes of buffer,
+ *                    must be larger than the previous size
+ */
+static inline void rebase_put_bits(struct put_bits_context *s,
+	u8 *buffer, int buffer_size)
+{
+	s->buf_end = buffer + buffer_size;
+	s->buf_ptr = buffer + (s->buf_ptr - s->buf);
+	s->buf     = buffer;
+	s->size_in_bits = 8 * buffer_size;
+}
+
+/**
+ * @return the total number of bits written to the bitstream.
+ */
+static inline int put_bits_count(struct put_bits_context *s)
+{
+	return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left;
+}
+
+/**
+ * @return the number of bits available in the bitstream.
+ */
+static inline int put_bits_left(struct put_bits_context* s)
+{
+	return (s->buf_end - s->buf_ptr) * 8 - 32 + s->bit_left;
+}
+
+/**
+ * Pad the end of the output stream with zeros.
+ */
+static inline void flush_put_bits(struct put_bits_context *s)
+{
+#ifndef BITSTREAM_WRITER_LE
+	if (s->bit_left < 32)
+		s->bit_buf <<= s->bit_left;
+#endif
+	while (s->bit_left < 32) {
+#ifdef BITSTREAM_WRITER_LE
+		*s->buf_ptr++ = s->bit_buf;
+		s->bit_buf  >>= 8;
+#else
+		*s->buf_ptr++ = s->bit_buf >> 24;
+		s->bit_buf  <<= 8;
+#endif
+		s->bit_left  += 8;
+	}
+	s->bit_left = 32;
+	s->bit_buf  = 0;
+}
+
+static inline void flush_put_bits_le(struct put_bits_context *s)
+{
+	while (s->bit_left < 32) {
+		*s->buf_ptr++ = s->bit_buf;
+		s->bit_buf  >>= 8;
+		s->bit_left  += 8;
+	}
+	s->bit_left = 32;
+	s->bit_buf  = 0;
+}
+
+#ifdef BITSTREAM_WRITER_LE
+#define avpriv_align_put_bits align_put_bits_unsupported_here
+#define avpriv_put_string ff_put_string_unsupported_here
+#define avpriv_copy_bits avpriv_copy_bits_unsupported_here
+#else
+/**
+ * Pad the bitstream with zeros up to the next byte boundary.
+ */
+void avpriv_align_put_bits(struct put_bits_context *s);
+
+/**
+ * Put the string string in the bitstream.
+ *
+ * @param terminate_string 0-terminates the written string if value is 1
+ */
+void avpriv_put_string(struct put_bits_context *pb,
+	const char *string, int terminate_string);
+
+/**
+ * Copy the content of src to the bitstream.
+ *
+ * @param length the number of bits of src to copy
+ */
+void avpriv_copy_bits(struct put_bits_context *pb, const u8 *src, int length);
+#endif
+
+/**
+ * Write up to 31 bits into a bitstream.
+ * Use put_bits32 to write 32 bits.
+ */
+static inline void put_bits(struct put_bits_context *s, int n, u32 value)
+{
+	u32 bit_buf;
+	int bit_left;
+
+	bit_buf  = s->bit_buf;
+	bit_left = s->bit_left;
+
+	/* XXX: optimize */
+#ifdef BITSTREAM_WRITER_LE
+	bit_buf |= value << (32 - bit_left);
+	if (n >= bit_left) {
+		if (3 < s->buf_end - s->buf_ptr) {
+			AV_WL32(s->buf_ptr, bit_buf);
+			s->buf_ptr += 4;
+		} else {
+			pr_err("Internal error, put_bits buffer too small\n");
+		}
+		bit_buf     = value >> bit_left;
+		bit_left   += 32;
+	}
+	bit_left -= n;
+#else
+	if (n < bit_left) {
+		bit_buf     = (bit_buf << n) | value;
+		bit_left   -= n;
+	} else {
+		bit_buf   <<= bit_left;
+		bit_buf    |= value >> (n - bit_left);
+		if (3 < s->buf_end - s->buf_ptr) {
+			AV_WB32(s->buf_ptr, bit_buf);
+			s->buf_ptr += 4;
+		} else {
+			pr_err("Internal error, put_bits buffer too small\n");
+		}
+		bit_left   += 32 - n;
+		bit_buf     = value;
+	}
+#endif
+	s->bit_buf  = bit_buf;
+	s->bit_left = bit_left;
+}
+
+static inline void put_bits_le(struct put_bits_context *s, int n, u32 value)
+{
+	u32 bit_buf;
+	int bit_left;
+
+	bit_buf  = s->bit_buf;
+	bit_left = s->bit_left;
+
+	bit_buf |= value << (32 - bit_left);
+	if (n >= bit_left) {
+		if (3 < s->buf_end - s->buf_ptr) {
+			AV_WL32(s->buf_ptr, bit_buf);
+			s->buf_ptr += 4;
+		} else {
+			pr_err("Internal error, put_bits buffer too small\n");
+		}
+		bit_buf     = value >> bit_left;
+		bit_left   += 32;
+	}
+	bit_left -= n;
+
+	s->bit_buf  = bit_buf;
+	s->bit_left = bit_left;
+}
+
+static inline u32 av_mod_uintp2(u32 a, u32 p)
+{
+	return a & ((1 << p) - 1);
+}
+
+static inline void put_sbits(struct put_bits_context *pb, int n, int32_t value)
+{
+	put_bits(pb, n, av_mod_uintp2(value, n));
+}
+
+/**
+ * Write exactly 32 bits into a bitstream.
+ */
+static void put_bits32(struct put_bits_context *s, u32 value)
+{
+	u32 bit_buf;
+	int bit_left;
+
+	bit_buf  = s->bit_buf;
+	bit_left = s->bit_left;
+
+#ifdef BITSTREAM_WRITER_LE
+	bit_buf |= value << (32 - bit_left);
+	if (3 < s->buf_end - s->buf_ptr) {
+		AV_WL32(s->buf_ptr, bit_buf);
+		s->buf_ptr += 4;
+	} else {
+		pr_err("Internal error, put_bits buffer too small\n");
+	}
+	bit_buf     = (uint64_t)value >> bit_left;
+#else
+	bit_buf     = (uint64_t)bit_buf << bit_left;
+	bit_buf    |= value >> (32 - bit_left);
+	if (3 < s->buf_end - s->buf_ptr) {
+		AV_WB32(s->buf_ptr, bit_buf);
+		s->buf_ptr += 4;
+	} else {
+		pr_err("Internal error, put_bits buffer too small\n");
+	}
+	bit_buf     = value;
+#endif
+
+	s->bit_buf  = bit_buf;
+	s->bit_left = bit_left;
+}
+
+/**
+ * Write up to 64 bits into a bitstream.
+ */
+static inline void put_bits64(struct put_bits_context *s, int n, uint64_t value)
+{
+	if (n < 32)
+		put_bits(s, n, value);
+	else if (n == 32)
+		put_bits32(s, value);
+	else if (n < 64) {
+		u32 lo = value & 0xffffffff;
+		u32 hi = value >> 32;
+#ifdef BITSTREAM_WRITER_LE
+		put_bits32(s, lo);
+		put_bits(s, n - 32, hi);
+#else
+		put_bits(s, n - 32, hi);
+		put_bits32(s, lo);
+#endif
+	} else {
+		u32 lo = value & 0xffffffff;
+		u32 hi = value >> 32;
+#ifdef BITSTREAM_WRITER_LE
+		put_bits32(s, lo);
+		put_bits32(s, hi);
+#else
+		put_bits32(s, hi);
+		put_bits32(s, lo);
+#endif
+	}
+}
+
+/**
+ * Return the pointer to the byte where the bitstream writer will put
+ * the next bit.
+ */
+static inline u8 *put_bits_ptr(struct put_bits_context *s)
+{
+	return s->buf_ptr;
+}
+
+/**
+ * Skip the given number of bytes.
+ * struct put_bits_context must be flushed & aligned to a byte boundary before calling this.
+ */
+static inline void skip_put_bytes(struct put_bits_context *s, int n)
+{
+	s->buf_ptr += n;
+}
+
+/**
+ * Skip the given number of bits.
+ * Must only be used if the actual values in the bitstream do not matter.
+ * If n is 0 the behavior is undefined.
+ */
+static inline void skip_put_bits(struct put_bits_context *s, int n)
+{
+	s->bit_left -= n;
+	s->buf_ptr  -= 4 * (s->bit_left >> 5);
+	s->bit_left &= 31;
+}
+
+/**
+ * Change the end of the buffer.
+ *
+ * @param size the new size in bytes of the buffer where to put bits
+ */
+static inline void set_put_bits_buffer_size(struct put_bits_context *s, int size)
+{
+	s->buf_end = s->buf + size;
+	s->size_in_bits = 8*size;
+}
+
+#endif /* AVCODEC_PUT_BITS_H */
+
diff --git a/drivers/amvdec_ports/vdec_drv_base.h b/drivers/amvdec_ports/vdec_drv_base.h
new file mode 100644
index 0000000..990d406
--- /dev/null
+++ b/drivers/amvdec_ports/vdec_drv_base.h
@@ -0,0 +1,73 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#ifndef _VDEC_DRV_BASE_
+#define _VDEC_DRV_BASE_
+
+#include "aml_vcodec_drv.h"
+
+#include "vdec_drv_if.h"
+
+struct vdec_common_if {
+	/**
+	 * (*init)() - initialize decode driver
+	 * @ctx     : [in] aml v4l2 context
+	 * @h_vdec  : [out] driver handle
+	 */
+	int (*init)(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec);
+
+	int (*probe)(unsigned long h_vdec,
+		struct aml_vcodec_mem *bs, void *out);
+
+	/**
+	 * (*decode)() - trigger decode
+	 * @h_vdec  : [in] driver handle
+	 * @bs      : [in] input bitstream
+	 * @fb      : [in] frame buffer to store decoded frame
+	 * @res_chg : [out] resolution change happen
+	 */
+	int (*decode)(unsigned long h_vdec, struct aml_vcodec_mem *bs,
+		bool *res_chg);
+
+	/**
+	 * (*get_param)() - get driver's parameter
+	 * @h_vdec : [in] driver handle
+	 * @type   : [in] input parameter type
+	 * @out    : [out] buffer to store query result
+	 */
+	int (*get_param)(unsigned long h_vdec,
+		enum vdec_get_param_type type, void *out);
+
+	/**
+	 * (*set_param)() - set driver's parameter
+	 * @h_vdec : [in] driver handle
+	 * @type   : [in] input parameter type
+	 * @in    : [in] buffer to store query result
+	 */
+	int (*set_param)(unsigned long h_vdec,
+		enum vdec_set_param_type type, void *in);
+
+	/**
+	 * (*deinit)() - deinitialize driver.
+	 * @h_vdec : [in] driver handle to be deinit
+	 */
+	void (*deinit)(unsigned long h_vdec);
+};
+
+#endif
diff --git a/drivers/amvdec_ports/vdec_drv_if.c b/drivers/amvdec_ports/vdec_drv_if.c
new file mode 100644
index 0000000..01510c5
--- /dev/null
+++ b/drivers/amvdec_ports/vdec_drv_if.c
@@ -0,0 +1,139 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "vdec_drv_if.h"
+#include "aml_vcodec_dec.h"
+#include "vdec_drv_base.h"
+
+const struct vdec_common_if *get_h264_dec_comm_if(void);
+const struct vdec_common_if *get_hevc_dec_comm_if(void);
+const struct vdec_common_if *get_vp9_dec_comm_if(void);
+const struct vdec_common_if *get_mpeg12_dec_comm_if(void);
+const struct vdec_common_if *get_mpeg4_dec_comm_if(void);
+const struct vdec_common_if *get_mjpeg_dec_comm_if(void);
+const struct vdec_common_if *get_av1_dec_comm_if(void);
+
+int vdec_if_init(struct aml_vcodec_ctx *ctx, unsigned int fourcc)
+{
+	int ret = 0;
+
+	switch (fourcc) {
+	case V4L2_PIX_FMT_H264:
+		ctx->dec_if = get_h264_dec_comm_if();
+		break;
+	case V4L2_PIX_FMT_HEVC:
+		ctx->dec_if = get_hevc_dec_comm_if();
+		break;
+	case V4L2_PIX_FMT_VP9:
+		ctx->dec_if = get_vp9_dec_comm_if();
+		break;
+	case V4L2_PIX_FMT_MPEG:
+	case V4L2_PIX_FMT_MPEG1:
+	case V4L2_PIX_FMT_MPEG2:
+		ctx->dec_if = get_mpeg12_dec_comm_if();
+		break;
+	case V4L2_PIX_FMT_MPEG4:
+		ctx->dec_if = get_mpeg4_dec_comm_if();
+		break;
+	case V4L2_PIX_FMT_MJPEG:
+		ctx->dec_if = get_mjpeg_dec_comm_if();
+		break;
+	case V4L2_PIX_FMT_AV1:
+		ctx->dec_if = get_av1_dec_comm_if();
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = ctx->dec_if->init(ctx, &ctx->drv_handle);
+
+	return ret;
+}
+
+int vdec_if_probe(struct aml_vcodec_ctx *ctx,
+	struct aml_vcodec_mem *bs, void *out)
+{
+	int ret = 0;
+
+	ret = ctx->dec_if->probe(ctx->drv_handle, bs, out);
+
+	return ret;
+}
+
+int vdec_if_decode(struct aml_vcodec_ctx *ctx,
+		   struct aml_vcodec_mem *bs, bool *res_chg)
+{
+	int ret = 0;
+
+	if (bs) {
+		if ((bs->addr & 63) != 0) {
+			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
+				"bs dma_addr should 64 byte align\n");
+			return -EINVAL;
+		}
+	}
+
+	if (ctx->drv_handle == 0)
+		return -EIO;
+
+	aml_vcodec_set_curr_ctx(ctx->dev, ctx);
+	ret = ctx->dec_if->decode(ctx->drv_handle, bs, res_chg);
+	aml_vcodec_set_curr_ctx(ctx->dev, NULL);
+
+	return ret;
+}
+
+int vdec_if_get_param(struct aml_vcodec_ctx *ctx,
+	enum vdec_get_param_type type, void *out)
+{
+	int ret = 0;
+
+	if (ctx->drv_handle == 0)
+		return -EIO;
+
+	ret = ctx->dec_if->get_param(ctx->drv_handle, type, out);
+
+	return ret;
+}
+
+int vdec_if_set_param(struct aml_vcodec_ctx *ctx,
+	enum vdec_set_param_type type, void *in)
+{
+	int ret = 0;
+
+	if (ctx->drv_handle == 0)
+		return -EIO;
+
+	ret = ctx->dec_if->set_param(ctx->drv_handle, type, in);
+
+	return ret;
+}
+
+void vdec_if_deinit(struct aml_vcodec_ctx *ctx)
+{
+	if (ctx->drv_handle == 0)
+		return;
+
+	ctx->dec_if->deinit(ctx->drv_handle);
+	ctx->drv_handle = 0;
+}
diff --git a/drivers/amvdec_ports/vdec_drv_if.h b/drivers/amvdec_ports/vdec_drv_if.h
new file mode 100644
index 0000000..29911f8
--- /dev/null
+++ b/drivers/amvdec_ports/vdec_drv_if.h
@@ -0,0 +1,165 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#ifndef _VDEC_DRV_IF_H_
+#define _VDEC_DRV_IF_H_
+
+#include "aml_vcodec_drv.h"
+#include "aml_vcodec_dec.h"
+#include "aml_vcodec_util.h"
+#include "../stream_input/amports/streambuf.h"
+
+#define AML_VIDEO_MAGIC CODEC_MODE('A', 'M', 'L', 'V')
+
+#define V4L_STREAM_TYPE_MATEDATA	(0)
+#define V4L_STREAM_TYPE_FRAME		(1)
+
+struct stream_info {
+	u32 stream_width;
+	u32 stream_height;
+	u32 stream_field;
+	u32 stream_dpb;
+};
+
+struct aml_video_stream {
+	u32 magic;
+	u32 type;
+	union {
+		struct stream_info s;
+		u8 buf[64];
+	} m;
+	u32 len;
+	u8 data[0];
+};
+
+/**
+ * struct vdec_fb_status  - decoder frame buffer status
+ * @FB_ST_INIT		: initial state
+ * @FB_ST_DECODER	: frame buffer be allocted by decoder.
+ * @FB_ST_VPP		: frame buffer be allocate by vpp.
+ * @FB_ST_DISPLAY	: frame buffer is ready to be displayed.
+ * @FB_ST_FREE		: frame buffer is not used by decoder any more
+ */
+enum vdec_fb_status {
+	FB_ST_INIT,
+	FB_ST_DECODER,
+	FB_ST_VPP,
+	FB_ST_GE2D,
+	FB_ST_DISPLAY,
+	FB_ST_FREE
+};
+
+enum vdec_dw_mode {
+	VDEC_DW_AFBC_ONLY = 0,
+	VDEC_DW_AFBC_1_1_DW = 1,
+	VDEC_DW_AFBC_1_4_DW = 2,
+	VDEC_DW_AFBC_x2_1_4_DW = 3,
+	VDEC_DW_AFBC_1_2_DW = 4,
+	VDEC_DW_NO_AFBC = 16,
+	VDEC_DW_AFBC_AUTO_1_2 = 0x100,
+	VDEC_DW_AFBC_AUTO_1_4 = 0x200,
+};
+
+/*
+ * the caller does not own the returned buffer. The buffer will not be
+ *				released before vdec_if_deinit.
+ * GET_PARAM_PIC_INFO		: get picture info, struct vdec_pic_info*
+ * GET_PARAM_CROP_INFO		: get crop info, struct v4l2_crop*
+ * GET_PARAM_DPB_SIZE		: get dpb size, unsigned int*
+ * GET_PARAM_DW_MODE:		: get double write mode, unsigned int*
+ * GET_PARAM_COMP_BUF_INFO	: get compressed buf info,  struct vdec_comp_buf_info*
+ */
+enum vdec_get_param_type {
+	GET_PARAM_PIC_INFO,
+	GET_PARAM_CROP_INFO,
+	GET_PARAM_DPB_SIZE,
+	GET_PARAM_CONFIG_INFO,
+	GET_PARAM_DW_MODE,
+	GET_PARAM_COMP_BUF_INFO
+};
+
+/*
+ * SET_PARAM_PS_INFO	       : set picture parms, data parsed from ucode.
+ */
+enum vdec_set_param_type {
+	SET_PARAM_WRITE_FRAME_SYNC,
+	SET_PARAM_PS_INFO,
+	SET_PARAM_COMP_BUF_INFO,
+	SET_PARAM_HDR_INFO,
+	SET_PARAM_POST_EVENT,
+	SET_PARAM_PIC_INFO,
+	SET_PARAM_CFG_INFO
+};
+
+/**
+ * struct vdec_fb_node  - decoder frame buffer node
+ * @list	: list to hold this node
+ * @fb	: point to frame buffer (vdec_fb), fb could point to frame buffer and
+ *	working buffer this is for maintain buffers in different state
+ */
+struct vdec_fb_node {
+	struct list_head list;
+	struct vdec_fb *fb;
+};
+
+/**
+ * vdec_if_init() - initialize decode driver
+ * @ctx	: [in] v4l2 context
+ * @fourcc	: [in] video format fourcc, V4L2_PIX_FMT_H264/VP8/VP9..
+ */
+int vdec_if_init(struct aml_vcodec_ctx *ctx, unsigned int fourcc);
+
+int vdec_if_probe(struct aml_vcodec_ctx *ctx,
+	struct aml_vcodec_mem *bs, void *out);
+
+/**
+ * vdec_if_deinit() - deinitialize decode driver
+ * @ctx	: [in] v4l2 context
+ *
+ */
+void vdec_if_deinit(struct aml_vcodec_ctx *ctx);
+
+/**
+ * vdec_if_decode() - trigger decode
+ * @ctx	: [in] v4l2 context
+ * @bs	: [in] input bitstream
+ * @fb	: [in] frame buffer to store decoded frame, when null menas parse
+ *	header only
+ * @res_chg	: [out] resolution change happens if current bs have different
+ *	picture width/height
+ * Note: To flush the decoder when reaching EOF, set input bitstream as NULL.
+ *
+ * Return: 0 on success. -EIO on unrecoverable error.
+ */
+int vdec_if_decode(struct aml_vcodec_ctx *ctx,
+		   struct aml_vcodec_mem *bs, bool *res_chg);
+
+/**
+ * vdec_if_get_param() - get driver's parameter
+ * @ctx	: [in] v4l2 context
+ * @type	: [in] input parameter type
+ * @out	: [out] buffer to store query result
+ */
+int vdec_if_get_param(struct aml_vcodec_ctx *ctx,
+	enum vdec_get_param_type type, void *out);
+
+int vdec_if_set_param(struct aml_vcodec_ctx *ctx,
+	enum vdec_set_param_type type, void *in);
+
+#endif
diff --git a/drivers/common/Makefile b/drivers/common/Makefile
new file mode 100644
index 0000000..77ce080
--- /dev/null
+++ b/drivers/common/Makefile
@@ -0,0 +1,2 @@
+obj-y	+=	media_clock/
+obj-y	+=	firmware/
diff --git a/drivers/common/chips/chips.c b/drivers/common/chips/chips.c
new file mode 100644
index 0000000..158e32c
--- /dev/null
+++ b/drivers/common/chips/chips.c
@@ -0,0 +1,198 @@
+/*
+ * drivers/amlogic/media/common/arch/chips/chips.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/media/registers/cpu_version.h>
+#include "../../stream_input/amports/amports_priv.h"
+#include "../../frame_provider/decoder/utils/vdec.h"
+#include "chips.h"
+#include <linux/amlogic/media/utils/log.h>
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "decoder_cpu_ver_info.h"
+
+#define VIDEO_FIRMWARE_FATHER_NAME "video"
+
+/*
+ *#define MESON_CPU_MAJOR_ID_M6		0x16
+ *#define MESON_CPU_MAJOR_ID_M6TV		0x17
+ *#define MESON_CPU_MAJOR_ID_M6TVL	0x18
+ *#define MESON_CPU_MAJOR_ID_M8		0x19
+ *#define MESON_CPU_MAJOR_ID_MTVD		0x1A
+ *#define MESON_CPU_MAJOR_ID_M8B		0x1B
+ *#define MESON_CPU_MAJOR_ID_MG9TV	0x1C
+ *#define MESON_CPU_MAJOR_ID_M8M2		0x1D
+ *#define MESON_CPU_MAJOR_ID_GXBB		0x1F
+ *#define MESON_CPU_MAJOR_ID_GXTVBB		0x20
+ *#define MESON_CPU_MAJOR_ID_GXL		0x21
+ *#define MESON_CPU_MAJOR_ID_GXM		0x22
+ *#define MESON_CPU_MAJOR_ID_TXL		0x23
+ */
+struct type_name {
+
+	int type;
+
+	const char *name;
+};
+static const struct type_name cpu_type_name[] = {
+	{AM_MESON_CPU_MAJOR_ID_M6, "m6"},
+	{AM_MESON_CPU_MAJOR_ID_M6TV, "m6tv"},
+	{AM_MESON_CPU_MAJOR_ID_M6TVL, "m6tvl"},
+	{AM_MESON_CPU_MAJOR_ID_M8, "m8"},
+	{AM_MESON_CPU_MAJOR_ID_MTVD, "mtvd"},
+	{AM_MESON_CPU_MAJOR_ID_M8B, "m8b"},
+	{AM_MESON_CPU_MAJOR_ID_MG9TV, "mg9tv"},
+	{AM_MESON_CPU_MAJOR_ID_M8M2, "m8"},
+	{AM_MESON_CPU_MAJOR_ID_GXBB, "gxbb"},
+	{AM_MESON_CPU_MAJOR_ID_GXTVBB, "gxtvbb"},
+	{AM_MESON_CPU_MAJOR_ID_GXL, "gxl"},
+	{AM_MESON_CPU_MAJOR_ID_GXM, "gxm"},
+	{AM_MESON_CPU_MAJOR_ID_TXL, "txl"},
+	{AM_MESON_CPU_MAJOR_ID_TXLX, "txlx"},
+	{AM_MESON_CPU_MAJOR_ID_GXLX, "gxlx"},
+	{AM_MESON_CPU_MAJOR_ID_G12A, "g12a"},
+	{AM_MESON_CPU_MAJOR_ID_G12B, "g12b"},
+	{AM_MESON_CPU_MAJOR_ID_SM1, "sm1"},
+	{AM_MESON_CPU_MAJOR_ID_TL1, "tl1"},
+	{AM_MESON_CPU_MAJOR_ID_TM2, "tm2"},
+	{AM_MESON_CPU_MAJOR_ID_SC2, "sc2"},
+	{AM_MESON_CPU_MAJOR_ID_T5, "t5"},
+	{AM_MESON_CPU_MAJOR_ID_T5D, "t5d"},
+	{AM_MESON_CPU_MAJOR_ID_T7, "t7"},
+	{AM_MESON_CPU_MAJOR_ID_S4, "s4"},
+	{AM_MESON_CPU_MAJOR_ID_T3, "t3"},
+	{AM_MESON_CPU_MAJOR_ID_P1, "p1"},
+	{AM_MESON_CPU_MAJOR_ID_S4D, "s4d"},
+	{AM_MESON_CPU_MAJOR_ID_T5W, "t5w"},
+	{0, NULL},
+};
+
+static const char *get_type_name(const struct type_name *typename, int size,
+	int type)
+{
+
+	const char *name = "unknown";
+
+	int i;
+
+	for (i = 0; i < size; i++) {
+
+		if (type == typename[i].type)
+
+			name = typename[i].name;
+
+	}
+
+	return name;
+}
+
+const char *get_cpu_type_name(void)
+{
+
+	return get_type_name(cpu_type_name,
+		sizeof(cpu_type_name) / sizeof(struct type_name),
+		get_cpu_major_id());
+}
+EXPORT_SYMBOL(get_cpu_type_name);
+
+/*
+ *enum vformat_e {
+ *	VFORMAT_MPEG12 = 0,
+ *	VFORMAT_MPEG4,
+ *	VFORMAT_H264,
+ *	VFORMAT_MJPEG,
+ *	VFORMAT_REAL,
+ *	VFORMAT_JPEG,
+ *	VFORMAT_VC1,
+ *	VFORMAT_AVS,
+ *	VFORMAT_YUV,
+ *	VFORMAT_H264MVC,
+ *	VFORMAT_H264_4K2K,
+ *	VFORMAT_HEVC,
+ *	VFORMAT_H264_ENC,
+ *	VFORMAT_JPEG_ENC,
+ *	VFORMAT_VP9,
+*	VFORMAT_AVS2,
+ *	VFORMAT_MAX
+ *};
+ */
+static const struct type_name vformat_type_name[] = {
+	{VFORMAT_MPEG12, "mpeg12"},
+	{VFORMAT_MPEG4, "mpeg4"},
+	{VFORMAT_H264, "h264"},
+	{VFORMAT_MJPEG, "mjpeg"},
+	{VFORMAT_REAL, "real"},
+	{VFORMAT_JPEG, "jpeg"},
+	{VFORMAT_VC1, "vc1"},
+	{VFORMAT_AVS, "avs"},
+	{VFORMAT_YUV, "yuv"},
+	{VFORMAT_H264MVC, "h264mvc"},
+	{VFORMAT_H264_4K2K, "h264_4k"},
+	{VFORMAT_HEVC, "hevc"},
+	{VFORMAT_H264_ENC, "h264_enc"},
+	{VFORMAT_JPEG_ENC, "jpeg_enc"},
+	{VFORMAT_VP9, "vp9"},
+	{VFORMAT_AVS2, "avs2"},
+	{VFORMAT_AV1, "av1"},
+	{VFORMAT_YUV, "yuv"},
+	{0, NULL},
+};
+
+const char *get_video_format_name(enum vformat_e type)
+{
+
+	return get_type_name(vformat_type_name,
+		sizeof(vformat_type_name) / sizeof(struct type_name), type);
+}
+EXPORT_SYMBOL(get_video_format_name);
+
+static struct chip_vdec_info_s current_chip_info;
+
+struct chip_vdec_info_s *get_current_vdec_chip(void)
+{
+
+	return &current_chip_info;
+}
+EXPORT_SYMBOL(get_current_vdec_chip);
+
+bool check_efuse_chip(int vformat)
+{
+	unsigned int status, i = 0;
+	int type[] = {15, 14, 11, 2}; /* avs2, vp9, h265, h264 */
+
+	status =  (READ_EFUSE_REG(EFUSE_LIC2) >> 8 & 0xf);
+	if (!status)
+		return false;
+
+	do {
+		if ((status & 1) && (type[i] == vformat))
+			return true;
+		i++;
+	} while (status >>= 1);
+
+	return false;
+}
+EXPORT_SYMBOL(check_efuse_chip);
+
diff --git a/drivers/common/chips/chips.h b/drivers/common/chips/chips.h
new file mode 100644
index 0000000..003e9d2
--- /dev/null
+++ b/drivers/common/chips/chips.h
@@ -0,0 +1,40 @@
+/*
+ * drivers/amlogic/media/common/arch/chips/chips.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef UCODE_MANAGER_HEADER
+#define UCODE_MANAGER_HEADER
+#include "../media_clock/clk/clk_priv.h"
+
+struct chip_vdec_info_s {
+
+	int cpu_type;
+
+	struct video_firmware_s *firmware;
+
+	struct chip_vdec_clk_s *clk_mgr[VDEC_MAX];
+
+	struct clk_set_setting *clk_setting_array;
+};
+
+const char *get_cpu_type_name(void);
+const char *get_video_format_name(enum vformat_e type);
+
+struct chip_vdec_info_s *get_current_vdec_chip(void);
+
+bool check_efuse_chip(int vformat);
+
+#endif
diff --git a/drivers/common/chips/decoder_cpu_ver_info.c b/drivers/common/chips/decoder_cpu_ver_info.c
new file mode 100644
index 0000000..af162b8
--- /dev/null
+++ b/drivers/common/chips/decoder_cpu_ver_info.c
@@ -0,0 +1,271 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/kernel.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/amlogic/media/registers/cpu_version.h>
+#include "decoder_cpu_ver_info.h"
+
+#define DECODE_CPU_VER_ID_NODE_NAME "cpu_ver_name"
+#define AM_SUCESS 0
+#define MAJOR_ID_START AM_MESON_CPU_MAJOR_ID_M6
+
+static enum AM_MESON_CPU_MAJOR_ID cpu_ver_id = AM_MESON_CPU_MAJOR_ID_MAX;
+static int cpu_sub_id = 0;
+
+static enum AM_MESON_CPU_MAJOR_ID cpu_ver_info[AM_MESON_CPU_MAJOR_ID_MAX - MAJOR_ID_START]=
+{
+	AM_MESON_CPU_MAJOR_ID_M6,
+	AM_MESON_CPU_MAJOR_ID_M6TV,
+	AM_MESON_CPU_MAJOR_ID_M6TVL,
+	AM_MESON_CPU_MAJOR_ID_M8,
+	AM_MESON_CPU_MAJOR_ID_MTVD,
+	AM_MESON_CPU_MAJOR_ID_M8B,
+	AM_MESON_CPU_MAJOR_ID_MG9TV,
+	AM_MESON_CPU_MAJOR_ID_M8M2,
+	AM_MESON_CPU_MAJOR_ID_UNUSE,
+	AM_MESON_CPU_MAJOR_ID_GXBB,
+	AM_MESON_CPU_MAJOR_ID_GXTVBB,
+	AM_MESON_CPU_MAJOR_ID_GXL,
+	AM_MESON_CPU_MAJOR_ID_GXM,
+	AM_MESON_CPU_MAJOR_ID_TXL,
+	AM_MESON_CPU_MAJOR_ID_TXLX,
+	AM_MESON_CPU_MAJOR_ID_AXG,
+	AM_MESON_CPU_MAJOR_ID_GXLX,
+	AM_MESON_CPU_MAJOR_ID_TXHD,
+	AM_MESON_CPU_MAJOR_ID_G12A,
+	AM_MESON_CPU_MAJOR_ID_G12B,
+	AM_MESON_CPU_MAJOR_ID_GXLX2,
+	AM_MESON_CPU_MAJOR_ID_SM1,
+	AM_MESON_CPU_MAJOR_ID_A1,
+	AM_MESON_CPU_MAJOR_ID_RES_0x2d,
+	AM_MESON_CPU_MAJOR_ID_TL1,
+	AM_MESON_CPU_MAJOR_ID_TM2,
+	AM_MESON_CPU_MAJOR_ID_C1,
+	AM_MESON_CPU_MAJOR_ID_RES_0x31,
+	AM_MESON_CPU_MAJOR_ID_SC2,
+	AM_MESON_CPU_MAJOR_ID_C2,
+	AM_MESON_CPU_MAJOR_ID_T5,
+	AM_MESON_CPU_MAJOR_ID_T5D,
+	AM_MESON_CPU_MAJOR_ID_T7,
+	AM_MESON_CPU_MAJOR_ID_S4,
+	AM_MESON_CPU_MAJOR_ID_T3,
+	AM_MESON_CPU_MAJOR_ID_P1,
+	AM_MESON_CPU_MAJOR_ID_S4D,
+	AM_MESON_CPU_MAJOR_ID_T5W,
+};
+
+static const struct of_device_id cpu_ver_of_match[] = {
+	{
+		.compatible = "amlogic, cpu-major-id-axg",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_AXG - MAJOR_ID_START],
+	},
+
+	{
+		.compatible = "amlogic, cpu-major-id-g12a",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_G12A - MAJOR_ID_START],
+	},
+
+	{
+		.compatible = "amlogic, cpu-major-id-gxl",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_GXL - MAJOR_ID_START],
+	},
+
+	{
+		.compatible = "amlogic, cpu-major-id-gxm",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_GXM - MAJOR_ID_START],
+	},
+
+	{
+		.compatible = "amlogic, cpu-major-id-txl",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TXL - MAJOR_ID_START],
+	},
+
+	{
+		.compatible = "amlogic, cpu-major-id-txlx",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TXLX - MAJOR_ID_START],
+	},
+
+	{
+		.compatible = "amlogic, cpu-major-id-sm1",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_SM1 - MAJOR_ID_START],
+	},
+
+	{
+		.compatible = "amlogic, cpu-major-id-tl1",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TL1 - MAJOR_ID_START],
+	},
+	{
+		.compatible = "amlogic, cpu-major-id-tm2",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_TM2 - MAJOR_ID_START],
+	},
+	{
+		.compatible = "amlogic, cpu-major-id-sc2",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_SC2 - MAJOR_ID_START],
+	},
+	{
+		.compatible = "amlogic, cpu-major-id-t5",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_T5 - MAJOR_ID_START],
+	},
+	{
+		.compatible = "amlogic, cpu-major-id-t5d",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_T5D - MAJOR_ID_START],
+	},
+	{
+		.compatible = "amlogic, cpu-major-id-t7",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_T7 - MAJOR_ID_START],
+	},
+	{
+		.compatible = "amlogic, cpu-major-id-s4",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_S4 - MAJOR_ID_START],
+	},
+	{
+		.compatible = "amlogic, cpu-major-id-t3",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_T3 - MAJOR_ID_START],
+	},
+	{
+		.compatible = "amlogic, cpu-major-id-p1",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_P1 - MAJOR_ID_START],
+	},
+	{
+		.compatible = "amlogic, cpu-major-id-s4d",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_S4D - MAJOR_ID_START],
+	},
+	{
+		.compatible = "amlogic, cpu-major-id-t5w",
+		.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_T5W - MAJOR_ID_START],
+	},
+	{},
+};
+
+static const int cpu_sub_info[] = {
+		AM_MESON_CPU_MINOR_ID_REVB_G12B,
+		AM_MESON_CPU_MINOR_ID_REVB_TM2,
+		AM_MESON_CPU_MINOR_ID_S4_S805X2,
+};
+
+static const struct of_device_id cpu_sub_id_of_match[] = {
+	{
+		.compatible = "amlogic, cpu-major-id-g12b-b",
+		.data = &cpu_sub_info[0],
+	},
+	{
+		.compatible = "amlogic, cpu-major-id-tm2-b",
+		.data = &cpu_sub_info[1],
+	},
+	{
+		.compatible = "amlogic, cpu-major-id-s4-805x2",
+		.data = &cpu_sub_info[2],
+	},
+};
+
+static bool get_cpu_id_from_dtb(enum AM_MESON_CPU_MAJOR_ID *pid_type, int *sub_id)
+{
+	struct device_node *pnode = NULL;
+	struct platform_device *pdev = NULL;
+	const struct of_device_id *pmatch = NULL;
+
+	pnode = of_find_node_by_name(NULL, DECODE_CPU_VER_ID_NODE_NAME);
+	if (NULL == pnode) {
+		pr_err("No find node.\n");
+		return -EINVAL;
+	}
+
+	pdev =  of_find_device_by_node(pnode);
+	if (NULL == pdev)
+		return -EINVAL;
+
+	pmatch = of_match_device(cpu_ver_of_match, &pdev->dev);
+	if (NULL == pmatch) {
+		pmatch = of_match_device(cpu_sub_id_of_match, &pdev->dev);
+		if (NULL == pmatch) {
+			pr_err("No find of_match_device\n");
+			return -EINVAL;
+		}
+	}
+
+	*pid_type = (enum AM_MESON_CPU_MAJOR_ID)(*(int *)pmatch->data) & (MAJOY_ID_MASK);
+
+	*sub_id = ((*(int *)pmatch->data) & (SUB_ID_MASK)) >> 8;
+
+	return AM_SUCESS;
+}
+
+static void initial_cpu_id(void)
+{
+	enum AM_MESON_CPU_MAJOR_ID id_type = AM_MESON_CPU_MAJOR_ID_MAX;
+	int sub_id = 0;
+
+	if (AM_SUCESS == get_cpu_id_from_dtb(&id_type, &sub_id)) {
+		cpu_ver_id = id_type;
+		cpu_sub_id = sub_id;
+	} else {
+		cpu_ver_id = (enum AM_MESON_CPU_MAJOR_ID)get_cpu_type();
+		cpu_sub_id = (is_meson_rev_b()) ? CHIP_REVB : CHIP_REVA;
+	}
+
+	if ((AM_MESON_CPU_MAJOR_ID_G12B == cpu_ver_id) && (CHIP_REVB == cpu_sub_id))
+		cpu_ver_id = AM_MESON_CPU_MAJOR_ID_TL1;
+
+	pr_info("vdec init cpu id: 0x%x(%d)", cpu_ver_id, cpu_sub_id);
+}
+
+enum AM_MESON_CPU_MAJOR_ID get_cpu_major_id(void)
+{
+	if (AM_MESON_CPU_MAJOR_ID_MAX == cpu_ver_id)
+		initial_cpu_id();
+
+	return cpu_ver_id;
+}
+EXPORT_SYMBOL(get_cpu_major_id);
+
+int get_cpu_sub_id(void)
+{
+	return cpu_sub_id;
+}
+EXPORT_SYMBOL(get_cpu_sub_id);
+
+bool is_cpu_meson_revb(void)
+{
+	if (AM_MESON_CPU_MAJOR_ID_MAX == cpu_ver_id)
+		initial_cpu_id();
+
+	return (cpu_sub_id == CHIP_REVB);
+}
+EXPORT_SYMBOL(is_cpu_meson_revb);
+
+bool is_cpu_tm2_revb(void)
+{
+	return ((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_TM2)
+		&& (is_cpu_meson_revb()));
+}
+EXPORT_SYMBOL(is_cpu_tm2_revb);
+
+bool is_cpu_s4_s805x2(void)
+{
+	return ((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_S4)
+		&& (get_cpu_sub_id() == CHIP_REVX));
+}
+EXPORT_SYMBOL(is_cpu_s4_s805x2);
+
diff --git a/drivers/common/chips/decoder_cpu_ver_info.h b/drivers/common/chips/decoder_cpu_ver_info.h
new file mode 100644
index 0000000..6129244
--- /dev/null
+++ b/drivers/common/chips/decoder_cpu_ver_info.h
@@ -0,0 +1,95 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#ifndef DECODER_CPU_VER_INFO_H
+#define DECODER_CPU_VER_INFO_H
+#include <linux/amlogic/media/registers/cpu_version.h>
+/* majoy chip id define */
+#define MAJOY_ID_MASK (0x000000ff)
+
+enum AM_MESON_CPU_MAJOR_ID {
+	AM_MESON_CPU_MAJOR_ID_M6	= 0x16,
+	AM_MESON_CPU_MAJOR_ID_M6TV	= 0x17,
+	AM_MESON_CPU_MAJOR_ID_M6TVL	= 0x18,
+	AM_MESON_CPU_MAJOR_ID_M8	= 0x19,
+	AM_MESON_CPU_MAJOR_ID_MTVD	= 0x1A,
+	AM_MESON_CPU_MAJOR_ID_M8B	= 0x1B,
+	AM_MESON_CPU_MAJOR_ID_MG9TV	= 0x1C,
+	AM_MESON_CPU_MAJOR_ID_M8M2	= 0x1D,
+	AM_MESON_CPU_MAJOR_ID_UNUSE	= 0x1E,
+	AM_MESON_CPU_MAJOR_ID_GXBB	= 0x1F,
+	AM_MESON_CPU_MAJOR_ID_GXTVBB	= 0x20,
+	AM_MESON_CPU_MAJOR_ID_GXL	= 0x21,
+	AM_MESON_CPU_MAJOR_ID_GXM	= 0x22,
+	AM_MESON_CPU_MAJOR_ID_TXL	= 0x23,
+	AM_MESON_CPU_MAJOR_ID_TXLX	= 0x24,
+	AM_MESON_CPU_MAJOR_ID_AXG	= 0x25,
+	AM_MESON_CPU_MAJOR_ID_GXLX	= 0x26,
+	AM_MESON_CPU_MAJOR_ID_TXHD	= 0x27,
+	AM_MESON_CPU_MAJOR_ID_G12A	= 0x28,
+	AM_MESON_CPU_MAJOR_ID_G12B	= 0x29,
+	AM_MESON_CPU_MAJOR_ID_GXLX2	= 0x2a,
+	AM_MESON_CPU_MAJOR_ID_SM1	= 0x2b,
+	AM_MESON_CPU_MAJOR_ID_A1	= 0x2c,
+	AM_MESON_CPU_MAJOR_ID_RES_0x2d,
+	AM_MESON_CPU_MAJOR_ID_TL1	= 0x2e,
+	AM_MESON_CPU_MAJOR_ID_TM2	= 0x2f,
+	AM_MESON_CPU_MAJOR_ID_C1	= 0x30,
+	AM_MESON_CPU_MAJOR_ID_RES_0x31,
+	AM_MESON_CPU_MAJOR_ID_SC2	= 0x32,
+	AM_MESON_CPU_MAJOR_ID_C2	= 0x33,
+	AM_MESON_CPU_MAJOR_ID_T5	= 0x34,
+	AM_MESON_CPU_MAJOR_ID_T5D	= 0x35,
+	AM_MESON_CPU_MAJOR_ID_T7	= 0x36,
+	AM_MESON_CPU_MAJOR_ID_S4	= 0x37,
+	AM_MESON_CPU_MAJOR_ID_T3	= 0x38,
+	AM_MESON_CPU_MAJOR_ID_P1	= 0x39,
+	AM_MESON_CPU_MAJOR_ID_S4D	= 0x3a,
+	AM_MESON_CPU_MAJOR_ID_T5W	= 0x3b,
+	AM_MESON_CPU_MAJOR_ID_MAX,
+};
+
+/* chips sub id define */
+#define CHIP_REVA 0x0
+#define CHIP_REVB 0x1
+#define CHIP_REVC 0x2
+#define CHIP_REVX 0x10
+
+#define REVB_MASK (CHIP_REVB << 8)
+#define REVC_MASK (CHIP_REVC << 8)
+#define REVX_MASK (CHIP_REVX << 8)
+
+#define SUB_ID_MASK (REVB_MASK | REVC_MASK | REVX_MASK)
+
+#define AM_MESON_CPU_MINOR_ID_REVB_G12B	 (REVB_MASK | AM_MESON_CPU_MAJOR_ID_G12B)
+#define AM_MESON_CPU_MINOR_ID_REVB_TM2   (REVB_MASK | AM_MESON_CPU_MAJOR_ID_TM2)
+#define AM_MESON_CPU_MINOR_ID_S4_S805X2  (REVX_MASK | AM_MESON_CPU_MAJOR_ID_S4)
+
+/* export functions */
+enum AM_MESON_CPU_MAJOR_ID get_cpu_major_id(void);
+
+bool is_cpu_meson_revb(void);
+
+bool is_cpu_tm2_revb(void);
+
+int get_cpu_sub_id(void);
+
+bool is_cpu_s4_s805x2(void);
+
+#endif
diff --git a/drivers/common/firmware/Makefile b/drivers/common/firmware/Makefile
new file mode 100644
index 0000000..748039c
--- /dev/null
+++ b/drivers/common/firmware/Makefile
@@ -0,0 +1,3 @@
+obj-m	+=	firmware.o
+firmware-objs	+=	firmware_drv.o
+firmware-objs	+=	firmware_type.o
diff --git a/drivers/common/firmware/firmware_cfg.h b/drivers/common/firmware/firmware_cfg.h
new file mode 100644
index 0000000..e23ac2a
--- /dev/null
+++ b/drivers/common/firmware/firmware_cfg.h
@@ -0,0 +1,32 @@
+/*
+ * drivers/amlogic/media/common/firmware/firmware_cfg.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+/*all firmwares in one bin.*/
+{VIDEO_MISC,	VIDEO_PACKAGE,	"video_ucode.bin"},
+
+/* Note: if the addition of new package has the same name */
+/* as the firmware in the video_ucode.bin, the firmware */
+/* in the video_ucode.bin will be ignored yet, because the */
+/* video_ucode.bin will always be processed in the end */
+{VIDEO_ENCODE,	VIDEO_PACKAGE,	"h264_enc.bin"},
+
+
+/*firmware for a special format, to replace the format in the package.*/
+/*{VIDEO_DECODE,	VIDEO_FW_FILE,	"h265.bin"},*/
+/*{VIDEO_DECODE,	VIDEO_FW_FILE,	"h264.bin"},*/
+/*{VIDEO_DECODE,	VIDEO_FW_FILE,	"h264_multi.bin"},*/
+
diff --git a/drivers/common/firmware/firmware_drv.c b/drivers/common/firmware/firmware_drv.c
new file mode 100644
index 0000000..9422198
--- /dev/null
+++ b/drivers/common/firmware/firmware_drv.c
@@ -0,0 +1,1056 @@
+/*
+ * drivers/amlogic/media/common/firmware/firmware.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/media/registers/cpu_version.h>
+#include "../../stream_input/amports/amports_priv.h"
+#include "../../frame_provider/decoder/utils/vdec.h"
+#include "firmware_priv.h"
+#include "../chips/chips.h"
+#include <linux/string.h>
+#include <linux/amlogic/media/utils/log.h>
+#include <linux/firmware.h>
+#include <linux/amlogic/tee.h>
+//#include <linux/amlogic/major.h> //if kernel is 4.9 then use this one
+#include <uapi/linux/major.h>
+#include <linux/cdev.h>
+#include <linux/crc32.h>
+#include "../chips/decoder_cpu_ver_info.h"
+
+/* major.minor */
+#define PACK_VERS "v0.3"
+
+#define CLASS_NAME	"firmware_codec"
+#define DEV_NAME	"firmware_vdec"
+#define DIR		"video"
+#define FRIMWARE_SIZE	(64 * 1024) /*64k*/
+#define BUFF_SIZE	(1024 * 1024 * 2)
+
+#define FW_LOAD_FORCE	(0x1)
+#define FW_LOAD_TRY	(0X2)
+
+/*the first 256 bytes are signature data*/
+#define SEC_OFFSET	(256)
+
+#define TRY_PARSE_MAX	(256)
+
+#define PACK ('P' << 24 | 'A' << 16 | 'C' << 8 | 'K')
+#define CODE ('C' << 24 | 'O' << 16 | 'D' << 8 | 'E')
+
+#ifndef FIRMWARE_MAJOR
+#define FIRMWARE_MAJOR AMSTREAM_MAJOR
+#endif
+
+static DEFINE_MUTEX(mutex);
+
+static  struct ucode_file_info_s ucode_info[] = {
+#include "firmware_cfg.h"
+};
+
+static const struct file_operations fw_fops = {
+	.owner = THIS_MODULE
+};
+
+struct fw_mgr_s *g_mgr;
+struct fw_dev_s *g_dev;
+struct package_head_s package_head;
+
+static u32 debug;
+static u32 detail;
+
+int get_firmware_data(unsigned int format, char *buf)
+{
+	int data_len, ret = -1;
+	struct fw_mgr_s *mgr = g_mgr;
+	struct fw_info_s *info;
+
+	pr_info("[%s], the fw (%s) will be loaded...\n",
+		tee_enabled() ? "TEE" : "LOCAL",
+		get_fw_format_name(format));
+
+	if (tee_enabled())
+		return 0;
+
+	mutex_lock(&mutex);
+
+	if (list_empty(&mgr->fw_head)) {
+		pr_info("the info list is empty.\n");
+		goto out;
+	}
+
+	list_for_each_entry(info, &mgr->fw_head, node) {
+		if (format != info->format)
+			continue;
+
+		data_len = info->data->head.data_size;
+		memcpy(buf, info->data->data, data_len);
+		ret = data_len;
+
+		break;
+	}
+
+out:
+	mutex_unlock(&mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL(get_firmware_data);
+
+int get_data_from_name(const char *name, char *buf)
+{
+	int data_len, ret = -1;
+	struct fw_mgr_s *mgr = g_mgr;
+	struct fw_info_s *info;
+	char *fw_name = __getname();
+	int len;
+
+	if (fw_name == NULL)
+		return -ENOMEM;
+
+	len = snprintf(fw_name, PATH_MAX, "%s.bin", name);
+	if (len >= PATH_MAX) {
+		__putname(fw_name);
+		return -ENAMETOOLONG;
+	}
+
+	mutex_lock(&mutex);
+
+	if (list_empty(&mgr->fw_head)) {
+		pr_info("the info list is empty.\n");
+		goto out;
+	}
+
+	list_for_each_entry(info, &mgr->fw_head, node) {
+		if (strcmp(fw_name, info->name))
+			continue;
+
+		data_len = info->data->head.data_size;
+		memcpy(buf, info->data->data, data_len);
+		ret = data_len;
+
+		break;
+	}
+out:
+	mutex_unlock(&mutex);
+
+	__putname(fw_name);
+
+	return ret;
+}
+EXPORT_SYMBOL(get_data_from_name);
+
+static int fw_probe(char *buf)
+{
+	int magic = 0;
+
+	memcpy(&magic, buf, sizeof(int));
+	return magic;
+}
+
+static int request_firmware_from_sys(const char *file_name,
+		char *buf, int size)
+{
+	int ret = -1;
+	const struct firmware *fw;
+	int magic, offset = 0;
+
+	pr_info("Try to load %s  ...\n", file_name);
+
+	ret = request_firmware(&fw, file_name, g_dev->dev);
+	if (ret < 0) {
+		pr_info("Error : %d can't load the %s.\n", ret, file_name);
+		goto err;
+	}
+
+	if (fw->size > size) {
+		pr_info("Not enough memory size for ucode.\n");
+		ret = -ENOMEM;
+		goto release;
+	}
+
+	magic = fw_probe((char *)fw->data);
+	if (magic != PACK && magic != CODE) {
+		if (fw->size < SEC_OFFSET) {
+			pr_info("This is an invalid firmware file.\n");
+			goto release;
+		}
+
+		magic = fw_probe((char *)fw->data + SEC_OFFSET);
+		if (magic != PACK) {
+			pr_info("The firmware file is not packet.\n");
+			goto release;
+		}
+
+		offset = SEC_OFFSET;
+	}
+
+	memcpy(buf, (char *)fw->data + offset, fw->size - offset);
+
+	pr_info("load firmware size : %zd, Name : %s.\n",
+		fw->size, file_name);
+	ret = fw->size;
+release:
+	release_firmware(fw);
+err:
+	return ret;
+}
+
+int request_decoder_firmware_on_sys(enum vformat_e format,
+	const char *file_name, char *buf, int size)
+{
+	int ret;
+
+	ret = get_data_from_name(file_name, buf);
+	if (ret < 0)
+		pr_info("Get firmware fail.\n");
+
+	if (ret > size) {
+		pr_info("Not enough memory.\n");
+		return -ENOMEM;
+	}
+
+	return ret;
+}
+int get_decoder_firmware_data(enum vformat_e format,
+	const char *file_name, char *buf, int size)
+{
+	int ret;
+
+	ret = request_decoder_firmware_on_sys(format, file_name, buf, size);
+	if (ret < 0)
+		pr_info("get_decoder_firmware_data %s for format %d failed!\n",
+				file_name, format);
+
+	return ret;
+}
+EXPORT_SYMBOL(get_decoder_firmware_data);
+
+static unsigned long fw_mgr_lock(struct fw_mgr_s *mgr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mgr->lock, flags);
+	return flags;
+}
+
+static void fw_mgr_unlock(struct fw_mgr_s *mgr, unsigned long flags)
+{
+	spin_unlock_irqrestore(&mgr->lock, flags);
+}
+
+static void fw_add_info(struct fw_info_s *info)
+{
+	unsigned long flags;
+	struct fw_mgr_s *mgr = g_mgr;
+
+	flags = fw_mgr_lock(mgr);
+	list_add(&info->node, &mgr->fw_head);
+	fw_mgr_unlock(mgr, flags);
+}
+
+static void fw_del_info(struct fw_info_s *info)
+{
+	unsigned long flags;
+	struct fw_mgr_s *mgr = g_mgr;
+
+	flags = fw_mgr_lock(mgr);
+	list_del(&info->node);
+	kfree(info);
+	fw_mgr_unlock(mgr, flags);
+}
+
+static void fw_info_walk(void)
+{
+	struct fw_mgr_s *mgr = g_mgr;
+	struct fw_info_s *info;
+
+	if (list_empty(&mgr->fw_head)) {
+		pr_info("the info list is empty.\n");
+		return;
+	}
+
+	list_for_each_entry(info, &mgr->fw_head, node) {
+		if (IS_ERR_OR_NULL(info->data))
+			continue;
+
+		pr_info("name : %s.\n", info->name);
+		pr_info("ver  : %s.\n",
+			info->data->head.version);
+		pr_info("crc  : 0x%x.\n",
+			info->data->head.checksum);
+		pr_info("size : %d.\n",
+			info->data->head.data_size);
+		pr_info("maker: %s.\n",
+			info->data->head.maker);
+		pr_info("from : %s.\n", info->src_from);
+		pr_info("date : %s.\n",
+			info->data->head.date);
+		if (info->data->head.duplicate)
+			pr_info("NOTE : Dup from %s.\n",
+				info->data->head.dup_from);
+		pr_info("\n");
+	}
+}
+
+static void fw_files_info_walk(void)
+{
+	struct fw_mgr_s *mgr = g_mgr;
+	struct fw_files_s *files;
+
+	if (list_empty(&mgr->files_head)) {
+		pr_info("the file list is empty.\n");
+		return;
+	}
+
+	list_for_each_entry(files, &mgr->files_head, node) {
+		pr_info("type : %s.\n", !files->fw_type ?
+			"VIDEO_DECODE" : files->fw_type == 1 ?
+			"VIDEO_ENCODE" : "VIDEO_MISC");
+		pr_info("from : %s.\n", !files->file_type ?
+			"VIDEO_PACKAGE" : "VIDEO_FW_FILE");
+		pr_info("path : %s.\n", files->path);
+		pr_info("name : %s.\n\n", files->name);
+	}
+}
+
+static ssize_t info_show(struct class *class,
+			struct class_attribute *attr, char *buf)
+{
+	char *pbuf = buf;
+	struct fw_mgr_s *mgr = g_mgr;
+	struct fw_info_s *info;
+	unsigned int secs = 0;
+	struct tm tm;
+	char history_change_id[7] = {0};
+	int i;
+
+	mutex_lock(&mutex);
+
+	if (list_empty(&mgr->fw_head)) {
+		pbuf += sprintf(pbuf, "No firmware.\n");
+		goto out;
+	}
+
+	/* shows version of driver. */
+	pr_info("The ucode driver version is %s\n", PACK_VERS);
+
+	pr_info("The firmware version is %d.%d.%d-g%s\n",
+			(package_head.version >> 16) & 0xff,
+			package_head.version & 0xff,
+			package_head.submit_count,
+			package_head.commit);
+
+	pr_info("change id history:\n");
+	for (i = 0; i < 5; i++) {
+		memset(history_change_id, 0, sizeof(history_change_id));
+		strncpy(history_change_id, &(package_head.history_change_id[i * 6]), 6);
+		pr_info("\t%s\n", history_change_id);
+		
+	}
+
+	list_for_each_entry(info, &mgr->fw_head, node) {
+		if (IS_ERR_OR_NULL(info->data))
+			continue;
+
+		if (detail) {
+			pr_info("%-5s: %s\n", "name", info->name);
+			pr_info("%-5s: %s\n", "ver",
+				info->data->head.version);
+			pr_info("%-5s: 0x%x\n", "sum",
+				info->data->head.checksum);
+			pr_info("%-5s: %d\n", "size",
+				info->data->head.data_size);
+			pr_info("%-5s: %s\n", "maker",
+				info->data->head.maker);
+			pr_info("%-5s: %s\n", "from",
+				info->src_from);
+			pr_info("%-5s: %s\n\n", "date",
+				info->data->head.date);
+			continue;
+		}
+
+		secs = info->data->head.time
+			- sys_tz.tz_minuteswest * 60;
+		//time_to_tm(secs, 0, &tm);//kernel4.9
+		time64_to_tm(secs, 0, &tm);
+
+		pr_info("%s %-16s, %02d:%02d:%02d %d/%d/%ld, %s %-8s, %s %-8s, %s %s\n",
+			"fmt:", info->data->head.format,
+			tm.tm_hour, tm.tm_min, tm.tm_sec,
+			tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900,
+			"cmtid:", info->data->head.commit,
+			"chgid:", info->data->head.change_id,
+			"mk:", info->data->head.maker);
+	}
+out:
+	mutex_unlock(&mutex);
+
+	return pbuf - buf;
+}
+
+static ssize_t info_store(struct class *cls,
+	struct class_attribute *attr, const char *buf, size_t count)
+{
+	if (kstrtoint(buf, 0, &detail) < 0)
+		return -EINVAL;
+
+	return count;
+}
+
+static int fw_info_fill(void)
+{
+	int ret = 0, i, len;
+	struct fw_mgr_s *mgr = g_mgr;
+	struct fw_files_s *files;
+	int info_size = ARRAY_SIZE(ucode_info);
+	char *path = __getname();
+	const char *name;
+
+	if (path == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < info_size; i++) {
+		name = ucode_info[i].name;
+		if (IS_ERR_OR_NULL(name))
+			break;
+
+		len = snprintf(path, PATH_MAX, "%s/%s", DIR,
+			ucode_info[i].name);
+		if (len >= PATH_MAX)
+			continue;
+
+		files = kzalloc(sizeof(struct fw_files_s), GFP_KERNEL);
+		if (files == NULL) {
+			__putname(path);
+			return -ENOMEM;
+		}
+
+		files->file_type = ucode_info[i].file_type;
+		files->fw_type = ucode_info[i].fw_type;
+		strncpy(files->path, path, sizeof(files->path));
+		files->path[sizeof(files->path) - 1] = '\0';
+		strncpy(files->name, name, sizeof(files->name));
+		files->name[sizeof(files->name) - 1] = '\0';
+
+		list_add(&files->node, &mgr->files_head);
+	}
+
+	__putname(path);
+
+	if (debug)
+		fw_files_info_walk();
+
+	return ret;
+}
+
+static int fw_data_check_sum(struct firmware_s *fw)
+{
+	unsigned int crc;
+
+	crc = crc32_le(~0U, fw->data, fw->head.data_size);
+
+	/*pr_info("firmware crc result : 0x%x\n", crc ^ ~0U);*/
+
+	return fw->head.checksum != (crc ^ ~0U) ? 0 : 1;
+}
+
+static int fw_data_filter(struct firmware_s *fw,
+	struct fw_info_s *fw_info)
+{
+	struct fw_mgr_s *mgr = g_mgr;
+	struct fw_info_s *info, *tmp;
+	int cpu = fw_get_cpu(fw->head.cpu);
+
+	if (mgr->cur_cpu < cpu) {
+		kfree(fw_info);
+		kfree(fw);
+		return -1;
+	}
+
+	/* the encode fw need to ignoring filtering rules. */
+	if (fw_info->format == FIRMWARE_MAX)
+		return 0;
+
+	list_for_each_entry_safe(info, tmp, &mgr->fw_head, node) {
+		if (info->format != fw_info->format)
+			continue;
+
+		if (IS_ERR_OR_NULL(info->data)) {
+			fw_del_info(info);
+			return 0;
+		}
+
+		/* high priority of VIDEO_FW_FILE */
+		if (info->file_type == VIDEO_FW_FILE) {
+			pr_info("the %s need to priority proc.\n",info->name);
+			kfree(fw_info);
+			kfree(fw);
+			return 1;
+		}
+
+		/* the cpu ver is lower and needs to be filtered */
+		if (cpu < fw_get_cpu(info->data->head.cpu)) {
+			if (debug)
+				pr_info("keep the newer fw (%s) and ignore the older fw (%s).\n",
+					info->name, fw_info->name);
+			kfree(fw_info);
+			kfree(fw);
+			return 1;
+		}
+
+		/* removes not match fw from info list */
+		if (debug)
+			pr_info("drop the old fw (%s) will be load the newer fw (%s).\n",
+					info->name, fw_info->name);
+		kfree(info->data);
+		fw_del_info(info);
+	}
+
+	return 0;
+}
+
+static int fw_replace_dup_data(char *buf)
+{
+	int ret = 0;
+	struct fw_mgr_s *mgr = g_mgr;
+	struct package_s *pkg =
+		(struct package_s *) buf;
+	struct package_info_s *pinfo =
+		(struct package_info_s *) pkg->data;
+	struct fw_info_s *info = NULL;
+	char *pdata = pkg->data;
+	int try_cnt = TRY_PARSE_MAX;
+
+	do {
+		if (!pinfo->head.length)
+			break;
+		list_for_each_entry(info, &mgr->fw_head, node) {
+			struct firmware_s *comp = NULL;
+			struct firmware_s *data = NULL;
+			int len = 0;
+
+			comp = (struct firmware_s *)pinfo->data;
+			if (comp->head.duplicate)
+				break;
+
+			if (!info->data->head.duplicate ||
+				comp->head.checksum !=
+				info->data->head.checksum)
+				continue;
+
+			len = pinfo->head.length;
+			data = kzalloc(len, GFP_KERNEL);
+			if (data == NULL) {
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			memcpy(data, pinfo->data, len);
+
+			/* update header information. */
+			memcpy(data, info->data, sizeof(*data));
+
+			/* if replaced success need to update real size. */
+			data->head.data_size = comp->head.data_size;
+
+			kfree(info->data);
+			info->data = data;
+		}
+		pdata += (pinfo->head.length + sizeof(*pinfo));
+		pinfo = (struct package_info_s *)pdata;
+	} while (try_cnt--);
+out:
+	return ret;
+}
+
+static int fw_check_pack_version(char *buf)
+{
+	struct package_s *pack = NULL;
+	int major, minor, major_fw, minor_fw;
+	int ret;
+
+	pack = (struct package_s *) buf;
+	ret = sscanf(PACK_VERS, "v%x.%x", &major, &minor);
+	if (ret != 2)
+		return -1;
+
+	package_head = pack->head;
+	major_fw = (pack->head.version >> 16) & 0xff;
+	minor_fw = pack->head.version & 0xff;
+
+	if (major < major_fw) {
+		pr_info("the pack ver v%d.%d too higher to unsupport.\n",
+			major_fw, minor_fw);
+		return -1;
+	}
+
+	if (minor < minor_fw) {
+		pr_info("The fw driver version (v%d.%d) is lower than the pkg version (v%d.%d).\n",
+			major, minor, major_fw, minor_fw);
+		pr_info("The driver version is too low that may affect the work please update asap.\n");
+	}
+
+	if (debug) {
+		pr_info("The package has %d fws totally.\n", pack->head.total);
+		pr_info("The driver ver is v%d.%d\n", major, minor);
+		pr_info("The firmware ver is v%d.%d.%d\n", major_fw, minor_fw, pack->head.submit_count);
+	}
+
+	return 0;
+}
+
+static int fw_package_parse(struct fw_files_s *files,
+	char *buf, int size)
+{
+	int ret = 0;
+	struct package_info_s *pack_info;
+	struct fw_info_s *info;
+	struct firmware_s *data;
+	char *pack_data;
+	int info_len, len;
+	int try_cnt = TRY_PARSE_MAX;
+	char *path = __getname();
+
+	if (path == NULL)
+		return -ENOMEM;
+
+	pack_data = ((struct package_s *)buf)->data;
+	pack_info = (struct package_info_s *)pack_data;
+	info_len = sizeof(struct package_info_s);
+
+	do {
+		if (!pack_info->head.length)
+			break;
+
+		len = snprintf(path, PATH_MAX, "%s/%s", DIR,
+			pack_info->head.name);
+		if (len >= PATH_MAX)
+			continue;
+
+		info = kzalloc(sizeof(struct fw_info_s), GFP_KERNEL);
+		if (info == NULL) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		data = kzalloc(FRIMWARE_SIZE, GFP_KERNEL);
+		if (data == NULL) {
+			kfree(info);
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		info->file_type = files->file_type;
+		strncpy(info->src_from, files->name,
+			sizeof(info->src_from));
+		info->src_from[sizeof(info->src_from) - 1] = '\0';
+		strncpy(info->name, pack_info->head.name,
+			sizeof(info->name));
+		info->name[sizeof(info->name) - 1] = '\0';
+		info->format = get_fw_format(pack_info->head.format);
+
+		len = pack_info->head.length;
+		memcpy(data, pack_info->data, len);
+
+		pack_data += (pack_info->head.length + info_len);
+		pack_info = (struct package_info_s *)pack_data;
+
+		if (!data->head.duplicate &&
+			!fw_data_check_sum(data)) {
+			pr_info("check sum fail !\n");
+			kfree(data);
+			kfree(info);
+			goto out;
+		}
+
+		if (fw_data_filter(data, info))
+			continue;
+
+		if (debug)
+			pr_info("adds %s to the fw list.\n", info->name);
+
+		info->data = data;
+		fw_add_info(info);
+	} while (try_cnt--);
+
+	/* process the fw of dup attribute. */
+	ret = fw_replace_dup_data(buf);
+	if (ret)
+		pr_err("replace dup fw failed.\n");
+out:
+	__putname(path);
+
+	return ret;
+}
+
+static int fw_code_parse(struct fw_files_s *files,
+	char *buf, int size)
+{
+	struct fw_info_s *info;
+
+	info = kzalloc(sizeof(struct fw_info_s), GFP_KERNEL);
+	if (info == NULL)
+		return -ENOMEM;
+
+	info->data = kzalloc(FRIMWARE_SIZE, GFP_KERNEL);
+	if (info->data == NULL) {
+		kfree(info);
+		return -ENOMEM;
+	}
+
+	info->file_type = files->file_type;
+	strncpy(info->src_from, files->name,
+		sizeof(info->src_from));
+	info->src_from[sizeof(info->src_from) - 1] = '\0';
+	memcpy(info->data, buf, size);
+
+	if (!fw_data_check_sum(info->data)) {
+		pr_info("check sum fail !\n");
+		kfree(info->data);
+		kfree(info);
+		return -1;
+	}
+
+	if (debug)
+		pr_info("adds %s to the fw list.\n", info->name);
+
+	fw_add_info(info);
+
+	return 0;
+}
+
+static int get_firmware_from_sys(const char *path,
+	char *buf, int size)
+{
+	int len = 0;
+
+	len = request_firmware_from_sys(path, buf, size);
+	if (len < 0)
+		pr_info("get data from fsys fail.\n");
+
+	return len;
+}
+
+static int fw_data_binding(void)
+{
+	int ret = 0, magic = 0;
+	struct fw_mgr_s *mgr = g_mgr;
+	struct fw_files_s *files, *tmp;
+	char *buf = NULL;
+	int size;
+
+	if (list_empty(&mgr->files_head)) {
+		pr_info("the file list is empty.\n");
+		return 0;
+	}
+
+	buf = vmalloc(BUFF_SIZE);
+	if (IS_ERR_OR_NULL(buf))
+		return -ENOMEM;
+
+	memset(buf, 0, BUFF_SIZE);
+
+	list_for_each_entry_safe(files, tmp, &mgr->files_head, node) {
+		size = get_firmware_from_sys(files->path, buf, BUFF_SIZE);
+		magic = fw_probe(buf);
+
+		if (files->file_type == VIDEO_PACKAGE && magic == PACK) {
+			if (!fw_check_pack_version(buf))
+				ret = fw_package_parse(files, buf, size);
+		} else if (files->file_type == VIDEO_FW_FILE && magic == CODE) {
+			ret = fw_code_parse(files, buf, size);
+		} else {
+			list_del(&files->node);
+			kfree(files);
+			pr_info("invaild file type.\n");
+		}
+
+		memset(buf, 0, BUFF_SIZE);
+	}
+
+	if (debug)
+		fw_info_walk();
+
+	vfree(buf);
+
+	return ret;
+}
+
+static int fw_pre_load(void)
+{
+	if (fw_info_fill() < 0) {
+		pr_info("Get path fail.\n");
+		return -1;
+	}
+
+	if (fw_data_binding() < 0) {
+		pr_info("Set data fail.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int fw_mgr_init(void)
+{
+	g_mgr = kzalloc(sizeof(struct fw_mgr_s), GFP_KERNEL);
+	if (IS_ERR_OR_NULL(g_mgr))
+		return -ENOMEM;
+
+	g_mgr->cur_cpu = get_cpu_major_id();
+	INIT_LIST_HEAD(&g_mgr->files_head);
+	INIT_LIST_HEAD(&g_mgr->fw_head);
+	spin_lock_init(&g_mgr->lock);
+
+	return 0;
+}
+
+static void fw_ctx_clean(void)
+{
+	struct fw_mgr_s *mgr = g_mgr;
+	struct fw_files_s *files;
+	struct fw_info_s *info;
+	unsigned long flags;
+
+	flags = fw_mgr_lock(mgr);
+	while (!list_empty(&mgr->files_head)) {
+		files = list_entry(mgr->files_head.next,
+			struct fw_files_s, node);
+		list_del(&files->node);
+		kfree(files);
+	}
+
+	while (!list_empty(&mgr->fw_head)) {
+		info = list_entry(mgr->fw_head.next,
+			struct fw_info_s, node);
+		list_del(&info->node);
+		kfree(info->data);
+		kfree(info);
+	}
+	fw_mgr_unlock(mgr, flags);
+}
+
+int video_fw_reload(int mode)
+{
+	int ret = 0;
+	struct fw_mgr_s *mgr = g_mgr;
+
+	if (tee_enabled())
+		return 0;
+
+	mutex_lock(&mutex);
+
+	if (mode & FW_LOAD_FORCE) {
+		fw_ctx_clean();
+
+		ret = fw_pre_load();
+		if (ret < 0)
+			pr_err("The fw reload fail.\n");
+	} else if (mode & FW_LOAD_TRY) {
+		if (!list_empty(&mgr->fw_head)) {
+			pr_info("The fw has been loaded.\n");
+			goto out;
+		}
+
+		ret = fw_pre_load();
+		if (ret < 0)
+			pr_err("The fw try to reload fail.\n");
+	}
+out:
+	mutex_unlock(&mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL(video_fw_reload);
+
+static ssize_t reload_show(struct class *class,
+			struct class_attribute *attr, char *buf)
+{
+	char *pbuf = buf;
+
+	pbuf += sprintf(pbuf, "The fw reload usage.\n");
+	pbuf += sprintf(pbuf, "> set 1 means that the fw is forced to update\n");
+	pbuf += sprintf(pbuf, "> set 2 means that the fw is try to reload\n");
+
+	return pbuf - buf;
+}
+
+static ssize_t reload_store(struct class *class,
+		struct class_attribute *attr,
+		const char *buf, size_t size)
+{
+	int ret = -1;
+	unsigned int val;
+
+	ret = kstrtoint(buf, 0, &val);
+	if (ret != 0)
+		return -EINVAL;
+
+	ret = video_fw_reload(val);
+	if (ret < 0)
+		pr_err("fw reload fail.\n");
+
+	return size;
+}
+
+static ssize_t debug_show(struct class *cls,
+	struct class_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%x\n", debug);
+}
+
+static ssize_t debug_store(struct class *cls,
+	struct class_attribute *attr, const char *buf, size_t count)
+{
+	if (kstrtoint(buf, 0, &debug) < 0)
+		return -EINVAL;
+
+	return count;
+}
+
+#if 0 //kernel4.9
+static struct class_attribute fw_class_attrs[] = {
+	__ATTR(info, 0664, info_show, info_store),
+	__ATTR(reload, 0664, reload_show, reload_store),
+	__ATTR(debug, 0664, debug_show, debug_store),
+	__ATTR_NULL
+};
+
+static struct class fw_class = {
+	.name = CLASS_NAME,
+	.class_attrs = fw_class_attrs,
+};
+#else //below is for kernel 4.19 and 5.4
+static CLASS_ATTR_RW(info);
+static CLASS_ATTR_RW(reload);
+static CLASS_ATTR_RW(debug);
+
+static struct attribute *fw_class_attrs[] = {
+	&class_attr_info.attr,
+	&class_attr_reload.attr,
+	&class_attr_debug.attr,
+	NULL
+};
+
+ATTRIBUTE_GROUPS(fw_class);
+
+static struct class fw_class = {
+	.name = CLASS_NAME,
+	.class_groups = fw_class_groups,
+};
+
+#endif
+static int fw_driver_init(void)
+{
+	int ret = -1;
+
+	g_dev = kzalloc(sizeof(struct fw_dev_s), GFP_KERNEL);
+	if (IS_ERR_OR_NULL(g_dev))
+		return -ENOMEM;
+
+	g_dev->dev_no = MKDEV(FIRMWARE_MAJOR, 100);
+
+	ret = register_chrdev_region(g_dev->dev_no, 1, DEV_NAME);
+	if (ret < 0) {
+		pr_info("Can't get major number %d.\n", FIRMWARE_MAJOR);
+		goto err;
+	}
+
+	cdev_init(&g_dev->cdev, &fw_fops);
+	g_dev->cdev.owner = THIS_MODULE;
+
+	ret = cdev_add(&g_dev->cdev, g_dev->dev_no, 1);
+	if (ret) {
+		pr_info("Error %d adding cdev fail.\n", ret);
+		goto err;
+	}
+
+	ret = class_register(&fw_class);
+	if (ret < 0) {
+		pr_info("Failed in creating class.\n");
+		goto err;
+	}
+
+	g_dev->dev = device_create(&fw_class, NULL,
+		g_dev->dev_no, NULL, DEV_NAME);
+	if (IS_ERR_OR_NULL(g_dev->dev)) {
+		pr_info("Create device failed.\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	pr_info("Registered firmware driver success.\n");
+err:
+	return ret;
+}
+
+static void fw_driver_exit(void)
+{
+	cdev_del(&g_dev->cdev);
+	device_destroy(&fw_class, g_dev->dev_no);
+	class_unregister(&fw_class);
+	unregister_chrdev_region(g_dev->dev_no, 1);
+	kfree(g_dev);
+	kfree(g_mgr);
+}
+
+static int __init fw_module_init(void)
+{
+	int ret = -1;
+
+	ret = fw_driver_init();
+	if (ret) {
+		pr_info("Error %d firmware driver init fail.\n", ret);
+		goto err;
+	}
+
+	ret = fw_mgr_init();
+	if (ret) {
+		pr_info("Error %d firmware mgr init fail.\n", ret);
+		goto err;
+	}
+
+	ret = fw_pre_load();
+	if (ret) {
+		pr_info("Error %d firmware pre load fail.\n", ret);
+		goto err;
+	}
+err:
+	return ret;
+}
+
+static void __exit fw_module_exit(void)
+{
+	fw_ctx_clean();
+	fw_driver_exit();
+	pr_info("Firmware driver cleaned up.\n");
+}
+
+module_init(fw_module_init);
+module_exit(fw_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nanxin Qin <nanxin.qin@amlogic.com>");
diff --git a/drivers/common/firmware/firmware_priv.h b/drivers/common/firmware/firmware_priv.h
new file mode 100644
index 0000000..d901f9d
--- /dev/null
+++ b/drivers/common/firmware/firmware_priv.h
@@ -0,0 +1,124 @@
+/*
+ * drivers/amlogic/media/common/firmware/firmware.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+*/
+
+#ifndef __VIDEO_FIRMWARE_PRIV_HEAD_
+#define __VIDEO_FIRMWARE_PRIV_HEAD_
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/cdev.h>
+#include "firmware_type.h"
+
+struct fw_mgr_s {
+	struct list_head fw_head;
+	struct list_head files_head;
+	spinlock_t lock;
+	int cur_cpu;
+};
+
+struct fw_files_s {
+	struct list_head node;
+	int fw_type;
+	int file_type;
+	char name[32];
+	char path[64];
+};
+
+struct ucode_file_info_s {
+	int fw_type;
+	int file_type;
+	const char *name;
+};
+
+struct fw_info_s {
+	struct list_head node;
+	char name[32];
+	char src_from[32];
+	int file_type;
+	unsigned int format;
+	struct firmware_s *data;
+};
+
+struct fw_head_s {
+	int magic;
+	int checksum;
+	char name[32];
+	char cpu[16];
+	char format[32];
+	char version[32];
+	char maker[32];
+	char date[32];
+	char commit[16];
+	int data_size;
+	unsigned int time;
+	char change_id[16];
+	int duplicate;
+	char dup_from[16];
+	char reserved[92];
+};
+
+struct firmware_s {
+	union {
+		struct fw_head_s head;
+		char buf[512];
+	};
+	char data[0];
+};
+
+struct package_head_s {
+	int magic;
+	int size;
+	int checksum;
+	int total;
+	int version;
+	int submit_count;
+	char change_id[16];
+	char commit[16];
+	char history_change_id[30];
+	char reserved[62];
+};
+
+struct package_s {
+	union {
+		struct package_head_s head;
+		char buf[256];
+	};
+	char data[0];
+};
+
+struct info_head_s {
+	char name[32];
+	char format[32];
+	char cpu[32];
+	int length;
+};
+
+struct package_info_s {
+	union {
+		struct info_head_s head;
+		char buf[256];
+	};
+	char data[0];
+};
+
+struct fw_dev_s {
+	struct cdev cdev;
+	struct device *dev;
+	dev_t dev_no;
+};
+
+#endif
diff --git a/drivers/common/firmware/firmware_type.c b/drivers/common/firmware/firmware_type.c
new file mode 100644
index 0000000..8d95c12
--- /dev/null
+++ b/drivers/common/firmware/firmware_type.c
@@ -0,0 +1,129 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include "firmware_type.h"
+#include "../chips/decoder_cpu_ver_info.h"
+
+static const struct format_name_s format_name[] = {
+	{VIDEO_DEC_MPEG12,		"mpeg12"},
+	{VIDEO_DEC_MPEG12_MULTI,	"mpeg12_multi"},
+	{VIDEO_DEC_MPEG4_3,		"mpeg4_3"},
+	{VIDEO_DEC_MPEG4_4,		"mpeg4_4"},
+	{VIDEO_DEC_MPEG4_4_MULTI,	"mpeg4_4_multi"},
+	{VIDEO_DEC_MPEG4_5,		"xvid"},
+	{VIDEO_DEC_MPEG4_5_MULTI,	"xvid_multi"},
+	{VIDEO_DEC_H263,		"h263"},
+	{VIDEO_DEC_H263_MULTI,		"h263_multi"},
+	{VIDEO_DEC_MJPEG,		"mjpeg"},
+	{VIDEO_DEC_MJPEG_MULTI,		"mjpeg_multi"},
+	{VIDEO_DEC_REAL_V8,		"real_v8"},
+	{VIDEO_DEC_REAL_V9,		"real_v9"},
+	{VIDEO_DEC_VC1,			"vc1"},
+	{VIDEO_DEC_VC1_G12A,		"vc1_g12a"},
+	{VIDEO_DEC_AVS,			"avs"},
+	{VIDEO_DEC_AVS_GXM,		"avs_gxm"},
+	{VIDEO_DEC_AVS_NOCABAC,		"avs_no_cabac"},
+	{VIDEO_DEC_AVS_MULTI,		"avs_multi"},
+	{VIDEO_DEC_H264,		"h264"},
+	{VIDEO_DEC_H264_MVC,		"h264_mvc"},
+	{VIDEO_DEC_H264_MVC_GXM,	"h264_mvc_gxm"},
+	{VIDEO_DEC_H264_MULTI,		"h264_multi"},
+	{VIDEO_DEC_H264_MULTI_MMU,	"h264_multi_mmu"},
+	{VIDEO_DEC_H264_MULTI_GXM,	"h264_multi_gxm"},
+	{VIDEO_DEC_HEVC,		"hevc"},
+	{VIDEO_DEC_HEVC_MMU,		"hevc_mmu"},
+	{VIDEO_DEC_HEVC_MMU_SWAP,	"hevc_mmu_swap"},
+	{VIDEO_DEC_HEVC_G12A,		"hevc_g12a"},
+	{VIDEO_DEC_VP9,			"vp9"},
+	{VIDEO_DEC_VP9_MMU,		"vp9_mmu"},
+	{VIDEO_DEC_VP9_G12A,		"vp9_g12a"},
+	{VIDEO_DEC_AVS2,		"avs2"},
+	{VIDEO_DEC_AVS2_MMU,		"avs2_mmu"},
+	{VIDEO_DEC_AV1_MMU,		"av1_mmu"},
+	{VIDEO_ENC_H264,		"h264_enc"},
+	{VIDEO_ENC_JPEG,		"jpeg_enc"},
+	{FIRMWARE_MAX,			"unknown"},
+};
+
+static const struct cpu_type_s cpu_type[] = {
+	{AM_MESON_CPU_MAJOR_ID_GXL,	"gxl"},
+	{AM_MESON_CPU_MAJOR_ID_GXM,	"gxm"},
+	{AM_MESON_CPU_MAJOR_ID_TXL,	"txl"},
+	{AM_MESON_CPU_MAJOR_ID_TXLX,	"txlx"},
+	{AM_MESON_CPU_MAJOR_ID_AXG,	"axg"},
+	{AM_MESON_CPU_MAJOR_ID_GXLX,	"gxlx"},
+	{AM_MESON_CPU_MAJOR_ID_TXHD,	"txhd"},
+	{AM_MESON_CPU_MAJOR_ID_G12A,	"g12a"},
+	{AM_MESON_CPU_MAJOR_ID_G12B,	"g12b"},
+	{AM_MESON_CPU_MAJOR_ID_GXLX2,	"gxlx2"},
+	{AM_MESON_CPU_MAJOR_ID_SM1,	"sm1"},
+	{AM_MESON_CPU_MAJOR_ID_TL1,	"tl1"},
+	{AM_MESON_CPU_MAJOR_ID_TM2,	"tm2"},
+	{AM_MESON_CPU_MAJOR_ID_SC2,	"sc2"},
+	{AM_MESON_CPU_MAJOR_ID_T5,	"t5"},
+	{AM_MESON_CPU_MAJOR_ID_T5D,	"t5d"},
+	{AM_MESON_CPU_MAJOR_ID_T7,	"t7"},
+	{AM_MESON_CPU_MAJOR_ID_S4,	"s4"},
+	{AM_MESON_CPU_MAJOR_ID_T3,	"t3"},
+	{AM_MESON_CPU_MAJOR_ID_P1,	"p1"},
+	{AM_MESON_CPU_MAJOR_ID_S4D,	"s4d"},
+};
+
+const char *get_fw_format_name(unsigned int format)
+{
+	const char *name = "unknown";
+	int i, size = ARRAY_SIZE(format_name);
+
+	for (i = 0; i < size; i++) {
+		if (format == format_name[i].format)
+			name = format_name[i].name;
+	}
+
+	return name;
+}
+EXPORT_SYMBOL(get_fw_format_name);
+
+unsigned int get_fw_format(const char *name)
+{
+	unsigned int format = FIRMWARE_MAX;
+	int i, size = ARRAY_SIZE(format_name);
+
+	for (i = 0; i < size; i++) {
+		if (!strcmp(name, format_name[i].name))
+			format = format_name[i].format;
+	}
+
+	return format;
+}
+EXPORT_SYMBOL(get_fw_format);
+
+int fw_get_cpu(const char *name)
+{
+	int type = 0;
+	int i, size = ARRAY_SIZE(cpu_type);
+
+	for (i = 0; i < size; i++) {
+		if (!strcmp(name, cpu_type[i].name))
+			type = cpu_type[i].type;
+	}
+
+	return type;
+}
+EXPORT_SYMBOL(fw_get_cpu);
+
diff --git a/drivers/common/firmware/firmware_type.h b/drivers/common/firmware/firmware_type.h
new file mode 100644
index 0000000..4615baf
--- /dev/null
+++ b/drivers/common/firmware/firmware_type.h
@@ -0,0 +1,99 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#ifndef __VIDEO_FIRMWARE_FORMAT_
+#define __VIDEO_FIRMWARE_FORMAT_
+
+#include <linux/slab.h>
+
+/* example: #define VIDEO_DEC_AV1  TAG('A', 'V', '1', '-')*/
+#define TAG(a, b, c, d)\
+	((a << 24) | (b << 16) | (c << 8) | d)
+
+/* fws define */
+#define VIDEO_DEC_MPEG12		(0)
+#define VIDEO_DEC_MPEG4_3		(1)
+#define VIDEO_DEC_MPEG4_4		(2)
+#define VIDEO_DEC_MPEG4_5		(3)
+#define VIDEO_DEC_H263			(4)
+#define VIDEO_DEC_MJPEG			(5)
+#define VIDEO_DEC_MJPEG_MULTI		(6)
+#define VIDEO_DEC_REAL_V8		(7)
+#define VIDEO_DEC_REAL_V9		(8)
+#define VIDEO_DEC_VC1			(9)
+#define VIDEO_DEC_AVS			(10)
+#define VIDEO_DEC_H264			(11)
+#define VIDEO_DEC_H264_4k2K		(12)
+#define VIDEO_DEC_H264_4k2K_SINGLE	(13)
+#define VIDEO_DEC_H264_MVC		(14)
+#define VIDEO_DEC_H264_MULTI		(15)
+#define VIDEO_DEC_HEVC			(16)
+#define VIDEO_DEC_HEVC_MMU		(17)
+#define VIDEO_DEC_VP9			(18)
+#define VIDEO_DEC_VP9_MMU		(19)
+#define VIDEO_ENC_H264			(20)
+#define VIDEO_ENC_JPEG			(21)
+#define VIDEO_DEC_H264_MULTI_MMU	(23)
+#define VIDEO_DEC_HEVC_G12A		(24)
+#define VIDEO_DEC_VP9_G12A		(25)
+#define VIDEO_DEC_AVS2			(26)
+#define VIDEO_DEC_AVS2_MMU		(27)
+#define VIDEO_DEC_AVS_GXM		(28)
+#define VIDEO_DEC_AVS_NOCABAC		(29)
+#define VIDEO_DEC_H264_MULTI_GXM	(30)
+#define VIDEO_DEC_H264_MVC_GXM		(31)
+#define VIDEO_DEC_VC1_G12A		(32)
+#define VIDEO_DEC_MPEG12_MULTI		TAG('M', '1', '2', 'M')
+#define VIDEO_DEC_MPEG4_4_MULTI		TAG('M', '4', '4', 'M')
+#define VIDEO_DEC_MPEG4_5_MULTI		TAG('M', '4', '5', 'M')
+#define VIDEO_DEC_H263_MULTI		TAG('2', '6', '3', 'M')
+#define VIDEO_DEC_HEVC_MMU_SWAP		TAG('2', '6', '5', 'S')
+#define VIDEO_DEC_AVS_MULTI		TAG('A', 'V', 'S', 'M')
+#define VIDEO_DEC_AV1_MMU		TAG('A', 'V', '1', 'M')
+
+/* ... */
+#define FIRMWARE_MAX			(UINT_MAX)
+
+#define VIDEO_PACKAGE			(0)
+#define VIDEO_FW_FILE			(1)
+
+#define VIDEO_DECODE			(0)
+#define VIDEO_ENCODE			(1)
+#define VIDEO_MISC			(2)
+
+#define OPTEE_VDEC_LEGENCY		(0)
+#define OPTEE_VDEC			(1)
+#define OPTEE_VDEC_HEVC			(2)
+#define OPTEE_VDEC_HCDEC			(3)
+
+struct format_name_s {
+	unsigned int format;
+	const char *name;
+};
+
+struct cpu_type_s {
+	int type;
+	const char *name;
+};
+
+const char *get_fw_format_name(unsigned int format);
+unsigned int get_fw_format(const char *name);
+int fw_get_cpu(const char *name);
+
+#endif
diff --git a/drivers/common/media_clock/Makefile b/drivers/common/media_clock/Makefile
new file mode 100644
index 0000000..975b5e5
--- /dev/null
+++ b/drivers/common/media_clock/Makefile
@@ -0,0 +1,6 @@
+obj-m	+=	media_clock.o
+media_clock-objs += ../chips/chips.o
+media_clock-objs += clk/clkg12.o
+media_clock-objs += clk/clk.o
+media_clock-objs += switch/amports_gate.o
+media_clock-objs += ../chips/decoder_cpu_ver_info.o
diff --git a/drivers/common/media_clock/clk/clk.c b/drivers/common/media_clock/clk/clk.c
new file mode 100644
index 0000000..6340c1a
--- /dev/null
+++ b/drivers/common/media_clock/clk/clk.c
@@ -0,0 +1,473 @@
+/*
+ * drivers/amlogic/media/common/arch/clk/clk.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/media/registers/cpu_version.h>
+#include "../../../stream_input/amports/amports_priv.h"
+#include "../../../frame_provider/decoder/utils/vdec.h"
+#include "../../chips/chips.h"
+#include "clk_priv.h"
+#include <linux/amlogic/media/utils/log.h>
+#include "../../chips/decoder_cpu_ver_info.h"
+
+#define p_vdec() (get_current_vdec_chip()->clk_mgr[VDEC_1])
+#define p_vdec2() (get_current_vdec_chip()->clk_mgr[VDEC_2])
+#define p_vdec_hcodec() (get_current_vdec_chip()->clk_mgr[VDEC_HCODEC])
+#define p_vdec_hevc() (get_current_vdec_chip()->clk_mgr[VDEC_HEVC])
+#define p_vdec_hevc_back() (get_current_vdec_chip()->clk_mgr[VDEC_HEVCB])
+
+static int clock_source_wxhxfps_saved[VDEC_MAX + 1];
+
+#define IF_HAVE_RUN(p, fn)\
+	do {\
+		if (p && p->fn)\
+			p->fn();\
+	} while (0)
+/*
+ *#define IF_HAVE_RUN_P1_RET(p, fn, p1)\
+ *			do {\
+ *				pr_debug("%s-----%d\n", __func__, clk);\
+ *				if (p && p->fn)\
+ *					return p->fn(p1);\
+ *				else\
+ *					return -1;\
+ *			} while (0)
+ *
+ *#define IF_HAVE_RUN_RET(p, fn)\
+ *	do {\
+ *		if (p && p->fn)\
+ *			return p->fn();\
+ *		else\
+ *			return 0;\
+ *	} while (0)
+ */
+
+int vdec_clock_init(void)
+{
+	if (p_vdec() && p_vdec()->clock_init)
+		return p_vdec()->clock_init();
+	else
+		return 0;
+}
+EXPORT_SYMBOL(vdec_clock_init);
+
+/*
+ *clk ==0 :
+ *	to be release.
+ *	released shared clk,
+ *clk ==1 :default low clk
+ *clk ==2 :default high clk
+ */
+int vdec_clock_set(int clk)
+{
+	pr_debug("%s-----%d\n", __func__, clk);
+	if (p_vdec() && p_vdec()->clock_set)
+		return p_vdec()->clock_set(clk);
+	else
+		return -1;
+}
+EXPORT_SYMBOL(vdec_clock_set);
+
+void vdec_clock_enable(void)
+{
+	vdec_clock_set(1);
+}
+EXPORT_SYMBOL(vdec_clock_enable);
+
+void vdec_clock_hi_enable(void)
+{
+	vdec_clock_set(2);
+}
+EXPORT_SYMBOL(vdec_clock_hi_enable);
+
+void vdec_clock_on(void)
+{
+	IF_HAVE_RUN(p_vdec(), clock_on);
+}
+EXPORT_SYMBOL(vdec_clock_on);
+
+void vdec_clock_off(void)
+{
+	IF_HAVE_RUN(p_vdec(), clock_off);
+	clock_source_wxhxfps_saved[VDEC_1] = 0;
+}
+EXPORT_SYMBOL(vdec_clock_off);
+
+int vdec2_clock_set(int clk)
+{
+	pr_debug("%s-----%d\n", __func__, clk);
+	if (p_vdec2() && p_vdec2()->clock_set)
+		return p_vdec2()->clock_set(clk);
+	else
+		return -1;
+}
+EXPORT_SYMBOL(vdec2_clock_set);
+
+void vdec2_clock_enable(void)
+{
+	vdec2_clock_set(1);
+}
+EXPORT_SYMBOL(vdec2_clock_enable);
+
+void vdec2_clock_hi_enable(void)
+{
+	vdec2_clock_set(2);
+}
+EXPORT_SYMBOL(vdec2_clock_hi_enable);
+
+void vdec2_clock_on(void)
+{
+	IF_HAVE_RUN(p_vdec2(), clock_on);
+}
+EXPORT_SYMBOL(vdec2_clock_on);
+
+void vdec2_clock_off(void)
+{
+	IF_HAVE_RUN(p_vdec2(), clock_off);
+	clock_source_wxhxfps_saved[VDEC_2] = 0;
+}
+EXPORT_SYMBOL(vdec2_clock_off);
+
+int hcodec_clock_set(int clk)
+{
+	pr_debug("%s-----%d\n", __func__, clk);
+	if (p_vdec_hcodec() && p_vdec_hcodec()->clock_set)
+		return p_vdec_hcodec()->clock_set(clk);
+	else
+		return -1;
+}
+EXPORT_SYMBOL(hcodec_clock_set);
+
+void hcodec_clock_enable(void)
+{
+	hcodec_clock_set(667);
+}
+EXPORT_SYMBOL(hcodec_clock_enable);
+
+void hcodec_clock_hi_enable(void)
+{
+	hcodec_clock_set(2);
+}
+EXPORT_SYMBOL(hcodec_clock_hi_enable);
+
+void hcodec_clock_on(void)
+{
+	IF_HAVE_RUN(p_vdec_hcodec(), clock_on);
+}
+EXPORT_SYMBOL(hcodec_clock_on);
+
+void hcodec_clock_off(void)
+{
+	IF_HAVE_RUN(p_vdec_hcodec(), clock_off);
+	clock_source_wxhxfps_saved[VDEC_HCODEC] = 0;
+}
+EXPORT_SYMBOL(hcodec_clock_off);
+
+int hevc_back_clock_init(void)
+{
+	if (p_vdec_hevc_back() && p_vdec_hevc_back()->clock_init)
+		return p_vdec_hevc_back()->clock_init();
+	else
+		return 0;
+}
+EXPORT_SYMBOL(hevc_back_clock_init);
+
+int hevc_back_clock_set(int clk)
+{
+	pr_debug("%s-----%d\n", __func__, clk);
+	if (p_vdec_hevc_back() && p_vdec_hevc_back()->clock_set)
+		return p_vdec_hevc_back()->clock_set(clk);
+	else
+		return -1;
+}
+EXPORT_SYMBOL(hevc_back_clock_set);
+
+void hevc_back_clock_enable(void)
+{
+	hevc_back_clock_set(1);
+}
+EXPORT_SYMBOL(hevc_back_clock_enable);
+
+void hevc_back_clock_hi_enable(void)
+{
+	hevc_back_clock_set(2);
+}
+EXPORT_SYMBOL(hevc_back_clock_hi_enable);
+
+int hevc_clock_init(void)
+{
+	if (p_vdec_hevc() && p_vdec_hevc()->clock_init)
+		return p_vdec_hevc()->clock_init();
+	else
+		return 0;
+}
+EXPORT_SYMBOL(hevc_clock_init);
+
+int hevc_clock_set(int clk)
+{
+	pr_debug("%s-----%d\n", __func__, clk);
+	if (p_vdec_hevc() && p_vdec_hevc()->clock_set)
+		return p_vdec_hevc()->clock_set(clk);
+	else
+		return -1;
+}
+EXPORT_SYMBOL(hevc_clock_set);
+
+void hevc_clock_enable(void)
+{
+	hevc_clock_set(1);
+}
+EXPORT_SYMBOL(hevc_clock_enable);
+
+void hevc_clock_hi_enable(void)
+{
+	hevc_clock_set(2);
+}
+EXPORT_SYMBOL(hevc_clock_hi_enable);
+
+void hevc_back_clock_on(void)
+{
+	IF_HAVE_RUN(p_vdec_hevc_back(), clock_on);
+}
+EXPORT_SYMBOL(hevc_back_clock_on);
+
+void hevc_back_clock_off(void)
+{
+	IF_HAVE_RUN(p_vdec_hevc_back(), clock_off);
+	clock_source_wxhxfps_saved[VDEC_HEVCB] = 0;
+}
+EXPORT_SYMBOL(hevc_back_clock_off);
+
+void hevc_clock_on(void)
+{
+	IF_HAVE_RUN(p_vdec_hevc(), clock_on);
+}
+EXPORT_SYMBOL(hevc_clock_on);
+
+void hevc_clock_off(void)
+{
+	IF_HAVE_RUN(p_vdec_hevc(), clock_off);
+	clock_source_wxhxfps_saved[VDEC_HEVC] = 0;
+}
+EXPORT_SYMBOL(hevc_clock_off);
+
+int vdec_source_get(enum vdec_type_e core)
+{
+	return clock_source_wxhxfps_saved[core];
+}
+EXPORT_SYMBOL(vdec_source_get);
+
+int vdec_clk_get(enum vdec_type_e core)
+{
+	return get_current_vdec_chip()->clk_mgr[core]->clock_get(core);
+}
+EXPORT_SYMBOL(vdec_clk_get);
+
+int get_clk_with_source(int format, int w_x_h_fps)
+{
+	struct clk_set_setting *p_setting;
+	int i;
+	int clk = -2;
+
+	p_setting = get_current_vdec_chip()->clk_setting_array;
+	if (!p_setting || format < 0 || format > VFORMAT_MAX) {
+		pr_info("error on get_clk_with_source ,%p,%d\n",
+			p_setting, format);
+		return -1;	/*no setting found. */
+	}
+	p_setting = &p_setting[format];
+	for (i = 0; i < MAX_CLK_SET; i++) {
+		if (p_setting->set[i].wh_X_fps > w_x_h_fps) {
+			clk = p_setting->set[i].clk_Mhz;
+			break;
+		}
+	}
+	return clk;
+}
+EXPORT_SYMBOL(get_clk_with_source);
+
+bool is_hevc_front_back_clk_combined(void)
+{
+	int cpu_id = get_cpu_major_id();
+
+	if (cpu_id == AM_MESON_CPU_MAJOR_ID_T5 ||
+		(cpu_id == AM_MESON_CPU_MAJOR_ID_T5D) ||
+		(cpu_id == AM_MESON_CPU_MAJOR_ID_S4) ||
+		(cpu_id == AM_MESON_CPU_MAJOR_ID_S4D) ||
+		(cpu_id == AM_MESON_CPU_MAJOR_ID_T5W))
+		return true;
+
+	return false;
+}
+EXPORT_SYMBOL(is_hevc_front_back_clk_combined);
+
+int vdec_source_changed_for_clk_set(int format, int width, int height, int fps)
+{
+	int clk = get_clk_with_source(format, width * height * fps);
+	int ret_clk;
+
+	if (clk < 0) {
+		pr_info("can't get valid clk for source ,%d,%d,%d\n",
+			width, height, fps);
+		if (format >= 1920 && width >= 1080 && fps >= 30)
+			clk = 2;	/*default high clk */
+		else
+			clk = 0;	/*default clk. */
+	}
+	if (width * height * fps == 0)
+		clk = 0;
+	/*
+	 *clk == 0
+	 *is used for set default clk;
+	 *if used supper clk.
+	 *changed to default  min clk.
+	 */
+
+	if (format == VFORMAT_HEVC || format == VFORMAT_VP9
+		|| format == VFORMAT_AVS2
+		|| format == VFORMAT_AV1) {
+		ret_clk = hevc_clock_set(clk);
+		clock_source_wxhxfps_saved[VDEC_HEVC] = width * height * fps;
+		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A &&
+			!is_hevc_front_back_clk_combined()) {
+			ret_clk = hevc_back_clock_set(clk);
+			clock_source_wxhxfps_saved[VDEC_HEVCB] = width * height * fps;
+		}
+	} else if (format == VFORMAT_H264_ENC || format == VFORMAT_JPEG_ENC) {
+		ret_clk = hcodec_clock_set(clk);
+		clock_source_wxhxfps_saved[VDEC_HCODEC] = width * height * fps;
+	} else if (format == VFORMAT_H264_4K2K &&
+		get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_M8) {
+		ret_clk = vdec2_clock_set(clk);
+		clock_source_wxhxfps_saved[VDEC_2] = width * height * fps;
+		ret_clk = vdec_clock_set(clk);
+		clock_source_wxhxfps_saved[VDEC_1] = width * height * fps;
+	} else {
+		ret_clk = vdec_clock_set(clk);
+		clock_source_wxhxfps_saved[VDEC_1] = width * height * fps;
+	}
+	return ret_clk;
+}
+EXPORT_SYMBOL(vdec_source_changed_for_clk_set);
+
+static int register_vdec_clk_mgr_per_cpu(int cputype,
+	enum vdec_type_e vdec_type, struct chip_vdec_clk_s *t_mgr)
+{
+
+	struct chip_vdec_clk_s *mgr;
+
+	if (cputype != get_cpu_major_id() || vdec_type >= VDEC_MAX) {
+		/*
+		 *pr_info("ignore vdec clk mgr for vdec[%d] cpu=%d\n",
+		 *vdec_type, cputype);
+		 */
+		return 0;	/* ignore don't needed firmare. */
+	}
+	mgr = kmalloc(sizeof(struct chip_vdec_clk_s), GFP_KERNEL);
+	if (!mgr)
+		return -ENOMEM;
+	*mgr = *t_mgr;
+	/*
+	 *pr_info("register vdec clk mgr for vdec[%d]\n", vdec_type);
+	 */
+	if (mgr->clock_init) {
+		if (mgr->clock_init()) {
+			kfree(mgr);
+			return -ENOMEM;
+		}
+	}
+	get_current_vdec_chip()->clk_mgr[vdec_type] = mgr;
+	return 0;
+}
+
+int register_vdec_clk_mgr(int cputype[], enum vdec_type_e vdec_type,
+	struct chip_vdec_clk_s *t_mgr)
+{
+	int i = 0;
+
+	while (cputype[i] > 0) {
+		register_vdec_clk_mgr_per_cpu(cputype[i], vdec_type, t_mgr);
+		i++;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(register_vdec_clk_mgr);
+
+int unregister_vdec_clk_mgr(enum vdec_type_e vdec_type)
+{
+	kfree(get_current_vdec_chip()->clk_mgr[vdec_type]);
+
+	return 0;
+}
+EXPORT_SYMBOL(unregister_vdec_clk_mgr);
+
+static int register_vdec_clk_setting_per_cpu(int cputype,
+	struct clk_set_setting *setting, int size)
+{
+
+	struct clk_set_setting *p_setting;
+
+	if (cputype != get_cpu_major_id()) {
+		/*
+		 *pr_info("ignore clk_set_setting for cpu=%d\n",
+		 *cputype);
+		 */
+		return 0;	/* ignore don't needed this setting . */
+	}
+	p_setting = kmalloc(size, GFP_KERNEL);
+	if (!p_setting)
+		return -ENOMEM;
+	memcpy(p_setting, setting, size);
+
+	pr_info("register clk_set_setting cpu[%d]\n", cputype);
+
+	get_current_vdec_chip()->clk_setting_array = p_setting;
+	return 0;
+}
+
+int register_vdec_clk_setting(int cputype[],
+	struct clk_set_setting *p_seting, int size)
+{
+	int i = 0;
+
+	while (cputype[i] > 0) {
+		register_vdec_clk_setting_per_cpu(cputype[i], p_seting, size);
+		i++;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(register_vdec_clk_setting);
+
+int unregister_vdec_clk_setting(void)
+{
+	kfree(get_current_vdec_chip()->clk_setting_array);
+
+	return 0;
+}
+EXPORT_SYMBOL(unregister_vdec_clk_setting);
+
diff --git a/drivers/common/media_clock/clk/clk.h b/drivers/common/media_clock/clk/clk.h
new file mode 100644
index 0000000..bbc3bee
--- /dev/null
+++ b/drivers/common/media_clock/clk/clk.h
@@ -0,0 +1,177 @@
+/*
+ * drivers/amlogic/media/common/arch/clk/clk.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef VDEC_CHIP_CLK_HEADER
+#define VDEC_CHIP_CLK_HEADER
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include "clk_priv.h"
+#include <linux/amlogic/media/clk/gp_pll.h>
+
+#ifndef INCLUDE_FROM_ARCH_CLK_MGR
+int vdec_clock_init(void);
+int vdec_clock_set(int clk);
+int vdec2_clock_set(int clk);
+
+int hcodec_clock_set(int clk);
+int hevc_clock_init(void);
+int hevc_clock_set(int clk);
+
+void vdec_clock_on(void);
+void vdec_clock_off(void);
+void vdec2_clock_on(void);
+
+void vdec2_clock_off(void);
+void hcodec_clock_on(void);
+void hcodec_clock_off(void);
+void hevc_clock_on(void);
+void hevc_clock_off(void);
+
+int hevc_back_clock_init(void);
+void hevc_back_clock_on(void);
+void hevc_back_clock_off(void);
+int hevc_back_clock_set(int clk);
+void hevc_back_clock_enable(void);
+void hevc_back_clock_hi_enable(void);
+
+int vdec_source_get(enum vdec_type_e core);
+int vdec_clk_get(enum vdec_type_e core);
+
+bool is_hevc_front_back_clk_combined(void);
+
+int vdec_source_changed_for_clk_set(int format, int width, int height, int fps);
+int get_clk_with_source(int format, int w_x_h_fps);
+
+void vdec_clock_enable(void);
+void vdec_clock_hi_enable(void);
+void hcodec_clock_enable(void);
+void hcodec_clock_hi_enable(void);
+void hevc_clock_enable(void);
+void hevc_clock_hi_enable(void);
+void vdec2_clock_enable(void);
+void vdec2_clock_hi_enable(void);
+void set_clock_gate(struct gate_switch_node *nodes, int num);
+
+#endif
+int register_vdec_clk_mgr(int cputype[],
+	enum vdec_type_e vdec_type, struct chip_vdec_clk_s *t_mgr);
+
+int unregister_vdec_clk_mgr(enum vdec_type_e vdec_type);
+
+int register_vdec_clk_setting(int cputype[],
+	struct clk_set_setting *p_seting, int size);
+
+int unregister_vdec_clk_setting(void);
+
+#ifdef INCLUDE_FROM_ARCH_CLK_MGR
+static struct chip_vdec_clk_s vdec_clk_mgr __initdata = {
+	.clock_init = vdec_clock_init,
+	.clock_set = vdec_clock_set,
+	.clock_on = vdec_clock_on,
+	.clock_off = vdec_clock_off,
+	.clock_get = vdec_clock_get,
+};
+
+#ifdef VDEC_HAS_VDEC2
+static struct chip_vdec_clk_s vdec2_clk_mgr __initdata = {
+	.clock_set = vdec2_clock_set,
+	.clock_on = vdec2_clock_on,
+	.clock_off = vdec2_clock_off,
+	.clock_get = vdec_clock_get,
+};
+#endif
+
+#ifdef VDEC_HAS_HEVC
+static struct chip_vdec_clk_s vdec_hevc_clk_mgr __initdata = {
+	.clock_init = hevc_clock_init,
+	.clock_set = hevc_clock_set,
+	.clock_on = hevc_clock_on,
+	.clock_off = hevc_clock_off,
+	.clock_get = vdec_clock_get,
+};
+static struct chip_vdec_clk_s vdec_hevc_back_clk_mgr __initdata = {
+        .clock_init = hevc_back_clock_init,
+        .clock_set = hevc_back_clock_set,
+        .clock_on = hevc_back_clock_on,
+        .clock_off = hevc_back_clock_off,
+        .clock_get = vdec_clock_get,
+};
+#endif
+
+#ifdef VDEC_HAS_VDEC_HCODEC
+static struct chip_vdec_clk_s vdec_hcodec_clk_mgr __initdata = {
+	.clock_set = hcodec_clock_set,
+	.clock_on = hcodec_clock_on,
+	.clock_off = hcodec_clock_off,
+	.clock_get = vdec_clock_get,
+};
+#endif
+
+static int __init vdec_init_clk(void)
+{
+	int cpus[] = CLK_FOR_CPU;
+
+	register_vdec_clk_mgr(cpus, VDEC_1, &vdec_clk_mgr);
+#ifdef VDEC_HAS_VDEC2
+	register_vdec_clk_mgr(cpus, VDEC_2, &vdec2_clk_mgr);
+#endif
+#ifdef VDEC_HAS_HEVC
+	register_vdec_clk_mgr(cpus, VDEC_HEVC, &vdec_hevc_clk_mgr);
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
+		register_vdec_clk_mgr(cpus, VDEC_HEVCB, &vdec_hevc_back_clk_mgr);
+#endif
+#ifdef VDEC_HAS_VDEC_HCODEC
+	register_vdec_clk_mgr(cpus, VDEC_HCODEC, &vdec_hcodec_clk_mgr);
+#endif
+
+#ifdef VDEC_HAS_CLK_SETTINGS
+	register_vdec_clk_setting(cpus,
+		clks_for_formats, sizeof(clks_for_formats));
+#endif
+	return 0;
+}
+
+static void __exit vdec_clk_exit(void)
+{
+		unregister_vdec_clk_mgr(VDEC_1);
+#ifdef VDEC_HAS_VDEC2
+		unregister_vdec_clk_mgr(VDEC_2);
+#endif
+#ifdef VDEC_HAS_HEVC
+		unregister_vdec_clk_mgr(VDEC_HEVC);
+#endif
+#ifdef VDEC_HAS_VDEC_HCODEC
+		unregister_vdec_clk_mgr(VDEC_HCODEC);
+#endif
+#ifdef VDEC_HAS_CLK_SETTINGS
+		unregister_vdec_clk_setting();
+#endif
+		pr_info("media clock exit.\n");
+}
+
+#define ARCH_VDEC_CLK_INIT()\
+		module_init(vdec_init_clk)
+
+#define ARCH_VDEC_CLK_EXIT()\
+		module_exit(vdec_clk_exit)
+
+MODULE_DESCRIPTION("AMLOGIC clk Driver");
+MODULE_LICENSE("GPL");
+
+#endif
+#endif
diff --git a/drivers/common/media_clock/clk/clk_priv.h b/drivers/common/media_clock/clk/clk_priv.h
new file mode 100644
index 0000000..60b7be0
--- /dev/null
+++ b/drivers/common/media_clock/clk/clk_priv.h
@@ -0,0 +1,38 @@
+/*
+ * drivers/amlogic/media/common/arch/clk/clk_priv.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef AMPORTS_CLK_PRIV_HEADER
+#define AMPORTS_CLK_PRIV_HEADER
+
+struct clk_set {
+	u32 wh_X_fps;		/* [x*y*fps */
+	u32 clk_Mhz;		/*min MHZ */
+};
+#define MAX_CLK_SET 6
+struct clk_set_setting {
+	struct clk_set set[MAX_CLK_SET];
+};
+
+struct chip_vdec_clk_s {
+	int (*clock_get)(enum vdec_type_e core);
+	int (*clock_init)(void);
+	int (*clock_set)(int clk);
+	void (*clock_on)(void);
+	void (*clock_off)(void);
+	void (*clock_prepare_switch)(void);
+};
+#endif
diff --git a/drivers/common/media_clock/clk/clkg12.c b/drivers/common/media_clock/clk/clkg12.c
new file mode 100644
index 0000000..c49d150
--- /dev/null
+++ b/drivers/common/media_clock/clk/clkg12.c
@@ -0,0 +1,1071 @@
+/*
+ * drivers/amlogic/media/common/arch/clk/clkgx.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+#define DEBUG
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/amlogic/media/clk/gp_pll.h>
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include <linux/amlogic/media/utils/amports_config.h>
+#include "../../../frame_provider/decoder/utils/vdec.h"
+#include <linux/amlogic/media/registers/register.h>
+#include "clk_priv.h"
+#include <linux/amlogic/media/utils/log.h>
+
+#include <linux/amlogic/media/registers/register_ops.h>
+#include "../switch/amports_gate.h"
+#include "../../chips/decoder_cpu_ver_info.h"
+
+#define MHz (1000000)
+#define debug_print pr_info
+#define TL1_HEVC_MAX_CLK  (800)
+
+//#define  NO_CLKTREE
+
+/* set gp0 648M vdec use gp0 clk*/
+#define VDEC1_648M() \
+	WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL,  (6 << 9) | (0), 0, 16)
+
+#define HEVC_648M() \
+	WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (0), 16, 16)
+
+/*set gp0 1296M vdec use gp0 clk div2*/
+#define VDEC1_648M_DIV() \
+	WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL,  (6 << 9) | (1), 0, 16)
+
+#define HEVC_648M_DIV() \
+	WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (1), 16, 16)
+
+#define VDEC1_WITH_GP_PLL() \
+	((READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0xe00) == 0xc00)
+#define HEVC_WITH_GP_PLL() \
+	((READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0xe000000) == 0xc000000)
+
+#define VDEC1_CLOCK_ON()  \
+	do { if (is_meson_m8_cpu()) { \
+		WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \
+		WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \
+		} else { \
+		WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \
+		WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 15, 1); \
+		WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 8, 1); \
+		WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \
+		} \
+	} while (0)
+
+#define VDEC2_CLOCK_ON()   do {\
+		WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 8, 1); \
+		WRITE_VREG(DOS_GCLK_EN1, 0x3ff);\
+	} while (0)
+
+#define HCODEC_CLOCK_ON()  do {\
+		WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 24, 1); \
+		WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15);\
+	} while (0)
+#define HEVC_CLOCK_ON()    do {\
+		WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 24, 1); \
+		WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 8, 1); \
+		WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 31, 1); \
+		WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 15, 1); \
+		WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 24, 1); \
+		WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);\
+	} while (0)
+#define VDEC1_SAFE_CLOCK() do {\
+	WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, \
+		READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x7f, 0, 7); \
+	WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 8, 1); \
+	WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 15, 1);\
+	} while (0)
+
+#define VDEC1_CLOCK_OFF()  \
+	WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL,  0, 8, 1)
+#define VDEC2_CLOCK_OFF()  \
+	WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 8, 1)
+#define HCODEC_CLOCK_OFF() \
+	WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 24, 1)
+#define HEVC_SAFE_CLOCK()  do { \
+	WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \
+		(READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 16) & 0x7f, 16, 7);\
+	WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \
+		(READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 25) & 0x7f, 25, 7);\
+	WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 24, 1); \
+	WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 31, 1);\
+	WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 15, 1);\
+	} while (0)
+
+#define HEVC_CLOCK_OFF()  do {\
+	WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 24, 1);\
+	WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 8, 1);\
+}while(0)
+
+static int clock_real_clk[VDEC_MAX + 1];
+
+static unsigned int set_frq_enable, vdec_frq, hevc_frq, hevcb_frq;
+
+#ifdef NO_CLKTREE
+static struct gp_pll_user_handle_s *gp_pll_user_vdec, *gp_pll_user_hevc;
+static bool is_gp0_div2 = true;
+
+static int gp_pll_user_cb_vdec(struct gp_pll_user_handle_s *user,
+			int event)
+{
+	debug_print("gp_pll_user_cb_vdec call\n");
+	if (event == GP_PLL_USER_EVENT_GRANT) {
+		struct clk *clk = clk_get(NULL, "gp0_pll");
+		if (!IS_ERR(clk)) {
+			if (is_gp0_div2)
+				clk_set_rate(clk, 1296000000UL);
+			else
+				clk_set_rate(clk, 648000000UL);
+			VDEC1_SAFE_CLOCK();
+			VDEC1_CLOCK_OFF();
+			if (is_gp0_div2)
+				VDEC1_648M_DIV();
+			else
+				VDEC1_648M();
+
+			VDEC1_CLOCK_ON();
+			debug_print("gp_pll_user_cb_vdec call set\n");
+		}
+	}
+	return 0;
+}
+
+static int gp_pll_user_cb_hevc(struct gp_pll_user_handle_s *user,
+			int event)
+{
+	debug_print("gp_pll_user_cb_hevc callback\n");
+	if (event == GP_PLL_USER_EVENT_GRANT) {
+		struct clk *clk = clk_get(NULL, "gp0_pll");
+		if (!IS_ERR(clk)) {
+			if (is_gp0_div2)
+				clk_set_rate(clk, 1296000000UL);
+			else
+				clk_set_rate(clk, 648000000UL);
+//			HEVC_SAFE_CLOCK();
+			HEVC_CLOCK_OFF();
+			if (is_gp0_div2)
+				HEVC_648M_DIV();
+			else
+				HEVC_648M();
+			HEVC_CLOCK_ON();
+			debug_print("gp_pll_user_cb_hevc callback2\n");
+		}
+	}
+
+	return 0;
+}
+
+
+#endif
+
+struct clk_mux_s {
+	struct gate_switch_node *vdec_mux_node;
+	struct gate_switch_node *hcodec_mux_node;
+	struct gate_switch_node *hevc_mux_node;
+	struct gate_switch_node *hevc_back_mux_node;
+};
+
+struct clk_mux_s gclk;
+
+void vdec1_set_clk(int source, int div)
+{
+	pr_debug("vdec1_set_clk %d, %d\n", source, div);
+	WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (source << 9) | (div - 1), 0, 16);
+}
+EXPORT_SYMBOL(vdec1_set_clk);
+
+void hcodec_set_clk(int source, int div)
+{
+	WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL,
+		(source << 9) | (div - 1), 16, 16);
+}
+EXPORT_SYMBOL(hcodec_set_clk);
+
+void vdec2_set_clk(int source, int div)
+{
+	WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL,
+		(source << 9) | (div - 1), 0, 16);
+}
+EXPORT_SYMBOL(vdec2_set_clk);
+
+//extern uint force_hevc_clock_cntl;
+uint force_hevc_clock_cntl = 0;
+void hevc_set_clk(int source, int div)
+{
+	if (force_hevc_clock_cntl) {
+		pr_info("%s, write force clock cntl %x\n", __func__, force_hevc_clock_cntl);
+		WRITE_HHI_REG(HHI_VDEC2_CLK_CNTL, force_hevc_clock_cntl);
+	} else {
+		pr_debug("hevc_set_clk %d, %d\n", source, div);
+		WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL,
+			(source << 9) | (div - 1), 16, 16);
+		WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (source << 9) | (div - 1), 0, 16);
+	}
+}
+EXPORT_SYMBOL(hevc_set_clk);
+
+void vdec_get_clk_source(int clk, int *source, int *div, int *rclk)
+{
+#define source_div4 (0)
+#define source_div3 (1)
+#define source_div5 (2)
+#define source_div7 (3)
+	if (clk > 500) {
+		*source = source_div3;
+		*div = 1;
+		*rclk = 667;
+	} else if (clk >= 500) {
+		*source = source_div4;
+		*div = 1;
+		*rclk = 500;
+	} else if (clk >= 400) {
+		*source = source_div5;
+		*div = 1;
+		*rclk = 400;
+	} else if (clk >= 333) {
+		*source = source_div3;
+		*div = 2;
+		*rclk = 333;
+	} else if (clk >= 200) {
+		*source = source_div5;
+		*div = 2;
+		*rclk = 200;
+	} else if (clk >= 166) {
+		*source = source_div4;
+		*div = 3;
+		*rclk = 166;
+	} else if (clk >= 133) {
+		*source = source_div5;
+		*div = 3;
+		*rclk = 133;
+	} else if (clk >= 100) {
+		*source = source_div5;
+		*div = 4;
+		*rclk = 100;
+	} else if (clk >= 50) {
+		*source = source_div5;
+		*div = 8;
+		*rclk = 50;
+	} else {
+		*source = source_div5;
+		*div = 20;
+		*rclk = 10;
+	}
+}
+EXPORT_SYMBOL(vdec_get_clk_source);
+
+
+/*
+ *enum vformat_e {
+ *	VFORMAT_MPEG12 = 0,
+ *	VFORMAT_MPEG4,
+ *	VFORMAT_H264,
+ *	VFORMAT_MJPEG,
+ *	VFORMAT_REAL,
+ *	VFORMAT_JPEG,
+ *	VFORMAT_VC1,
+ *	VFORMAT_AVS,
+ *	VFORMAT_YUV,
+ *	VFORMAT_H264MVC,
+ *	VFORMAT_H264_4K2K,
+ *	VFORMAT_HEVC,
+ *	VFORMAT_H264_ENC,
+ *	VFORMAT_JPEG_ENC,
+ *	VFORMAT_VP9,
+ *	VFORMAT_MAX
+ *};
+ *sample:
+ *{{1280*720*30, 100}, {1920*1080*30, 166}, {1920*1080*60, 333},
+ *	{4096*2048*30, 600}, {4096*2048*60, 600}, {INT_MAX, 600},}
+ *mean:
+ *width * height * fps
+ *<720p30fps						clk=100MHZ
+ *>=720p30fps & < 1080p30fps		clk=166MHZ
+ *>=1080p 30fps & < 1080p60fps	clk=333MHZ
+ */
+static struct clk_set_setting clks_for_formats[] = {
+	{			/*[VFORMAT_MPEG12] */
+			{{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
+				{1920 * 1080 * 60, 333},
+				{4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+						600}, {INT_MAX, 600},
+				}
+		},
+	{			/*[VFORMAT_MPEG4] */
+			{{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
+				{1920 * 1080 * 60, 333},
+				{4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+						600}, {INT_MAX, 600},
+				}
+		},
+	{			/*[VFORMAT_H264] */
+			{{1280 * 720 * 30, 100}, {1920 * 1080 * 21, 166},
+				{1920 * 1080 * 30, 333},
+				{1920 * 1080 * 60, 600}, {4096 * 2048 * 60,
+						600}, {INT_MAX, 600},
+				}
+		},
+	{			/*[VFORMAT_MJPEG] */
+			{{1280 * 720 * 30, 200}, {1920 * 1080 * 30, 200},
+				{1920 * 1080 * 60, 333},
+				{4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+						600}, {INT_MAX, 600},
+				}
+		},
+	{			/*[VFORMAT_REAL] */
+			{{1280 * 720 * 20, 200}, {1920 * 1080 * 30, 500},
+				{1920 * 1080 * 60, 500},
+				{4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+						600}, {INT_MAX, 600},
+				}
+		},
+	{			/*[VFORMAT_JPEG] */
+			{{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
+				{1920 * 1080 * 60, 333},
+				{4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+						600}, {INT_MAX, 600},
+				}
+		},
+	{			/*[VFORMAT_VC1] */
+			{{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
+				{1920 * 1080 * 60, 333},
+				{4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+						600}, {INT_MAX, 600},
+				}
+		},
+	{			/*[VFORMAT_AVS] */
+			{{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
+				{1920 * 1080 * 60, 333},
+				{4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+						600}, {INT_MAX, 600},
+				}
+		},
+	{			/*[VFORMAT_YUV] */
+			{{1280 * 720 * 30, 100}, {INT_MAX, 100},
+				{0, 0}, {0, 0}, {0, 0}, {0, 0},
+				}
+		},
+	{			/*VFORMAT_H264MVC */
+			{{1280 * 720 * 30, 333}, {1920 * 1080 * 30, 333},
+				{4096 * 2048 * 60, 600},
+				{INT_MAX, 630}, {0, 0}, {0, 0},
+				}
+		},
+	{			/*VFORMAT_H264_4K2K */
+			{{1280 * 720 * 30, 600}, {4096 * 2048 * 60, 630},
+				{INT_MAX, 630},
+				{0, 0}, {0, 0}, {0, 0},
+				}
+		},
+	{			/*VFORMAT_HEVC */
+			{{1280 * 720 * 30, 100}, {1920 * 1080 * 60, 600},
+				{4096 * 2048 * 25, 630},
+				{4096 * 2048 * 30, 630}, {4096 * 2048 * 60,
+						630}, {INT_MAX, 630},
+				}
+		},
+	{			/*VFORMAT_H264_ENC */
+			{{1280 * 720 * 30, 0}, {INT_MAX, 0},
+				{0, 0}, {0, 0}, {0, 0}, {0, 0},
+				}
+		},
+	{			/*VFORMAT_JPEG_ENC */
+			{{1280 * 720 * 30, 0}, {INT_MAX, 0},
+				{0, 0}, {0, 0}, {0, 0}, {0, 0},
+				}
+		},
+	{			/*VFORMAT_VP9 */
+			{{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 100},
+				{1920 * 1080 * 60, 166},
+				{4096 * 2048 * 30, 333}, {4096 * 2048 * 60,
+						630}, {INT_MAX, 630},
+				}
+		},
+	{/*VFORMAT_AVS2*/
+		{{1280*720*30, 100}, {1920*1080*30, 100},
+		{1920*1080*60, 166}, {4096*2048*30, 333},
+		{4096*2048*60, 630}, {INT_MAX, 630},}
+	},
+	{/*VFORMAT_AV1*/
+		{{1280*720*30, 100}, {1920*1080*30, 100},
+		{1920*1080*60, 166}, {4096*2048*30, 333},
+		{4096*2048*60, 630}, {INT_MAX, 630},}
+	},
+
+};
+
+void set_clock_gate(struct gate_switch_node *nodes, int num)
+{
+	struct gate_switch_node *node = NULL;
+	char *hevc_mux_str = NULL;
+
+	if ((get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SC2) ||
+		(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5) ||
+		(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5D))
+		hevc_mux_str = "clk_hevc_mux";
+	else
+		hevc_mux_str = "clk_hevcf_mux";
+
+	do {
+		node = &nodes[num - 1];
+		if (IS_ERR_OR_NULL(node) || (IS_ERR_OR_NULL(node->clk)))
+			pr_info("get mux clk err.\n");
+
+		if (!strcmp(node->name, "clk_vdec_mux"))
+			gclk.vdec_mux_node = node;
+		else if (!strcmp(node->name, "clk_hcodec_mux"))
+			gclk.hcodec_mux_node = node;
+		else if (!strcmp(node->name, hevc_mux_str))
+				gclk.hevc_mux_node = node;
+		else if (!strcmp(node->name, "clk_hevcb_mux"))
+			gclk.hevc_back_mux_node = node;
+	} while(--num);
+}
+EXPORT_SYMBOL(set_clock_gate);
+#ifdef NO_CLKTREE
+int vdec_set_clk(int dec, int source, int div)
+{
+
+	if (dec == VDEC_1)
+		vdec1_set_clk(source, div);
+	else if (dec == VDEC_2)
+		vdec2_set_clk(source, div);
+	else if (dec == VDEC_HEVC)
+		hevc_set_clk(source, div);
+	else if (dec == VDEC_HCODEC)
+		hcodec_set_clk(source, div);
+	return 0;
+}
+
+#else
+static int vdec_set_clk(int dec, int rate)
+{
+	struct clk *clk = NULL;
+
+	switch (dec) {
+	case VDEC_1:
+		clk = gclk.vdec_mux_node->clk;
+		WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10);
+		break;
+
+	case VDEC_HCODEC:
+		clk = gclk.hcodec_mux_node->clk;
+		WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15);
+		break;
+
+	case VDEC_2:
+		clk = gclk.vdec_mux_node->clk;
+		WRITE_VREG(DOS_GCLK_EN1, 0x3ff);
+		break;
+
+	case VDEC_HEVC:
+		clk = gclk.hevc_mux_node->clk;
+		WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);
+		break;
+
+	case VDEC_HEVCB:
+		clk = gclk.hevc_back_mux_node->clk;
+		WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);
+		break;
+
+	case VDEC_MAX:
+		break;
+
+	default:
+		pr_info("invaild vdec type.\n");
+	}
+
+	if (IS_ERR_OR_NULL(clk)) {
+		pr_info("the mux clk err.\n");
+		return -1;
+	}
+
+	clk_set_rate(clk, rate);
+
+	return 0;
+}
+
+static int vdec_clock_init(void)
+{
+	return 0;
+}
+
+#endif
+#ifdef NO_CLKTREE
+static int vdec_clock_init(void)
+{
+	gp_pll_user_vdec = gp_pll_user_register("vdec", 0,
+		gp_pll_user_cb_vdec);
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL)
+		is_gp0_div2 = false;
+	else
+		is_gp0_div2 = true;
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) {
+		pr_info("used fix clk for vdec clk source!\n");
+		//update_vdec_clk_config_settings(1);
+	}
+	return (gp_pll_user_vdec) ? 0 : -ENOMEM;
+}
+
+
+
+static void update_clk_with_clk_configs(
+	int clk, int *source, int *div, int *rclk)
+{
+	unsigned int config = 0;//get_vdec_clk_config_settings();
+
+	if (!config)
+		return;
+	if (config >= 10) {
+		int wantclk;
+		wantclk = config;
+		vdec_get_clk_source(wantclk, source, div, rclk);
+	}
+	return;
+}
+#define NO_GP0_PLL 0//(get_vdec_clk_config_settings() == 1)
+#define ALWAYS_GP0_PLL 0//(get_vdec_clk_config_settings() == 2)
+
+#define NO_GP0_PLL 0//(get_vdec_clk_config_settings() == 1)
+#define ALWAYS_GP0_PLL 0//(get_vdec_clk_config_settings() == 2)
+
+static int vdec_clock_set(int clk)
+{
+	int use_gpll = 0;
+	int source, div, rclk;
+	int clk_seted = 0;
+	int gp_pll_wait = 0;
+	if (clk == 1)
+		clk = 200;
+	else if (clk == 2) {
+		if (clock_real_clk[VDEC_1] != 648)
+			clk = 500;
+		else
+			clk = 648;
+	} else if (clk == 0) {
+		/*used for release gp pull.
+		   if used, release it.
+		   if not used gp pll
+		   do nothing.
+		 */
+		if (clock_real_clk[VDEC_1] == 667 ||
+		    (clock_real_clk[VDEC_1] == 648) ||
+			clock_real_clk[VDEC_1] <= 0)
+			clk = 200;
+		else
+			clk = clock_real_clk[VDEC_1];
+	}
+	vdec_get_clk_source(clk, &source, &div, &rclk);
+	update_clk_with_clk_configs(clk, &source, &div, &rclk);
+
+	if (clock_real_clk[VDEC_1] == rclk)
+		return rclk;
+	if (NO_GP0_PLL) {
+		use_gpll = 0;
+		clk_seted = 0;
+	} else if ((rclk > 500 && clk != 667) || ALWAYS_GP0_PLL) {
+		if (clock_real_clk[VDEC_1] == 648)
+			return 648;
+		use_gpll = 1;
+		gp_pll_request(gp_pll_user_vdec);
+		while (!VDEC1_WITH_GP_PLL() && gp_pll_wait++ < 1000000)
+			udelay(1);
+		if (VDEC1_WITH_GP_PLL()) {
+			clk_seted = 1;
+			rclk = 648;
+		} else {
+			use_gpll = 0;
+			rclk = 667;
+			/*gp_pull request failed,used default 500Mhz*/
+			pr_info("get gp pll failed used fix pull\n");
+		}
+	}
+	if (!clk_seted) {/*if 648 not set,*/
+		VDEC1_SAFE_CLOCK();
+		VDEC1_CLOCK_OFF();
+		vdec_set_clk(VDEC_1, source, div);
+		VDEC1_CLOCK_ON();
+	}
+
+	if (!use_gpll)
+		gp_pll_release(gp_pll_user_vdec);
+	clock_real_clk[VDEC_1] = rclk;
+	debug_print("vdec_clock_set 2 to %d\n", rclk);
+	return rclk;
+}
+static int hevc_clock_init(void)
+{
+	gp_pll_user_hevc = gp_pll_user_register("hevc", 0,
+		gp_pll_user_cb_hevc);
+
+	return (gp_pll_user_hevc) ? 0 : -ENOMEM;
+}
+static int hevc_back_clock_init(void)
+{
+	return 0;
+}
+
+static int hevc_back_clock_set(int clk)
+{
+	return 0;
+}
+
+static int hevc_clock_set(int clk)
+{
+	int use_gpll = 0;
+	int source, div, rclk;
+	int gp_pll_wait = 0;
+	int clk_seted = 0;
+
+	debug_print("hevc_clock_set 1 to clk %d\n", clk);
+	if (clk == 1)
+		clk = 200;
+	else if (clk == 2) {
+		if (clock_real_clk[VDEC_HEVC] != 648)
+			clk = 500;
+		else
+			clk = 648;
+	} else if (clk == 0) {
+		/*used for release gp pull.
+		   if used, release it.
+		   if not used gp pll
+		   do nothing.
+		 */
+		if ((clock_real_clk[VDEC_HEVC] == 667) ||
+			(clock_real_clk[VDEC_HEVC] == 648) ||
+			(clock_real_clk[VDEC_HEVC] <= 0))
+			clk = 200;
+		else
+			clk = clock_real_clk[VDEC_HEVC];
+	}
+	vdec_get_clk_source(clk, &source, &div, &rclk);
+	update_clk_with_clk_configs(clk, &source, &div, &rclk);
+
+	if (rclk == clock_real_clk[VDEC_HEVC])
+		return rclk;/*clk not changed,*/
+	if (NO_GP0_PLL) {
+		use_gpll = 0;
+		clk_seted = 0;
+	} else if ((rclk > 500 && clk != 667) || ALWAYS_GP0_PLL) {
+		if (clock_real_clk[VDEC_HEVC] == 648)
+			return 648;
+		use_gpll = 1;
+		gp_pll_request(gp_pll_user_hevc);
+		while (!HEVC_WITH_GP_PLL() && gp_pll_wait++ < 1000000)
+			udelay(1);
+		if (HEVC_WITH_GP_PLL()) {
+			clk_seted = 1;
+			rclk = 648;
+		} else {
+			rclk = 667;
+			/*gp_pull request failed,used default 500Mhz*/
+			pr_info("get gp pll failed used fix pull\n");
+		}
+	}
+	if (!clk_seted) {/*if 648 not set,*/
+//		HEVC_SAFE_CLOCK();
+		HEVC_CLOCK_OFF();
+		vdec_set_clk(VDEC_HEVC, source, div);
+		HEVC_CLOCK_ON();
+	}
+	if (!use_gpll)
+		gp_pll_release(gp_pll_user_hevc);
+	clock_real_clk[VDEC_HEVC] = rclk;
+	/*debug_print("hevc_clock_set 2 to rclk=%d, configs=%d\n",
+		rclk,
+		get_vdec_clk_config_settings());*/ //DEBUG_TMP
+	return rclk;
+}
+
+static int hcodec_clock_set(int clk)
+{
+	int source, div, rclk;
+	HCODEC_CLOCK_OFF();
+	vdec_get_clk_source(200, &source, &div, &rclk);
+	vdec_set_clk(VDEC_HCODEC, source, div);
+	HCODEC_CLOCK_ON();
+	clock_real_clk[VDEC_HCODEC] = rclk;
+	return rclk;
+}
+
+
+#else
+static int vdec_clock_set(int clk)
+{
+	if (clk == 1)
+		clk = 200;
+	else if (clk == 2) {
+		if (clock_real_clk[VDEC_1] != 648)
+			clk = 500;
+		else
+			clk = 648;
+	} else if (clk == 0) {
+		if (clock_real_clk[VDEC_1] == 667 ||
+			(clock_real_clk[VDEC_1] == 648) ||
+			clock_real_clk[VDEC_1] <= 0)
+			clk = 200;
+		else
+			clk = clock_real_clk[VDEC_1];
+	}
+
+	if ((clk > 500 && clk != 667)) {
+		if (clock_real_clk[VDEC_1] == 648)
+			return 648;
+		clk = 667;
+	}
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1 &&
+		get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1 &&
+		get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5 &&
+		get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5D)
+		clk = 800;
+
+	if (is_cpu_s4_s805x2())
+		clk = 500;
+
+	if (set_frq_enable && vdec_frq) {
+		pr_info("Set the vdec frq is %u MHz\n", vdec_frq);
+		clk = vdec_frq;
+	}
+
+	vdec_set_clk(VDEC_1, clk * MHz);
+
+	clock_real_clk[VDEC_1] = clk;
+
+	pr_debug("vdec mux clock is %lu Hz\n",
+		clk_get_rate(gclk.vdec_mux_node->clk));
+
+	return clk;
+}
+
+static int hevc_clock_init(void)
+{
+	return 0;
+}
+
+static int hevc_back_clock_init(void)
+{
+	return 0;
+}
+
+static int hevc_back_clock_set(int clk)
+{
+	if (clk == 1)
+		clk = 200;
+	else if (clk == 2) {
+		if (clock_real_clk[VDEC_HEVCB] != 648)
+			clk = 500;
+		else
+			clk = 648;
+	} else if (clk == 0) {
+		if (clock_real_clk[VDEC_HEVCB] == 667 ||
+			(clock_real_clk[VDEC_HEVCB] == 648) ||
+			clock_real_clk[VDEC_HEVCB] <= 0)
+			clk = 200;
+		else
+			clk = clock_real_clk[VDEC_HEVCB];
+	}
+
+	if ((clk > 500 && clk != 667)) {
+		if (clock_real_clk[VDEC_HEVCB] == 648)
+		return 648;
+		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)
+			clk = TL1_HEVC_MAX_CLK;
+		else
+			clk = 667;
+	}
+
+	if (set_frq_enable && hevcb_frq) {
+		pr_info("Set the hevcb frq is %u MHz\n", hevcb_frq);
+		clk = hevcb_frq;
+	}
+
+	if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) &&
+		(get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SC2)) {
+		if ((READ_EFUSE_REG(EFUSE_LIC1) >> 28 & 0x1) && clk > 333) {
+			pr_info("The hevcb clock limit to 333MHz.\n");
+			clk = 333;
+		}
+	}
+
+	vdec_set_clk(VDEC_HEVCB, clk * MHz);
+
+	clock_real_clk[VDEC_HEVCB] = clk;
+	pr_debug("hevc back mux clock is %lu Hz\n",
+		clk_get_rate(gclk.hevc_back_mux_node->clk));
+
+	return clk;
+}
+
+static int hevc_clock_set(int clk)
+{
+	if (clk == 1)
+		clk = 200;
+	else if (clk == 2) {
+		if (clock_real_clk[VDEC_HEVC] != 648)
+			clk = 500;
+		else
+			clk = 648;
+	} else if (clk == 0) {
+		if (clock_real_clk[VDEC_HEVC] == 667 ||
+			(clock_real_clk[VDEC_HEVC] == 648) ||
+			clock_real_clk[VDEC_HEVC] <= 0)
+			clk = 200;
+		else
+			clk = clock_real_clk[VDEC_HEVC];
+	}
+
+	if ((clk > 500 && clk != 667)) {
+		if (clock_real_clk[VDEC_HEVC] == 648)
+			return 648;
+		if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+			(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5) &&
+			(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5D))
+			clk = TL1_HEVC_MAX_CLK;
+		else
+			clk = 667;
+
+		if (is_cpu_s4_s805x2())
+			clk = 500;
+	}
+
+	if (set_frq_enable && hevc_frq) {
+		pr_info("Set the hevc frq is %u MHz\n", hevc_frq);
+		clk = hevc_frq;
+	}
+
+	vdec_set_clk(VDEC_HEVC, clk * MHz);
+
+	clock_real_clk[VDEC_HEVC] = clk;
+
+	pr_debug("hevc mux clock is %lu Hz\n",
+		clk_get_rate(gclk.hevc_mux_node->clk));
+
+	return clk;
+}
+
+static int hcodec_clock_set(int clk)
+{
+	if (clk == 1)
+		clk = 200;
+	else if (clk == 2) {
+		if (clock_real_clk[VDEC_HCODEC] != 648)
+			clk = 500;
+		else
+			clk = 648;
+	} else if (clk == 0) {
+		if (clock_real_clk[VDEC_HCODEC] == 667 ||
+			(clock_real_clk[VDEC_HCODEC] == 648) ||
+			clock_real_clk[VDEC_HCODEC] <= 0)
+			clk = 200;
+		else
+			clk = clock_real_clk[VDEC_HCODEC];
+	}
+
+	if ((clk > 500 && clk != 667)) {
+		if (clock_real_clk[VDEC_HCODEC] == 648)
+			return 648;
+		clk = 667;
+	}
+
+	vdec_set_clk(VDEC_HCODEC, clk * MHz);
+
+	clock_real_clk[VDEC_HCODEC] = clk;
+
+	pr_debug("hcodec mux clock is %lu Hz\n",
+		clk_get_rate(gclk.hcodec_mux_node->clk));
+
+	return clk;
+}
+#endif
+
+static void vdec_clock_on(void)
+{
+	mutex_lock(&gclk.vdec_mux_node->mutex);
+	if (!gclk.vdec_mux_node->ref_count)
+		clk_prepare_enable(gclk.vdec_mux_node->clk);
+
+	gclk.vdec_mux_node->ref_count++;
+	mutex_unlock(&gclk.vdec_mux_node->mutex);
+
+	pr_debug("the %-15s clock on, ref cnt: %d\n",
+		gclk.vdec_mux_node->name,
+		gclk.vdec_mux_node->ref_count);
+}
+
+static void vdec_clock_off(void)
+{
+	mutex_lock(&gclk.vdec_mux_node->mutex);
+	gclk.vdec_mux_node->ref_count--;
+	if (!gclk.vdec_mux_node->ref_count)
+		clk_disable_unprepare(gclk.vdec_mux_node->clk);
+
+	clock_real_clk[VDEC_1] = 0;
+	mutex_unlock(&gclk.vdec_mux_node->mutex);
+
+	pr_debug("the %-15s clock off, ref cnt: %d\n",
+		gclk.vdec_mux_node->name,
+		gclk.vdec_mux_node->ref_count);
+}
+
+static void hcodec_clock_on(void)
+{
+	mutex_lock(&gclk.hcodec_mux_node->mutex);
+	if (!gclk.hcodec_mux_node->ref_count)
+		clk_prepare_enable(gclk.hcodec_mux_node->clk);
+
+	gclk.hcodec_mux_node->ref_count++;
+	mutex_unlock(&gclk.hcodec_mux_node->mutex);
+
+	pr_debug("the %-15s clock on, ref cnt: %d\n",
+		gclk.hcodec_mux_node->name,
+		gclk.hcodec_mux_node->ref_count);
+}
+
+static void hcodec_clock_off(void)
+{
+	mutex_lock(&gclk.hcodec_mux_node->mutex);
+	gclk.hcodec_mux_node->ref_count--;
+	if (!gclk.hcodec_mux_node->ref_count)
+		clk_disable_unprepare(gclk.hcodec_mux_node->clk);
+
+	mutex_unlock(&gclk.hcodec_mux_node->mutex);
+
+	pr_debug("the %-15s clock off, ref cnt: %d\n",
+		gclk.hcodec_mux_node->name,
+		gclk.hcodec_mux_node->ref_count);
+}
+
+static void hevc_clock_on(void)
+{
+	mutex_lock(&gclk.hevc_mux_node->mutex);
+	if (!gclk.hevc_mux_node->ref_count)
+		clk_prepare_enable(gclk.hevc_mux_node->clk);
+
+	gclk.hevc_mux_node->ref_count++;
+	WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);
+	mutex_unlock(&gclk.hevc_mux_node->mutex);
+
+	pr_debug("the %-15s clock on, ref cnt: %d\n",
+		gclk.hevc_mux_node->name,
+		gclk.hevc_mux_node->ref_count);
+}
+
+static void hevc_clock_off(void)
+{
+	mutex_lock(&gclk.hevc_mux_node->mutex);
+	gclk.hevc_mux_node->ref_count--;
+	if (!gclk.hevc_mux_node->ref_count)
+		clk_disable_unprepare(gclk.hevc_mux_node->clk);
+
+	clock_real_clk[VDEC_HEVC] = 0;
+	mutex_unlock(&gclk.hevc_mux_node->mutex);
+
+	pr_debug("the %-15s clock off, ref cnt: %d\n",
+		gclk.hevc_mux_node->name,
+		gclk.hevc_mux_node->ref_count);
+}
+
+static void hevc_back_clock_on(void)
+{
+	mutex_lock(&gclk.hevc_back_mux_node->mutex);
+	if (!gclk.hevc_back_mux_node->ref_count)
+		clk_prepare_enable(gclk.hevc_back_mux_node->clk);
+
+	gclk.hevc_back_mux_node->ref_count++;
+	WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);
+	mutex_unlock(&gclk.hevc_back_mux_node->mutex);
+
+	pr_debug("the %-15s clock on, ref cnt: %d\n",
+		gclk.hevc_back_mux_node->name,
+		gclk.hevc_back_mux_node->ref_count);
+}
+
+static void hevc_back_clock_off(void)
+{
+	mutex_lock(&gclk.hevc_back_mux_node->mutex);
+	gclk.hevc_back_mux_node->ref_count--;
+	if (!gclk.hevc_back_mux_node->ref_count)
+		clk_disable_unprepare(gclk.hevc_back_mux_node->clk);
+
+	clock_real_clk[VDEC_HEVC] = 0;
+	mutex_unlock(&gclk.hevc_back_mux_node->mutex);
+
+	pr_debug("the %-15s clock off, ref cnt: %d\n",
+		gclk.hevc_back_mux_node->name,
+		gclk.hevc_back_mux_node->ref_count);
+}
+
+static int vdec_clock_get(enum vdec_type_e core)
+{
+	if (core >= VDEC_MAX)
+		return 0;
+
+	return clock_real_clk[core];
+}
+
+#define INCLUDE_FROM_ARCH_CLK_MGR
+
+/*#define VDEC_HAS_VDEC2*/
+#define VDEC_HAS_HEVC
+#define VDEC_HAS_VDEC_HCODEC
+#define VDEC_HAS_CLK_SETTINGS
+#define CLK_FOR_CPU {\
+	AM_MESON_CPU_MAJOR_ID_GXBB,\
+	AM_MESON_CPU_MAJOR_ID_GXTVBB,\
+	AM_MESON_CPU_MAJOR_ID_GXL,\
+	AM_MESON_CPU_MAJOR_ID_GXM,\
+	AM_MESON_CPU_MAJOR_ID_TXL,\
+	AM_MESON_CPU_MAJOR_ID_TXLX,\
+	AM_MESON_CPU_MAJOR_ID_GXLX,\
+	AM_MESON_CPU_MAJOR_ID_G12A,\
+	AM_MESON_CPU_MAJOR_ID_G12B,\
+	AM_MESON_CPU_MAJOR_ID_SM1,\
+	AM_MESON_CPU_MAJOR_ID_TL1,\
+	AM_MESON_CPU_MAJOR_ID_TM2,\
+	AM_MESON_CPU_MAJOR_ID_SC2,\
+	AM_MESON_CPU_MAJOR_ID_T5,\
+	AM_MESON_CPU_MAJOR_ID_T5D,\
+	AM_MESON_CPU_MAJOR_ID_T7,\
+	AM_MESON_CPU_MAJOR_ID_S4,\
+	AM_MESON_CPU_MAJOR_ID_T3,\
+	AM_MESON_CPU_MAJOR_ID_P1,\
+	AM_MESON_CPU_MAJOR_ID_S4D,\
+	AM_MESON_CPU_MAJOR_ID_T5W,\
+	0}
+#include "clk.h"
+
+module_param(set_frq_enable, uint, 0664);
+MODULE_PARM_DESC(set_frq_enable, "\n set frequency enable\n");
+
+module_param(vdec_frq, uint, 0664);
+MODULE_PARM_DESC(vdec_frq, "\n set vdec frequency\n");
+
+module_param(hevc_frq, uint, 0664);
+MODULE_PARM_DESC(hevc_frq, "\n set hevc frequency\n");
+
+module_param(hevcb_frq, uint, 0664);
+MODULE_PARM_DESC(hevcb_frq, "\n set hevcb frequency\n");
+
+ARCH_VDEC_CLK_INIT();
+ARCH_VDEC_CLK_EXIT();
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/common/media_clock/switch/amports_gate.c b/drivers/common/media_clock/switch/amports_gate.c
new file mode 100644
index 0000000..58a0289
--- /dev/null
+++ b/drivers/common/media_clock/switch/amports_gate.c
@@ -0,0 +1,204 @@
+/*
+ * drivers/amlogic/media/common/arch/switch/amports_gate.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+#define DEBUG
+#include <linux/compiler.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include "amports_gate.h"
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../../../stream_input/amports/amports_priv.h"
+#include "../../../frame_provider/decoder/utils/vdec.h"
+#include "../clk/clk.h"
+
+
+#define DEBUG_REF 1
+#define GATE_RESET_OK
+
+#ifdef GATE_RESET_OK
+
+struct gate_switch_node gates[] = {
+	{
+		.name = "demux",
+	},
+	{
+		.name = "parser_top",
+	},
+	{
+		.name = "vdec",
+	},
+	{
+		.name = "clk_81",
+	},
+	{
+		.name = "clk_vdec_mux",
+	},
+	{
+		.name = "clk_hcodec_mux",
+	},
+	{
+		.name = "clk_hevc_mux",
+	},
+	{
+		.name = "clk_hevcb_mux",
+	},
+	{
+		.name = "ahbarb0",
+	},
+	{
+		.name = "asyncfifo",
+	},
+	{
+		.name = "clk_hevcf_mux",
+	},
+};
+
+/*
+ *mesonstream {
+ *	compatible = "amlogic, codec, streambuf";
+ *	dev_name = "mesonstream";
+ *	status = "okay";
+ *	clocks = <&clkc CLKID_DOS_PARSER
+ *		&clkc CLKID_DEMUX
+ *		&clkc CLKID_DOS
+ *		&clkc CLKID_VDEC_MUX
+ *		&clkc CLKID_HCODEC_MUX
+ *		&clkc CLKID_HEVCF_MUX
+ *		&clkc CLKID_HEVC_MUX>;
+ *	clock-names = "parser_top",
+ *		"demux",
+ *		"vdec",
+ *		"clk_vdec_mux",
+ *		"clk_hcodec_mux",
+ *		"clk_hevc_mux",
+ *		"clk_hevcb_mux";
+ *};
+ */
+
+int amports_clock_gate_init(struct device *dev)
+{
+	int i;
+
+	for (i = 0; i < sizeof(gates) / sizeof(struct gate_switch_node); i++) {
+		gates[i].clk = devm_clk_get(dev, gates[i].name);
+		if (IS_ERR_OR_NULL(gates[i].clk)) {
+			gates[i].clk = NULL;
+			pr_info("get gate %s control failed %px\n",
+				gates[i].name,
+				gates[i].clk);
+		} else {
+			pr_info("get gate %s control ok %px\n",
+				gates[i].name,
+				gates[i].clk);
+		}
+		gates[i].ref_count = 0;
+		mutex_init(&gates[i].mutex);
+	}
+
+	set_clock_gate(gates, ARRAY_SIZE(gates));
+
+	return 0;
+}
+EXPORT_SYMBOL(amports_clock_gate_init);
+
+static int amports_gate_clk(struct gate_switch_node *gate_node, int enable)
+{
+	mutex_lock(&gate_node->mutex);
+	if (enable) {
+		if (gate_node->ref_count == 0)
+			clk_prepare_enable(gate_node->clk);
+
+		gate_node->ref_count++;
+
+		if (DEBUG_REF)
+			pr_debug("the %-15s clock on, ref cnt: %d\n",
+				gate_node->name, gate_node->ref_count);
+	} else {
+		gate_node->ref_count--;
+		if (gate_node->ref_count == 0)
+			clk_disable_unprepare(gate_node->clk);
+
+		if (DEBUG_REF)
+			pr_debug("the %-15s clock off, ref cnt: %d\n",
+				gate_node->name, gate_node->ref_count);
+	}
+	mutex_unlock(&gate_node->mutex);
+
+	return 0;
+}
+
+int amports_switch_gate(const char *name, int enable)
+{
+	int i;
+
+	for (i = 0; i < sizeof(gates) / sizeof(struct gate_switch_node); i++) {
+		if (!strcmp(name, gates[i].name)) {
+
+			/*pr_info("openclose:%d gate %s control\n", enable,
+			 *	gates[i].name);
+			 */
+
+			if (gates[i].clk)
+				amports_gate_clk(&gates[i], enable);
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(amports_switch_gate);
+
+#else
+/*
+ *can used for debug.
+ *on chip bringup.
+ */
+int amports_clock_gate_init(struct device *dev)
+{
+	static int gate_inited;
+
+	if (gate_inited)
+		return 0;
+/*
+ *#define HHI_GCLK_MPEG0    0x1050
+ *#define HHI_GCLK_MPEG1    0x1051
+ *#define HHI_GCLK_MPEG2    0x1052
+ *#define HHI_GCLK_OTHER    0x1054
+ *#define HHI_GCLK_AO       0x1055
+ */
+	WRITE_HHI_REG_BITS(HHI_GCLK_MPEG0, 1, 1, 1);/*dos*/
+	WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 1, 25, 1);/*U_parser_top()*/
+	WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 0xff, 6, 8);/*aiu()*/
+	WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 1, 4, 1);/*demux()*/
+	WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 1, 2, 1);/*audio in()*/
+	WRITE_HHI_REG_BITS(HHI_GCLK_MPEG2, 1, 25, 1);/*VPU Interrupt*/
+	gate_inited++;
+
+
+
+	return 0;
+}
+EXPORT_SYMBOL(amports_clock_gate_init);
+
+
+int amports_switch_gate(const char *name, int enable)
+{
+	return 0;
+}
+EXPORT_SYMBOL(amports_switch_gate);
+
+#endif
diff --git a/drivers/common/media_clock/switch/amports_gate.h b/drivers/common/media_clock/switch/amports_gate.h
new file mode 100644
index 0000000..58abc92
--- /dev/null
+++ b/drivers/common/media_clock/switch/amports_gate.h
@@ -0,0 +1,32 @@
+/*
+ * drivers/amlogic/media/common/arch/switch/amports_gate.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef AMPORT_GATE_H
+#define AMPORT_GATE_H
+#include <linux/device.h>
+
+struct gate_switch_node {
+	struct clk *clk;
+	const char *name;
+	struct mutex mutex;
+	int ref_count;
+};
+
+extern int amports_clock_gate_init(struct device *dev);
+extern int amports_switch_gate(const char *name, int enable);
+
+#endif
diff --git a/drivers/frame_provider/Makefile b/drivers/frame_provider/Makefile
new file mode 100644
index 0000000..f30c4f1
--- /dev/null
+++ b/drivers/frame_provider/Makefile
@@ -0,0 +1,2 @@
+obj-y	+=	decoder/
+obj-y	+=	decoder_v4l/
diff --git a/drivers/frame_provider/decoder/Makefile b/drivers/frame_provider/decoder/Makefile
new file mode 100644
index 0000000..bb0079e
--- /dev/null
+++ b/drivers/frame_provider/decoder/Makefile
@@ -0,0 +1,13 @@
+obj-y	+=	utils/
+obj-y	+=	mpeg12/
+obj-y	+=	mpeg4/
+obj-y	+=	vc1/
+obj-y	+=	h264/
+obj-y	+=	h264_multi/
+obj-y	+=	h265/
+obj-y	+=	vp9/
+obj-y	+=	mjpeg/
+obj-y	+=	avs/
+obj-y	+=	avs2/
+obj-y	+=	avs_multi/
+obj-y	+=	vav1/
diff --git a/drivers/frame_provider/decoder/avs/Makefile b/drivers/frame_provider/decoder/avs/Makefile
new file mode 100644
index 0000000..1d56236
--- /dev/null
+++ b/drivers/frame_provider/decoder/avs/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_AVS) += amvdec_avs.o
+amvdec_avs-objs += avs.o avsp_trans.o
diff --git a/drivers/frame_provider/decoder/avs/avs.c b/drivers/frame_provider/decoder/avs/avs.c
new file mode 100644
index 0000000..5869eac
--- /dev/null
+++ b/drivers/frame_provider/decoder/avs/avs.c
@@ -0,0 +1,1988 @@
+/*
+ * drivers/amlogic/amports/vavs.c
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+#define DEBUG
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/kfifo.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../../../stream_input/amports/streambuf_reg.h"
+#include "../utils/amvdec.h"
+#include <linux/amlogic/media/registers/register.h>
+#include "../../../stream_input/amports/amports_priv.h"
+#include <linux/dma-mapping.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/slab.h>
+#include "avs.h"
+#include <linux/amlogic/media/codec_mm/configs.h>
+#include "../utils/decoder_mmu_box.h"
+#include "../utils/decoder_bmmu_box.h"
+#include "../utils/firmware.h"
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+//#include <linux/amlogic/tee.h>
+#include <uapi/linux/tee.h>
+
+#define DRIVER_NAME "amvdec_avs"
+#define MODULE_NAME "amvdec_avs"
+
+
+#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
+#define NV21
+#endif
+
+#define USE_AVS_SEQ_INFO
+#define HANDLE_AVS_IRQ
+#define DEBUG_PTS
+
+#define I_PICTURE   0
+#define P_PICTURE   1
+#define B_PICTURE   2
+
+/* #define ORI_BUFFER_START_ADDR   0x81000000 */
+#define ORI_BUFFER_START_ADDR   0x80000000
+
+#define INTERLACE_FLAG          0x80
+#define TOP_FIELD_FIRST_FLAG 0x40
+
+/* protocol registers */
+#define AVS_PIC_RATIO       AV_SCRATCH_0
+#define AVS_PIC_WIDTH      AV_SCRATCH_1
+#define AVS_PIC_HEIGHT     AV_SCRATCH_2
+#define AVS_FRAME_RATE     AV_SCRATCH_3
+
+#define AVS_ERROR_COUNT    AV_SCRATCH_6
+#define AVS_SOS_COUNT     AV_SCRATCH_7
+#define AVS_BUFFERIN       AV_SCRATCH_8
+#define AVS_BUFFEROUT      AV_SCRATCH_9
+#define AVS_REPEAT_COUNT    AV_SCRATCH_A
+#define AVS_TIME_STAMP      AV_SCRATCH_B
+#define AVS_OFFSET_REG      AV_SCRATCH_C
+#define MEM_OFFSET_REG      AV_SCRATCH_F
+#define AVS_ERROR_RECOVERY_MODE   AV_SCRATCH_G
+
+#define VF_POOL_SIZE        32
+#define PUT_INTERVAL        (HZ/100)
+
+#if 1 /*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8*/
+#define INT_AMVENCODER INT_DOS_MAILBOX_1
+#else
+/* #define AMVENC_DEV_VERSION "AML-MT" */
+#define INT_AMVENCODER INT_MAILBOX_1A
+#endif
+
+
+#define DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE 0x0001
+static u32 dec_control = DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE;
+
+
+#define VPP_VD1_POSTBLEND       (1 << 10)
+
+static int debug_flag;
+
+/********************************
+firmware_sel
+    0: use avsp_trans long cabac ucode;
+    1: not use avsp_trans long cabac ucode
+********************************/
+static int firmware_sel;
+static int disable_longcabac_trans = 1;
+
+static int support_user_data = 1;
+
+int avs_get_debug_flag(void)
+{
+	return debug_flag;
+}
+
+static struct vframe_s *vavs_vf_peek(void *);
+static struct vframe_s *vavs_vf_get(void *);
+static void vavs_vf_put(struct vframe_s *, void *);
+static int vavs_event_cb(int type, void *data, void *private_data);
+static int vavs_vf_states(struct vframe_states *states, void *);
+
+static const char vavs_dec_id[] = "vavs-dev";
+
+#define PROVIDER_NAME   "decoder.avs"
+static DEFINE_SPINLOCK(lock);
+static DEFINE_MUTEX(vavs_mutex);
+
+static const struct vframe_operations_s vavs_vf_provider = {
+	.peek = vavs_vf_peek,
+	.get = vavs_vf_get,
+	.put = vavs_vf_put,
+	.event_cb = vavs_event_cb,
+	.vf_states = vavs_vf_states,
+};
+static void *mm_blk_handle;
+static struct vframe_provider_s vavs_vf_prov;
+
+#define VF_BUF_NUM_MAX 16
+#define WORKSPACE_SIZE		(4 * SZ_1M)
+
+#ifdef AVSP_LONG_CABAC
+#define MAX_BMMU_BUFFER_NUM	(VF_BUF_NUM_MAX + 2)
+#define WORKSPACE_SIZE_A		(MAX_CODED_FRAME_SIZE + LOCAL_HEAP_SIZE)
+#else
+#define MAX_BMMU_BUFFER_NUM	(VF_BUF_NUM_MAX + 1)
+#endif
+
+#define RV_AI_BUFF_START_ADDR	 0x01a00000
+#define LONG_CABAC_RV_AI_BUFF_START_ADDR	 0x00000000
+
+static u32 vf_buf_num = 8;
+static u32 vf_buf_num_used;
+static u32 canvas_base = 128;
+#ifdef NV21
+	int	canvas_num = 2; /*NV21*/
+#else
+	int	canvas_num = 3;
+#endif
+
+static struct vframe_s vfpool[VF_POOL_SIZE];
+/*static struct vframe_s vfpool2[VF_POOL_SIZE];*/
+static struct vframe_s *cur_vfpool;
+static unsigned char recover_flag;
+static s32 vfbuf_use[VF_BUF_NUM_MAX];
+static u32 saved_resolution;
+static u32 frame_width, frame_height, frame_dur, frame_prog;
+static struct timer_list recycle_timer;
+static u32 stat;
+static u32 buf_size = 32 * 1024 * 1024;
+static u32 buf_offset;
+static u32 avi_flag;
+static u32 vavs_ratio;
+static u32 pic_type;
+static u32 pts_by_offset = 1;
+static u32 total_frame;
+static u32 next_pts;
+static unsigned char throw_pb_flag;
+#ifdef DEBUG_PTS
+static u32 pts_hit, pts_missed, pts_i_hit, pts_i_missed;
+#endif
+
+static u32 radr, rval;
+static struct dec_sysinfo vavs_amstream_dec_info;
+static struct vdec_info *gvs;
+static u32 fr_hint_status;
+static struct work_struct notify_work;
+static struct work_struct set_clk_work;
+static bool is_reset;
+
+static struct vdec_s *vdec = NULL;
+
+#ifdef AVSP_LONG_CABAC
+static struct work_struct long_cabac_wd_work;
+void *es_write_addr_virt;
+dma_addr_t es_write_addr_phy;
+
+void *bitstream_read_tmp;
+dma_addr_t bitstream_read_tmp_phy;
+void *avsp_heap_adr;
+static uint long_cabac_busy;
+#endif
+
+
+static void *user_data_buffer;
+static dma_addr_t user_data_buffer_phys;
+
+static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE);
+static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE);
+static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE);
+
+static inline u32 index2canvas(u32 index)
+{
+	const u32 canvas_tab[VF_BUF_NUM_MAX] = {
+		0x010100, 0x030302, 0x050504, 0x070706,
+		0x090908, 0x0b0b0a, 0x0d0d0c, 0x0f0f0e,
+		0x111110, 0x131312, 0x151514, 0x171716,
+		0x191918, 0x1b1b1a, 0x1d1d1c, 0x1f1f1e,
+	};
+	const u32 canvas_tab_3[4] = {
+		0x010100, 0x040403, 0x070706, 0x0a0a09
+	};
+
+	if (canvas_num == 2)
+		return canvas_tab[index] + (canvas_base << 16)
+		+ (canvas_base << 8) + canvas_base;
+
+	return canvas_tab_3[index] + (canvas_base << 16)
+		+ (canvas_base << 8) + canvas_base;
+}
+
+static const u32 frame_rate_tab[16] = {
+	96000 / 30,		/* forbidden */
+	96000000 / 23976,	/* 24000/1001 (23.967) */
+	96000 / 24,
+	96000 / 25,
+	9600000 / 2997,		/* 30000/1001 (29.97) */
+	96000 / 30,
+	96000 / 50,
+	9600000 / 5994,		/* 60000/1001 (59.94) */
+	96000 / 60,
+	/* > 8 reserved, use 24 */
+	96000 / 24, 96000 / 24, 96000 / 24, 96000 / 24,
+	96000 / 24, 96000 / 24, 96000 / 24
+};
+
+static void set_frame_info(struct vframe_s *vf, unsigned int *duration)
+{
+	int ar = 0;
+
+	unsigned int pixel_ratio = READ_VREG(AVS_PIC_RATIO);
+#ifndef USE_AVS_SEQ_INFO
+	if (vavs_amstream_dec_info.width > 0
+		&& vavs_amstream_dec_info.height > 0) {
+		vf->width = vavs_amstream_dec_info.width;
+		vf->height = vavs_amstream_dec_info.height;
+	} else
+#endif
+	{
+		vf->width = READ_VREG(AVS_PIC_WIDTH);
+		vf->height = READ_VREG(AVS_PIC_HEIGHT);
+		frame_width = vf->width;
+		frame_height = vf->height;
+		/* pr_info("%s: (%d,%d)\n", __func__,vf->width, vf->height);*/
+	}
+
+#ifndef USE_AVS_SEQ_INFO
+	if (vavs_amstream_dec_info.rate > 0)
+		*duration = vavs_amstream_dec_info.rate;
+	else
+#endif
+	{
+		*duration = frame_rate_tab[READ_VREG(AVS_FRAME_RATE) & 0xf];
+		/* pr_info("%s: duration = %d\n", __func__, *duration); */
+		frame_dur = *duration;
+		schedule_work(&notify_work);
+	}
+
+	if (vavs_ratio == 0) {
+		/* always stretch to 16:9 */
+		vf->ratio_control |= (0x90 <<
+				DISP_RATIO_ASPECT_RATIO_BIT);
+	} else {
+		switch (pixel_ratio) {
+		case 1:
+			ar = (vf->height * vavs_ratio) / vf->width;
+			break;
+		case 2:
+			ar = (vf->height * 3 * vavs_ratio) / (vf->width * 4);
+			break;
+		case 3:
+			ar = (vf->height * 9 * vavs_ratio) / (vf->width * 16);
+			break;
+		case 4:
+			ar = (vf->height * 100 * vavs_ratio) / (vf->width *
+					221);
+			break;
+		default:
+			ar = (vf->height * vavs_ratio) / vf->width;
+			break;
+		}
+	}
+
+	ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX);
+
+	vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT);
+	/*vf->ratio_control |= DISP_RATIO_FORCECONFIG | DISP_RATIO_KEEPRATIO; */
+
+	vf->flag = 0;
+}
+
+
+static struct work_struct userdata_push_work;
+/*
+#define DUMP_LAST_REPORTED_USER_DATA
+*/
+static void userdata_push_do_work(struct work_struct *work)
+{
+	unsigned int user_data_flags;
+	unsigned int user_data_wp;
+	unsigned int user_data_length;
+	struct userdata_poc_info_t user_data_poc;
+#ifdef DUMP_LAST_REPORTED_USER_DATA
+	int user_data_len;
+	int wp_start;
+	unsigned char *pdata;
+	int nLeft;
+#endif
+
+	user_data_flags = READ_VREG(AV_SCRATCH_N);
+	user_data_wp = (user_data_flags >> 16) & 0xffff;
+	user_data_length = user_data_flags & 0x7fff;
+
+#ifdef DUMP_LAST_REPORTED_USER_DATA
+	dma_sync_single_for_cpu(amports_get_dma_device(),
+			user_data_buffer_phys, USER_DATA_SIZE,
+			DMA_FROM_DEVICE);
+
+	if (user_data_length & 0x07)
+		user_data_len = (user_data_length + 8) & 0xFFFFFFF8;
+	else
+		user_data_len = user_data_length;
+
+	if (user_data_wp >= user_data_len) {
+		wp_start = user_data_wp - user_data_len;
+
+		pdata = (unsigned char *)user_data_buffer;
+		pdata += wp_start;
+		nLeft = user_data_len;
+		while (nLeft >= 8) {
+			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+				pdata[0], pdata[1], pdata[2], pdata[3],
+				pdata[4], pdata[5], pdata[6], pdata[7]);
+			nLeft -= 8;
+			pdata += 8;
+		}
+	} else {
+		wp_start = user_data_wp +
+			USER_DATA_SIZE - user_data_len;
+
+		pdata = (unsigned char *)user_data_buffer;
+		pdata += wp_start;
+		nLeft = USER_DATA_SIZE - wp_start;
+
+		while (nLeft >= 8) {
+			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+				pdata[0], pdata[1], pdata[2], pdata[3],
+				pdata[4], pdata[5], pdata[6], pdata[7]);
+			nLeft -= 8;
+			pdata += 8;
+		}
+
+		pdata = (unsigned char *)user_data_buffer;
+		nLeft = user_data_wp;
+		while (nLeft >= 8) {
+			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+				pdata[0], pdata[1], pdata[2], pdata[3],
+				pdata[4], pdata[5], pdata[6], pdata[7]);
+			nLeft -= 8;
+			pdata += 8;
+		}
+	}
+#endif
+
+/*
+	pr_info("pocinfo 0x%x, poc %d, wp 0x%x, len %d\n",
+		   READ_VREG(AV_SCRATCH_L), READ_VREG(AV_SCRATCH_M),
+		   user_data_wp, user_data_length);
+*/
+	user_data_poc.poc_info = READ_VREG(AV_SCRATCH_L);
+	user_data_poc.poc_number = READ_VREG(AV_SCRATCH_M);
+
+	WRITE_VREG(AV_SCRATCH_N, 0);
+/*
+	wakeup_userdata_poll(user_data_poc, user_data_wp,
+				(unsigned long)user_data_buffer,
+				USER_DATA_SIZE, user_data_length);
+*/
+}
+
+static void UserDataHandler(void)
+{
+	unsigned int user_data_flags;
+
+	user_data_flags = READ_VREG(AV_SCRATCH_N);
+	if (user_data_flags & (1 << 15)) {	/* data ready */
+		schedule_work(&userdata_push_work);
+	}
+}
+
+
+#ifdef HANDLE_AVS_IRQ
+static irqreturn_t vavs_isr(int irq, void *dev_id)
+#else
+static void vavs_isr(void)
+#endif
+{
+	u32 reg;
+	struct vframe_s *vf;
+	u32 dur;
+	u32 repeat_count;
+	u32 picture_type;
+	u32 buffer_index;
+	u32 frame_size;
+	bool force_interlaced_frame = false;
+	unsigned int pts, pts_valid = 0, offset = 0;
+	u64 pts_us64;
+	if (debug_flag & AVS_DEBUG_UCODE) {
+		if (READ_VREG(AV_SCRATCH_E) != 0) {
+			pr_info("dbg%x: %x\n", READ_VREG(AV_SCRATCH_E),
+				   READ_VREG(AV_SCRATCH_D));
+			WRITE_VREG(AV_SCRATCH_E, 0);
+		}
+	}
+#ifdef AVSP_LONG_CABAC
+	if (firmware_sel == 0 && READ_VREG(LONG_CABAC_REQ)) {
+#ifdef PERFORMANCE_DEBUG
+		pr_info("%s:schedule long_cabac_wd_work\r\n", __func__);
+#endif
+		pr_info("schedule long_cabac_wd_work and requested from %d\n",
+			(READ_VREG(LONG_CABAC_REQ) >> 8)&0xFF);
+		schedule_work(&long_cabac_wd_work);
+	}
+#endif
+
+
+	UserDataHandler();
+
+	reg = READ_VREG(AVS_BUFFEROUT);
+
+	if (reg) {
+		if (debug_flag & AVS_DEBUG_PRINT)
+			pr_info("AVS_BUFFEROUT=%x\n", reg);
+		if (pts_by_offset) {
+			offset = READ_VREG(AVS_OFFSET_REG);
+			if (debug_flag & AVS_DEBUG_PRINT)
+				pr_info("AVS OFFSET=%x\n", offset);
+			if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, offset, &pts,
+				&frame_size,
+				0, &pts_us64) == 0) {
+				pts_valid = 1;
+#ifdef DEBUG_PTS
+				pts_hit++;
+#endif
+			} else {
+#ifdef DEBUG_PTS
+				pts_missed++;
+#endif
+			}
+		}
+
+		repeat_count = READ_VREG(AVS_REPEAT_COUNT);
+		if (firmware_sel == 0)
+			buffer_index =
+				((reg & 0x7) +
+				(((reg >> 8) & 0x3) << 3) - 1) & 0x1f;
+		else
+			buffer_index =
+				((reg & 0x7) - 1) & 7;
+
+		picture_type = (reg >> 3) & 7;
+#ifdef DEBUG_PTS
+		if (picture_type == I_PICTURE) {
+			/* pr_info("I offset 0x%x, pts_valid %d\n",
+			 *   offset, pts_valid);
+			 */
+			if (!pts_valid)
+				pts_i_missed++;
+			else
+				pts_i_hit++;
+		}
+#endif
+
+		if ((dec_control & DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE)
+			&& frame_width == 1920 && frame_height == 1080) {
+			force_interlaced_frame = true;
+		}
+
+		if (throw_pb_flag && picture_type != I_PICTURE) {
+
+			if (debug_flag & AVS_DEBUG_PRINT) {
+				pr_info("picture type %d throwed\n",
+					   picture_type);
+			}
+			WRITE_VREG(AVS_BUFFERIN, ~(1 << buffer_index));
+		} else if (reg & INTERLACE_FLAG || force_interlaced_frame) {	/* interlace */
+			throw_pb_flag = 0;
+
+			if (debug_flag & AVS_DEBUG_PRINT) {
+				pr_info("interlace, picture type %d\n",
+					   picture_type);
+			}
+
+			if (kfifo_get(&newframe_q, &vf) == 0) {
+				pr_info
+				("fatal error, no available buffer slot.");
+				return IRQ_HANDLED;
+			}
+			set_frame_info(vf, &dur);
+			vf->bufWidth = 1920;
+			pic_type = 2;
+			if ((picture_type == I_PICTURE) && pts_valid) {
+				vf->pts = pts;
+				vf->pts_us64 = pts_us64;
+				if ((repeat_count > 1) && avi_flag) {
+					/* next_pts = pts +
+					 *   (vavs_amstream_dec_info.rate *
+					 *   repeat_count >> 1)*15/16;
+					 */
+					next_pts =
+						pts +
+						(dur * repeat_count >> 1) *
+						15 / 16;
+				} else
+					next_pts = 0;
+			} else {
+				vf->pts = next_pts;
+				if (vf->pts == 0) {
+					vf->pts_us64 = 0;
+				}
+				if ((repeat_count > 1) && avi_flag) {
+					/* vf->duration =
+					 *   vavs_amstream_dec_info.rate *
+					 *   repeat_count >> 1;
+					 */
+					vf->duration = dur * repeat_count >> 1;
+					if (next_pts != 0) {
+						next_pts +=
+							((vf->duration) -
+							 ((vf->duration) >> 4));
+					}
+				} else {
+					/* vf->duration =
+					 *   vavs_amstream_dec_info.rate >> 1;
+					 */
+					vf->duration = dur >> 1;
+					next_pts = 0;
+				}
+			}
+			vf->signal_type = 0;
+			vf->index = buffer_index;
+			vf->duration_pulldown = 0;
+			if (force_interlaced_frame) {
+				vf->type = VIDTYPE_INTERLACE_TOP;
+			}else{
+				vf->type =
+				(reg & TOP_FIELD_FIRST_FLAG)
+				? VIDTYPE_INTERLACE_TOP
+				: VIDTYPE_INTERLACE_BOTTOM;
+				}
+#ifdef NV21
+			vf->type |= VIDTYPE_VIU_NV21;
+#endif
+			vf->canvas0Addr = vf->canvas1Addr =
+				index2canvas(buffer_index);
+			vf->type_original = vf->type;
+
+			if (debug_flag & AVS_DEBUG_PRINT) {
+				pr_info("buffer_index %d, canvas addr %x\n",
+					   buffer_index, vf->canvas0Addr);
+			}
+
+			vf->pts = (pts_valid)?pts:0;
+			/*
+			*vf->pts_us64 = (pts_valid) ? pts_us64 : 0;
+			*/
+			vfbuf_use[buffer_index]++;
+			vf->mem_handle =
+				decoder_bmmu_box_get_mem_handle(
+					mm_blk_handle,
+					buffer_index);
+			decoder_do_frame_check(NULL, vf);
+			kfifo_put(&display_q,
+					  (const struct vframe_s *)vf);
+			ATRACE_COUNTER(MODULE_NAME, vf->pts);
+			vf_notify_receiver(PROVIDER_NAME,
+					VFRAME_EVENT_PROVIDER_VFRAME_READY,
+					NULL);
+
+			if (kfifo_get(&newframe_q, &vf) == 0) {
+				pr_info("fatal error, no available buffer slot.");
+				return IRQ_HANDLED;
+						}
+			set_frame_info(vf, &dur);
+			vf->bufWidth = 1920;
+			if (force_interlaced_frame)
+				vf->pts = 0;
+			else
+			vf->pts = next_pts;
+			if (vf->pts == 0) {
+				vf->pts_us64 = 0;
+			}
+			if ((repeat_count > 1) && avi_flag) {
+				/* vf->duration = vavs_amstream_dec_info.rate *
+				 *   repeat_count >> 1;
+				 */
+				vf->duration = dur * repeat_count >> 1;
+				if (next_pts != 0) {
+					next_pts +=
+						((vf->duration) -
+						 ((vf->duration) >> 4));
+				}
+			} else {
+				/* vf->duration = vavs_amstream_dec_info.rate
+				 *   >> 1;
+				 */
+				vf->duration = dur >> 1;
+				next_pts = 0;
+			}
+			vf->signal_type = 0;
+			vf->index = buffer_index;
+			vf->duration_pulldown = 0;
+			if (force_interlaced_frame) {
+				vf->type = VIDTYPE_INTERLACE_BOTTOM;
+			} else {
+						vf->type =
+						(reg & TOP_FIELD_FIRST_FLAG) ?
+						VIDTYPE_INTERLACE_BOTTOM :
+						VIDTYPE_INTERLACE_TOP;
+					}
+#ifdef NV21
+			vf->type |= VIDTYPE_VIU_NV21;
+#endif
+			vf->canvas0Addr = vf->canvas1Addr =
+				index2canvas(buffer_index);
+			vf->type_original = vf->type;
+			vf->pts_us64 = 0;
+			vfbuf_use[buffer_index]++;
+			vf->mem_handle =
+				decoder_bmmu_box_get_mem_handle(
+					mm_blk_handle,
+					buffer_index);
+
+			kfifo_put(&display_q,
+					  (const struct vframe_s *)vf);
+			ATRACE_COUNTER(MODULE_NAME, vf->pts);
+			vf_notify_receiver(PROVIDER_NAME,
+					VFRAME_EVENT_PROVIDER_VFRAME_READY,
+					NULL);
+			total_frame++;
+		} else {	/* progressive */
+			throw_pb_flag = 0;
+
+			if (debug_flag & AVS_DEBUG_PRINT) {
+				pr_info("progressive picture type %d\n",
+					   picture_type);
+			}
+			if (kfifo_get(&newframe_q, &vf) == 0) {
+				pr_info
+				("fatal error, no available buffer slot.");
+				return IRQ_HANDLED;
+			}
+			set_frame_info(vf, &dur);
+			vf->bufWidth = 1920;
+			pic_type = 1;
+
+			if ((picture_type == I_PICTURE) && pts_valid) {
+				vf->pts = pts;
+				if ((repeat_count > 1) && avi_flag) {
+					/* next_pts = pts +
+					 *   (vavs_amstream_dec_info.rate *
+					 *   repeat_count)*15/16;
+					 */
+					next_pts =
+						pts +
+						(dur * repeat_count) * 15 / 16;
+				} else
+					next_pts = 0;
+			} else {
+				vf->pts = next_pts;
+				if (vf->pts == 0) {
+					vf->pts_us64 = 0;
+				}
+				if ((repeat_count > 1) && avi_flag) {
+					/* vf->duration =
+					 *   vavs_amstream_dec_info.rate *
+					 *   repeat_count;
+					 */
+					vf->duration = dur * repeat_count;
+					if (next_pts != 0) {
+						next_pts +=
+							((vf->duration) -
+							 ((vf->duration) >> 4));
+					}
+				} else {
+					/* vf->duration =
+					 *   vavs_amstream_dec_info.rate;
+					 */
+					vf->duration = dur;
+					next_pts = 0;
+				}
+			}
+			vf->signal_type = 0;
+			vf->index = buffer_index;
+			vf->duration_pulldown = 0;
+			vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
+#ifdef NV21
+			vf->type |= VIDTYPE_VIU_NV21;
+#endif
+			vf->canvas0Addr = vf->canvas1Addr =
+				index2canvas(buffer_index);
+			vf->type_original = vf->type;
+			vf->pts = (pts_valid)?pts:0;
+			/*
+			*vf->pts_us64 = (pts_valid) ? pts_us64 : 0;
+			*/
+			if (debug_flag & AVS_DEBUG_PRINT) {
+				pr_info("buffer_index %d, canvas addr %x\n",
+					   buffer_index, vf->canvas0Addr
+					   );
+			 pr_info("PicType = %d, PTS = 0x%x\n",
+				picture_type, vf->pts);
+			}
+
+			vfbuf_use[buffer_index]++;
+			vf->mem_handle =
+				decoder_bmmu_box_get_mem_handle(
+					mm_blk_handle,
+					buffer_index);
+			decoder_do_frame_check(NULL, vf);
+			kfifo_put(&display_q,
+					  (const struct vframe_s *)vf);
+			ATRACE_COUNTER(MODULE_NAME, vf->pts);
+			vf_notify_receiver(PROVIDER_NAME,
+					VFRAME_EVENT_PROVIDER_VFRAME_READY,
+					NULL);
+			total_frame++;
+		}
+
+		/*count info*/
+		gvs->frame_dur = frame_dur;
+		vdec_count_info(gvs, 0, offset);
+
+		/* pr_info("PicType = %d, PTS = 0x%x\n",
+		 *   picture_type, vf->pts);
+		 */
+		WRITE_VREG(AVS_BUFFEROUT, 0);
+	}
+	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+#ifdef HANDLE_AVS_IRQ
+	return IRQ_HANDLED;
+#else
+	return;
+#endif
+}
+/*
+ *static int run_flag = 1;
+ *static int step_flag;
+ */
+static int error_recovery_mode;   /*0: blocky  1: mosaic*/
+/*
+ *static uint error_watchdog_threshold=10;
+ *static uint error_watchdog_count;
+ *static uint error_watchdog_buf_threshold = 0x4000000;
+ */
+
+static struct vframe_s *vavs_vf_peek(void *op_arg)
+{
+	struct vframe_s *vf;
+
+	if (recover_flag)
+		return NULL;
+
+	if (kfifo_peek(&display_q, &vf))
+		return vf;
+
+	return NULL;
+
+}
+
+static struct vframe_s *vavs_vf_get(void *op_arg)
+{
+	struct vframe_s *vf;
+
+	if (recover_flag)
+		return NULL;
+
+	if (kfifo_get(&display_q, &vf))
+		return vf;
+
+	return NULL;
+
+}
+
+static void vavs_vf_put(struct vframe_s *vf, void *op_arg)
+{
+	int i;
+
+	if (recover_flag)
+		return;
+
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		if (vf == &cur_vfpool[i])
+			break;
+	}
+	if (i < VF_POOL_SIZE)
+		kfifo_put(&recycle_q, (const struct vframe_s *)vf);
+
+}
+
+static int vavs_event_cb(int type, void *data, void *private_data)
+{
+	if (type & VFRAME_EVENT_RECEIVER_REQ_STATE) {
+		struct provider_state_req_s *req =
+			(struct provider_state_req_s *)data;
+		if (req->req_type == REQ_STATE_SECURE && vdec)
+			req->req_result[0] = vdec_secure(vdec);
+		else
+			req->req_result[0] = 0xffffffff;
+	}
+
+	return 0;
+}
+
+int vavs_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
+{
+	if (!(stat & STAT_VDEC_RUN))
+		return -1;
+
+	vstatus->frame_width = frame_width;
+	vstatus->frame_height = frame_height;
+	if (frame_dur != 0)
+		vstatus->frame_rate = 96000 / frame_dur;
+	else
+		vstatus->frame_rate = -1;
+	vstatus->error_count = READ_VREG(AV_SCRATCH_C);
+	vstatus->status = stat;
+	vstatus->bit_rate = gvs->bit_rate;
+	vstatus->frame_dur = frame_dur;
+	vstatus->frame_data = gvs->frame_data;
+	vstatus->total_data = gvs->total_data;
+	vstatus->frame_count = gvs->frame_count;
+	vstatus->error_frame_count = gvs->error_frame_count;
+	vstatus->drop_frame_count = gvs->drop_frame_count;
+	vstatus->total_data = gvs->total_data;
+	vstatus->samp_cnt = gvs->samp_cnt;
+	vstatus->offset = gvs->offset;
+	snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
+		"%s", DRIVER_NAME);
+
+	return 0;
+}
+
+int vavs_set_isreset(struct vdec_s *vdec, int isreset)
+{
+	is_reset = isreset;
+	return 0;
+}
+
+static int vavs_vdec_info_init(void)
+{
+	gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL);
+	if (NULL == gvs) {
+		pr_info("the struct of vdec status malloc failed.\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+/****************************************/
+static int vavs_canvas_init(void)
+{
+	int i, ret;
+	u32 canvas_width, canvas_height;
+	u32 decbuf_size, decbuf_y_size, decbuf_uv_size;
+	unsigned long buf_start;
+	int need_alloc_buf_num;
+	u32 endian;
+
+	vf_buf_num_used = vf_buf_num;
+	if (buf_size <= 0x00400000) {
+		/* SD only */
+		canvas_width = 768;
+		canvas_height = 576;
+		decbuf_y_size = 0x80000;
+		decbuf_uv_size = 0x20000;
+		decbuf_size = 0x100000;
+	} else {
+		/* HD & SD */
+		canvas_width = 1920;
+		canvas_height = 1088;
+		decbuf_y_size = 0x200000;
+		decbuf_uv_size = 0x80000;
+		decbuf_size = 0x300000;
+	}
+
+#ifdef AVSP_LONG_CABAC
+	need_alloc_buf_num = vf_buf_num_used + 2;
+#else
+	need_alloc_buf_num = vf_buf_num_used + 1;
+#endif
+	for (i = 0; i < need_alloc_buf_num; i++) {
+
+		if (i == (need_alloc_buf_num - 1))
+			decbuf_size = WORKSPACE_SIZE;
+#ifdef AVSP_LONG_CABAC
+		else if (i == (need_alloc_buf_num - 2))
+			decbuf_size = WORKSPACE_SIZE_A;
+#endif
+		ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, i,
+				decbuf_size, DRIVER_NAME, &buf_start);
+		if (ret < 0)
+			return ret;
+		if (i == (need_alloc_buf_num - 1)) {
+			if (firmware_sel == 1)
+				buf_offset = buf_start -
+					RV_AI_BUFF_START_ADDR;
+			else
+				buf_offset = buf_start -
+					LONG_CABAC_RV_AI_BUFF_START_ADDR;
+			continue;
+		}
+#ifdef AVSP_LONG_CABAC
+		else if (i == (need_alloc_buf_num - 2)) {
+			avsp_heap_adr = codec_mm_phys_to_virt(buf_start);
+			continue;
+		}
+#endif
+		if (vdec->canvas_mode == CANVAS_BLKMODE_LINEAR)
+			endian = 7;
+		else
+			endian = 0;
+#ifdef NV21
+			config_cav_lut_ex(canvas_base + canvas_num * i + 0,
+					buf_start,
+					canvas_width, canvas_height,
+					CANVAS_ADDR_NOWRAP,
+					vdec->canvas_mode, endian, VDEC_1);
+			config_cav_lut_ex(canvas_base + canvas_num * i + 1,
+					buf_start +
+					decbuf_y_size, canvas_width,
+					canvas_height / 2,
+					CANVAS_ADDR_NOWRAP,
+					vdec->canvas_mode, endian, VDEC_1);
+#else
+			config_cav_lut_ex(canvas_num * i + 0,
+					buf_start,
+					canvas_width, canvas_height,
+					CANVAS_ADDR_NOWRAP,
+					vdec->canvas_mode, endian, VDEC_1);
+			config_cav_lut_ex(canvas_num * i + 1,
+					buf_start +
+					decbuf_y_size, canvas_width / 2,
+					canvas_height / 2,
+					CANVAS_ADDR_NOWRAP,
+					vdec->canvas_mode, endian, VDEC_1);
+			config_cav_lut_ex(canvas_num * i + 2,
+					buf_start +
+					decbuf_y_size + decbuf_uv_size,
+					canvas_width / 2, canvas_height / 2,
+					CANVAS_ADDR_NOWRAP,
+					vdec->canvas_mode, endian, VDEC_1);
+#endif
+			if (debug_flag & AVS_DEBUG_PRINT) {
+				pr_info("canvas config %d, addr %p\n", i,
+					   (void *)buf_start);
+			}
+
+	}
+	return 0;
+}
+
+void vavs_recover(void)
+{
+	vavs_canvas_init();
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	READ_VREG(DOS_SW_RESET0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+	WRITE_VREG(AV_SCRATCH_H, 0);
+	if (firmware_sel == 1) {
+		WRITE_VREG(POWER_CTL_VLD, 0x10);
+		WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2,
+			MEM_FIFO_CNT_BIT, 2);
+		WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 8,
+			MEM_LEVEL_CNT_BIT, 6);
+		WRITE_VREG(AV_SCRATCH_H, 1); // 8 buf flag to ucode
+	}
+
+
+	if (firmware_sel == 0) {
+		/* fixed canvas index */
+		WRITE_VREG(AV_SCRATCH_0, canvas_base);
+		WRITE_VREG(AV_SCRATCH_1, vf_buf_num_used);
+	} else {
+		int ii;
+
+		for (ii = 0; ii < 4; ii++) {
+			WRITE_VREG(AV_SCRATCH_0 + ii,
+				(canvas_base + canvas_num * ii) |
+				((canvas_base + canvas_num * ii + 1)
+					<< 8) |
+				((canvas_base + canvas_num * ii + 1)
+					<< 16)
+			);
+		}
+	}
+
+	/* notify ucode the buffer offset */
+	WRITE_VREG(AV_SCRATCH_F, buf_offset);
+
+	/* disable PSCALE for hardware sharing */
+	WRITE_VREG(PSCALE_CTRL, 0);
+
+	WRITE_VREG(AVS_SOS_COUNT, 0);
+	WRITE_VREG(AVS_BUFFERIN, 0);
+	WRITE_VREG(AVS_BUFFEROUT, 0);
+	if (error_recovery_mode)
+		WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 0);
+	else
+		WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 1);
+	/* clear mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+	/* enable mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_MASK, 1);
+#if 1				/* def DEBUG_UCODE */
+	WRITE_VREG(AV_SCRATCH_D, 0);
+#endif
+
+#ifdef NV21
+	SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17);
+#endif
+
+#ifdef PIC_DC_NEED_CLEAR
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31);
+#endif
+
+#ifdef AVSP_LONG_CABAC
+	if (firmware_sel == 0) {
+		WRITE_VREG(LONG_CABAC_DES_ADDR, es_write_addr_phy);
+		WRITE_VREG(LONG_CABAC_REQ, 0);
+		WRITE_VREG(LONG_CABAC_PIC_SIZE, 0);
+		WRITE_VREG(LONG_CABAC_SRC_ADDR, 0);
+	}
+#endif
+	WRITE_VREG(AV_SCRATCH_N, (u32)(user_data_buffer_phys - buf_offset));
+	pr_info("support_user_data = %d\n", support_user_data);
+	if (support_user_data)
+		WRITE_VREG(AV_SCRATCH_M, 1);
+	else
+		WRITE_VREG(AV_SCRATCH_M, 0);
+
+	WRITE_VREG(AV_SCRATCH_5, 0);
+
+}
+
+static int vavs_prot_init(void)
+{
+	int r;
+#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	READ_VREG(DOS_SW_RESET0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+#else
+	WRITE_RESET_REG(RESET0_REGISTER,
+				   RESET_IQIDCT | RESET_MC | RESET_VLD_PART);
+	READ_RESET_REG(RESET0_REGISTER);
+	WRITE_RESET_REG(RESET0_REGISTER,
+				   RESET_IQIDCT | RESET_MC | RESET_VLD_PART);
+
+	WRITE_RESET_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK);
+#endif
+
+	/***************** reset vld   **********************************/
+	WRITE_VREG(POWER_CTL_VLD, 0x10);
+	WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2, MEM_FIFO_CNT_BIT, 2);
+	WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL,	8, MEM_LEVEL_CNT_BIT, 6);
+	/*************************************************************/
+
+	r = vavs_canvas_init();
+	WRITE_VREG(AV_SCRATCH_H, 0);
+#ifdef NV21
+		if (firmware_sel == 0) {
+			/* fixed canvas index */
+			WRITE_VREG(AV_SCRATCH_0, canvas_base);
+			WRITE_VREG(AV_SCRATCH_1, vf_buf_num_used);
+		} else {
+			int ii;
+
+			for (ii = 0; ii < 4; ii++) {
+				WRITE_VREG(AV_SCRATCH_0 + ii,
+					(canvas_base + canvas_num * ii) |
+					((canvas_base + canvas_num * ii + 1)
+						<< 8) |
+					((canvas_base + canvas_num * ii + 1)
+						<< 16)
+				);
+			}
+			WRITE_VREG(AV_SCRATCH_H, 1); // 8 buf flag to ucode
+		}
+#else
+	/* index v << 16 | u << 8 | y */
+	WRITE_VREG(AV_SCRATCH_0, 0x020100);
+	WRITE_VREG(AV_SCRATCH_1, 0x050403);
+	WRITE_VREG(AV_SCRATCH_2, 0x080706);
+	WRITE_VREG(AV_SCRATCH_3, 0x0b0a09);
+#endif
+	/* notify ucode the buffer offset */
+	WRITE_VREG(AV_SCRATCH_F, buf_offset);
+
+	/* disable PSCALE for hardware sharing */
+	WRITE_VREG(PSCALE_CTRL, 0);
+
+	WRITE_VREG(AVS_SOS_COUNT, 0);
+	WRITE_VREG(AVS_BUFFERIN, 0);
+	WRITE_VREG(AVS_BUFFEROUT, 0);
+	if (error_recovery_mode)
+		WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 0);
+	else
+		WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 1);
+	/* clear mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+	/* enable mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_MASK, 1);
+#if 1				/* def DEBUG_UCODE */
+	WRITE_VREG(AV_SCRATCH_D, 0);
+#endif
+
+#ifdef NV21
+	SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17);
+#endif
+
+#ifdef PIC_DC_NEED_CLEAR
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31);
+#endif
+
+#ifdef AVSP_LONG_CABAC
+	if (firmware_sel == 0) {
+		WRITE_VREG(LONG_CABAC_DES_ADDR, es_write_addr_phy);
+		WRITE_VREG(LONG_CABAC_REQ, 0);
+		WRITE_VREG(LONG_CABAC_PIC_SIZE, 0);
+		WRITE_VREG(LONG_CABAC_SRC_ADDR, 0);
+	}
+#endif
+
+	WRITE_VREG(AV_SCRATCH_N, (u32)(user_data_buffer_phys - buf_offset));
+	pr_info("support_user_data = %d\n", support_user_data);
+	if (support_user_data)
+		WRITE_VREG(AV_SCRATCH_M, 1);
+	else
+		WRITE_VREG(AV_SCRATCH_M, 0);
+
+	return r;
+}
+
+#ifdef AVSP_LONG_CABAC
+static unsigned char es_write_addr[MAX_CODED_FRAME_SIZE]  __aligned(64);
+#endif
+static void vavs_local_init(bool is_reset)
+{
+	int i;
+
+	is_reset = 0;
+	vavs_ratio = vavs_amstream_dec_info.ratio;
+
+	avi_flag = (unsigned long) vavs_amstream_dec_info.param;
+
+	frame_width = frame_height = frame_dur = frame_prog = 0;
+
+	throw_pb_flag = 1;
+
+	total_frame = 0;
+	saved_resolution = 0;
+	next_pts = 0;
+
+#ifdef DEBUG_PTS
+	pts_hit = pts_missed = pts_i_hit = pts_i_missed = 0;
+#endif
+
+	if (!is_reset) {
+		INIT_KFIFO(display_q);
+		INIT_KFIFO(recycle_q);
+		INIT_KFIFO(newframe_q);
+
+		for (i = 0; i < VF_POOL_SIZE; i++) {
+			const struct vframe_s *vf = &vfpool[i];
+
+			vfpool[i].index = vf_buf_num;
+			vfpool[i].bufWidth = 1920;
+			kfifo_put(&newframe_q, vf);
+		}
+
+		for (i = 0; i < vf_buf_num; i++)
+			vfbuf_use[i] = 0;
+	}
+
+	cur_vfpool = vfpool;
+
+	if (recover_flag == 1)
+		return;
+
+	if (mm_blk_handle) {
+		decoder_bmmu_box_free(mm_blk_handle);
+		mm_blk_handle = NULL;
+	}
+
+	mm_blk_handle = decoder_bmmu_box_alloc_box(
+		DRIVER_NAME,
+		0,
+		MAX_BMMU_BUFFER_NUM,
+		4 + PAGE_SHIFT,
+		CODEC_MM_FLAGS_CMA_CLEAR |
+		CODEC_MM_FLAGS_FOR_VDECODER);
+
+}
+
+static int vavs_vf_states(struct vframe_states *states, void *op_arg)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&lock, flags);
+	states->vf_pool_size = VF_POOL_SIZE;
+	states->buf_free_num = kfifo_len(&newframe_q);
+	states->buf_avail_num = kfifo_len(&display_q);
+	states->buf_recycle_num = kfifo_len(&recycle_q);
+	spin_unlock_irqrestore(&lock, flags);
+	return 0;
+}
+
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+static void vavs_ppmgr_reset(void)
+{
+	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL);
+
+	vavs_local_init(true);
+
+	pr_info("vavs: vf_ppmgr_reset\n");
+}
+#endif
+
+static void vavs_local_reset(void)
+{
+	mutex_lock(&vavs_mutex);
+	//recover_flag = 1;
+	pr_info("error, local reset\n");
+	amvdec_stop();
+	msleep(100);
+	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL);
+	vavs_local_init(true);
+	vavs_recover();
+
+
+	reset_userdata_fifo(1);
+
+
+	amvdec_start();
+	recover_flag = 0;
+#if 0
+	error_watchdog_count = 0;
+
+	pr_info("pc %x stream buf wp %x rp %x level %x\n",
+		READ_VREG(MPC_E),
+		READ_VREG(VLD_MEM_VIFIFO_WP),
+		READ_VREG(VLD_MEM_VIFIFO_RP),
+		READ_VREG(VLD_MEM_VIFIFO_LEVEL));
+#endif
+
+
+
+	mutex_unlock(&vavs_mutex);
+}
+
+static struct work_struct fatal_error_wd_work;
+static struct work_struct notify_work;
+static atomic_t error_handler_run = ATOMIC_INIT(0);
+static void vavs_fatal_error_handler(struct work_struct *work)
+{
+	if (debug_flag & AVS_DEBUG_OLD_ERROR_HANDLE) {
+		mutex_lock(&vavs_mutex);
+		pr_info("vavs fatal error reset !\n");
+		amvdec_stop();
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+		vavs_ppmgr_reset();
+#else
+		vf_light_unreg_provider(&vavs_vf_prov);
+		vavs_local_init(true);
+		vf_reg_provider(&vavs_vf_prov);
+#endif
+		vavs_recover();
+		amvdec_start();
+		mutex_unlock(&vavs_mutex);
+	} else {
+		pr_info("avs fatal_error_handler\n");
+		vavs_local_reset();
+	}
+	atomic_set(&error_handler_run, 0);
+}
+
+static void vavs_notify_work(struct work_struct *work)
+{
+	if (fr_hint_status == VDEC_NEED_HINT) {
+		vf_notify_receiver(PROVIDER_NAME ,
+			VFRAME_EVENT_PROVIDER_FR_HINT ,
+			(void *)((unsigned long)frame_dur));
+		fr_hint_status = VDEC_HINTED;
+	}
+	return;
+}
+
+static void avs_set_clk(struct work_struct *work)
+{
+		int fps = 96000 / frame_dur;
+
+		saved_resolution = frame_width * frame_height * fps;
+		if (firmware_sel == 0 &&
+			(debug_flag & AVS_DEBUG_USE_FULL_SPEED)) {
+			vdec_source_changed(VFORMAT_AVS,
+				4096, 2048, 60);
+		} else {
+			vdec_source_changed(VFORMAT_AVS,
+			frame_width, frame_height, fps);
+		}
+}
+
+static void vavs_put_timer_func(struct timer_list *timer)
+{
+#ifndef HANDLE_AVS_IRQ
+	vavs_isr();
+#endif
+
+	if (READ_VREG(AVS_SOS_COUNT)) {
+		if (!error_recovery_mode) {
+#if 0
+			if (debug_flag & AVS_DEBUG_OLD_ERROR_HANDLE) {
+				mutex_lock(&vavs_mutex);
+				pr_info("vavs fatal error reset !\n");
+				amvdec_stop();
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+				vavs_ppmgr_reset();
+#else
+				vf_light_unreg_provider(&vavs_vf_prov);
+				vavs_local_init(true);
+				vf_reg_provider(&vavs_vf_prov);
+#endif
+				vavs_recover();
+				amvdec_start();
+				mutex_unlock(&vavs_mutex);
+			} else {
+				vavs_local_reset();
+			}
+#else
+			if (!atomic_read(&error_handler_run)) {
+				atomic_set(&error_handler_run, 1);
+				pr_info("AVS_SOS_COUNT = %d\n",
+					READ_VREG(AVS_SOS_COUNT));
+				pr_info("WP = 0x%x, RP = 0x%x, LEVEL = 0x%x, AVAIL = 0x%x, CUR_PTR = 0x%x\n",
+					READ_VREG(VLD_MEM_VIFIFO_WP),
+					READ_VREG(VLD_MEM_VIFIFO_RP),
+					READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+					READ_VREG(VLD_MEM_VIFIFO_BYTES_AVAIL),
+					READ_VREG(VLD_MEM_VIFIFO_CURR_PTR));
+				schedule_work(&fatal_error_wd_work);
+			}
+#endif
+		}
+	}
+#if 0
+	if (long_cabac_busy == 0 &&
+		error_watchdog_threshold > 0 &&
+		kfifo_len(&display_q) == 0 &&
+		READ_VREG(VLD_MEM_VIFIFO_LEVEL) >
+		error_watchdog_buf_threshold) {
+		pr_info("newq %d dispq %d recyq %d\r\n",
+			kfifo_len(&newframe_q),
+			kfifo_len(&display_q),
+			kfifo_len(&recycle_q));
+		pr_info("pc %x stream buf wp %x rp %x level %x\n",
+			READ_VREG(MPC_E),
+			READ_VREG(VLD_MEM_VIFIFO_WP),
+			READ_VREG(VLD_MEM_VIFIFO_RP),
+			READ_VREG(VLD_MEM_VIFIFO_LEVEL));
+		error_watchdog_count++;
+		if (error_watchdog_count >= error_watchdog_threshold)
+			vavs_local_reset();
+	} else
+		error_watchdog_count = 0;
+#endif
+	if (radr != 0) {
+		if (rval != 0) {
+			WRITE_VREG(radr, rval);
+			pr_info("WRITE_VREG(%x,%x)\n", radr, rval);
+		} else
+			pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr));
+		rval = 0;
+		radr = 0;
+	}
+
+	if (!kfifo_is_empty(&recycle_q) && (READ_VREG(AVS_BUFFERIN) == 0)) {
+		struct vframe_s *vf;
+
+		if (kfifo_get(&recycle_q, &vf)) {
+			if ((vf->index < vf_buf_num) &&
+			 (--vfbuf_use[vf->index] == 0)) {
+				WRITE_VREG(AVS_BUFFERIN, ~(1 << vf->index));
+				vf->index = vf_buf_num;
+			}
+				kfifo_put(&newframe_q,
+						  (const struct vframe_s *)vf);
+		}
+	}
+
+	if (frame_dur > 0 && saved_resolution !=
+		frame_width * frame_height * (96000 / frame_dur))
+		schedule_work(&set_clk_work);
+
+	timer->expires = jiffies + PUT_INTERVAL;
+
+	add_timer(timer);
+}
+
+#ifdef AVSP_LONG_CABAC
+
+static void long_cabac_do_work(struct work_struct *work)
+{
+	int status = 0;
+#ifdef PERFORMANCE_DEBUG
+	pr_info("enter %s buf level (new %d, display %d, recycle %d)\r\n",
+		__func__,
+		kfifo_len(&newframe_q),
+		kfifo_len(&display_q),
+		kfifo_len(&recycle_q)
+		);
+#endif
+	mutex_lock(&vavs_mutex);
+	long_cabac_busy = 1;
+	while (READ_VREG(LONG_CABAC_REQ)) {
+		if (process_long_cabac() < 0) {
+			status = -1;
+			break;
+		}
+	}
+	long_cabac_busy = 0;
+	mutex_unlock(&vavs_mutex);
+#ifdef PERFORMANCE_DEBUG
+	pr_info("exit %s buf level (new %d, display %d, recycle %d)\r\n",
+		__func__,
+		kfifo_len(&newframe_q),
+		kfifo_len(&display_q),
+		kfifo_len(&recycle_q)
+		);
+#endif
+	if (status < 0) {
+		pr_info("transcoding error, local reset\r\n");
+		vavs_local_reset();
+	}
+
+}
+#endif
+
+#ifdef AVSP_LONG_CABAC
+static void init_avsp_long_cabac_buf(void)
+{
+#if 0
+	es_write_addr_phy = (unsigned long)codec_mm_alloc_for_dma(
+		"vavs",
+		PAGE_ALIGN(MAX_CODED_FRAME_SIZE)/PAGE_SIZE,
+		0, CODEC_MM_FLAGS_DMA_CPU);
+	es_write_addr_virt = codec_mm_phys_to_virt(es_write_addr_phy);
+
+#elif 0
+	es_write_addr_virt =
+		(void *)dma_alloc_coherent(amports_get_dma_device(),
+		 MAX_CODED_FRAME_SIZE, &es_write_addr_phy,
+		GFP_KERNEL);
+#else
+	/*es_write_addr_virt = kmalloc(MAX_CODED_FRAME_SIZE, GFP_KERNEL);
+	 *	es_write_addr_virt = (void *)__get_free_pages(GFP_KERNEL,
+	 *	get_order(MAX_CODED_FRAME_SIZE));
+	 */
+	es_write_addr_virt = &es_write_addr[0];
+	if (es_write_addr_virt == NULL) {
+		pr_err("%s: failed to alloc es_write_addr_virt buffer\n",
+			__func__);
+		return;
+	}
+
+	es_write_addr_phy = dma_map_single(amports_get_dma_device(),
+			es_write_addr_virt,
+			MAX_CODED_FRAME_SIZE, DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(amports_get_dma_device(),
+			es_write_addr_phy)) {
+		pr_err("%s: failed to map es_write_addr_virt buffer\n",
+			__func__);
+		/*kfree(es_write_addr_virt);*/
+		es_write_addr_virt = NULL;
+		return;
+	}
+#endif
+
+
+#ifdef BITSTREAM_READ_TMP_NO_CACHE
+	bitstream_read_tmp =
+		(void *)dma_alloc_coherent(amports_get_dma_device(),
+			SVA_STREAM_BUF_SIZE, &bitstream_read_tmp_phy,
+			 GFP_KERNEL);
+
+#else
+
+	bitstream_read_tmp = kmalloc(SVA_STREAM_BUF_SIZE, GFP_KERNEL);
+		/*bitstream_read_tmp = (void *)__get_free_pages(GFP_KERNEL,
+		 *get_order(MAX_CODED_FRAME_SIZE));
+		 */
+	if (bitstream_read_tmp == NULL) {
+		pr_err("%s: failed to alloc bitstream_read_tmp buffer\n",
+			__func__);
+		return;
+	}
+
+	bitstream_read_tmp_phy = dma_map_single(amports_get_dma_device(),
+			bitstream_read_tmp,
+			SVA_STREAM_BUF_SIZE, DMA_FROM_DEVICE);
+	if (dma_mapping_error(amports_get_dma_device(),
+			bitstream_read_tmp_phy)) {
+		pr_err("%s: failed to map rpm buffer\n", __func__);
+		kfree(bitstream_read_tmp);
+		bitstream_read_tmp = NULL;
+		return;
+	}
+#endif
+}
+#endif
+
+
+static s32 vavs_init(void)
+{
+	int ret, size = -1;
+	char *buf = vmalloc(0x1000 * 16);
+
+	if (IS_ERR_OR_NULL(buf))
+		return -ENOMEM;
+
+	pr_info("vavs_init\n");
+
+	stat |= STAT_TIMER_INIT;
+
+	amvdec_enable();
+	vavs_local_init(false);
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM)
+		size = get_firmware_data(VIDEO_DEC_AVS, buf);
+	else {
+		if (firmware_sel == 1)
+			size = get_firmware_data(VIDEO_DEC_AVS_NOCABAC, buf);
+#ifdef AVSP_LONG_CABAC
+		else {
+			init_avsp_long_cabac_buf();
+			size = get_firmware_data(VIDEO_DEC_AVS, buf);
+		}
+#endif
+	}
+
+	if (size < 0) {
+		amvdec_disable();
+		pr_err("get firmware fail.");
+		vfree(buf);
+		return -1;
+	}
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM)
+		ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, buf);
+	else if (firmware_sel == 1)
+		ret = amvdec_loadmc_ex(VFORMAT_AVS, "avs_no_cabac", buf);
+	else
+		ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, buf);
+
+	if (ret < 0) {
+		amvdec_disable();
+		vfree(buf);
+		pr_err("AVS: the %s fw loading failed, err: %x\n",
+			tee_enabled() ? "TEE" : "local", ret);
+		return -EBUSY;
+	}
+
+	vfree(buf);
+
+	stat |= STAT_MC_LOAD;
+
+	/* enable AMRISC side protocol */
+	ret = vavs_prot_init();
+	if (ret < 0)
+		return ret;
+
+#ifdef HANDLE_AVS_IRQ
+	if (vdec_request_irq(VDEC_IRQ_1, vavs_isr,
+			"vavs-irq", (void *)vavs_dec_id)) {
+		amvdec_disable();
+		pr_info("vavs irq register error.\n");
+		return -ENOENT;
+	}
+#endif
+
+	stat |= STAT_ISR_REG;
+
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+	vf_provider_init(&vavs_vf_prov, PROVIDER_NAME, &vavs_vf_provider, NULL);
+	vf_reg_provider(&vavs_vf_prov);
+	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL);
+#else
+	vf_provider_init(&vavs_vf_prov, PROVIDER_NAME, &vavs_vf_provider, NULL);
+	vf_reg_provider(&vavs_vf_prov);
+#endif
+
+	if (vavs_amstream_dec_info.rate != 0) {
+		if (!is_reset) {
+			vf_notify_receiver(PROVIDER_NAME,
+					VFRAME_EVENT_PROVIDER_FR_HINT,
+					(void *)((unsigned long)
+					vavs_amstream_dec_info.rate));
+			fr_hint_status = VDEC_HINTED;
+		}
+	} else
+		fr_hint_status = VDEC_NEED_HINT;
+
+	stat |= STAT_VF_HOOK;
+
+	timer_setup(&recycle_timer, vavs_put_timer_func, 0);
+	recycle_timer.expires = jiffies + PUT_INTERVAL;
+	add_timer(&recycle_timer);
+
+	stat |= STAT_TIMER_ARM;
+
+#ifdef AVSP_LONG_CABAC
+	if (firmware_sel == 0)
+		INIT_WORK(&long_cabac_wd_work, long_cabac_do_work);
+#endif
+	vdec_source_changed(VFORMAT_AVS,
+					1920, 1080, 30);
+	amvdec_start();
+
+	stat |= STAT_VDEC_RUN;
+
+	return 0;
+}
+
+static int amvdec_avs_probe(struct platform_device *pdev)
+{
+	struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
+
+	if (pdata == NULL) {
+		pr_info("amvdec_avs memory resource undefined.\n");
+		return -EFAULT;
+	}
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM || disable_longcabac_trans)
+		firmware_sel = 1;
+
+	if (firmware_sel == 1) {
+		vf_buf_num = 8;
+		canvas_base = 0;
+		canvas_num = 2;
+	} else {
+
+		canvas_base = 128;
+		canvas_num = 2; /*NV21*/
+	}
+
+
+	if (pdata->sys_info)
+		vavs_amstream_dec_info = *pdata->sys_info;
+
+	pr_info("%s (%d,%d) %d\n", __func__, vavs_amstream_dec_info.width,
+		   vavs_amstream_dec_info.height, vavs_amstream_dec_info.rate);
+
+	pdata->dec_status = vavs_dec_status;
+	pdata->set_isreset = vavs_set_isreset;
+	is_reset = 0;
+
+	pdata->user_data_read = NULL;
+	pdata->reset_userdata_fifo = NULL;
+
+	vavs_vdec_info_init();
+
+
+	if (NULL == user_data_buffer) {
+		user_data_buffer =
+			dma_alloc_coherent(amports_get_dma_device(),
+				USER_DATA_SIZE,
+				&user_data_buffer_phys, GFP_KERNEL);
+		if (!user_data_buffer) {
+			pr_info("%s: Can not allocate user_data_buffer\n",
+				   __func__);
+			return -ENOMEM;
+		}
+		pr_debug("user_data_buffer = 0x%p, user_data_buffer_phys = 0x%x\n",
+			user_data_buffer, (u32)user_data_buffer_phys);
+	}
+
+	INIT_WORK(&set_clk_work, avs_set_clk);
+	vdec = pdata;
+
+	INIT_WORK(&fatal_error_wd_work, vavs_fatal_error_handler);
+	atomic_set(&error_handler_run, 0);
+
+	INIT_WORK(&userdata_push_work, userdata_push_do_work);
+	INIT_WORK(&notify_work, vavs_notify_work);
+
+	if (vavs_init() < 0) {
+		pr_info("amvdec_avs init failed.\n");
+		kfree(gvs);
+		gvs = NULL;
+		pdata->dec_status = NULL;
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static int amvdec_avs_remove(struct platform_device *pdev)
+{
+	if (stat & STAT_TIMER_ARM) {
+		del_timer_sync(&recycle_timer);
+		stat &= ~STAT_TIMER_ARM;
+	}
+	cancel_work_sync(&fatal_error_wd_work);
+	atomic_set(&error_handler_run, 0);
+
+	cancel_work_sync(&userdata_push_work);
+
+	cancel_work_sync(&notify_work);
+	if (stat & STAT_VDEC_RUN) {
+		amvdec_stop();
+		stat &= ~STAT_VDEC_RUN;
+	}
+
+	if (stat & STAT_ISR_REG) {
+		vdec_free_irq(VDEC_IRQ_1, (void *)vavs_dec_id);
+		stat &= ~STAT_ISR_REG;
+	}
+
+#ifdef AVSP_LONG_CABAC
+	if (firmware_sel == 0) {
+		mutex_lock(&vavs_mutex);
+		cancel_work_sync(&long_cabac_wd_work);
+		mutex_unlock(&vavs_mutex);
+
+		if (es_write_addr_virt) {
+#if 0
+			codec_mm_free_for_dma("vavs", es_write_addr_phy);
+#else
+			dma_unmap_single(amports_get_dma_device(),
+				es_write_addr_phy,
+				MAX_CODED_FRAME_SIZE, DMA_FROM_DEVICE);
+			/*kfree(es_write_addr_virt);*/
+			es_write_addr_virt = NULL;
+#endif
+		}
+
+#ifdef BITSTREAM_READ_TMP_NO_CACHE
+		if (bitstream_read_tmp) {
+			dma_free_coherent(amports_get_dma_device(),
+				SVA_STREAM_BUF_SIZE, bitstream_read_tmp,
+				bitstream_read_tmp_phy);
+			bitstream_read_tmp = NULL;
+		}
+#else
+		if (bitstream_read_tmp) {
+			dma_unmap_single(amports_get_dma_device(),
+				bitstream_read_tmp_phy,
+				SVA_STREAM_BUF_SIZE, DMA_FROM_DEVICE);
+			kfree(bitstream_read_tmp);
+			bitstream_read_tmp = NULL;
+		}
+#endif
+	}
+#endif
+	if (stat & STAT_VF_HOOK) {
+		if (fr_hint_status == VDEC_HINTED)
+			vf_notify_receiver(PROVIDER_NAME,
+				VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL);
+		fr_hint_status = VDEC_NO_NEED_HINT;
+		vf_unreg_provider(&vavs_vf_prov);
+		stat &= ~STAT_VF_HOOK;
+	}
+
+
+	if (user_data_buffer != NULL) {
+		dma_free_coherent(
+			amports_get_dma_device(),
+			USER_DATA_SIZE,
+			user_data_buffer,
+			user_data_buffer_phys);
+		user_data_buffer = NULL;
+		user_data_buffer_phys = 0;
+	}
+
+
+	amvdec_disable();
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TM2)
+		vdec_reset_core(NULL);
+	pic_type = 0;
+	if (mm_blk_handle) {
+		decoder_bmmu_box_free(mm_blk_handle);
+		mm_blk_handle = NULL;
+	}
+#ifdef DEBUG_PTS
+	pr_debug("pts hit %d, pts missed %d, i hit %d, missed %d\n", pts_hit,
+		   pts_missed, pts_i_hit, pts_i_missed);
+	pr_debug("total frame %d, avi_flag %d, rate %d\n", total_frame, avi_flag,
+		   vavs_amstream_dec_info.rate);
+#endif
+	kfree(gvs);
+	gvs = NULL;
+	vdec = NULL;
+
+	cancel_work_sync(&set_clk_work);
+	return 0;
+}
+
+/****************************************/
+#ifdef CONFIG_PM
+static int avs_suspend(struct device *dev)
+{
+	amvdec_suspend(to_platform_device(dev), dev->power.power_state);
+	return 0;
+}
+
+static int avs_resume(struct device *dev)
+{
+	amvdec_resume(to_platform_device(dev));
+	return 0;
+}
+
+static const struct dev_pm_ops avs_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(avs_suspend, avs_resume)
+};
+#endif
+
+static struct platform_driver amvdec_avs_driver = {
+	.probe = amvdec_avs_probe,
+	.remove = amvdec_avs_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+#ifdef CONFIG_PM
+		.pm = &avs_pm_ops,
+#endif
+	}
+};
+
+static struct codec_profile_t amvdec_avs_profile = {
+	.name = "avs",
+	.profile = ""
+};
+
+static struct mconfig avs_configs[] = {
+	MC_PU32("stat", &stat),
+	MC_PU32("debug_flag", &debug_flag),
+	MC_PU32("error_recovery_mode", &error_recovery_mode),
+	MC_PU32("pic_type", &pic_type),
+	MC_PU32("radr", &radr),
+	MC_PU32("vf_buf_num", &vf_buf_num),
+	MC_PU32("vf_buf_num_used", &vf_buf_num_used),
+	MC_PU32("canvas_base", &canvas_base),
+	MC_PU32("firmware_sel", &firmware_sel),
+};
+static struct mconfig_node avs_node;
+
+
+static int __init amvdec_avs_driver_init_module(void)
+{
+	pr_debug("amvdec_avs module init\n");
+
+	if (platform_driver_register(&amvdec_avs_driver)) {
+		pr_info("failed to register amvdec_avs driver\n");
+		return -ENODEV;
+	}
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB)
+		amvdec_avs_profile.profile = "avs+";
+
+	vcodec_profile_register(&amvdec_avs_profile);
+	INIT_REG_NODE_CONFIGS("media.decoder", &avs_node,
+		"avs", avs_configs, CONFIG_FOR_RW);
+	return 0;
+}
+
+static void __exit amvdec_avs_driver_remove_module(void)
+{
+	pr_debug("amvdec_avs module remove.\n");
+
+	platform_driver_unregister(&amvdec_avs_driver);
+}
+
+/****************************************/
+
+module_param(stat, uint, 0664);
+MODULE_PARM_DESC(stat, "\n amvdec_avs stat\n");
+
+/******************************************
+ *module_param(run_flag, uint, 0664);
+ *MODULE_PARM_DESC(run_flag, "\n run_flag\n");
+ *
+ *module_param(step_flag, uint, 0664);
+ *MODULE_PARM_DESC(step_flag, "\n step_flag\n");
+ *******************************************
+ */
+
+module_param(debug_flag, uint, 0664);
+MODULE_PARM_DESC(debug_flag, "\n debug_flag\n");
+
+module_param(error_recovery_mode, uint, 0664);
+MODULE_PARM_DESC(error_recovery_mode, "\n error_recovery_mode\n");
+
+/******************************************
+ *module_param(error_watchdog_threshold, uint, 0664);
+ *MODULE_PARM_DESC(error_watchdog_threshold, "\n error_watchdog_threshold\n");
+ *
+ *module_param(error_watchdog_buf_threshold, uint, 0664);
+ *MODULE_PARM_DESC(error_watchdog_buf_threshold,
+ *			"\n error_watchdog_buf_threshold\n");
+ *******************************************
+ */
+
+module_param(pic_type, uint, 0444);
+MODULE_PARM_DESC(pic_type, "\n amdec_vas picture type\n");
+
+module_param(radr, uint, 0664);
+MODULE_PARM_DESC(radr, "\nradr\n");
+
+module_param(rval, uint, 0664);
+MODULE_PARM_DESC(rval, "\nrval\n");
+
+module_param(vf_buf_num, uint, 0664);
+MODULE_PARM_DESC(vf_buf_num, "\nvf_buf_num\n");
+
+module_param(vf_buf_num_used, uint, 0664);
+MODULE_PARM_DESC(vf_buf_num_used, "\nvf_buf_num_used\n");
+
+module_param(canvas_base, uint, 0664);
+MODULE_PARM_DESC(canvas_base, "\ncanvas_base\n");
+
+
+module_param(firmware_sel, uint, 0664);
+MODULE_PARM_DESC(firmware_sel, "\n firmware_sel\n");
+
+module_param(disable_longcabac_trans, uint, 0664);
+MODULE_PARM_DESC(disable_longcabac_trans, "\n disable_longcabac_trans\n");
+
+module_param(dec_control, uint, 0664);
+MODULE_PARM_DESC(dec_control, "\n amvdec_vavs decoder control\n");
+
+module_param(support_user_data, uint, 0664);
+MODULE_PARM_DESC(support_user_data, "\n support_user_data\n");
+
+module_init(amvdec_avs_driver_init_module);
+module_exit(amvdec_avs_driver_remove_module);
+
+MODULE_DESCRIPTION("AMLOGIC AVS Video Decoder Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Qi Wang <qi.wang@amlogic.com>");
diff --git a/drivers/frame_provider/decoder/avs/avs.h b/drivers/frame_provider/decoder/avs/avs.h
new file mode 100644
index 0000000..8277d20
--- /dev/null
+++ b/drivers/frame_provider/decoder/avs/avs.h
@@ -0,0 +1,91 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#ifndef AVS_H_
+#define AVS_H_
+
+#ifdef CONFIG_AMLOGIC_AVSP_LONG_CABAC
+#define AVSP_LONG_CABAC
+#endif
+/*#define BITSTREAM_READ_TMP_NO_CACHE*/
+
+#ifdef AVSP_LONG_CABAC
+#define MAX_CODED_FRAME_SIZE 1500000         /*!< bytes for one frame*/
+#define LOCAL_HEAP_SIZE    (1024*1024*10)
+/*
+ *#define MAX_CODED_FRAME_SIZE  240000
+ *#define MAX_CODED_FRAME_SIZE  700000
+ */
+#define SVA_STREAM_BUF_SIZE 1024
+
+extern void *es_write_addr_virt;
+extern dma_addr_t es_write_addr_phy;
+
+extern void *bitstream_read_tmp;
+extern dma_addr_t bitstream_read_tmp_phy;
+extern void *avsp_heap_adr;
+
+int avs_get_debug_flag(void);
+
+int process_long_cabac(void);
+
+/* bit [6] - skip_mode_flag
+ * bit [5:4] - picture_type
+ * bit [3] - picture_structure (0-Field, 1-Frame)
+ * bit [2] - fixed_picture_qp
+ * bit [1] - progressive_sequence
+ * bit [0] - active
+ */
+#define LONG_CABAC_REQ        AV_SCRATCH_K
+#define LONG_CABAC_SRC_ADDR   AV_SCRATCH_H
+#define LONG_CABAC_DES_ADDR   AV_SCRATCH_I
+/* bit[31:16] - vertical_size
+ * bit[15:0] - horizontal_size
+ */
+#define LONG_CABAC_PIC_SIZE   AV_SCRATCH_J
+
+#endif
+
+/*
+ *#define PERFORMANCE_DEBUG
+ *#define DUMP_DEBUG
+ */
+#define AVS_DEBUG_PRINT         0x01
+#define AVS_DEBUG_UCODE         0x02
+#define AVS_DEBUG_OLD_ERROR_HANDLE	0x10
+#define AVS_DEBUG_USE_FULL_SPEED 0x80
+#define AEC_DUMP				0x100
+#define STREAM_INFO_DUMP		0x200
+#define SLICE_INFO_DUMP			0x400
+#define MB_INFO_DUMP			0x800
+#define MB_NUM_DUMP				0x1000
+#define BLOCK_NUM_DUMP			0x2000
+#define COEFF_DUMP				0x4000
+#define ES_DUMP					0x8000
+#define DQUANT_DUMP				0x10000
+#define STREAM_INFO_DUMP_MORE   0x20000
+#define STREAM_INFO_DUMP_MORE2  0x40000
+
+extern void *es_write_addr_virt;
+extern void *bitstream_read_tmp;
+extern dma_addr_t bitstream_read_tmp_phy;
+int read_bitstream(unsigned char *Buf, int size);
+int u_v(int LenInBits, char *tracestring);
+
+#endif
diff --git a/drivers/frame_provider/decoder/avs/avsp_trans.c b/drivers/frame_provider/decoder/avs/avsp_trans.c
new file mode 100644
index 0000000..a92dbb9
--- /dev/null
+++ b/drivers/frame_provider/decoder/avs/avsp_trans.c
@@ -0,0 +1,5065 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/platform_device.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/dma-mapping.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/slab.h>
+/* #include <mach/am_regs.h> */
+#include <linux/module.h>
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../../../stream_input/amports/streambuf_reg.h"
+#include "../utils/amvdec.h"
+#include <linux/amlogic/media/registers/register.h>
+#include "../../../stream_input/amports/amports_priv.h"
+
+#include "avs.h"
+#ifdef AVSP_LONG_CABAC
+
+#define DECODING_SANITY_CHECK
+
+#define TRACE 0
+#define LIWR_FIX 0
+#define pow2(a, b) (1<<b)
+#define io_printf pr_info
+
+static unsigned char *local_heap_adr;
+static int local_heap_size;
+static int local_heap_pos;
+static int transcoding_error_flag;
+
+unsigned char *local_alloc(int num, int size)
+{
+	unsigned char *ret_buf = NULL;
+	int alloc_size = num * size;
+
+	if ((local_heap_pos + alloc_size) <= local_heap_size) {
+		ret_buf = local_heap_adr + local_heap_pos;
+		local_heap_pos += alloc_size;
+	} else {
+		pr_info(
+				"!!!local_alloc(%d) error, local_heap (size %d) is not enough\r\n",
+				alloc_size, local_heap_size);
+	}
+	return ret_buf;
+}
+
+int local_heap_init(int size)
+{
+	/*local_heap_adr = &local_heap[0];*/
+	local_heap_adr = (unsigned char *)(avsp_heap_adr +
+	MAX_CODED_FRAME_SIZE);
+	memset(local_heap_adr, 0, LOCAL_HEAP_SIZE);
+
+	local_heap_size = LOCAL_HEAP_SIZE;
+	local_heap_pos = 0;
+	return 0;
+}
+
+void local_heap_uninit(void)
+{
+	local_heap_adr = NULL;
+	local_heap_size = 0;
+	local_heap_pos = 0;
+}
+
+#define CODE2D_ESCAPE_SYMBOL 59
+
+const int vlc_golomb_order[3][7][2] =
+
+{{{2, 9}, {2, 9}, {2, 9}, {2, 9}, {2, 9}, {2, 9}, {2, 9}, }, {{3, 9}, {2, 9}, {
+		2, 9}, {2, 9}, {2, 9}, {2, 9}, {2, 9}, }, {{2, 9}, {0, 9},
+		{1, 9}, {1, 9}, {0, 9}, {-1, -1}, {-1, -1}, }, };
+
+const int MaxRun[3][7] = {{22, 14, 9, 6, 4, 2, 1}, {25, 18, 13, 9, 6, 4, 3}, {
+		24, 19, 10, 7, 4, -1, -1} };
+
+const int refabslevel[19][26] = {{4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+		2, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1}, {7, 4, 4, 3, 3, 3, 3, 3, 2,
+		2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+		10, 6, 4, 4, 3, 3, 3, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1}, {13, 7, 5, 4, 3, 2, 2, -1, -1,
+		-1 - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {18, 8, 4, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {22, 7, 3, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {27, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4,
+		3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+		2, 2, 2, 2}, {5, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+		2, 2, -1, -1, -1, -1, -1, -1, -1}, {7, 5, 4, 4, 3, 3, 3, 2, 2,
+		2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+		{10, 6, 5, 4, 3, 3, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1}, {13, 7, 5, 4,
+				3, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1}, {17, 8, 4,
+				3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				22, 6, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1}, {5, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+				2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1}, {6, 4, 3,
+				3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+				2, -1, -1, -1, -1, -1, -1}, {10, 6, 4, 4, 3, 3,
+				2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {14, 7, 4, 3, 3, 2,
+				2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1}, {20, 7, 3, 2,
+				2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1} };
+
+static const int incvlc_intra[7] = {0, 1, 2, 4, 7, 10, 3000};
+static const int incvlc_chroma[5] = {0, 1, 2, 4, 3000};
+
+const int AVS_2DVLC_INTRA[7][26][27] = {{{0, 22, 38, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {2, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 44, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {6, 50, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {8, 54, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {10, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {12, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {14, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {18, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {20, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {24, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {28, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {30, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {34, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {40, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {42, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {46, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {48, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {52, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {56, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, }, {{8, 0, 4, 15, 27, 41,
+		55, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, 2, 17, 35, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+		{-1, 6, 25, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, 9, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, 11, 39, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, 13, 45, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, 19, 49, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, 21, 51, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, 23, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, 31, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, 37, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, 47, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, 57, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, }, {{8, 0, 2, 6,
+		13, 17, 27, 35, 45, 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {-1, 4, 11, 21, 33, 49, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {-1, 9, 23, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, 15,
+		29, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, 19, 39, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, 25, 43, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {-1, 31, 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, 41,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, 47, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, 57, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, }, {{8, 0, 2, 4, 9, 11, 17, 21, 25, 33, 39, 45, 55, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, 6, 13, 19,
+		29, 35, 47, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {-1, 15, 27, 41, 57, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1}, {-1, 23, 37, 53, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+		-1, 31, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, 43, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {-1, 49, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, }, {{6, 0, 2, 4, 7, 9, 11, 15, 17,
+		21, 23, 29, 33, 35, 43, 47, 49, 57, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {-1, 13, 19, 27, 31, 37, 45, 55, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+		25, 41, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, 39, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1}, {-1, 53, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, }, {{0,
+		1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 23, 25, 27, 31, 33, 37, 41,
+		45, 49, 51, 55, -1, -1, -1, -1, -1}, {-1, 21, 29, 35, 43, 47,
+		53, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, 39, 57, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1}, }, {{0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19,
+		21, 23, 25, 27, 29, 31, 35, 37, 39, 41, 43, 47, 49, 51, 53, 57},
+		{-1, 33, 45, 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} } };
+
+const int AVS_2DVLC_CHROMA[5][26][27] = {{{0, 14, 32, 56, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {2, 48, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1}, {6, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1}, {8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {10,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {12, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1}, {16, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {18, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {20,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {22, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1}, {24, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {26, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {28,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {30, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1}, {34, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {38,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {40, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1}, {42, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {44, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {46,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {50, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1}, {52, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1}, {54, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, }, {{0, 1, 5, 15, 29,
+		43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1}, {-1, 3, 21, 45, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1}, {-1, 7, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, 9, 41, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {-1, 11, 53, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1}, {-1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+		-1, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, 19, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {-1, 23, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1}, {-1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+		-1, 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, 31, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {-1, 33, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1}, {-1, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+		-1, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, 47, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {-1, 49, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1}, {-1, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+		-1, 55, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, 57, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+		-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, },
+		{{2, 0, 3, 7, 11, 17, 27, 33, 47, 53, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {
+				-1, 5, 13, 21, 37, 55, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1}, {-1, 9, 23, 41, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, 15, 31, 57, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				19, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, 25, 45, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, 29, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, 39, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, 49, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, }, {{0, 1, 3, 5, 7, 11, 15, 19, 23, 29,
+				35, 43, 47, 53, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1}, {-1, 9, 13, 21, 31, 39, 51,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1}, {-1, 17, 27,
+				37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+				{-1, 25, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1}, {
+						-1, 33, 55, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1}, {-1, 45, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1}, {
+						-1, 49, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1}, {-1, 57, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1}, {
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1}, {-1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1}, {
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1}, {-1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1}, {
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1}, {-1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1}, {
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1}, {-1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1}, {
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1}, {-1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1}, {
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1}, {-1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1}, {
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1}, {-1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1}, {
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1}, {-1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1}, {
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1}, {-1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1, -1,
+						-1, -1, -1, -1, -1, -1, -1}, },
+		{{0, 1, 3, 5, 7, 9, 11, 13, 15, 19, 21, 23, 27, 29, 33, 37, 41,
+				43, 51, 55, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				17, 25, 31, 39, 45, 53, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, 35, 49, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, 47, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				57, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+				-1, -1}, } };
+
+const int UE[64][2] = {{1, 1}, {2, 3}, {3, 3}, {4, 5}, {5, 5}, {6, 5}, {7, 5}, {
+		8, 7}, {9, 7}, {10, 7}, {11, 7}, {12, 7}, {13, 7}, {14, 7}, {15,
+		7}, {16, 9}, {17, 9}, {18, 9}, {19, 9}, {20, 9}, {21, 9},
+		{22, 9}, {23, 9}, {24, 9}, {25, 9}, {26, 9}, {27, 9}, {28, 9}, {
+				29, 9}, {30, 9}, {31, 9}, {32, 11}, {33, 11}, {
+				34, 11}, {35, 11}, {36, 11}, {37, 11}, {38, 11},
+		{39, 11}, {40, 11}, {41, 11}, {42, 11}, {43, 11}, {44, 11}, {45,
+				11}, {46, 11}, {47, 11}, {48, 11}, {49, 11}, {
+				50, 11}, {51, 11}, {52, 11}, {53, 11}, {54, 11},
+		{55, 11}, {56, 11}, {57, 11}, {58, 11}, {59, 11}, {60, 11}, {61,
+				11}, {62, 11}, {63, 11}, {64, 13} };
+
+unsigned int src_start;
+unsigned int des_start;
+
+#ifdef AVSP_LONG_CABAC
+
+unsigned char *es_buf;
+unsigned int es_buf_ptr;
+unsigned int es_buf_is_overflow;
+
+#else
+FILE *f_es;
+#endif
+unsigned int es_ptr;
+unsigned int es_res;
+unsigned int es_res_ptr;
+unsigned int previous_es;
+
+void init_es(void)
+{
+
+#ifdef AVSP_LONG_CABAC
+	es_buf_is_overflow = 0;
+
+	es_buf[0] = 0x00;
+	es_buf[1] = 0x00;
+	es_buf[2] = 0x01;
+	es_buf_ptr = 3;
+	es_ptr = 3;
+#else
+	f_es = fopen("es.out", "wb");
+	if (f_es == NULL)
+		io_printf(" ERROR : Can not open es.out for write\n");
+	putc(0x00, f_es);
+	putc(0x00, f_es);
+	putc(0x01, f_es);
+
+	es_ptr = 3;
+#endif
+	es_res = 0;
+	es_res_ptr = 0;
+	previous_es = 0xff;
+
+}
+
+void push_es(int value, int num)
+{
+	unsigned char wr_es_data;
+	int push_num;
+	int push_value;
+
+#ifdef DUMP_DEBUG
+	if (avs_get_debug_flag() & ES_DUMP)
+		io_printf(" push_es : value : 0x%x, num : %d\n", value, num);
+#endif
+	while (num > 0) {
+		if (num >= 8)
+			push_num = 8;
+		else
+			push_num = num;
+
+		num = num - push_num;
+		push_value = (value >> num);
+
+		es_res = (es_res << push_num) | push_value;
+		es_res_ptr = es_res_ptr + push_num;
+
+#ifdef DUMP_DEBUG
+		if (avs_get_debug_flag() & ES_DUMP)
+			io_printf(" #### es_res : 0x%X, es_res_ptr : %d\n",
+				es_res, es_res_ptr);
+#endif
+
+		while (es_res_ptr >= 8) {
+			es_res_ptr = es_res_ptr & 7;
+			wr_es_data = (es_res >> es_res_ptr) & 0xff;
+			if ((previous_es == 0) & (wr_es_data < 4)) {
+				io_printf(
+						" Insert 2'b10 for emu at position : %d\n",
+						es_ptr);
+
+				es_res_ptr = es_res_ptr + 2;
+				wr_es_data = 2;
+			}
+#ifdef AVSP_LONG_CABAC
+#ifdef DUMP_DEBUG
+			if (avs_get_debug_flag() & ES_DUMP)
+				pr_info("es_buf[%d] = 0x%02x\r\n",
+					es_buf_ptr, wr_es_data);
+#endif
+			if (!es_buf_is_overflow) {
+				es_buf[es_buf_ptr++] = wr_es_data;
+				if (es_buf_ptr >= MAX_CODED_FRAME_SIZE)
+					es_buf_is_overflow = 1;
+			}
+#else
+			putc(wr_es_data, f_es);
+#endif
+			es_ptr++;
+			previous_es = ((previous_es << 8) | wr_es_data)
+					& 0xffff;
+		}
+
+	}
+}
+
+#ifdef BLOCK_SIZE
+#undef BLOCK_SIZE
+#endif
+
+#define MIN_QP          0
+#define MAX_QP          63
+
+#define BLOCK_SIZE      4
+#define B8_SIZE         8
+#define MB_BLOCK_SIZE   16
+
+#define BLOCK_MULTIPLE      (MB_BLOCK_SIZE/(BLOCK_SIZE*2))
+
+#define DECODE_COPY_MB  0
+#define DECODE_MB       1
+
+#define NO_INTRA_PMODE  5
+#define INTRA_PMODE_4x4   10
+#define NO_INTRA_PMODE_4x4	19
+/* 8x8 intra prediction modes */
+#define VERT_PRED             0
+#define HOR_PRED              1
+#define DC_PRED               2
+#define DOWN_LEFT_PRED   3
+#define DOWN_RIGHT_PRED  4
+
+#define VERT_PRED_4x4   0
+#define HOR_PRED_4x4	1
+#define DC_PRED_4x4		2
+#define DOWN_LEFT_PRED_4x4	3
+#define DOWN_RIGHT_PRED_4x4	4
+
+#define HOR_DOWN_PRED_4x4		5
+#define VERT_LEFT_PRED_4x4	6
+#define HOR_UP_PRED_4x4	   7
+#define VERT_RIGHT_PRED_4x4	8
+
+#define DC_PRED_8       0
+#define HOR_PRED_8      1
+#define VERT_PRED_8     2
+#define PLANE_8         3
+
+#define LUMA_16DC       0
+#define LUMA_16AC       1
+#define LUMA_8x8        2
+#define LUMA_8x4        3
+#define LUMA_4x8        4
+#define LUMA_4x4        5
+#define CHROMA_DC       6
+#define CHROMA_AC       7
+#define NUM_BLOCK_TYPES 8
+
+#define I_PICTURE_START_CODE    0xB3
+#define PB_PICTURE_START_CODE   0xB6
+#define SLICE_START_CODE_MIN    0x00
+#define SLICE_START_CODE_MAX    0xAF
+#define USER_DATA_START_CODE    0xB2
+#define SEQUENCE_HEADER_CODE    0xB0
+#define EXTENSION_START_CODE    0xB5
+#define SEQUENCE_END_CODE       0xB1
+#define VIDEO_EDIT_CODE         0xB7
+
+#define EOS             1
+#define SOP             2
+#define SOS             3
+#define P8x8    8
+#define I8MB    9
+#define I4MB   10
+#define IBLOCK  11
+#define SI4MB   12
+#define MAXMODE 13
+
+#define IS_INTRA(MB)    ((MB)->mb_type == I8MB  || (MB)->mb_type == I4MB)
+#define IS_NEWINTRA(MB) ((MB)->mb_type == I4MB)
+#define IS_OLDINTRA(MB) ((MB)->mb_type == I8MB)
+#define IS_INTER(MB)    ((MB)->mb_type != I8MB  && (MB)->mb_type != I4MB)
+#define IS_INTERMV(MB)  ((MB)->mb_type != I8MB  && (MB)->mb_type != I4MB\
+	&& (MB)->mb_type != 0)
+
+#define IS_DIRECT(MB)   ((MB)->mb_type == 0     && (img->type == B_IMG))
+#define IS_COPY(MB)     ((MB)->mb_type == 0     && (img->type == P_IMG))
+#define IS_P8x8(MB)     ((MB)->mb_type == P8x8)
+
+#define P_IMG     0
+#define B_IMG     1
+#define I_IMG     2
+
+#define FIELD     0
+#define FRAME     1
+
+#define SE_CABP    21
+struct decoding_environment_s {
+	unsigned int dbuffer;
+	int dbits_to_go;
+	unsigned char *dcodestrm;
+	int *dcodestrm_len;
+};
+
+struct bi_context_type_s {
+	unsigned char MPS;
+	unsigned int LG_PMPS;
+	unsigned char cycno;
+};
+
+
+/**********************************************************************
+ * C O N T E X T S   F O R   R M   S Y N T A X   E L E M E N T S
+ **********************************************************************
+ */
+
+#define NUM_MB_TYPE_CTX  11
+#define NUM_B8_TYPE_CTX  9
+#define NUM_MV_RES_CTX   10
+#define NUM_REF_NO_CTX   6
+#define NUM_DELTA_QP_CTX 4
+#define NUM_MB_AFF_CTX 4
+
+struct motion_info_contexts_s {
+	struct bi_context_type_s mb_type_contexts[4][NUM_MB_TYPE_CTX];
+	struct bi_context_type_s b8_type_contexts[2][NUM_B8_TYPE_CTX];
+	struct bi_context_type_s mv_res_contexts[2][NUM_MV_RES_CTX];
+	struct bi_context_type_s ref_no_contexts[2][NUM_REF_NO_CTX];
+	struct bi_context_type_s delta_qp_contexts[NUM_DELTA_QP_CTX];
+	struct bi_context_type_s mb_aff_contexts[NUM_MB_AFF_CTX];
+#ifdef TEST_WEIGHTING_AEC
+struct bi_context_type_s mb_weighting_pred;
+#endif
+};
+
+#define NUM_IPR_CTX    2
+#define NUM_CIPR_CTX   4
+#define NUM_CBP_CTX    4
+#define NUM_BCBP_CTX   4
+#define NUM_MAP_CTX   16
+#define NUM_LAST_CTX  16
+
+#define NUM_ONE_CTX    5
+#define NUM_ABS_CTX    5
+
+struct texture_info_contexts {
+	struct bi_context_type_s ipr_contexts[NUM_IPR_CTX];
+	struct bi_context_type_s cipr_contexts[NUM_CIPR_CTX];
+	struct bi_context_type_s cbp_contexts[3][NUM_CBP_CTX];
+	struct bi_context_type_s bcbp_contexts[NUM_BLOCK_TYPES][NUM_BCBP_CTX];
+	struct bi_context_type_s one_contexts[NUM_BLOCK_TYPES][NUM_ONE_CTX];
+	struct bi_context_type_s abs_contexts[NUM_BLOCK_TYPES][NUM_ABS_CTX];
+	struct bi_context_type_s fld_map_contexts[NUM_BLOCK_TYPES][NUM_MAP_CTX];
+	struct bi_context_type_s fld_last_contexts
+	[NUM_BLOCK_TYPES][NUM_LAST_CTX];
+	struct bi_context_type_s map_contexts[NUM_BLOCK_TYPES][NUM_MAP_CTX];
+	struct bi_context_type_s last_contexts[NUM_BLOCK_TYPES][NUM_LAST_CTX];
+};
+struct img_par;
+
+struct syntaxelement {
+	int type;
+	int value1;
+	int value2;
+	int len;
+	int inf;
+	unsigned int bitpattern;
+	int context;
+	int k;
+	int golomb_grad;
+	int golomb_maxlevels;
+#if TRACE
+#define       TRACESTRING_SIZE 100
+	char tracestring[TRACESTRING_SIZE];
+#endif
+
+	void (*mapping)(int len, int info, int *value1, int *value2);
+
+	void (*reading)(struct syntaxelement *, struct img_par *,
+			struct decoding_environment_s *);
+
+};
+
+struct bitstream_s {
+
+	int read_len;
+	int code_len;
+
+	int frame_bitoffset;
+	int bitstream_length;
+
+	unsigned char *stream_buffer;
+};
+
+struct datapartition {
+
+	struct bitstream_s *bitstream;
+	struct decoding_environment_s de_aec;
+
+	int (*read_syntax_element)(struct syntaxelement *, struct img_par *,
+			struct datapartition *);
+/*!< virtual function;
+ * actual method depends on chosen data partition and
+ * entropy coding method
+ */
+};
+
+struct slice_s {
+	int picture_id;
+	int qp;
+	int picture_type;
+	int start_mb_nr;
+	int max_part_nr;
+	int num_mb;
+
+	struct datapartition *part_arr;
+	struct motion_info_contexts_s *mot_ctx;
+	struct texture_info_contexts *tex_ctx;
+	int field_ctx[3][2];
+};
+
+struct img_par {
+	int number;
+	int current_mb_nr;
+	int max_mb_nr;
+	int current_slice_nr;
+	int tr;
+	int qp;
+	int type;
+
+	int typeb;
+
+	int width;
+	int height;
+	int width_cr;
+	int height_cr;
+	int source_bitdepth;
+	int mb_y;
+	int mb_x;
+	int block_y;
+	int pix_y;
+	int pix_x;
+	int pix_c_y;
+	int block_x;
+	int pix_c_x;
+
+	int ***mv;
+	int mpr[16][16];
+
+	int m7[16][16];
+	int m8[/*2*/4][8][8];
+	int cof[4][/*6*/8][4][4];
+	int cofu[4];
+	int **ipredmode;
+	int quad[256];
+	int cod_counter;
+
+	int ***dfmv;
+	int ***dbmv;
+	int **fw_reffrarr;
+	int **bw_reffrarr;
+
+	int ***mv_frm;
+	int **fw_reffrarr_frm;
+	int **bw_reffrarr_frm;
+	int imgtr_next_p;
+	int imgtr_last_p;
+	int tr_frm;
+	int tr_fld;
+	int imgtr_last_prev_p;
+
+	int no_forward_reference;
+	int seq_header_indicate;
+	int b_discard_flag;
+
+	int ***fw_mv;
+	int ***bw_mv;
+	int subblock_x;
+	int subblock_y;
+
+	int buf_cycle;
+
+	int direct_type;
+
+	int ***mv_top;
+	int ***mv_bot;
+	int **fw_reffrarr_top;
+	int **bw_reffrarr_top;
+	int **fw_reffrarr_bot;
+	int **bw_reffrarr_bot;
+
+	int **ipredmode_top;
+	int **ipredmode_bot;
+	int ***fw_mv_top;
+	int ***fw_mv_bot;
+	int ***bw_mv_top;
+	int ***bw_mv_bot;
+	int ***dfmv_top;
+	int ***dbmv_top;
+	int ***dfmv_bot;
+	int ***dbm_bot;
+
+	int toppoc;
+	int bottompoc;
+	int framepoc;
+	unsigned int frame_num;
+
+	unsigned int pic_distance;
+	int delta_pic_order_cnt_bottom;
+
+	signed int pic_distance_msb;
+	unsigned int prev_pic_distance_lsb;
+	signed int curr_pic_distance_msb;
+	unsigned int this_poc;
+
+	int pic_width_inmbs;
+	int pic_height_inmbs;
+	int pic_size_inmbs;
+
+	int block8_x, block8_y;
+	int structure;
+	int pn;
+	int buf_used;
+	int buf_size;
+	int picture_structure;
+	int advanced_pred_mode_disable;
+	int types;
+	int current_mb_nr_fld;
+
+	int p_field_enhanced;
+	int b_field_enhanced;
+
+	int slice_weighting_flag;
+	int lum_scale[4];
+	int lum_shift[4];
+	int chroma_scale[4];
+	int chroma_shift[4];
+	int mb_weighting_flag;
+	int weighting_prediction;
+	int mpr_weight[16][16];
+	int top_bot;
+	int bframe_number;
+
+	int auto_crop_right;
+	int auto_crop_bottom;
+
+	struct slice_s *current_slice;
+	int is_v_block;
+	int is_intra_block;
+
+	int new_seq_header_flag;
+	int new_sequence_flag;
+	int last_pic_bbv_delay;
+
+	int sequence_end_flag;
+	int is_top_field;
+
+	int abt_flag;
+	int qp_shift;
+
+#ifdef EIGHTH
+int eighth_subpixel_flag;
+int subpixel_precision;
+int unit_length;
+int subpixel_mask;
+
+int max_mvd;
+int min_mvd;
+#endif
+
+};
+
+struct macroblock {
+	int qp;
+	int slice_nr;
+	int delta_quant;
+	struct macroblock *mb_available[3][3];
+	/*!< pointer to neighboring MBs in a 3x3 window of current MB,
+	 *which is located at [1][1]
+	 * NULL pointer identifies neighboring MBs which are unavailable
+	 */
+
+	int mb_type;
+	int mvd[2][BLOCK_MULTIPLE][BLOCK_MULTIPLE][2];
+	int cbp, cbp_blk, cbp01;
+	unsigned long cbp_bits;
+
+	int b8mode[4];
+	int b8pdir[4];
+	int mb_type_2;
+	int c_ipred_mode_2;
+	int dct_mode;
+
+	int c_ipred_mode;
+	int lf_disable;
+	int lf_alpha_c0_offset;
+	int lf_beta_offset;
+
+	int CABT[4];
+	int CABP[4];
+	int cbp_4x4[4];
+
+	int skip_flag;
+
+	struct macroblock *mb_available_up;
+	struct macroblock *mb_available_left;
+	unsigned int mbaddr_a, mbaddr_b, mbaddr_c, mbaddr_d;
+	unsigned int mbavail_a, mbavail_b, mbavail_c, mbavail_d;
+
+};
+
+struct macroblock *mb_data;
+
+struct img_par *img;
+
+struct bitstream_s *curr_stream;
+
+struct datapartition *alloc_partition(int n);
+
+unsigned int vld_mem_start_addr;
+unsigned int vld_mem_end_addr;
+
+int marker_bit;
+
+int progressive_sequence;
+int horizontal_size;
+int vertical_size;
+
+int second_ifield;
+int pre_img_type;
+
+/* slice_header() */
+int slice_vertical_position;
+int slice_vertical_position_extension;
+int fixed_picture_qp;
+int fixed_slice_qp;
+int slice_qp;
+
+/*
+ *************************************************************************
+ * Function:ue_v, reads an u(v) syntax element, the length in bits is stored in
+ the global UsedBits variable
+ * Input:
+ tracestring
+ the string for the trace file
+ bitstream
+ the stream to be read from
+ * Output:
+ * Return: the value of the coded syntax element
+ * Attention:
+ *************************************************************************
+ */
+/*!
+ *  definition of AVS syntaxelements
+ *  order of elements follow dependencies for picture reconstruction
+ */
+/*!
+ * \brief   Assignment of old TYPE partition elements to new
+ *          elements
+ *
+ *  old element     | new elements
+ *  TYPE_HEADER     | SE_HEADER, SE_PTYPE
+ *  TYPE_MBHEADER    | SE_MBTYPE, SE_REFFRAME, SE_INTRAPREDMODE
+ *  TYPE_MVD        | SE_MVD
+ *  TYPE_CBP        | SE_CBP_INTRA, SE_CBP_INTER * SE_DELTA_QUANT_INTER
+ *  SE_DELTA_QUANT_INTRA
+ *  TYPE_COEFF_Y    | SE_LUM_DC_INTRA, SE_LUM_AC_INTRA,
+    SE_LUM_DC_INTER, SE_LUM_AC_INTER
+ *  TYPE_2x2DC      | SE_CHR_DC_INTRA, SE_CHR_DC_INTER
+ *  TYPE_COEFF_C    | SE_CHR_AC_INTRA, SE_CHR_AC_INTER
+ *  TYPE_EOS        | SE_EOS
+ */
+
+#define SE_HEADER           0
+#define SE_PTYPE            1
+#define SE_MBTYPE           2
+#define SE_REFFRAME         3
+#define SE_INTRAPREDMODE    4
+#define SE_MVD              5
+#define SE_CBP_INTRA        6
+#define SE_LUM_DC_INTRA     7
+#define SE_CHR_DC_INTRA     8
+#define SE_LUM_AC_INTRA     9
+#define SE_CHR_AC_INTRA     10
+#define SE_CBP_INTER        11
+#define SE_LUM_DC_INTER     12
+#define SE_CHR_DC_INTER     13
+#define SE_LUM_AC_INTER     14
+#define SE_CHR_AC_INTER     15
+#define SE_DELTA_QUANT_INTER      16
+#define SE_DELTA_QUANT_INTRA      17
+#define SE_BFRAME           18
+#define SE_EOS              19
+#define SE_MAX_ELEMENTS     20
+#define SE_CBP01            21
+int chroma_format;
+/*
+ *************************************************************************
+ * Function:Reads bits from the bitstream buffer
+ * Input:
+ byte buffer[]
+ containing VLC-coded data bits
+ int totbitoffset
+ bit offset from start of partition
+ int bytecount
+ total bytes in bitstream
+ int numbits
+ number of bits to read
+ * Output:
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+int get_bits(unsigned char buffer[], int totbitoffset, int *info, int bytecount,
+		int numbits)
+{
+	register int inf;
+	long byteoffset;
+	int bitoffset;
+
+	int bitcounter = numbits;
+
+	byteoffset = totbitoffset / 8;
+	bitoffset = 7 - (totbitoffset % 8);
+
+	inf = 0;
+	while (numbits) {
+		inf <<= 1;
+		inf |= (buffer[byteoffset] & (0x01 << bitoffset)) >> bitoffset;
+		numbits--;
+		bitoffset--;
+		if (bitoffset < 0) {
+			byteoffset++;
+			bitoffset += 8;
+			if (byteoffset > bytecount)
+				return -1;
+		}
+	}
+
+	*info = inf;
+
+
+	return bitcounter;
+}
+
+/*
+ *************************************************************************
+ * Function:read FLC codeword from UVLC-partition
+ * Input:
+ * Output:
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+int read_syntaxelement_flc(struct syntaxelement *sym)
+{
+	int frame_bitoffset = curr_stream->frame_bitoffset;
+	unsigned char *buf = curr_stream->stream_buffer;
+	int bitstreamlengthinbytes = curr_stream->bitstream_length;
+
+	if ((get_bits(buf, frame_bitoffset, &(sym->inf), bitstreamlengthinbytes,
+			sym->len)) < 0)
+		return -1;
+
+	curr_stream->frame_bitoffset += sym->len;
+	sym->value1 = sym->inf;
+
+#if TRACE
+	tracebits2(sym->tracestring, sym->len, sym->inf);
+#endif
+
+	return 1;
+}
+
+/*
+ *************************************************************************
+ * Function:ue_v, reads an u(1) syntax element, the length in bits is stored in
+ the global UsedBits variable
+ * Input:
+ tracestring
+ the string for the trace file
+ bitstream
+ the stream to be read from
+ * Output:
+ * Return: the value of the coded syntax element
+ * Attention:
+ *************************************************************************
+ */
+int u_1(char *tracestring)
+{
+	return u_v(1, tracestring);
+}
+
+/*
+ *************************************************************************
+ * Function:mapping rule for ue(v) syntax elements
+ * Input:length and info
+ * Output:number in the code table
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+void linfo_ue(int len, int info, int *value1, int *dummy)
+{
+	*value1 = (int)pow2(2, (len / 2)) + info - 1;
+}
+
+int u_v(int leninbits, char *tracestring)
+{
+	struct syntaxelement symbol, *sym = &symbol;
+
+#ifdef AVSP_LONG_CABAC
+#else
+	assert(curr_stream->stream_buffer != NULL);
+#endif
+	sym->type = SE_HEADER;
+	sym->mapping = linfo_ue;
+	sym->len = leninbits;
+	read_syntaxelement_flc(sym);
+
+	return sym->inf;
+}
+
+/*
+ *************************************************************************
+ * Function:mapping rule for se(v) syntax elements
+ * Input:length and info
+ * Output:signed mvd
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+void linfo_se(int len, int info, int *value1, int *dummy)
+{
+	int n;
+
+	n = (int)pow2(2, (len / 2)) + info - 1;
+	*value1 = (n + 1) / 2;
+	if ((n & 0x01) == 0)
+		*value1 = -*value1;
+
+}
+
+/*
+ *************************************************************************
+ * Function:length and info
+ * Input:
+ * Output:cbp (intra)
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+void linfo_cbp_intra(int len, int info, int *cbp, int *dummy)
+{
+}
+
+const int NCBP[64][2] = {{4, 0}, {16, 19}, {17, 16}, {19, 15}, {14, 18},
+		{9, 11}, {22, 31}, {8, 13}, {11, 17}, {21, 30}, {10, 12},
+		{7, 9}, {12, 10}, {6, 7}, {5, 8}, {1, 1}, {35, 4}, {47, 42}, {
+				48, 38}, {38, 27}, {46, 39}, {36, 33}, {50, 59},
+		{26, 26}, {45, 40}, {52, 58}, {41, 35}, {28, 25}, {37, 29}, {23,
+				24}, {31, 28}, {2, 3}, {43, 5}, {51, 51}, {56,
+				52}, {39, 37}, {55, 50}, {33, 43}, {62, 63}, {
+				27, 44}, {54, 53}, {60, 62}, {40, 48}, {32, 47},
+		{42, 34}, {24, 45}, {29, 49}, {3, 6}, {49, 14}, {53, 55}, {57,
+				56}, {25, 36}, {58, 54}, {30, 41}, {59, 60}, {
+				15, 21}, {61, 57}, {63, 61}, {44, 46}, {18, 22},
+		{34, 32}, {13, 20}, {20, 23}, {0, 2} };
+
+unsigned int s1, t1, value_s, value_t;
+unsigned char dec_bypass, dec_final;
+
+#define get_byte() {                                         \
+	dbuffer = dcodestrm[(*dcodestrm_len)++];\
+	dbits_to_go = 7;                        \
+}
+
+#define dbuffer         (dep->dbuffer)
+#define dbits_to_go     (dep->dbits_to_go)
+#define dcodestrm       (dep->dcodestrm)
+#define dcodestrm_len   (dep->dcodestrm_len)
+
+#define B_BITS	10
+
+#define LG_PMPS_SHIFTNO 2
+
+#define HALF      (1 << (B_BITS-1))
+#define QUARTER   (1 << (B_BITS-2))
+
+unsigned int biari_decode_symbol(struct decoding_environment_s *dep,
+		struct bi_context_type_s *bi_ct)
+{
+	register unsigned char bit;
+	register unsigned char s_flag;
+	register unsigned char is_lps = 0;
+	register unsigned char cwr;
+	register unsigned char cycno = bi_ct->cycno;
+	register unsigned int lg_pmps = bi_ct->LG_PMPS;
+	register unsigned int t_rlps;
+	register unsigned int s2, t2;
+
+#ifdef DUMP_DEBUG
+	if (avs_get_debug_flag() & AEC_DUMP)
+		io_printf("LG_PMPS : %03X, MPS : %d, cycno : %d -- %p\n",
+			bi_ct->LG_PMPS, bi_ct->MPS, bi_ct->cycno, bi_ct);
+#endif
+
+	bit = bi_ct->MPS;
+
+	cwr = (cycno <= 1) ? 3 : (cycno == 2) ? 4 : 5;
+
+	if (t1 >= (lg_pmps >> LG_PMPS_SHIFTNO)) {
+		s2 = s1;
+		t2 = t1 - (lg_pmps >> LG_PMPS_SHIFTNO);
+		s_flag = 0;
+	} else {
+		s2 = s1 + 1;
+		t2 = 256 + t1 - (lg_pmps >> LG_PMPS_SHIFTNO);
+		s_flag = 1;
+	}
+
+#ifdef DUMP_DEBUG
+	if (avs_get_debug_flag() & AEC_DUMP)
+		io_printf(" s2 : %d, t2 : %03X\n", s2, t2);
+#endif
+
+	if (s2 > value_s || (s2 == value_s && value_t >= t2)) {
+		is_lps = 1;
+		bit = !bit;
+
+		t_rlps = (s_flag == 0) ?
+				(lg_pmps >> LG_PMPS_SHIFTNO) :
+				(t1 + (lg_pmps >> LG_PMPS_SHIFTNO));
+
+		if (s2 == value_s)
+			value_t = (value_t - t2);
+		else {
+			if (--dbits_to_go < 0)
+				get_byte();
+
+			value_t = (value_t << 1)
+					| ((dbuffer >> dbits_to_go) & 0x01);
+			value_t = 256 + value_t - t2;
+
+		}
+
+		while (t_rlps < QUARTER) {
+			t_rlps = t_rlps << 1;
+			if (--dbits_to_go < 0)
+				get_byte();
+
+			value_t = (value_t << 1)
+					| ((dbuffer >> dbits_to_go) & 0x01);
+		}
+
+		s1 = 0;
+		t1 = t_rlps & 0xff;
+
+		value_s = 0;
+		while (value_t < QUARTER) {
+			int j;
+
+			if (--dbits_to_go < 0)
+				get_byte();
+			j = (dbuffer >> dbits_to_go) & 0x01;
+
+			value_t = (value_t << 1) | j;
+			value_s++;
+		}
+		value_t = value_t & 0xff;
+	} else {
+
+		s1 = s2;
+		t1 = t2;
+	}
+
+	if (dec_bypass)
+		return bit;
+
+	if (is_lps)
+		cycno = (cycno <= 2) ? (cycno + 1) : 3;
+	else if (cycno == 0)
+		cycno = 1;
+	bi_ct->cycno = cycno;
+
+	if (is_lps) {
+		switch (cwr) {
+		case 3:
+			lg_pmps = lg_pmps + 197;
+			break;
+		case 4:
+			lg_pmps = lg_pmps + 95;
+			break;
+		default:
+			lg_pmps = lg_pmps + 46;
+		}
+
+		if (lg_pmps >= (256 << LG_PMPS_SHIFTNO)) {
+			lg_pmps = (512 << LG_PMPS_SHIFTNO) - 1 - lg_pmps;
+			bi_ct->MPS = !(bi_ct->MPS);
+		}
+	} else {
+#ifdef DUMP_DEBUG
+		if (avs_get_debug_flag() & AEC_DUMP)
+			io_printf(" - lg_pmps_MPS : %X (%X - %X - %X)\n",
+					lg_pmps - (unsigned int)(lg_pmps>>cwr)
+					- (unsigned int)(lg_pmps>>(cwr+2)),
+					lg_pmps,
+					(unsigned int)(lg_pmps>>cwr),
+					(unsigned int)(lg_pmps>>(cwr+2))
+			);
+#endif
+		lg_pmps = lg_pmps - (unsigned int)(lg_pmps >> cwr)
+				- (unsigned int)(lg_pmps >> (cwr + 2));
+	}
+
+	bi_ct->LG_PMPS = lg_pmps;
+
+	return bit;
+}
+
+unsigned int biari_decode_symbolw(struct decoding_environment_s *dep,
+		struct bi_context_type_s *bi_ct1,
+		struct bi_context_type_s *bi_ct2)
+{
+	register unsigned char bit1, bit2;
+	register unsigned char pred_mps, bit;
+	register unsigned int lg_pmps;
+	register unsigned char cwr1, cycno1 = bi_ct1->cycno;
+	register unsigned char cwr2, cycno2 = bi_ct2->cycno;
+	register unsigned int lg_pmps1 = bi_ct1->LG_PMPS;
+	register unsigned int lg_pmps2 =
+			bi_ct2->LG_PMPS;
+	register unsigned int t_rlps;
+	register unsigned char s_flag, is_lps = 0;
+	register unsigned int s2, t2;
+
+
+	bit1 = bi_ct1->MPS;
+	bit2 = bi_ct2->MPS;
+
+	cwr1 = (cycno1 <= 1) ? 3 : (cycno1 == 2) ? 4 : 5;
+	cwr2 = (cycno2 <= 1) ? 3 : (cycno2 == 2) ? 4 : 5;
+
+	if (bit1 == bit2) {
+		pred_mps = bit1;
+		lg_pmps = (lg_pmps1 + lg_pmps2) / 2;
+	} else {
+		if (lg_pmps1 < lg_pmps2) {
+			pred_mps = bit1;
+			lg_pmps = (256 << LG_PMPS_SHIFTNO) - 1
+					- ((lg_pmps2 - lg_pmps1) >> 1);
+		} else {
+			pred_mps = bit2;
+			lg_pmps = (256 << LG_PMPS_SHIFTNO) - 1
+					- ((lg_pmps1 - lg_pmps2) >> 1);
+		}
+	}
+
+#ifdef DUMP_DEBUG
+	if (avs_get_debug_flag() & AEC_DUMP)
+		io_printf(" - Begin - LG_PMPS : %03X, MPS : %d\n",
+			lg_pmps, pred_mps);
+#endif
+	if (t1 >= (lg_pmps >> LG_PMPS_SHIFTNO)) {
+		s2 = s1;
+		t2 = t1 - (lg_pmps >> LG_PMPS_SHIFTNO);
+		s_flag = 0;
+	} else {
+		s2 = s1 + 1;
+		t2 = 256 + t1 - (lg_pmps >> LG_PMPS_SHIFTNO);
+		s_flag = 1;
+	}
+
+	bit = pred_mps;
+	if (s2 > value_s || (s2 == value_s && value_t >= t2)) {
+		is_lps = 1;
+		bit = !bit;
+		t_rlps = (s_flag == 0) ?
+				(lg_pmps >> LG_PMPS_SHIFTNO) :
+				(t1 + (lg_pmps >> LG_PMPS_SHIFTNO));
+
+		if (s2 == value_s)
+			value_t = (value_t - t2);
+		else {
+			if (--dbits_to_go < 0)
+				get_byte();
+
+			value_t = (value_t << 1)
+					| ((dbuffer >> dbits_to_go) & 0x01);
+			value_t = 256 + value_t - t2;
+		}
+
+		while (t_rlps < QUARTER) {
+			t_rlps = t_rlps << 1;
+			if (--dbits_to_go < 0)
+				get_byte();
+
+			value_t = (value_t << 1)
+					| ((dbuffer >> dbits_to_go) & 0x01);
+		}
+		s1 = 0;
+		t1 = t_rlps & 0xff;
+
+		value_s = 0;
+		while (value_t < QUARTER) {
+			int j;
+
+			if (--dbits_to_go < 0)
+				get_byte();
+			j = (dbuffer >> dbits_to_go) & 0x01;
+
+			value_t = (value_t << 1) | j;
+			value_s++;
+		}
+		value_t = value_t & 0xff;
+	} else {
+		s1 = s2;
+		t1 = t2;
+	}
+
+	if (bit != bit1) {
+		cycno1 = (cycno1 <= 2) ? (cycno1 + 1) : 3;
+	} else {
+		if (cycno1 == 0)
+			cycno1 = 1;
+	}
+
+	if (bit != bit2) {
+		cycno2 = (cycno2 <= 2) ? (cycno2 + 1) : 3;
+	} else {
+		if (cycno2 == 0)
+			cycno2 = 1;
+	}
+	bi_ct1->cycno = cycno1;
+	bi_ct2->cycno = cycno2;
+
+	{
+
+		if (bit == bit1) {
+			lg_pmps1 =
+					lg_pmps1
+				- (unsigned int)(lg_pmps1
+					>> cwr1)
+				- (unsigned int)(lg_pmps1
+					>> (cwr1
+					+ 2));
+		} else {
+			switch (cwr1) {
+			case 3:
+				lg_pmps1 = lg_pmps1 + 197;
+				break;
+			case 4:
+				lg_pmps1 = lg_pmps1 + 95;
+				break;
+			default:
+				lg_pmps1 = lg_pmps1 + 46;
+			}
+
+			if (lg_pmps1 >= (256 << LG_PMPS_SHIFTNO)) {
+				lg_pmps1 = (512 << LG_PMPS_SHIFTNO) - 1
+						- lg_pmps1;
+				bi_ct1->MPS = !(bi_ct1->MPS);
+			}
+		}
+		bi_ct1->LG_PMPS = lg_pmps1;
+
+		if (bit == bit2) {
+			lg_pmps2 =
+					lg_pmps2
+				- (unsigned int)(lg_pmps2
+				>> cwr2)
+				- (unsigned int)(lg_pmps2
+				>> (cwr2
+				+ 2));
+		} else {
+			switch (cwr2) {
+			case 3:
+				lg_pmps2 = lg_pmps2 + 197;
+				break;
+			case 4:
+				lg_pmps2 = lg_pmps2 + 95;
+				break;
+			default:
+				lg_pmps2 = lg_pmps2 + 46;
+			}
+
+			if (lg_pmps2 >= (256 << LG_PMPS_SHIFTNO)) {
+				lg_pmps2 = (512 << LG_PMPS_SHIFTNO) - 1
+						- lg_pmps2;
+				bi_ct2->MPS = !(bi_ct2->MPS);
+			}
+		}
+		bi_ct2->LG_PMPS = lg_pmps2;
+	}
+
+
+	return bit;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    biari_decode_symbol_eq_prob():
+ * \return
+ *    the decoded symbol
+ ************************************************************************
+ */
+unsigned int biari_decode_symbol_eq_prob(struct decoding_environment_s *dep)
+{
+	unsigned char bit;
+	struct bi_context_type_s octx;
+	struct bi_context_type_s *ctx = &octx;
+
+	ctx->LG_PMPS = (QUARTER << LG_PMPS_SHIFTNO) - 1;
+	ctx->MPS = 0;
+	ctx->cycno = 0xfe;
+	dec_bypass = 1;
+	bit = biari_decode_symbol(dep, ctx);
+	dec_bypass = 0;
+	return bit;
+}
+
+unsigned int biari_decode_final(struct decoding_environment_s *dep)
+{
+	unsigned char bit;
+	struct bi_context_type_s octx;
+	struct bi_context_type_s *ctx = &octx;
+
+	ctx->LG_PMPS = 1 << LG_PMPS_SHIFTNO;
+	ctx->MPS = 0;
+	ctx->cycno = 0xff;
+	dec_final = 1;
+	bit = biari_decode_symbol(dep, ctx);
+	dec_final = 0;
+	return bit;
+}
+
+int i_8(char *tracestring)
+{
+	int frame_bitoffset = curr_stream->frame_bitoffset;
+	unsigned char *buf = curr_stream->stream_buffer;
+	int bitstreamlengthinbytes = curr_stream->bitstream_length;
+	struct syntaxelement symbol, *sym = &symbol;
+#ifdef AVSP_LONG_CABAC
+#else
+	assert(curr_stream->stream_buffer != NULL);
+#endif
+
+	sym->len = 8;
+	sym->type = SE_HEADER;
+	sym->mapping = linfo_ue;
+
+	if ((get_bits(buf, frame_bitoffset, &(sym->inf), bitstreamlengthinbytes,
+			sym->len)) < 0)
+		return -1;
+	curr_stream->frame_bitoffset += sym->len;
+	sym->value1 = sym->inf;
+	if (sym->inf & 0x80)
+		sym->inf = -(~((int)0xffffff00 | sym->inf) + 1);
+#if TRACE
+	tracebits2(sym->tracestring, sym->len, sym->inf);
+#endif
+	return sym->inf;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    arideco_bits_read
+ ************************************************************************
+ */
+int arideco_bits_read(struct decoding_environment_s *dep)
+{
+
+	return 8 * ((*dcodestrm_len) - 1) + (8 - dbits_to_go);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    arithmetic decoding
+ ************************************************************************
+ */
+int read_syntaxelement_aec(struct syntaxelement *se, struct img_par *img,
+		struct datapartition *this_data_part)
+{
+	int curr_len;
+	struct decoding_environment_s *dep_dp = &(this_data_part->de_aec);
+
+	curr_len = arideco_bits_read(dep_dp);
+
+	se->reading(se, img, dep_dp);
+
+	se->len = (arideco_bits_read(dep_dp) - curr_len);
+	return se->len;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    This function is used to arithmetically decode the
+ *    run length info of the skip mb
+ ************************************************************************
+ */
+void readrunlenghtfrombuffer_aec(struct syntaxelement *se, struct img_par *img,
+		struct decoding_environment_s *dep_dp)
+{
+	struct bi_context_type_s *pctx;
+	int ctx, symbol;
+
+	pctx = img->current_slice->tex_ctx->one_contexts[0];
+	symbol = 0;
+	ctx = 0;
+	while (biari_decode_symbol(dep_dp, pctx + ctx) == 0) {
+		symbol += 1;
+		ctx++;
+		if (ctx >= 3)
+			ctx = 3;
+	}
+	se->value1 = symbol;
+#if TRACE
+	fprintf(p_trace, "@%d%s\t\t\t%d\n",
+		symbol_count++, se->tracestring, se->value1);
+	fflush(p_trace);
+#endif
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    This function is used to arithmetically decode a pair of
+ *    intra prediction modes of a given MB.
+ ************************************************************************
+ */
+int mapd_intrap[5] = {0, 2, 3, 4, 1};
+void read_intrapredmode_aec(struct syntaxelement *se, struct img_par *img,
+		struct decoding_environment_s *dep_dp)
+{
+	struct bi_context_type_s *pctx;
+	int ctx, symbol;
+
+	pctx = img->current_slice->tex_ctx->one_contexts[1];
+	symbol = 0;
+	ctx = 0;
+#ifdef DUMP_DEBUG
+	if (avs_get_debug_flag() & AEC_DUMP)
+		io_printf(" -- read_intrapredmode_aec ctx : %d\n", ctx);
+#endif
+	while (biari_decode_symbol(dep_dp, pctx + ctx) == 0) {
+		symbol += 1;
+		ctx++;
+		if (ctx >= 3)
+			ctx = 3;
+#ifdef DUMP_DEBUG
+		if (avs_get_debug_flag() & AEC_DUMP)
+			io_printf(" -- read_intrapredmode_aec ctx : %d\n", ctx);
+#endif
+		if (symbol == 4)
+			break;
+		}
+	se->value1 = mapd_intrap[symbol] - 1;
+
+#if TRACE
+	fprintf(p_trace, "@%d %s\t\t\t%d\n",
+		symbol_count++, se->tracestring, se->value1);
+	fflush(p_trace);
+#endif
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    decoding of unary binarization using one or 2 distinct
+ *    models for the first and all remaining bins; no terminating
+ *    "0" for max_symbol
+ ***********************************************************************
+ */
+unsigned int unary_bin_max_decode(struct decoding_environment_s *dep_dp,
+		struct bi_context_type_s *ctx,
+		int ctx_offset, unsigned int max_symbol)
+{
+	unsigned int l;
+	unsigned int symbol;
+	struct bi_context_type_s *ictx;
+
+	symbol = biari_decode_symbol(dep_dp, ctx);
+
+	if (symbol == 0)
+		return 0;
+
+	if (max_symbol == 1)
+		return symbol;
+	symbol = 0;
+	ictx = ctx + ctx_offset;
+	do {
+		l = biari_decode_symbol(dep_dp, ictx);
+		symbol++;
+	} while ((l != 0) && (symbol < max_symbol - 1));
+	if ((l != 0) && (symbol == max_symbol - 1))
+		symbol++;
+	return symbol;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    decoding of unary binarization using one or 2 distinct
+ *    models for the first and all remaining bins
+ ***********************************************************************
+ */
+unsigned int unary_bin_decode(struct decoding_environment_s *dep_dp,
+		struct bi_context_type_s *ctx, int ctx_offset)
+{
+	unsigned int l;
+	unsigned int symbol;
+	struct bi_context_type_s *ictx;
+
+	symbol = 1 - biari_decode_symbol(dep_dp, ctx);
+
+	if (symbol == 0)
+		return 0;
+	symbol = 0;
+	ictx = ctx + ctx_offset;
+	do {
+		l = 1 - biari_decode_symbol(dep_dp, ictx);
+		symbol++;
+	} while (l != 0);
+	return symbol;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    This function is used to arithmetically decode the chroma
+ *    intra prediction mode of a given MB.
+ ************************************************************************
+ */
+void read_cipredmode_aec(struct syntaxelement *se,
+	struct img_par *img,
+		struct decoding_environment_s *dep_dp)
+{
+	struct texture_info_contexts *ctx = img->current_slice->tex_ctx;
+	struct macroblock *curr_mb = &mb_data[img->current_mb_nr];
+	int act_ctx, a, b;
+	int act_sym = se->value1;
+
+	if (curr_mb->mb_available_up == NULL)
+		b = 0;
+	else {
+		/*if ( (curr_mb->mb_available_up)->mb_type==IPCM)
+		 * b=0;
+		 * else
+		 */
+		b = (((curr_mb->mb_available_up)->c_ipred_mode != 0) ? 1 : 0);
+	}
+
+	if (curr_mb->mb_available_left == NULL)
+		a = 0;
+	else {
+		/* if ( (curr_mb->mb_available_left)->mb_type==IPCM)
+		 * a=0;
+		 * else
+		 */
+		a = (((curr_mb->mb_available_left)->c_ipred_mode != 0) ? 1 : 0);
+	}
+
+	act_ctx = a + b;
+
+
+	act_sym = biari_decode_symbol(dep_dp, ctx->cipr_contexts + act_ctx);
+
+	if (act_sym != 0)
+		act_sym = unary_bin_max_decode(dep_dp, ctx->cipr_contexts + 3,
+				0, 2) + 1;
+
+	se->value1 = act_sym;
+
+#if TRACE
+	fprintf(p_trace, "@%d %s\t\t%d\n",
+		symbol_count++, se->tracestring, se->value1);
+	fflush(p_trace);
+#endif
+
+}
+
+int slice_header(char *buf, int startcodepos, int length)
+{
+	int i;
+
+	int weight_para_num = 0;
+	int mb_row;
+	int mb_column;
+	int mb_index;
+	int mb_width, mb_height;
+
+	mb_column = 0;
+
+	memcpy(curr_stream->stream_buffer, buf, length);
+	curr_stream->code_len = curr_stream->bitstream_length = length;
+
+	curr_stream->read_len =
+	curr_stream->frame_bitoffset = (startcodepos) * 8;
+	slice_vertical_position = u_v(8, "slice vertical position");
+
+	push_es(slice_vertical_position, 8);
+
+#ifdef DUMP_DEBUG
+	if (avs_get_debug_flag() & SLICE_INFO_DUMP)
+		io_printf(" * 8-bits slice_vertical_position : %d\n",
+			slice_vertical_position);
+#endif
+
+	if (vertical_size > 2800) {
+		slice_vertical_position_extension = u_v(3,
+				"slice vertical position extension");
+		push_es(slice_vertical_position_extension, 3);
+
+	}
+
+	if (vertical_size > 2800)
+		mb_row = (slice_vertical_position_extension << 7)
+				+ slice_vertical_position;
+	else
+		mb_row = slice_vertical_position;
+
+	mb_width = (horizontal_size + 15) / 16;
+	if (!progressive_sequence)
+		mb_height = 2 * ((vertical_size + 31) / 32);
+	else
+		mb_height = (vertical_size + 15) / 16;
+
+
+	mb_index = mb_row * mb_width + mb_column;
+
+	if (!img->picture_structure && img->type == I_IMG
+			&& (mb_index >= mb_width * mb_height / 2)) {
+		second_ifield = 1;
+		img->type = P_IMG;
+		pre_img_type = P_IMG;
+	}
+
+	{
+		if (!fixed_picture_qp) {
+			fixed_slice_qp = u_v(1, "fixed_slice_qp");
+			push_es(fixed_slice_qp, 1);
+#ifdef DUMP_DEBUG
+			if (avs_get_debug_flag() & SLICE_INFO_DUMP)
+				io_printf(" * 1-bit fixed_slice_qp : %d\n",
+					fixed_slice_qp);
+#endif
+			slice_qp = u_v(6, "slice_qp");
+			push_es(slice_qp, 6);
+#ifdef DUMP_DEBUG
+			if (avs_get_debug_flag() & SLICE_INFO_DUMP)
+				io_printf(" * 6-bits slice_qp : %d\n",
+					slice_qp);
+#endif
+
+			img->qp = slice_qp;
+		}
+
+		if (img->type != I_IMG) {
+			img->slice_weighting_flag = u_v(1,
+					"slice weighting flag");
+
+			if (img->slice_weighting_flag) {
+
+				if (second_ifield && !img->picture_structure)
+					weight_para_num = 1;
+				else if (img->type == P_IMG
+						&& img->picture_structure)
+					weight_para_num = 2;
+				else if (img->type == P_IMG
+						&& !img->picture_structure)
+					weight_para_num = 4;
+				else if (img->type == B_IMG
+						&& img->picture_structure)
+					weight_para_num = 2;
+				else if (img->type == B_IMG
+						&& !img->picture_structure)
+					weight_para_num = 4;
+
+#ifdef DUMP_DEBUG
+				if (avs_get_debug_flag() & SLICE_INFO_DUMP)
+					io_printf(" - weight_para_num : %d\n",
+						weight_para_num);
+#endif
+				for (i = 0; i < weight_para_num; i++) {
+					img->lum_scale[i] = u_v(8,
+							"luma scale");
+
+					img->lum_shift[i] = i_8("luma shift");
+
+					marker_bit = u_1("insert bit");
+
+
+					{
+						img->chroma_scale[i] = u_v(8,
+								"chroma scale");
+
+						img->chroma_shift[i] = i_8(
+								"chroma shift");
+
+						marker_bit = u_1("insert bit");
+
+					}
+				}
+				img->mb_weighting_flag = u_v(1,
+						"MB weighting flag");
+
+			}
+		}
+	}
+
+
+#if 1
+	return mb_index;
+#endif
+}
+
+void no_mem_exit(char *where)
+{
+	io_printf("%s\r\n", where);
+}
+
+unsigned char bit[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
+
+struct inputstream_s {
+	/*FILE *f;*/
+	unsigned char buf[SVA_STREAM_BUF_SIZE];
+	unsigned int uclear_bits;
+	unsigned int upre_3bytes;
+	int ibyte_position;
+	int ibuf_bytesnum;
+	int iclear_bitsnum;
+	int istuff_bitsnum;
+	int ibits_count;
+};
+
+struct inputstream_s IRABS;
+struct inputstream_s *p_irabs = &IRABS;
+
+struct stat_bits {
+	int curr_frame_bits;
+	int prev_frame_bits;
+	int emulate_bits;
+	int prev_emulate_bits;
+	int last_unit_bits;
+	int bitrate;
+	int total_bitrate[1000];
+	int coded_pic_num;
+	int time_s;
+};
+
+struct stat_bits *stat_bits_ptr;
+
+unsigned char *temp_slice_buf;
+int start_codeposition;
+int first_slice_length;
+int first_slice_startpos;
+
+int bitstream_buf_used;
+int startcode_offset;
+
+int bitstream_read_ptr;
+
+int demulate_enable;
+
+int last_dquant;
+
+int total_mb_count;
+
+int current_mb_skip;
+
+int skip_mode_flag;
+
+int current_mb_intra;
+
+/*
+ *************************************************************************
+ * Function: Check start code's type
+ * Input:
+ * Output:
+ * Return:
+ * Author: XZHENG, 20080515
+ *************************************************************************
+ */
+void check_type(int startcode)
+{
+	startcode = startcode & 0x000000ff;
+	switch (startcode) {
+	case 0xb0:
+	case 0xb2:
+	case 0xb5:
+		demulate_enable = 0;
+		break;
+	default:
+		demulate_enable = 1;
+		break;
+	}
+
+}
+/*
+ *************************************************************************
+ * Function:
+ * Input:
+ * Output:
+ * Return:  0 : OK
+ -1 : arrive at stream end
+ -2 : meet another start code
+ * Attention:
+ *************************************************************************
+ */
+int clear_nextbyte(struct inputstream_s *p)
+{
+	int i, k, j;
+	unsigned char temp[3];
+
+	i = p->ibyte_position;
+	k = p->ibuf_bytesnum - i;
+	if (k < 3) {
+		for (j = 0; j < k; j++)
+			temp[j] = p->buf[i + j];
+
+		p->ibuf_bytesnum = read_bitstream(p->buf + k,
+				SVA_STREAM_BUF_SIZE - k);
+		bitstream_buf_used++;
+		if (p->ibuf_bytesnum == 0) {
+			if (k > 0) {
+				while (k > 0) {
+					p->upre_3bytes = ((p->upre_3bytes << 8)
+							| p->buf[i])
+							& 0x00ffffff;
+					if (p->upre_3bytes < 4
+							&& demulate_enable) {
+						p->uclear_bits =
+						(p->uclear_bits
+						<< 6)
+						| (p->buf[i]
+						>> 2);
+						p->iclear_bitsnum += 6;
+						stat_bits_ptr->emulate_bits
+						+= 2;
+					} else {
+						p->uclear_bits = (p->uclear_bits
+						<< 8)
+						| p->buf[i];
+						p->iclear_bitsnum += 8;
+					}
+					p->ibyte_position++;
+					k--;
+					i++;
+				}
+				return 0;
+			} else {
+				return -1;
+			}
+		} else {
+			for (j = 0; j < k; j++)
+				p->buf[j] = temp[j];
+			p->ibuf_bytesnum += k;
+			i = p->ibyte_position = 0;
+		}
+	}
+	if (p->buf[i] == 0 && p->buf[i + 1] == 0 && p->buf[i + 2] == 1)
+		return -2;
+	p->upre_3bytes = ((p->upre_3bytes << 8) | p->buf[i]) & 0x00ffffff;
+	if (p->upre_3bytes < 4 && demulate_enable) {
+		p->uclear_bits = (p->uclear_bits << 6) | (p->buf[i] >> 2);
+		p->iclear_bitsnum += 6;
+		stat_bits_ptr->emulate_bits += 2;
+	} else {
+		p->uclear_bits = (p->uclear_bits << 8) | p->buf[i];
+		p->iclear_bitsnum += 8;
+	}
+	p->ibyte_position++;
+	return 0;
+}
+
+/*
+ *************************************************************************
+ * Function:
+ * Input:
+ * Output:
+ * Return:  0 : OK
+ -1 : arrive at stream end
+ -2 : meet another start code
+ * Attention:
+ *************************************************************************
+ */
+int read_n_bit(struct inputstream_s *p, int n, int *v)
+{
+	int r;
+	unsigned int t;
+
+	while (n > p->iclear_bitsnum) {
+		r = clear_nextbyte(p);
+		if (r) {
+			if (r == -1) {
+				if (p->ibuf_bytesnum - p->ibyte_position > 0)
+					break;
+			}
+			return r;
+		}
+	}
+	t = p->uclear_bits;
+	r = 32 - p->iclear_bitsnum;
+	*v = (t << r) >> (32 - n);
+	p->iclear_bitsnum -= n;
+	return 0;
+}
+
+#ifdef AVSP_LONG_CABAC
+unsigned char TMP_BUF[2 * SVA_STREAM_BUF_SIZE];
+int tmp_buf_wr_ptr;
+int tmp_buf_rd_ptr;
+int tmp_buf_count;
+#endif
+void open_irabs(struct inputstream_s *p)
+{
+	p->uclear_bits = 0xffffffff;
+	p->ibyte_position = 0;
+	p->ibuf_bytesnum = 0;
+	p->iclear_bitsnum = 0;
+	p->istuff_bitsnum = 0;
+	p->ibits_count = 0;
+	p->upre_3bytes = 0;
+
+	bitstream_buf_used = 0;
+	bitstream_read_ptr = (src_start - 16) & 0xfffffff0;
+
+#ifdef AVSP_LONG_CABAC
+	tmp_buf_count = 0;
+	tmp_buf_wr_ptr = 0;
+	tmp_buf_rd_ptr = 0;
+#endif
+
+}
+
+void move_bitstream(unsigned int move_from_addr, unsigned int move_to_addr,
+		int move_size)
+{
+	int move_bytes_left = move_size;
+	unsigned int move_read_addr;
+	unsigned int move_write_addr = move_to_addr;
+
+	int move_byte;
+	unsigned int data32;
+
+	while (move_from_addr > vld_mem_end_addr) {
+		move_from_addr = move_from_addr + vld_mem_start_addr
+				- vld_mem_end_addr - 8;
+	}
+	move_read_addr = move_from_addr;
+	while (move_bytes_left > 0) {
+		move_byte = move_bytes_left;
+		if (move_byte > 512)
+			move_byte = 512;
+		if ((move_read_addr + move_byte) > vld_mem_end_addr)
+			move_byte = (vld_mem_end_addr + 8) - move_read_addr;
+
+		WRITE_VREG(LMEM_DMA_ADR, move_read_addr);
+		WRITE_VREG(LMEM_DMA_COUNT, move_byte / 2);
+		WRITE_VREG(LMEM_DMA_CTRL, 0xc200);
+
+		data32 = 0x8000;
+		while (data32 & 0x8000)
+			data32 = READ_VREG(LMEM_DMA_CTRL);
+
+		WRITE_VREG(LMEM_DMA_ADR, move_write_addr);
+		WRITE_VREG(LMEM_DMA_COUNT, move_byte / 2);
+		WRITE_VREG(LMEM_DMA_CTRL, 0x8200);
+
+		data32 = 0x8000;
+		while (data32 & 0x8000)
+			data32 = READ_VREG(LMEM_DMA_CTRL);
+
+		data32 = 0x0fff;
+		while (data32 & 0x0fff)
+			data32 = READ_VREG(WRRSP_LMEM);
+
+#ifdef DUMP_DEBUG
+		if (avs_get_debug_flag() & STREAM_INFO_DUMP)
+			io_printf("  2 MOVE %d Bytes from 0x%x to 0x%x\n",
+				move_byte, move_read_addr, move_write_addr);
+#endif
+
+		move_read_addr = move_read_addr + move_byte;
+		if (move_read_addr > vld_mem_end_addr)
+			move_read_addr = vld_mem_start_addr;
+		move_write_addr = move_write_addr + move_byte;
+		move_bytes_left = move_bytes_left - move_byte;
+	}
+
+}
+
+int read_bitstream(unsigned char *buf, int size)
+{
+	int i;
+
+#ifdef AVSP_LONG_CABAC
+
+	unsigned int *TMP_BUF_32 = (unsigned int *)bitstream_read_tmp;
+
+	if (tmp_buf_count < size) {
+		dma_sync_single_for_cpu(amports_get_dma_device(),
+				bitstream_read_tmp_phy, SVA_STREAM_BUF_SIZE,
+				DMA_FROM_DEVICE);
+
+		move_bitstream(bitstream_read_ptr, bitstream_read_tmp_phy,
+				SVA_STREAM_BUF_SIZE);
+
+		for (i = 0; i < SVA_STREAM_BUF_SIZE / 8; i++) {
+			TMP_BUF[tmp_buf_wr_ptr++] =
+					(TMP_BUF_32[2 * i + 1] >> 24) & 0xff;
+			if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE))
+				tmp_buf_wr_ptr = 0;
+			TMP_BUF[tmp_buf_wr_ptr++] =
+					(TMP_BUF_32[2 * i + 1] >> 16) & 0xff;
+			if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE))
+				tmp_buf_wr_ptr = 0;
+			TMP_BUF[tmp_buf_wr_ptr++] = (TMP_BUF_32[2 * i + 1] >> 8)
+					& 0xff;
+			if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE))
+				tmp_buf_wr_ptr = 0;
+			TMP_BUF[tmp_buf_wr_ptr++] = (TMP_BUF_32[2 * i + 1] >> 0)
+					& 0xff;
+			if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE))
+				tmp_buf_wr_ptr = 0;
+			TMP_BUF[tmp_buf_wr_ptr++] =
+					(TMP_BUF_32[2 * i + 0] >> 24) & 0xff;
+			if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE))
+				tmp_buf_wr_ptr = 0;
+			TMP_BUF[tmp_buf_wr_ptr++] =
+					(TMP_BUF_32[2 * i + 0] >> 16) & 0xff;
+			if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE))
+				tmp_buf_wr_ptr = 0;
+			TMP_BUF[tmp_buf_wr_ptr++] = (TMP_BUF_32[2 * i + 0] >> 8)
+					& 0xff;
+			if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE))
+				tmp_buf_wr_ptr = 0;
+			TMP_BUF[tmp_buf_wr_ptr++] = (TMP_BUF_32[2 * i + 0] >> 0)
+					& 0xff;
+			if (tmp_buf_wr_ptr >= (2 * SVA_STREAM_BUF_SIZE))
+				tmp_buf_wr_ptr = 0;
+		}
+		tmp_buf_count = tmp_buf_count + SVA_STREAM_BUF_SIZE;
+		bitstream_read_ptr = bitstream_read_ptr + SVA_STREAM_BUF_SIZE;
+	}
+
+#ifdef DUMP_DEBUG
+	if (avs_get_debug_flag() & STREAM_INFO_DUMP)
+		io_printf(" Read %d bytes from %d, size left : %d\n",
+			size, tmp_buf_rd_ptr, tmp_buf_count);
+#endif
+	for (i = 0; i < size; i++) {
+		buf[i] = TMP_BUF[tmp_buf_rd_ptr++];
+		if (tmp_buf_rd_ptr >= (2 * SVA_STREAM_BUF_SIZE))
+			tmp_buf_rd_ptr = 0;
+	}
+	tmp_buf_count = tmp_buf_count - size;
+
+#else
+	for (i = 0; i < size; i++)
+		buf[i] = tmp_stream[bitstream_read_ptr + i];
+	bitstream_read_ptr = bitstream_read_ptr + size;
+#endif
+
+	return size;
+}
+
+int next_startcode(struct inputstream_s *p)
+{
+	int i, m;
+	unsigned char a = 0, b = 0;
+
+	m = 0;
+
+	while (1) {
+		if (p->ibyte_position >= p->ibuf_bytesnum - 2) {
+			m = p->ibuf_bytesnum - p->ibyte_position;
+			if (m < 0)
+				return -2;
+			if (m == 1)
+				b = p->buf[p->ibyte_position + 1];
+			if (m == 2) {
+				b = p->buf[p->ibyte_position + 1];
+				a = p->buf[p->ibyte_position];
+			}
+			p->ibuf_bytesnum = read_bitstream(p->buf,
+					SVA_STREAM_BUF_SIZE);
+			p->ibyte_position = 0;
+			bitstream_buf_used++;
+		}
+
+		if (p->ibuf_bytesnum + m < 3)
+			return -1;
+
+		if (m == 1 && b == 0 && p->buf[0] == 0 && p->buf[1] == 1) {
+			p->ibyte_position = 2;
+			p->iclear_bitsnum = 0;
+			p->istuff_bitsnum = 0;
+			p->ibits_count += 24;
+			p->upre_3bytes = 1;
+			return 0;
+		}
+
+		if (m == 2 && b == 0 && a == 0 && p->buf[0] == 1) {
+			p->ibyte_position = 1;
+			p->iclear_bitsnum = 0;
+			p->istuff_bitsnum = 0;
+			p->ibits_count += 24;
+			p->upre_3bytes = 1;
+			return 0;
+		}
+
+		if (m == 2 && b == 0 && p->buf[0] == 0 && p->buf[1] == 1) {
+			p->ibyte_position = 2;
+			p->iclear_bitsnum = 0;
+			p->istuff_bitsnum = 0;
+			p->ibits_count += 24;
+			p->upre_3bytes = 1;
+			return 0;
+		}
+
+		for (i = p->ibyte_position; i < p->ibuf_bytesnum - 2; i++) {
+			if (p->buf[i] == 0 && p->buf[i + 1] == 0
+					&& p->buf[i + 2] == 1) {
+				p->ibyte_position = i + 3;
+				p->iclear_bitsnum = 0;
+				p->istuff_bitsnum = 0;
+				p->ibits_count += 24;
+				p->upre_3bytes = 1;
+				return 0;
+			}
+			p->ibits_count += 8;
+		}
+		p->ibyte_position = i;
+	}
+}
+
+int get_oneunit(char *buf, int *startcodepos, int *length)
+{
+	int i, j, k;
+
+	i = next_startcode(p_irabs);
+
+	if (i != 0) {
+		if (i == -1)
+			io_printf(
+					"\narrive at stream end and start code is not found!");
+		if (i == -2)
+			io_printf("\np->ibyte_position error!");
+
+	}
+	startcode_offset =
+			p_irabs->ibyte_position
+					- 3 + (bitstream_buf_used-1)
+					* SVA_STREAM_BUF_SIZE;
+	buf[0] = 0;
+	buf[1] = 0;
+	buf[2] = 1;
+	*startcodepos = 3;
+	i = read_n_bit(p_irabs, 8, &j);
+	buf[3] = (char)j;
+
+	check_type(buf[3]);
+	if (buf[3] == SEQUENCE_END_CODE) {
+		*length = 4;
+		return -1;
+	}
+	k = 4;
+	while (1) {
+		i = read_n_bit(p_irabs, 8, &j);
+		if (i < 0)
+			break;
+		buf[k++] = (char)j;
+		if (k >= (MAX_CODED_FRAME_SIZE - 1))
+			break;
+	}
+	if (p_irabs->iclear_bitsnum > 0) {
+		int shift;
+
+		shift = 8 - p_irabs->iclear_bitsnum;
+		i = read_n_bit(p_irabs, p_irabs->iclear_bitsnum, &j);
+
+		if (j != 0)
+			buf[k++] = (char)(j << shift);
+		stat_bits_ptr->last_unit_bits += shift;
+	}
+	*length = k;
+	return k;
+}
+
+/*unsigned char tmp_buf[MAX_CODED_FRAME_SIZE] __attribute__ ((aligned(64)));*/
+/*unsigned char tmp_buf[MAX_CODED_FRAME_SIZE] __aligned(64);*/
+int header(void)
+{
+	unsigned char *buf;
+	int startcodepos, length;
+
+	unsigned char *tmp_buf;
+
+	tmp_buf = (unsigned char *)avsp_heap_adr;
+
+	buf = &tmp_buf[0];
+	while (1) {
+		start_codeposition = get_oneunit(buf, &startcodepos, &length);
+
+		switch (buf[startcodepos]) {
+		case SEQUENCE_HEADER_CODE:
+			io_printf(
+					"# SEQUENCE_HEADER_CODE (0x%02x) found at offset %d (0x%x)\n",
+					buf[startcodepos], startcode_offset,
+					startcode_offset);
+			break;
+		case EXTENSION_START_CODE:
+			io_printf(
+					"# EXTENSION_START_CODE (0x%02x) found at offset %d (0x%x)\n",
+					buf[startcodepos], startcode_offset,
+					startcode_offset);
+			break;
+		case USER_DATA_START_CODE:
+			io_printf(
+					"# USER_DATA_START_CODE (0x%02x) found at offset %d (0x%x)\n",
+					buf[startcodepos], startcode_offset,
+					startcode_offset);
+			break;
+		case VIDEO_EDIT_CODE:
+			io_printf(
+					"# VIDEO_EDIT_CODE (0x%02x) found at offset %d (0x%x)\n",
+					buf[startcodepos], startcode_offset,
+					startcode_offset);
+			break;
+		case I_PICTURE_START_CODE:
+			io_printf(
+					"# I_PICTURE_START_CODE (0x%02x) found at offset %d (0x%x)\n",
+					buf[startcodepos], startcode_offset,
+					startcode_offset);
+			break;
+		case PB_PICTURE_START_CODE:
+			io_printf(
+					"# PB_PICTURE_START_CODE (0x%02x) found at offset %d (0x%x)\n",
+					buf[startcodepos], startcode_offset,
+					startcode_offset);
+			break;
+		case SEQUENCE_END_CODE:
+			io_printf(
+					"# SEQUENCE_END_CODE (0x%02x) found at offset %d (0x%x)\n",
+					buf[startcodepos], startcode_offset,
+					startcode_offset);
+			break;
+		default:
+			io_printf(
+					"# SLICE_START_CODE (0x%02x) found at offset %d (0x%x)\n",
+					buf[startcodepos], startcode_offset,
+					startcode_offset);
+#if 0
+			io_printf("VLD_MEM_VIFIFO_START_PTR %x\r\n",
+					READ_VREG(VLD_MEM_VIFIFO_START_PTR));
+			io_printf("VLD_MEM_VIFIFO_CURR_PTR %x\r\n",
+					READ_VREG(VLD_MEM_VIFIFO_CURR_PTR));
+			io_printf("VLD_MEM_VIFIFO_END_PTR %x\r\n",
+					READ_VREG(VLD_MEM_VIFIFO_END_PTR));
+			io_printf("VLD_MEM_VIFIFO_WP %x\r\n"
+					READ_VREG(VLD_MEM_VIFIFO_WP));
+			io_printf("VLD_MEM_VIFIFO_RP %x\r\n",
+					READ_VREG(VLD_MEM_VIFIFO_RP));
+			io_printf("VLD_MEM_VBUF_RD_PTR %x\r\n"
+					READ_VREG(VLD_MEM_VBUF_RD_PTR));
+			io_printf("VLD_MEM_VIFIFO_BUF_CNTL %x\r\n",
+					READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL));
+			io_printf("PARSER_VIDEO_HOLE %x\r\n",
+					READ_MPEG_REG(PARSER_VIDEO_HOLE));
+#endif
+			if ((buf[startcodepos] >= SLICE_START_CODE_MIN
+				&& buf[startcodepos]
+				<= SLICE_START_CODE_MAX)
+				&& ((!img->seq_header_indicate)
+				|| (img->type == B_IMG
+				&& img->b_discard_flag
+				== 1
+				&& !img->no_forward_reference))) {
+				break;
+			} else if (buf[startcodepos] >= SLICE_START_CODE_MIN) {
+
+				first_slice_length = length;
+				first_slice_startpos = startcodepos;
+
+				temp_slice_buf = &tmp_buf[0];
+				return SOP;
+			} else {
+				io_printf("Can't find start code");
+				return -EOS;
+			}
+		}
+	}
+
+}
+
+/*
+ *************************************************************************
+ * Function:Allocates a Bitstream
+ * Input:
+ * Output:allocated Bitstream point
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+struct bitstream_s *alloc_bitstream(void)
+{
+	struct bitstream_s *bitstream;
+
+	bitstream = (struct bitstream_s *)local_alloc(1,
+		sizeof(struct bitstream_s));
+	if (bitstream == NULL) {
+		io_printf(
+			"AllocBitstream: Memory allocation for Bitstream failed");
+		return NULL;
+	}
+	bitstream->stream_buffer = (unsigned char *)local_alloc(
+			MAX_CODED_FRAME_SIZE,
+			sizeof(unsigned char));
+	if (bitstream->stream_buffer == NULL) {
+		io_printf(
+				"AllocBitstream: Memory allocation for streamBuffer failed");
+		return NULL;
+	}
+
+	return bitstream;
+}
+
+void biari_init_context_logac(struct bi_context_type_s *ctx)
+{
+	ctx->LG_PMPS = (QUARTER << LG_PMPS_SHIFTNO) - 1;
+	ctx->MPS = 0;
+	ctx->cycno = 0;
+}
+
+#define BIARI_CTX_INIT1_LOG(jj, ctx)\
+{\
+	for (j = 0; j < jj; j++)\
+		biari_init_context_logac(&(ctx[j]));\
+}
+
+#define BIARI_CTX_INIT2_LOG(ii, jj, ctx)\
+{\
+	for (i = 0; i < ii; i++)\
+		for (j = 0; j < jj; j++)\
+			biari_init_context_logac(&(ctx[i][j]));\
+}
+
+#define BIARI_CTX_INIT3_LOG(ii, jj, kk, ctx)\
+{\
+	for (i = 0; i < ii; i++)\
+		for (j = 0; j < jj; j++)\
+			for (k = 0; k < kk; k++)\
+				biari_init_context_logac(&(ctx[i][j][k]));\
+}
+
+#define BIARI_CTX_INIT4_LOG(ii, jj, kk, ll, ctx)\
+{\
+	for (i = 0; i < ii; i++)\
+		for (j = 0; j < jj; j++)\
+			for (k = 0; k < kk; k++)\
+				for (l = 0; l < ll; l++)\
+					biari_init_context_logac\
+					(&(ctx[i][j][k][l]));\
+}
+
+void init_contexts(struct img_par *img)
+{
+	struct motion_info_contexts_s *mc = img->current_slice->mot_ctx;
+	struct texture_info_contexts *tc = img->current_slice->tex_ctx;
+	int i, j;
+
+#ifdef DUMP_DEBUG
+	if (avs_get_debug_flag() & SLICE_INFO_DUMP)
+		io_printf(" ---- init_contexts ----\n");
+#endif
+
+	BIARI_CTX_INIT2_LOG(3, NUM_MB_TYPE_CTX, mc->mb_type_contexts);
+	BIARI_CTX_INIT2_LOG(2, NUM_B8_TYPE_CTX, mc->b8_type_contexts);
+	BIARI_CTX_INIT2_LOG(2, NUM_MV_RES_CTX, mc->mv_res_contexts);
+	BIARI_CTX_INIT2_LOG(2, NUM_REF_NO_CTX, mc->ref_no_contexts);
+	BIARI_CTX_INIT1_LOG(NUM_DELTA_QP_CTX, mc->delta_qp_contexts);
+	BIARI_CTX_INIT1_LOG(NUM_MB_AFF_CTX, mc->mb_aff_contexts);
+
+	BIARI_CTX_INIT1_LOG(NUM_IPR_CTX, tc->ipr_contexts);
+	BIARI_CTX_INIT1_LOG(NUM_CIPR_CTX, tc->cipr_contexts);
+	BIARI_CTX_INIT2_LOG(3, NUM_CBP_CTX, tc->cbp_contexts);
+	BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_BCBP_CTX, tc->bcbp_contexts);
+	BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_ONE_CTX, tc->one_contexts);
+	BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_ABS_CTX, tc->abs_contexts);
+	BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_MAP_CTX, tc->fld_map_contexts);
+	BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_LAST_CTX,
+			tc->fld_last_contexts);
+	BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_MAP_CTX, tc->map_contexts);
+	BIARI_CTX_INIT2_LOG(NUM_BLOCK_TYPES, NUM_LAST_CTX, tc->last_contexts);
+#ifdef TEST_WEIGHTING_AEC
+	biari_init_context_logac(&mc->mb_weighting_pred);
+#endif
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Allocation of contexts models for the motion info
+ *    used for arithmetic decoding
+ *
+ ************************************************************************
+ */
+struct motion_info_contexts_s *create_contexts_motioninfo(void)
+{
+	struct motion_info_contexts_s *deco_ctx;
+
+	deco_ctx = (struct motion_info_contexts_s *)local_alloc(1,
+			sizeof(struct motion_info_contexts_s));
+	if (deco_ctx == NULL)
+		no_mem_exit("create_contexts_motioninfo: deco_ctx");
+
+	return deco_ctx;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Allocates of contexts models for the texture info
+ *    used for arithmetic decoding
+ ************************************************************************
+ */
+struct texture_info_contexts *create_contexts_textureinfo(void)
+{
+	struct texture_info_contexts *deco_ctx;
+
+	deco_ctx = (struct texture_info_contexts *)local_alloc(1,
+			sizeof(struct texture_info_contexts));
+	if (deco_ctx == NULL)
+		no_mem_exit("create_contexts_textureinfo: deco_ctx");
+
+	return deco_ctx;
+}
+
+struct datapartition *alloc_partition(int n)
+{
+	struct datapartition *part_arr, *datapart;
+	int i;
+
+	part_arr =
+	(struct datapartition *)local_alloc(n, sizeof(struct datapartition));
+	if (part_arr == NULL) {
+		no_mem_exit(
+				"alloc_partition: Memory allocation for Data Partition failed");
+		return NULL;
+	}
+
+#if LIWR_FIX
+	part_arr[0].bitstream = NULL;
+#else
+	for (i = 0; i < n; i++) {
+		datapart = &(part_arr[i]);
+		datapart->bitstream = (struct bitstream_s *)local_alloc(1,
+				sizeof(struct bitstream_s));
+		if (datapart->bitstream == NULL) {
+			no_mem_exit(
+					"alloc_partition: Memory allocation for Bitstream failed");
+			return NULL;
+		}
+	}
+#endif
+	return part_arr;
+}
+
+int malloc_slice(struct img_par *img)
+{
+	struct slice_s *currslice;
+
+	img->current_slice =
+	(struct slice_s *)local_alloc(1, sizeof(struct slice_s));
+	currslice = img->current_slice;
+	if (currslice == NULL) {
+		no_mem_exit(
+			"Memory allocation for struct slice_s datastruct Failed"
+			);
+		return 0;
+	}
+	if (1) {
+
+		currslice->mot_ctx = create_contexts_motioninfo();
+		if (currslice->mot_ctx == NULL)
+			return 0;
+
+		currslice->tex_ctx = create_contexts_textureinfo();
+		if (currslice->tex_ctx == NULL)
+			return 0;
+	}
+#if LIWR_FIX
+	currslice->max_part_nr = 1;
+#else
+	currslice->max_part_nr = 3;
+#endif
+	currslice->part_arr = alloc_partition(currslice->max_part_nr);
+	if (currslice->part_arr == NULL)
+		return 0;
+	return 1;
+}
+
+void init(struct img_par *img)
+{
+	int i;
+
+	for (i = 0; i < 256; i++)
+		img->quad[i] = i * i;
+}
+
+/*
+ *************************************************************************
+ * Function:Allocate 2D memory array -> int array2D[rows][columns]
+ * Input:
+ * Output: memory size in bytes
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+int get_mem2Dint(int ***array2D, int rows, int columns)
+{
+	int i;
+
+	*array2D = (int **)local_alloc(rows, sizeof(int *));
+	if (*array2D == NULL) {
+		no_mem_exit("get_mem2Dint: array2D");
+		return -1;
+	}
+	(*array2D)[0] = (int *)local_alloc(rows * columns, sizeof(int));
+	if ((*array2D)[0] == NULL) {
+		no_mem_exit("get_mem2Dint: array2D");
+		return -1;
+	}
+
+	for (i = 1; i < rows; i++)
+		(*array2D)[i] = (*array2D)[i - 1] + columns;
+
+	return rows * columns * sizeof(int);
+}
+
+int initial_decode(void)
+{
+	int i, j;
+	int ret;
+	int img_height = (vertical_size + img->auto_crop_bottom);
+	int memory_size = 0;
+
+	ret = malloc_slice(img);
+	if (ret == 0)
+		return 0;
+
+	mb_data = (struct macroblock *)local_alloc(
+			(img->width / MB_BLOCK_SIZE)
+			* (img_height /*vertical_size*/
+			/ MB_BLOCK_SIZE), sizeof(struct macroblock));
+	if (mb_data == NULL) {
+		no_mem_exit("init_global_buffers: mb_data");
+		return 0;
+	}
+
+	if (progressive_sequence) {
+		int size;
+		size = get_mem2Dint(&(img->ipredmode),
+				img->width / B8_SIZE * 2 + 4,
+				vertical_size / B8_SIZE * 2 + 4);
+		if (size == -1)
+			return 0;
+
+		memory_size += size;
+	} else {
+		int size;
+		size = get_mem2Dint(&(img->ipredmode),
+				img->width / B8_SIZE * 2 + 4,
+				(vertical_size + 32) / (2 * B8_SIZE) * 4 + 4);
+		if (size == -1)
+			return 0;
+
+		memory_size += size;
+	}
+
+	for (i = 0; i < img->width / (B8_SIZE) * 2 + 4; i++) {
+		for (j = 0; j < img->height / (B8_SIZE) * 2 + 4; j++)
+			img->ipredmode[i][j] = -1;
+	}
+
+	init(img);
+	img->number = 0;
+	img->type = I_IMG;
+	img->imgtr_last_p = 0;
+	img->imgtr_next_p = 0;
+
+	img->new_seq_header_flag = 1;
+	img->new_sequence_flag = 1;
+
+	return 1;
+}
+
+void aec_new_slice(void)
+{
+	last_dquant = 0;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Initializes the DecodingEnvironment for the arithmetic coder
+ ************************************************************************
+ */
+
+void arideco_start_decoding(struct decoding_environment_s *dep,
+	unsigned char *cpixcode,
+		int firstbyte, int *cpixcode_len, int slice_type)
+{
+
+	dcodestrm = cpixcode;
+	dcodestrm_len = cpixcode_len;
+	*dcodestrm_len = firstbyte;
+
+	s1 = 0;
+	t1 = QUARTER - 1;
+	value_s = 0;
+
+	value_t = 0;
+
+	{
+		int i;
+
+		dbits_to_go = 0;
+		for (i = 0; i < B_BITS - 1; i++) {
+			if (--dbits_to_go < 0)
+				get_byte();
+
+			value_t = (value_t << 1)
+					| ((dbuffer >> dbits_to_go) & 0x01);
+		}
+	}
+
+	while (value_t < QUARTER) {
+		if (--dbits_to_go < 0)
+			get_byte();
+
+		value_t = (value_t << 1) | ((dbuffer >> dbits_to_go) & 0x01);
+		value_s++;
+	}
+	value_t = value_t & 0xff;
+
+	dec_final = dec_bypass = 0;
+
+
+
+}
+
+/*
+ *************************************************************************
+ * Function:Checks the availability of neighboring macroblocks of
+ the current macroblock for prediction and context determination;
+ marks the unavailable MBs for intra prediction in the
+ ipredmode-array by -1. Only neighboring MBs in the causal
+ past of the current MB are checked.
+ * Input:
+ * Output:
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+void checkavailabilityofneighbors(struct img_par *img)
+{
+	int i, j;
+	const int mb_width = img->width / MB_BLOCK_SIZE;
+	const int mb_nr = img->current_mb_nr;
+	struct macroblock *curr_mb = &mb_data[mb_nr];
+	int check_value;
+	int remove_prediction;
+
+	curr_mb->mb_available_up = NULL;
+	curr_mb->mb_available_left = NULL;
+
+	for (i = 0; i < 3; i++)
+		for (j = 0; j < 3; j++)
+			mb_data[mb_nr].mb_available[i][j] = NULL;
+
+	mb_data[mb_nr].mb_available[1][1] = curr_mb;
+
+	if (img->pix_x >= MB_BLOCK_SIZE) {
+		remove_prediction = curr_mb->slice_nr
+				!= mb_data[mb_nr - 1].slice_nr;
+
+		if (remove_prediction)
+
+		{
+
+			img->ipredmode[(img->block_x + 1) * 2 - 1][(img->block_y
+					+ 1) * 2] = -1;
+			img->ipredmode[(img->block_x + 1) * 2 - 1][(img->block_y
+					+ 1) * 2 + 1] = -1;
+			img->ipredmode[(img->block_x + 1) * 2 - 1][(img->block_y
+					+ 2) * 2] = -1;
+			img->ipredmode[(img->block_x + 1) * 2 - 1][(img->block_y
+					+ 2) * 2 + 1] = -1;
+		}
+		if (!remove_prediction)
+			curr_mb->mb_available[1][0] = &(mb_data[mb_nr - 1]);
+
+	}
+
+	check_value = (img->pix_y >= MB_BLOCK_SIZE);
+	if (check_value) {
+		remove_prediction = curr_mb->slice_nr
+				!= mb_data[mb_nr - mb_width].slice_nr;
+
+		if (remove_prediction) {
+			img->ipredmode
+			[(img->block_x + 1) * 2][(img->block_y + 1)
+					* 2 - 1] = -1;
+			img->ipredmode[(img->block_x + 1) * 2 + 1][(img->block_y
+					+ 1) * 2 - 1] = -1;
+			img->ipredmode[(img->block_x + 1) * 2 + 2][(img->block_y
+					+ 1) * 2 - 1] = -1;
+			img->ipredmode[(img->block_x + 1) * 2 + 3][(img->block_y
+					+ 1) * 2 - 1] = -1;
+		}
+
+		if (!remove_prediction) {
+			curr_mb->mb_available[0][1] =
+					&(mb_data[mb_nr - mb_width]);
+		}
+	}
+
+	if (img->pix_y >= MB_BLOCK_SIZE && img->pix_x >= MB_BLOCK_SIZE) {
+		remove_prediction = curr_mb->slice_nr
+				!= mb_data[mb_nr - mb_width - 1].slice_nr;
+
+		if (remove_prediction) {
+			img->ipredmode[img->block_x * 2 + 1][img->block_y * 2
+					+ 1] = -1;
+		}
+		if (!remove_prediction) {
+			curr_mb->mb_available[0][0] = &(mb_data[mb_nr - mb_width
+					- 1]);
+		}
+	}
+
+	if (img->pix_y >= MB_BLOCK_SIZE
+			&& img->pix_x < (img->width - MB_BLOCK_SIZE)) {
+		if (curr_mb->slice_nr == mb_data[mb_nr - mb_width + 1].slice_nr)
+			curr_mb->mb_available[0][2] = &(mb_data[mb_nr - mb_width
+					+ 1]);
+	}
+
+	if (1) {
+		curr_mb->mbaddr_a = mb_nr - 1;
+		curr_mb->mbaddr_b = mb_nr - img->pic_width_inmbs;
+		curr_mb->mbaddr_c = mb_nr - img->pic_width_inmbs + 1;
+		curr_mb->mbaddr_d = mb_nr - img->pic_width_inmbs - 1;
+
+		curr_mb->mbavail_a =
+		(curr_mb->mb_available[1][0] != NULL) ? 1 : 0;
+		curr_mb->mbavail_b =
+		(curr_mb->mb_available[0][1] != NULL) ? 1 : 0;
+		curr_mb->mbavail_c =
+		(curr_mb->mb_available[0][2] != NULL) ? 1 : 0;
+		curr_mb->mbavail_d =
+		(curr_mb->mb_available[0][0] != NULL) ? 1 : 0;
+
+	}
+
+}
+
+void checkavailabilityofneighborsaec(void)
+{
+
+	int i, j;
+	const int mb_width = img->width / MB_BLOCK_SIZE;
+	const int mb_nr = img->current_mb_nr;
+	struct macroblock *curr_mb = &(mb_data[mb_nr]);
+	int check_value;
+
+	for (i = 0; i < 3; i++)
+		for (j = 0; j < 3; j++)
+			mb_data[mb_nr].mb_available[i][j] = NULL;
+	mb_data[mb_nr].mb_available[1][1] = &(mb_data[mb_nr]);
+
+	if (img->pix_x >= MB_BLOCK_SIZE) {
+		int remove_prediction = curr_mb->slice_nr
+				!= mb_data[mb_nr - 1].slice_nr;
+		if (!remove_prediction)
+			curr_mb->mb_available[1][0] = &(mb_data[mb_nr - 1]);
+	}
+
+	check_value = (img->pix_y >= MB_BLOCK_SIZE);
+	if (check_value) {
+		int remove_prediction = curr_mb->slice_nr
+				!= mb_data[mb_nr - mb_width].slice_nr;
+
+		if (!remove_prediction) {
+			curr_mb->mb_available[0][1] =
+					&(mb_data[mb_nr - mb_width]);
+		}
+	}
+
+	if (img->pix_y >= MB_BLOCK_SIZE && img->pix_x >= MB_BLOCK_SIZE) {
+		int remove_prediction = curr_mb->slice_nr
+				!= mb_data[mb_nr - mb_width - 1].slice_nr;
+		if (!remove_prediction) {
+			curr_mb->mb_available[0][0] = &(mb_data[mb_nr - mb_width
+					- 1]);
+		}
+	}
+
+	if (img->pix_y >= MB_BLOCK_SIZE
+			&& img->pix_x < (img->width - MB_BLOCK_SIZE)) {
+		if (curr_mb->slice_nr == mb_data[mb_nr - mb_width + 1].slice_nr)
+			curr_mb->mb_available[0][2] = &(mb_data[mb_nr - mb_width
+					+ 1]);
+	}
+	curr_mb->mb_available_left = curr_mb->mb_available[1][0];
+	curr_mb->mb_available_up = curr_mb->mb_available[0][1];
+	curr_mb->mbaddr_a = mb_nr - 1;
+	curr_mb->mbaddr_b = mb_nr - img->pic_width_inmbs;
+	curr_mb->mbaddr_c = mb_nr - img->pic_width_inmbs + 1;
+	curr_mb->mbaddr_d = mb_nr - img->pic_width_inmbs - 1;
+
+	curr_mb->mbavail_a = (curr_mb->mb_available[1][0] != NULL) ? 1 : 0;
+	curr_mb->mbavail_b = (curr_mb->mb_available[0][1] != NULL) ? 1 : 0;
+	curr_mb->mbavail_c = (curr_mb->mb_available[0][2] != NULL) ? 1 : 0;
+	curr_mb->mbavail_d = (curr_mb->mb_available[0][0] != NULL) ? 1 : 0;
+}
+
+/*
+ *************************************************************************
+ * Function:initializes the current macroblock
+ * Input:
+ * Output:
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+void start_macroblock(struct img_par *img)
+{
+	int i, j, k, l;
+	struct macroblock *curr_mb;
+
+#ifdef AVSP_LONG_CABAC
+#else
+
+#endif
+
+	curr_mb = &mb_data[img->current_mb_nr];
+
+	/* Update coordinates of the current macroblock */
+	img->mb_x = (img->current_mb_nr) % (img->width / MB_BLOCK_SIZE);
+	img->mb_y = (img->current_mb_nr) / (img->width / MB_BLOCK_SIZE);
+
+#ifdef DUMP_DEBUG
+	if (avs_get_debug_flag() & MB_NUM_DUMP)
+		io_printf(" #Begin MB : %d, (%x, %x) es_ptr %d\n",
+			img->current_mb_nr, img->mb_x, img->mb_y, es_ptr);
+#endif
+
+
+	total_mb_count = total_mb_count + 1;
+
+	/* Define vertical positions */
+	img->block_y = img->mb_y * BLOCK_SIZE / 2; /* luma block position */
+	img->block8_y = img->mb_y * BLOCK_SIZE / 2;
+	img->pix_y = img->mb_y * MB_BLOCK_SIZE; /* luma macroblock position */
+	if (chroma_format == 2)
+		img->pix_c_y = img->mb_y *
+		MB_BLOCK_SIZE; /* chroma macroblock position */
+	else
+		img->pix_c_y = img->mb_y *
+		MB_BLOCK_SIZE / 2; /* chroma macroblock position */
+
+	/* Define horizontal positions */
+	img->block_x = img->mb_x * BLOCK_SIZE / 2; /* luma block position */
+	img->block8_x = img->mb_x * BLOCK_SIZE / 2;
+	img->pix_x = img->mb_x * MB_BLOCK_SIZE; /* luma pixel position */
+	img->pix_c_x = img->mb_x *
+	MB_BLOCK_SIZE / 2; /* chroma pixel position */
+
+	checkavailabilityofneighbors(img);
+
+	/*<!*******EDIT START BY lzhang ******************/
+
+	if (1)
+		checkavailabilityofneighborsaec();
+	/*<!*******EDIT end BY lzhang ******************/
+
+	curr_mb->qp = img->qp;
+	curr_mb->mb_type = 0;
+	curr_mb->delta_quant = 0;
+	curr_mb->cbp = 0;
+	curr_mb->cbp_blk = 0;
+	curr_mb->c_ipred_mode = DC_PRED_8;
+	curr_mb->c_ipred_mode_2 = DC_PRED_8;
+
+	for (l = 0; l < 2; l++)
+		for (j = 0; j < BLOCK_MULTIPLE; j++)
+			for (i = 0; i < BLOCK_MULTIPLE; i++)
+				for (k = 0; k < 2; k++)
+					curr_mb->mvd[l][j][i][k] = 0;
+
+	curr_mb->cbp_bits = 0;
+
+	for (j = 0; j < MB_BLOCK_SIZE; j++)
+		for (i = 0; i < MB_BLOCK_SIZE; i++)
+			img->m7[i][j] = 0;
+
+	for (j = 0; j < 2 * BLOCK_SIZE; j++)
+		for (i = 0; i < 2 * BLOCK_SIZE; i++) {
+			img->m8[0][i][j] = 0;
+			img->m8[1][i][j] = 0;
+			img->m8[2][i][j] = 0;
+			img->m8[3][i][j] = 0;
+		}
+
+	curr_mb->lf_disable = 1;
+
+	img->weighting_prediction = 0;
+}
+
+/*
+ *************************************************************************
+ * Function:init macroblock I and P frames
+ * Input:
+ * Output:
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+void init_macroblock(struct img_par *img)
+{
+	int i, j;
+
+
+	for (i = 0; i < 4; i++) {
+		for (j = 0; j < 4; j++) {
+			img->ipredmode[img->block_x * 2 + i + 2][img->block_y
+					* 2 + j + 2] = -1;
+		}
+	}
+
+}
+
+/*
+ *************************************************************************
+ * Function:Interpret the mb mode for I-Frames
+ * Input:
+ * Output:
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+void interpret_mb_mode_i(struct img_par *img)
+{
+	int i;
+
+	struct macroblock *curr_mb = &mb_data[img->current_mb_nr];
+	int num = 4;
+
+	curr_mb->mb_type = I8MB;
+
+
+	current_mb_intra = 1;
+
+	for (i = 0; i < 4; i++) {
+		curr_mb->b8mode[i] = IBLOCK;
+		curr_mb->b8pdir[i] = -1;
+	}
+
+	for (i = num; i < 4; i++) {
+		curr_mb->b8mode[i] =
+				curr_mb->mb_type_2 == P8x8 ?
+						4 : curr_mb->mb_type_2;
+		curr_mb->b8pdir[i] = 0;
+	}
+}
+
+const int pred_4x4[9][9] = {{0, 0, 0, 0, 0, 0, 0, 0, 0}, {1, 1, 1, 1, 1, 1, 1,
+		1, 1}, {0, 1, 2, 3, 4, 5, 6, 7, 8}, {0, 0, 0, 3, 3, 3, 3, 3, 3},
+		{0, 1, 4, 4, 4, 4, 4, 4, 4}, {0, 1, 5, 5, 5, 5, 5, 5, 5}, {0, 0,
+				0, 0, 0, 0, 6, 0, 0},
+		{0, 1, 7, 7, 7, 7, 7, 7, 7}, {0, 0, 0, 0, 4, 5, 6, 7, 8}
+
+};
+
+const int pred_4x4to8x8[9] = {0, 1, 2, 3, 4, 1, 0, 1, 0
+
+};
+
+const int pred_8x8to4x4[5] = {0, 1, 2, 3, 4};
+
+void read_ipred_block_modes(struct img_par *img, int b8)
+{
+	int bi, bj, dec;
+	struct syntaxelement curr_se;
+	struct macroblock *curr_mb;
+	int j2;
+	int mostprobableintrapredmode;
+	int upintrapredmode;
+	int uprightintrapredmode;
+	int leftintrapredmode;
+	int leftdownintrapredmode;
+	int intrachromapredmodeflag;
+
+	struct slice_s *currslice = img->current_slice;
+	struct datapartition *dp;
+
+	curr_mb = mb_data + img->current_mb_nr;
+	intrachromapredmodeflag = IS_INTRA(curr_mb);
+
+	curr_se.type = SE_INTRAPREDMODE;
+#if TRACE
+	strncpy(curr_se.tracestring, "Ipred Mode", TRACESTRING_SIZE);
+#endif
+
+	if (b8 < 4) {
+		if (curr_mb->b8mode[b8] == IBLOCK) {
+			intrachromapredmodeflag = 1;
+
+			if (1) {
+				dp = &(currslice->part_arr[0]);
+				curr_se.reading = read_intrapredmode_aec;
+				dp->read_syntax_element(&curr_se, img, dp);
+
+				if (curr_se.value1 == -1)
+					push_es(1, 1);
+				else
+					push_es(curr_se.value1, 3);
+
+
+			}
+			bi = img->block_x + (b8 & 1);
+			bj = img->block_y + (b8 / 2);
+
+			upintrapredmode = img->ipredmode[(bi + 1) * 2][(bj) * 2
+					+ 1];
+			uprightintrapredmode =
+					img->ipredmode[(bi + 1) * 2 + 1][(bj)
+							* 2 + 1];
+			leftintrapredmode =
+					img->ipredmode[(bi) * 2 + 1][(bj + 1)
+							* 2];
+			leftdownintrapredmode = img->ipredmode[(bi) * 2 + 1][(bj
+					+ 1) * 2 + 1];
+
+			if ((upintrapredmode < 0) || (leftintrapredmode < 0)) {
+				mostprobableintrapredmode = DC_PRED;
+			} else if ((upintrapredmode < NO_INTRA_PMODE)
+					&& (leftintrapredmode <
+						NO_INTRA_PMODE)) {
+				mostprobableintrapredmode =
+					upintrapredmode
+					< leftintrapredmode ?
+					upintrapredmode :
+					leftintrapredmode;
+			} else if (upintrapredmode < NO_INTRA_PMODE) {
+				mostprobableintrapredmode = upintrapredmode;
+			} else if (leftintrapredmode < NO_INTRA_PMODE) {
+				mostprobableintrapredmode = leftintrapredmode;
+			} else {
+				mostprobableintrapredmode =
+					pred_4x4[leftintrapredmode
+					- INTRA_PMODE_4x4][upintrapredmode
+					- INTRA_PMODE_4x4];
+				mostprobableintrapredmode =
+				pred_4x4to8x8[mostprobableintrapredmode];
+			}
+
+
+
+			dec =
+					(curr_se.value1 == -1) ?
+					mostprobableintrapredmode :
+					curr_se.value1
+					+ (curr_se.value1
+					>= mostprobableintrapredmode);
+
+#ifdef DUMP_DEBUG
+			if (avs_get_debug_flag() & MB_INFO_DUMP)
+				io_printf(" - ipredmode[%d] : %d\n", b8, dec);
+#endif
+
+			img->ipredmode[(1 + bi) * 2][(1 + bj) * 2] = dec;
+			img->ipredmode[(1 + bi) * 2 + 1][(1 + bj) * 2] = dec;
+			img->ipredmode[(1 + bi) * 2][(1 + bj) * 2 + 1] = dec;
+			img->ipredmode[(1 + bi) * 2 + 1][(1 + bj) * 2 + 1] =
+					dec;
+
+			j2 = bj;
+		}
+	} else if (b8 == 4 && curr_mb->b8mode[b8 - 3] == IBLOCK) {
+
+		curr_se.type = SE_INTRAPREDMODE;
+#if TRACE
+		strncpy(curr_se.tracestring,
+			"Chroma intra pred mode", TRACESTRING_SIZE);
+#endif
+
+		if (1) {
+			dp = &(currslice->part_arr[0]);
+			curr_se.reading = read_cipredmode_aec;
+			dp->read_syntax_element(&curr_se, img, dp);
+		} else
+
+		{
+		}
+		curr_mb->c_ipred_mode = curr_se.value1;
+
+		push_es(UE[curr_se.value1][0], UE[curr_se.value1][1]);
+
+#ifdef DUMP_DEBUG
+		if (avs_get_debug_flag() & MB_INFO_DUMP)
+			io_printf(" * UE c_ipred_mode read : %d\n",
+				curr_mb->c_ipred_mode);
+#endif
+
+		if (curr_se.value1 < DC_PRED_8 || curr_se.value1 > PLANE_8) {
+#ifdef DUMP_DEBUG
+			if (avs_get_debug_flag() & MB_INFO_DUMP)
+				io_printf("%d\n", img->current_mb_nr);
+#endif
+			pr_info("illegal chroma intra pred mode!\n");
+		}
+	}
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    This function is used to arithmetically decode the coded
+ *    block pattern of a given MB.
+ ************************************************************************
+ */
+void readcp_aec(struct syntaxelement *se, struct img_par *img,
+		struct decoding_environment_s *dep_dp)
+{
+	struct texture_info_contexts *ctx = img->current_slice->tex_ctx;
+	struct macroblock *curr_mb = &mb_data[img->current_mb_nr];
+
+	int mb_x, mb_y;
+	int a, b;
+	int curr_cbp_ctx, curr_cbp_idx;
+	int cbp = 0;
+	int cbp_bit;
+	int mask;
+
+	for (mb_y = 0; mb_y < 4; mb_y += 2) {
+		for (mb_x = 0; mb_x < 4; mb_x += 2) {
+			if (curr_mb->b8mode[mb_y + (mb_x / 2)] == IBLOCK)
+				curr_cbp_idx = 0;
+			else
+				curr_cbp_idx = 1;
+
+			if (mb_y == 0) {
+				if (curr_mb->mb_available_up == NULL)
+					b = 0;
+				else {
+					b = ((((curr_mb->mb_available_up)->cbp
+							& (1 << (2 + mb_x / 2)))
+							== 0) ? 1 : 0);
+				}
+
+			} else
+				b = (((cbp & (1 << (mb_x / 2))) == 0) ? 1 : 0);
+
+			if (mb_x == 0) {
+				if (curr_mb->mb_available_left == NULL)
+					a = 0;
+				else {
+					a =
+					((((curr_mb->mb_available_left)->cbp
+					& (1
+					<< (2
+					* (mb_y
+					/ 2)
+					+ 1)))
+					== 0) ?
+					1 : 0);
+				}
+			} else
+				a = (((cbp & (1 << mb_y)) == 0) ? 1 : 0);
+			curr_cbp_ctx = a + 2 * b;
+			mask = (1 << (mb_y + mb_x / 2));
+			cbp_bit = biari_decode_symbol(dep_dp,
+					ctx->cbp_contexts[0] + curr_cbp_ctx);
+
+			if (cbp_bit)
+				cbp += mask;
+		}
+	}
+	curr_cbp_ctx = 0;
+	cbp_bit = biari_decode_symbol(dep_dp,
+			ctx->cbp_contexts[1] + curr_cbp_ctx);
+
+	if (cbp_bit) {
+		curr_cbp_ctx = 1;
+		cbp_bit = biari_decode_symbol(dep_dp,
+				ctx->cbp_contexts[1] + curr_cbp_ctx);
+		if (cbp_bit) {
+			cbp += 48;
+
+		} else {
+			curr_cbp_ctx = 1;
+			cbp_bit = biari_decode_symbol(dep_dp,
+					ctx->cbp_contexts[1] + curr_cbp_ctx);
+			cbp += (cbp_bit == 1) ? 32 : 16;
+
+		}
+	}
+
+	se->value1 = cbp;
+	if (!cbp)
+		last_dquant = 0;
+
+
+
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    This function is used to arithmetically decode the delta qp
+ *     of a given MB.
+ ************************************************************************
+ */
+void readdquant_aec(struct syntaxelement *se, struct img_par *img,
+		struct decoding_environment_s *dep_dp)
+{
+	struct motion_info_contexts_s *ctx = img->current_slice->mot_ctx;
+
+	int act_ctx;
+	int act_sym;
+	int dquant;
+
+
+	act_ctx = ((last_dquant != 0) ? 1 : 0);
+
+	act_sym = 1
+			- biari_decode_symbol(dep_dp,
+					ctx->delta_qp_contexts + act_ctx);
+	if (act_sym != 0) {
+		act_ctx = 2;
+		act_sym = unary_bin_decode(dep_dp,
+				ctx->delta_qp_contexts + act_ctx, 1);
+		act_sym++;
+	}
+	act_sym &= 0x3f;
+	push_es(UE[act_sym][0], UE[act_sym][1]);
+
+	dquant = (act_sym + 1) / 2;
+	if ((act_sym & 0x01) == 0)
+		dquant = -dquant;
+	se->value1 = dquant;
+
+	last_dquant = dquant;
+
+}
+
+int csyntax;
+
+#define CHECKDELTAQP {\
+	if (img->qp+curr_mb->delta_quant > 63\
+			|| img->qp+curr_mb->delta_quant < 0) {\
+		csyntax = 0;\
+		transcoding_error_flag = 1;\
+		io_printf("error(0) (%3d|%3d) @ MB%d\n",\
+			curr_mb->delta_quant,\
+			img->qp+curr_mb->delta_quant,\
+			img->picture_structure == 0 \
+			? img->current_mb_nr_fld : img->current_mb_nr);\
+		} }
+
+int dct_level[65];
+int dct_run[65];
+int pair_pos;
+int dct_pairs = -1;
+const int t_chr[5] = {0, 1, 2, 4, 3000};
+
+void readrunlevel_aec_ref(struct syntaxelement *se, struct img_par *img,
+		struct decoding_environment_s *dep_dp)
+{
+	int pairs, rank, pos;
+	int run, level, abslevel, symbol;
+	int sign;
+
+	if (dct_pairs < 0) {
+		struct bi_context_type_s (*primary)[NUM_MAP_CTX];
+		struct bi_context_type_s *pctx;
+		struct bi_context_type_s *pCTX2;
+		int ctx, ctx2, offset;
+
+		if (se->context == LUMA_8x8) {
+			if (img->picture_structure == 0) {
+				primary =
+				img->current_slice->tex_ctx->fld_map_contexts;
+			} else {
+				primary =
+				img->current_slice->tex_ctx->map_contexts;
+			}
+		} else {
+			if (img->picture_structure == 0) {
+				primary =
+				img->current_slice->tex_ctx->fld_last_contexts;
+			} else {
+				primary =
+				img->current_slice->tex_ctx->last_contexts;
+			}
+		}
+
+		rank = 0;
+		pos = 0;
+		for (pairs = 0; pairs < 65; pairs++) {
+#ifdef DECODING_SANITY_CHECK
+			/*max index is NUM_BLOCK_TYPES - 1*/
+			pctx = primary[rank & 0x7];
+#else
+			pctx = primary[rank];
+#endif
+			if (rank > 0) {
+#ifdef DECODING_SANITY_CHECK
+				/*max index is NUM_BLOCK_TYPES - 1*/
+				pCTX2 = primary[(5 + (pos >> 5)) & 0x7];
+#else
+				pCTX2 = primary[5 + (pos >> 5)];
+#endif
+				ctx2 = (pos >> 1) & 0x0f;
+				ctx = 0;
+
+
+				if (biari_decode_symbolw(dep_dp, pctx + ctx,
+						pCTX2 + ctx2)) {
+					break;
+				}
+			}
+
+			ctx = 1;
+			symbol = 0;
+			while (biari_decode_symbol(dep_dp, pctx + ctx) == 0) {
+				symbol += 1;
+				ctx++;
+				if (ctx >= 2)
+					ctx = 2;
+			}
+			abslevel = symbol + 1;
+
+			if (biari_decode_symbol_eq_prob(dep_dp)) {
+				level = -abslevel;
+				sign = 1;
+			} else {
+				level = abslevel;
+				sign = 0;
+			}
+#if TRACE
+			tracebits2("level", 1, level);
+#endif
+
+			if (abslevel == 1)
+				offset = 4;
+			else
+				offset = 6;
+			symbol = 0;
+			ctx = 0;
+			while (biari_decode_symbol(dep_dp, pctx + ctx + offset)
+					== 0) {
+				symbol += 1;
+				ctx++;
+				if (ctx >= 1)
+					ctx = 1;
+			}
+			run = symbol;
+
+#if TRACE
+			tracebits2("run", 1, run);
+#endif
+			dct_level[pairs] = level;
+			dct_run[pairs] = run;
+			if (abslevel > t_chr[rank]) {
+				if (abslevel <= 2)
+					rank = abslevel;
+				else if (abslevel <= 4)
+					rank = 3;
+				else
+					rank = 4;
+			}
+			pos += (run + 1);
+			if (pos >= 64)
+				pos = 63;
+		}
+		dct_pairs = pairs;
+		pair_pos = dct_pairs;
+	}
+
+	if (dct_pairs > 0) {
+		se->value1 = dct_level[pair_pos - 1];
+		se->value2 = dct_run[pair_pos - 1];
+		pair_pos--;
+	} else {
+
+		se->value1 = se->value2 = 0;
+	}
+
+	if ((dct_pairs--) == 0)
+		pair_pos = 0;
+}
+
+int b8_ctr;
+#if 0
+int curr_residual_chroma[4][16][16];
+int curr_residual_luma[16][16];
+#endif
+
+const int SCAN[2][64][2] = {{{0, 0}, {0, 1}, {0, 2}, {1, 0}, {0, 3}, {0, 4}, {1,
+		1}, {1, 2}, {0, 5}, {0, 6}, {1, 3}, {2, 0}, {2, 1}, {0, 7}, {1,
+		4}, {2, 2}, {3, 0}, {1, 5}, {1, 6}, {2, 3}, {3, 1}, {3, 2}, {4,
+		0}, {1, 7}, {2, 4}, {4, 1}, {2, 5}, {3, 3}, {4, 2}, {2, 6}, {3,
+		4}, {4, 3}, {5, 0}, {5, 1}, {2, 7}, {3, 5}, {4, 4}, {5, 2}, {6,
+		0}, {5, 3}, {3, 6}, {4, 5}, {6, 1}, {6, 2}, {5, 4}, {3, 7}, {4,
+		6}, {6, 3}, {5, 5}, {4, 7}, {6, 4}, {5, 6}, {6, 5}, {5, 7}, {6,
+		6}, {7, 0}, {6, 7}, {7, 1}, {7, 2}, {7, 3}, {7, 4}, {7, 5}, {7,
+		6}, {7, 7} }, {{0, 0}, {1, 0}, {0, 1}, {0, 2}, {1, 1}, {2, 0}, {
+		3, 0}, {2, 1}, {1, 2}, {0, 3}, {0, 4}, {1, 3}, {2, 2}, {3, 1}, {
+		4, 0}, {5, 0}, {4, 1}, {3, 2}, {2, 3}, {1, 4}, {0, 5}, {0, 6}, {
+		1, 5}, {2, 4}, {3, 3}, {4, 2}, {5, 1}, {6, 0}, {7, 0}, {6, 1}, {
+		5, 2}, {4, 3}, {3, 4}, {2, 5}, {1, 6}, {0, 7}, {1, 7}, {2, 6}, {
+		3, 5}, {4, 4}, {5, 3}, {6, 2}, {7, 1}, {7, 2}, {6, 3}, {5, 4}, {
+		4, 5}, {3, 6}, {2, 7}, {3, 7}, {4, 6}, {5, 5}, {6, 4}, {7, 3}, {
+		7, 4}, {6, 5}, {5, 6}, {4, 7}, {5, 7}, {6, 6}, {7, 5}, {7, 6}, {
+		6, 7}, {7, 7} } };
+
+const int SCAN_4x4[16][2] = {{0, 0}, {1, 0}, {0, 1}, {0, 2}, {1, 1}, {2, 0}, {3,
+		0}, {2, 1}, {1, 2}, {0, 3}, {1, 3}, {2, 2}, {3, 1}, {3, 2}, {2,
+		3}, {3, 3} };
+
+/*
+ *************************************************************************
+ * Function:
+ * Input:
+ * Output:
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+void encode_golomb_word(unsigned int symbol, unsigned int grad0,
+		unsigned int max_levels, unsigned int *res_bits,
+		unsigned int *res_len)
+{
+	unsigned int level, res, numbits;
+
+	res = 1UL << grad0;
+	level = 1UL;
+	numbits = 1UL + grad0;
+
+	while (symbol >= res && level < max_levels) {
+		symbol -= res;
+		res = res << 1;
+		level++;
+		numbits += 2UL;
+	}
+
+	if (level >= max_levels) {
+		if (symbol >= res)
+			symbol = res - 1UL;
+	}
+
+	*res_bits = res | symbol;
+	*res_len = numbits;
+}
+
+/*
+ *************************************************************************
+ * Function:
+ * Input:
+ * Output:
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+void encode_multilayer_golomb_word(unsigned int symbol,
+		const unsigned int *grad, const unsigned int *max_levels,
+		unsigned int *res_bits, unsigned int *res_len)
+{
+	unsigned int accbits, acclen, bits, len, tmp;
+
+	accbits = acclen = 0UL;
+
+	while (1) {
+		encode_golomb_word(symbol, *grad, *max_levels, &bits, &len);
+		accbits = (accbits << len) | bits;
+		acclen += len;
+#ifdef AVSP_LONG_CABAC
+#else
+		assert(acclen <= 32UL);
+#endif
+		tmp = *max_levels - 1UL;
+
+		if (!((len == (tmp << 1) + (*grad))
+				&& (bits == (1UL << (tmp + *grad)) - 1UL)))
+			break;
+
+		tmp = *max_levels;
+		symbol -= (((1UL << tmp) - 1UL) << (*grad)) - 1UL;
+		grad++;
+		max_levels++;
+	}
+	*res_bits = accbits;
+	*res_len = acclen;
+}
+
+/*
+ *************************************************************************
+ * Function:
+ * Input:
+ * Output:
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+int writesyntaxelement_golomb(struct syntaxelement *se, int write_to_stream)
+{
+	unsigned int bits, len, i;
+	unsigned int grad[4], max_lev[4];
+
+	if (!(se->golomb_maxlevels & ~0xFF))
+		encode_golomb_word(se->value1, se->golomb_grad,
+				se->golomb_maxlevels, &bits, &len);
+	else {
+		for (i = 0UL; i < 4UL; i++) {
+			grad[i] = (se->golomb_grad >> (i << 3)) & 0xFFUL;
+			max_lev[i] = (se->golomb_maxlevels >> (i << 3))
+					& 0xFFUL;
+		}
+		encode_multilayer_golomb_word(se->value1, grad, max_lev, &bits,
+				&len);
+	}
+
+	se->len = len;
+	se->bitpattern = bits;
+
+	if (write_to_stream)
+		push_es(bits, len);
+	return se->len;
+}
+
+/*
+ *************************************************************************
+ * Function:Get coded block pattern and coefficients (run/level)
+ from the bitstream
+ * Input:
+ * Output:
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+void read_cbpandcoeffsfrom_nal(struct img_par *img)
+{
+
+	int tablenum;
+	int inumblk;
+	int inumcoeff;
+	int symbol2D;
+	int escape_level_diff;
+	const int (*AVS_2DVLC_table_intra)[26][27];
+	const int (*AVS_2DVLC_table_chroma)[26][27];
+	int write_to_stream;
+	struct syntaxelement currse_enc;
+	struct syntaxelement *e_currse = &currse_enc;
+
+	int coeff_save[65][2];
+	int coeff_ptr;
+
+	int ii, jj;
+	int mb_nr = img->current_mb_nr;
+
+	int m2, jg2;
+	struct macroblock *curr_mb = &mb_data[mb_nr];
+
+	int block8x8;
+
+	int block_x, block_y;
+
+	struct slice_s *currslice = img->current_slice;
+	int level, run, coef_ctr, len, k, i0, j0, uv, qp;
+
+	int boff_x, boff_y, start_scan;
+	struct syntaxelement curr_se;
+	struct datapartition *dp;
+
+	AVS_2DVLC_table_intra = AVS_2DVLC_INTRA;
+	AVS_2DVLC_table_chroma = AVS_2DVLC_CHROMA;
+	write_to_stream = 1;
+
+	dct_pairs = -1;
+
+	curr_mb->qp = img->qp;
+	qp = curr_mb->qp;
+
+
+	for (block_y = 0; block_y < 4; block_y += 2) {/* all modes */
+	for (block_x = 0; block_x < 4; block_x += 2) {
+		block8x8 = 2 * (block_y / 2) + block_x / 2;
+		if (curr_mb->cbp & (1 << block8x8)) {
+			tablenum = 0;
+			inumblk = 1;
+			inumcoeff = 65;
+			coeff_save[0][0] = 0;
+			coeff_save[0][1] = 0;
+			coeff_ptr = 1;
+
+			b8_ctr = block8x8;
+
+			boff_x = (block8x8 % 2) << 3;
+			boff_y = (block8x8 / 2) << 3;
+
+			img->subblock_x = boff_x >> 2;
+			img->subblock_y = boff_y >> 2;
+
+			start_scan = 0;
+			coef_ctr = start_scan - 1;
+			level = 1;
+			img->is_v_block = 0;
+			img->is_intra_block = IS_INTRA(curr_mb);
+			for (k = start_scan;
+				(k < 65) && (level != 0);
+				k++) {
+
+				curr_se.context = LUMA_8x8;
+				curr_se.type =
+				(IS_INTRA(curr_mb)) ?
+					SE_LUM_AC_INTRA :
+					SE_LUM_AC_INTER;
+
+				dp = &(currslice->part_arr[0]);
+				curr_se.reading =
+					readrunlevel_aec_ref;
+				dp->
+				read_syntax_element(&curr_se,
+					img, dp);
+				level = curr_se.value1;
+				run = curr_se.value2;
+				len = curr_se.len;
+
+				if (level != 0) {
+					coeff_save[coeff_ptr][0] =
+					run;
+					coeff_save[coeff_ptr][1] =
+					level;
+					coeff_ptr++;
+				}
+
+
+
+				if (level != 0) {/* leave if len = 1 */
+					coef_ctr += run + 1;
+					if ((img->picture_structure
+						== FRAME)) {
+						ii =
+						SCAN[img->picture_structure]
+						[coef_ctr][0];
+						jj =
+						SCAN[img->picture_structure]
+						[coef_ctr][1];
+					} else {
+						ii =
+						SCAN[img->picture_structure]
+						[coef_ctr][0];
+						jj =
+						SCAN[img->picture_structure]
+						[coef_ctr][1];
+					}
+
+				}
+			}
+
+			while (coeff_ptr > 0) {
+				run =
+						coeff_save[coeff_ptr
+								- 1][0];
+				level =
+						coeff_save[coeff_ptr
+								- 1][1];
+
+				coeff_ptr--;
+
+				symbol2D = CODE2D_ESCAPE_SYMBOL;
+				if (level > -27 && level < 27
+					&& run < 26) {
+					if (tablenum == 0)
+
+						symbol2D =
+						AVS_2DVLC_table_intra
+						[tablenum]
+						[run][abs(
+						level)
+						- 1];
+					else
+
+						symbol2D =
+						AVS_2DVLC_table_intra
+						[tablenum]
+						[run][abs(
+					level)];
+					if (symbol2D >= 0
+							&& level
+									< 0)
+						symbol2D++;
+					if (symbol2D < 0)
+
+						symbol2D =
+						(CODE2D_ESCAPE_SYMBOL
+						+ (run
+						<< 1)
+						+ ((level
+						> 0) ?
+						1 :
+						0));
+				}
+
+				else {
+
+					symbol2D =
+						(CODE2D_ESCAPE_SYMBOL
+						+ (run
+						<< 1)
+						+ ((level
+						> 0) ?
+						1 :
+						0));
+				}
+
+
+
+				e_currse->type = SE_LUM_AC_INTER;
+				e_currse->value1 = symbol2D;
+				e_currse->value2 = 0;
+
+				e_currse->golomb_grad =
+						vlc_golomb_order
+						[0][tablenum][0];
+				e_currse->golomb_maxlevels =
+						vlc_golomb_order
+						[0][tablenum][1];
+
+				writesyntaxelement_golomb(
+						e_currse,
+						write_to_stream);
+
+				if (symbol2D
+						>= CODE2D_ESCAPE_SYMBOL) {
+
+					e_currse->type =
+							SE_LUM_AC_INTER;
+					e_currse->golomb_grad =
+							1;
+					e_currse->golomb_maxlevels =
+							11;
+					escape_level_diff =
+						abs(
+						level)
+						- ((run
+						> MaxRun[0][tablenum]) ?
+						1 :
+						refabslevel[tablenum][run]);
+					e_currse->value1 =
+							escape_level_diff;
+
+					writesyntaxelement_golomb(
+							e_currse,
+							write_to_stream);
+
+				}
+
+				if (abs(level)
+					> incvlc_intra[tablenum]) {
+					if (abs(level) <= 2)
+						tablenum =
+						abs(
+						level);
+					else if (abs(level) <= 4)
+						tablenum = 3;
+					else if (abs(level) <= 7)
+						tablenum = 4;
+					else if (abs(level)
+							<= 10)
+						tablenum = 5;
+					else
+						tablenum = 6;
+				}
+			}
+
+
+		}
+		}
+	}
+
+
+
+	m2 = img->mb_x * 2;
+	jg2 = img->mb_y * 2;
+
+
+	uv = -1;
+	block_y = 4;
+#if 0
+	qp = QP_SCALE_CR[curr_mb->qp];
+#endif
+	for (block_x = 0; block_x < 4; block_x += 2) {
+
+		uv++;
+
+
+		b8_ctr = (uv + 4);
+		if ((curr_mb->cbp >> (uv + 4)) & 0x1) {
+
+			tablenum = 0;
+			inumblk = 1;
+			inumcoeff = 65;
+			coeff_save[0][0] = 0;
+			coeff_save[0][1] = 0;
+			coeff_ptr = 1;
+
+			coef_ctr = -1;
+			level = 1;
+			img->subblock_x = 0;
+			img->subblock_y = 0;
+			curr_se.context = CHROMA_AC;
+			curr_se.type = (IS_INTRA(curr_mb) ?
+					SE_CHR_AC_INTRA :
+					SE_CHR_AC_INTER);
+			dp = &(currslice->part_arr[0]);
+			curr_se.reading = readrunlevel_aec_ref;
+			img->is_v_block = uv;
+			img->is_intra_block = IS_INTRA(curr_mb);
+			for (k = 0; (k < 65) && (level != 0); k++) {
+
+				dp->read_syntax_element
+				(&curr_se, img, dp);
+				level = curr_se.value1;
+				run = curr_se.value2;
+				len = curr_se.len;
+
+				if (level != 0) {
+					coeff_save[coeff_ptr][0] = run;
+					coeff_save[coeff_ptr][1] =
+							level;
+					coeff_ptr++;
+				}
+
+
+				if (level != 0) {
+					coef_ctr = coef_ctr + run + 1;
+					if ((img->picture_structure
+						== FRAME)
+						/*&& (!curr_mb->mb_field)*/) {
+						i0 =
+						SCAN[img->picture_structure]
+						[coef_ctr][0];
+						j0 =
+						SCAN[img->picture_structure]
+						[coef_ctr][1];
+					} else {
+						i0 =
+						SCAN[img->picture_structure]
+						[coef_ctr][0];
+						j0 =
+						SCAN[img->picture_structure]
+						[coef_ctr][1];
+					}
+
+				}
+			}
+
+			while (coeff_ptr > 0) {
+
+				run = coeff_save[coeff_ptr - 1][0];
+				level = coeff_save[coeff_ptr - 1][1];
+
+				coeff_ptr--;
+
+				symbol2D = CODE2D_ESCAPE_SYMBOL;
+				if (level > -27 && level < 27
+						&& run < 26) {
+					if (tablenum == 0)
+
+						symbol2D =
+						AVS_2DVLC_table_chroma
+						[tablenum][run][abs(
+						level)
+						- 1];
+					else
+						symbol2D =
+							AVS_2DVLC_table_chroma
+							[tablenum][run][abs(
+							level)];
+					if (symbol2D >= 0
+						&& level < 0)
+						symbol2D++;
+					if (symbol2D < 0)
+						symbol2D =
+						(CODE2D_ESCAPE_SYMBOL
+						+ (run
+						<< 1)
+						+ ((level
+						> 0) ?
+						1 :
+						0));
+				}
+
+				else {
+					symbol2D =
+					(CODE2D_ESCAPE_SYMBOL
+					+ (run
+					<< 1)
+					+ ((level
+					> 0) ?
+					1 :
+					0));
+				}
+
+				e_currse->type = SE_LUM_AC_INTER;
+				e_currse->value1 = symbol2D;
+				e_currse->value2 = 0;
+				e_currse->golomb_grad =
+						vlc_golomb_order[2]
+						[tablenum][0];
+				e_currse->golomb_maxlevels =
+						vlc_golomb_order[2]
+						[tablenum][1];
+
+				writesyntaxelement_golomb(e_currse,
+						write_to_stream);
+
+				/*
+				 * if (write_to_stream)
+				 * {
+				 * bitCount[BITS_COEFF_UV_MB]+=e_currse->len;
+				 * e_currse++;
+				 * curr_mb->currSEnr++;
+				 * }
+				 * no_bits+=e_currse->len;
+
+
+				 * if (icoef == 0) break;
+				 */
+
+				if (symbol2D >= CODE2D_ESCAPE_SYMBOL) {
+
+					e_currse->type = SE_LUM_AC_INTER;
+					e_currse->golomb_grad = 0;
+					e_currse->golomb_maxlevels = 11;
+					escape_level_diff =
+						abs(level)
+						- ((run
+						> MaxRun[2][tablenum]) ?
+						1 :
+						refabslevel[tablenum
+						+ 14][run]);
+					e_currse->value1 =
+							escape_level_diff;
+
+					writesyntaxelement_golomb(
+							e_currse,
+							write_to_stream);
+
+				}
+
+				if (abs(level)
+				> incvlc_chroma[tablenum]) {
+					if (abs(level) <= 2)
+						tablenum = abs(level);
+					else if (abs(level) <= 4)
+						tablenum = 3;
+					else
+						tablenum = 4;
+				}
+			}
+
+		}
+	}
+}
+
+/*
+ *************************************************************************
+ * Function:Get the syntax elements from the NAL
+ * Input:
+ * Output:
+ * Return:
+ * Attention:
+ *************************************************************************
+ */
+
+int read_one_macroblock(struct img_par *img)
+{
+	int i, j;
+
+	struct syntaxelement curr_se;
+	struct macroblock *curr_mb = &mb_data[img->current_mb_nr];
+
+	int cabp_flag;
+
+	int tempcbp;
+	int fixqp;
+
+	struct slice_s *currslice = img->current_slice;
+	struct datapartition *dp;
+
+	fixqp = (fixed_picture_qp || fixed_slice_qp);
+
+	for (i = 0; i < 8; i++)
+		for (j = 0; j < 8; j++) {
+			img->m8[0][i][j] = 0;
+			img->m8[1][i][j] = 0;
+			img->m8[2][i][j] = 0;
+			img->m8[3][i][j] = 0;
+		}
+
+	current_mb_skip = 0;
+
+	curr_mb->qp = img->qp;
+	curr_se.type = SE_MBTYPE;
+	curr_se.mapping = linfo_ue;
+
+	curr_mb->mb_type_2 = 0;
+
+	if (img->type == I_IMG)
+		curr_mb->mb_type = 0;
+
+	interpret_mb_mode_i(img);
+
+	init_macroblock(img);
+
+	if ((IS_INTRA(curr_mb)) && (img->abt_flag)) {
+
+#if TRACE
+		strncpy(curr_se.tracestring, "cabp_flag", TRACESTRING_SIZE);
+#endif
+
+		curr_se.len = 1;
+		curr_se.type = SE_CABP;
+		read_syntaxelement_flc(&curr_se);
+		cabp_flag = curr_se.value1;
+		if (cabp_flag == 0) {
+			curr_mb->CABP[0] = 0;
+			curr_mb->CABP[1] = 0;
+			curr_mb->CABP[2] = 0;
+			curr_mb->CABP[3] = 0;
+		} else {
+			for (i = 0; i < 4; i++) {
+				curr_se.len = 1;
+				curr_se.type = SE_CABP;
+				read_syntaxelement_flc(&curr_se);
+				curr_mb->CABP[i] = curr_se.value1;
+			}
+		}
+
+	} else {
+		curr_mb->CABP[0] = 0;
+		curr_mb->CABP[1] = 0;
+		curr_mb->CABP[2] = 0;
+		curr_mb->CABP[3] = 0;
+
+	}
+
+	if (IS_INTRA(curr_mb)) {
+		for (i = 0; i < /*5*/(chroma_format + 4); i++)
+
+			read_ipred_block_modes(img, i);
+	}
+
+	curr_se.type = SE_CBP_INTRA;
+	curr_se.mapping = linfo_cbp_intra;
+
+#if TRACE
+	snprintf(curr_se.tracestring, TRACESTRING_SIZE, "CBP");
+#endif
+
+	if (img->type == I_IMG || IS_INTER(curr_mb)) {
+		curr_se.golomb_maxlevels = 0;
+
+		if (1) {
+			dp = &(currslice->part_arr[0]);
+			curr_se.reading = readcp_aec;
+			dp->read_syntax_element(&curr_se, img, dp);
+		}
+
+
+		curr_mb->cbp = curr_se.value1;
+		push_es(UE[NCBP[curr_se.value1][0]][0],
+				UE[NCBP[curr_se.value1][0]][1]);
+
+	}
+
+# if 1
+	if (curr_mb->cbp != 0)
+		tempcbp = 1;
+	else
+		tempcbp = 0;
+#else
+
+	if (chroma_format == 2)	{
+#if TRACE
+		snprintf(curr_se.tracestring, TRACESTRING_SIZE, "CBP422");
+#endif
+		curr_se.mapping = /*linfo_se*/linfo_ue;
+		curr_se.type = SE_CBP_INTRA;
+		readsyntaxelement_uvlc(&curr_se, inp);
+		curr_mb->cbp01 = curr_se.value1;
+		io_printf(" * UE cbp01 read : 0x%02X\n", curr_mb->cbp01);
+	}
+
+	if (chroma_format == 2)	{
+		if (curr_mb->cbp != 0 || curr_mb->cbp01 != 0)
+			tempcbp = 1;
+		else
+			tempcbp = 0;
+
+	} else {
+		if (curr_mb->cbp != 0)
+			tempcbp = 1;
+		else
+			tempcbp = 0;
+	}
+
+#endif
+
+	if (IS_INTRA(curr_mb) && (img->abt_flag) && (curr_mb->cbp & (0xF))) {
+		curr_mb->CABT[0] = curr_mb->CABP[0];
+		curr_mb->CABT[1] = curr_mb->CABP[1];
+		curr_mb->CABT[2] = curr_mb->CABP[2];
+		curr_mb->CABT[3] = curr_mb->CABP[3];
+	} else {
+
+		curr_mb->CABT[0] = 0;
+		curr_mb->CABT[1] = 0;
+		curr_mb->CABT[2] = 0;
+		curr_mb->CABT[3] = 0;
+
+		if (!fixqp && (tempcbp)) {
+			if (IS_INTER(curr_mb))
+				curr_se.type = SE_DELTA_QUANT_INTER;
+			else
+				curr_se.type = SE_DELTA_QUANT_INTRA;
+
+#if TRACE
+			snprintf(curr_se.tracestring,
+				TRACESTRING_SIZE, "Delta quant ");
+#endif
+
+			if (1) {
+				dp = &(currslice->part_arr[0]);
+				curr_se.reading = readdquant_aec;
+				dp->read_syntax_element(&curr_se, img, dp);
+			}
+
+			curr_mb->delta_quant = curr_se.value1;
+#ifdef DUMP_DEBUG
+			if (avs_get_debug_flag() & MB_INFO_DUMP) {
+				io_printf(" * SE delta_quant read : %d\n",
+					curr_mb->delta_quant);
+			}
+#endif
+			CHECKDELTAQP
+
+			if (transcoding_error_flag)
+				return -1;
+
+			img->qp = (img->qp - MIN_QP + curr_mb->delta_quant
+					+ (MAX_QP - MIN_QP + 1))
+					% (MAX_QP - MIN_QP + 1) + MIN_QP;
+		}
+
+		if (fixqp) {
+			curr_mb->delta_quant = 0;
+			img->qp = (img->qp - MIN_QP + curr_mb->delta_quant
+					+ (MAX_QP - MIN_QP + 1))
+					% (MAX_QP - MIN_QP + 1) + MIN_QP;
+
+		}
+#ifdef DUMP_DEBUG
+		if (avs_get_debug_flag() & MB_INFO_DUMP)
+			io_printf(" - img->qp : %d\n", img->qp);
+#endif
+	}
+
+	read_cbpandcoeffsfrom_nal(img);
+	return DECODE_MB;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    finding end of a slice in case this is not the end of a frame
+ *
+ * Unsure whether the "correction" below actually solves an off-by-one
+ * problem or whether it introduces one in some cases :-(  Anyway,
+ * with this change the bit stream format works with AEC again.
+ * StW, 8.7.02
+ ************************************************************************
+ */
+int aec_startcode_follows(struct img_par *img, int eos_bit)
+{
+	struct slice_s *currslice = img->current_slice;
+	struct datapartition *dp;
+	unsigned int bit;
+	struct decoding_environment_s *dep_dp;
+
+	dp = &(currslice->part_arr[0]);
+	dep_dp = &(dp->de_aec);
+
+	if (eos_bit)
+		bit = biari_decode_final(dep_dp);
+	else
+		bit = 0;
+
+	return bit == 1 ? 1 : 0;
+}
+
+#ifdef AVSP_LONG_CABAC
+int process_long_cabac(void)
+#else
+void main(void)
+#endif
+{
+	int data32;
+	int current_header;
+	int i;
+	int tmp;
+	int ret;
+
+	int byte_startposition;
+	int aec_mb_stuffing_bit;
+	struct slice_s *currslice;
+#ifdef PERFORMANCE_DEBUG
+	pr_info("enter %s\r\n", __func__);
+#endif
+	transcoding_error_flag = 0;
+	ret = 0;
+	es_buf = es_write_addr_virt;
+
+	if (local_heap_init(MAX_CODED_FRAME_SIZE * 4) < 0) {
+		ret = -1;
+		goto End;
+	}
+
+	img = (struct img_par *)local_alloc(1, sizeof(struct img_par));
+	if (img	== NULL) {
+		no_mem_exit("main: img");
+		ret = -1;
+		goto End;
+	}
+	stat_bits_ptr = (struct stat_bits *)local_alloc(1,
+			sizeof(struct stat_bits));
+	if (stat_bits_ptr == NULL) {
+		no_mem_exit("main: stat_bits");
+		ret = -1;
+		goto End;
+	}
+
+	curr_stream = alloc_bitstream();
+	if (curr_stream == NULL) {
+		io_printf("alloc bitstream failed\n");
+		ret = -1;
+		goto End;
+	}
+
+	chroma_format = 1;
+	demulate_enable = 0;
+	img->seq_header_indicate = 1;
+
+#ifdef AVSP_LONG_CABAC
+	data32 = READ_VREG(LONG_CABAC_REQ);
+	progressive_sequence = (data32 >> 1) & 1;
+	fixed_picture_qp = (data32 >> 2) & 1;
+	img->picture_structure = (data32 >> 3) & 1;
+	img->type = (data32 >> 4) & 3;
+	skip_mode_flag = (data32 >> 6) & 1;
+
+	src_start = READ_VREG(LONG_CABAC_SRC_ADDR);
+	des_start = READ_VREG(LONG_CABAC_DES_ADDR);
+
+	data32 = READ_VREG(LONG_CABAC_PIC_SIZE);
+	horizontal_size = (data32 >> 0) & 0xffff;
+	vertical_size = (data32 >> 16) & 0xffff;
+	if (horizontal_size * vertical_size > 1920 * 1080) {
+		io_printf("pic size check failed: width = %d, height = %d\n",
+			horizontal_size, vertical_size);
+		ret = -1;
+		goto End;
+	}
+
+	vld_mem_start_addr = READ_VREG(VLD_MEM_VIFIFO_START_PTR);
+	vld_mem_end_addr = READ_VREG(VLD_MEM_VIFIFO_END_PTR);
+
+#else
+	progressive_sequence = 0;
+	fixed_picture_qp = 0;
+	img->picture_structure = 0;
+	img->type = I_IMG;
+	skip_mode_flag = 1;
+	horizontal_size = 1920;
+	vertical_size = 1080;
+
+	src_start = 0;
+#endif
+
+	if (horizontal_size % 16 != 0)
+		img->auto_crop_right = 16 - (horizontal_size % 16);
+	else
+		img->auto_crop_right = 0;
+
+	if (!progressive_sequence) {
+		if (vertical_size % 32 != 0)
+			img->auto_crop_bottom = 32 - (vertical_size % 32);
+		else
+			img->auto_crop_bottom = 0;
+	} else {
+		if (vertical_size % 16 != 0)
+			img->auto_crop_bottom = 16 - (vertical_size % 16);
+		else
+			img->auto_crop_bottom = 0;
+	}
+
+	img->width = (horizontal_size + img->auto_crop_right);
+	if (img->picture_structure)
+		img->height = (vertical_size + img->auto_crop_bottom);
+	else
+		img->height = (vertical_size + img->auto_crop_bottom) / 2;
+	img->width_cr = (img->width >> 1);
+
+	img->pic_width_inmbs = img->width / MB_BLOCK_SIZE;
+	img->pic_height_inmbs = img->height / MB_BLOCK_SIZE;
+	img->pic_size_inmbs = img->pic_width_inmbs * img->pic_height_inmbs;
+
+	io_printf(
+			"[LONG CABAC] Start Transcoding from 0x%x to 0x%x Size : %d x %d\r\n",
+			src_start, des_start, horizontal_size, vertical_size);
+#if 0
+	io_printf("VLD_MEM_VIFIFO_START_PTR %x\r\n",
+			READ_VREG(VLD_MEM_VIFIFO_START_PTR));
+	io_printf("VLD_MEM_VIFIFO_CURR_PTR %x\r\n",
+			READ_VREG(VLD_MEM_VIFIFO_CURR_PTR));
+	io_printf("VLD_MEM_VIFIFO_END_PTR %x\r\n",
+			READ_VREG(VLD_MEM_VIFIFO_END_PTR));
+	io_printf("VLD_MEM_VIFIFO_WP %x\r\n",
+			READ_VREG(VLD_MEM_VIFIFO_WP));
+	io_printf("VLD_MEM_VIFIFO_RP %x\r\n",
+			READ_VREG(VLD_MEM_VIFIFO_RP));
+	io_printf("VLD_MEM_VBUF_RD_PTR %x\r\n",
+			READ_VREG(VLD_MEM_VBUF_RD_PTR));
+	io_printf("VLD_MEM_VIFIFO_BUF_CNTL %x\r\n",
+			READ_VREG(VLD_MEM_VIFIFO_BUF_CNTL));
+#endif
+	io_printf(
+			"[LONG CABAC] progressive_sequence : %d, fixed_picture_qp : %d, skip_mode_flag : %d\r\n",
+			progressive_sequence, fixed_picture_qp, skip_mode_flag);
+	io_printf("[LONG CABAC] picture_structure : %d, picture_type : %d\r\n",
+			img->picture_structure, img->type);
+
+	open_irabs(p_irabs);
+
+
+	if (initial_decode() == 0) {
+		io_printf("initial_decode failed\n");
+		ret = -1;
+		goto End;
+	}
+
+	init_es();
+
+	current_header = header();
+	io_printf("[LONG CABAC] header Return : %d\n", current_header);
+
+	tmp = slice_header(temp_slice_buf, first_slice_startpos,
+			first_slice_length);
+
+	init_contexts(img);
+	aec_new_slice();
+	byte_startposition = (curr_stream->frame_bitoffset) / 8;
+
+	currslice = img->current_slice;
+
+	if (1) {
+		for (i = 0; i < 1; i++) {
+			img->current_slice->part_arr[i].read_syntax_element =
+					read_syntaxelement_aec;
+			img->current_slice->part_arr[i].bitstream = curr_stream;
+		}
+		curr_stream = currslice->part_arr[0].bitstream;
+	}
+	if ((curr_stream->frame_bitoffset) % 8 != 0)
+		byte_startposition++;
+
+	arideco_start_decoding(&img->current_slice->part_arr[0].de_aec,
+			curr_stream->stream_buffer, (byte_startposition),
+			&(curr_stream->read_len), img->type);
+
+	img->current_mb_nr = 0;
+	total_mb_count = 0;
+	while (img->current_mb_nr < img->pic_size_inmbs)
+
+	{
+		start_macroblock(img);
+		if (-1 == read_one_macroblock(img)) {
+			ret = -1;
+			pr_info("macroblock trans failed, exit\n");
+			goto End;
+		}
+		if (img->cod_counter <= 0)
+			aec_mb_stuffing_bit = aec_startcode_follows(img, 1);
+		img->current_mb_nr++;
+	}
+
+	push_es(0xff, 8);
+	io_printf(" Total ES_LENGTH : %d\n", es_ptr);
+
+#ifdef AVSP_LONG_CABAC
+	push_es(0xff, 64);
+	if (es_buf_is_overflow) {
+		io_printf("fatal error: es_buf_is_overflow\n");
+		ret = -1;
+		goto End;
+	}
+
+	if (transcoding_error_flag == 0) {
+#if 1
+		dma_sync_single_for_device(amports_get_dma_device(),
+			es_write_addr_phy,
+			es_ptr, DMA_TO_DEVICE);
+
+		wmb(); /**/
+#endif
+	}
+#else
+	fclose(f_es);
+#endif
+
+End:
+#ifdef AVSP_LONG_CABAC
+	WRITE_VREG(LONG_CABAC_REQ, 0);
+#endif
+	local_heap_uninit();
+#ifdef PERFORMANCE_DEBUG
+	pr_info("exit %s\r\n", __func__);
+#endif
+	return ret;
+}
+#endif
diff --git a/drivers/frame_provider/decoder/avs2/Makefile b/drivers/frame_provider/decoder/avs2/Makefile
new file mode 100644
index 0000000..5fe8566
--- /dev/null
+++ b/drivers/frame_provider/decoder/avs2/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_AVS2) += amvdec_avs2.o
+amvdec_avs2-objs += vavs2.o avs2_bufmgr.o
diff --git a/drivers/frame_provider/decoder/avs2/avs2_bufmgr.c b/drivers/frame_provider/decoder/avs2/avs2_bufmgr.c
new file mode 100644
index 0000000..de9a3d2
--- /dev/null
+++ b/drivers/frame_provider/decoder/avs2/avs2_bufmgr.c
@@ -0,0 +1,2205 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/semaphore.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/kfifo.h>
+#include <linux/kthread.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
+#include <linux/slab.h>
+//#include <linux/amlogic/tee.h>
+#include <uapi/linux/tee.h>
+#include <linux/sched/clock.h>
+#include "../../../stream_input/amports/amports_priv.h"
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include "../utils/decoder_mmu_box.h"
+#include "../utils/decoder_bmmu_box.h"
+#include "avs2_global.h"
+
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../utils/vdec.h"
+#include "../utils/amvdec.h"
+
+#undef pr_info
+#define pr_info printk
+
+#define assert(chk_cond) {\
+	if (!(chk_cond))\
+		pr_info("error line %d\n", __LINE__);\
+	while (!(chk_cond))\
+		;\
+}
+
+int16_t get_param(uint16_t value, int8_t *print_info)
+{
+	if (is_avs2_print_param())
+		pr_info("%s = %x\n", print_info, value);
+	return (int16_t)value;
+}
+
+void readAlfCoeff(struct avs2_decoder *avs2_dec, struct ALFParam_s *Alfp)
+{
+	int32_t pos;
+	union param_u *rpm_param = &avs2_dec->param;
+
+	int32_t f = 0, symbol, pre_symbole;
+	const int32_t numCoeff = (int32_t)ALF_MAX_NUM_COEF;
+
+	switch (Alfp->componentID) {
+	case ALF_Cb:
+	case ALF_Cr: {
+		for (pos = 0; pos < numCoeff; pos++) {
+			if (Alfp->componentID == ALF_Cb)
+				Alfp->coeffmulti[0][pos] =
+					get_param(
+					rpm_param->alf.alf_cb_coeffmulti[pos],
+					"Chroma ALF coefficients");
+			else
+				Alfp->coeffmulti[0][pos] =
+					get_param(
+					rpm_param->alf.alf_cr_coeffmulti[pos],
+					"Chroma ALF coefficients");
+#if Check_Bitstream
+			if (pos <= 7)
+				assert(Alfp->coeffmulti[0][pos] >= -64
+					&& Alfp->coeffmulti[0][pos] <= 63);
+			if (pos == 8)
+				assert(Alfp->coeffmulti[0][pos] >= -1088
+					&& Alfp->coeffmulti[0][pos] <= 1071);
+#endif
+		}
+	}
+	break;
+	case ALF_Y: {
+		int32_t region_distance_idx = 0;
+		Alfp->filters_per_group =
+			get_param(rpm_param->alf.alf_filters_num_m_1,
+				"ALF_filter_number_minus_1");
+#if Check_Bitstream
+		assert(Alfp->filters_per_group >= 0
+			&& Alfp->filters_per_group <= 15);
+#endif
+		Alfp->filters_per_group = Alfp->filters_per_group + 1;
+
+		memset(Alfp->filterPattern, 0, NO_VAR_BINS * sizeof(int32_t));
+		pre_symbole = 0;
+		symbol = 0;
+		for (f = 0; f < Alfp->filters_per_group; f++) {
+			if (f > 0) {
+				if (Alfp->filters_per_group != 16) {
+					symbol =
+					get_param(rpm_param->alf.region_distance
+						[region_distance_idx++],
+						"Region distance");
+				} else {
+					symbol = 1;
+				}
+				Alfp->filterPattern[symbol + pre_symbole] = 1;
+				pre_symbole = symbol + pre_symbole;
+			}
+
+			for (pos = 0; pos < numCoeff; pos++) {
+				Alfp->coeffmulti[f][pos] =
+				get_param(
+					rpm_param->alf.alf_y_coeffmulti[f][pos],
+					"Luma ALF coefficients");
+#if Check_Bitstream
+				if (pos <= 7)
+					assert(
+						Alfp->coeffmulti[f][pos]
+						>= -64 &&
+						Alfp->coeffmulti[f][pos]
+						<= 63);
+				if (pos == 8)
+					assert(
+						Alfp->coeffmulti[f][pos]
+						>= -1088 &&
+						Alfp->coeffmulti[f][pos]
+						<= 1071);
+#endif
+
+			}
+		}
+
+#if Check_Bitstream
+		assert(pre_symbole >= 0 && pre_symbole <= 15);
+
+#endif
+	}
+	break;
+	default: {
+		pr_info("Not a legal component ID\n");
+		assert(0);
+		return; /* exit(-1);*/
+	}
+	}
+}
+
+void Read_ALF_param(struct avs2_decoder *avs2_dec)
+{
+	struct inp_par    *input = &avs2_dec->input;
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	union param_u *rpm_param = &avs2_dec->param;
+	int32_t compIdx;
+	if (input->alf_enable) {
+		img->pic_alf_on[0] =
+			get_param(
+			rpm_param->alf.picture_alf_enable_Y,
+			"alf_pic_flag_Y");
+		img->pic_alf_on[1] =
+			get_param(
+			rpm_param->alf.picture_alf_enable_Cb,
+			"alf_pic_flag_Cb");
+		img->pic_alf_on[2] =
+			get_param(
+			rpm_param->alf.picture_alf_enable_Cr,
+			"alf_pic_flag_Cr");
+
+		avs2_dec->m_alfPictureParam[ALF_Y].alf_flag
+			= img->pic_alf_on[ALF_Y];
+		avs2_dec->m_alfPictureParam[ALF_Cb].alf_flag
+			= img->pic_alf_on[ALF_Cb];
+		avs2_dec->m_alfPictureParam[ALF_Cr].alf_flag
+			= img->pic_alf_on[ALF_Cr];
+		if (img->pic_alf_on[0]
+			|| img->pic_alf_on[1]
+			|| img->pic_alf_on[2]) {
+			for (compIdx = 0;
+				compIdx < NUM_ALF_COMPONENT;
+				compIdx++) {
+				if (img->pic_alf_on[compIdx]) {
+					readAlfCoeff(
+					avs2_dec,
+					&avs2_dec->m_alfPictureParam[compIdx]);
+				}
+			}
+		}
+	}
+
+}
+
+void Get_SequenceHeader(struct avs2_decoder *avs2_dec)
+{
+	struct inp_par    *input = &avs2_dec->input;
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Com_data_s *hc = &avs2_dec->hc;
+	struct Video_Dec_data_s *hd = &avs2_dec->hd;
+	union param_u *rpm_param = &avs2_dec->param;
+	/*int32_t i, j;*/
+
+	/*fpr_info(stdout, "Sequence Header\n");*/
+	/*memcpy(currStream->streamBuffer, buf, length);*/
+	/*currStream->code_len = currStream->bitstream_length = length;*/
+	/*currStream->read_len = currStream->frame_bitoffset = (startcodepos +
+	  1) * 8;*/
+
+	input->profile_id           =
+		get_param(rpm_param->p.profile_id, "profile_id");
+	input->level_id             =
+		get_param(rpm_param->p.level_id, "level_id");
+	hd->progressive_sequence        =
+		get_param(
+			rpm_param->p.progressive_sequence,
+			"progressive_sequence");
+#if INTERLACE_CODING
+	hd->is_field_sequence           =
+		get_param(
+			rpm_param->p.is_field_sequence,
+			"field_coded_sequence");
+#endif
+#if HALF_PIXEL_COMPENSATION || HALF_PIXEL_CHROMA
+	img->is_field_sequence = hd->is_field_sequence;
+#endif
+	hd->horizontal_size =
+		get_param(rpm_param->p.horizontal_size, "horizontal_size");
+	hd->vertical_size =
+		get_param(rpm_param->p.vertical_size, "vertical_size");
+	input->chroma_format               =
+		get_param(rpm_param->p.chroma_format, "chroma_format");
+	input->output_bit_depth = 8;
+	input->sample_bit_depth = 8;
+	hd->sample_precision = 1;
+	if (input->profile_id == BASELINE10_PROFILE) { /* 10bit profile (0x52)*/
+		input->output_bit_depth =
+			get_param(rpm_param->p.sample_precision,
+			"sample_precision");
+		input->output_bit_depth =
+			6 + (input->output_bit_depth) * 2;
+		input->sample_bit_depth =
+			get_param(rpm_param->p.encoding_precision,
+			"encoding_precision");
+		input->sample_bit_depth =
+			6 + (input->sample_bit_depth) * 2;
+	} else { /* other profile*/
+		hd->sample_precision =
+			get_param(rpm_param->p.sample_precision,
+				"sample_precision");
+	}
+	hd->aspect_ratio_information    =
+		get_param(rpm_param->p.aspect_ratio_information,
+			"aspect_ratio_information");
+	hd->frame_rate_code             =
+		get_param(rpm_param->p.frame_rate_code, "frame_rate_code");
+
+	hd->bit_rate_lower              =
+		get_param(rpm_param->p.bit_rate_lower, "bit_rate_lower");
+	/*hd->marker_bit                  = get_param(rpm_param->p.marker_bit,
+	 * "marker bit");*/
+	/*CHECKMARKERBIT*/
+	hd->bit_rate_upper              =
+		get_param(rpm_param->p.bit_rate_upper, "bit_rate_upper");
+	hd->low_delay                   =
+		get_param(rpm_param->p.low_delay, "low_delay");
+	/*hd->marker_bit                  =
+		get_param(rpm_param->p.marker_bit2,
+	 "marker bit");*/
+	/*CHECKMARKERBIT*/
+#if M3480_TEMPORAL_SCALABLE
+	hd->temporal_id_exist_flag      =
+		get_param(rpm_param->p.temporal_id_exist_flag,
+			"temporal_id exist flag"); /*get
+		Extention Flag*/
+#endif
+	/*u_v(18, "bbv buffer size");*/
+	input->g_uiMaxSizeInBit         =
+		get_param(rpm_param->p.g_uiMaxSizeInBit,
+		"Largest Coding Block Size");
+
+
+	/*hd->background_picture_enable = 0x01 ^
+		(get_param(rpm_param->p.avs2_seq_flags,
+		"background_picture_disable")
+		>> BACKGROUND_PICTURE_DISABLE_BIT) & 0x1;*/
+	/*rain???*/
+	hd->background_picture_enable = 0x01 ^
+		((get_param(rpm_param->p.avs2_seq_flags,
+		"background_picture_disable")
+		>> BACKGROUND_PICTURE_DISABLE_BIT) & 0x1);
+
+
+	hd->b_dmh_enabled           = 1;
+
+	hd->b_mhpskip_enabled       =
+		get_param(rpm_param->p.avs2_seq_flags >> B_MHPSKIP_ENABLED_BIT,
+			"mhpskip enabled") & 0x1;
+	hd->dhp_enabled             =
+		get_param(rpm_param->p.avs2_seq_flags >> DHP_ENABLED_BIT,
+			"dhp enabled") & 0x1;
+	hd->wsm_enabled             =
+		get_param(rpm_param->p.avs2_seq_flags >> WSM_ENABLED_BIT,
+			"wsm enabled") & 0x1;
+
+	img->inter_amp_enable       =
+		get_param(rpm_param->p.avs2_seq_flags >> INTER_AMP_ENABLE_BIT,
+			"Asymmetric Motion Partitions") & 0x1;
+	input->useNSQT              =
+		get_param(rpm_param->p.avs2_seq_flags >> USENSQT_BIT,
+			"useNSQT") & 0x1;
+	input->useSDIP              =
+		get_param(rpm_param->p.avs2_seq_flags >> USESDIP_BIT,
+			"useNSIP") & 0x1;
+
+	hd->b_secT_enabled          =
+		get_param(rpm_param->p.avs2_seq_flags >> B_SECT_ENABLED_BIT,
+			"secT enabled") & 0x1;
+
+	input->sao_enable           =
+		get_param(rpm_param->p.avs2_seq_flags >> SAO_ENABLE_BIT,
+			"SAO Enable Flag") & 0x1;
+	input->alf_enable           =
+		get_param(rpm_param->p.avs2_seq_flags >> ALF_ENABLE_BIT,
+			"ALF Enable Flag") & 0x1;
+	hd->b_pmvr_enabled          =
+		get_param(rpm_param->p.avs2_seq_flags >> B_PMVR_ENABLED_BIT,
+			"pmvr enabled") & 0x1;
+
+
+	hd->gop_size = get_param(rpm_param->p.num_of_RPS,
+		"num_of_RPS");
+#if Check_Bitstream
+	/*assert(hd->gop_size<=32);*/
+#endif
+
+	if (hd->low_delay == 0) {
+		hd->picture_reorder_delay  =
+			get_param(rpm_param->p.picture_reorder_delay,
+			"picture_reorder_delay");
+	}
+
+	input->crossSliceLoopFilter    =
+		get_param(rpm_param->p.avs2_seq_flags
+			>> CROSSSLICELOOPFILTER_BIT,
+			"Cross Loop Filter Flag") & 0x1;
+
+#if BCBR
+	if ((input->profile_id == SCENE_PROFILE ||
+		input->profile_id == SCENE10_PROFILE) &&
+		hd->background_picture_enable) {
+		hd->bcbr_enable = u_v(1,
+			"block_composed_background_picture_enable");
+		u_v(1, "reserved bits");
+	} else {
+		hd->bcbr_enable = 0;
+		u_v(2, "reserved bits");
+	}
+#else
+	/*u_v(2, "reserved bits");*/
+#endif
+
+	img->width          = hd->horizontal_size;
+	img->height         = hd->vertical_size;
+	img->width_cr       = (img->width >> 1);
+
+	if (input->chroma_format == 1) {
+		img->height_cr
+		= (img->height >> 1);
+	}
+
+	img->PicWidthInMbs  = img->width / MIN_CU_SIZE;
+	img->PicHeightInMbs = img->height / MIN_CU_SIZE;
+	img->PicSizeInMbs   = img->PicWidthInMbs * img->PicHeightInMbs;
+	img->buf_cycle      = input->buf_cycle + 1;
+	img->max_mb_nr      = (img->width * img->height)
+		/ (MIN_CU_SIZE * MIN_CU_SIZE);
+
+#ifdef AML
+avs2_dec->lcu_size =
+	get_param(rpm_param->p.lcu_size, "lcu_size");
+avs2_dec->lcu_size = 1<<(avs2_dec->lcu_size);
+#endif
+hc->seq_header++;
+}
+
+
+void Get_I_Picture_Header(struct avs2_decoder *avs2_dec)
+{
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Dec_data_s *hd = &avs2_dec->hd;
+	union param_u *rpm_param = &avs2_dec->param;
+
+#if RD1501_FIX_BG /*//Longfei.Wang@mediatek.com*/
+	hd->background_picture_flag = 0;
+	hd->background_picture_output_flag = 0;
+	img->typeb = 0;
+#endif
+
+	hd->time_code_flag       =
+		get_param(rpm_param->p.time_code_flag,
+		"time_code_flag");
+
+	if (hd->time_code_flag) {
+		hd->time_code        =
+			get_param(rpm_param->p.time_code,
+			"time_code");
+	}
+	if (hd->background_picture_enable) {
+		hd->background_picture_flag =
+			get_param(rpm_param->p.background_picture_flag,
+			"background_picture_flag");
+
+		if (hd->background_picture_flag) {
+			img->typeb =
+				BACKGROUND_IMG;
+		} else {
+			img->typeb = 0;
+		}
+
+		if (img->typeb == BACKGROUND_IMG) {
+			hd->background_picture_output_flag =
+				get_param(
+				rpm_param->p.background_picture_output_flag,
+				"background_picture_output_flag");
+		}
+	}
+
+
+	{
+		img->coding_order         =
+			get_param(rpm_param->p.coding_order,
+			"coding_order");
+
+
+
+#if M3480_TEMPORAL_SCALABLE
+		if (hd->temporal_id_exist_flag == 1) {
+			hd->cur_layer =
+				get_param(rpm_param->p.cur_layer,
+				"temporal_id");
+		}
+#endif
+#if RD1501_FIX_BG  /*Longfei.Wang@mediatek.com*/
+		if (hd->low_delay == 0
+			&& !(hd->background_picture_flag &&
+		!hd->background_picture_output_flag)) { /*cdp*/
+#else
+			if (hd->low_delay == 0 &&
+			    !(hd->background_picture_enable &&
+			      !hd->background_picture_output_flag)) { /*cdp*/
+#endif
+				hd->displaydelay =
+					get_param(rpm_param->p.displaydelay,
+					"picture_output_delay");
+			}
+
+		}
+		{
+			int32_t RPS_idx;/* = (img->coding_order-1) % gop_size;*/
+			int32_t predict;
+			int32_t j;
+			predict =
+				get_param(rpm_param->p.predict,
+				"use RCS in SPS");
+			/*if (predict) {*/
+			RPS_idx =
+				get_param(rpm_param->p.RPS_idx,
+				"predict for RCS");
+			/*    hd->curr_RPS = hd->decod_RPS[RPS_idx];*/
+			/*} else {*/
+			/*gop size16*/
+			hd->curr_RPS.referd_by_others =
+				get_param(rpm_param->p.referd_by_others_cur,
+				"refered by others");
+			hd->curr_RPS.num_of_ref =
+				get_param(rpm_param->p.num_of_ref_cur,
+				"num of reference picture");
+			for (j = 0; j < hd->curr_RPS.num_of_ref; j++) {
+				hd->curr_RPS.ref_pic[j] =
+					get_param(rpm_param->p.ref_pic_cur[j],
+					"delta COI of ref pic");
+			}
+			hd->curr_RPS.num_to_remove =
+				get_param(rpm_param->p.num_to_remove_cur,
+				"num of removed picture");
+#ifdef SANITY_CHECK
+			if (hd->curr_RPS.num_to_remove > MAXREF)	{
+				hd->curr_RPS.num_to_remove = MAXREF;
+				pr_info("Warning, %s: num_to_remove %d beyond range, force to MAXREF\n",
+					__func__, hd->curr_RPS.num_to_remove);
+			}
+#endif
+
+			for (j = 0; j < hd->curr_RPS.num_to_remove; j++) {
+				hd->curr_RPS.remove_pic[j] =
+					get_param(
+					rpm_param->p.remove_pic_cur[j],
+					"delta COI of removed pic");
+			}
+			/*u_v(1, "marker bit");*/
+
+			/*}*/
+		}
+		/*xyji 12.23*/
+		if (hd->low_delay) {
+			/*ue_v(
+			"bbv check times");*/
+		}
+
+		hd->progressive_frame =
+			get_param(rpm_param->p.progressive_frame,
+			"progressive_frame");
+
+		if (!hd->progressive_frame) {
+			img->picture_structure   =
+				get_param(rpm_param->p.picture_structure,
+				"picture_structure");
+		} else {
+			img->picture_structure
+				= 1;
+		}
+
+		hd->top_field_first =
+			get_param(rpm_param->p.top_field_first,
+			"top_field_first");
+		hd->repeat_first_field =
+			get_param(rpm_param->p.repeat_first_field,
+			"repeat_first_field");
+#if INTERLACE_CODING
+		if (hd->is_field_sequence) {
+			hd->is_top_field         =
+				get_param(rpm_param->p.is_top_field,
+				"is_top_field");
+#if HALF_PIXEL_COMPENSATION || HALF_PIXEL_CHROMA
+			img->is_top_field       = hd->is_top_field;
+#endif
+		}
+#endif
+
+
+	img->qp                = hd->picture_qp;
+
+	img->type              = I_IMG;
+
+}
+
+/*
+ * Function:pb picture header
+ * Input:
+ * Output:
+ * Return:
+ * Attention:
+ */
+
+void Get_PB_Picture_Header(struct avs2_decoder *avs2_dec)
+{
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Dec_data_s *hd = &avs2_dec->hd;
+	union param_u *rpm_param = &avs2_dec->param;
+
+
+	/*u_v(32, "bbv delay");*/
+
+	hd->picture_coding_type                =
+		get_param(rpm_param->p.picture_coding_type,
+		"picture_coding_type");
+
+	if (hd->background_picture_enable &&
+		(hd->picture_coding_type == 1 ||
+			hd->picture_coding_type == 3)) {
+		if (hd->picture_coding_type == 1) {
+			hd->background_pred_flag       =
+				get_param(
+				rpm_param->p.background_pred_flag,
+				"background_pred_flag");
+		} else {
+			hd->background_pred_flag = 0;
+		}
+		if (hd->background_pred_flag == 0) {
+
+			hd->background_reference_enable =
+				get_param(
+				rpm_param->
+				p.background_reference_enable,
+				"background_reference_enable");
+
+		} else {
+#if RD170_FIX_BG
+			hd->background_reference_enable = 1;
+#else
+			hd->background_reference_enable = 0;
+#endif
+		}
+
+	} else {
+		hd->background_pred_flag = 0;
+		hd->background_reference_enable = 0;
+	}
+
+
+
+	if (hd->picture_coding_type == 1) {
+		img->type =
+			P_IMG;
+	} else if (hd->picture_coding_type == 3) {
+		img->type =
+			F_IMG;
+	} else {
+		img->type =
+			B_IMG;
+	}
+
+
+	if (hd->picture_coding_type == 1 &&
+		hd->background_pred_flag) {
+		img->typeb = BP_IMG;
+	} else {
+		img->typeb = 0;
+	}
+
+
+	{
+		img->coding_order         =
+			get_param(
+			rpm_param->p.coding_order,
+			"coding_order");
+
+
+#if M3480_TEMPORAL_SCALABLE
+		if (hd->temporal_id_exist_flag == 1) {
+			hd->cur_layer =
+				get_param(rpm_param->p.cur_layer,
+				"temporal_id");
+		}
+#endif
+
+		if (hd->low_delay == 0) {
+			hd->displaydelay      =
+			get_param(rpm_param->p.displaydelay,
+			"displaydelay");
+		}
+	}
+	{
+		int32_t RPS_idx;/* = (img->coding_order-1) % gop_size;*/
+		int32_t predict;
+		predict    =
+			get_param(rpm_param->p.predict,
+			"use RPS in SPS");
+		if (predict) {
+			RPS_idx =
+				get_param(rpm_param->p.RPS_idx,
+				"predict for RPS");
+			hd->curr_RPS = hd->decod_RPS[RPS_idx];
+		} /*else*/
+		{
+			/*gop size16*/
+			int32_t j;
+			hd->curr_RPS.referd_by_others =
+				get_param(
+				rpm_param->p.referd_by_others_cur,
+				"refered by others");
+			hd->curr_RPS.num_of_ref =
+				get_param(
+				rpm_param->p.num_of_ref_cur,
+				"num of reference picture");
+			for (j = 0; j < hd->curr_RPS.num_of_ref; j++) {
+				hd->curr_RPS.ref_pic[j] =
+					get_param(
+					rpm_param->p.ref_pic_cur[j],
+					"delta COI of ref pic");
+			}
+			hd->curr_RPS.num_to_remove =
+				get_param(
+				rpm_param->p.num_to_remove_cur,
+				"num of removed picture");
+#ifdef SANITY_CHECK
+			if (hd->curr_RPS.num_to_remove > MAXREF)	{
+				hd->curr_RPS.num_to_remove = MAXREF;
+				pr_info("Warning, %s: num_to_remove %d beyond range, force to MAXREF\n",
+					__func__, hd->curr_RPS.num_to_remove);
+			}
+#endif
+			for (j = 0;
+				j < hd->curr_RPS.num_to_remove; j++) {
+				hd->curr_RPS.remove_pic[j] =
+				get_param(
+					rpm_param->p.remove_pic_cur[j],
+					"delta COI of removed pic");
+			}
+			/*u_v(1, "marker bit");*/
+
+		}
+	}
+	/*xyji 12.23*/
+	if (hd->low_delay) {
+		/*ue_v(
+		"bbv check times");*/
+	}
+
+	hd->progressive_frame       =
+	get_param(rpm_param->p.progressive_frame,
+		"progressive_frame");
+
+	if (!hd->progressive_frame) {
+		img->picture_structure  =
+		get_param(rpm_param->p.picture_structure,
+			"picture_structure");
+	} else {
+		img->picture_structure  = 1;
+	}
+
+	hd->top_field_first         =
+	get_param(rpm_param->p.top_field_first,
+		"top_field_first");
+	hd->repeat_first_field      =
+	get_param(rpm_param->p.repeat_first_field,
+		"repeat_first_field");
+#if INTERLACE_CODING
+	if (hd->is_field_sequence) {
+		hd->is_top_field        =
+		get_param(rpm_param->p.is_top_field,
+			"is_top_field");
+#if HALF_PIXEL_COMPENSATION || HALF_PIXEL_CHROMA
+		img->is_top_field = hd->is_top_field;
+#endif
+		/*u_v(1, "reserved bit for interlace coding");*/
+	}
+#endif
+
+#if Check_Bitstream
+	/*assert(hd->picture_qp>=0&&hd->picture_qp<=(63 + 8 *
+	  (input->sample_bit_depth - 8)));*/
+#endif
+
+	img->random_access_decodable_flag =
+	get_param(rpm_param->p.random_access_decodable_flag,
+		"random_access_decodable_flag");
+
+	img->qp                = hd->picture_qp;
+}
+
+
+
+
+void calc_picture_distance(struct avs2_decoder *avs2_dec)
+{
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Com_data_s *hc = &avs2_dec->hc;
+	struct Video_Dec_data_s *hd = &avs2_dec->hd;
+	/*
+	union param_u *rpm_param = &avs2_dec->param;
+
+	for POC mode 0:
+	uint32_t        MaxPicDistanceLsb = (1 << 8);
+	 */
+	if (img->coding_order  <  img->PrevPicDistanceLsb)
+
+	{
+		int32_t i, j;
+
+		hc->total_frames++;
+		for (i = 0; i < avs2_dec->ref_maxbuffer; i++) {
+			if (
+				avs2_dec->fref[i]->imgtr_fwRefDistance
+				>= 0) {
+				avs2_dec->fref[i]->
+				imgtr_fwRefDistance -= 256;
+				avs2_dec->fref[i]->
+				imgcoi_ref -= 256;
+			}
+#if RD170_FIX_BG
+	for (j = 0; j < MAXREF; j++) {
+#else
+		for (j = 0; j < 4; j++) {
+#endif
+			avs2_dec->fref[i]->ref_poc[j] -= 256;
+		}
+	}
+	for (i = 0; i < avs2_dec->outprint.buffer_num; i++) {
+		avs2_dec->outprint.stdoutdata[i].framenum -= 256;
+		avs2_dec->outprint.stdoutdata[i].tr -= 256;
+	}
+
+	hd->last_output -= 256;
+	hd->curr_IDRtr -= 256;
+	hd->curr_IDRcoi -= 256;
+	hd->next_IDRtr -= 256;
+	hd->next_IDRcoi -= 256;
+	}
+	if (hd->low_delay == 0) {
+		img->tr = img->coding_order +
+		hd->displaydelay - hd->picture_reorder_delay;
+	} else {
+		img->tr =
+		img->coding_order;
+	}
+
+#if REMOVE_UNUSED
+	img->pic_distance = img->tr;
+#else
+	img->pic_distance = img->tr % 256;
+#endif
+	hc->picture_distance = img->pic_distance;
+
+}
+
+int32_t avs2_init_global_buffers(struct avs2_decoder *avs2_dec)
+{
+	struct inp_par    *input = &avs2_dec->input;
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Com_data_s *hc = &avs2_dec->hc;
+
+	int32_t refnum;
+
+	int32_t memory_size = 0;
+	/*
+int32_t img_height = (hd->vertical_size + img->auto_crop_bottom);
+	 */
+	img->buf_cycle = input->buf_cycle + 1;
+
+	img->buf_cycle *= 2;
+
+	hc->background_ref = hc->backgroundReferenceFrame;
+
+	for (refnum = 0; refnum < REF_MAXBUFFER; refnum++) {
+		avs2_dec->fref[refnum] = &avs2_dec->frm_pool[refnum];
+
+		/*//avs2_dec->fref[i] memory allocation*/
+		if (is_avs2_print_bufmgr_detail())
+			pr_info("[t] avs2_dec->fref[%d]@0x%p\n",
+			refnum, avs2_dec->fref[refnum]);
+		avs2_dec->fref[refnum]->imgcoi_ref = -257;
+		avs2_dec->fref[refnum]->is_output = -1;
+		avs2_dec->fref[refnum]->refered_by_others = -1;
+		avs2_dec->fref[refnum]->
+			imgtr_fwRefDistance = -256;
+		init_frame_t(avs2_dec->fref[refnum]);
+#ifdef AML
+		avs2_dec->fref[refnum]->index = refnum;
+#endif
+	}
+#ifdef AML
+	avs2_dec->f_bg = NULL;
+
+	avs2_dec->m_bg = &avs2_dec->frm_pool[REF_MAXBUFFER];
+		/*///avs2_dec->fref[i] memory allocation*/
+	if (is_avs2_print_bufmgr_detail())
+		pr_info("[t] avs2_dec->m_bg@0x%p\n",
+		avs2_dec->m_bg);
+	avs2_dec->m_bg->imgcoi_ref = -257;
+	avs2_dec->m_bg->is_output = -1;
+	avs2_dec->m_bg->refered_by_others = -1;
+	avs2_dec->m_bg->imgtr_fwRefDistance = -256;
+	init_frame_t(avs2_dec->m_bg);
+	avs2_dec->m_bg->index = refnum;
+#endif
+
+#if BCBR
+	/*init BCBR related*/
+	img->iNumCUsInFrame =
+		((img->width + MAX_CU_SIZE - 1) / MAX_CU_SIZE)
+		* ((img->height + MAX_CU_SIZE - 1)
+		/ MAX_CU_SIZE);
+	/*img->BLCUidx =  (int32_t*) calloc(
+	  img->iNumCUsInFrame, sizeof(int32_t));*/
+	/*memset( img->BLCUidx, 0, img->iNumCUsInFrame);*/
+#endif
+	return memory_size;
+}
+
+#ifdef AML
+static void free_unused_buffers(struct avs2_decoder *avs2_dec)
+{
+	struct inp_par    *input = &avs2_dec->input;
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Com_data_s *hc = &avs2_dec->hc;
+
+	int32_t refnum;
+
+	img->buf_cycle = input->buf_cycle + 1;
+
+	img->buf_cycle *= 2;
+
+	hc->background_ref = hc->backgroundReferenceFrame;
+
+	for (refnum = 0; refnum < REF_MAXBUFFER; refnum++) {
+#ifndef NO_DISPLAY
+		if (avs2_dec->fref[refnum]->vf_ref > 0 ||
+			avs2_dec->fref[refnum]->to_prepare_disp)
+			continue;
+#endif
+		if (is_avs2_print_bufmgr_detail())
+			pr_info("%s[t] avs2_dec->fref[%d]@0x%p\n",
+			__func__, refnum, avs2_dec->fref[refnum]);
+		avs2_dec->fref[refnum]->imgcoi_ref = -257;
+		avs2_dec->fref[refnum]->is_output = -1;
+		avs2_dec->fref[refnum]->refered_by_others = -1;
+		avs2_dec->fref[refnum]->
+			imgtr_fwRefDistance = -256;
+		memset(avs2_dec->fref[refnum]->ref_poc, 0,
+			sizeof(avs2_dec->fref[refnum]->ref_poc));
+	}
+	avs2_dec->f_bg = NULL;
+
+	if (is_avs2_print_bufmgr_detail())
+		pr_info("%s[t] avs2_dec->m_bg@0x%p\n",
+		__func__, avs2_dec->m_bg);
+	avs2_dec->m_bg->imgcoi_ref = -257;
+	avs2_dec->m_bg->is_output = -1;
+	avs2_dec->m_bg->refered_by_others = -1;
+	avs2_dec->m_bg->imgtr_fwRefDistance = -256;
+	memset(avs2_dec->m_bg->ref_poc, 0,
+		sizeof(avs2_dec->m_bg->ref_poc));
+
+#if BCBR
+	/*init BCBR related*/
+	img->iNumCUsInFrame =
+		((img->width + MAX_CU_SIZE - 1) / MAX_CU_SIZE)
+		* ((img->height + MAX_CU_SIZE - 1)
+		/ MAX_CU_SIZE);
+	/*img->BLCUidx =  (int32_t*) calloc(
+	  img->iNumCUsInFrame, sizeof(int32_t));*/
+	/*memset( img->BLCUidx, 0, img->iNumCUsInFrame);*/
+#endif
+}
+#endif
+
+void init_frame_t(struct avs2_frame_s *currfref)
+{
+	memset(currfref, 0, sizeof(struct avs2_frame_s));
+	currfref->imgcoi_ref          = -257;
+	currfref->is_output           = -1;
+	currfref->refered_by_others   = -1;
+	currfref->imgtr_fwRefDistance = -256;
+	memset(currfref->ref_poc, 0, sizeof(currfref->ref_poc));
+}
+
+void get_reference_list_info(struct avs2_decoder *avs2_dec, int8_t *str)
+{
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Com_data_s *hc = &avs2_dec->hc;
+
+	int8_t str_tmp[16];
+	int32_t i;
+	/* int32_t poc = hc->f_rec->imgtr_fwRefDistance;
+	  fred.chiu@mediatek.com*/
+
+	if (img->num_of_references > 0) {
+		strcpy(str, "[");
+		for (i = 0; i < img->num_of_references; i++) {
+#if RD1510_FIX_BG
+			if (img->type == B_IMG) {
+				sprintf(str_tmp, "%4d    ",
+					hc->f_rec->
+					ref_poc[
+					img->num_of_references - 1 - i]);
+			} else {
+				sprintf(str_tmp, "%4d    ",
+					hc->f_rec->ref_poc[i]);
+			}
+#else
+			sprintf(str_tmp, "%4d     ",
+				avs2_dec->fref[i]->imgtr_fwRefDistance);
+#endif
+
+			str_tmp[5] = '\0';
+			strcat(str, str_tmp);
+		}
+		strcat(str, "]");
+	} else {
+		str[0] = '\0';
+	}
+}
+
+void prepare_RefInfo(struct avs2_decoder *avs2_dec)
+{
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Com_data_s *hc = &avs2_dec->hc;
+	struct Video_Dec_data_s *hd = &avs2_dec->hd;
+
+	int32_t i, j;
+	int32_t ii;
+	struct avs2_frame_s *tmp_fref;
+
+	/*update IDR frame*/
+	if (img->tr > hd->next_IDRtr && hd->curr_IDRtr != hd->next_IDRtr) {
+		hd->curr_IDRtr  = hd->next_IDRtr;
+		hd->curr_IDRcoi = hd->next_IDRcoi;
+	}
+	/* re-order the ref buffer according to RPS*/
+	img->num_of_references = hd->curr_RPS.num_of_ref;
+
+#if 1
+	/*rain*/
+	if (is_avs2_print_bufmgr_detail()) {
+		pr_info("%s: coding_order is %d, curr_IDRcoi is %d\n",
+		__func__, img->coding_order, hd->curr_IDRcoi);
+		for (ii = 0; ii < MAXREF; ii++) {
+			pr_info("ref_pic(%d)=%d\n",
+			ii, hd->curr_RPS.ref_pic[ii]);
+	}
+	for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) {
+		pr_info(
+			"fref[%d]: index %d imgcoi_ref %d imgtr_fwRefDistance %d\n",
+			ii, avs2_dec->fref[ii]->index,
+			avs2_dec->fref[ii]->imgcoi_ref,
+			avs2_dec->fref[ii]->imgtr_fwRefDistance);
+	}
+	}
+#endif
+
+	for (i = 0; i < hd->curr_RPS.num_of_ref; i++) {
+		/*int32_t accumulate = 0;*/
+		/* copy tmp_fref from avs2_dec->fref[i] */
+		tmp_fref = avs2_dec->fref[i];
+
+#if REMOVE_UNUSED
+		for (j = i; j < avs2_dec->ref_maxbuffer; j++) {
+			/*/////////////to be modified  IDR*/
+			if (avs2_dec->fref[j]->imgcoi_ref ==
+				img->coding_order -
+				hd->curr_RPS.ref_pic[i]) {
+				break;
+			}
+		}
+#else
+
+		for (j = i; j < avs2_dec->ref_maxbuffer; j++) {
+			/*/////////////to be modified  IDR*/
+			int32_t k , tmp_tr;
+			for (k = 0; k < avs2_dec->ref_maxbuffer; k++) {
+				if (((int32_t)img->coding_order -
+					(int32_t)hd->curr_RPS.ref_pic[i]) ==
+					avs2_dec->fref[k]->imgcoi_ref &&
+					avs2_dec->fref[k]->imgcoi_ref >= -256) {
+					break;
+				}
+			}
+			if (k == avs2_dec->ref_maxbuffer) {
+				tmp_tr =
+				-1-1;
+			} else {
+				tmp_tr =
+					avs2_dec->fref[k]->imgtr_fwRefDistance;
+			}
+			if (tmp_tr < hd->curr_IDRtr) {
+				hd->curr_RPS.ref_pic[i] =
+					img->coding_order - hd->curr_IDRcoi;
+
+				for (k = 0; k < i; k++) {
+					if (hd->curr_RPS.ref_pic[k] ==
+						hd->curr_RPS.ref_pic[i]) {
+						accumulate++;
+						break;
+					}
+				}
+			}
+			if (avs2_dec->fref[j]->imgcoi_ref ==
+				img->coding_order - hd->curr_RPS.ref_pic[i]) {
+				break;
+			}
+		}
+		if (j == avs2_dec->ref_maxbuffer || accumulate)
+			img->num_of_references--;
+#endif
+		if (j != avs2_dec->ref_maxbuffer) {
+			/* copy avs2_dec->fref[i] from avs2_dec->fref[j] */
+			avs2_dec->fref[i] = avs2_dec->fref[j];
+			/* copy avs2_dec->fref[j] from ferf[tmp] */
+			avs2_dec->fref[j] = tmp_fref;
+			if (is_avs2_print_bufmgr_detail()) {
+				pr_info("%s, switch %d %d: ", __func__, i, j);
+				for (ii = 0; ii < hd->curr_RPS.num_of_ref
+				|| ii <= j; ii++)
+					pr_info("%d ",
+					avs2_dec->fref[ii]->index);
+				pr_info("\n");
+			}
+		}
+	}
+	if (img->type == B_IMG &&
+		(avs2_dec->fref[0]->imgtr_fwRefDistance <= img->tr
+		|| avs2_dec->fref[1]->imgtr_fwRefDistance >= img->tr)) {
+
+		pr_info("wrong reference configuration for B frame\n");
+		pr_info(
+			"fref0 imgtr_fwRefDistance %d, fref1 imgtr_fwRefDistance %d, img->tr %d\n",
+				avs2_dec->fref[0]->imgtr_fwRefDistance,
+				avs2_dec->fref[1]->imgtr_fwRefDistance,
+				img->tr);
+		hc->f_rec->error_mark = 1;
+		avs2_dec->bufmgr_error_flag = 1;
+		return; /* exit(-1);*/
+		/*******************************************/
+	}
+
+#if !FIX_PROFILE_LEVEL_DPB_RPS_1
+	/* delete the frame that will never be used*/
+	for (i = 0; i < hd->curr_RPS.num_to_remove; i++) {
+		for (j = 0; j < avs2_dec->ref_maxbuffer; j++) {
+			if (avs2_dec->fref[j]->imgcoi_ref >= -256
+				&& avs2_dec->fref[j]->imgcoi_ref
+				== img->coding_order -
+				hd->curr_RPS.remove_pic[i]) {
+				break;
+			}
+		}
+		if (j < avs2_dec->ref_maxbuffer &&
+			j >= img->num_of_references) {
+			avs2_dec->fref[j]->imgcoi_ref = -257;
+#if M3480_TEMPORAL_SCALABLE
+			avs2_dec->fref[j]->temporal_id = -1;
+#endif
+			if (avs2_dec->fref[j]->is_output == -1) {
+				avs2_dec->fref[j]->
+				imgtr_fwRefDistance = -256;
+			}
+		}
+	}
+#endif
+
+	/* add inter-view reference picture*/
+
+	/*   add current frame to ref buffer*/
+	for (i = 0; i < avs2_dec->ref_maxbuffer; i++) {
+		if ((avs2_dec->fref[i]->imgcoi_ref < -256
+			|| abs(avs2_dec->fref[i]->
+				imgtr_fwRefDistance - img->tr) >= 128)
+				&& avs2_dec->fref[i]->is_output == -1
+				&& avs2_dec->fref[i]->bg_flag == 0
+#ifndef NO_DISPLAY
+				&& avs2_dec->fref[i]->vf_ref == 0
+				&& avs2_dec->fref[i]->to_prepare_disp == 0
+#endif
+				) {
+			break;
+		}
+	}
+	if (i == avs2_dec->ref_maxbuffer) {
+		pr_info(
+			"%s, warning, no enough buf\n",
+			__func__);
+		i--;
+	}
+
+	hc->f_rec        = avs2_dec->fref[i];
+	hc->currentFrame = hc->f_rec->ref;
+	hc->f_rec->imgtr_fwRefDistance = img->tr;
+	hc->f_rec->imgcoi_ref = img->coding_order;
+#if M3480_TEMPORAL_SCALABLE
+	hc->f_rec->temporal_id = hd->cur_layer;
+#endif
+	hc->f_rec->is_output = 1;
+#ifdef AML
+	hc->f_rec->error_mark = 0;
+	hc->f_rec->decoded_lcu = 0;
+	hc->f_rec->slice_type = img->type;
+#endif
+	hc->f_rec->refered_by_others = hd->curr_RPS.referd_by_others;
+	if (is_avs2_print_bufmgr_detail())
+		pr_info(
+			"%s, set f_rec (cur_pic) <= fref[%d] img->tr %d coding_order %d img_type %d\n",
+			__func__, i, img->tr, img->coding_order,
+			img->type);
+
+	if (img->type != B_IMG) {
+		for (j = 0;
+			j < img->num_of_references; j++) {
+			hc->f_rec->ref_poc[j] =
+			avs2_dec->fref[j]->imgtr_fwRefDistance;
+		}
+	} else {
+		hc->f_rec->ref_poc[0] =
+			avs2_dec->fref[1]->imgtr_fwRefDistance;
+		hc->f_rec->ref_poc[1] =
+			avs2_dec->fref[0]->imgtr_fwRefDistance;
+	}
+
+#if M3480_TEMPORAL_SCALABLE
+
+	for (j = img->num_of_references;
+		j < 4; j++) {
+		/**/
+		hc->f_rec->ref_poc[j] = 0;
+	}
+
+	if (img->type == INTRA_IMG) {
+		int32_t l;
+		for (l = 0; l < 4; l++) {
+			hc->f_rec->ref_poc[l]
+			= img->tr;
+		}
+	}
+
+#endif
+
+/*////////////////////////////////////////////////////////////////////////*/
+	/* updata ref pointer*/
+
+	if (img->type != I_IMG) {
+
+		img->imgtr_next_P = img->type == B_IMG ?
+			avs2_dec->fref[0]->imgtr_fwRefDistance : img->tr;
+		if (img->type == B_IMG) {
+			hd->trtmp = avs2_dec->fref[0]->imgtr_fwRefDistance;
+			avs2_dec->fref[0]->imgtr_fwRefDistance =
+			avs2_dec->fref[1]->imgtr_fwRefDistance;
+		}
+	}
+#if 1
+	/*rain*/
+	if (is_avs2_print_bufmgr_detail()) {
+		for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) {
+			pr_info(
+			"fref[%d]: index %d imgcoi_ref %d imgtr_fwRefDistance %d refered %d, is_out %d, bg %d, vf_ref %d ref_pos(%d,%d,%d,%d,%d,%d,%d)\n",
+			ii, avs2_dec->fref[ii]->index,
+			avs2_dec->fref[ii]->imgcoi_ref,
+			avs2_dec->fref[ii]->imgtr_fwRefDistance,
+			avs2_dec->fref[ii]->refered_by_others,
+			avs2_dec->fref[ii]->is_output,
+			avs2_dec->fref[ii]->bg_flag,
+			avs2_dec->fref[ii]->vf_ref,
+			avs2_dec->fref[ii]->ref_poc[0],
+			avs2_dec->fref[ii]->ref_poc[1],
+			avs2_dec->fref[ii]->ref_poc[2],
+			avs2_dec->fref[ii]->ref_poc[3],
+			avs2_dec->fref[ii]->ref_poc[4],
+			avs2_dec->fref[ii]->ref_poc[5],
+			avs2_dec->fref[ii]->ref_poc[6]
+		);
+	}
+	}
+#endif
+}
+
+int32_t init_frame(struct avs2_decoder *avs2_dec)
+{
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Com_data_s *hc = &avs2_dec->hc;
+	struct Video_Dec_data_s *hd = &avs2_dec->hd;
+
+
+#if RD1510_FIX_BG
+	if (img->type == I_IMG &&
+		img->typeb == BACKGROUND_IMG) { /*G/GB frame*/
+		img->num_of_references = 0;
+	} else if (img->type == P_IMG && img->typeb == BP_IMG) {
+		/* only one reference frame(G\GB) for S frame*/
+		img->num_of_references = 1;
+	}
+#endif
+
+	if (img->typeb == BACKGROUND_IMG &&
+		hd->background_picture_output_flag == 0) {
+		hc->currentFrame = hc->background_ref;
+#ifdef AML
+		hc->cur_pic = avs2_dec->m_bg;
+#endif
+	} else {
+		prepare_RefInfo(avs2_dec);
+#ifdef AML
+		hc->cur_pic = hc->f_rec;
+#endif
+	}
+
+
+#ifdef FIX_CHROMA_FIELD_MV_BK_DIST
+	if (img->typeb == BACKGROUND_IMG
+		&& img->is_field_sequence) {
+		avs2_dec->bk_img_is_top_field
+			= img->is_top_field;
+	}
+#endif
+	return 0;
+}
+
+void delete_trbuffer(struct outdata_s *data, int32_t pos)
+{
+	int32_t i;
+	for (i = pos;
+		i < data->buffer_num - 1; i++) {
+		data->stdoutdata[i] =
+		data->stdoutdata[i + 1];
+	}
+	data->buffer_num--;
+}
+
+#if RD170_FIX_BG
+void flushDPB(struct avs2_decoder *avs2_dec)
+{
+	struct Video_Dec_data_s *hd = &avs2_dec->hd;
+	int j, tmp_min, i, pos = -1;
+	int search_times = avs2_dec->outprint.buffer_num;
+
+	tmp_min = 1 << 20;
+	i = 0, j = 0;
+	pos = -1;
+
+	for (j = 0; j < search_times; j++) {
+		pos = -1;
+		tmp_min = (1 << 20);
+		/*search for min poi picture to display*/
+		for (i = 0; i < avs2_dec->outprint.buffer_num; i++) {
+			if (avs2_dec->outprint.stdoutdata[i].tr < tmp_min) {
+				pos = i;
+				tmp_min = avs2_dec->outprint.stdoutdata[i].tr;
+			}
+		}
+
+		if (pos != -1) {
+			hd->last_output = avs2_dec->outprint.stdoutdata[pos].tr;
+			report_frame(avs2_dec, &avs2_dec->outprint, pos);
+			if (avs2_dec->outprint.stdoutdata[pos].typeb
+				== BACKGROUND_IMG &&
+			avs2_dec->outprint.stdoutdata[pos].
+			background_picture_output_flag
+			== 0) {
+				/*write_GB_frame(hd->p_out_background);*/
+			} else {
+				write_frame(avs2_dec,
+					avs2_dec->outprint.stdoutdata[pos].tr);
+			}
+
+			delete_trbuffer(&avs2_dec->outprint, pos);
+		}
+	}
+
+	/*clear dpb info*/
+	for (j = 0; j < REF_MAXBUFFER; j++) {
+		avs2_dec->fref[j]->imgtr_fwRefDistance = -256;
+		avs2_dec->fref[j]->imgcoi_ref = -257;
+		avs2_dec->fref[j]->temporal_id = -1;
+		avs2_dec->fref[j]->refered_by_others = 0;
+	}
+}
+#endif
+
+
+
+#if M3480_TEMPORAL_SCALABLE
+void cleanRefMVBufRef(int pos)
+{
+#if 0
+	int k, x, y;
+	/*re-init mvbuf*/
+	for (k = 0; k < 2; k++) {
+		for (y = 0; y < img->height / MIN_BLOCK_SIZE; y++) {
+			for (x = 0; x < img->width / MIN_BLOCK_SIZE; x++)
+				fref[pos]->mvbuf[y][x][k] = 0;
+
+		}
+	}
+	/*re-init refbuf*/
+	for (y = 0; y < img->height / MIN_BLOCK_SIZE; y++) {
+		for (x = 0; x < img->width / MIN_BLOCK_SIZE ; x++)
+			fref[pos]->refbuf[y][x] = -1;
+
+	}
+#endif
+}
+#endif
+
+static int frame_postprocessing(struct avs2_decoder *avs2_dec)
+{
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Com_data_s *hc = &avs2_dec->hc;
+	struct Video_Dec_data_s *hd = &avs2_dec->hd;
+
+	int32_t pointer_tmp = avs2_dec->outprint.buffer_num;
+	int32_t i;
+	struct STDOUT_DATA_s *p_outdata;
+#if RD160_FIX_BG
+	int32_t j, tmp_min, output_cur_dec_pic, pos = -1;
+	int32_t search_times = avs2_dec->outprint.buffer_num;
+#endif
+	/*pic dist by Grandview Semi. @ [06-07-20 15:25]*/
+	img->PrevPicDistanceLsb = (img->coding_order % 256);
+
+	pointer_tmp = avs2_dec->outprint.buffer_num;
+	p_outdata   = &avs2_dec->outprint.stdoutdata[pointer_tmp];
+
+	p_outdata->type = img->type;
+	p_outdata->typeb = img->typeb;
+	p_outdata->framenum = img->tr;
+	p_outdata->tr = img->tr;
+#if 0 /*def ORI*/
+	p_outdata->qp = img->qp;
+#else
+	p_outdata->qp = 0;
+#endif
+	/*p_outdata->snr_y = snr->snr_y;*/
+	/*p_outdata->snr_u = snr->snr_u;*/
+	/*p_outdata->snr_v = snr->snr_v;*/
+	p_outdata->tmp_time = hd->tmp_time;
+	p_outdata->picture_structure = img->picture_structure;
+	/*p_outdata->curr_frame_bits =
+	  StatBitsPtr->curr_frame_bits;*/
+	/*p_outdata->emulate_bits = StatBitsPtr->emulate_bits;*/
+#if RD1501_FIX_BG
+	p_outdata->background_picture_output_flag
+		= hd->background_picture_output_flag;
+		/*Longfei.Wang@mediatek.com*/
+#endif
+
+#if RD160_FIX_BG
+	p_outdata->picture_reorder_delay = hd->picture_reorder_delay;
+#endif
+	avs2_dec->outprint.buffer_num++;
+
+#if RD170_FIX_BG
+	search_times = avs2_dec->outprint.buffer_num;
+#endif
+	/* record the reference list*/
+	strcpy(p_outdata->str_reference_list, hc->str_list_reference);
+
+#if !REF_OUTPUT
+	#error "!!!REF_OUTPUT should be 1"
+	for (i = 0; i < avs2_dec->outprint.buffer_num; i++) {
+		min_tr(avs2_dec->outprint, &pos);
+		if (avs2_dec->outprint.stdoutdata[pos].tr < img->tr
+			|| avs2_dec->outprint.stdoutdata[pos].tr
+			== (hd->last_output + 1)) {
+			hd->last_output = avs2_dec->outprint.stdoutdata[pos].tr;
+			report_frame(avs2_dec, &avs2_dec->outprint, pos);
+#if 0 /*def ORI*/
+			write_frame(hd->p_out,
+			avs2_dec->outprint.stdoutdata[pos].tr);
+#endif
+			delete_trbuffer(&avs2_dec->outprint, pos);
+			i--;
+		} else {
+			break;
+		}
+	}
+#else
+#if RD160_FIX_BG /*Longfei.Wang@mediatek.com*/
+	tmp_min = 1 << 20;
+	i = 0, j = 0;
+	output_cur_dec_pic = 0;
+	pos = -1;
+	for (j = 0; j < search_times; j++) {
+		pos = -1;
+		tmp_min = (1 << 20);
+		/*search for min poi picture to display*/
+		for (i = 0; i < avs2_dec->outprint.buffer_num; i++) {
+			if ((avs2_dec->outprint.stdoutdata[i].tr < tmp_min) &&
+				((avs2_dec->outprint.stdoutdata[i].tr
+				+ avs2_dec->outprint.stdoutdata[i].
+					picture_reorder_delay)
+				<= (int32_t)img->coding_order)) {
+				pos = i;
+				tmp_min = avs2_dec->outprint.stdoutdata[i].tr;
+			}
+		}
+
+		if ((0 == hd->displaydelay) && (0 == output_cur_dec_pic)) {
+			if (img->tr <= tmp_min)	{/*fred.chiu@mediatek.com*/
+				/*output current decode picture
+				  right now*/
+				pos = avs2_dec->outprint.buffer_num - 1;
+				output_cur_dec_pic = 1;
+			}
+		}
+		if (pos != -1) {
+			hd->last_output = avs2_dec->outprint.stdoutdata[pos].tr;
+			report_frame(avs2_dec, &avs2_dec->outprint, pos);
+#if 1 /*def ORI*/
+			if (avs2_dec->outprint.stdoutdata[pos].typeb
+				== BACKGROUND_IMG &&
+				avs2_dec->outprint.stdoutdata[pos].
+				background_picture_output_flag == 0) {
+				/**/
+				/**/
+			} else {
+				write_frame(avs2_dec,
+				avs2_dec->outprint.stdoutdata[pos].tr);
+			}
+#endif
+			delete_trbuffer(&avs2_dec->outprint, pos);
+		}
+
+	}
+
+#else
+	#error "!!!RD160_FIX_BG should be defined"
+	if (img->coding_order +
+		(uint32_t)hc->total_frames * 256 >=
+		(uint32_t)hd->picture_reorder_delay) {
+		int32_t tmp_min, pos = -1;
+		tmp_min = 1 << 20;
+
+		for (i = 0; i <
+			avs2_dec->outprint.buffer_num; i++) {
+			if (avs2_dec->outprint.stdoutdata[i].tr
+				< tmp_min &&
+				avs2_dec->outprint.stdoutdata[i].tr
+				>= hd->last_output) {
+				/*GB has the same "tr" with "last_output"*/
+				pos = i;
+				tmp_min =
+				avs2_dec->outprint.stdoutdata[i].tr;
+			}
+		}
+
+		if (pos != -1) {
+			hd->last_output = avs2_dec->outprint.stdoutdata[pos].tr;
+			report_frame(avs2_dec, &avs2_dec->outprint, pos);
+#if RD1501_FIX_BG
+			if (avs2_dec->outprint.stdoutdata[pos].typeb
+				== BACKGROUND_IMG && avs2_dec->
+				outprint.stdoutdata[pos].
+				background_picture_output_flag == 0) {
+#else
+				if (avs2_dec->outprint.stdoutdata[pos].typeb
+					== BACKGROUND_IMG &&
+					hd->background_picture_output_flag
+					== 0) {
+#endif
+					write_GB_frame(
+						hd->p_out_background);
+				} else {
+					write_frame(avs2_dec,
+					avs2_dec->outprint.stdoutdata[pos].tr);
+				}
+				delete_trbuffer(&avs2_dec->outprint, pos);
+
+			}
+
+		}
+#endif
+#endif
+	return pos;
+
+	}
+
+void write_frame(struct avs2_decoder *avs2_dec, int32_t pos)
+{
+	int32_t j;
+
+	if (is_avs2_print_bufmgr_detail())
+		pr_info("%s(pos = %d)\n", __func__, pos);
+
+	for (j = 0; j < avs2_dec->ref_maxbuffer; j++) {
+		if (avs2_dec->fref[j]->imgtr_fwRefDistance == pos) {
+			avs2_dec->fref[j]->imgtr_fwRefDistance_bak = pos;
+			avs2_dec->fref[j]->is_output = -1;
+			avs2_dec->fref[j]->to_prepare_disp =
+				avs2_dec->to_prepare_disp_count++;
+			if (avs2_dec->fref[j]->refered_by_others == 0
+				|| avs2_dec->fref[j]->imgcoi_ref
+				== -257) {
+				avs2_dec->fref[j]->imgtr_fwRefDistance
+					= -256;
+				avs2_dec->fref[j]->imgcoi_ref = -257;
+#if M3480_TEMPORAL_SCALABLE
+				avs2_dec->fref[j]->temporal_id = -1;
+#endif
+				if (is_avs2_print_bufmgr_detail())
+					pr_info("%s, fref index %d\n",
+						 __func__, j);
+			}
+			break;
+		}
+	}
+}
+
+/*rain???, outdata *data*/
+void report_frame(struct avs2_decoder *avs2_dec,
+	struct outdata_s *data, int32_t pos)
+{
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Com_data_s *hc = &avs2_dec->hc;
+	struct Video_Dec_data_s *hd = &avs2_dec->hd;
+
+	int8_t *Frmfld;
+	int8_t Frm[] = "FRM";
+	int8_t Fld[] = "FLD";
+	struct STDOUT_DATA_s *p_stdoutdata
+	= &data->stdoutdata[pos];
+	const int8_t *typ;
+
+#if 0
+	if (input->MD5Enable & 0x02) {
+		sprintf(MD5str, "%08X%08X%08X%08X\0",
+				p_stdoutdata->DecMD5Value[0],
+				p_stdoutdata->DecMD5Value[1],
+				p_stdoutdata->DecMD5Value[2],
+				p_stdoutdata->DecMD5Value[3]);
+	} else {
+		memset(MD5val, 0, 16);
+		memset(MD5str, 0, 33);
+	}
+#endif
+
+	if (p_stdoutdata->
+		picture_structure) {
+		Frmfld = Frm;
+	} else {
+		Frmfld = Fld;
+	}
+#if INTERLACE_CODING
+	if (img->is_field_sequence) { /*rcs??*/
+		Frmfld = Fld;
+	}
+#endif
+	if ((p_stdoutdata->tr + hc->total_frames * 256)
+	    == hd->end_SeqTr) {   /* I picture*/
+		/*if ( img->new_sequence_flag == 1 )*/
+		{
+			img->sequence_end_flag = 0;
+			/*fprintf(stdout, "Sequence
+			  End\n\n");*/
+		}
+	}
+	if ((p_stdoutdata->tr + hc->total_frames * 256)
+		== hd->next_IDRtr) {
+#if !RD170_FIX_BG
+		if (hd->vec_flag) /**/
+#endif
+		{
+			hd->vec_flag = 0;
+			/*fprintf(stdout, "Video Edit
+			  Code\n");*/
+		}
+	}
+
+	if (p_stdoutdata->typeb == BACKGROUND_IMG) {
+		typ = (hd->background_picture_output_flag != 0) ? "G" : "GB";
+	} else {
+#if REMOVE_UNUSED
+		typ = (p_stdoutdata->type == INTRA_IMG)
+			? "I" : (p_stdoutdata->type == INTER_IMG) ?
+			((p_stdoutdata->typeb == BP_IMG) ? "S" : "P")
+			: (p_stdoutdata->type == F_IMG ? "F" : "B");
+#else
+		typ = (p_stdoutdata->type == INTRA_IMG) ? "I" :
+			(p_stdoutdata->type == INTER_IMG) ?
+			((p_stdoutdata->type == BP_IMG) ? "S" : "P")
+			: (p_stdoutdata->type == F_IMG ? "F" : "B");
+#endif
+	}
+
+#if 0
+	/*rain???*/
+	pr_info("%3d(%s)  %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\t%s",
+			p_stdoutdata->framenum + hc->total_frames * 256,
+			typ, p_stdoutdata->tr + hc->total_frames * 256,
+			p_stdoutdata->qp, p_stdoutdata->snr_y,
+			p_stdoutdata->snr_u, p_stdoutdata->snr_v,
+			p_stdoutdata->tmp_time, Frmfld,
+			p_stdoutdata->curr_frame_bits,
+			p_stdoutdata->emulate_bits,
+			"");
+#endif
+	if (is_avs2_print_bufmgr_detail())
+		pr_info(" %s\n", p_stdoutdata->str_reference_list);
+
+	/*fflush(stdout);*/
+	hd->FrameNum++;
+}
+
+void avs2_prepare_header(struct avs2_decoder *avs2_dec, int32_t start_code)
+{
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Dec_data_s *hd = &avs2_dec->hd;
+
+	switch (start_code) {
+	case SEQUENCE_HEADER_CODE:
+		img->new_sequence_flag = 1;
+		if (is_avs2_print_bufmgr_detail())
+			pr_info("SEQUENCE\n");
+#ifdef TO_CHECK
+#if SEQ_CHANGE_CHECKER
+		if (seq_checker_buf == NULL) {
+			seq_checker_buf = malloc(length);
+			seq_checker_length = length;
+			memcpy(seq_checker_buf, Buf, length);
+		} else {
+			if ((seq_checker_length != length) ||
+				(memcmp(seq_checker_buf, Buf, length) != 0)) {
+				free(seq_checker_buf);
+				/*fprintf(stdout,
+				  "Non-conformance
+				  stream: sequence
+				  header cannot change
+				  !!\n");*/
+#if RD170_FIX_BG
+				seq_checker_buf = NULL;
+				seq_checker_length = 0;
+				seq_checker_buf = malloc(length);
+				seq_checker_length = length;
+				memcpy(seq_checker_buf, Buf, length);
+#endif
+			}
+
+
+		}
+#endif
+#if RD170_FIX_BG
+		if (input->alf_enable
+			&& alfParAllcoated == 1) {
+			ReleaseAlfGlobalBuffer();
+			alfParAllcoated = 0;
+		}
+#endif
+/*TO_CHECK*/
+#endif
+#if FIX_FLUSH_DPB_BY_LF
+		if (hd->vec_flag) {
+			int32_t k;
+			if (is_avs2_print_bufmgr_detail())
+				pr_info("vec_flag is 1, flushDPB and reinit bugmgr\n");
+
+			flushDPB(avs2_dec);
+			for (k = 0; k < avs2_dec->ref_maxbuffer; k++)
+				cleanRefMVBufRef(k);
+
+			hd->vec_flag = 0;
+#ifdef AML
+			free_unused_buffers(avs2_dec);
+#else
+			free_global_buffers(avs2_dec);
+#endif
+			img->number = 0;
+			img->PrevPicDistanceLsb = 0;
+			avs2_dec->init_hw_flag = 0;
+		}
+#endif
+
+#if FIX_SEQ_END_FLUSH_DPB_BY_LF
+		if (img->new_sequence_flag
+			&& img->sequence_end_flag) {
+			int32_t k;
+			if (is_avs2_print_bufmgr_detail())
+				pr_info(
+				"new_sequence_flag after sequence_end_flag, flushDPB and reinit bugmgr\n");
+			flushDPB(avs2_dec);
+			for (k = 0; k < avs2_dec->ref_maxbuffer; k++)
+				cleanRefMVBufRef(k);
+
+#ifdef AML
+			free_unused_buffers(avs2_dec);
+#else
+			free_global_buffers(avs2_dec);
+#endif
+			img->number = 0;
+			img->PrevPicDistanceLsb = 0;
+			avs2_dec->init_hw_flag = 0;
+		}
+#endif
+		img->seq_header_indicate = 1;
+		break;
+	case I_PICTURE_START_CODE:
+		if (is_avs2_print_bufmgr_detail())
+			pr_info("PIC-I\n");
+		Get_SequenceHeader(avs2_dec);
+		Get_I_Picture_Header(avs2_dec);
+		calc_picture_distance(avs2_dec);
+		Read_ALF_param(avs2_dec);
+		if (!img->seq_header_indicate) {
+			img->B_discard_flag = 1;
+			/*fprintf(stdout, "    I
+			  %3d\t\tDIDSCARD!!\n",
+			  img->tr);*/
+			break;
+		}
+		break;
+	case PB_PICTURE_START_CODE:
+		if (is_avs2_print_bufmgr_detail())
+			pr_info("PIC-PB\n");
+		Get_SequenceHeader(avs2_dec);
+		Get_PB_Picture_Header(avs2_dec);
+		calc_picture_distance(avs2_dec);
+		Read_ALF_param(avs2_dec);
+		/* xiaozhen zheng, 20071009*/
+		if (!img->seq_header_indicate) {
+			img->B_discard_flag = 1;
+
+			if (img->type == P_IMG) {
+				/*fprintf(stdout, "    P
+				  %3d\t\tDIDSCARD!!\n",
+				  img->tr);*/
+			}
+			if (img->type == F_IMG) {
+				/*fprintf(stdout, "    F
+				  %3d\t\tDIDSCARD!!\n",
+				  img->tr);*/
+			} else {
+				/*fprintf(stdout, "    B
+				  %3d\t\tDIDSCARD!!\n",
+				  img->tr);*/
+			}
+
+			break;
+		}
+
+		if (img->seq_header_indicate == 1
+			&& img->type != B_IMG) {
+			img->B_discard_flag = 0;
+		}
+		if (img->type == B_IMG && img->B_discard_flag == 1
+			&& !img->random_access_decodable_flag) {
+			/*fprintf(stdout, "    B
+			  %3d\t\tDIDSCARD!!\n",
+			  img->tr);*/
+			break;
+		}
+
+		break;
+	case SEQUENCE_END_CODE:
+		if (is_avs2_print_bufmgr_detail())
+			pr_info("SEQUENCE_END_CODE\n");
+#ifdef TO_CHECK
+#if SEQ_CHANGE_CHECKER
+		if (seq_checker_buf != NULL) {
+			free(seq_checker_buf);
+			seq_checker_buf = NULL;
+			seq_checker_length = 0;
+		}
+#endif
+#endif
+img->new_sequence_flag = 1;
+img->sequence_end_flag = 1;
+break;
+	case VIDEO_EDIT_CODE:
+		if (is_avs2_print_bufmgr_detail())
+			pr_info("VIDEO_EDIT_CODE\n");
+		/*video_edit_code_data(Buf, startcodepos, length);*/
+		hd->vec_flag = 1;
+#ifdef TO_CHECK
+#if SEQ_CHANGE_CHECKER
+		if (seq_checker_buf != NULL) {
+			free(seq_checker_buf);
+			seq_checker_buf = NULL;
+			seq_checker_length = 0;
+		}
+#endif
+#endif
+
+break;
+	}
+}
+
+#ifdef AML
+static uint32_t log2i(uint32_t val)
+{
+	uint32_t ret = -1;
+	while (val != 0) {
+		val >>= 1;
+		ret++;
+	}
+	return ret;
+}
+#endif
+
+int32_t avs2_process_header(struct avs2_decoder *avs2_dec)
+{
+	struct inp_par    *input = &avs2_dec->input;
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Dec_data_s *hd = &avs2_dec->hd;
+	int32_t lcu_x_num_div;
+	int32_t lcu_y_num_div;
+
+	int32_t N8_SizeScale;
+	/*pr_info("%s\n", __func__);*/
+	{
+		N8_SizeScale = 1;
+
+		if (hd->horizontal_size %
+			(MIN_CU_SIZE * N8_SizeScale) != 0) {
+			img->auto_crop_right =
+				(MIN_CU_SIZE * N8_SizeScale) -
+				(hd->horizontal_size %
+				(MIN_CU_SIZE * N8_SizeScale));
+		} else
+			img->auto_crop_right = 0;
+
+#if !INTERLACE_CODING
+		if (hd->progressive_sequence) /**/
+#endif
+		{
+			if (hd->vertical_size %
+				(MIN_CU_SIZE * N8_SizeScale) != 0) {
+				img->auto_crop_bottom =
+				(MIN_CU_SIZE * N8_SizeScale) -
+				(hd->vertical_size %
+				(MIN_CU_SIZE * N8_SizeScale));
+			} else
+				img->auto_crop_bottom = 0;
+		}
+
+		/* Reinit parameters (NOTE: need to do
+		  before init_frame //*/
+		img->width          =
+			(hd->horizontal_size + img->auto_crop_right);
+		img->height         =
+			(hd->vertical_size + img->auto_crop_bottom);
+		img->width_cr       = (img->width >> 1);
+
+		if (input->chroma_format == 1)
+			img->height_cr      = (img->height >> 1);
+
+		img->PicWidthInMbs  = img->width / MIN_CU_SIZE;
+		img->PicHeightInMbs = img->height / MIN_CU_SIZE;
+		img->PicSizeInMbs   = img->PicWidthInMbs * img->PicHeightInMbs;
+		img->max_mb_nr      = (img->width * img->height) /
+			(MIN_CU_SIZE * MIN_CU_SIZE);
+	}
+
+	if (img->new_sequence_flag && img->sequence_end_flag) {
+#if 0/*RD170_FIX_BG //*/
+		int32_t k;
+		flushDPB();
+		for (k = 0; k < avs2_dec->ref_maxbuffer; k++)
+			cleanRefMVBufRef(k);
+
+		free_global_buffers();
+		img->number = 0;
+#endif
+		hd->end_SeqTr = img->tr;
+		img->sequence_end_flag = 0;
+	}
+	if (img->new_sequence_flag) {
+		hd->next_IDRtr = img->tr;
+		hd->next_IDRcoi = img->coding_order;
+		img->new_sequence_flag = 0;
+	}
+#if 0/*RD170_FIX_BG*/
+	if (hd->vec_flag) {
+		int32_t k;
+		flushDPB();
+		for (k = 0; k < avs2_dec->ref_maxbuffer; k++)
+			cleanRefMVBufRef(k);
+
+		hd->vec_flag = 0;
+		free_global_buffers();
+		img->number = 0;
+	}
+#endif
+/* allocate memory for frame buffers*/
+#if 0
+/* called in vavs2.c*/
+	if (img->number == 0)
+		avs2_init_global_buffers(avs2_dec);
+#endif
+	img->current_mb_nr = 0;
+
+	init_frame(avs2_dec);
+
+	img->types = img->type;   /* jlzheng 7.15*/
+
+	if (img->type != B_IMG) {
+		hd->pre_img_type = img->type;
+		hd->pre_img_types = img->types;
+	}
+
+#ifdef AML
+	avs2_dec->lcu_size_log2 = log2i(avs2_dec->lcu_size);
+	lcu_x_num_div = (img->width/avs2_dec->lcu_size);
+	lcu_y_num_div = (img->height/avs2_dec->lcu_size);
+	avs2_dec->lcu_x_num = ((img->width % avs2_dec->lcu_size) == 0) ?
+		lcu_x_num_div : lcu_x_num_div+1;
+	avs2_dec->lcu_y_num = ((img->height % avs2_dec->lcu_size) == 0) ?
+		lcu_y_num_div : lcu_y_num_div+1;
+	avs2_dec->lcu_total = avs2_dec->lcu_x_num*avs2_dec->lcu_y_num;
+#endif
+	return SOP;
+}
+
+int avs2_post_process(struct avs2_decoder *avs2_dec)
+{
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Com_data_s *hc = &avs2_dec->hc;
+	struct Video_Dec_data_s *hd = &avs2_dec->hd;
+	int32_t i;
+	int ret;
+	if (img->typeb == BACKGROUND_IMG && hd->background_picture_enable) {
+#ifdef AML
+		for (i = 0; i < avs2_dec->ref_maxbuffer; i++) {
+			if (avs2_dec->fref[i]->bg_flag != 0) {
+				avs2_dec->fref[i]->bg_flag = 0;
+				if (is_avs2_print_bufmgr_detail())
+					pr_info(
+					"clear old BACKGROUND_IMG for index %d\r\n",
+					avs2_dec->fref[i]->index);
+			}
+		}
+		if (is_avs2_print_bufmgr_detail())
+			pr_info(
+			"post_process: set BACKGROUND_IMG flag for %d\r\n",
+			hc->cur_pic->index);
+		avs2_dec->f_bg = hc->cur_pic;
+		hc->cur_pic->bg_flag = 1;
+#endif
+	}
+
+#if BCBR
+	if (hd->background_picture_enable
+		&& hd->bcbr_enable && img->number > 0)
+		updateBgReference();
+#endif
+
+	if (img->typeb == BACKGROUND_IMG &&
+		hd->background_picture_output_flag == 0)
+		hd->background_number++;
+
+	if (img->type == B_IMG) {
+		avs2_dec->fref[0]->imgtr_fwRefDistance
+		= hd->trtmp;
+	}
+
+	/* record the reference list information*/
+	get_reference_list_info(avs2_dec, avs2_dec->hc.str_list_reference);
+
+	/*pr_info("%s\n", __func__);*/
+	ret = frame_postprocessing(avs2_dec);
+
+#if FIX_PROFILE_LEVEL_DPB_RPS_1
+	/* delete the frame that will never be used*/
+	{
+		int32_t i, j;
+		if (is_avs2_print_bufmgr_detail()) {
+			pr_info(
+				"%s, coding_order %d to remove %d buf: ",
+				__func__,
+				img->coding_order,
+				hd->curr_RPS.num_to_remove);
+			for (i = 0; i < hd->curr_RPS.num_to_remove; i++)
+				pr_info("%d ", hd->curr_RPS.remove_pic[i]);
+			pr_info("\n");
+		}
+		for (i = 0; i < hd->curr_RPS.num_to_remove; i++) {
+			for (j = 0; j < avs2_dec->ref_maxbuffer; j++) {
+
+				if (avs2_dec->fref[j]->imgcoi_ref >= -256
+					&& avs2_dec->fref[j]->imgcoi_ref ==
+					img->coding_order -
+					hd->curr_RPS.remove_pic[i])
+					break;
+			}
+			if (j < avs2_dec->ref_maxbuffer) { /**/
+#if FIX_RPS_PICTURE_REMOVE
+/* Label new frames as "un-referenced" */
+				avs2_dec->fref[j]->refered_by_others = 0;
+
+				/* remove frames which have been outputted */
+				if (avs2_dec->fref[j]->is_output == -1) {
+					avs2_dec->fref[j]->
+					imgtr_fwRefDistance = -256;
+					avs2_dec->fref[j]->imgcoi_ref = -257;
+					avs2_dec->fref[j]->temporal_id = -1;
+
+				}
+#else
+				avs2_dec->fref[j]->imgcoi_ref = -257;
+#if M3480_TEMPORAL_SCALABLE
+				avs2_dec->fref[j]->temporal_id = -1;
+#endif
+				if (avs2_dec->fref[j]->is_output == -1) {
+					avs2_dec->fref[j]->imgtr_fwRefDistance
+						= -256;
+				}
+#endif
+			}
+		}
+	}
+#endif
+
+
+	/*! TO 19.11.2001 Known Problem: for init_frame
+	 * we have to know the picture type of the
+	 * actual frame*/
+	/*! in case the first slice of the P-Frame
+	 * following the I-Frame was lost we decode this
+	 * P-Frame but! do not write it because it
+	 * was
+	 * assumed to be an I-Frame in init_frame.So we
+	 * force the decoder to*/
+	/*! guess the right picture type. This is a hack
+	 * a should be removed by the time there is a
+	 * clean*/
+	/*! solution where we do not have to know the
+	 * picture type for the function init_frame.*/
+	/*! End TO 19.11.2001//Lou*/
+
+	{
+		if (img->type == I_IMG ||
+			img->type == P_IMG ||
+			img->type == F_IMG)
+			img->number++;
+		else {
+			hc->Bframe_ctr++;  /* B
+					      pictures*/
+		}
+	}
+	return ret;
+}
+
+void init_avs2_decoder(struct avs2_decoder *avs2_dec)
+{
+	int32_t i, j, k;
+
+	struct inp_par    *input = &avs2_dec->input;
+	struct ImageParameters_s    *img = &avs2_dec->img;
+	struct Video_Com_data_s *hc = &avs2_dec->hc;
+	struct Video_Dec_data_s *hd = &avs2_dec->hd;
+	if (is_avs2_print_bufmgr_detail())
+		pr_info("[t] struct avs2_dec @0x%p\n", avs2_dec);
+	memset(avs2_dec, 0, sizeof(struct avs2_decoder));
+#ifdef AML
+	avs2_dec->to_prepare_disp_count = 1;
+#endif
+	/*
+	 * ALFParam init
+	 */
+	for (i = 0; i < 3; i++) {
+		avs2_dec->m_alfPictureParam[i].alf_flag = 0; /*1*/
+		avs2_dec->m_alfPictureParam[i].num_coeff = 9; /*1*/
+		avs2_dec->m_alfPictureParam[i].filters_per_group = 3;  /*1*/
+		avs2_dec->m_alfPictureParam[i].componentID = i; /*1*/
+		for (j = 0; j < 16; j++) {
+			avs2_dec->m_alfPictureParam[i].filterPattern[j]	= 0;
+			/*16*/
+		}
+		for (j = 0; j < 16; j++) {
+			for (k = 0; k < 9; k++) {
+				avs2_dec->
+				m_alfPictureParam[i].coeffmulti[j][k] = 0;
+				/*16*9*/
+			}
+		}
+	}
+
+	img->seq_header_indicate = 0;
+	img->B_discard_flag = 0;
+
+	hd->eos = 0;
+
+	if (input->ref_pic_order) {   /*ref order*/
+		hd->dec_ref_num = 0;
+	}
+
+	/*
+	memset(g_log2size, -1, MAX_CU_SIZE + 1);
+	c = 2;
+	for (k = 4; k <= MAX_CU_SIZE; k *= 2) {
+		g_log2size[k] = c;
+		c++;
+	}
+	 */
+
+	avs2_dec->outprint.buffer_num = 0;
+
+	hd->last_output = -1;
+	hd->end_SeqTr = -1;
+	hd->curr_IDRtr = 0;
+	hd->curr_IDRcoi = 0;
+	hd->next_IDRtr = 0;
+	hd->next_IDRcoi = 0;
+	/* Allocate Slice data struct*/
+	img->number = 0;
+	img->type = I_IMG;
+
+	img->imgtr_next_P = 0;
+
+	img->imgcoi_next_ref = 0;
+
+
+	img->num_of_references = 0;
+	hc->seq_header = 0;
+
+	img->new_sequence_flag   = 1;
+
+	hd->vec_flag = 0;
+
+	hd->FrameNum = 0;
+
+	/* B pictures*/
+	hc->Bframe_ctr = 0;
+	hc->total_frames = 0;
+
+	/* time for total decoding session*/
+	hc->tot_time = 0;
+
+}
+
diff --git a/drivers/frame_provider/decoder/avs2/avs2_global.h b/drivers/frame_provider/decoder/avs2/avs2_global.h
new file mode 100644
index 0000000..be35a5e
--- /dev/null
+++ b/drivers/frame_provider/decoder/avs2/avs2_global.h
@@ -0,0 +1,1690 @@
+/* The copyright in this software is being made available under the BSD
+ * License, included below. This software may be subject to other third party
+ * and contributor rights, including patent rights, and no such rights are
+ * granted under this license.
+ *
+ * Copyright (c) 2002-2016, Audio Video coding Standard Workgroup of China
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *  * Neither the name of Audio Video coding Standard Workgroup of China
+ *    nor the names of its contributors maybe
+ *    used to endorse or promote products
+ *    derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+
+/*
+ * File name: global.h
+ * Function:  global definitions for for AVS decoder.
+ *
+ */
+
+#ifndef _GLOBAL_H_
+#define _GLOBAL_H_
+
+/* #include <stdio.h>                              //!< for FILE */
+/* #include <stdlib.h> */
+
+#define AML
+#define SANITY_CHECK
+#undef NO_DISPLAY
+
+/* #include "define.h" */
+#define RD      "19.2"
+#define VERSION "19.2"
+
+#define RESERVED_PROFILE_ID      0x24
+#define BASELINE_PICTURE_PROFILE 18
+#define BASELINE_PROFILE         32  /* 0x20 */
+#define BASELINE10_PROFILE       34  /* 0x22 */
+
+
+#define SCENE_PROFILE            48  /* 0x21 */
+#define SCENE10_PROFILE          50  /* 0x23 */
+
+#define TRACE                    0 /* !< 0:Trace off 1:Trace on */
+
+
+/* Type definitions and file operation for Windows/Linux
+ * All file operations for windows are replaced with native (FILE *) operations
+ * Falei LUO (falei.luo@vipl.ict.ac.cn)
+ * */
+
+#define _FILE_OFFSET_BITS 64       /* for 64 bit fseeko */
+#define fseek fseeko
+
+#define int16 int16_t
+#define int64 int64_t
+
+/* ////////////////// bug fix ///////////////////////////// */
+#define ALFSliceFix                        1
+#define WRITENBIT_FIX                      1
+#define FIX_PROFILE_LEVEL_DPB_RPS_1        1
+#define FIX_PROFILE_LEVEL_DPB_RPS_2        1
+#define FIX_RPS_PICTURE_REMOVE             1   /* flluo@pku.edu.cn */
+#define Mv_Clip                            1   /* yuquanhe@hisilicon.com */
+#define REMOVE_UNUSED                      1   /* yuquanhe@hisilicon.com */
+#define SAO_Height_Fix                     1   /* yuquanhe@hisilicon.com */
+#define B_BACKGROUND_Fix                   1   /* yuquanhe@hisilicon.com */
+#define Check_Bitstream                    1   /* yuquanhe@hisilicon.com */
+#define Wq_param_Clip                      1   /* yuquanhe@hisilicon.com */
+    /* luofalei flluo@pku.edu.cn , wlq15@mails.tsinghua.edu.cn ,
+    Longfei.Wang@mediatek.com */
+#define RD1501_FIX_BG                      1
+    /* yuquanhe@hisilicon.com ; he-yuan.lin@mstarsemi.com */
+#define Mv_Rang                            1
+     /* Longfei.Wang@mediatek.com ;fred.chiu@mediatek.com
+     jie1222.chen@samsung.com */
+#define RD160_FIX_BG                       1
+     /* Y_K_Tu@novatek.com.tw, he-yuan.lin@mstarsemi.com,
+     victor.huang@montage-tech.com M4041 */
+#define RD1601_FIX_BG                      1
+#define SEQ_CHANGE_CHECKER                 1    /* he-yuan.lin@mstarsemi.com */
+#define M4140_END_OF_SLICE_CHECKER         1    /* he-yuan.lin@mstarsemi.com */
+     /* wlq15@mails.tsinghua.edu.cn */
+#define Mv_check_bug                       1
+#define SAO_ASSERTION_FIX                  1    /* fred.chiu@mediatek.com */
+#define FIELD_HORI_MV_NO_SCALE_FIX         1    /* fred.chiu@mediatek.com */
+#define RD170_FIX_BG                       1
+#define FIX_CHROMA_FIELD_MV_BK_DIST        1
+#define FIX_LUMA_FIELD_MV_BK_DIST          1
+#define FIX_CHROMA_FIELD_MV_CLIP           1
+#if 1
+#define FIX_FLUSH_DPB_BY_LF                1    /* fred.chiu@mediatek.com */
+#define FIX_SEQ_END_FLUSH_DPB_BY_LF        1   /* fred.chiu@mediatek.com */
+#else
+#define FIX_FLUSH_DPB_BY_LF                0    /* fred.chiu@mediatek.com */
+#define FIX_SEQ_END_FLUSH_DPB_BY_LF        0   /* fred.chiu@mediatek.com */
+#endif
+#define RD191_FIX_BUG                      1  /* yuquanhe@hsilicon.com */
+#define SYM_MV_SCALE_FIX                   1/* peisong.chen@broadcom.com */
+#define BUG_10BIT_REFINEQP                 0 /* wangzhenyu */
+
+
+
+#if RD191_FIX_BUG
+#endif
+
+/************************
+ * AVS2 macros start
+ **************************/
+
+#define INTERLACE_CODING                   1
+#if INTERLACE_CODING  /* M3531: MV scaling compensation */
+/* Luma component */
+#define HALF_PIXEL_COMPENSATION            1 /* common functions definition */
+#define HALF_PIXEL_COMPENSATION_PMV        1 /* spacial MV prediction */
+#define HALF_PIXEL_COMPENSATION_DIRECT     1 /* B direct mode */
+  /* MV derivation method 1, weighted P_skip mode */
+#define HALF_PIXEL_COMPENSATION_M1         1
+  /* M1 related with mv-scaling function */
+#define HALF_PIXEL_COMPENSATION_M1_FUCTION 1
+#define HALF_PIXEL_COMPENSATION_MVD        1 /* MV scaling from FW->BW */
+/* Chroma components */
+  /* chroma MV is scaled with luma MV for 4:2:0 format */
+#define HALF_PIXEL_CHROMA                  1
+  /* half pixel compensation for p skip/direct */
+#define HALF_PIXEL_PSKIP                   1
+#define INTERLACE_CODING_FIX               1 /* HLS fix */
+#define OUTPUT_INTERLACE_MERGED_PIC        1
+
+#endif
+/*
+ *******************************
+AVS2 10bit/12bit profile
+ ********************************
+ */
+
+#define DBFIX_10bit              1
+
+#define BUG_10bit              1
+
+/*
+ ***************************************
+AVS2 HIGH LEVEL SYNTAX
+ ***************************************
+ */
+#define AVS2_HDR_HLS             1
+ /* AVS2 HDR technology //yuquanhe@hisilicon.com */
+#define AVS2_HDR_Tec                       1
+#if AVS2_HDR_Tec
+#define HDR_CHROMA_DELTA_QP                1 /* M3905 */
+#define HDR_ADPTIVE_UV_DELTA                  1
+#endif
+/*
+ *************************************
+AVS2 S2
+ *************************************
+ */
+#define AVS2_S2_FASTMODEDECISION 1
+#define RD1510_FIX_BG            1      /* 20160714, flluo@pku.edu.cn */
+
+
+/* ////////////////// prediction techniques ///////////////////////////// */
+#define LAM_2Level_TU            0.8
+
+
+#define DIRECTION                4
+#define DS_FORWARD               4
+#define DS_BACKWARD              2
+#define DS_SYM                   3
+#define DS_BID                   1
+
+#define MH_PSKIP_NUM             4
+#define NUM_OFFSET               0
+#define BID_P_FST                1
+#define BID_P_SND                2
+#define FW_P_FST                 3
+#define FW_P_SND                 4
+#define WPM_NUM                  3
+      /* M3330 changes it to 2, the original value is 3 */
+#define MAX_MVP_CAND_NUM         2
+
+#define DMH_MODE_NUM             5     /* Number of DMH mode */
+#define TH_ME                    0     /* Threshold of ME */
+
+#define MV_SCALE                 1
+
+/* ///// reference picture management // */
+#define FIX_MAX_REF              1     /* Falei LUO, flluo@pku.edu.cn */
+#if FIX_MAX_REF
+      /* maximum number of reference frame for each frame */
+#define MAXREF                   7
+#define MAXGOP                   32
+#endif
+
+/* #define REF_MAXBUFFER            7 */
+/* more bufferes for displaying and background */
+/* #define REF_MAXBUFFER            15 */
+#if 1
+#define REF_MAXBUFFER            23
+#define REF_BUFFER  16
+#else
+#if RD170_FIX_BG
+#define REF_MAXBUFFER            16
+#else
+#define REF_MAXBUFFER            7
+#endif
+#endif
+
+#ifdef TO_PORTING
+    /* block-composed background reference, fangdong@mail.ustc.edu.cn */
+#define BCBR                     1
+#else
+#define BCBR    0
+#endif
+/* one more buffer for background when background_picture_output_flag is 0*/
+#define AVS2_MAX_BUFFER_NUM               (REF_MAXBUFFER + 1)
+
+/* /////////////////Adaptive Loop Filter////////////////////////// */
+#define NUM_ALF_COEFF_CTX        1
+#define NUM_ALF_LCU_CTX          4
+
+#define LAMBDA_SCALE_LUMA       (1.0)
+#define LAMBDA_SCALE_CHROMA     (1.0)
+
+
+
+/* ////////////////// entropy coding ///////////////////////////// */
+   /* M3090: Make sure rs1 will not overflow for 8-bit unsign char */
+#define NUN_VALUE_BOUND          254
+#define Encoder_BYPASS_Final     1    /* M3484 */
+#define Decoder_Bypass_Annex     0    /* M3484 */
+#define Decoder_Final_Annex      0    /* M3540 */
+
+
+/* ////////////////// coefficient coding ///// */
+     /* M3035 size of an coefficient group, 4x4 */
+#define CG_SIZE                  16
+
+#define SWAP(x, y) {\
+	(y) = (y) ^ (x);\
+	(x) = (y) ^ (x);\
+	(y) = (x) ^ (y);\
+}
+
+/* ////////////////// encoder optimization /////// */
+#define TH                                 2
+
+#define M3624MDLOG                             /* reserved */
+
+#define TDRDO                               1  /* M3528 */
+/* #define FIX_TDRDO_BG  1  // flluo@pku.edu.cn, 20160318// */
+#define RATECONTROL                         1  /* M3580 M3627 M3689 */
+#define AQPO                                1  /* M3623 */
+#define AQPOM3694                           0
+#define AQPOM4063                           1
+#define AQPOM3762                           1
+#define BGQPO                               1  /* M4061 */
+#if BGQPO
+#define LONGREFERENCE                       32
+#endif
+
+/* #define REPORT */
+/* ////////////////// Quantization   /////////////////////////////////////// */
+ /* Adaptive frequency weighting quantization */
+#define FREQUENCY_WEIGHTING_QUANTIZATION    1
+#if FREQUENCY_WEIGHTING_QUANTIZATION
+#define CHROMA_DELTA_QP                     1
+#define AWQ_WEIGHTING                       1
+#define AWQ_LARGE_BLOCK_ENABLE              1
+#define COUNT_BIT_OVERHEAD                  0
+#define AWQ_LARGE_BLOCK_EXT_MAPPING         1
+#endif
+
+#define QuantClip                           1
+#define QuantMatrixClipFix                  1  /* 20160418, fllu@pku.edu.cn */
+
+#define WQ_MATRIX_FCD                       1
+#if !WQ_MATRIX_FCD
+#define WQ_FLATBASE_INBIT  7
+#else
+#define WQ_FLATBASE_INBIT  6
+#endif
+
+
+#define REFINED_QP                          1
+
+
+/* ////////////////// delta QP ///// */
+      /* M3122: the minimum dQP unit is Macro block */
+#define MB_DQP                    1
+      /* M3122: 1 represents left prediction
+      and 0 represents previous prediction */
+#define LEFT_PREDICTION           1
+
+
+/* //////////////////////SAO///////// */
+#define NUM_BO_OFFSET             32
+#define MAX_NUM_SAO_CLASSES       32
+#define NUM_SAO_BO_CLASSES_LOG2   5
+#define NUM_SAO_BO_CLASSES_IN_BIT 5
+#define MAX_DOUBLE                (1.7e + 308)
+#define NUM_SAO_EO_TYPES_LOG2     2
+#define NUM_SAO_BO_CLASSES        (1<<NUM_SAO_BO_CLASSES_LOG2)
+#define SAO_RATE_THR              0.75
+#define SAO_RATE_CHROMA_THR       1
+#define SAO_SHIFT_PIX_NUM         4
+
+#define SAO_PARA_CROSS_SLICE      1
+#define SAO_MULSLICE_FTR_FIX      1
+
+/* /////////////////// Transform ///////////////////// */
+#define SEC_TR_SIZE               4
+   /* apply secT to greater than or equal to 8x8 block, */
+#define SEC_TR_MIN_BITSIZE        3
+
+#define BUGFIXED_COMBINED_ST_BD   1
+
+/* /////////////////// Scalable ///////////////////// */
+#define M3480_TEMPORAL_SCALABLE   1
+#define TEMPORAL_MAXLEVEL         8
+#define TEMPORAL_MAXLEVEL_BIT     3
+
+
+
+
+/*
+ *************************************
+ * AVS2 macros end
+ *
+ *************************************
+ */
+
+#define CHROMA                    1
+#define LUMA_8x8                  2
+#define NUM_BLOCK_TYPES           8
+
+#if (!defined clamp)
+     /* !< clamp a to the range of [b;c] */
+#define clamp(a, b, c) ((a) < (b) ? (b) : ((a) > (c) ? (c) : (a)))
+#endif
+
+	/* POC200301 moved from defines.h */
+#define LOG2_MAX_FRAME_NUM_MINUS4    4
+	/* !< bytes for one frame */
+#define MAX_CODED_FRAME_SIZE         15000000
+
+/* ----------------------- */
+/* FLAGS and DEFINES for new chroma intra prediction, Dzung Hoang */
+/* Threshold values to zero out quantized transform coefficients. */
+/* Recommend that _CHROMA_COEFF_COST_ be low to improve chroma quality */
+#define _LUMA_COEFF_COST_         4 /* !< threshold for luma coeffs */
+  /* !< Number of pixels padded around the reference frame (>=4) */
+#define IMG_PAD_SIZE              64
+
+#define OUTSTRING_SIZE            255
+
+	/* !< abs macro, faster than procedure */
+#define absm(A) ((A) < (0) ? (-(A)) : (A))
+    /* !< used for start value for some variables */
+#define MAX_VALUE                999999
+
+#define Clip1(a)     ((a) > 255 ? 255:((a) < 0 ? 0 : (a)))
+#define Clip3(min, max, val) (((val) < (min)) ?\
+		(min) : (((val) > (max)) ? (max) : (val)))
+
+/* --------------------------------------------- */
+
+/* block size of block transformed by AVS */
+#define PSKIPDIRECT               0
+#define P2NX2N                    1
+#define P2NXN                     2
+#define PNX2N                     3
+#define PHOR_UP                   4
+#define PHOR_DOWN                 5
+#define PVER_LEFT                 6
+#define PVER_RIGHT                7
+#define PNXN                      8
+#define I8MB                      9
+#define I16MB                     10
+#define IBLOCK                    11
+#define InNxNMB                   12
+#define INxnNMB                   13
+#define MAXMODE                   14   /* add yuqh 20130824 */
+#define  LAMBDA_ACCURACY_BITS     16
+#define  LAMBDA_FACTOR(lambda) ((int)((double)(1 << LAMBDA_ACCURACY_BITS)\
+		* lambda + 0.5))
+#define  WEIGHTED_COST(factor, bits) (((factor) * (bits))\
+		>> LAMBDA_ACCURACY_BITS)
+#define  MV_COST(f, s, cx, cy, px, py) (WEIGHTED_COST(f, mvbits[((cx) << (s))\
+		- px] +	mvbits[((cy) << (s)) - py]))
+#define  REF_COST(f, ref)              (WEIGHTED_COST(f, refbits[(ref)]))
+
+#define  BWD_IDX(ref)                 (((ref) < 2) ? 1 - (ref) : (ref))
+#define  REF_COST_FWD(f, ref) (WEIGHTED_COST(f,\
+		((img->num_ref_pic_active_fwd_minus1 == 0) ?\
+			0 : refbits[(ref)])))
+#define  REF_COST_BWD(f, ef) (WEIGHTED_COST(f,\
+		((img->num_ref_pic_active_bwd_minus1 == 0) ?\
+			0 : BWD_IDX(refbits[ref]))))
+
+#define IS_INTRA(MB) ((MB)->cuType == I8MB ||\
+	(MB)->cuType == I16MB ||\
+	(MB)->cuType == InNxNMB || (MB)->cuType == INxnNMB)
+#define IS_INTER(MB) ((MB)->cuType != I8MB &&\
+	(MB)->cuType != I16MB && (MB)->cuType != InNxNMB\
+	&& (MB)->cuType != INxnNMB)
+#define IS_INTERMV(MB) ((MB)->cuType != I8MB &&\
+	(MB)->cuType != I16MB && (MB)->cuType != InNxNMB &&\
+	(MB)->cuType != INxnNMB && (MB)->cuType != 0)
+
+
+#define IS_DIRECT(MB) ((MB)->cuType == PSKIPDIRECT && (img->type == B_IMG))
+#define IS_P_SKIP(MB) ((MB)->cuType == PSKIPDIRECT &&\
+	(((img->type == F_IMG)) || ((img->type == P_IMG))))
+#define IS_P8x8(MB)  ((MB)->cuType == PNXN)
+
+/* Quantization parameter range */
+#define MIN_QP                       0
+#define MAX_QP                       63
+#define SHIFT_QP                     11
+
+/* Picture types */
+#define INTRA_IMG                    0   /* !< I frame */
+#define INTER_IMG                    1   /* !< P frame */
+#define B_IMG                        2   /* !< B frame */
+#define I_IMG                        0   /* !< I frame */
+#define P_IMG                        1   /* !< P frame */
+#define F_IMG                        4  /* !< F frame */
+
+#define BACKGROUND_IMG               3
+
+#define BP_IMG                       5
+
+
+/* Direct Mode types */
+#define MIN_CU_SIZE                  8
+#define MIN_BLOCK_SIZE               4
+#define MIN_CU_SIZE_IN_BIT           3
+#define MIN_BLOCK_SIZE_IN_BIT        2
+#define BLOCK_MULTIPLE              (MIN_CU_SIZE/(MIN_BLOCK_SIZE))
+#define MAX_CU_SIZE                  64
+#define MAX_CU_SIZE_IN_BIT           6
+#define B4X4_IN_BIT                  2
+#define B8X8_IN_BIT                  3
+#define B16X16_IN_BIT                4
+#define B32X32_IN_BIT                5
+#define B64X64_IN_BIT                6
+    /* !< # luma intra prediction modes */
+#define NUM_INTRA_PMODE              33
+    /* number of luma modes for full RD search */
+#define NUM_MODE_FULL_RD             9
+    /* !< #chroma intra prediction modes */
+#define NUM_INTRA_PMODE_CHROMA       5
+
+/* luma intra prediction modes */
+
+#define DC_PRED                      0
+#define PLANE_PRED                   1
+#define BI_PRED                      2
+#define VERT_PRED                    12
+#define HOR_PRED                     24
+
+
+/* chroma intra prediction modes */
+#define DM_PRED_C                    0
+#define DC_PRED_C                    1
+#define HOR_PRED_C                   2
+#define VERT_PRED_C                  3
+#define BI_PRED_C                    4
+
+#define EOS                          1         /* !< End Of Sequence */
+	/* !< Start Of Picture */
+#define SOP                          2
+
+#define DECODING_OK                  0
+#define SEARCH_SYNC                  1
+#define DECODE_MB                    1
+
+#ifndef max
+  /* !< Macro returning max value */
+#define max(a, b)                   ((a) > (b) ? (a) : (b))
+  /* !< Macro returning min value */
+#define min(a, b)                   ((a) < (b) ? (a) : (b))
+#endif
+
+
+#define XY_MIN_PMV                   1
+#if XY_MIN_PMV
+#define MVPRED_xy_MIN                0
+#else
+#define MVPRED_MEDIAN                0
+#endif
+#define MVPRED_L                     1
+#define MVPRED_U                     2
+#define MVPRED_UR                    3
+
+#define DUAL                         4
+#define FORWARD                      0
+#define BACKWARD                     1
+#define SYM                          2
+#define BID                          3
+#define INTRA                        -1
+
+#define BUF_CYCLE                    5
+
+#define ROI_M3264                    1      /* ROI Information Encoding */
+
+#define PicExtensionData             1
+
+
+#define REF_OUTPUT                   1  /* M3337 */
+
+
+/* MV scaling 14 bit */
+#define MULTI                        16384
+#define HALF_MULTI                   8192
+#define OFFSET                       14
+/* end of MV scaling */
+ /* store the middle pixel's mv in a motion information unit */
+#define MV_DECIMATION_FACTOR         4
+
+/* BUGFIX_AVAILABILITY_INTRA */
+#define NEIGHBOR_INTRA_LEFT                 0
+#define NEIGHBOR_INTRA_UP                   1
+#define NEIGHBOR_INTRA_UP_RIGHT             2
+#define NEIGHBOR_INTRA_UP_LEFT              3
+#define NEIGHBOR_INTRA_LEFT_DOWN            4
+/* end of BUGFIX_AVAILABILITY_INTRA */
+
+/* end #include "define.h" */
+
+/*#include "commonStructures.h"*/
+
+/*typedef uint16_t byte;*/    /* !< byte type definition */
+#define byte uint16_t
+#define pel_t byte
+
+enum BitCountType_e {
+	BITS_HEADER,
+	BITS_TOTAL_MB,
+	BITS_MB_MODE,
+	BITS_INTER_MB,
+	BITS_CBP_MB,
+	BITS_CBP01_MB,
+	BITS_COEFF_Y_MB,
+	BITS_COEFF_UV_MB,
+	BITS_DELTA_QUANT_MB,
+	BITS_SAO_MB,
+	MAX_BITCOUNTER_MB
+};
+
+
+enum SAOEOClasses {
+/* EO Groups, the assignments depended on
+how you implement the edgeType calculation */
+	SAO_CLASS_EO_FULL_VALLEY = 0,
+	SAO_CLASS_EO_HALF_VALLEY = 1,
+	SAO_CLASS_EO_PLAIN       = 2,
+	SAO_CLASS_EO_HALF_PEAK   = 3,
+	SAO_CLASS_EO_FULL_PEAK   = 4,
+	SAO_CLASS_BO             = 5,
+	NUM_SAO_EO_CLASSES = SAO_CLASS_BO,
+	NUM_SAO_OFFSET
+};
+
+struct SAOstatdata {
+	int32_t diff[MAX_NUM_SAO_CLASSES];
+	int32_t  count[MAX_NUM_SAO_CLASSES];
+};
+
+struct CopyRight_s {
+	int32_t extension_id;
+	int32_t copyright_flag;
+	int32_t copyright_id;
+	int32_t original_or_copy;
+	int32_t reserved;
+	int32_t copyright_number;
+};
+
+struct CameraParamters_s {
+	int32_t reserved;
+	int32_t camera_id;
+	int32_t height_of_image_device;
+	int32_t focal_length;
+	int32_t f_number;
+	int32_t vertical_angle_of_view;
+	int32_t camera_position_x;
+	int32_t camera_position_y;
+	int32_t camera_position_z;
+	int32_t camera_direction_x;
+	int32_t camera_direction_y;
+	int32_t camera_direction_z;
+	int32_t image_plane_vertical_x;
+	int32_t image_plane_vertical_y;
+	int32_t image_plane_vertical_z;
+};
+
+/* ! SNRParameters */
+struct SNRParameters_s {
+	double snr_y;               /* !< current Y SNR */
+	double snr_u;               /* !< current U SNR */
+	double snr_v;               /* !< current V SNR */
+	double snr_y1;              /* !< SNR Y(dB) first frame */
+	double snr_u1;              /* !< SNR U(dB) first frame */
+	double snr_v1;              /* !< SNR V(dB) first frame */
+	double snr_ya;              /* !< Average SNR Y(dB) remaining frames */
+	double snr_ua;              /* !< Average SNR U(dB) remaining frames */
+	double snr_va;              /* !< Average SNR V(dB) remaining frames */
+#if INTERLACE_CODING
+	double i_snr_ya;               /* !< current Y SNR */
+	double i_snr_ua;               /* !< current U SNR */
+	double i_snr_va;               /* !< current V SNR */
+#endif
+};
+
+/* signal to noise ratio parameters */
+
+/* ! codingUnit */
+struct codingUnit {
+	uint32_t        ui_MbBitSize;
+	int32_t                 uiBitSize;            /* size of MB */
+	/* !< number of current syntax element */
+	int32_t                 currSEnr;
+	int32_t                 slice_nr;
+	int32_t                 delta_quant;          /* !< for rate control */
+	int32_t                 delta_qp;
+	int32_t                 qp;
+	int32_t                 bitcounter[MAX_BITCOUNTER_MB];
+	struct codingUnit
+	*mb_available[3][3]; /*!< pointer to neighboring MBs
+		in a 3x3 window of current MB, which is located at [1][1] \n
+		NULL pointer identifies neighboring MBs which are unavailable */
+	/* some storage of codingUnit syntax elements for global access */
+	int32_t                 cuType;
+	int32_t                 weighted_skipmode;
+
+	int32_t                 md_directskip_mode;
+
+	int32_t                 trans_size;
+	int
+	/* !< indices correspond to [forw,backw][block_y][block_x][x,y, dmh] */
+	mvd[2][BLOCK_MULTIPLE][BLOCK_MULTIPLE][3];
+
+	int32_t  intra_pred_modes[BLOCK_MULTIPLE * BLOCK_MULTIPLE];
+	int32_t  real_intra_pred_modes[BLOCK_MULTIPLE * BLOCK_MULTIPLE];
+	int32_t  l_ipred_mode;
+	int32_t  cbp, cbp_blk;
+	uint32_t cbp_bits;
+
+	int32_t                 b8mode[4];
+	int32_t                 b8pdir[4];
+      /* !< chroma intra prediction mode */
+	int32_t                 c_ipred_mode;
+
+   /* !< pointer to neighboring MB (AEC) */
+	struct codingUnit   *mb_available_up;
+	 /* !< pointer to neighboring MB (AEC) */
+	struct codingUnit   *mb_available_left;
+	int32_t                 mbAddrA, mbAddrB, mbAddrC, mbAddrD;
+       /* !<added by mz, 2008.04 */
+	int32_t                 slice_set_index;
+     /* added by mz, 2008.04 */
+	int32_t                 slice_header_flag;
+	int32_t                 sliceqp;         /* added by mz, 2008.04 */
+#if MB_DQP
+	int32_t                 previouse_qp;
+	int32_t                 left_cu_qp;
+#endif
+	int32_t                 block_available_up;
+	int32_t                 block_available_left;
+
+};
+
+
+/* image parameters */
+struct syntaxelement;
+struct slice;
+struct alfdatapart;
+struct SAOBlkParam_s {
+	int32_t modeIdc; /* NEW, MERGE, OFF */
+	/* NEW: EO_0, EO_90, EO_135, EO_45, BO. MERGE: left, above */
+	int32_t typeIdc;
+	int32_t startBand; /* BO: starting band index */
+	int32_t startBand2;
+	int32_t deltaband;
+	int32_t offset[MAX_NUM_SAO_CLASSES];
+};
+struct ALFParam_s {
+	int32_t alf_flag;
+	int32_t num_coeff;
+	int32_t filters_per_group;
+	int32_t componentID;
+	int32_t filterPattern[16]; /* *filterPattern; */
+	int32_t coeffmulti[16][9]; /* **coeffmulti; */
+};
+
+enum ALFComponentID {
+	ALF_Y = 0,
+	ALF_Cb,
+	ALF_Cr,
+	NUM_ALF_COMPONENT
+};
+struct ALF_APS_s {
+	int32_t usedflag;
+	int32_t cur_number;
+	int32_t max_number;
+	struct ALFParam_s alf_par[NUM_ALF_COMPONENT];
+};
+
+
+/* ------------------------------------------------------
+ * frame data
+ */
+struct avs2_frame_s {
+	int32_t imgcoi_ref;
+	byte * *referenceFrame[3];
+	int32_t **refbuf;
+	int32_t ***mvbuf;
+#if 0
+	double saorate[NUM_SAO_COMPONENTS];
+#endif
+	byte ***ref;
+
+	int32_t imgtr_fwRefDistance;
+	int32_t refered_by_others;
+	int32_t is_output;
+	int32_t to_prepare_disp;
+#if M3480_TEMPORAL_SCALABLE
+	/* temporal level setted in configure file */
+	int32_t temporal_id;
+#endif
+	byte **oneForthRefY;
+#if FIX_MAX_REF
+	int32_t ref_poc[MAXREF];
+#else
+	int32_t ref_poc[4];
+#endif
+#ifdef AML
+	int32_t index;
+	int32_t mmu_alloc_flag;
+	int32_t lcu_size_log2;
+	/*uint32_t header_adr;*/
+	uint32_t mc_y_adr;
+	uint32_t mc_u_v_adr;
+	uint32_t mc_canvas_y;
+	uint32_t mc_canvas_u_v;
+	uint32_t mpred_mv_wr_start_addr;
+	uint8_t bg_flag;
+	/**/
+	unsigned long header_adr;
+	/*AVS2_10B_MMU_DW*/
+	unsigned long dw_header_adr;
+
+	int buf_size;
+	int lcu_total;
+	int comp_body_size;
+	uint32_t dw_y_adr;
+	uint32_t dw_u_v_adr;
+	int y_canvas_index;
+	int uv_canvas_index;
+	struct canvas_config_s canvas_config[2];
+	int double_write_mode;
+	int bit_depth;
+	unsigned long cma_alloc_addr;
+	int BUF_index;
+	int pic_w;
+	int pic_h;
+	int stream_offset;
+	u32 pts;
+	u64 pts64;
+	/**/
+	int vf_ref;
+	int decode_idx;
+	int slice_type;
+	int32_t imgtr_fwRefDistance_bak;
+	int32_t error_mark;
+	int32_t decoded_lcu;
+#endif
+#ifndef MV_USE_FIXED_BUF
+	int mv_buf_index;
+#endif
+
+	/* picture qos infomation*/
+	int max_qp;
+	int avg_qp;
+	int min_qp;
+	int max_skip;
+	int avg_skip;
+	int min_skip;
+	int max_mv;
+	int min_mv;
+	int avg_mv;
+
+	u32 hw_decode_time;
+	u32 frame_size; // For frame base mode
+
+	char *cuva_data_buf;
+	int  cuva_data_size;
+};
+
+
+struct ImageParameters_s {
+	struct codingUnit    *mb_data;
+	int32_t number;                                 /* <! frame number */
+	int32_t numIPFrames;
+
+	int32_t type;
+	int32_t typeb;
+	int32_t typeb_before;
+
+	int32_t qp; /* <! quant for the current frame */
+	int32_t current_mb_nr; /* bitstream order */
+	int32_t current_slice_nr;
+	int32_t tr;   /* <! temporal reference, 8 bit, */
+
+	int32_t width;                   /* !< Number of pels */
+	int32_t width_cr;                /* !< Number of pels chroma */
+	int32_t height;                  /* !< Number of lines */
+	int32_t height_cr;               /* !< Number of lines  chroma */
+	int32_t PicWidthInMbs;
+	int32_t PicSizeInMbs;
+	int32_t block8_x, block8_y;
+	int32_t   subblock_x;
+	int32_t   subblock_y;
+
+	int32_t num_of_references;
+    /* <! Bug Fix: correct picture size for outputted reconstructed pictures */
+	int32_t auto_crop_right;
+	int32_t auto_crop_bottom;
+	int32_t buf_cycle;
+	int32_t picture_structure;
+	 /* <! pointer to current Slice data struct */
+	struct slice       *currentSlice;
+
+	int32_t **predBlock;             /* !< current best prediction mode */
+	int32_t **predBlockTmp;
+	/* !< the diff pixel values between orginal image and prediction */
+	int32_t **resiY;
+	/* !< Array containing square values,used for snr computation */
+	int32_t *quad;
+
+	/* //location of current MB////// */
+	int32_t mb_y;                    /* !< current MB vertical */
+	int32_t mb_x;                    /* !< current MB horizontal */
+	int32_t pix_y;                   /* !< current pixel vertical */
+	int32_t pix_x;                   /* !< current pixel horizontal */
+	int32_t pix_c_y;                 /* !< current pixel chroma vertical */
+	int32_t pix_c_x; /* !< current pixel chroma horizontal */
+
+	int32_t imgtr_next_P;
+
+	int32_t imgcoi_next_ref;
+
+    /* !< GH ipredmode[90][74];prediction mode for inter frames */
+    /* fix from ver 4.1 */
+	int32_t **ipredmode;
+	int32_t **rec_ipredmode;
+
+
+	/* //////////////decoder////////////////////////// */
+	int32_t max_mb_nr;
+	int32_t **intra_block;
+
+	int32_t block_y;
+	int32_t block_x;
+    /* <! final 4x4 block. Extended to 16x16 for AVS */
+	int32_t resiUV[2][MAX_CU_SIZE][MAX_CU_SIZE];
+
+	int32_t **fw_refFrArr;                          /* <! [72][88]; */
+	int32_t **bw_refFrArr;                          /* <! [72][88]; */
+
+	int32_t random_access_decodable_flag;
+
+	int32_t seq_header_indicate;
+	int32_t B_discard_flag;
+
+	/* B pictures */
+	uint32_t pic_distance;
+
+	uint32_t coding_order;
+
+	uint32_t PrevPicDistanceLsb;
+	int32_t CurrPicDistanceMsb;
+
+	int32_t PicHeightInMbs;
+
+	int32_t types;
+
+	int32_t new_sequence_flag;
+	int32_t sequence_end_flag;            /* <! rm52k_r2 */
+
+	int32_t current_slice_set_index;          /* <! added by mz, 2008.04 */
+	int32_t current_slice_header_flag;        /* <! added by mz, 2008.04 */
+	int32_t slice_set_qp[64];             /* <! added by mz, 2008.04 */
+
+
+	int32_t inter_amp_enable;
+
+	/* ////////////////////////encoder////////////////////////// */
+
+	/* int32_t nb_references;     //!< replaced by "num_of_references" */
+
+	int32_t framerate;
+
+	int32_t ***predBlockY;        /* !< all 9 prediction modes */
+     /* !< new chroma 8x8 intra prediction modes */
+	int32_t ****predBlockUV;
+
+	int32_t **Coeff_all;/* qyu 0821 */
+
+	struct syntaxelement   *MB_SyntaxElements; /* !< by oliver 0612 */
+
+	/* B pictures */
+
+	int32_t b_frame_to_code;
+	int32_t num_ref_pic_active_fwd_minus1;
+	int32_t num_ref_pic_active_bwd_minus1;
+	int32_t mv_range_flag;
+
+	uint32_t frame_num;   /* frame_num for this frame */
+	int32_t slice_offset;
+	/* the following are sent in the slice header */
+	int32_t NoResidueDirect;
+	int32_t coded_mb_nr;
+	int32_t progressive_frame;
+	int32_t tc_reserve_bit;
+	 /* the last MB no in current slice.      Yulj 2004.07.15 */
+	int32_t mb_no_currSliceLastMB;
+	int32_t Seqheader_flag;     /* Added by cjw, 20070327 */
+	int32_t EncodeEnd_flag;         /* Carmen, 2007/12/19 */
+
+	uint16_t bbv_delay;
+
+	int32_t tmp_fwBSkipMv[DIRECTION + 1][2];
+	int32_t tmp_bwBSkipMv[DIRECTION + 1][2];
+
+	int32_t tmp_pref_fst[MH_PSKIP_NUM + NUM_OFFSET + 1];
+	int32_t tmp_pref_snd[MH_PSKIP_NUM + NUM_OFFSET + 1];
+	int32_t tmp_fstPSkipMv[MH_PSKIP_NUM + NUM_OFFSET + 1][3];
+	int32_t tmp_sndPSkipMv[MH_PSKIP_NUM + NUM_OFFSET + 1][3];
+#if BCBR
+byte *org_ref_y;
+byte *org_ref_u;
+byte *org_ref_v;
+int32_t  *BLCUidx;
+int32_t  *DQPList;
+int32_t  iNumCUsInFrame;
+
+byte *org_ref2_y;
+byte *org_ref2_u;
+byte *org_ref2_v;
+int32_t  ref2Num;
+#endif
+/* //////////////SAO parameter////////////////// */
+double        *cur_saorate;
+#if 0
+int32_t            slice_sao_on[NUM_SAO_COMPONENTS];
+#endif
+int32_t            pic_alf_on[NUM_ALF_COMPONENT];
+struct alfdatapart   *dp_ALF;
+
+#if INTERLACE_CODING
+int32_t is_field_sequence;
+int32_t is_top_field;
+#endif
+
+
+};
+
+
+
+/* ! struct for context management */
+struct BiContextType_s {
+	uint8_t MPS;   /* 1 bit */
+	uint32_t  LG_PMPS; /* 10 bits */
+	uint8_t cycno;  /* 2 bits */
+};
+
+/***********************************************************************
+ * D a t a    t y p e s   f o r  A E C
+ ************************************************************************/
+
+
+
+struct pix_pos {
+	int32_t available;   /* ABCD */
+	int32_t mb_addr;    /* MB position */
+	int32_t x;
+	int32_t y;
+	int32_t pos_x;     /* 4x4 x-pos */
+	int32_t pos_y;
+};
+
+
+
+struct STDOUT_DATA_s {
+	int32_t type;
+	int32_t typeb;
+
+	int32_t   framenum;
+	int32_t   tr;
+	int32_t   qp;
+	double snr_y;
+	double snr_u;
+	double snr_v;
+	int32_t   tmp_time;
+	int32_t   picture_structure;
+	int32_t   curr_frame_bits;
+	int32_t   emulate_bits;
+
+	uint32_t DecMD5Value[4];
+#if RD1501_FIX_BG
+int32_t background_picture_output_flag;/* Longfei.Wang@mediatek.com */
+#endif
+#if RD160_FIX_BG
+int32_t picture_reorder_delay;
+#endif
+int8_t str_reference_list[128];  /* reference list information */
+};
+
+/**********************************************************************
+ * C O N T E X T S   F O R   T M L   S Y N T A X   E L E M E N T S
+ **********************************************************************
+ */
+#define NUM_CuType_CTX              (11 + 10)
+#define NUM_B8_TYPE_CTX              9
+#define NUM_MVD_CTX                 15
+#define NUM_PMV_IDX_CTX             10
+#define NUM_REF_NO_CTX               6
+#define NUM_DELTA_QP_CTX             4
+#define NUM_INTER_DIR_CTX           18
+#define NUM_INTER_DIR_DHP_CTX           3
+#define NUM_B8_TYPE_DHP_CTX             1
+#define NUM_AMP_CTX                  2
+#define NUM_C_INTRA_MODE_CTX         4
+#define NUM_CBP_CTX                  4
+#define NUM_BCBP_CTX                 4
+#define NUM_MAP_CTX                 17
+#define NUM_LAST_CTX                17
+
+#define NUM_INTRA_MODE_CTX           7
+
+#define NUM_ABS_CTX                  5
+#define NUM_TU_CTX                   3
+#define NUM_SPLIT_CTX                8  /* CU depth */
+#if BCBR
+#define NUM_BGBLCOK_CTX              1
+#endif
+
+#define NUM_BRP_CTX                  8
+
+
+#define NUM_LAST_CG_CTX_LUMA        12
+#define NUM_LAST_CG_CTX_CHROMA       6
+#define NUM_SIGCG_CTX_LUMA           2
+#define NUM_SIGCG_CTX_CHROMA         1
+#define NUM_LAST_POS_CTX_LUMA   56
+#define NUM_LAST_POS_CTX_CHROMA 16
+#define NUM_LAST_CG_CTX (NUM_LAST_CG_CTX_LUMA + NUM_LAST_CG_CTX_CHROMA)
+#define NUM_SIGCG_CTX (NUM_SIGCG_CTX_LUMA + NUM_SIGCG_CTX_CHROMA)
+#define NUM_LAST_POS_CTX (NUM_LAST_POS_CTX_LUMA + NUM_LAST_POS_CTX_CHROMA)
+#define NUM_SAO_MERGE_FLAG_CTX                   3
+#define NUM_SAO_MODE_CTX                         1
+#define NUM_SAO_OFFSET_CTX                       2
+#define NUM_INTER_DIR_MIN_CTX         2
+
+/*end #include "commonStructures.h"*/
+
+/*#include "commonVariables.h"*/
+
+/*
+extern struct CameraParamters_s *camera;
+extern struct SNRParameters_s *snr;
+extern struct ImageParameters_s *img;
+ */
+
+/* avs2_frame_t *fref[REF_MAXBUFFER]; */
+
+
+#define ET_SIZE 300      /* !< size of error text buffer */
+
+
+/* ------------------------------------------------------
+ * common data
+ */
+struct Video_Com_data_s {
+	int32_t   Bframe_ctr;
+
+	/* FILE *p_log;                     //!< SNR file */
+	/* FILE *p_trace;                   //!< Trace file */
+
+	int32_t   tot_time;
+
+	/* Tsinghua for picture_distance  200701 */
+	int32_t   picture_distance;
+
+	/* M3178 PKU Reference Manage */
+	int32_t   coding_order;
+	/* !< current encoding/decoding frame pointer */
+	struct avs2_frame_s *f_rec;
+	int32_t   seq_header;
+    /* !< Array for reference frames of each block */
+	int32_t    **refFrArr;
+	int32_t    **p_snd_refFrArr;
+
+	byte  ***currentFrame; /* [yuv][height][width] */
+#ifdef AML
+	struct avs2_frame_s *cur_pic; /*either f_rec or m_bg*/
+#endif
+	byte   **backgroundReferenceFrame[3];
+	byte  ***background_ref;
+
+
+	int32_t  total_frames;
+
+	/* mv_range, 20071009 */
+	int32_t  Min_V_MV;
+	int32_t  Max_V_MV;
+	int32_t  Min_H_MV;
+	int32_t  Max_H_MV;
+	/* !< buffer for error message for exit with error(void) */
+	int8_t errortext[ET_SIZE];
+	int8_t str_list_reference[128];
+
+
+};
+/* extern Video_Com_data *hc; */
+
+
+/*end #include "commonVariables.h"*/
+/* #define USE_PARAM_TXT */
+/*
+#if FIX_CHROMA_FIELD_MV_BK_DIST
+int8_t bk_img_is_top_field;
+#endif
+*/
+/* void write_GB_frame(FILE *p_dec); */
+
+#if !FIX_MAX_REF
+#define MAXREF    4
+#define MAXGOP    32
+#endif
+
+struct StatBits {
+	int32_t   curr_frame_bits;
+	int32_t   prev_frame_bits;
+	int32_t   emulate_bits;
+	int32_t   prev_emulate_bits;
+	int32_t   last_unit_bits;
+	int32_t   bitrate;
+	int32_t   total_bitrate[1000];
+	int32_t   coded_pic_num;
+	int32_t   time_s;
+};
+
+struct reference_management {
+	int32_t poc;
+	int32_t qp_offset;
+	int32_t num_of_ref;
+	int32_t referd_by_others;
+	int32_t ref_pic[MAXREF];
+	int32_t predict;
+	int32_t deltaRPS;
+	int32_t num_to_remove;
+	int32_t remove_pic[MAXREF];
+};
+
+
+/* ------------------------------------------------------
+ * dec data
+ */
+struct Video_Dec_data_s {
+	byte **background_frame[3];
+	int32_t background_reference_enable;
+
+	int32_t background_picture_flag;
+	int32_t background_picture_output_flag;
+	int32_t background_picture_enable;
+
+	int32_t background_number;
+
+#if BCBR
+	int32_t bcbr_enable;
+#endif
+
+	int32_t demulate_enable;
+	int32_t currentbitoffset;
+
+	int32_t aspect_ratio_information;
+	int32_t frame_rate_code;
+	int32_t bit_rate_lower;
+	int32_t bit_rate_upper;
+	int32_t  marker_bit;
+
+	int32_t video_format;
+	int32_t color_description;
+	int32_t color_primaries;
+	int32_t transfer_characteristics;
+	int32_t matrix_coefficients;
+
+	int32_t progressive_sequence;
+#if INTERLACE_CODING
+int32_t is_field_sequence;
+#endif
+int32_t low_delay;
+int32_t horizontal_size;
+int32_t vertical_size;
+int32_t sample_precision;
+int32_t video_range;
+
+int32_t display_horizontal_size;
+int32_t display_vertical_size;
+int32_t TD_mode;
+int32_t view_packing_mode;
+int32_t view_reverse;
+
+int32_t b_pmvr_enabled;
+int32_t dhp_enabled;
+int32_t b_dmh_enabled;
+int32_t b_mhpskip_enabled;
+int32_t wsm_enabled;
+int32_t b_secT_enabled;
+
+int32_t tmp_time;
+int32_t FrameNum;
+int32_t eos;
+int32_t pre_img_type;
+int32_t pre_img_types;
+/* int32_t pre_str_vec; */
+int32_t pre_img_tr;
+int32_t pre_img_qp;
+int32_t pre_tmp_time;
+int32_t RefPicExist;   /* 20071224 */
+int32_t BgRefPicExist;
+int32_t dec_ref_num;                /* ref order */
+
+/* video edit code */ /* M1956 by Grandview 2006.12.12 */
+int32_t vec_flag;
+
+/* Copyright_extension(void) header */
+int32_t copyright_flag;
+int32_t copyright_identifier;
+int32_t original_or_copy;
+int64_t copyright_number_1;
+int64_t copyright_number_2;
+int64_t copyright_number_3;
+/* Camera_parameters_extension */
+int32_t camera_id;
+int32_t height_of_image_device;
+int32_t focal_length;
+int32_t f_number;
+int32_t vertical_angle_of_view;
+int32_t camera_position_x_upper;
+int32_t camera_position_x_lower;
+int32_t camera_position_y_upper;
+int32_t camera_position_y_lower;
+int32_t camera_position_z_upper;
+int32_t camera_position_z_lower;
+int32_t camera_direction_x;
+int32_t camera_direction_y;
+int32_t camera_direction_z;
+int32_t image_plane_vertical_x;
+int32_t image_plane_vertical_y;
+int32_t image_plane_vertical_z;
+
+#if AVS2_HDR_HLS
+/* mastering_display_and_content_metadata_extension(void) header */
+int32_t display_primaries_x0;
+int32_t display_primaries_y0;
+int32_t display_primaries_x1;
+int32_t display_primaries_y1;
+int32_t display_primaries_x2;
+int32_t display_primaries_y2;
+int32_t white_point_x;
+int32_t white_point_y;
+int32_t max_display_mastering_luminance;
+int32_t min_display_mastering_luminance;
+int32_t maximum_content_light_level;
+int32_t maximum_frame_average_light_level;
+#endif
+
+/* I_pictures_header(void) */
+int32_t top_field_first;
+int32_t repeat_first_field;
+int32_t progressive_frame;
+#if INTERLACE_CODING
+int32_t is_top_field;
+#endif
+/* int32_t fixed_picture_qp;   //qyu 0927 */
+int32_t picture_qp;
+int32_t fixed_picture_qp;
+int32_t time_code_flag;
+int32_t time_code;
+int32_t loop_filter_disable;
+int32_t loop_filter_parameter_flag;
+/* int32_t alpha_offset; */
+/* int32_t beta_offset; */
+
+/* Pb_picture_header(void) */
+int32_t picture_coding_type;
+
+/*picture_display_extension(void)*/
+int32_t frame_centre_horizontal_offset[4];
+int32_t frame_centre_vertical_offset[4];
+
+/* slice_header(void) */
+int32_t img_width;
+int32_t slice_vertical_position;
+int32_t slice_vertical_position_extension;
+int32_t fixed_slice_qp;
+int32_t slice_qp;
+int32_t slice_horizontal_positon;       /* added by mz, 2008.04 */
+int32_t slice_horizontal_positon_extension;
+
+int32_t StartCodePosition;
+int32_t background_pred_flag;
+
+
+/* Reference Manage */
+int32_t displaydelay;
+int32_t picture_reorder_delay;
+#if M3480_TEMPORAL_SCALABLE
+int32_t temporal_id_exist_flag;
+#endif
+
+int32_t gop_size;
+struct reference_management decod_RPS[MAXGOP];
+struct reference_management curr_RPS;
+int32_t last_output;
+int32_t trtmp;
+#if M3480_TEMPORAL_SCALABLE
+int32_t cur_layer;
+#endif
+
+/* Adaptive frequency weighting quantization */
+#if FREQUENCY_WEIGHTING_QUANTIZATION
+int32_t weight_quant_enable_flag;
+int32_t load_seq_weight_quant_data_flag;
+
+int32_t pic_weight_quant_enable_flag;
+int32_t pic_weight_quant_data_index;
+int32_t weighting_quant_param;
+int32_t weighting_quant_model;
+int16_t quant_param_undetail[6];      /* M2148 2007-09 */
+int16_t quant_param_detail[6];        /* M2148 2007-09 */
+int32_t WeightQuantEnable;              /* M2148 2007-09 */
+int32_t mb_adapt_wq_disable;            /* M2331 2008-04 */
+int32_t mb_wq_mode;                     /* M2331 2008-04 */
+#if CHROMA_DELTA_QP
+int32_t chroma_quant_param_disable;
+int32_t chroma_quant_param_delta_u;
+int32_t chroma_quant_param_delta_v;
+#endif
+
+int32_t b_pre_dec_intra_img;
+int32_t pre_dec_img_type;
+int32_t CurrentSceneModel;
+#endif
+
+int32_t curr_IDRcoi;
+int32_t curr_IDRtr;
+int32_t next_IDRtr;
+int32_t next_IDRcoi;
+int32_t end_SeqTr;
+
+#if MB_DQP
+int32_t lastQP;
+/* FILE * testQP; */
+#endif
+
+};
+/* extern Video_Dec_data *hd; */
+
+struct DecodingEnvironment_s {
+	uint32_t    Dbuffer;
+	int32_t             Dbits_to_go;
+	uint8_t            *Dcodestrm;
+	int32_t             *Dcodestrm_len;
+};
+
+/* added at rm52k version */
+
+struct inp_par;
+
+
+
+/* ! Slice */
+struct slice {
+	int32_t                 picture_id;
+	int32_t                 qp;
+	int32_t                 picture_type; /* !< picture type */
+	int32_t                 start_mb_nr;
+	 /* !< number of different partitions */
+	int32_t                 max_part_nr;
+
+	/* added by lzhang */
+	/* !< pointer to struct of context models for use in AEC */
+	struct SyntaxInfoContexts_s  *syn_ctx;
+};
+
+struct alfdatapart {
+	struct Bitstream_s           *bitstream;
+	struct DecodingEnvironment_s de_AEC;
+	struct SyntaxInfoContexts_s  *syn_ctx;
+};
+/* static int32_t alfParAllcoated = 0; */
+
+/* input parameters from configuration file */
+struct inp_par {
+	int32_t   buf_cycle;                 /* <! Frame buffer size */
+	int32_t   ref_pic_order;             /* <! ref order */
+	int32_t   output_dec_pic;            /* <! output_dec_pic */
+	int32_t   profile_id;
+	int32_t   level_id;
+	int32_t   chroma_format;
+	int32_t   g_uiMaxSizeInBit;
+	int32_t   alpha_c_offset;
+	int32_t   beta_offset;
+	int32_t   useNSQT;
+#if MB_DQP
+	int32_t   useDQP;
+#endif
+	int32_t   useSDIP;
+	int32_t sao_enable;
+#if M3480_TEMPORAL_SCALABLE
+	int32_t temporal_id_exist_flag;
+#endif
+	int32_t alf_enable;
+
+	int32_t crossSliceLoopFilter;
+
+	int32_t   sample_bit_depth;  /* sample bit depth */
+  /* decoded file bit depth (assuming output_bit_depth is
+  less or equal to sample_bit_depth) */
+	int32_t   output_bit_depth;
+
+
+	int32_t MD5Enable;
+
+#if OUTPUT_INTERLACE_MERGED_PIC
+	int32_t output_interlace_merged_picture;
+#endif
+
+};
+
+/* extern struct inp_par *input; */
+
+struct outdata_s {
+#if RD170_FIX_BG
+	struct STDOUT_DATA_s stdoutdata[REF_MAXBUFFER];
+#else
+	struct STDOUT_DATA_s stdoutdata[8];
+#endif
+	int32_t         buffer_num;
+};
+/* outdata outprint; */
+
+#define PAYLOAD_TYPE_IDERP 8
+
+struct Bitstream_s *AllocBitstream(void);
+void FreeBitstream(void);
+#if TRACE
+void tracebits2(const int8_t *trace_str, int32_t len, int32_t info);
+#endif
+
+/* int32_t   direct_mv[45][80][4][4][3]; // only to verify result */
+
+#define I_PICTURE_START_CODE    0xB3
+#define PB_PICTURE_START_CODE   0xB6
+#define SLICE_START_CODE_MIN    0x00
+#define SLICE_START_CODE_MAX    0x8F
+#define USER_DATA_START_CODE    0xB2
+#define SEQUENCE_HEADER_CODE    0xB0
+#define EXTENSION_START_CODE    0xB5
+#define SEQUENCE_END_CODE       0xB1
+#define VIDEO_EDIT_CODE         0xB7
+
+
+#define SEQUENCE_DISPLAY_EXTENSION_ID            2
+#define COPYRIGHT_EXTENSION_ID                   4
+#define CAMERAPARAMETERS_EXTENSION_ID            11
+#define PICTURE_DISPLAY_EXTENSION_ID             7
+#if M3480_TEMPORAL_SCALABLE
+#define TEMPORAL_SCALABLE_EXTENSION_ID           3
+#endif
+
+#if ROI_M3264
+#if RD1501_FIX_BG
+#define LOCATION_DATA_EXTENSION_ID               12
+#else
+#define LOCATION_DATA_EXTENSION_ID               15
+#endif
+#endif
+
+#if AVS2_HDR_HLS
+#define MASTERING_DISPLAY_AND_CONTENT_METADATA_EXTENSION     10
+#endif
+
+void malloc_slice(void);
+void free_slice(void);
+
+
+void read_ipred_modes(void);
+
+int32_t  AEC_startcode_follows(int32_t eos_bit);
+
+/* extern uint32_t max_value_s; */
+
+/*ComAdaptiveLoopFilter.h*/
+#define ALF_MAX_NUM_COEF       9
+#define NO_VAR_BINS            16
+
+
+#define RPM_BEGIN                                              0x100
+#define ALF_BEGIN                                              0x180
+#define RPM_END                                                0x280
+
+union param_u {
+	struct {
+		uint16_t data[RPM_END - RPM_BEGIN];
+	} l;
+	struct {
+		/*sequence*/
+		uint16_t profile_id;
+		uint16_t level_id;
+		uint16_t progressive_sequence;
+		uint16_t is_field_sequence;
+		uint16_t horizontal_size;
+		uint16_t vertical_size;
+		uint16_t chroma_format;
+		uint16_t sample_precision;
+		uint16_t encoding_precision;
+		uint16_t aspect_ratio_information;
+		uint16_t frame_rate_code;
+		uint16_t bit_rate_lower;
+		uint16_t bit_rate_upper;
+		uint16_t low_delay;
+		uint16_t temporal_id_exist_flag;
+		uint16_t g_uiMaxSizeInBit;
+
+#define BACKGROUND_PICTURE_DISABLE_BIT         11
+#define B_MHPSKIP_ENABLED_BIT                  10
+#define DHP_ENABLED_BIT                         9
+#define WSM_ENABLED_BIT                        8
+#define INTER_AMP_ENABLE_BIT                   7
+#define USENSQT_BIT                            6
+#define USESDIP_BIT                            5
+#define B_SECT_ENABLED_BIT                     4
+#define SAO_ENABLE_BIT                         3
+#define ALF_ENABLE_BIT                         2
+#define B_PMVR_ENABLED_BIT                     1
+#define CROSSSLICELOOPFILTER_BIT               0
+		uint16_t avs2_seq_flags;
+
+		uint16_t num_of_RPS;
+		uint16_t picture_reorder_delay;
+		/*PIC*/
+		uint16_t time_code_flag;
+		uint16_t time_code;
+		uint16_t background_picture_flag;
+		uint16_t background_picture_output_flag;
+		uint16_t coding_order;
+		uint16_t cur_layer;
+		uint16_t displaydelay; /*???*/
+		uint16_t predict;     /*???*/
+		uint16_t RPS_idx;      /*???*/
+		uint16_t referd_by_others_cur;
+		uint16_t num_of_ref_cur;
+		uint16_t ref_pic_cur[8];
+		uint16_t num_to_remove_cur;
+		uint16_t remove_pic_cur[8];
+		uint16_t progressive_frame;
+		uint16_t picture_structure;
+		uint16_t top_field_first;
+		uint16_t repeat_first_field;
+		uint16_t is_top_field;
+
+		uint16_t picture_coding_type;
+		uint16_t background_pred_flag;
+		uint16_t background_reference_enable;
+		uint16_t random_access_decodable_flag;
+		uint16_t lcu_size;
+		uint16_t alpha_c_offset;
+		uint16_t beta_offset;
+		uint16_t chroma_quant_param_delta_cb;
+		uint16_t chroma_quant_param_delta_cr;
+		uint16_t loop_filter_disable;
+
+		uint16_t video_signal_type;
+		uint16_t color_description;
+		uint16_t display_primaries_x[3];
+		uint16_t display_primaries_y[3];
+		uint16_t white_point_x;
+		uint16_t white_point_y;
+		uint16_t max_display_mastering_luminance;
+		uint16_t min_display_mastering_luminance;
+		uint16_t max_content_light_level;
+		uint16_t max_picture_average_light_level;
+	} p;
+	struct {
+		uint16_t padding[ALF_BEGIN - RPM_BEGIN];
+		uint16_t picture_alf_enable_Y;
+		uint16_t picture_alf_enable_Cb;
+		uint16_t picture_alf_enable_Cr;
+		uint16_t alf_filters_num_m_1;
+		uint16_t region_distance[16];
+		uint16_t alf_cb_coeffmulti[9];
+		uint16_t alf_cr_coeffmulti[9];
+		uint16_t alf_y_coeffmulti[16][9];
+	} alf;
+};
+
+
+struct avs2_decoder {
+	uint8_t init_hw_flag;
+	struct inp_par   input;
+	struct ImageParameters_s  img;
+	struct Video_Com_data_s  hc;
+	struct Video_Dec_data_s  hd;
+	union param_u param;
+	struct avs2_frame_s frm_pool[AVS2_MAX_BUFFER_NUM];
+	struct avs2_frame_s *fref[REF_MAXBUFFER];
+#ifdef AML
+	/*used for background
+	when background_picture_output_flag is 0*/
+	struct avs2_frame_s *m_bg;
+	/*current background picture, ether m_bg or fref[..]*/
+	struct avs2_frame_s *f_bg;
+#endif
+	struct outdata_s outprint;
+	uint32_t cm_header_start;
+	struct ALFParam_s m_alfPictureParam[NUM_ALF_COMPONENT];
+#ifdef FIX_CHROMA_FIELD_MV_BK_DIST
+	int8_t bk_img_is_top_field;
+#endif
+#ifdef AML
+	int32_t lcu_size;
+	int32_t lcu_size_log2;
+	int32_t lcu_x_num;
+	int32_t lcu_y_num;
+	int32_t lcu_total;
+	int32_t ref_maxbuffer;
+	int32_t to_prepare_disp_count;
+	int8_t bufmgr_error_flag;
+#endif
+};
+
+
+extern void write_frame(struct avs2_decoder *avs2_dec, int32_t pos);
+extern void init_frame_t(struct avs2_frame_s *currfref);
+extern void report_frame(struct avs2_decoder *avs2_dec,
+	struct outdata_s *data, int32_t pos);
+
+extern int avs2_post_process(struct avs2_decoder *avs2_dec);
+extern void avs2_prepare_header(struct avs2_decoder *avs2_dec,
+	int32_t start_code);
+extern int32_t avs2_process_header(struct avs2_decoder *avs2_dec);
+
+extern void init_avs2_decoder(struct avs2_decoder *avs2_dec);
+
+extern int32_t avs2_init_global_buffers(struct avs2_decoder *avs2_dec);
+
+extern bool is_avs2_print_param(void);
+extern bool is_avs2_print_bufmgr_detail(void);
+#endif
+
diff --git a/drivers/frame_provider/decoder/avs2/vavs2.c b/drivers/frame_provider/decoder/avs2/vavs2.c
new file mode 100644
index 0000000..e21dc55
--- /dev/null
+++ b/drivers/frame_provider/decoder/avs2/vavs2.c
@@ -0,0 +1,8623 @@
+ /*
+ * drivers/amlogic/amports/avs2.c
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+*/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/semaphore.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/kfifo.h>
+#include <linux/kthread.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include <linux/amlogic/media/frame_sync/tsync.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
+#include <linux/slab.h>
+//#include <linux/amlogic/tee.h>
+#include <uapi/linux/tee.h>
+#include <linux/sched/clock.h>
+#include "../../../stream_input/amports/amports_priv.h"
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include "../utils/decoder_mmu_box.h"
+#include "../utils/decoder_bmmu_box.h"
+#include "avs2_global.h"
+
+#define MEM_NAME "codec_avs2"
+/* #include <mach/am_regs.h> */
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../utils/vdec.h"
+#include "../utils/amvdec.h"
+
+#include <linux/amlogic/media/video_sink/video.h>
+#include <linux/amlogic/media/codec_mm/configs.h>
+#include "../utils/config_parser.h"
+#include "../utils/firmware.h"
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+#include "../utils/vdec_feature.h"
+
+#define I_ONLY_SUPPORT
+#define MIX_STREAM_SUPPORT
+#define CONSTRAIN_MAX_BUF_NUM
+
+#define CO_MV_COMPRESS
+
+#include "vavs2.h"
+#define HEVC_SHIFT_LENGTH_PROTECT                  0x313a
+#define HEVC_MPRED_CTRL4                           0x324c
+#define HEVC_MPRED_CTRL9                           0x325b
+#define HEVC_DBLK_CFGD                             0x350d
+#define HEVC_CM_HEADER_START_ADDR                  0x3628
+#define HEVC_DBLK_CFGB                             0x350b
+#define HEVCD_MPP_ANC2AXI_TBL_DATA                 0x3464
+#define HEVC_SAO_MMU_VH1_ADDR                      0x363b
+#define HEVC_SAO_MMU_VH0_ADDR                      0x363a
+
+#define HEVC_CM_BODY_LENGTH2                       0x3663
+#define HEVC_CM_HEADER_OFFSET2                     0x3664
+#define HEVC_CM_HEADER_LENGTH2                     0x3665
+
+#define HEVC_ASSIST_MMU_MAP_ADDR                   0x3009
+
+#define HEVC_CM_HEADER_START_ADDR                  0x3628
+#define HEVC_CM_HEADER_START_ADDR2                 0x364a
+#define HEVC_SAO_MMU_VH1_ADDR                      0x363b
+#define HEVC_SAO_MMU_VH0_ADDR                      0x363a
+#define HEVC_SAO_MMU_VH0_ADDR2                     0x364d
+#define HEVC_SAO_MMU_VH1_ADDR2                     0x364e
+
+#define HEVC_SAO_MMU_DMA_CTRL2                     0x364c
+#define HEVC_SAO_MMU_STATUS2                       0x3650
+#define HEVC_DW_VH0_ADDDR                          0x365e
+#define HEVC_DW_VH1_ADDDR                          0x365f
+
+#define HEVC_SAO_CTRL9                             0x362d
+
+
+
+/*
+ * AVS2_DEC_STATUS define
+*/
+/*internal*/
+#define AVS2_DEC_IDLE                           0
+#define AVS2_SEQUENCE                           1
+#define AVS2_I_PICTURE                          2
+#define AVS2_PB_PICTURE                         3
+#define AVS2_DISCARD_STARTCODE                  4
+#define AVS2_DISCARD_NAL                        4
+
+#define AVS2_SLICE_DECODING                     6
+
+#define SWAP_IN_CMD                          0x10
+#define SWAP_OUT_CMD                         0x11
+#define SWAP_OUTIN_CMD                       0x12
+#define SWAP_DONE                            0x13
+#define SWAP_POST_INIT                       0x14
+
+/*head*/
+#define AVS2_HEAD_SEQ_READY                  0x21
+#define AVS2_HEAD_PIC_I_READY                0x22
+#define AVS2_HEAD_PIC_PB_READY               0x23
+#define AVS2_HEAD_SEQ_END_READY              0x24
+#define AVS2_STARTCODE_SEARCH_DONE           0x25
+
+/*pic done*/
+#define HEVC_DECPIC_DATA_DONE       0x30
+#define HEVC_DECPIC_DATA_ERROR      0x31
+#define HEVC_NAL_DECODE_DONE        0x32
+#define AVS2_DECODE_BUFEMPTY        0x33
+#define AVS2_DECODE_TIMEOUT         0x34
+#define AVS2_DECODE_OVER_SIZE       0x35
+#define AVS2_EOS                    0x36
+
+/*cmd*/
+#define AVS2_10B_DISCARD_NAL                 0xf0
+#define AVS2_SEARCH_NEW_PIC                  0xf1
+#define AVS2_ACTION_ERROR                    0xfe
+#define HEVC_ACTION_ERROR                    0xfe
+#define AVS2_ACTION_DONE                     0xff
+/*AVS2_DEC_STATUS end*/
+
+
+#define VF_POOL_SIZE        32
+
+#undef pr_info
+#define pr_info printk
+
+#define DECODE_MODE_SINGLE				(0 | (0x80 << 24))
+#define DECODE_MODE_MULTI_STREAMBASE	(1 | (0x80 << 24))
+#define DECODE_MODE_MULTI_FRAMEBASE		(2 | (0x80 << 24))
+
+
+#define  VP9_TRIGGER_FRAME_DONE		0x100
+#define  VP9_TRIGGER_FRAME_ENABLE	0x200
+
+/*#define MV_MEM_UNIT 0x240*/
+#define MV_MEM_UNIT 0x200
+/*---------------------------------------------------
+ Include "parser_cmd.h"
+---------------------------------------------------*/
+#define PARSER_CMD_SKIP_CFG_0 0x0000090b
+
+#define PARSER_CMD_SKIP_CFG_1 0x1b14140f
+
+#define PARSER_CMD_SKIP_CFG_2 0x001b1910
+
+
+#define PARSER_CMD_NUMBER 37
+
+static unsigned short parser_cmd[PARSER_CMD_NUMBER] = {
+0x0401,
+0x8401,
+0x0800,
+0x0402,
+0x9002,
+0x1423,
+0x8CC3,
+0x1423,
+0x8804,
+0x9825,
+0x0800,
+0x04FE,
+0x8406,
+0x8411,
+0x1800,
+0x8408,
+0x8409,
+0x8C2A,
+0x9C2B,
+0x1C00,
+0x840F,
+0x8407,
+0x8000,
+0x8408,
+0x2000,
+0xA800,
+0x8410,
+0x04DE,
+0x840C,
+0x840D,
+0xAC00,
+0xA000,
+0x08C0,
+0x08E0,
+0xA40E,
+0xFC00,
+0x7C00
+};
+
+static int32_t g_WqMDefault4x4[16] = {
+	64,     64,     64,     68,
+	64,     64,     68,     72,
+	64,     68,     76,     80,
+	72,     76,     84,     96
+};
+
+
+static int32_t g_WqMDefault8x8[64] = {
+	64,     64,     64,     64,     68,     68,     72,     76,
+	64,     64,     64,     68,     72,     76,     84,     92,
+	64,     64,     68,     72,     76,     80,     88,     100,
+	64,     68,     72,     80,     84,     92,     100,    112,
+	68,     72,     80,     84,     92,     104,    112,    128,
+	76,     80,     84,     92,     104,    116,    132,    152,
+	96,     100,    104,    116,    124,    140,    164,    188,
+	104,    108,    116,    128,    152,    172,    192,    216
+};
+/*#define HEVC_PIC_STRUCT_SUPPORT*/
+/* to remove, fix build error */
+
+/*#define CODEC_MM_FLAGS_FOR_VDECODER  0*/
+
+#define MULTI_INSTANCE_SUPPORT
+/* #define ERROR_HANDLE_DEBUG */
+
+#ifndef STAT_KTHREAD
+#define STAT_KTHREAD 0x40
+#endif
+
+#ifdef MULTI_INSTANCE_SUPPORT
+#define MAX_DECODE_INSTANCE_NUM     12
+#define MULTI_DRIVER_NAME "ammvdec_avs2"
+
+#define lock_buffer(dec, flags) \
+		spin_lock_irqsave(&dec->buffer_lock, flags)
+
+#define unlock_buffer(dec, flags) \
+		spin_unlock_irqrestore(&dec->buffer_lock, flags)
+
+static u32 debug_mask = 0xffffffff;
+#define get_dbg_flag(dec) ((debug_mask & (1 << dec->index)) ? debug : 0)
+
+static unsigned int max_decode_instance_num
+				= MAX_DECODE_INSTANCE_NUM;
+static unsigned int decode_frame_count[MAX_DECODE_INSTANCE_NUM];
+static unsigned int display_frame_count[MAX_DECODE_INSTANCE_NUM];
+static unsigned int max_process_time[MAX_DECODE_INSTANCE_NUM];
+static unsigned int run_count[MAX_DECODE_INSTANCE_NUM];
+static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM];
+static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM];
+
+static u32 decode_timeout_val = 200;
+
+static int start_decode_buf_level = 0x8000;
+
+static u32 work_buf_size;
+
+static u32 mv_buf_margin;
+static int pre_decode_buf_level = 0x1000;
+static u32 again_threshold;
+
+
+/* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */
+/* double_write_mode:
+ *	0, no double write;
+ *	1, 1:1 ratio;
+ *	2, (1/4):(1/4) ratio;
+ *	3, (1/4):(1/4) ratio, with both compressed frame included
+ *	4, (1/2):(1/2) ratio;
+ *	8, (1/8):(1/8) ratio;
+ *	0x10, double write only
+ *	0x100, if > 1080p,use mode 4,else use mode 1;
+ *	0x200, if > 1080p,use mode 2,else use mode 1;
+ *	0x300, if > 720p, use mode 4, else use mode 1;
+ */
+static u32 double_write_mode;
+static u32 without_display_mode;
+
+static u32 mv_buf_dynamic_alloc;
+
+#define DRIVER_NAME "amvdec_avs2"
+#define DRIVER_HEADER_NAME "amvdec_avs2_header"
+
+
+#define PUT_INTERVAL        (HZ/100)
+#define ERROR_SYSTEM_RESET_COUNT   200
+
+#define PTS_NORMAL                0
+#define PTS_NONE_REF_USE_DURATION 1
+
+#define PTS_MODE_SWITCHING_THRESHOLD           3
+#define PTS_MODE_SWITCHING_RECOVERY_THREASHOLD 3
+
+#define DUR2PTS(x) ((x)*90/96)
+
+struct AVS2Decoder_s;
+static int vavs2_vf_states(struct vframe_states *states, void *);
+static struct vframe_s *vavs2_vf_peek(void *);
+static struct vframe_s *vavs2_vf_get(void *);
+static void vavs2_vf_put(struct vframe_s *, void *);
+static int vavs2_event_cb(int type, void *data, void *private_data);
+static void set_vframe(struct AVS2Decoder_s *dec,
+	struct vframe_s *vf, struct avs2_frame_s *pic, u8 dummy);
+
+static int vavs2_stop(struct AVS2Decoder_s *dec);
+static s32 vavs2_init(struct vdec_s *vdec);
+static void vavs2_prot_init(struct AVS2Decoder_s *dec);
+static int vavs2_local_init(struct AVS2Decoder_s *dec);
+static void vavs2_put_timer_func(struct timer_list *timer);
+static void dump_data(struct AVS2Decoder_s *dec, int size);
+static unsigned char get_data_check_sum
+	(struct AVS2Decoder_s *dec, int size);
+static void dump_pic_list(struct AVS2Decoder_s *dec);
+
+static const char vavs2_dec_id[] = "vavs2-dev";
+
+#define PROVIDER_NAME   "decoder.avs2"
+#define MULTI_INSTANCE_PROVIDER_NAME    "vdec.avs2"
+
+static const struct vframe_operations_s vavs2_vf_provider = {
+	.peek = vavs2_vf_peek,
+	.get = vavs2_vf_get,
+	.put = vavs2_vf_put,
+	.event_cb = vavs2_event_cb,
+	.vf_states = vavs2_vf_states,
+};
+
+static struct vframe_provider_s vavs2_vf_prov;
+
+static u32 bit_depth_luma;
+static u32 bit_depth_chroma;
+static u32 frame_width;
+static u32 frame_height;
+static u32 video_signal_type;
+static u32 pts_unstable;
+static u32 on_no_keyframe_skiped;
+
+static u32 force_video_signal_type;
+static u32 enable_force_video_signal_type;
+#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK	0x20000000
+#define HDR_CUVA_MASK                           0x40000000
+
+
+static const char * const video_format_names[] = {
+	"component", "PAL", "NTSC", "SECAM",
+	"MAC", "unspecified", "Reserved", "Reserved"
+};
+
+static inline int div_r32(int64_t m, int n)
+{
+/*
+return (int)(m/n)
+*/
+#ifndef CONFIG_ARM64
+	int64_t qu = 0;
+	qu = div_s64(m, n);
+	return (int)qu;
+#else
+	return (int)(m/n);
+#endif
+}
+
+enum vpx_bit_depth_t {
+	AVS2_BITS_8  =  8,  /**<  8 bits */
+	AVS2_BITS_10 = 10,  /**< 10 bits */
+	AVS2_BITS_12 = 12,  /**< 12 bits */
+};
+
+/*USE_BUF_BLOCK*/
+struct BUF_s {
+	int index;
+	unsigned int alloc_flag;
+	/*buffer */
+	unsigned int cma_page_count;
+	unsigned long alloc_addr;
+	unsigned long start_adr;
+	unsigned int size;
+
+	unsigned int free_start_adr;
+} /*BUF_t */;
+
+struct MVBUF_s {
+	unsigned long start_adr;
+	unsigned int size;
+	int used_flag;
+} /*MVBUF_t */;
+
+	/* #undef BUFMGR_ONLY to enable hardware configuration */
+
+/*#define TEST_WR_PTR_INC*/
+#define WR_PTR_INC_NUM 128
+
+#define SIMULATION
+#define DOS_PROJECT
+#undef MEMORY_MAP_IN_REAL_CHIP
+
+/*#undef DOS_PROJECT*/
+/*#define MEMORY_MAP_IN_REAL_CHIP*/
+
+/*#define BUFFER_MGR_ONLY*/
+/*#define CONFIG_HEVC_CLK_FORCED_ON*/
+/*#define ENABLE_SWAP_TEST*/
+
+#ifdef AVS2_10B_NV21
+#define MEM_MAP_MODE 2  /* 0:linear 1:32x32 2:64x32*/
+#else
+#define MEM_MAP_MODE 0  /* 0:linear 1:32x32 2:64x32*/
+#endif
+
+#ifdef AVS2_10B_NV21
+#else
+#define LOSLESS_COMPRESS_MODE
+#endif
+
+#define DOUBLE_WRITE_YSTART_TEMP 0x02000000
+#define DOUBLE_WRITE_CSTART_TEMP 0x02900000
+
+#define AVS2_DBG_BUFMGR                   0x01
+#define AVS2_DBG_BUFMGR_MORE              0x02
+#define AVS2_DBG_BUFMGR_DETAIL            0x04
+#define AVS2_DBG_IRQ_EVENT                0x08
+#define AVS2_DBG_OUT_PTS                  0x10
+#define AVS2_DBG_PRINT_SOURCE_LINE        0x20
+#define AVS2_DBG_PRINT_PARAM              0x40
+#define AVS2_DBG_PRINT_PIC_LIST           0x80
+#define AVS2_DBG_SEND_PARAM_WITH_REG      0x100
+#define AVS2_DBG_MERGE                    0x200
+#define AVS2_DBG_DBG_LF_PRINT             0x400
+#define AVS2_DBG_REG                      0x800
+#define AVS2_DBG_PIC_LEAK                 0x1000
+#define AVS2_DBG_PIC_LEAK_WAIT            0x2000
+#define AVS2_DBG_HDR_INFO                 0x4000
+#define AVS2_DBG_HDR_DATA                 0x8000
+#define AVS2_DBG_DIS_LOC_ERROR_PROC       0x10000
+#define AVS2_DBG_DIS_SYS_ERROR_PROC   0x20000
+#define AVS2_DBG_DUMP_PIC_LIST       0x40000
+#define AVS2_DBG_TRIG_SLICE_SEGMENT_PROC 0x80000
+#define AVS2_DBG_FORCE_UNCOMPRESS       0x100000
+#define AVS2_DBG_LOAD_UCODE_FROM_FILE   0x200000
+#define AVS2_DBG_FORCE_SEND_AGAIN       0x400000
+#define AVS2_DBG_DUMP_DATA              0x800000
+#define AVS2_DBG_DUMP_LMEM_BUF         0x1000000
+#define AVS2_DBG_DUMP_RPM_BUF          0x2000000
+#define AVS2_DBG_CACHE                 0x4000000
+#define IGNORE_PARAM_FROM_CONFIG         0x8000000
+/*MULTI_INSTANCE_SUPPORT*/
+#define PRINT_FLAG_ERROR				0
+#define PRINT_FLAG_VDEC_STATUS             0x20000000
+#define PRINT_FLAG_VDEC_DETAIL             0x40000000
+#define PRINT_FLAG_VDEC_DATA             0x80000000
+
+#define PRINT_LINE() \
+	do { \
+		if (debug & AVS2_DBG_PRINT_SOURCE_LINE)\
+			pr_info("%s line %d\n", __func__, __LINE__);\
+	} while (0)
+
+static u32 debug;
+
+static u32 debug_again;
+
+bool is_avs2_print_param(void)
+{
+	bool ret = false;
+	if (debug & AVS2_DBG_PRINT_PARAM)
+		ret = true;
+	return ret;
+}
+
+bool is_avs2_print_bufmgr_detail(void)
+{
+	bool ret = false;
+	if (debug & AVS2_DBG_BUFMGR_DETAIL)
+		ret = true;
+	return ret;
+}
+static bool is_reset;
+/*for debug*/
+static u32 force_bufspec;
+/*
+	udebug_flag:
+	bit 0, enable ucode print
+	bit 1, enable ucode detail print
+	bit [31:16] not 0, pos to dump lmem
+		bit 2, pop bits to lmem
+		bit [11:8], pre-pop bits for alignment (when bit 2 is 1)
+*/
+static u32 udebug_flag;
+/*
+	when udebug_flag[1:0] is not 0
+	udebug_pause_pos not 0,
+		pause position
+*/
+static u32 udebug_pause_pos;
+/*
+	when udebug_flag[1:0] is not 0
+	and udebug_pause_pos is not 0,
+		pause only when DEBUG_REG2 is equal to this val
+*/
+static u32 udebug_pause_val;
+
+static u32 udebug_pause_decode_idx;
+
+static u32 force_disp_pic_index;
+
+#define AUX_BUF_ALIGN(adr) ((adr + 0xf) & (~0xf))
+static u32 cuva_buf_size = 512;
+
+#define DEBUG_REG
+#ifdef DEBUG_REG
+static void WRITE_VREG_DBG2(unsigned adr, unsigned val)
+{
+	if (debug & AVS2_DBG_REG)
+		pr_info("%s(%x, %x)\n", __func__, adr, val);
+	if (adr != 0)
+		WRITE_VREG(adr, val);
+}
+
+#undef WRITE_VREG
+#define WRITE_VREG WRITE_VREG_DBG2
+#endif
+
+#define MMU_COMPRESS_HEADER_SIZE_1080P  0x10000
+#define MMU_COMPRESS_HEADER_SIZE_4K  0x48000
+#define MMU_COMPRESS_HEADER_SIZE_8K  0x120000
+
+#define INVALID_IDX -1  /* Invalid buffer index.*/
+
+
+#define FRAME_BUFFERS (AVS2_MAX_BUFFER_NUM)
+#define HEADER_FRAME_BUFFERS (FRAME_BUFFERS)
+#define MAX_BUF_NUM (FRAME_BUFFERS)
+
+#define FRAME_CONTEXTS_LOG2 2
+#define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2)
+/*buffer + header buffer + workspace*/
+
+#ifdef MV_USE_FIXED_BUF
+#define MAX_BMMU_BUFFER_NUM ((FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1)+1)
+#define VF_BUFFER_IDX(n) (n)
+#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n+1)
+#define WORK_SPACE_BUF_ID (FRAME_BUFFERS + HEADER_FRAME_BUFFERS+1)
+#else
+#define MAX_BMMU_BUFFER_NUM (((FRAME_BUFFERS*2)+HEADER_FRAME_BUFFERS+1)+1)
+#define VF_BUFFER_IDX(n) (n)
+#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n+1)
+#define MV_BUFFER_IDX(n) ((FRAME_BUFFERS * 2) + n+1)
+#define WORK_SPACE_BUF_ID ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS+1)
+//#define DW_HEADER_BUFFER_IDX(n) ((FRAME_BUFFERS * 3) + n+1)
+#endif
+
+#define CO_MV_BUF_SIZE_1080P  0x3fc00
+#define CO_MV_BUF_SIZE_4K     0x120000
+#define CO_MV_BUF_SIZE_8K     0x480000
+/*
+static void set_canvas(struct AVS2Decoder_s *dec,
+	struct avs2_frame_s *pic);
+int avs2_prepare_display_buf(struct AVS2Decoder_s *dec,
+					int pos);
+*/
+
+
+struct buff_s {
+	u32 buf_start;
+	u32 buf_size;
+	u32 buf_end;
+};
+
+struct BuffInfo_s {
+	u32 max_width;
+	u32 max_height;
+	u32 start_adr;
+	u32 end_adr;
+	struct buff_s ipp;
+	struct buff_s sao_abv;
+	struct buff_s sao_vb;
+	struct buff_s short_term_rps;
+	struct buff_s rcs;
+	struct buff_s sps;
+	struct buff_s pps;
+	struct buff_s sao_up;
+	struct buff_s swap_buf;
+	struct buff_s swap_buf2;
+	struct buff_s scalelut;
+	struct buff_s dblk_para;
+	struct buff_s dblk_data;
+	struct buff_s dblk_data2;
+#ifdef AVS2_10B_MMU
+	struct buff_s mmu_vbh;
+	struct buff_s cm_header;
+#endif
+#ifdef AVS2_10B_MMU_DW
+	struct buff_s mmu_vbh_dw;
+	struct buff_s cm_header_dw;
+#endif
+	struct buff_s mpred_above;
+#ifdef MV_USE_FIXED_BUF
+	struct buff_s mpred_mv;
+#endif
+	struct buff_s rpm;
+	struct buff_s lmem;
+};
+
+#define DEC_RESULT_NONE             0
+#define DEC_RESULT_DONE             1
+#define DEC_RESULT_AGAIN            2
+#define DEC_RESULT_CONFIG_PARAM     3
+#define DEC_RESULT_ERROR            4
+#define DEC_INIT_PICLIST			5
+#define DEC_UNINIT_PICLIST			6
+#define DEC_RESULT_GET_DATA         7
+#define DEC_RESULT_GET_DATA_RETRY   8
+#define DEC_RESULT_EOS              9
+#define DEC_RESULT_FORCE_EXIT       10
+
+static void avs2_work(struct work_struct *work);
+struct loop_filter_info_n;
+struct loopfilter;
+struct segmentation;
+
+struct AVS2Decoder_s {
+	int pic_list_init_flag;
+	unsigned char index;
+	spinlock_t buffer_lock;
+	struct device *cma_dev;
+	struct platform_device *platform_dev;
+	void (*vdec_cb)(struct vdec_s *, void *);
+	void *vdec_cb_arg;
+	struct vframe_chunk_s *chunk;
+	int dec_result;
+	struct work_struct work;
+	u32 start_shift_bytes;
+
+	struct BuffInfo_s work_space_buf_store;
+	unsigned long buf_start;
+	u32 buf_size;
+	u32 cma_alloc_count;
+	unsigned long cma_alloc_addr;
+	uint8_t eos;
+	unsigned long int start_process_time;
+	unsigned last_lcu_idx;
+	int decode_timeout_count;
+	unsigned timeout_num;
+
+	int double_write_mode;
+
+	unsigned char m_ins_flag;
+	char *provider_name;
+	int frame_count;
+	u32 stat;
+	struct timer_list timer;
+	u32 frame_dur;
+	u32 frame_ar;
+	u32 vavs2_ratio;
+	int fatal_error;
+	uint8_t init_flag;
+	uint8_t first_sc_checked;
+	uint8_t process_busy;
+#define PROC_STATE_INIT			0
+#define PROC_STATE_HEAD_DONE	1
+#define PROC_STATE_DECODING		2
+#define PROC_STATE_HEAD_AGAIN	3
+#define PROC_STATE_DECODE_AGAIN	4
+#define PROC_STATE_TEST1		5
+	uint8_t process_state;
+	u32 ucode_pause_pos;
+
+	int show_frame_num;
+#ifndef AVS2_10B_MMU
+	struct buff_s mc_buf_spec;
+#endif
+	struct dec_sysinfo vavs2_amstream_dec_info;
+	void *rpm_addr;
+	void *lmem_addr;
+	dma_addr_t rpm_phy_addr;
+	dma_addr_t lmem_phy_addr;
+	unsigned short *lmem_ptr;
+	unsigned short *debug_ptr;
+
+#ifdef AVS2_10B_MMU
+	bool mmu_enable;
+
+	u32 cuva_size;
+	void *cuva_addr;
+	dma_addr_t cuva_phy_addr;
+
+	void *frame_mmu_map_addr;
+	dma_addr_t frame_mmu_map_phy_addr;
+#endif
+#ifdef AVS2_10B_MMU_DW
+	bool dw_mmu_enable;
+	void *dw_mmu_box;
+	void *dw_frame_mmu_map_addr;
+	dma_addr_t dw_frame_mmu_map_phy_addr;
+#endif
+	unsigned int use_cma_flag;
+
+	struct BUF_s m_BUF[MAX_BUF_NUM];
+	struct MVBUF_s m_mv_BUF[MAX_BUF_NUM];
+	u32 used_buf_num;
+	DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE);
+	DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE);
+	DECLARE_KFIFO(pending_q, struct vframe_s *, VF_POOL_SIZE);
+	struct vframe_s vfpool[VF_POOL_SIZE];
+	u32 vf_pre_count;
+	u32 vf_get_count;
+	u32 vf_put_count;
+	int buf_num;
+	unsigned int losless_comp_body_size;
+
+	u32 video_signal_type;
+	u32 video_ori_signal_type;
+
+	int pts_mode;
+	int last_lookup_pts;
+	int last_pts;
+	u64 last_lookup_pts_us64;
+	u64 last_pts_us64;
+	u64 shift_byte_count;
+	u32 shift_byte_count_lo;
+	u32 shift_byte_count_hi;
+	int pts_mode_switching_count;
+	int pts_mode_recovery_count;
+
+	bool get_frame_dur;
+	u32 saved_resolution;
+
+	/**/
+	int refresh_frame_flags;
+	uint8_t hold_ref_buf;
+	struct BuffInfo_s *work_space_buf;
+#ifndef AVS2_10B_MMU
+	struct buff_s *mc_buf;
+#endif
+	unsigned int frame_width;
+	unsigned int frame_height;
+
+	unsigned short *rpm_ptr;
+	int     init_pic_w;
+	int     init_pic_h;
+
+	int     slice_type;
+
+	int decode_idx;
+	int slice_idx;
+	uint8_t wait_buf;
+	uint8_t error_flag;
+	unsigned int bufmgr_error_count;
+
+	/* bit 0, for decoding; bit 1, for displaying */
+	uint8_t ignore_bufmgr_error;
+	uint8_t skip_PB_before_I;
+	int PB_skip_mode;
+	int PB_skip_count_after_decoding;
+	/*hw*/
+
+	/**/
+	struct vdec_info *gvs;
+
+
+	unsigned int dec_status;
+	u32 last_put_idx;
+	int new_frame_displayed;
+	void *mmu_box;
+	void *bmmu_box;
+	struct vframe_master_display_colour_s vf_dp;
+	struct firmware_s *fw;
+#ifdef AVS2_10B_MMU
+	int cur_fb_idx_mmu;
+	long used_4k_num;
+#endif
+	struct avs2_decoder avs2_dec;
+#define ALF_NUM_BIT_SHIFT      6
+#define NO_VAR_BINS            16
+	int32_t m_filterCoeffSym[16][9];
+	int32_t m_varIndTab[NO_VAR_BINS];
+
+	struct vframe_s vframe_dummy;
+		/* start_decoding_flag,
+			bit 0, SEQ ready
+			bit 1, I ready
+		*/
+	unsigned char start_decoding_flag;
+	uint32_t mpred_abv_start_addr;
+	uint32_t mpred_abv_start_addr_bak;
+	u8 next_again_flag;
+	u32 pre_parser_wr_ptr;
+	int need_cache_size;
+	u64 sc_start_time;
+#ifdef I_ONLY_SUPPORT
+	u32 i_only;
+#endif
+	int frameinfo_enable;
+	struct vframe_qos_s vframe_qos;
+	u32 dynamic_buf_margin;
+	int sidebind_type;
+	int sidebind_channel_id;
+	u32 endian;
+	char vdec_name[32];
+	char pts_name[32];
+	char new_q_name[32];
+	char disp_q_name[32];
+	dma_addr_t rdma_phy_adr;
+	unsigned *rdma_adr;
+	int hdr_flag;
+};
+
+static int  compute_losless_comp_body_size(
+		struct AVS2Decoder_s *dec, int width, int height,
+		uint8_t is_bit_depth_10);
+
+static int avs2_print(struct AVS2Decoder_s *dec,
+	int flag, const char *fmt, ...)
+{
+#define HEVC_PRINT_BUF		256
+	unsigned char buf[HEVC_PRINT_BUF];
+	int len = 0;
+	if (dec == NULL ||
+		(flag == 0) ||
+		(debug & flag)) {
+		va_list args;
+		va_start(args, fmt);
+		if (dec)
+			len = sprintf(buf, "[%d]", dec->index);
+		vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args);
+		pr_info("%s", buf);
+		va_end(args);
+	}
+	return 0;
+}
+
+static int avs2_print_cont(struct AVS2Decoder_s *dec,
+	int flag, const char *fmt, ...)
+{
+	unsigned char buf[HEVC_PRINT_BUF];
+	int len = 0;
+	if (dec == NULL ||
+		(flag == 0) ||
+		(debug & flag)) {
+		va_list args;
+		va_start(args, fmt);
+		vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args);
+		pr_info("%s", buf);
+		va_end(args);
+	}
+	return 0;
+}
+
+#define PROB_SIZE    (496 * 2 * 4)
+#define PROB_BUF_SIZE    (0x5000)
+#define COUNT_BUF_SIZE   (0x300 * 4 * 4)
+/*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/
+#define MAX_FRAME_4K_NUM 0x1200
+#define MAX_FRAME_8K_NUM 0x4800
+#define MAX_SIZE_4K (4096 * 2304)
+#define IS_8K_SIZE(w, h)	(((w) * (h)) > MAX_SIZE_4K)
+#define IS_4K_SIZE(w, h)  (((w) * (h)) > (1920*1088))
+
+static int get_frame_mmu_map_size(struct AVS2Decoder_s *dec)
+{
+	if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+		(IS_8K_SIZE(dec->init_pic_w, dec->init_pic_h)))
+		return (MAX_FRAME_8K_NUM * 4);
+	return (MAX_FRAME_4K_NUM * 4);
+}
+
+static int get_compress_header_size(struct AVS2Decoder_s *dec)
+{
+	if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+		(IS_8K_SIZE(dec->init_pic_w, dec->init_pic_h)))
+		return MMU_COMPRESS_HEADER_SIZE_8K;
+	else if (IS_4K_SIZE(dec->init_pic_w, dec->init_pic_h))
+		return MMU_COMPRESS_HEADER_SIZE_4K;
+	return MMU_COMPRESS_HEADER_SIZE_1080P;
+}
+
+static void reset_process_time(struct AVS2Decoder_s *dec)
+{
+	if (dec->start_process_time) {
+		unsigned process_time =
+			1000 * (jiffies - dec->start_process_time) / HZ;
+		dec->start_process_time = 0;
+		if (process_time > max_process_time[dec->index])
+			max_process_time[dec->index] = process_time;
+	}
+}
+
+static void start_process_time(struct AVS2Decoder_s *dec)
+{
+	dec->start_process_time = jiffies;
+	dec->decode_timeout_count = 0;
+	dec->last_lcu_idx = 0;
+}
+
+static void update_decoded_pic(struct AVS2Decoder_s *dec);
+
+static void timeout_process(struct AVS2Decoder_s *dec)
+{
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic;
+	dec->timeout_num++;
+	amhevc_stop();
+	avs2_print(dec,
+		0, "%s decoder timeout\n", __func__);
+	if (cur_pic)
+		cur_pic->error_mark = 1;
+	dec->dec_result = DEC_RESULT_DONE;
+	update_decoded_pic(dec);
+	reset_process_time(dec);
+	vdec_schedule_work(&dec->work);
+}
+
+static u32 get_valid_double_write_mode(struct AVS2Decoder_s *dec)
+{
+	u32 dw_mode;
+
+	dw_mode = (dec->m_ins_flag &&
+		((double_write_mode & 0x80000000) == 0)) ?
+		dec->double_write_mode :
+		(double_write_mode & 0x7fffffff);
+	if (dw_mode & 0x20) {
+		if ((get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_T3)
+			&& ((dw_mode & 0xf) == 2 || (dw_mode & 0xf) == 3))
+			dw_mode = 0;
+	}
+
+	return dw_mode;
+}
+
+static int get_double_write_mode(struct AVS2Decoder_s *dec)
+{
+	u32 valid_dw_mode = get_valid_double_write_mode(dec);
+	int w = dec->avs2_dec.img.width;
+	int h = dec->avs2_dec.img.height;
+	u32 dw = 0x1; /*1:1*/
+	switch (valid_dw_mode) {
+	case 0x100:
+		if (w > 1920 && h > 1088)
+			dw = 0x4; /*1:2*/
+		break;
+	case 0x200:
+		if (w > 1920 && h > 1088)
+			dw = 0x2; /*1:4*/
+		break;
+	case 0x300:
+		if (w > 1280 && h > 720)
+			dw = 0x4; /*1:2*/
+		break;
+	default:
+		dw = valid_dw_mode;
+		break;
+	}
+	return dw;
+}
+
+/* for double write buf alloc */
+static int get_double_write_mode_init(struct AVS2Decoder_s *dec)
+{
+	u32 valid_dw_mode = get_valid_double_write_mode(dec);
+	u32 dw;
+	int w = dec->init_pic_w;
+	int h = dec->init_pic_h;
+
+	dw = 0x1; /*1:1*/
+	switch (valid_dw_mode) {
+	case 0x100:
+		if (w > 1920 && h > 1088)
+			dw = 0x4; /*1:2*/
+		break;
+	case 0x200:
+		if (w > 1920 && h > 1088)
+			dw = 0x2; /*1:4*/
+		break;
+	case 0x300:
+		if (w > 1280 && h > 720)
+			dw = 0x4; /*1:2*/
+		break;
+	default:
+		dw = valid_dw_mode;
+		break;
+	}
+	return dw;
+}
+
+//#define	MAX_4K_NUM		0x1200
+#ifdef AVS2_10B_MMU
+int avs2_alloc_mmu(
+	struct AVS2Decoder_s *dec,
+	int cur_buf_idx,
+	int pic_width,
+	int pic_height,
+	unsigned short bit_depth,
+	unsigned int *mmu_index_adr)
+{
+	int bit_depth_10 = (bit_depth == AVS2_BITS_10);
+	int picture_size;
+	int cur_mmu_4k_number, max_frame_num;
+
+	picture_size = compute_losless_comp_body_size(
+		dec, pic_width, pic_height,
+		bit_depth_10);
+	cur_mmu_4k_number = ((picture_size + (1 << 12) - 1) >> 12);
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)
+		max_frame_num = MAX_FRAME_8K_NUM;
+	else
+		max_frame_num = MAX_FRAME_4K_NUM;
+	if (cur_mmu_4k_number > max_frame_num) {
+		pr_err("over max !! cur_mmu_4k_number 0x%x width %d height %d\n",
+			cur_mmu_4k_number, pic_width, pic_height);
+		return -1;
+	}
+	return decoder_mmu_box_alloc_idx(
+		dec->mmu_box,
+		cur_buf_idx,
+		cur_mmu_4k_number,
+		mmu_index_adr);
+}
+#endif
+
+#ifdef AVS2_10B_MMU_DW
+int avs2_alloc_dw_mmu(
+	struct AVS2Decoder_s *dec,
+	int cur_buf_idx,
+	int pic_width,
+	int pic_height,
+	unsigned short bit_depth,
+	unsigned int *mmu_index_adr)
+{
+	int bit_depth_10 = (bit_depth == AVS2_BITS_10);
+	int picture_size;
+	int cur_mmu_4k_number, max_frame_num;
+
+	picture_size = compute_losless_comp_body_size(
+		dec, pic_width, pic_height,
+		bit_depth_10);
+	cur_mmu_4k_number = ((picture_size + (1 << 12) - 1) >> 12);
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)
+		max_frame_num = MAX_FRAME_8K_NUM;
+	else
+		max_frame_num = MAX_FRAME_4K_NUM;
+	if (cur_mmu_4k_number > max_frame_num) {
+		pr_err("over max !! cur_mmu_4k_number 0x%x width %d height %d\n",
+			cur_mmu_4k_number, pic_width, pic_height);
+		return -1;
+	}
+	return decoder_mmu_box_alloc_idx(
+		dec->dw_mmu_box,
+		cur_buf_idx,
+		cur_mmu_4k_number,
+		mmu_index_adr);
+}
+#endif
+
+static int get_free_buf_count(struct AVS2Decoder_s *dec)
+{
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	int i;
+	int count = 0;
+	for (i = 0; i < avs2_dec->ref_maxbuffer; i++) {
+		if ((avs2_dec->fref[i]->imgcoi_ref < -256
+#if 0
+			|| abs(avs2_dec->fref[i]->
+				imgtr_fwRefDistance - img->tr) >= 128
+#endif
+				) && avs2_dec->fref[i]->is_output == -1
+				&& avs2_dec->fref[i]->bg_flag == 0
+#ifndef NO_DISPLAY
+				&& avs2_dec->fref[i]->vf_ref == 0
+				&& avs2_dec->fref[i]->to_prepare_disp == 0
+#endif
+				) {
+			count++;
+		}
+	}
+
+	return count;
+}
+
+#ifdef CONSTRAIN_MAX_BUF_NUM
+static int get_vf_ref_only_buf_count(struct AVS2Decoder_s *dec)
+{
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	int i;
+	int count = 0;
+	for (i = 0; i < avs2_dec->ref_maxbuffer; i++) {
+		if ((avs2_dec->fref[i]->imgcoi_ref < -256
+#if 0
+			|| abs(avs2_dec->fref[i]->
+				imgtr_fwRefDistance - img->tr) >= 128
+#endif
+				) && avs2_dec->fref[i]->is_output == -1
+				&& avs2_dec->fref[i]->bg_flag == 0
+#ifndef NO_DISPLAY
+				&& avs2_dec->fref[i]->vf_ref > 0
+				&& avs2_dec->fref[i]->to_prepare_disp == 0
+#endif
+				) {
+			count++;
+		}
+	}
+
+	return count;
+}
+
+static int get_used_buf_count(struct AVS2Decoder_s *dec)
+{
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	int i;
+	int count = 0;
+	for (i = 0; i < avs2_dec->ref_maxbuffer; i++) {
+		if ((avs2_dec->fref[i]->imgcoi_ref >= -256
+#if 0
+			|| abs(avs2_dec->fref[i]->
+				imgtr_fwRefDistance - img->tr) >= 128
+#endif
+				) || avs2_dec->fref[i]->is_output != -1
+				|| avs2_dec->fref[i]->bg_flag != 0
+#ifndef NO_DISPLAY
+				|| avs2_dec->fref[i]->vf_ref != 0
+				|| avs2_dec->fref[i]->to_prepare_disp != 0
+#endif
+				) {
+			count++;
+		}
+	}
+
+	return count;
+}
+#endif
+
+int avs2_bufmgr_init(struct AVS2Decoder_s *dec, struct BuffInfo_s *buf_spec_i,
+		struct buff_s *mc_buf_i) {
+
+	dec->frame_count = 0;
+#ifdef AVS2_10B_MMU
+	dec->used_4k_num = -1;
+	dec->cur_fb_idx_mmu = INVALID_IDX;
+#endif
+
+
+	/* private init */
+	dec->work_space_buf = buf_spec_i;
+#ifndef AVS2_10B_MMU
+	dec->mc_buf = mc_buf_i;
+#endif
+	dec->rpm_addr = NULL;
+	dec->lmem_addr = NULL;
+
+	dec->use_cma_flag = 0;
+	dec->decode_idx = 0;
+	dec->slice_idx = 0;
+	/*int m_uiMaxCUWidth = 1<<7;*/
+	/*int m_uiMaxCUHeight = 1<<7;*/
+	dec->wait_buf = 0;
+	dec->error_flag = 0;
+	dec->skip_PB_before_I = 0;
+
+	dec->pts_mode = PTS_NORMAL;
+	dec->last_pts = 0;
+	dec->last_lookup_pts = 0;
+	dec->last_pts_us64 = 0;
+	dec->last_lookup_pts_us64 = 0;
+	dec->shift_byte_count = 0;
+	dec->shift_byte_count_lo = 0;
+	dec->shift_byte_count_hi = 0;
+	dec->pts_mode_switching_count = 0;
+	dec->pts_mode_recovery_count = 0;
+
+	dec->buf_num = 0;
+
+	dec->bufmgr_error_count = 0;
+	return 0;
+}
+
+
+
+#define HEVC_CM_BODY_START_ADDR                    0x3626
+#define HEVC_CM_BODY_LENGTH                        0x3627
+#define HEVC_CM_HEADER_LENGTH                      0x3629
+#define HEVC_CM_HEADER_OFFSET                      0x362b
+
+#define LOSLESS_COMPRESS_MODE
+
+/*#define DECOMP_HEADR_SURGENT*/
+
+static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */
+static u32 enable_mem_saving = 1;
+static u32 force_w_h;
+
+static u32 force_fps;
+
+
+const u32 avs2_version = 201602101;
+static u32 radr;
+static u32 rval;
+static u32 pop_shorts;
+static u32 dbg_cmd;
+static u32 dbg_skip_decode_index;
+/*
+ * bit 0~3, for HEVCD_IPP_AXIIF_CONFIG endian config
+ * bit 8~23, for HEVC_SAO_CTRL1 endian config
+ */
+static u32 endian;
+#define HEVC_CONFIG_BIG_ENDIAN     ((0x880 << 8) | 0x8)
+#define HEVC_CONFIG_LITTLE_ENDIAN  ((0xff0 << 8) | 0xf)
+
+#ifdef ERROR_HANDLE_DEBUG
+static u32 dbg_nal_skip_flag;
+		/* bit[0], skip vps; bit[1], skip sps; bit[2], skip pps */
+static u32 dbg_nal_skip_count;
+#endif
+/*for debug*/
+static u32 decode_pic_begin;
+static uint slice_parse_begin;
+static u32 step;
+#ifdef MIX_STREAM_SUPPORT
+static u32 buf_alloc_width = 4096;
+static u32 buf_alloc_height = 2304;
+
+static u32 dynamic_buf_num_margin;
+#else
+static u32 buf_alloc_width;
+static u32 buf_alloc_height;
+static u32 dynamic_buf_num_margin = 7;
+#endif
+#ifdef CONSTRAIN_MAX_BUF_NUM
+static u32 run_ready_max_vf_only_num;
+static u32 run_ready_display_q_num;
+	/*0: not check
+	  0xff: avs2_dec.ref_maxbuffer
+	  */
+static u32 run_ready_max_buf_num = 0xff;
+#endif
+static u32 buf_alloc_depth = 10;
+static u32 buf_alloc_size;
+/*
+bit[0]: 0,
+    bit[1]: 0, always release cma buffer when stop
+    bit[1]: 1, never release cma buffer when stop
+bit[0]: 1, when stop, release cma buffer if blackout is 1;
+do not release cma buffer is blackout is not 1
+
+bit[2]: 0, when start decoding, check current displayed buffer
+	 (only for buffer decoded by vp9) if blackout is 0
+	 1, do not check current displayed buffer
+
+bit[3]: 1, if blackout is not 1, do not release current
+			displayed cma buffer always.
+*/
+/* set to 1 for fast play;
+	set to 8 for other case of "keep last frame"
+*/
+static u32 buffer_mode = 1;
+/* buffer_mode_dbg: debug only*/
+static u32 buffer_mode_dbg = 0xffff0000;
+/**/
+
+/*
+bit 0, 1: only display I picture;
+bit 1, 1: only decode I picture;
+*/
+static u32 i_only_flag;
+
+
+static u32 max_decoding_time;
+/*
+error handling
+*/
+/*error_handle_policy:
+bit 0: search seq again if buffer mgr error occur
+	(buffer mgr error count need big than
+	re_search_seq_threshold)
+bit 1:  1, display from I picture;
+		0, display from any correct pic
+*/
+
+static u32 error_handle_policy = 1;
+/*
+re_search_seq_threshold:
+	bit 7~0: buffer mgr error research seq count
+	bit 15~8: frame count threshold
+*/
+static u32 re_search_seq_threshold = 0x800; /*0x8;*/
+/*static u32 parser_sei_enable = 1;*/
+
+static u32 max_buf_num = (REF_BUFFER + 1);
+
+static u32 run_ready_min_buf_num = 2;
+
+static DEFINE_MUTEX(vavs2_mutex);
+
+#define HEVC_DEC_STATUS_REG       HEVC_ASSIST_SCRATCH_0
+#define HEVC_RPM_BUFFER           HEVC_ASSIST_SCRATCH_1
+#define AVS2_ALF_SWAP_BUFFER      HEVC_ASSIST_SCRATCH_2
+#define HEVC_RCS_BUFFER           HEVC_ASSIST_SCRATCH_3
+#define HEVC_SPS_BUFFER           HEVC_ASSIST_SCRATCH_4
+#define HEVC_PPS_BUFFER           HEVC_ASSIST_SCRATCH_5
+//#define HEVC_SAO_UP               HEVC_ASSIST_SCRATCH_6
+#ifdef AVS2_10B_MMU
+#define AVS2_MMU_MAP_BUFFER       HEVC_ASSIST_SCRATCH_7
+#else
+#define HEVC_STREAM_SWAP_BUFFER   HEVC_ASSIST_SCRATCH_7
+#endif
+#define HEVC_STREAM_SWAP_BUFFER2  HEVC_ASSIST_SCRATCH_8
+/*
+#define VP9_PROB_SWAP_BUFFER      HEVC_ASSIST_SCRATCH_9
+#define VP9_COUNT_SWAP_BUFFER     HEVC_ASSIST_SCRATCH_A
+#define VP9_SEG_MAP_BUFFER        HEVC_ASSIST_SCRATCH_B
+*/
+#define AVS2_CUVA_ADR             HEVC_ASSIST_SCRATCH_A
+#define AVS2_CUVA_DATA_SIZE       HEVC_ASSIST_SCRATCH_B
+
+//#define HEVC_SCALELUT             HEVC_ASSIST_SCRATCH_D
+#define HEVC_WAIT_FLAG            HEVC_ASSIST_SCRATCH_E
+#define RPM_CMD_REG               HEVC_ASSIST_SCRATCH_F
+#define LMEM_DUMP_ADR             HEVC_ASSIST_SCRATCH_9
+#define HEVC_STREAM_SWAP_TEST     HEVC_ASSIST_SCRATCH_L
+/*!!!*/
+#define HEVC_DECODE_COUNT       HEVC_ASSIST_SCRATCH_M
+#define HEVC_DECODE_SIZE		HEVC_ASSIST_SCRATCH_N
+#define DEBUG_REG1              HEVC_ASSIST_SCRATCH_G
+#define DEBUG_REG2              HEVC_ASSIST_SCRATCH_H
+
+
+/*
+ucode parser/search control
+bit 0:  0, header auto parse; 1, header manual parse
+bit 1:  0, auto skip for noneseamless stream; 1, no skip
+bit [3:2]: valid when bit1==0;
+0, auto skip nal before first vps/sps/pps/idr;
+1, auto skip nal before first vps/sps/pps
+2, auto skip nal before first  vps/sps/pps,
+	and not decode until the first I slice (with slice address of 0)
+
+3, auto skip before first I slice (nal_type >=16 && nal_type<=21)
+bit [15:4] nal skip count (valid when bit0 == 1 (manual mode) )
+bit [16]: for NAL_UNIT_EOS when bit0 is 0:
+	0, send SEARCH_DONE to arm ;  1, do not send SEARCH_DONE to arm
+bit [17]: for NAL_SEI when bit0 is 0:
+	0, do not parse SEI in ucode; 1, parse SEI in ucode
+bit [31:20]: used by ucode for debug purpose
+*/
+#define NAL_SEARCH_CTL            HEVC_ASSIST_SCRATCH_I
+	/*DECODE_MODE: set before start decoder
+		bit 7~0: decode mode
+		bit 23~16: start_decoding_flag
+			bit [0]   - SEQ_ready
+			bit [2:1] - I Picture Count
+		bit 31~24: chip feature
+	*/
+#define DECODE_MODE              HEVC_ASSIST_SCRATCH_J
+#define DECODE_STOP_POS         HEVC_ASSIST_SCRATCH_K
+	/*read only*/
+#define CUR_NAL_UNIT_TYPE       HEVC_ASSIST_SCRATCH_J
+
+#define RPM_BUF_SIZE (0x600 * 2)
+#define LMEM_BUF_SIZE (0x600 * 2)
+
+	/*mmu_vbh buf is used by HEVC_SAO_MMU_VH0_ADDR, HEVC_SAO_MMU_VH1_ADDR*/
+#define VBH_BUF_SIZE_1080P 0x3000
+#define VBH_BUF_SIZE_4K 0x5000
+#define VBH_BUF_SIZE_8K 0xa000
+#define VBH_BUF_SIZE(bufspec) (bufspec->mmu_vbh.buf_size / 2)
+	/*mmu_vbh_dw buf is used by HEVC_SAO_MMU_VH0_ADDR2,HEVC_SAO_MMU_VH1_ADDR2,
+		HEVC_DW_VH0_ADDDR, HEVC_DW_VH1_ADDDR*/
+#define DW_VBH_BUF_SIZE_1080P (VBH_BUF_SIZE_1080P * 2)
+#define DW_VBH_BUF_SIZE_4K (VBH_BUF_SIZE_4K * 2)
+#define DW_VBH_BUF_SIZE_8K (VBH_BUF_SIZE_8K * 2)
+#define DW_VBH_BUF_SIZE(bufspec) (bufspec->mmu_vbh_dw.buf_size / 4)
+
+/* necessary 4K page size align for t7/t3 decoder and after */
+#define WORKBUF_ALIGN(addr) (ALIGN(addr, PAGE_SIZE))
+
+#define WORK_BUF_SPEC_NUM 6
+static struct BuffInfo_s amvavs2_workbuff_spec[WORK_BUF_SPEC_NUM] = {
+	{
+		/* 8M bytes */
+		.max_width = 1920,
+		.max_height = 1088,
+		.ipp = {
+			/* IPP work space calculation :
+			   4096 * (Y+CbCr+Flags) = 12k, round to 16k */
+			.buf_size = 0x4000,
+		},
+		.sao_abv = {
+			.buf_size = 0x30000,
+		},
+		.sao_vb = {
+			.buf_size = 0x30000,
+		},
+		.short_term_rps = {
+			/* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
+			   total 64x16x2 = 2048 bytes (0x800) */
+			.buf_size = 0x800,
+		},
+		.rcs = {
+			/* RCS STORE AREA - Max 32 RCS, each has 32 bytes,
+				total 0x0400 bytes */
+			.buf_size = 0x400,
+		},
+		.sps = {
+			/* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
+			total 0x0800 bytes*/
+			.buf_size = 0x800,
+		},
+		.pps = {
+			/*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes,
+			total 0x2000 bytes*/
+			.buf_size = 0x2000,
+		},
+		.sao_up = {
+			/* SAO UP STORE AREA - Max 640(10240/16) LCU,
+			   each has 16 bytes total 0x2800 bytes */
+			.buf_size = 0x2800,
+		},
+		.swap_buf = {
+			/* 256cyclex64bit = 2K bytes 0x800
+			   (only 144 cycles valid) */
+			.buf_size = 0x800,
+		},
+		.swap_buf2 = {
+			.buf_size = 0x800,
+		},
+		.scalelut = {
+			/* support up to 32 SCALELUT 1024x32 =
+			   32Kbytes (0x8000) */
+			.buf_size = 0x8000,
+		},
+		.dblk_para = {
+			/* DBLK -> Max 256(4096/16) LCU,
+			each para 1024bytes(total:0x40000),
+			data 1024bytes(total:0x40000)*/
+			.buf_size = 0x40000,
+		},
+		.dblk_data = {
+			.buf_size = 0x40000,
+		},
+		.dblk_data2 = {
+			.buf_size = 0x40000,
+		},
+#ifdef AVS2_10B_MMU
+		.mmu_vbh = {
+			.buf_size = 0x5000, /*2*16*(more than 2304)/4, 4K*/
+		},
+#if 0
+		.cm_header = {
+			/*add one for keeper.*/
+			.buf_size = MMU_COMPRESS_HEADER_SIZE *
+						(FRAME_BUFFERS + 1),
+			/* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */
+		},
+#endif
+#endif
+		.mpred_above = {
+			.buf_size = 0x8000, /* 2 * size of hevc*/
+		},
+#ifdef MV_USE_FIXED_BUF
+		.mpred_mv = {/* 1080p, 0x40000 per buffer */
+			.buf_size = 0x40000 * FRAME_BUFFERS,
+		},
+#endif
+		.rpm = {
+			.buf_size = RPM_BUF_SIZE,
+		},
+		.lmem = {
+			.buf_size = 0x400 * 2,
+		}
+	},
+	{
+		.max_width = 4096,
+		.max_height = 2304,
+		.ipp = {
+			/* IPP work space calculation :
+			   4096 * (Y+CbCr+Flags) = 12k, round to 16k */
+			.buf_size = 0x4000,
+		},
+		.sao_abv = {
+			.buf_size = 0x30000,
+		},
+		.sao_vb = {
+			.buf_size = 0x30000,
+		},
+		.short_term_rps = {
+			/* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
+			   total 64x16x2 = 2048 bytes (0x800) */
+			.buf_size = 0x800,
+		},
+		.rcs = {
+			/* RCS STORE AREA - Max 16 RCS, each has 32 bytes,
+			total 0x0400 bytes */
+			.buf_size = 0x400,
+		},
+		.sps = {
+			/* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
+			   total 0x0800 bytes */
+			.buf_size = 0x800,
+		},
+		.pps = {
+			/* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes,
+			   total 0x2000 bytes */
+			.buf_size = 0x2000,
+		},
+		.sao_up = {
+			/* SAO UP STORE AREA - Max 640(10240/16) LCU,
+			   each has 16 bytes total 0x2800 bytes */
+			.buf_size = 0x2800,
+		},
+		.swap_buf = {
+			/* 256cyclex64bit = 2K bytes 0x800
+			   (only 144 cycles valid) */
+			.buf_size = 0x800,
+		},
+		.swap_buf2 = {
+			.buf_size = 0x800,
+		},
+		.scalelut = {
+			/* support up to 32 SCALELUT 1024x32 = 32Kbytes
+			   (0x8000) */
+			.buf_size = 0x8000,
+		},
+		.dblk_para = {
+			/* DBLK -> Max 256(4096/16) LCU,
+			each para 1024bytes(total:0x40000),
+			data 1024bytes(total:0x40000)*/
+			.buf_size = 0x80000,
+		},
+		.dblk_data = {
+			/*DBLK -> Max 256(4096/16) LCU,
+			each para 1024bytes(total:0x40000),
+			data 1024bytes(total:0x40000)*/
+			.buf_size = 0x80000,
+		},
+		.dblk_data2 = {
+			.buf_size = 0x80000,
+		},
+#ifdef AVS2_10B_MMU
+		.mmu_vbh = {
+			.buf_size = 0x5000,/*2*16*(more than 2304)/4, 4K*/
+		},
+#if 0
+		.cm_header = {
+			/*add one for keeper.*/
+			.buf_size = MMU_COMPRESS_HEADER_SIZE *
+						(FRAME_BUFFERS + 1),
+			/* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */
+		},
+#endif
+#endif
+		.mpred_above = {
+			.buf_size = 0x10000, /* 2 * size of hevc*/
+		},
+#ifdef MV_USE_FIXED_BUF
+		.mpred_mv = {
+			/* .buf_size = 0x100000*16,
+			//4k2k , 0x100000 per buffer */
+			/* 4096x2304 , 0x120000 per buffer */
+			.buf_size = 0x120000 * FRAME_BUFFERS,
+		},
+#endif
+		.rpm = {
+			.buf_size = RPM_BUF_SIZE,
+		},
+		.lmem = {
+			.buf_size = 0x400 * 2,
+		}
+	},
+	{
+		.max_width = 4096 * 2,
+		.max_height = 2304 * 2,
+		.ipp = {
+		/*IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k,
+		round to 16k*/
+			.buf_size = 0x4000 * 2,
+		},
+		.sao_abv = {
+			.buf_size = 0x30000 * 2,
+		},
+		.sao_vb = {
+			.buf_size = 0x30000 * 2,
+		},
+		.short_term_rps = {
+		/*SHORT_TERM_RPS - Max 64 set, 16 entry every set,
+			total 64x16x2 = 2048 bytes (0x800)*/
+			.buf_size = 0x800,
+		},
+		.rcs = {
+		/*RCS STORE AREA - Max 16 RCS, each has 32 bytes,
+		total 0x0400 bytes*/
+			.buf_size = 0x400,
+		},
+		.sps = {
+		/*SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
+			total 0x0800 bytes*/
+			.buf_size = 0x800,
+		},
+		.pps = {
+		/*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total
+			0x2000 bytes*/
+			.buf_size = 0x2000,
+		},
+		.sao_up = {
+		/*SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes i
+				total 0x2800 bytes*/
+			.buf_size = 0x2800 * 2,
+		},
+		.swap_buf = {
+		/*256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid)*/
+			.buf_size = 0x800,
+		},
+		.swap_buf2 = {
+			.buf_size = 0x800,
+		},
+		.scalelut = {
+		/*support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000)*/
+			.buf_size = 0x8000 * 2,
+		},
+		.dblk_para  = {
+			.buf_size = 0x40000 * 2,
+		},
+		.dblk_data  = {
+			.buf_size = 0x80000 * 2,
+		},
+		.dblk_data2 = {
+			.buf_size = 0x80000 * 2,
+		},
+#ifdef AVS2_10B_MMU
+		.mmu_vbh = {
+		  .buf_size = 0x5000 * 2, /*2*16*2304/4, 4K*/
+		},
+#if 0
+		.cm_header = {
+			/*0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/
+			.buf_size = MMU_COMPRESS_8K_HEADER_SIZE * 17,
+		},
+#endif
+#endif
+		.mpred_above = {
+			.buf_size = 0x8000 * 2,
+		},
+#ifdef MV_USE_FIXED_BUF
+		.mpred_mv = {
+			/*4k2k , 0x100000 per buffer*/
+			.buf_size = 0x120000 * FRAME_BUFFERS * 4,
+		},
+#endif
+		.rpm = {
+			.buf_size = RPM_BUF_SIZE,
+		},
+		.lmem = {
+			.buf_size = 0x400 * 2,
+		}
+	},
+	{
+		/* 8M bytes */
+		.max_width = 1920,
+		.max_height = 1088,
+		.ipp = {
+			/* IPP work space calculation :
+			   4096 * (Y+CbCr+Flags) = 12k, round to 16k */
+			.buf_size = 0x1e00,
+		},
+		.sao_abv = {
+			.buf_size = 0,
+		},
+		.sao_vb = {
+			.buf_size = 0,
+		},
+		.short_term_rps = {
+			/* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
+			   total 64x16x2 = 2048 bytes (0x800) */
+			.buf_size = 0x800,
+		},
+		.rcs = {
+			/* RCS STORE AREA - Max 32 RCS, each has 32 bytes,
+				total 0x0400 bytes */
+			.buf_size = 0x400,
+		},
+		.sps = {
+			/* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
+			total 0x0800 bytes*/
+			.buf_size = 0x800,
+		},
+		.pps = {
+			/*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes,
+			total 0x2000 bytes*/
+			.buf_size = 0x2000,
+		},
+		.sao_up = {
+			/* SAO UP STORE AREA - Max 640(10240/16) LCU,
+			   each has 16 bytes total 0x2800 bytes */
+			.buf_size = 0,
+		},
+		.swap_buf = {
+			/* 256cyclex64bit = 2K bytes 0x800
+			   (only 144 cycles valid) */
+			.buf_size = 0x800,
+		},
+		.swap_buf2 = {
+			.buf_size = 0x800,
+		},
+		.scalelut = {
+			/* support up to 32 SCALELUT 1024x32 =
+			   32Kbytes (0x8000) */
+			.buf_size = 0,
+		},
+		.dblk_para = {
+			/* DBLK -> Max 256(4096/16) LCU,
+			each para 1024bytes(total:0x40000),
+			data 1024bytes(total:0x40000)*/
+			.buf_size = 0x3d00, //0x3c80,
+		},
+		.dblk_data = {
+			.buf_size = 0x62800,
+		},
+		.dblk_data2 = {
+			.buf_size = 0x62800,
+		},
+#ifdef AVS2_10B_MMU
+		.mmu_vbh = {
+			.buf_size = VBH_BUF_SIZE_1080P, /*2*16*(more than 2304)/4, 4K*/
+		},
+#if 0
+		.cm_header = {
+			/*add one for keeper.*/
+			.buf_size = MMU_COMPRESS_HEADER_SIZE *
+						(FRAME_BUFFERS + 1),
+			/* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */
+		},
+#endif
+#endif
+#ifdef AVS2_10B_MMU_DW
+		.mmu_vbh_dw = {
+			.buf_size = DW_VBH_BUF_SIZE_1080P, //2*16*2304/4, 4K
+		},
+#if 0
+		.cm_header_dw = {
+			.buf_size = MMU_COMPRESS_HEADER_SIZE_DW*17, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
+		},
+#endif
+#endif
+		.mpred_above = {
+			.buf_size = 0x1e00, /* 2 * size of hevc*/
+		},
+#ifdef MV_USE_FIXED_BUF
+		.mpred_mv = {/* 1080p, 0x40000 per buffer */
+			.buf_size = CO_MV_BUF_SIZE_1080P * FRAME_BUFFERS,
+		},
+#endif
+		.rpm = {
+			.buf_size = RPM_BUF_SIZE,
+		},
+		.lmem = {
+			.buf_size = 0x400 * 2,
+		}
+	},
+	{
+		.max_width = 4096,
+		.max_height = 2304,
+		.ipp = {
+			/* IPP work space calculation :
+			   4096 * (Y+CbCr+Flags) = 12k, round to 16k */
+			.buf_size = 0x4000,
+		},
+		.sao_abv = {
+			.buf_size = 0,
+		},
+		.sao_vb = {
+			.buf_size = 0,
+		},
+		.short_term_rps = {
+			/* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
+			   total 64x16x2 = 2048 bytes (0x800) */
+			.buf_size = 0x800,
+		},
+		.rcs = {
+			/* RCS STORE AREA - Max 16 RCS, each has 32 bytes,
+			total 0x0400 bytes */
+			.buf_size = 0x400,
+		},
+		.sps = {
+			/* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
+			   total 0x0800 bytes */
+			.buf_size = 0x800,
+		},
+		.pps = {
+			/* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes,
+			   total 0x2000 bytes */
+			.buf_size = 0x2000,
+		},
+		.sao_up = {
+			/* SAO UP STORE AREA - Max 640(10240/16) LCU,
+			   each has 16 bytes total 0x2800 bytes */
+			.buf_size = 0,
+		},
+		.swap_buf = {
+			/* 256cyclex64bit = 2K bytes 0x800
+			   (only 144 cycles valid) */
+			.buf_size = 0x800,
+		},
+		.swap_buf2 = {
+			.buf_size = 0x800,
+		},
+		.scalelut = {
+			/* support up to 32 SCALELUT 1024x32 = 32Kbytes
+			   (0x8000) */
+			.buf_size = 0,
+		},
+		.dblk_para = {
+			/* DBLK -> Max 256(4096/16) LCU,
+			each para 1024bytes(total:0x40000),
+			data 1024bytes(total:0x40000)*/
+			.buf_size = 0x8100, //0x8080,
+		},
+		.dblk_data = {
+			/*DBLK -> Max 256(4096/16) LCU,
+			each para 1024bytes(total:0x40000),
+			data 1024bytes(total:0x40000)*/
+			.buf_size = 0x88800,
+		},
+		.dblk_data2 = {
+			.buf_size = 0x88800,
+		},
+#ifdef AVS2_10B_MMU
+		.mmu_vbh = {
+			.buf_size = VBH_BUF_SIZE_4K,/*2*16*(more than 2304)/4, 4K*/
+		},
+#if 0
+		.cm_header = {
+			/*add one for keeper.*/
+			.buf_size = MMU_COMPRESS_HEADER_SIZE *
+						(FRAME_BUFFERS + 1),
+			/* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */
+		},
+#endif
+#endif
+#ifdef AVS2_10B_MMU_DW
+		.mmu_vbh_dw = {
+			.buf_size = DW_VBH_BUF_SIZE_4K, //2*16*2304/4, 4K
+		},
+#if 0
+		.cm_header_dw = {
+			.buf_size = MMU_COMPRESS_HEADER_SIZE_DW*17, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
+		},
+#endif
+#endif
+		.mpred_above = {
+			.buf_size = 0x4000, /* 2 * size of hevc*/
+		},
+#ifdef MV_USE_FIXED_BUF
+		.mpred_mv = {
+			/* .buf_size = 0x100000*16,
+			//4k2k , 0x100000 per buffer */
+			/* 4096x2304 , 0x120000 per buffer */
+			.buf_size = CO_MV_BUF_SIZE_4K * FRAME_BUFFERS,
+		},
+#endif
+		.rpm = {
+			.buf_size = RPM_BUF_SIZE,
+		},
+		.lmem = {
+			.buf_size = 0x400 * 2,
+		}
+	},
+	{
+		.max_width = 4096 * 2,
+		.max_height = 2304 * 2,
+		.ipp = {
+		/*IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k,
+		round to 16k*/
+			.buf_size = 0x4000 * 2,
+		},
+		.sao_abv = {
+			.buf_size = 0,
+		},
+		.sao_vb = {
+			.buf_size = 0,
+		},
+		.short_term_rps = {
+		/*SHORT_TERM_RPS - Max 64 set, 16 entry every set,
+			total 64x16x2 = 2048 bytes (0x800)*/
+			.buf_size = 0x800,
+		},
+		.rcs = {
+		/*RCS STORE AREA - Max 16 RCS, each has 32 bytes,
+		total 0x0400 bytes*/
+			.buf_size = 0x400,
+		},
+		.sps = {
+		/*SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
+			total 0x0800 bytes*/
+			.buf_size = 0x800,
+		},
+		.pps = {
+		/*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total
+			0x2000 bytes*/
+			.buf_size = 0x2000,
+		},
+		.sao_up = {
+		/*SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes i
+				total 0x2800 bytes*/
+			.buf_size = 0,
+		},
+		.swap_buf = {
+		/*256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid)*/
+			.buf_size = 0x800,
+		},
+		.swap_buf2 = {
+			.buf_size = 0x800,
+		},
+		.scalelut = {
+		/*support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000)*/
+			.buf_size = 0,
+		},
+		.dblk_para  = {
+			.buf_size = 0x10100, //0x10080,
+		},
+		.dblk_data  = {
+			.buf_size = 0x110800,
+		},
+		.dblk_data2 = {
+			.buf_size = 0x110800,
+		},
+#ifdef AVS2_10B_MMU
+		.mmu_vbh = {
+		  .buf_size = VBH_BUF_SIZE_8K, /*2*16*2304/4, 4K*/
+		},
+#if 0
+		.cm_header = {
+			/*0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/
+			.buf_size = MMU_COMPRESS_8K_HEADER_SIZE * 17,
+		},
+#endif
+#endif
+#ifdef AVS2_10B_MMU_DW
+		.mmu_vbh_dw = {
+			.buf_size = DW_VBH_BUF_SIZE_8K, //2*16*2304/4, 4K
+		},
+#if 0
+		.cm_header_dw = {
+			.buf_size = MMU_COMPRESS_HEADER_SIZE_DW*17, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
+		},
+#endif
+#endif
+		.mpred_above = {
+			.buf_size = 0x8000,
+		},
+#ifdef MV_USE_FIXED_BUF
+		.mpred_mv = {
+			/*4k2k , 0x100000 per buffer*/
+			.buf_size = CO_MV_BUF_SIZE_8K * FRAME_BUFFERS,
+		},
+#endif
+		.rpm = {
+			.buf_size = RPM_BUF_SIZE,
+		},
+		.lmem = {
+			.buf_size = 0x400 * 2,
+		}
+	}
+};
+
+#define IS_8K_SIZE(w, h)  (((w) * (h)) > MAX_SIZE_4K)
+#define IS_4K_SIZE(w, h)  (((w) * (h)) > (1920*1088))
+#ifndef MV_USE_FIXED_BUF
+static uint32_t get_mv_buf_size(struct AVS2Decoder_s *dec, int width, int height) {
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	uint32_t size;
+	if (mv_buf_dynamic_alloc == 1) {
+		int mv_mem_unit =
+			avs2_dec->lcu_size_log2 == 6 ? 0x200 : avs2_dec->lcu_size_log2 ==
+			5 ? 0x80 : 0x20;
+		int extended_pic_width = (width + avs2_dec->lcu_size -1)
+				& (~(avs2_dec->lcu_size - 1));
+		int extended_pic_height = (height + avs2_dec->lcu_size -1)
+				& (~(avs2_dec->lcu_size - 1));
+		int lcu_x_num = extended_pic_width / avs2_dec->lcu_size;
+		int lcu_y_num = extended_pic_height / avs2_dec->lcu_size;
+		int new_size =  lcu_x_num * lcu_y_num * mv_mem_unit;
+		size = (new_size + 0xffff) & (~0xffff);
+
+	} else {
+		if (IS_8K_SIZE(width, height))
+			size = CO_MV_BUF_SIZE_8K;
+		else if (IS_4K_SIZE(width, height))
+			size = CO_MV_BUF_SIZE_4K;
+		else
+			size = CO_MV_BUF_SIZE_1080P;
+	}
+	return size;
+}
+#endif
+
+/*Losless compression body buffer size 4K per 64x32 (jt)*/
+static int  compute_losless_comp_body_size(struct AVS2Decoder_s *dec,
+	int width, int height,
+	uint8_t is_bit_depth_10)
+{
+	int     width_x64;
+	int     height_x32;
+	int     bsize;
+	width_x64 = width + 63;
+	width_x64 >>= 6;
+	height_x32 = height + 31;
+	height_x32 >>= 5;
+#ifdef AVS2_10B_MMU
+	 bsize = (is_bit_depth_10 ? 4096 : 3200)
+		* width_x64 * height_x32;
+#else
+	 bsize = (is_bit_depth_10 ? 4096 : 3072)
+		* width_x64 * height_x32;
+#endif
+	avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+		"%s(%d,%d,%d)=>%d\n",
+		__func__, width, height,
+		is_bit_depth_10, bsize);
+
+	return  bsize;
+}
+
+/* Losless compression header buffer size 32bytes per 128x64 (jt)*/
+static  int  compute_losless_comp_header_size(struct AVS2Decoder_s *dec,
+	int width, int height)
+{
+	int     width_x128;
+	int     height_x64;
+	int     hsize;
+	width_x128 = width + 127;
+	width_x128 >>= 7;
+	height_x64 = height + 63;
+	height_x64 >>= 6;
+
+	hsize = 32 * width_x128 * height_x64;
+	avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+		"%s(%d,%d)=>%d\n",
+		__func__, width, height,
+		hsize);
+
+	return  hsize;
+}
+
+static void init_buff_spec(struct AVS2Decoder_s *dec,
+	struct BuffInfo_s *buf_spec)
+{
+	void *mem_start_virt;
+	buf_spec->ipp.buf_start =
+		WORKBUF_ALIGN(buf_spec->start_adr);
+	buf_spec->sao_abv.buf_start =
+		WORKBUF_ALIGN(buf_spec->ipp.buf_start + buf_spec->ipp.buf_size);
+	buf_spec->sao_vb.buf_start =
+		WORKBUF_ALIGN(buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size);
+	buf_spec->short_term_rps.buf_start =
+		WORKBUF_ALIGN(buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size);
+	buf_spec->rcs.buf_start =
+		WORKBUF_ALIGN(buf_spec->short_term_rps.buf_start + buf_spec->short_term_rps.buf_size);
+	buf_spec->sps.buf_start =
+		WORKBUF_ALIGN(buf_spec->rcs.buf_start + buf_spec->rcs.buf_size);
+	buf_spec->pps.buf_start =
+		WORKBUF_ALIGN(buf_spec->sps.buf_start + buf_spec->sps.buf_size);
+	buf_spec->sao_up.buf_start =
+		WORKBUF_ALIGN(buf_spec->pps.buf_start + buf_spec->pps.buf_size);
+	buf_spec->swap_buf.buf_start =
+		WORKBUF_ALIGN(buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size);
+	buf_spec->swap_buf2.buf_start =
+		WORKBUF_ALIGN(buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size);
+	buf_spec->scalelut.buf_start =
+		WORKBUF_ALIGN(buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size);
+	buf_spec->dblk_para.buf_start =
+		WORKBUF_ALIGN(buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size);
+	buf_spec->dblk_data.buf_start =
+		WORKBUF_ALIGN(buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size);
+	buf_spec->dblk_data2.buf_start =
+		WORKBUF_ALIGN(buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size);
+#ifdef AVS2_10B_MMU
+	buf_spec->mmu_vbh.buf_start  =
+		WORKBUF_ALIGN(buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size);
+	#ifdef AVS2_10B_MMU_DW
+	buf_spec->mmu_vbh_dw.buf_start =
+		WORKBUF_ALIGN(buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size);
+	buf_spec->mpred_above.buf_start =
+		WORKBUF_ALIGN(buf_spec->mmu_vbh_dw.buf_start + buf_spec->mmu_vbh_dw.buf_size);
+	#else
+	buf_spec->mpred_above.buf_start =
+		WORKBUF_ALIGN(buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size);
+	#endif
+#else /* AVS2_10B_MMU */
+	#ifdef AVS2_10B_MMU_DW
+	buf_spec->mmu_vbh_dw.buf_start =
+		WORKBUF_ALIGN(buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size);
+	buf_spec->mpred_above.buf_start =
+		WORKBUF_ALIGN(buf_spec->mmu_vbh_dw.buf_start + buf_spec->mmu_vbh_dw.buf_size);
+	#else
+	buf_spec->mpred_above.buf_start =
+		WORKBUF_ALIGN(buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size);
+	#endif
+#endif /* AVS2_10B_MMU */
+#ifdef MV_USE_FIXED_BUF
+	buf_spec->mpred_mv.buf_start =
+		WORKBUF_ALIGN(buf_spec->mpred_above.buf_start + buf_spec->mpred_above.buf_size);
+	buf_spec->rpm.buf_start =
+		WORKBUF_ALIGN(buf_spec->mpred_mv.buf_start + buf_spec->mpred_mv.buf_size);
+#else
+	buf_spec->rpm.buf_start =
+		WORKBUF_ALIGN(buf_spec->mpred_above.buf_start + buf_spec->mpred_above.buf_size);
+#endif
+	buf_spec->lmem.buf_start =
+		WORKBUF_ALIGN(buf_spec->rpm.buf_start + buf_spec->rpm.buf_size);
+	buf_spec->end_adr =
+		WORKBUF_ALIGN(buf_spec->lmem.buf_start + buf_spec->lmem.buf_size);
+
+	if (dec) {
+		mem_start_virt =
+			codec_mm_phys_to_virt(buf_spec->dblk_para.buf_start);
+		if (mem_start_virt) {
+			memset(mem_start_virt, 0, buf_spec->dblk_para.buf_size);
+			codec_mm_dma_flush(mem_start_virt,
+				buf_spec->dblk_para.buf_size,
+				DMA_TO_DEVICE);
+		} else {
+			/*not virt for tvp playing,
+			may need clear on ucode.*/
+			pr_err("mem_start_virt failed\n");
+		}
+		if (debug) {
+			pr_info("%s workspace (%x %x) size = %x\n", __func__,
+				   buf_spec->start_adr, buf_spec->end_adr,
+				   buf_spec->end_adr - buf_spec->start_adr);
+		}
+		if (debug) {
+			pr_info("ipp.buf_start             :%x\n",
+				   buf_spec->ipp.buf_start);
+			pr_info("sao_abv.buf_start          :%x\n",
+				   buf_spec->sao_abv.buf_start);
+			pr_info("sao_vb.buf_start          :%x\n",
+				   buf_spec->sao_vb.buf_start);
+			pr_info("short_term_rps.buf_start  :%x\n",
+				   buf_spec->short_term_rps.buf_start);
+			pr_info("rcs.buf_start             :%x\n",
+				   buf_spec->rcs.buf_start);
+			pr_info("sps.buf_start             :%x\n",
+				   buf_spec->sps.buf_start);
+			pr_info("pps.buf_start             :%x\n",
+				   buf_spec->pps.buf_start);
+			pr_info("sao_up.buf_start          :%x\n",
+				   buf_spec->sao_up.buf_start);
+			pr_info("swap_buf.buf_start        :%x\n",
+				   buf_spec->swap_buf.buf_start);
+			pr_info("swap_buf2.buf_start       :%x\n",
+				   buf_spec->swap_buf2.buf_start);
+			pr_info("scalelut.buf_start        :%x\n",
+				   buf_spec->scalelut.buf_start);
+			pr_info("dblk_para.buf_start       :%x\n",
+				   buf_spec->dblk_para.buf_start);
+			pr_info("dblk_data.buf_start       :%x\n",
+				   buf_spec->dblk_data.buf_start);
+			pr_info("dblk_data2.buf_start       :%x\n",
+				   buf_spec->dblk_data2.buf_start);
+	#ifdef AVS2_10B_MMU
+			pr_info("mmu_vbh.buf_start     :%x\n",
+				buf_spec->mmu_vbh.buf_start);
+	#endif
+	#ifdef AVS2_10B_MMU_DW
+			pr_info("mmu_vbh_dw.buf_start     :%x\n",
+				buf_spec->mmu_vbh_dw.buf_start);
+	#endif
+			pr_info("mpred_above.buf_start     :%x\n",
+				   buf_spec->mpred_above.buf_start);
+#ifdef MV_USE_FIXED_BUF
+			pr_info("mpred_mv.buf_start        :%x\n",
+				   buf_spec->mpred_mv.buf_start);
+#endif
+			if ((debug & AVS2_DBG_SEND_PARAM_WITH_REG) == 0) {
+				pr_info("rpm.buf_start             :%x\n",
+					   buf_spec->rpm.buf_start);
+			}
+		}
+	}
+
+}
+
+static void uninit_mmu_buffers(struct AVS2Decoder_s *dec)
+{
+#ifdef AVS2_10B_MMU_DW
+	if (dec->dw_mmu_enable && dec->dw_mmu_box) {
+		decoder_mmu_box_free(dec->dw_mmu_box);
+		dec->dw_mmu_box = NULL;
+	}
+#endif
+	decoder_mmu_box_free(dec->mmu_box);
+	dec->mmu_box = NULL;
+
+	if (dec->bmmu_box)
+		decoder_bmmu_box_free(dec->bmmu_box);
+	dec->bmmu_box = NULL;
+}
+
+#ifndef AVS2_10B_MMU
+static void init_buf_list(struct AVS2Decoder_s *dec)
+{
+	int i;
+	int buf_size;
+	int mc_buffer_end = dec->mc_buf->buf_start + dec->mc_buf->buf_size;
+	dec->used_buf_num = max_buf_num;
+
+	if (dec->used_buf_num > MAX_BUF_NUM)
+		dec->used_buf_num = MAX_BUF_NUM;
+	if (buf_alloc_size > 0) {
+		buf_size = buf_alloc_size;
+		avs2_print(dec, AVS2_DBG_BUFMGR,
+			"[Buffer Management] init_buf_list:\n");
+	} else {
+		int pic_width = dec->init_pic_w;
+		int pic_height = dec->init_pic_h;
+
+	/*SUPPORT_10BIT*/
+	int losless_comp_header_size = compute_losless_comp_header_size
+			(dec, pic_width, pic_height);
+	int losless_comp_body_size = compute_losless_comp_body_size
+			(dec, pic_width, pic_height, buf_alloc_depth == 10);
+	int mc_buffer_size = losless_comp_header_size
+		+ losless_comp_body_size;
+	int mc_buffer_size_h = (mc_buffer_size + 0xffff)>>16;
+
+	int dw_mode = get_double_write_mode_init(dec);
+
+	if (dw_mode) {
+		int pic_width_dw = pic_width /
+			get_double_write_ratio(dw_mode);
+		int pic_height_dw = pic_height /
+			get_double_write_ratio(dw_mode);
+		int lcu_size = 64; /*fixed 64*/
+		int pic_width_64 = (pic_width_dw + 63) & (~0x3f);
+		int pic_height_32 = (pic_height_dw + 31) & (~0x1f);
+		int pic_width_lcu  =
+			(pic_width_64 % lcu_size) ? pic_width_64 / lcu_size
+			+ 1 : pic_width_64 / lcu_size;
+		int pic_height_lcu =
+			(pic_height_32 % lcu_size) ? pic_height_32 / lcu_size
+			+ 1 : pic_height_32 / lcu_size;
+		int lcu_total       = pic_width_lcu * pic_height_lcu;
+		int mc_buffer_size_u_v = lcu_total * lcu_size * lcu_size / 2;
+		int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16;
+			/*64k alignment*/
+		buf_size = ((mc_buffer_size_u_v_h << 16) * 3);
+	} else
+		buf_size = 0;
+
+	if (mc_buffer_size & 0xffff) { /*64k alignment*/
+		mc_buffer_size_h += 1;
+	}
+	if ((dw_mode & 0x10) == 0)
+		buf_size += (mc_buffer_size_h << 16);
+		avs2_print(dec, AVS2_DBG_BUFMGR,
+			"init_buf_list num %d (width %d height %d):\n",
+			 dec->used_buf_num, pic_width, pic_height);
+	}
+
+	for (i = 0; i < dec->used_buf_num; i++) {
+		if (((i + 1) * buf_size) > dec->mc_buf->buf_size)
+			dec->use_cma_flag = 1;
+
+		dec->m_BUF[i].alloc_flag = 0;
+		dec->m_BUF[i].index = i;
+
+		dec->use_cma_flag = 1;
+		if (dec->use_cma_flag) {
+			dec->m_BUF[i].cma_page_count =
+					PAGE_ALIGN(buf_size) / PAGE_SIZE;
+			if (decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box,
+					VF_BUFFER_IDX(i), buf_size, DRIVER_NAME,
+					&dec->m_BUF[i].alloc_addr) < 0) {
+				dec->m_BUF[i].cma_page_count = 0;
+				if (i <= 5) {
+					dec->fatal_error |=
+					DECODER_FATAL_ERROR_NO_MEM;
+				}
+				break;
+			}
+			dec->m_BUF[i].start_adr =  dec->m_BUF[i].alloc_addr;
+		} else {
+			dec->m_BUF[i].cma_page_count = 0;
+			dec->m_BUF[i].alloc_addr = 0;
+			dec->m_BUF[i].start_adr =
+				dec->mc_buf->buf_start + i * buf_size;
+		}
+		dec->m_BUF[i].size = buf_size;
+		dec->m_BUF[i].free_start_adr = dec->m_BUF[i].start_adr;
+
+		if (((dec->m_BUF[i].start_adr + buf_size) > mc_buffer_end)
+			&& (dec->m_BUF[i].alloc_addr == 0)) {
+			if (debug) {
+				avs2_print(dec, 0,
+				"Max mc buffer or mpred_mv buffer is used\n");
+			}
+			break;
+		}
+
+		avs2_print(dec, AVS2_DBG_BUFMGR,
+			"Buffer %d: start_adr %p size %x\n", i,
+			   (void *)dec->m_BUF[i].start_adr,
+			   dec->m_BUF[i].size);
+	}
+	dec->buf_num = i;
+}
+#endif
+
+static int config_pic(struct AVS2Decoder_s *dec,
+				struct avs2_frame_s *pic, int32_t lcu_size_log2)
+{
+	int ret = -1;
+	int i;
+	int pic_width = dec->init_pic_w;
+	int pic_height = dec->init_pic_h;
+	/*struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	int32_t lcu_size_log2 = avs2_dec->lcu_size_log2;*/
+	int32_t lcu_size = 1 << lcu_size_log2;
+	int pic_width_64 = (pic_width + 63) & (~0x3f);
+	int pic_height_32 = (pic_height + 31) & (~0x1f);
+	int pic_width_lcu  = (pic_width_64 % lcu_size) ?
+				pic_width_64 / lcu_size  + 1
+				: pic_width_64 / lcu_size;
+	int pic_height_lcu = (pic_height_32 % lcu_size) ?
+				pic_height_32 / lcu_size + 1
+				: pic_height_32 / lcu_size;
+	int lcu_total       = pic_width_lcu * pic_height_lcu;
+
+	u32 y_adr = 0;
+	int buf_size = 0;
+
+	int losless_comp_header_size =
+			compute_losless_comp_header_size(
+			dec, pic_width, pic_height);
+	int losless_comp_body_size = compute_losless_comp_body_size(
+			dec, pic_width,
+			pic_height, buf_alloc_depth == 10);
+	int mc_buffer_size = losless_comp_header_size + losless_comp_body_size;
+	int mc_buffer_size_h = (mc_buffer_size + 0xffff) >> 16;
+	int mc_buffer_size_u_v = 0;
+	int mc_buffer_size_u_v_h = 0;
+	int dw_mode = get_double_write_mode_init(dec);
+
+	if (dw_mode && ((dw_mode & 0x20) == 0)) {
+		int pic_width_dw = pic_width /
+			get_double_write_ratio(dw_mode);
+		int pic_height_dw = pic_height /
+			get_double_write_ratio(dw_mode);
+		int pic_width_64_dw = (pic_width_dw + 63) & (~0x3f);
+		int pic_height_32_dw = (pic_height_dw + 31) & (~0x1f);
+		int pic_width_lcu_dw  = (pic_width_64_dw % lcu_size) ?
+					pic_width_64_dw / lcu_size  + 1
+					: pic_width_64_dw / lcu_size;
+		int pic_height_lcu_dw = (pic_height_32_dw % lcu_size) ?
+					pic_height_32_dw / lcu_size + 1
+					: pic_height_32_dw / lcu_size;
+		int lcu_total_dw       = pic_width_lcu_dw * pic_height_lcu_dw;
+
+		mc_buffer_size_u_v = lcu_total_dw * lcu_size * lcu_size / 2;
+		mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16;
+		/*64k alignment*/
+		buf_size = ((mc_buffer_size_u_v_h << 16) * 3);
+		buf_size = ((buf_size + 0xffff) >> 16) << 16;
+	}
+	if (mc_buffer_size & 0xffff) /*64k alignment*/
+		mc_buffer_size_h += 1;
+
+
+#ifdef AVS2_10B_MMU
+	if (dec->mmu_enable) {
+		pic->header_adr = decoder_bmmu_box_get_phy_addr(
+				dec->bmmu_box, HEADER_BUFFER_IDX(pic->index));
+
+#ifdef AVS2_10B_MMU_DW
+		if (dec->dw_mmu_enable) {
+			pic->dw_header_adr = pic->header_adr
+				+ get_compress_header_size(dec);
+		}
+#endif
+		avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+			"buf_size %d, MMU header_adr %d: %ld\n",
+			buf_size, pic->index, pic->header_adr);
+	}
+#else
+	if ((dw_mode & 0x10) == 0)
+		buf_size += (mc_buffer_size_h << 16);
+#endif
+
+	i = pic->index;
+
+#ifndef AVS2_10B_MMU
+	if (debug) {
+		pr_err("start %x  .size=%d\n",
+			dec->mc_buf_spec.buf_start + i * buf_size, buf_size);
+	}
+	for (i = 0; i < dec->buf_num; i++) {
+		y_adr = ((dec->m_BUF[i].free_start_adr
+			+ 0xffff) >> 16) << 16;
+		/*64k alignment*/
+		if ((y_adr+buf_size) <=	(dec->m_BUF[i].start_adr+
+			dec->m_BUF[i].size)) {
+			dec->m_BUF[i].free_start_adr =
+				y_adr + buf_size;
+			break;
+		}
+	}
+	if (i < dec->buf_num)
+#else
+	/*if ((dec->mc_buf->buf_start + (i + 1) * buf_size) <
+		dec->mc_buf->buf_end)
+		y_adr = dec->mc_buf->buf_start + i * buf_size;
+	else {*/
+	if (buf_size > 0 && pic->cma_alloc_addr == 0) {
+		ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box,
+				VF_BUFFER_IDX(i),
+				buf_size, DRIVER_NAME,
+				&pic->cma_alloc_addr);
+		if (ret < 0) {
+			avs2_print(dec, 0,
+				"decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n",
+				VF_BUFFER_IDX(i),
+				buf_size
+				);
+			return ret;
+		}
+
+		if (pic->cma_alloc_addr)
+			y_adr = pic->cma_alloc_addr;
+		else {
+			avs2_print(dec, 0,
+				"decoder_bmmu_box_alloc_buf_phy idx %d size %d return null\n",
+				VF_BUFFER_IDX(i),
+				buf_size
+				);
+			return -1;
+		}
+	}
+#endif
+	{
+		/*ensure get_pic_by_POC()
+		not get the buffer not decoded*/
+		pic->BUF_index = i;
+		pic->lcu_total = lcu_total;
+
+		pic->comp_body_size = losless_comp_body_size;
+		pic->buf_size = buf_size;
+		pic->mc_canvas_y = pic->index;
+		pic->mc_canvas_u_v = pic->index;
+#ifndef AVS2_10B_MMU
+		pic->mc_y_adr = y_adr;
+		if (dw_mode & 0x10) {
+			pic->mc_u_v_adr = y_adr +
+			((mc_buffer_size_u_v_h << 16) << 1);
+
+			pic->mc_canvas_y =
+				(pic->index << 1);
+			pic->mc_canvas_u_v =
+				(pic->index << 1) + 1;
+
+			pic->dw_y_adr = y_adr;
+			pic->dw_u_v_adr = pic->mc_u_v_adr;
+		} else
+#endif
+		if (dw_mode) {
+#ifdef AVS2_10B_MMU
+			pic->dw_y_adr = y_adr;
+			pic->dw_u_v_adr = pic->dw_y_adr +
+				((mc_buffer_size_u_v_h << 16) << 1);
+			pic->mc_y_adr = pic->dw_y_adr;
+			pic->mc_u_v_adr = pic->dw_u_v_adr;
+#else
+			pic->dw_y_adr = y_adr + (mc_buffer_size_h << 16);
+			pic->dw_u_v_adr = pic->dw_y_adr +
+				((mc_buffer_size_u_v_h << 16) << 1);
+#endif
+		}
+#ifdef MV_USE_FIXED_BUF
+		pic->mpred_mv_wr_start_addr =
+			dec->work_space_buf->mpred_mv.buf_start +
+			pic->index * (dec->work_space_buf->mpred_mv.buf_size / FRAME_BUFFERS);
+		if (pic->mpred_mv_wr_start_addr >
+			(dec->work_space_buf->mpred_mv.buf_start
+			+ dec->work_space_buf->mpred_mv.buf_size)) {
+			avs2_print(dec, 0, "err: fixed mv buf out of size, 0x0%x\n",
+				pic->mpred_mv_wr_start_addr);
+			pic->mpred_mv_wr_start_addr =
+				dec->work_space_buf->mpred_mv.buf_start;
+		}
+#endif
+		if (debug) {
+			avs2_print(dec, AVS2_DBG_BUFMGR,
+			"%s index %d BUF_index %d mc_y_adr %x ",
+			__func__, pic->index,
+			pic->BUF_index,
+			pic->mc_y_adr);
+			avs2_print_cont(dec, AVS2_DBG_BUFMGR,
+			"comp_body_size %x comp_buf_size %x ",
+			pic->comp_body_size,
+			pic->buf_size);
+			avs2_print_cont(dec, AVS2_DBG_BUFMGR,
+			"mpred_mv_wr_start_adr %d\n",
+			pic->mpred_mv_wr_start_addr);
+			avs2_print_cont(dec, AVS2_DBG_BUFMGR,
+				"dw_y_adr %d, pic->dw_u_v_adr =%d\n",
+				pic->dw_y_adr,
+				pic->dw_u_v_adr);
+		}
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static void init_pic_list(struct AVS2Decoder_s *dec,
+	int32_t lcu_size_log2)
+{
+	int i;
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	struct avs2_frame_s *pic;
+#ifdef AVS2_10B_MMU
+	if (dec->mmu_enable) {
+		for (i = 0; i < dec->used_buf_num; i++) {
+			unsigned long buf_addr;
+			u32 header_size = get_compress_header_size(dec);
+#ifdef AVS2_10B_MMU_DW
+			if (dec->dw_mmu_enable)
+				header_size <<= 1;
+#endif
+			if (decoder_bmmu_box_alloc_buf_phy
+					(dec->bmmu_box,
+					HEADER_BUFFER_IDX(i), header_size,
+					DRIVER_HEADER_NAME,
+					&buf_addr) < 0){
+				avs2_print(dec, 0,
+					"%s malloc compress header failed %d\n",
+					DRIVER_HEADER_NAME, i);
+				dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM;
+				return;
+			}
+		}
+	}
+#endif
+	dec->frame_height = avs2_dec->img.height;
+	dec->frame_width = avs2_dec->img.width;
+
+	for (i = 0; i < dec->used_buf_num; i++) {
+		if (i == (dec->used_buf_num - 1))
+			pic = avs2_dec->m_bg;
+		else
+			pic = avs2_dec->fref[i];
+		pic->index = i;
+		pic->BUF_index = -1;
+		pic->mv_buf_index = -1;
+		if (config_pic(dec, pic, lcu_size_log2) < 0) {
+			if (debug)
+				avs2_print(dec, 0,
+					"Config_pic %d fail\n",
+					pic->index);
+			pic->index = -1;
+			break;
+		}
+		pic->pic_w = avs2_dec->img.width;
+		pic->pic_h = avs2_dec->img.height;
+	}
+	for (; i < dec->used_buf_num; i++) {
+		if (i == (dec->used_buf_num - 1))
+			pic = avs2_dec->m_bg;
+		else
+			pic = avs2_dec->fref[i];
+		pic->index = -1;
+		pic->BUF_index = -1;
+		pic->mv_buf_index = -1;
+	}
+	avs2_print(dec, AVS2_DBG_BUFMGR,
+		"%s ok, used_buf_num = %d\n",
+		__func__, dec->used_buf_num);
+	dec->pic_list_init_flag = 1;
+}
+
+
+static void init_pic_list_hw(struct AVS2Decoder_s *dec)
+{
+	int i;
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	struct avs2_frame_s *pic;
+	/*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x0);*/
+#if 0
+	WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
+		(0x1 << 1) | (0x1 << 2));
+
+#ifdef DUAL_CORE_64
+	WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
+		(0x1 << 1) | (0x1 << 2));
+#endif
+#endif
+	for (i = 0; i < dec->used_buf_num; i++) {
+		if (i == (dec->used_buf_num - 1))
+			pic = avs2_dec->m_bg;
+		else
+			pic = avs2_dec->fref[i];
+		if (pic->index < 0)
+			break;
+#ifdef AVS2_10B_MMU
+	/*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
+		pic->header_adr
+		| (pic->mc_canvas_y << 8)|0x1);*/
+		WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
+			(0x1 << 1) | (pic->index << 8));
+
+#ifdef DUAL_CORE_64
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXLX2)
+		WRITE_VREG(HEVC2_MPP_ANC2AXI_TBL_CONF_ADDR,
+			(0x1 << 1) | (pic->index << 8));
+	else
+		WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
+			(0x1 << 1) | (pic->index << 8));
+#endif
+	WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->header_adr >> 5);
+#else
+	/*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
+		pic->mc_y_adr
+		| (pic->mc_canvas_y << 8) | 0x1);*/
+	WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->mc_y_adr >> 5);
+#endif
+#ifndef LOSLESS_COMPRESS_MODE
+	/*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
+		pic->mc_u_v_adr
+		| (pic->mc_canvas_u_v << 8)| 0x1);*/
+	WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->mc_u_v_adr >> 5);
+#endif
+#ifdef DUAL_CORE_64
+#ifdef AVS2_10B_MMU
+	WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA,
+		pic->header_adr >> 5);
+#else
+	WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA,
+		pic->mc_y_adr >> 5);
+#endif
+#ifndef LOSLESS_COMPRESS_MODE
+	WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA,
+		pic->mc_u_v_adr >> 5);
+#endif
+/*DUAL_CORE_64*/
+#endif
+	}
+	WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1);
+#ifdef DUAL_CORE_64
+	WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
+		0x1);
+#endif
+	/*Zero out canvas registers in IPP -- avoid simulation X*/
+	WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			(0 << 8) | (0 << 1) | 1);
+	for (i = 0; i < 32; i++) {
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
+#ifdef DUAL_CORE_64
+		WRITE_VREG(HEVC2_HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
+#endif
+	}
+}
+
+
+static void dump_pic_list(struct AVS2Decoder_s *dec)
+{
+	int ii;
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) {
+		avs2_print(dec, 0,
+		"fref[%d]: index %d decode_id %d mvbuf %d imgcoi_ref %d imgtr_fwRefDistance %d refered %d, pre %d is_out %d, bg %d, vf_ref %d error %d lcu %d ref_pos(%d,%d,%d,%d,%d,%d,%d)\n",
+		ii, avs2_dec->fref[ii]->index,
+		avs2_dec->fref[ii]->decode_idx,
+		avs2_dec->fref[ii]->mv_buf_index,
+		avs2_dec->fref[ii]->imgcoi_ref,
+		avs2_dec->fref[ii]->imgtr_fwRefDistance,
+		avs2_dec->fref[ii]->refered_by_others,
+		avs2_dec->fref[ii]->to_prepare_disp,
+		avs2_dec->fref[ii]->is_output,
+		avs2_dec->fref[ii]->bg_flag,
+		avs2_dec->fref[ii]->vf_ref,
+		avs2_dec->fref[ii]->error_mark,
+		avs2_dec->fref[ii]->decoded_lcu,
+		avs2_dec->fref[ii]->ref_poc[0],
+		avs2_dec->fref[ii]->ref_poc[1],
+		avs2_dec->fref[ii]->ref_poc[2],
+		avs2_dec->fref[ii]->ref_poc[3],
+		avs2_dec->fref[ii]->ref_poc[4],
+		avs2_dec->fref[ii]->ref_poc[5],
+		avs2_dec->fref[ii]->ref_poc[6]
+		);
+	}
+	return;
+}
+
+static int config_mc_buffer(struct AVS2Decoder_s *dec)
+{
+	int32_t i;
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	struct avs2_frame_s *pic;
+	struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic;
+
+	/*if (avs2_dec->img.type == I_IMG)
+	return 0;
+	*/
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"Entered config_mc_buffer....\n");
+	if (avs2_dec->f_bg != NULL) {
+		avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+			"config_mc_buffer for background (canvas_y %d, canvas_u_v %d)\n",
+		avs2_dec->f_bg->mc_canvas_y, avs2_dec->f_bg->mc_canvas_u_v);
+		/*WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			(7 << 8) | (0<<1) | 1);    L0:BG */
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			(15 << 8) | (0<<1) | 1);   /* L0:BG*/
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+			(avs2_dec->f_bg->mc_canvas_u_v << 16) |
+			(avs2_dec->f_bg->mc_canvas_u_v << 8) |
+			avs2_dec->f_bg->mc_canvas_y);
+		/*WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			(23 << 8) | (0<<1) | 1);   L1:BG*/
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			(31 << 8) | (0<<1) | 1);  /* L1:BG*/
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+			(avs2_dec->f_bg->mc_canvas_u_v << 16) |
+			(avs2_dec->f_bg->mc_canvas_u_v << 8) |
+			avs2_dec->f_bg->mc_canvas_y);
+	}
+
+	if (avs2_dec->img.type == I_IMG)
+		return 0;
+
+	if (avs2_dec->img.type == P_IMG) {
+		avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+			"config_mc_buffer for P_IMG, img type %d\n",
+			avs2_dec->img.type);
+		/*refer to prepare_RefInfo()*/
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			(0 << 8) | (0<<1) | 1);
+		for (i = 0; i < avs2_dec->img.num_of_references; i++) {
+			pic = avs2_dec->fref[i];
+			WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+			(pic->mc_canvas_u_v << 16) |
+			(pic->mc_canvas_u_v << 8) |
+			pic->mc_canvas_y);
+
+			if (pic->error_mark)
+				cur_pic->error_mark = 1;
+
+			avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+				"refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n",
+				i, pic->mc_canvas_u_v, pic->mc_canvas_y,
+				pic->error_mark);
+		}
+	} else if (avs2_dec->img.type == F_IMG) {
+		avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+			"config_mc_buffer for F_IMG, img type %d\n",
+			avs2_dec->img.type);
+		/*refer to prepare_RefInfo()*/
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			(0 << 8) | (0<<1) | 1);
+		for (i = 0; i < avs2_dec->img.num_of_references; i++) {
+			pic = avs2_dec->fref[i];
+			WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+				(pic->mc_canvas_u_v << 16) |
+				(pic->mc_canvas_u_v << 8) |
+				pic->mc_canvas_y);
+
+			if (pic->error_mark)
+				cur_pic->error_mark = 1;
+
+			avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+				"refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n",
+				i, pic->mc_canvas_u_v, pic->mc_canvas_y,
+				pic->error_mark);
+		}
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			(16 << 8) | (0<<1) | 1);
+		for (i = 0; i < avs2_dec->img.num_of_references; i++) {
+			pic = avs2_dec->fref[i];
+			WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+				(pic->mc_canvas_u_v << 16) |
+				(pic->mc_canvas_u_v << 8) |
+				pic->mc_canvas_y);
+			avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+				"refid %x mc_canvas_u_v %x mc_canvas_y %x\n",
+				i, pic->mc_canvas_u_v, pic->mc_canvas_y);
+		}
+	} else {
+		avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+			"config_mc_buffer for B_IMG\n");
+		/*refer to prepare_RefInfo()*/
+		pic = avs2_dec->fref[1];
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			(0 << 8) | (0<<1) | 1);
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+			(pic->mc_canvas_u_v << 16) |
+			(pic->mc_canvas_u_v << 8) |
+			pic->mc_canvas_y);
+
+		if (pic->error_mark)
+			cur_pic->error_mark = 1;
+
+		avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+			"refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n",
+			1, pic->mc_canvas_u_v, pic->mc_canvas_y,
+			pic->error_mark);
+
+		pic = avs2_dec->fref[0];
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			(16 << 8) | (0<<1) | 1);
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+			(pic->mc_canvas_u_v<<16) |
+			(pic->mc_canvas_u_v<<8) |
+			pic->mc_canvas_y);
+
+		if (pic->error_mark)
+			cur_pic->error_mark = 1;
+
+		avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+			"refid %x mc_canvas_u_v %x mc_canvas_y %x error_mark %x\n",
+			0, pic->mc_canvas_u_v, pic->mc_canvas_y,
+			pic->error_mark);
+	}
+	return 0;
+}
+#if 0
+static void mcrcc_get_hitrate(void)
+{
+	u32 tmp;
+	u32 raw_mcr_cnt;
+	u32 hit_mcr_cnt;
+	u32 byp_mcr_cnt_nchoutwin;
+	u32 byp_mcr_cnt_nchcanv;
+	int hitrate;
+
+	if (debug & AVS2_DBG_CACHE)
+		pr_info("[cache_util.c] Entered mcrcc_get_hitrate...\n");
+	WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x0<<1));
+	raw_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
+	WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x1<<1));
+	hit_mcr_cnt = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
+	WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x2<<1));
+	byp_mcr_cnt_nchoutwin = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
+	WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x3<<1));
+	byp_mcr_cnt_nchcanv = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
+
+	if (debug & AVS2_DBG_CACHE) {
+		pr_info("raw_mcr_cnt_total: %d\n",raw_mcr_cnt);
+		pr_info("hit_mcr_cnt_total: %d\n",hit_mcr_cnt);
+		pr_info("byp_mcr_cnt_nchoutwin_total: %d\n",byp_mcr_cnt_nchoutwin);
+		pr_info("byp_mcr_cnt_nchcanv_total: %d\n",byp_mcr_cnt_nchcanv);
+	}
+	WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x4<<1));
+	tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
+	if (debug & AVS2_DBG_CACHE)
+		pr_info("miss_mcr_0_cnt_total: %d\n", tmp);
+
+	WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x5<<1));
+	tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
+	if (debug & AVS2_DBG_CACHE)
+		pr_info("miss_mcr_1_cnt_total: %d\n", tmp);
+
+	WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x6<<1));
+	tmp = READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
+	if (debug & AVS2_DBG_CACHE)
+		pr_info("hit_mcr_0_cnt_total: %d\n",tmp);
+
+	WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)(0x7<<1));
+	tmp= READ_VREG(HEVCD_MCRCC_PERFMON_DATA);
+	if (debug & AVS2_DBG_CACHE)
+		pr_info("hit_mcr_1_cnt_total: %d\n",tmp);
+
+	if (raw_mcr_cnt != 0) {
+		hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100;
+		if (debug & AVS2_DBG_CACHE)
+			pr_info("MCRCC_HIT_RATE : %d\n", hitrate);
+		hitrate = ((byp_mcr_cnt_nchoutwin + byp_mcr_cnt_nchcanv)
+			/raw_mcr_cnt) * 100;
+		if (debug & AVS2_DBG_CACHE)
+			pr_info("MCRCC_BYP_RATE : %d\n", hitrate);
+	} else if (debug & AVS2_DBG_CACHE) {
+			pr_info("MCRCC_HIT_RATE : na\n");
+			pr_info("MCRCC_BYP_RATE : na\n");
+	}
+	return;
+}
+
+
+static void  decomp_get_hitrate(void)
+{
+	u32 raw_mcr_cnt;
+	u32 hit_mcr_cnt;
+	int hitrate;
+
+	if (debug & AVS2_DBG_CACHE)
+		pr_info("[cache_util.c] Entered decomp_get_hitrate...\n");
+	WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x0<<1));
+	raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
+	WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x1<<1));
+	hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
+
+	if (debug & AVS2_DBG_CACHE) {
+		pr_info("hcache_raw_cnt_total: %d\n",raw_mcr_cnt);
+		pr_info("hcache_hit_cnt_total: %d\n",hit_mcr_cnt);
+	}
+	if (raw_mcr_cnt != 0) {
+		hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100;
+		if (debug & AVS2_DBG_CACHE)
+			pr_info("DECOMP_HCACHE_HIT_RATE : %d\n", hitrate);
+	} else {
+		if (debug & AVS2_DBG_CACHE)
+			pr_info("DECOMP_HCACHE_HIT_RATE : na\n");
+	}
+	WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x2<<1));
+	raw_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
+	WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x3<<1));
+	hit_mcr_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
+
+	if (debug & AVS2_DBG_CACHE) {
+		pr_info("dcache_raw_cnt_total: %d\n", raw_mcr_cnt);
+		pr_info("dcache_hit_cnt_total: %d\n", hit_mcr_cnt);
+	}
+	if (raw_mcr_cnt != 0) {
+		hitrate = (hit_mcr_cnt / raw_mcr_cnt) * 100;
+		if (debug & AVS2_DBG_CACHE)
+			pr_info("DECOMP_DCACHE_HIT_RATE : %d\n", hitrate);
+	} else if (debug & AVS2_DBG_CACHE) {
+		pr_info("DECOMP_DCACHE_HIT_RATE : na\n");
+	}
+return;
+}
+
+static void decomp_get_comprate(void)
+{
+	u32 raw_ucomp_cnt;
+	u32 fast_comp_cnt;
+	u32 slow_comp_cnt;
+	int comprate;
+
+	if (debug & AVS2_DBG_CACHE)
+		pr_info("[cache_util.c] Entered decomp_get_comprate...\n");
+	WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x4<<1));
+	fast_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
+	WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x5<<1));
+	slow_comp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
+	WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)(0x6<<1));
+	raw_ucomp_cnt = READ_VREG(HEVCD_MPP_DECOMP_PERFMON_DATA);
+	if (debug & AVS2_DBG_CACHE) {
+		pr_info("decomp_fast_comp_total: %d\n", fast_comp_cnt);
+		pr_info("decomp_slow_comp_total: %d\n", slow_comp_cnt);
+		pr_info("decomp_raw_uncomp_total: %d\n", raw_ucomp_cnt);
+	}
+
+	if (raw_ucomp_cnt != 0) {
+		comprate = ((fast_comp_cnt + slow_comp_cnt)
+			/ raw_ucomp_cnt) * 100;
+		if (debug & AVS2_DBG_CACHE)
+			pr_info("DECOMP_COMP_RATIO : %d\n", comprate);
+	} else if (debug & AVS2_DBG_CACHE) {
+			pr_info("DECOMP_COMP_RATIO : na\n");
+	}
+	return;
+}
+#endif
+
+static void config_mcrcc_axi_hw(struct AVS2Decoder_s *dec)
+{
+	uint32_t rdata32;
+	uint32_t rdata32_2;
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+
+	WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2); /* reset mcrcc*/
+
+	if (avs2_dec->img.type == I_IMG) { /* I-PIC*/
+		/* remove reset -- disables clock */
+		WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0);
+		return;
+	}
+/*
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
+		mcrcc_get_hitrate();
+		decomp_get_hitrate();
+		decomp_get_comprate();
+	}
+*/
+	if ((avs2_dec->img.type == B_IMG) ||
+		(avs2_dec->img.type == F_IMG)) { /*B-PIC or F_PIC*/
+		/*Programme canvas0 */
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			(0 << 8) | (0 << 1) | 0);
+		rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+		rdata32 = rdata32 & 0xffff;
+		rdata32 = rdata32 | (rdata32 << 16);
+		WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32);
+
+		/*Programme canvas1 */
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			(16 << 8) | (1 << 1) | 0);
+		rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+		rdata32_2 = rdata32_2 & 0xffff;
+		rdata32_2 = rdata32_2 | (rdata32_2 << 16);
+		if (rdata32 == rdata32_2) {
+			rdata32_2 =
+				READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+			rdata32_2 = rdata32_2 & 0xffff;
+			rdata32_2 = rdata32_2 | (rdata32_2 << 16);
+		}
+		WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32_2);
+	} else { /* P-PIC */
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			(0 << 8) | (1 << 1) | 0);
+		rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+		rdata32 = rdata32 & 0xffff;
+		rdata32 = rdata32 | (rdata32 << 16);
+		WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32);
+
+		/*Programme canvas1*/
+		rdata32 =
+			READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+		rdata32 = rdata32 & 0xffff;
+		rdata32 = rdata32 | (rdata32 << 16);
+		WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32);
+	}
+	/*enable mcrcc progressive-mode */
+	WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0);
+	return;
+}
+
+static void config_mpred_hw(struct AVS2Decoder_s *dec)
+{
+	uint32_t data32;
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic;
+	struct avs2_frame_s *col_pic = avs2_dec->fref[0];
+	int32_t mpred_mv_rd_start_addr;
+	int32_t mpred_curr_lcu_x;
+	int32_t mpred_curr_lcu_y;
+	int32_t mpred_mv_rd_end_addr;
+	int32_t above_en;
+	int32_t mv_wr_en;
+	int32_t mv_rd_en;
+	int32_t col_isIntra;
+	int mv_mem_unit;
+	if (avs2_dec->img.type != I_IMG) {
+		above_en = 1;
+		mv_wr_en = 1;
+		mv_rd_en = 1;
+		col_isIntra = 0;
+	} else {
+		above_en = 1;
+		mv_wr_en = 1;
+		mv_rd_en = 0;
+		col_isIntra = 0;
+	}
+
+	mpred_mv_rd_start_addr =
+		col_pic->mpred_mv_wr_start_addr;
+	data32 = READ_VREG(HEVC_MPRED_CURR_LCU);
+	mpred_curr_lcu_x = data32 & 0xffff;
+	mpred_curr_lcu_y = (data32 >> 16) & 0xffff;
+
+	mv_mem_unit = avs2_dec->lcu_size_log2 == 6 ?
+		0x200 : (avs2_dec->lcu_size_log2 == 5 ?
+			0x80 : 0x20);
+
+	mpred_mv_rd_end_addr =
+		mpred_mv_rd_start_addr +
+		((avs2_dec->lcu_x_num *
+		avs2_dec->lcu_y_num) * mv_mem_unit);
+
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"cur pic index %d  col pic index %d\n",
+		cur_pic->index, col_pic->index);
+
+
+	WRITE_VREG(HEVC_MPRED_MV_WR_START_ADDR,
+		cur_pic->mpred_mv_wr_start_addr);
+	WRITE_VREG(HEVC_MPRED_MV_RD_START_ADDR,
+		col_pic->mpred_mv_wr_start_addr);
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"[MPRED CO_MV] write 0x%x  read 0x%x\n",
+		cur_pic->mpred_mv_wr_start_addr,
+		col_pic->mpred_mv_wr_start_addr);
+
+	data32 =
+		((avs2_dec->bk_img_is_top_field) << 13) |
+		((avs2_dec->hd.background_picture_enable & 1) << 12) |
+		((avs2_dec->hd.curr_RPS.num_of_ref & 7) << 8) |
+		((avs2_dec->hd.b_pmvr_enabled & 1) << 6) |
+		((avs2_dec->img.is_top_field & 1) << 5) |
+		((avs2_dec->img.is_field_sequence & 1) << 4) |
+		((avs2_dec->img.typeb & 7) << 1) |
+		(avs2_dec->hd.background_reference_enable & 0x1);
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"HEVC_MPRED_CTRL9 <= 0x%x(num of ref %d)\n",
+		data32, avs2_dec->hd.curr_RPS.num_of_ref);
+	WRITE_VREG(HEVC_MPRED_CTRL9, data32);
+
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"%s: dis %d %d %d %d %d %d %d fref0_ref_poc %d %d %d %d %d %d %d\n",
+		__func__,
+		avs2_dec->fref[0]->imgtr_fwRefDistance,
+		avs2_dec->fref[1]->imgtr_fwRefDistance,
+		avs2_dec->fref[2]->imgtr_fwRefDistance,
+		avs2_dec->fref[3]->imgtr_fwRefDistance,
+		avs2_dec->fref[4]->imgtr_fwRefDistance,
+		avs2_dec->fref[5]->imgtr_fwRefDistance,
+		avs2_dec->fref[6]->imgtr_fwRefDistance,
+		avs2_dec->fref[0]->ref_poc[0],
+		avs2_dec->fref[0]->ref_poc[1],
+		avs2_dec->fref[0]->ref_poc[2],
+		avs2_dec->fref[0]->ref_poc[3],
+		avs2_dec->fref[0]->ref_poc[4],
+		avs2_dec->fref[0]->ref_poc[5],
+		avs2_dec->fref[0]->ref_poc[6]
+		);
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"pic_distance %d, imgtr_next_P %d\n",
+		avs2_dec->img.pic_distance, avs2_dec->img.imgtr_next_P);
+
+
+	WRITE_VREG(HEVC_MPRED_CUR_POC, avs2_dec->img.pic_distance);
+	WRITE_VREG(HEVC_MPRED_COL_POC, avs2_dec->img.imgtr_next_P);
+
+	/*below MPRED Ref_POC_xx_Lx registers
+		must follow Ref_POC_xx_L0 ->
+		Ref_POC_xx_L1 in pair write order!!!*/
+	WRITE_VREG(HEVC_MPRED_L0_REF00_POC,
+		avs2_dec->fref[0]->imgtr_fwRefDistance);
+	WRITE_VREG(HEVC_MPRED_L1_REF00_POC,
+		avs2_dec->fref[0]->ref_poc[0]);
+
+	WRITE_VREG(HEVC_MPRED_L0_REF01_POC,
+		avs2_dec->fref[1]->imgtr_fwRefDistance);
+	WRITE_VREG(HEVC_MPRED_L1_REF01_POC,
+		avs2_dec->fref[0]->ref_poc[1]);
+
+	WRITE_VREG(HEVC_MPRED_L0_REF02_POC,
+		avs2_dec->fref[2]->imgtr_fwRefDistance);
+	WRITE_VREG(HEVC_MPRED_L1_REF02_POC,
+		avs2_dec->fref[0]->ref_poc[2]);
+
+	WRITE_VREG(HEVC_MPRED_L0_REF03_POC,
+		avs2_dec->fref[3]->imgtr_fwRefDistance);
+	WRITE_VREG(HEVC_MPRED_L1_REF03_POC,
+		avs2_dec->fref[0]->ref_poc[3]);
+
+	WRITE_VREG(HEVC_MPRED_L0_REF04_POC,
+		avs2_dec->fref[4]->imgtr_fwRefDistance);
+	WRITE_VREG(HEVC_MPRED_L1_REF04_POC,
+		avs2_dec->fref[0]->ref_poc[4]);
+
+	WRITE_VREG(HEVC_MPRED_L0_REF05_POC,
+		avs2_dec->fref[5]->imgtr_fwRefDistance);
+	WRITE_VREG(HEVC_MPRED_L1_REF05_POC,
+		avs2_dec->fref[0]->ref_poc[5]);
+
+	WRITE_VREG(HEVC_MPRED_L0_REF06_POC,
+		avs2_dec->fref[6]->imgtr_fwRefDistance);
+	WRITE_VREG(HEVC_MPRED_L1_REF06_POC,
+		avs2_dec->fref[0]->ref_poc[6]);
+
+
+	WRITE_VREG(HEVC_MPRED_MV_RD_END_ADDR,
+		mpred_mv_rd_end_addr);
+}
+
+static void config_dblk_hw(struct AVS2Decoder_s *dec)
+{
+	/*
+	* Picture level de-block parameter configuration here
+	*/
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	union param_u *rpm_param = &avs2_dec->param;
+	uint32_t data32;
+
+	data32 = READ_VREG(HEVC_DBLK_CFG1);
+	data32 = (((data32 >> 20) & 0xfff) << 20) |
+		(((avs2_dec->input.sample_bit_depth == 10)
+		? 0xa : 0x0) << 16) |   /*[16 +: 4]: {luma_bd[1:0],
+							chroma_bd[1:0]}*/
+		(((data32 >> 2) & 0x3fff) << 2) |
+		(((rpm_param->p.lcu_size == 6)
+		? 0 : (rpm_param->p.lcu_size == 5)
+		? 1 : 2) << 0);/*[ 0 +: 2]: lcu_size*/
+	WRITE_VREG(HEVC_DBLK_CFG1, data32);
+
+	data32 = (avs2_dec->img.height << 16) |
+		avs2_dec->img.width;
+	WRITE_VREG(HEVC_DBLK_CFG2, data32);
+	/*
+	[27 +: 1]: cross_slice_loopfilter_enable_flag
+	[26 +: 1]: loop_filter_disable
+	[25 +: 1]: useNSQT
+	[22 +: 3]: imgtype
+	[17 +: 5]: alpha_c_offset (-8~8)
+	[12 +: 5]: beta_offset (-8~8)
+	[ 6 +: 6]: chroma_quant_param_delta_u (-16~16)
+	[ 0 +: 6]: chroma_quant_param_delta_v (-16~16)
+	*/
+	data32 = ((avs2_dec->input.crossSliceLoopFilter
+		& 0x1) << 27) |
+	((rpm_param->p.loop_filter_disable & 0x1) << 26) |
+	((avs2_dec->input.useNSQT & 0x1) << 25) |
+	((avs2_dec->img.type & 0x7) << 22) |
+	((rpm_param->p.alpha_c_offset & 0x1f) << 17) |
+	((rpm_param->p.beta_offset & 0x1f) << 12) |
+	((rpm_param->p.chroma_quant_param_delta_cb & 0x3f) << 6) |
+	((rpm_param->p.chroma_quant_param_delta_cr & 0x3f) << 0);
+
+	WRITE_VREG(HEVC_DBLK_CFG9, data32);
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"[c] cfgDBLK: crossslice(%d),lfdisable(%d),bitDepth(%d),lcuSize(%d),NSQT(%d)\n",
+		avs2_dec->input.crossSliceLoopFilter,
+		rpm_param->p.loop_filter_disable,
+		avs2_dec->input.sample_bit_depth,
+		avs2_dec->lcu_size,
+		avs2_dec->input.useNSQT);
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"[c] cfgDBLK: alphaCOffset(%d),betaOffset(%d),quantDeltaCb(%d),quantDeltaCr(%d)\n",
+		rpm_param->p.alpha_c_offset,
+		rpm_param->p.beta_offset,
+		rpm_param->p.chroma_quant_param_delta_cb,
+		rpm_param->p.chroma_quant_param_delta_cr);
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"[c] cfgDBLK: .done.\n");
+}
+
+static void config_sao_hw(struct AVS2Decoder_s *dec)
+{
+	uint32_t data32;
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic;
+
+	int lcu_size = 64;
+	int mc_buffer_size_u_v =
+		cur_pic->lcu_total * lcu_size*lcu_size/2;
+	int mc_buffer_size_u_v_h =
+		(mc_buffer_size_u_v + 0xffff) >> 16;/*64k alignment*/
+
+	data32 = READ_VREG(HEVC_SAO_CTRL0);
+	data32 &= (~0xf);
+	data32 |= avs2_dec->lcu_size_log2;
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"%s, lcu_size_log2 = %d, config HEVC_SAO_CTRL0 0x%x\n",
+		__func__,
+		avs2_dec->lcu_size_log2,
+		data32);
+
+	WRITE_VREG(HEVC_SAO_CTRL0, data32);
+
+#ifndef AVS2_10B_MMU
+	if ((get_double_write_mode(dec) & 0x10) == 0)
+		WRITE_VREG(HEVC_CM_BODY_START_ADDR, cur_pic->mc_y_adr);
+#endif
+	if ((get_double_write_mode(dec) & 0x20) == 0) {
+		WRITE_VREG(HEVC_SAO_Y_START_ADDR, cur_pic->dw_y_adr);
+		WRITE_VREG(HEVC_SAO_C_START_ADDR, cur_pic->dw_u_v_adr);
+		WRITE_VREG(HEVC_SAO_Y_WPTR, cur_pic->dw_y_adr);
+		WRITE_VREG(HEVC_SAO_C_WPTR, cur_pic->dw_u_v_adr);
+	} else {
+		WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff);
+		WRITE_VREG(HEVC_SAO_C_START_ADDR, 0xffffffff);
+	}
+#ifdef AVS2_10B_MMU
+	WRITE_VREG(HEVC_CM_HEADER_START_ADDR, cur_pic->header_adr);
+#endif
+#ifdef AVS2_10B_MMU_DW
+	if (dec->dw_mmu_enable) {
+		WRITE_VREG(HEVC_CM_HEADER_START_ADDR2, cur_pic->dw_header_adr);
+		WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0);
+		WRITE_VREG(HEVC_SAO_C_START_ADDR, 0);
+	}
+#endif
+
+	data32 = (mc_buffer_size_u_v_h << 16) << 1;
+	/*pr_info("data32=%x,mc_buffer_size_u_v_h=%x,lcu_total=%x\n",
+		data32, mc_buffer_size_u_v_h, cur_pic->lcu_total);*/
+	WRITE_VREG(HEVC_SAO_Y_LENGTH, data32);
+
+	data32 = (mc_buffer_size_u_v_h << 16);
+	WRITE_VREG(HEVC_SAO_C_LENGTH, data32);
+
+#ifdef AVS2_10B_NV21
+#ifdef DOS_PROJECT
+	data32 = READ_VREG(HEVC_SAO_CTRL1);
+	data32 &= (~0x3000);
+	/*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/
+	data32 |= (MEM_MAP_MODE << 12);
+	data32 &= (~0x3);
+	data32 |= 0x1; /* [1]:dw_disable [0]:cm_disable*/
+
+	/*
+	*  [31:24] ar_fifo1_axi_thred
+	*  [23:16] ar_fifo0_axi_thred
+	*  [15:14] axi_linealign, 0-16bytes, 1-32bytes, 2-64bytes
+	*  [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32
+	*  [11:08] axi_lendian_C
+	*  [07:04] axi_lendian_Y
+	*  [3]     reserved
+	*  [2]     clk_forceon
+	*  [1]     dw_disable:disable double write output
+	*  [0]     cm_disable:disable compress output
+	*/
+	data32 &= (~(3 << 14));
+	data32 |= (2 << 14);
+
+	WRITE_VREG(HEVC_SAO_CTRL1, data32);
+	/*[23:22] dw_v1_ctrl [21:20] dw_v0_ctrl [19:18] dw_h1_ctrl
+		[17:16] dw_h0_ctrl*/
+	data32 = READ_VREG(HEVC_SAO_CTRL5);
+	/*set them all 0 for H265_NV21 (no down-scale)*/
+	data32 &= ~(0xff << 16);
+	WRITE_VREG(HEVC_SAO_CTRL5, data32);
+	ata32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
+	data32 &= (~0x30);
+	/*[5:4] address_format 00:linear 01:32x32 10:64x32*/
+	data32 |= (MEM_MAP_MODE << 4);
+	WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32);
+#else
+	/*m8baby test1902*/
+	data32 = READ_VREG(HEVC_SAO_CTRL1);
+	data32 &= (~0x3000);
+	/*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/
+	data32 |= (MEM_MAP_MODE << 12);
+	data32 &= (~0xff0);
+	/*data32 |= 0x670;*/ /*Big-Endian per 64-bit*/
+	data32 |= 0x880;  /*.Big-Endian per 64-bit */
+	data32 &= (~0x3);
+	data32 |= 0x1; /*[1]:dw_disable [0]:cm_disable*/
+	WRITE_VREG(HEVC_SAO_CTRL1, data32);
+	/* [23:22] dw_v1_ctrl [21:20] dw_v0_ctrl
+	[19:18] dw_h1_ctrl [17:16] dw_h0_ctrl*/
+	data32 = READ_VREG(HEVC_SAO_CTRL5);
+	/* set them all 0 for H265_NV21 (no down-scale)*/
+	data32 &= ~(0xff << 16);
+	WRITE_VREG(HEVC_SAO_CTRL5, data32);
+
+	/*
+	* [3:0]   little_endian
+	* [5:4]   address_format 00:linear 01:32x32 10:64x32
+	* [7:6]   reserved
+	* [9:8]   Linear_LineAlignment 00:16byte 01:32byte 10:64byte
+	* [11:10] reserved
+	* [12]    CbCr_byte_swap
+	* [31:13] reserved
+	*/
+
+	data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
+	data32 &= (~0x30);
+	/*[5:4] address_format 00:linear 01:32x32 10:64x32*/
+	data32 |= (MEM_MAP_MODE << 4);
+	data32 &= (~0xF);
+	data32 |= 0x8; /*Big-Endian per 64-bit*/
+
+	data32 &= (~(3 << 8));
+	data32 |= (2 << 8);
+	WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32);
+#endif
+#else
+	data32 = READ_VREG(HEVC_SAO_CTRL1);
+	data32 &= (~(3 << 14));
+	data32 |= (2 << 14);	/* line align with 64*/
+	data32 &= (~0x3000);
+	data32 |= (MEM_MAP_MODE << 12);	/* [13:12] axi_aformat, 0-Linear,
+				   1-32x32, 2-64x32 */
+	data32 &= (~0xff0);
+#ifdef AVS2_10B_MMU_DW
+	if (dec->dw_mmu_enable == 0)
+		data32 |= ((dec->endian >> 8) & 0xfff);
+#else
+	data32 |= ((dec->endian >> 8) & 0xfff);	/* data32 |= 0x670; Big-Endian per 64-bit */
+#endif
+	data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/
+#if 0
+	if  (get_cpu_major_id() < MESON_CPU_MAJOR_ID_G12A) {
+		if (get_double_write_mode(dec) == 0)
+			data32 |= 0x2; /*disable double write*/
+#ifndef AVS2_10B_MMU
+		else
+		if (get_double_write_mode(dec) & 0x10)
+			data32 |= 0x1; /*disable cm*/
+#endif
+	}
+#endif
+	if (get_double_write_mode(dec) == 0)
+		data32 |= 0x2; /*disable double write*/
+	else if (get_double_write_mode(dec) & 0x10)
+		data32 |= 0x1; /*disable cm*/
+
+	/*
+	*  [31:24] ar_fifo1_axi_thred
+	*  [23:16] ar_fifo0_axi_thred
+	*  [15:14] axi_linealign, 0-16bytes, 1-32bytes, 2-64bytes
+	*  [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32
+	*  [11:08] axi_lendian_C
+	*  [07:04] axi_lendian_Y
+	*  [3]     reserved
+	*  [2]     clk_forceon
+	*  [1]     dw_disable:disable double write output
+	*  [0]     cm_disable:disable compress output
+	*/
+	WRITE_VREG(HEVC_SAO_CTRL1, data32);
+
+	if (get_double_write_mode(dec) & 0x10) {
+		/* [23:22] dw_v1_ctrl
+		[21:20] dw_v0_ctrl
+		[19:18] dw_h1_ctrl
+		[17:16] dw_h0_ctrl
+		*/
+		data32 = READ_VREG(HEVC_SAO_CTRL5);
+		/*set them all 0 for H265_NV21 (no down-scale)*/
+		data32 &= ~(0xff << 16);
+		WRITE_VREG(HEVC_SAO_CTRL5, data32);
+	} else {
+		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T7)
+			WRITE_VREG(HEVC_SAO_CTRL26, 0);
+
+		data32 = READ_VREG(HEVC_SAO_CTRL5);
+		data32 &= (~(0xff << 16));
+		if ((get_double_write_mode(dec) & 0xf) == 8 ||
+			(get_double_write_mode(dec) & 0xf) == 9) {
+			data32 |= (0xff<<16);
+			WRITE_VREG(HEVC_SAO_CTRL26, 0xf);
+		} else if ((get_double_write_mode(dec) & 0xf) == 2 ||
+			(get_double_write_mode(dec) & 0xf) == 3)
+			data32 |= (0xff<<16);
+		else if ((get_double_write_mode(dec) & 0xf) == 4)
+			data32 |= (0x33<<16);
+		WRITE_VREG(HEVC_SAO_CTRL5, data32);
+	}
+
+	/*
+	* [3:0]   little_endian
+	* [5:4]   address_format 00:linear 01:32x32 10:64x32
+	* [7:6]   reserved
+	* [9:8]   Linear_LineAlignment 00:16byte 01:32byte 10:64byte
+	* [11:10] reserved
+	* [12]    CbCr_byte_swap
+	* [31:13] reserved
+	*/
+
+	data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
+	data32 &= (~0x30);
+	/* [5:4]    -- address_format 00:linear 01:32x32 10:64x32 */
+	data32 |= (mem_map_mode << 4);
+	data32 &= (~0xF);
+	data32 |= (dec->endian & 0xf);  /* valid only when double write only */
+	/*data32 |= 0x8;*/		/* Big-Endian per 64-bit */
+	data32 &= (~(3 << 8));
+	data32 |= (2 << 8);		/* line align with 64 for dw only */
+	WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32);
+#endif
+#ifndef AVS2_10B_NV21
+#ifdef AVS2_10B_MMU_DW
+	if (dec->dw_mmu_enable) {
+		struct BuffInfo_s *buf_spec = NULL;
+		buf_spec = &dec->work_space_buf_store;
+		WRITE_VREG(HEVC_DW_VH0_ADDDR, buf_spec->mmu_vbh_dw.buf_start + (2 * DW_VBH_BUF_SIZE(buf_spec)));
+		WRITE_VREG(HEVC_DW_VH1_ADDDR, buf_spec->mmu_vbh_dw.buf_start + (3 * DW_VBH_BUF_SIZE(buf_spec)));
+	}
+#endif
+#endif
+
+}
+
+static void reconstructCoefficients(struct AVS2Decoder_s *dec,
+	struct ALFParam_s *alfParam)
+{
+	int32_t g, sum, i, coeffPred;
+	for (g = 0; g < alfParam->filters_per_group; g++) {
+		sum = 0;
+		for (i = 0; i < alfParam->num_coeff - 1; i++) {
+			sum += (2 * alfParam->coeffmulti[g][i]);
+			dec->m_filterCoeffSym[g][i] =
+			alfParam->coeffmulti[g][i];
+			/*pr_info("[t] dec->m_filterCoeffSym[%d][%d]=0x%x\n",
+			g, i, dec->m_filterCoeffSym[g][i]);*/
+		}
+		coeffPred = (1 << ALF_NUM_BIT_SHIFT) - sum;
+		dec->m_filterCoeffSym[g][alfParam->num_coeff - 1]
+		= coeffPred +
+		alfParam->coeffmulti[g][alfParam->num_coeff - 1];
+		/*pr_info("[t] dec->m_filterCoeffSym[%d][%d]=0x%x\n",
+		g, (alfParam->num_coeff - 1),
+		dec->m_filterCoeffSym[g][alfParam->num_coeff - 1]);*/
+	}
+}
+
+static void reconstructCoefInfo(struct AVS2Decoder_s *dec,
+	int32_t compIdx, struct ALFParam_s *alfParam)
+{
+	int32_t i;
+	if (compIdx == ALF_Y) {
+		if (alfParam->filters_per_group > 1) {
+			for (i = 1; i < NO_VAR_BINS; ++i) {
+				if (alfParam->filterPattern[i])
+					dec->m_varIndTab[i] =
+						dec->m_varIndTab[i - 1] + 1;
+				else
+					dec->m_varIndTab[i] =
+						dec->m_varIndTab[i - 1];
+			}
+		}
+	}
+	reconstructCoefficients(dec, alfParam);
+}
+
+static void config_alf_hw(struct AVS2Decoder_s *dec)
+{
+	/*
+	* Picture level ALF parameter configuration here
+	*/
+	uint32_t data32;
+	int32_t i, j;
+	int32_t m_filters_per_group;
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	struct ALFParam_s *m_alfPictureParam_y =
+		&avs2_dec->m_alfPictureParam[0];
+	struct ALFParam_s *m_alfPictureParam_cb =
+		&avs2_dec->m_alfPictureParam[1];
+	struct ALFParam_s *m_alfPictureParam_cr =
+		&avs2_dec->m_alfPictureParam[2];
+
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"[t]alfy,cidx(%d),flag(%d),filters_per_group(%d),filterPattern[0]=0x%x,[15]=0x%x\n",
+		m_alfPictureParam_y->componentID,
+		m_alfPictureParam_y->alf_flag,
+		m_alfPictureParam_y->filters_per_group,
+		m_alfPictureParam_y->filterPattern[0],
+		m_alfPictureParam_y->filterPattern[15]);
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"[t]alfy,num_coeff(%d),coeffmulti[0][0]=0x%x,[0][1]=0x%x,[1][0]=0x%x,[1][1]=0x%x\n",
+		m_alfPictureParam_y->num_coeff,
+		m_alfPictureParam_y->coeffmulti[0][0],
+		m_alfPictureParam_y->coeffmulti[0][1],
+		m_alfPictureParam_y->coeffmulti[1][0],
+		m_alfPictureParam_y->coeffmulti[1][1]);
+
+	/*Cr*/
+	for (i = 0; i < 16; i++)
+		dec->m_varIndTab[i] = 0;
+	for (j = 0; j < 16; j++)
+		for (i = 0; i < 9; i++)
+			dec->m_filterCoeffSym[j][i] = 0;
+	reconstructCoefInfo(dec, 2, m_alfPictureParam_cr);
+	data32 =
+		((dec->m_filterCoeffSym[0][4] & 0xf) << 28) |
+		((dec->m_filterCoeffSym[0][3] & 0x7f) << 21) |
+		((dec->m_filterCoeffSym[0][2] & 0x7f) << 14) |
+		((dec->m_filterCoeffSym[0][1] & 0x7f) << 7) |
+		((dec->m_filterCoeffSym[0][0] & 0x7f) << 0);
+	WRITE_VREG(HEVC_DBLK_CFGD, data32);
+	data32 =
+		((dec->m_filterCoeffSym[0][8] & 0x7f) << 24) |
+		((dec->m_filterCoeffSym[0][7] & 0x7f) << 17) |
+		((dec->m_filterCoeffSym[0][6] & 0x7f) << 10) |
+		((dec->m_filterCoeffSym[0][5] & 0x7f) << 3) |
+		(((dec->m_filterCoeffSym[0][4] >> 4) & 0x7) <<  0);
+	WRITE_VREG(HEVC_DBLK_CFGD, data32);
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"[c] pic_alf_on_cr(%d), alf_cr_coef(%d %d %d %d %d %d %d %d %d)\n",
+		m_alfPictureParam_cr->alf_flag,
+		dec->m_filterCoeffSym[0][0],
+		dec->m_filterCoeffSym[0][1],
+		dec->m_filterCoeffSym[0][2],
+		dec->m_filterCoeffSym[0][3],
+		dec->m_filterCoeffSym[0][4],
+		dec->m_filterCoeffSym[0][5],
+		dec->m_filterCoeffSym[0][6],
+		dec->m_filterCoeffSym[0][7],
+		dec->m_filterCoeffSym[0][8]);
+
+	/* Cb*/
+	for (j = 0; j < 16; j++)
+		for (i = 0; i < 9; i++)
+			dec->m_filterCoeffSym[j][i] = 0;
+	reconstructCoefInfo(dec, 1, m_alfPictureParam_cb);
+	data32 =
+		((dec->m_filterCoeffSym[0][4] & 0xf) << 28) |
+		((dec->m_filterCoeffSym[0][3] & 0x7f) << 21) |
+		((dec->m_filterCoeffSym[0][2] & 0x7f) << 14) |
+		((dec->m_filterCoeffSym[0][1] & 0x7f) << 7) |
+		((dec->m_filterCoeffSym[0][0] & 0x7f) << 0);
+	WRITE_VREG(HEVC_DBLK_CFGD, data32);
+	data32 =
+		((dec->m_filterCoeffSym[0][8] & 0x7f) << 24) |
+		((dec->m_filterCoeffSym[0][7] & 0x7f) << 17) |
+		((dec->m_filterCoeffSym[0][6] & 0x7f) << 10) |
+		((dec->m_filterCoeffSym[0][5] & 0x7f) << 3) |
+		(((dec->m_filterCoeffSym[0][4] >> 4) & 0x7) << 0);
+	WRITE_VREG(HEVC_DBLK_CFGD, data32);
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"[c] pic_alf_on_cb(%d), alf_cb_coef(%d %d %d %d %d %d %d %d %d)\n",
+		m_alfPictureParam_cb->alf_flag,
+		dec->m_filterCoeffSym[0][0],
+		dec->m_filterCoeffSym[0][1],
+		dec->m_filterCoeffSym[0][2],
+		dec->m_filterCoeffSym[0][3],
+		dec->m_filterCoeffSym[0][4],
+		dec->m_filterCoeffSym[0][5],
+		dec->m_filterCoeffSym[0][6],
+		dec->m_filterCoeffSym[0][7],
+		dec->m_filterCoeffSym[0][8]);
+
+	/* Y*/
+	for (j = 0; j < 16; j++)
+		for (i = 0; i < 9; i++)
+			dec->m_filterCoeffSym[j][i] = 0;
+	reconstructCoefInfo(dec, 0, m_alfPictureParam_y);
+	data32 =
+		((dec->m_varIndTab[7] & 0xf) << 28) |
+		((dec->m_varIndTab[6] & 0xf) << 24) |
+		((dec->m_varIndTab[5] & 0xf) << 20) |
+		((dec->m_varIndTab[4] & 0xf) << 16) |
+		((dec->m_varIndTab[3] & 0xf) << 12) |
+		((dec->m_varIndTab[2] & 0xf) << 8) |
+		((dec->m_varIndTab[1] & 0xf) << 4) |
+		((dec->m_varIndTab[0] & 0xf) << 0);
+	WRITE_VREG(HEVC_DBLK_CFGD, data32);
+	data32 = ((dec->m_varIndTab[15] & 0xf) << 28) |
+		((dec->m_varIndTab[14] & 0xf) << 24) |
+		((dec->m_varIndTab[13] & 0xf) << 20) |
+		((dec->m_varIndTab[12] & 0xf) << 16) |
+		((dec->m_varIndTab[11] & 0xf) << 12) |
+		((dec->m_varIndTab[10] & 0xf) << 8) |
+		((dec->m_varIndTab[9] & 0xf) << 4) |
+		((dec->m_varIndTab[8] & 0xf) << 0);
+	WRITE_VREG(HEVC_DBLK_CFGD, data32);
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"[c] pic_alf_on_y(%d), alf_y_tab(%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)\n",
+		m_alfPictureParam_y->alf_flag,
+		dec->m_varIndTab[0],
+		dec->m_varIndTab[1],
+		dec->m_varIndTab[2],
+		dec->m_varIndTab[3],
+		dec->m_varIndTab[4],
+		dec->m_varIndTab[5],
+		dec->m_varIndTab[6],
+		dec->m_varIndTab[7],
+		dec->m_varIndTab[8],
+		dec->m_varIndTab[9],
+		dec->m_varIndTab[10],
+		dec->m_varIndTab[11],
+		dec->m_varIndTab[12],
+		dec->m_varIndTab[13],
+		dec->m_varIndTab[14],
+		dec->m_varIndTab[15]);
+
+	m_filters_per_group =
+		(m_alfPictureParam_y->alf_flag == 0) ?
+		1 : m_alfPictureParam_y->filters_per_group;
+	for (i = 0; i < m_filters_per_group; i++) {
+		data32 =
+			((dec->m_filterCoeffSym[i][4] & 0xf) << 28) |
+			((dec->m_filterCoeffSym[i][3] & 0x7f) << 21) |
+			((dec->m_filterCoeffSym[i][2] & 0x7f) << 14) |
+			((dec->m_filterCoeffSym[i][1] & 0x7f) << 7) |
+			((dec->m_filterCoeffSym[i][0] & 0x7f) << 0);
+		WRITE_VREG(HEVC_DBLK_CFGD, data32);
+		data32 =
+			/*[31] last indication*/
+			((i == m_filters_per_group-1) << 31) |
+			((dec->m_filterCoeffSym[i][8] & 0x7f) << 24) |
+			((dec->m_filterCoeffSym[i][7] & 0x7f) << 17) |
+			((dec->m_filterCoeffSym[i][6] & 0x7f) << 10) |
+			((dec->m_filterCoeffSym[i][5] & 0x7f) << 3) |
+			(((dec->m_filterCoeffSym[i][4] >> 4) & 0x7) << 0);
+		WRITE_VREG(HEVC_DBLK_CFGD, data32);
+		avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+			"[c] alf_y_coef[%d](%d %d %d %d %d %d %d %d %d)\n",
+			i, dec->m_filterCoeffSym[i][0],
+			dec->m_filterCoeffSym[i][1],
+			dec->m_filterCoeffSym[i][2],
+			dec->m_filterCoeffSym[i][3],
+			dec->m_filterCoeffSym[i][4],
+			dec->m_filterCoeffSym[i][5],
+			dec->m_filterCoeffSym[i][6],
+			dec->m_filterCoeffSym[i][7],
+			dec->m_filterCoeffSym[i][8]);
+	}
+	avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+		"[c] cfgALF .done.\n");
+}
+
+static void config_other_hw(struct AVS2Decoder_s *dec)
+{
+	uint32_t data32;
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic;
+	int bit_depth = cur_pic->bit_depth;
+	int losless_comp_header_size =
+		compute_losless_comp_header_size(
+		dec, cur_pic->pic_w,
+		cur_pic->pic_h);
+	int losless_comp_body_size =
+		compute_losless_comp_body_size(
+		dec, cur_pic->pic_w,
+		cur_pic->pic_h, (bit_depth == AVS2_BITS_10));
+	cur_pic->comp_body_size = losless_comp_body_size;
+
+#ifdef LOSLESS_COMPRESS_MODE
+	data32 = READ_VREG(HEVC_SAO_CTRL5);
+	if (bit_depth == AVS2_BITS_10)
+		data32 &= ~(1 << 9);
+	else
+		data32 |= (1 << 9);
+
+	WRITE_VREG(HEVC_SAO_CTRL5, data32);
+
+#ifdef AVS2_10B_MMU
+	/*bit[4] : paged_mem_mode*/
+	WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4));
+#else
+	/*bit[3] smem mdoe*/
+	if (bit_depth == AVS2_BITS_10)
+		WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0 << 3));
+	else
+		WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (1 << 3));
+#endif
+	WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5));
+	/*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/
+	WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size);
+	WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size);
+	WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size);
+#else
+	WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
+#endif
+}
+
+static u32 init_cuva_size;
+static int cuva_data_is_avaible(struct AVS2Decoder_s *dec)
+{
+	u32 reg_val;
+
+	reg_val = READ_VREG(AVS2_CUVA_DATA_SIZE);
+	avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+		"%s:reg_val: %u \n",
+		__func__, reg_val);
+	if (reg_val != 0 && reg_val != init_cuva_size)
+		return 1;
+	else
+		return 0;
+}
+
+static void config_cuva_buf(struct AVS2Decoder_s *dec)
+{
+	WRITE_VREG(AVS2_CUVA_ADR, dec->cuva_phy_addr);
+	init_cuva_size = (dec->cuva_size >> 4) << 16;
+	WRITE_VREG(AVS2_CUVA_DATA_SIZE, init_cuva_size);
+}
+
+static void set_cuva_data(struct AVS2Decoder_s *dec)
+{
+	int i;
+	unsigned short *cuva_adr;
+	unsigned int size_reg_val =
+		READ_VREG(AVS2_CUVA_DATA_SIZE);
+	unsigned int cuva_count = 0;
+	int cuva_size = 0;
+	struct avs2_frame_s *pic = dec->avs2_dec.hc.cur_pic;
+	if (pic == NULL || 0 == cuva_data_is_avaible(dec)) {
+		avs2_print(dec, AVS2_DBG_HDR_INFO,
+		"%s:pic 0x%p or data not avaible\n",
+		__func__, pic);
+		return;
+	}
+
+	cuva_adr = (unsigned short *)dec->cuva_addr;
+	cuva_count = ((size_reg_val >> 16) << 4) >> 1;
+	cuva_size = dec->cuva_size;
+	dec->hdr_flag |= HDR_CUVA_MASK;
+
+	avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+			"%s:pic 0x%p cuva_count(%d) cuva_size(%d) hdr_flag 0x%x\n",
+			__func__, pic, cuva_count, cuva_size, dec->hdr_flag);
+	if (cuva_size > 0 && cuva_count > 0) {
+		int new_size;
+		char *new_buf;
+
+		new_size = cuva_size;
+		new_buf = vzalloc(new_size);
+		if (new_buf) {
+			unsigned char *p = new_buf;
+			int len = 0;
+			pic->cuva_data_buf = new_buf;
+
+			for (i = 0; i < cuva_count; i += 4) {
+				int j;
+
+				for (j = 0; j < 4; j++) {
+					unsigned short aa = cuva_adr[i + 3 - j];
+					*p = aa & 0xff;
+					p++;
+					len++;
+				}
+			}
+			if (len > 0) {
+				pic->cuva_data_size = len;
+			}
+
+			avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+				"cuva: (size %d)\n",
+				pic->cuva_data_size);
+			if (get_dbg_flag(dec) & AVS2_DBG_HDR_DATA) {
+				for (i = 0; i < pic->cuva_data_size; i++) {
+					pr_info("%02x ", pic->cuva_data_buf[i]);
+					if (((i + 1) & 0xf) == 0)
+						pr_info("\n");
+				}
+				pr_info("\n");
+			}
+
+		} else {
+			avs2_print(dec, 0, "new buf alloc failed\n");
+			if (pic->cuva_data_buf)
+				vfree(pic->cuva_data_buf);
+			pic->cuva_data_buf = NULL;
+			pic->cuva_data_size = 0;
+		}
+	}
+}
+
+static void release_cuva_data(struct avs2_frame_s *pic)
+{
+	if (pic == NULL)
+		return;
+	if (pic->cuva_data_buf) {
+		vfree(pic->cuva_data_buf);
+	}
+	pic->cuva_data_buf = NULL;
+	pic->cuva_data_size = 0;
+}
+
+static void avs2_config_work_space_hw(struct AVS2Decoder_s *dec)
+{
+	struct BuffInfo_s *buf_spec = dec->work_space_buf;
+#ifdef LOSLESS_COMPRESS_MODE
+	int losless_comp_header_size =
+		compute_losless_comp_header_size(
+		dec, dec->init_pic_w,
+		dec->init_pic_h);
+	int losless_comp_body_size =
+		compute_losless_comp_body_size(dec,
+		dec->init_pic_w,
+		dec->init_pic_h, buf_alloc_depth == 10);
+#endif
+#ifdef AVS2_10B_MMU
+	unsigned int data32;
+#endif
+	if (debug && dec->init_flag == 0)
+		avs2_print(dec, 0,
+			"%s %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
+			__func__,
+			buf_spec->ipp.buf_start,
+			buf_spec->start_adr,
+			buf_spec->short_term_rps.buf_start,
+			buf_spec->rcs.buf_start,
+			buf_spec->sps.buf_start,
+			buf_spec->pps.buf_start,
+			buf_spec->sao_up.buf_start,
+			buf_spec->swap_buf.buf_start,
+			buf_spec->swap_buf2.buf_start,
+			buf_spec->scalelut.buf_start,
+			buf_spec->dblk_para.buf_start,
+			buf_spec->dblk_data.buf_start,
+			buf_spec->dblk_data2.buf_start);
+	WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, buf_spec->ipp.buf_start);
+	if ((debug & AVS2_DBG_SEND_PARAM_WITH_REG) == 0)
+		WRITE_VREG(HEVC_RPM_BUFFER, (u32)dec->rpm_phy_addr);
+	WRITE_VREG(AVS2_ALF_SWAP_BUFFER, buf_spec->short_term_rps.buf_start);
+	WRITE_VREG(HEVC_RCS_BUFFER, buf_spec->rcs.buf_start);
+	WRITE_VREG(HEVC_SPS_BUFFER, buf_spec->sps.buf_start);
+	WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start);
+	//WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start);
+#ifdef AVS2_10B_MMU
+	WRITE_VREG(AVS2_MMU_MAP_BUFFER, dec->frame_mmu_map_phy_addr);
+#else
+	WRITE_VREG(HEVC_STREAM_SWAP_BUFFER, buf_spec->swap_buf.buf_start);
+#endif
+#ifdef AVS2_10B_MMU_DW
+	if (dec->dw_mmu_enable) {
+		//WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR2, FRAME_MMU_MAP_ADDR_DW);
+		WRITE_VREG(HEVC_SAO_MMU_DMA_CTRL2, dec->dw_frame_mmu_map_phy_addr);
+	}
+#endif
+	WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, buf_spec->swap_buf2.buf_start);
+	//WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start);
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
+		if (buf_spec->max_width <= 4096 && buf_spec->max_height <= 2304)
+			WRITE_VREG(HEVC_DBLK_CFG3, 0x404010); //default value
+		else
+			WRITE_VREG(HEVC_DBLK_CFG3, 0x808020); // make left storage 2 x 4k]
+		avs2_print(dec, AVS2_DBG_BUFMGR,
+			"HEVC_DBLK_CFG3 = %x\n", READ_VREG(HEVC_DBLK_CFG3));
+	}
+
+	/* cfg_p_addr */
+	WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start);
+	/* cfg_d_addr */
+	WRITE_VREG(HEVC_DBLK_CFG5, buf_spec->dblk_data.buf_start);
+
+	WRITE_VREG(HEVC_DBLK_CFGE, buf_spec->dblk_data2.buf_start);
+
+#ifdef LOSLESS_COMPRESS_MODE
+	data32 = READ_VREG(HEVC_SAO_CTRL5);
+#if 1
+	data32 &= ~(1<<9);
+#else
+	if (params->p.bit_depth != 0x00)
+		data32 &= ~(1<<9);
+	else
+		data32 |= (1<<9);
+#endif
+	WRITE_VREG(HEVC_SAO_CTRL5, data32);
+#ifdef AVS2_10B_MMU
+	/*bit[4] : paged_mem_mode*/
+	WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4));
+	WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0);
+#else
+	/* bit[3] smem mode*/
+	WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0<<3));
+
+	WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5));
+#endif
+	/*WRITE_VREG(HEVCD_MPP_DECOMP_CTL2,(losless_comp_body_size >> 5));*/
+	/*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/
+/*8-bit mode */
+	WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size);
+	WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size);
+	WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size);
+#else
+	WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
+#endif
+
+#ifdef AVS2_10B_MMU
+	WRITE_VREG(HEVC_SAO_MMU_VH0_ADDR, buf_spec->mmu_vbh.buf_start);
+	WRITE_VREG(HEVC_SAO_MMU_VH1_ADDR, buf_spec->mmu_vbh.buf_start
+			+ VBH_BUF_SIZE(buf_spec));
+	/*data32 = READ_VREG(HEVC_SAO_CTRL9);*/
+	/*data32 |= 0x1;*/
+	/*WRITE_VREG(HEVC_SAO_CTRL9, data32);*/
+
+	/* use HEVC_CM_HEADER_START_ADDR */
+	data32 = READ_VREG(HEVC_SAO_CTRL5);
+	data32 |= (1<<10);
+#if 1
+	if (debug & AVS2_DBG_FORCE_UNCOMPRESS)
+		data32 |= 0x80;
+#endif
+	WRITE_VREG(HEVC_SAO_CTRL5, data32);
+
+#endif
+
+#ifdef AVS2_10B_MMU_DW
+	if (dec->dw_mmu_enable) {
+		u32 data_tmp;
+		data_tmp = READ_VREG(HEVC_SAO_CTRL9);
+		data_tmp |= (1<<10);
+		WRITE_VREG(HEVC_SAO_CTRL9, data_tmp);
+
+		WRITE_VREG(HEVC_CM_BODY_LENGTH2,losless_comp_body_size);
+		WRITE_VREG(HEVC_CM_HEADER_OFFSET2,losless_comp_body_size);
+		WRITE_VREG(HEVC_CM_HEADER_LENGTH2,losless_comp_header_size);
+
+		WRITE_VREG(HEVC_SAO_MMU_VH0_ADDR2, buf_spec->mmu_vbh_dw.buf_start);
+		WRITE_VREG(HEVC_SAO_MMU_VH1_ADDR2, buf_spec->mmu_vbh_dw.buf_start + DW_VBH_BUF_SIZE(buf_spec));
+
+		/* use HEVC_CM_HEADER_START_ADDR */
+		data32 = READ_VREG(HEVC_SAO_CTRL5);
+		data32 |= (1<<15);
+		WRITE_VREG(HEVC_SAO_CTRL5, data32);
+	}
+#endif
+
+
+	WRITE_VREG(LMEM_DUMP_ADR, (u32)dec->lmem_phy_addr);
+
+	WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, buf_spec->mpred_above.buf_start);
+
+#ifdef CO_MV_COMPRESS
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T7) {
+	    data32 = READ_VREG(HEVC_MPRED_CTRL4);
+	    data32 |=  (1 << 1);
+	    WRITE_VREG(HEVC_MPRED_CTRL4, data32);
+	}
+#endif
+}
+
+static void decomp_perfcount_reset(void)
+{
+	if (debug & AVS2_DBG_CACHE)
+		pr_info("[cache_util.c] Entered decomp_perfcount_reset...\n");
+	WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)0x1);
+	WRITE_VREG(HEVCD_MPP_DECOMP_PERFMON_CTL, (unsigned int)0x0);
+	return;
+}
+
+static void mcrcc_perfcount_reset(void)
+{
+	if (debug & AVS2_DBG_CACHE)
+		pr_info("[cache_util.c] Entered mcrcc_perfcount_reset...\n");
+	WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)0x1);
+	WRITE_VREG(HEVCD_MCRCC_PERFMON_CTL, (unsigned int)0x0);
+	return;
+}
+
+static void avs2_init_decoder_hw(struct AVS2Decoder_s *dec)
+{
+	unsigned int data32;
+	unsigned int decode_mode;
+	int i;
+	/*if (debug & AVS2_DBG_BUFMGR_MORE)
+		pr_info("%s\n", __func__);*/
+		data32 = READ_VREG(HEVC_PARSER_INT_CONTROL);
+#if 1
+		/* set bit 31~29 to 3 if HEVC_STREAM_FIFO_CTL[29] is 1 */
+		data32 &= ~(7 << 29);
+		data32 |= (3 << 29);
+#endif
+		data32 = data32 |
+		(1 << 24) |/*stream_buffer_empty_int_amrisc_enable*/
+		(1 << 22) |/*stream_fifo_empty_int_amrisc_enable*/
+		(1 << 7) |/*dec_done_int_cpu_enable*/
+		(1 << 4) |/*startcode_found_int_cpu_enable*/
+		(0 << 3) |/*startcode_found_int_amrisc_enable*/
+		(1 << 0)    /*parser_int_enable*/
+		;
+	WRITE_VREG(HEVC_PARSER_INT_CONTROL, data32);
+
+	data32 = READ_VREG(HEVC_SHIFT_STATUS);
+	data32 = data32 |
+	(0 << 1) |/*emulation_check_off VP9
+		do not have emulation*/
+	(1 << 0)/*startcode_check_on*/
+	;
+	WRITE_VREG(HEVC_SHIFT_STATUS, data32);
+	WRITE_VREG(HEVC_SHIFT_CONTROL,
+		(6 << 20) | /* emu_push_bits  (6-bits for AVS2)*/
+		(0 << 19) | /* emu_3_enable, maybe turned on in microcode*/
+		(0 << 18) | /* emu_2_enable, maybe turned on in microcode*/
+		(0 << 17) | /* emu_1_enable, maybe turned on in microcode*/
+		(0 << 16) | /* emu_0_enable, maybe turned on in microcode*/
+		(0 << 14) | /*disable_start_code_protect*/
+		(3 << 6) | /* sft_valid_wr_position*/
+		(2 << 4) | /* emulate_code_length_sub_1*/
+		(2 << 1) | /* start_code_length_sub_1*/
+		(1 << 0)   /* stream_shift_enable*/
+		);
+
+	WRITE_VREG(HEVC_SHIFT_LENGTH_PROTECT,
+		(0 << 30) |   /*data_protect_fill_00_enable*/
+		(1 << 29)     /*data_protect_fill_ff_enable*/
+		);
+	WRITE_VREG(HEVC_CABAC_CONTROL,
+		(1 << 0)/*cabac_enable*/
+	);
+
+	WRITE_VREG(HEVC_PARSER_CORE_CONTROL,
+		(1 << 0)/* hevc_parser_core_clk_en*/
+	);
+
+
+	WRITE_VREG(HEVC_DEC_STATUS_REG, 0);
+
+	/*Initial IQIT_SCALELUT memory -- just to avoid X in simulation*/
+	if (is_rdma_enable())
+		rdma_back_end_work(dec->rdma_phy_adr, RDMA_SIZE);
+	else {
+		WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);/*cfg_p_addr*/
+		for (i = 0; i < 1024; i++)
+			WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0);
+	}
+
+#ifdef ENABLE_SWAP_TEST
+	WRITE_VREG(HEVC_STREAM_SWAP_TEST, 100);
+#else
+	WRITE_VREG(HEVC_STREAM_SWAP_TEST, 0);
+#endif
+	if (!dec->m_ins_flag)
+		decode_mode = DECODE_MODE_SINGLE;
+	else if (vdec_frame_based(hw_to_vdec(dec)))
+		decode_mode = DECODE_MODE_MULTI_FRAMEBASE;
+	else
+		decode_mode = DECODE_MODE_MULTI_STREAMBASE;
+	if (dec->avs2_dec.bufmgr_error_flag &&
+		(error_handle_policy & 0x1)) {
+		dec->bufmgr_error_count++;
+		dec->avs2_dec.bufmgr_error_flag = 0;
+		if (dec->bufmgr_error_count >
+			(re_search_seq_threshold & 0xff)
+			&& dec->frame_count >
+			((re_search_seq_threshold >> 8) & 0xff)) {
+			struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+			dec->start_decoding_flag = 0;
+			avs2_dec->hd.vec_flag = 1;
+			dec->skip_PB_before_I = 1;
+			avs2_print(dec, 0,
+				"!!Bufmgr error, search seq again (0x%x %d %d)\n",
+				error_handle_policy,
+				dec->frame_count,
+				dec->bufmgr_error_count);
+			dec->bufmgr_error_count = 0;
+		}
+	}
+	decode_mode |= (dec->start_decoding_flag << 16);
+
+	WRITE_VREG(DECODE_MODE, decode_mode);
+	WRITE_VREG(HEVC_DECODE_SIZE, 0);
+	WRITE_VREG(HEVC_DECODE_COUNT, 0);
+
+	/*Send parser_cmd*/
+	WRITE_VREG(HEVC_PARSER_CMD_WRITE, (1 << 16) | (0 << 0));
+	for (i = 0; i < PARSER_CMD_NUMBER; i++)
+		WRITE_VREG(HEVC_PARSER_CMD_WRITE, parser_cmd[i]);
+	WRITE_VREG(HEVC_PARSER_CMD_SKIP_0, PARSER_CMD_SKIP_CFG_0);
+	WRITE_VREG(HEVC_PARSER_CMD_SKIP_1, PARSER_CMD_SKIP_CFG_1);
+	WRITE_VREG(HEVC_PARSER_CMD_SKIP_2, PARSER_CMD_SKIP_CFG_2);
+
+
+	WRITE_VREG(HEVC_PARSER_IF_CONTROL,
+		(1 << 9) | /* parser_alf_if_en*/
+		/*  (1 << 8) |*/ /*sao_sw_pred_enable*/
+		(1 << 5) | /*parser_sao_if_en*/
+		(1 << 2) | /*parser_mpred_if_en*/
+		(1 << 0) /*parser_scaler_if_en*/
+	);
+
+#ifdef MULTI_INSTANCE_SUPPORT
+	WRITE_VREG(HEVC_MPRED_INT_STATUS, (1<<31));
+
+	WRITE_VREG(HEVC_PARSER_RESULT_3, 0xffffffff);
+
+	for (i = 0; i < 8; i++)
+		data32 = READ_VREG(HEVC_MPRED_ABV_START_ADDR);
+
+	WRITE_VREG(DOS_SW_RESET3, (1<<18)); /* reset mpred */
+	WRITE_VREG(DOS_SW_RESET3, 0);
+	WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32);
+	WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32);
+	WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, data32);
+#endif
+	/*End of Multi-instance*/
+	/*Changed to Start MPRED in microcode*/
+	/*
+	pr_info("[test.c] Start MPRED\n");
+	WRITE_VREG(HEVC_MPRED_INT_STATUS,
+	(1<<31)
+	);
+	*/
+
+	/*AVS2 default seq_wq_matrix config*/
+
+	avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+		"Config AVS2 default seq_wq_matrix ...\n");
+	/*4x4*/
+	 /* default seq_wq_matrix_4x4 begin address*/
+	WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 64);
+	for (i = 0; i < 16; i++)
+		WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, g_WqMDefault4x4[i]);
+
+	/*8x8*/
+	/*default seq_wq_matrix_8x8 begin address*/
+	WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);
+	for (i = 0; i < 64; i++)
+		WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, g_WqMDefault8x8[i]);
+
+
+	WRITE_VREG(HEVCD_IPP_TOP_CNTL,
+		(0 << 1) | /*enable ipp*/
+		(1 << 0)   /*software reset ipp and mpp*/
+	);
+	WRITE_VREG(HEVCD_IPP_TOP_CNTL,
+		(1 << 1) | /*enable ipp*/
+		(0 << 0)   /*software reset ipp and mpp*/
+	);
+#if 0
+/*AVS2_10B_NV21*/
+	/*Enable NV21 reference read mode for MC*/
+	WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
+#endif
+	/* Init dblk*/
+	data32 = READ_VREG(HEVC_DBLK_CFGB);
+	data32 |= (2 << 0);
+	/* [3:0] cfg_video_type -> AVS2*/
+
+	data32 &= (~0x300); /*[8]:first write enable (compress)
+					[9]:double write enable (uncompress)*/
+	if (get_double_write_mode(dec) == 0)
+		data32 |= (0x1 << 8); /*enable first write*/
+	else if (get_double_write_mode(dec) == 0x10)
+		data32 |= (0x1 << 9); /*double write only*/
+	else
+		data32 |= ((0x1 << 8) | (0x1 << 9));
+	WRITE_VREG(HEVC_DBLK_CFGB, data32);
+
+	WRITE_VREG(HEVC_DBLK_CFG0, (1 << 0)); /* [0] rst_sync*/
+	avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+		"Bitstream level Init for DBLK .Done.\n");
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
+	    mcrcc_perfcount_reset();
+	    decomp_perfcount_reset();
+	}
+
+	return;
+}
+
+
+#ifdef CONFIG_HEVC_CLK_FORCED_ON
+static void config_avs2_clk_forced_on(void)
+{
+	unsigned int rdata32;
+	/*IQIT*/
+	rdata32 = READ_VREG(HEVC_IQIT_CLK_RST_CTRL);
+	WRITE_VREG(HEVC_IQIT_CLK_RST_CTRL, rdata32 | (0x1 << 2));
+
+	/* DBLK*/
+	rdata32 = READ_VREG(HEVC_DBLK_CFG0);
+	WRITE_VREG(HEVC_DBLK_CFG0, rdata32 | (0x1 << 2));
+
+	/* SAO*/
+	rdata32 = READ_VREG(HEVC_SAO_CTRL1);
+	WRITE_VREG(HEVC_SAO_CTRL1, rdata32 | (0x1 << 2));
+
+	/*MPRED*/
+	rdata32 = READ_VREG(HEVC_MPRED_CTRL1);
+	WRITE_VREG(HEVC_MPRED_CTRL1, rdata32 | (0x1 << 24));
+
+	/* PARSER*/
+	rdata32 = READ_VREG(HEVC_STREAM_CONTROL);
+	WRITE_VREG(HEVC_STREAM_CONTROL, rdata32 | (0x1 << 15));
+	rdata32 = READ_VREG(HEVC_SHIFT_CONTROL);
+	WRITE_VREG(HEVC_SHIFT_CONTROL, rdata32 | (0x1 << 15));
+	rdata32 = READ_VREG(HEVC_CABAC_CONTROL);
+	WRITE_VREG(HEVC_CABAC_CONTROL, rdata32 | (0x1 << 13));
+	rdata32 = READ_VREG(HEVC_PARSER_CORE_CONTROL);
+	WRITE_VREG(HEVC_PARSER_CORE_CONTROL, rdata32 | (0x1 << 15));
+	rdata32 = READ_VREG(HEVC_PARSER_INT_CONTROL);
+	WRITE_VREG(HEVC_PARSER_INT_CONTROL, rdata32 | (0x1 << 15));
+	rdata32 = READ_VREG(HEVC_PARSER_IF_CONTROL);
+	WRITE_VREG(HEVC_PARSER_IF_CONTROL,
+			rdata32 | (0x1 << 6) | (0x1 << 3) | (0x1 << 1));
+
+	/*IPP*/
+	rdata32 = READ_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG);
+	WRITE_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG, rdata32 | 0xffffffff);
+
+	/* MCRCC*/
+	rdata32 = READ_VREG(HEVCD_MCRCC_CTL1);
+	WRITE_VREG(HEVCD_MCRCC_CTL1, rdata32 | (0x1 << 3));
+}
+#endif
+
+static struct AVS2Decoder_s gAVS2Decoder;
+
+static void avs2_local_uninit(struct AVS2Decoder_s *dec)
+{
+	dec->rpm_ptr = NULL;
+	dec->lmem_ptr = NULL;
+	if (dec->rpm_addr) {
+		dma_free_coherent(amports_get_dma_device(),
+						RPM_BUF_SIZE, dec->rpm_addr,
+						dec->rpm_phy_addr);
+		dec->rpm_addr = NULL;
+	}
+
+	if (dec->cuva_addr) {
+		dma_free_coherent(amports_get_dma_device(),
+				dec->cuva_size, dec->cuva_addr,
+					dec->cuva_phy_addr);
+		dec->cuva_addr = NULL;
+	}
+
+	if (dec->lmem_addr) {
+			if (dec->lmem_phy_addr)
+				dma_free_coherent(amports_get_dma_device(),
+						LMEM_BUF_SIZE, dec->lmem_addr,
+						dec->lmem_phy_addr);
+		dec->lmem_addr = NULL;
+	}
+
+#ifdef AVS2_10B_MMU
+	if (dec->frame_mmu_map_addr) {
+		if (dec->frame_mmu_map_phy_addr)
+			dma_free_coherent(amports_get_dma_device(),
+				get_frame_mmu_map_size(dec), dec->frame_mmu_map_addr,
+					dec->frame_mmu_map_phy_addr);
+		dec->frame_mmu_map_addr = NULL;
+	}
+#endif
+
+#ifdef AVS2_10B_MMU_DW
+	if (dec->dw_frame_mmu_map_addr) {
+		if (dec->dw_frame_mmu_map_phy_addr)
+			dma_free_coherent(amports_get_dma_device(),
+				get_frame_mmu_map_size(dec), dec->dw_frame_mmu_map_addr,
+					dec->dw_frame_mmu_map_phy_addr);
+		dec->dw_frame_mmu_map_addr = NULL;
+	}
+#endif
+
+	if (dec->gvs)
+		vfree(dec->gvs);
+	dec->gvs = NULL;
+}
+
+static int avs2_local_init(struct AVS2Decoder_s *dec)
+{
+	int ret = -1;
+	/*int losless_comp_header_size, losless_comp_body_size;*/
+
+	struct BuffInfo_s *cur_buf_info = NULL;
+
+	cur_buf_info = &dec->work_space_buf_store;
+	if (force_bufspec) {
+		memcpy(cur_buf_info, &amvavs2_workbuff_spec[force_bufspec & 0xf],
+		sizeof(struct BuffInfo_s));
+		pr_info("force buffer spec %d\n", force_bufspec & 0xf);
+	} else {
+		if (get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_TM2 && !is_cpu_tm2_revb()) {
+			if (vdec_is_support_4k()) {
+				if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)
+					memcpy(cur_buf_info, &amvavs2_workbuff_spec[2],	/* 8k */
+					sizeof(struct BuffInfo_s));
+				else
+					memcpy(cur_buf_info, &amvavs2_workbuff_spec[1],	/* 4k */
+					sizeof(struct BuffInfo_s));
+			} else
+				memcpy(cur_buf_info, &amvavs2_workbuff_spec[0],/* 1080p */
+				sizeof(struct BuffInfo_s));
+		} else { //get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_TM2 || is_cpu_tm2_revb()
+			if (vdec_is_support_4k()) {
+				memcpy(cur_buf_info, &amvavs2_workbuff_spec[5],	/* 8k */
+				sizeof(struct BuffInfo_s));
+			} else
+				memcpy(cur_buf_info, &amvavs2_workbuff_spec[3],/* 1080p */
+				sizeof(struct BuffInfo_s));
+		}
+	}
+
+	cur_buf_info->start_adr = dec->buf_start;
+#ifndef AVS2_10B_MMU
+	dec->mc_buf_spec.buf_end = dec->buf_start + dec->buf_size;
+#endif
+
+	init_buff_spec(dec, cur_buf_info);
+
+	init_avs2_decoder(&dec->avs2_dec);
+
+#ifdef AVS2_10B_MMU
+	avs2_bufmgr_init(dec, cur_buf_info, NULL);
+#else
+	dec->mc_buf_spec.buf_start = (cur_buf_info->end_adr + 0xffff)
+	    & (~0xffff);
+	dec->mc_buf_spec.buf_size = (dec->mc_buf_spec.buf_end
+	    - dec->mc_buf_spec.buf_start);
+	if (debug) {
+		pr_err("dec->mc_buf_spec.buf_start %x-%x\n",
+			dec->mc_buf_spec.buf_start,
+			dec->mc_buf_spec.buf_start +
+			dec->mc_buf_spec.buf_size);
+	}
+	avs2_bufmgr_init(dec, cur_buf_info, &dec->mc_buf_spec);
+#endif
+	if ((buf_alloc_width & buf_alloc_height) == 0) {
+		if (!vdec_is_support_4k()
+			&& (buf_alloc_width > 1920 &&  buf_alloc_height > 1088)) {
+			buf_alloc_width = 1920;
+			buf_alloc_height = 1088;
+		} else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
+			buf_alloc_width = 3840;
+			buf_alloc_height = 2160;
+		}
+	}
+	dec->init_pic_w = buf_alloc_width ? buf_alloc_width :
+		(dec->vavs2_amstream_dec_info.width ?
+		dec->vavs2_amstream_dec_info.width :
+		dec->work_space_buf->max_width);
+	dec->init_pic_h = buf_alloc_height ? buf_alloc_height :
+		(dec->vavs2_amstream_dec_info.height ?
+		dec->vavs2_amstream_dec_info.height :
+		dec->work_space_buf->max_height);
+
+#ifndef AVS2_10B_MMU
+	init_buf_list(dec);
+#else
+	dec->used_buf_num = max_buf_num + dec->dynamic_buf_margin;
+	if (dec->used_buf_num > MAX_BUF_NUM)
+		dec->used_buf_num = MAX_BUF_NUM;
+	if (dec->used_buf_num > FRAME_BUFFERS)
+		dec->used_buf_num = FRAME_BUFFERS;
+#endif
+	dec->avs2_dec.ref_maxbuffer = dec->used_buf_num - 1;
+	/*init_pic_list(dec);*/
+
+	pts_unstable = ((unsigned long)(dec->vavs2_amstream_dec_info.param)
+			& 0x40) >> 6;
+
+	if ((debug & AVS2_DBG_SEND_PARAM_WITH_REG) == 0) {
+		dec->rpm_addr = dma_alloc_coherent(amports_get_dma_device(),
+			RPM_BUF_SIZE,
+			&dec->rpm_phy_addr, GFP_KERNEL);
+		if (dec->rpm_addr == NULL) {
+			pr_err("%s: failed to alloc rpm buffer\n", __func__);
+			return -1;
+		}
+		avs2_print(dec, AVS2_DBG_BUFMGR,
+			"rpm_phy_addr %x\n", (u32) dec->rpm_phy_addr);
+		dec->rpm_ptr = dec->rpm_addr;
+	}
+
+	if (cuva_buf_size > 0) {
+		dec->cuva_size = AUX_BUF_ALIGN(cuva_buf_size);
+
+		dec->cuva_addr = dma_alloc_coherent(amports_get_dma_device(),
+				dec->cuva_size, &dec->cuva_phy_addr, GFP_KERNEL);
+	        avs2_print(dec, AVS2_DBG_BUFMGR,
+			"%s, cuva_size = %d cuva_phy_addr %x dec->cuva_addr = %px\n",
+			__func__, dec->cuva_size, (u32)dec->cuva_phy_addr, dec->cuva_addr);
+		if (dec->cuva_addr == NULL) {
+			pr_err("%s: failed to alloc cuva buffer\n", __func__);
+			return -1;
+		}
+	}
+
+	dec->lmem_addr = dma_alloc_coherent(amports_get_dma_device(),
+			LMEM_BUF_SIZE,
+			&dec->lmem_phy_addr, GFP_KERNEL);
+	if (dec->lmem_addr == NULL) {
+		pr_err("%s: failed to alloc lmem buffer\n", __func__);
+		return -1;
+	} else
+		avs2_print(dec, AVS2_DBG_BUFMGR,
+			"%s, lmem_phy_addr %x\n",
+			__func__, (u32)dec->lmem_phy_addr);
+	dec->lmem_ptr = dec->lmem_addr;
+
+#ifdef AVS2_10B_MMU
+	if (dec->mmu_enable) {
+		dec->frame_mmu_map_addr = dma_alloc_coherent(amports_get_dma_device(),
+					get_frame_mmu_map_size(dec),
+					&dec->frame_mmu_map_phy_addr, GFP_KERNEL);
+		if (dec->frame_mmu_map_addr == NULL) {
+			pr_err("%s: failed to alloc count_buffer\n", __func__);
+			return -1;
+		}
+		memset(dec->frame_mmu_map_addr, 0, get_frame_mmu_map_size(dec));
+	}
+#endif
+
+#ifdef AVS2_10B_MMU_DW
+	if (dec->dw_mmu_enable) {
+		dec->dw_frame_mmu_map_addr = dma_alloc_coherent(amports_get_dma_device(),
+					get_frame_mmu_map_size(dec),
+					&dec->dw_frame_mmu_map_phy_addr, GFP_KERNEL);
+		if (dec->dw_frame_mmu_map_addr == NULL) {
+			pr_err("%s: failed to alloc count_buffer\n", __func__);
+			return -1;
+		}
+		memset(dec->dw_frame_mmu_map_addr, 0, get_frame_mmu_map_size(dec));
+	}
+#endif
+	ret = 0;
+	return ret;
+}
+
+/********************************************
+ *  Mailbox command
+ ********************************************/
+#define CMD_FINISHED               0
+#define CMD_ALLOC_VIEW             1
+#define CMD_FRAME_DISPLAY          3
+#define CMD_DEBUG                  10
+
+
+#define DECODE_BUFFER_NUM_MAX    32
+#define DISPLAY_BUFFER_NUM       6
+
+#define video_domain_addr(adr) (adr&0x7fffffff)
+#define DECODER_WORK_SPACE_SIZE 0x800000
+
+#define spec2canvas(x)  \
+	(((x)->uv_canvas_index << 16) | \
+	 ((x)->uv_canvas_index << 8)  | \
+	 ((x)->y_canvas_index << 0))
+
+
+static void set_canvas(struct AVS2Decoder_s *dec,
+	struct avs2_frame_s *pic)
+{
+	int canvas_w = ALIGN(pic->pic_w, 64)/4;
+	int canvas_h = ALIGN(pic->pic_h, 32)/4;
+	int blkmode = mem_map_mode;
+	struct vdec_s *vdec = hw_to_vdec(dec);
+	/*CANVAS_BLKMODE_64X32*/
+	if	(pic->double_write_mode) {
+		canvas_w = pic->pic_w	/
+			get_double_write_ratio(pic->double_write_mode);
+		canvas_h = pic->pic_h /
+			get_double_write_ratio(pic->double_write_mode);
+		/*sao_crtl1 aligned with 64*/
+		canvas_w = ALIGN(canvas_w, 64);
+		canvas_h = ALIGN(canvas_h, 32);
+
+		if (vdec->parallel_dec == 1) {
+			if (pic->y_canvas_index == -1)
+				pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id);
+			if (pic->uv_canvas_index == -1)
+				pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id);
+		} else {
+			pic->y_canvas_index = 128 + pic->index * 2;
+			pic->uv_canvas_index = 128 + pic->index * 2 + 1;
+		}
+
+		config_cav_lut_ex(pic->y_canvas_index,
+			pic->dw_y_adr, canvas_w, canvas_h,
+			CANVAS_ADDR_NOWRAP, blkmode, 0x7, VDEC_HEVC);
+		config_cav_lut_ex(pic->uv_canvas_index,
+			pic->dw_u_v_adr,	canvas_w, canvas_h,
+			CANVAS_ADDR_NOWRAP, blkmode, 0x7, VDEC_HEVC);
+#ifdef MULTI_INSTANCE_SUPPORT
+		pic->canvas_config[0].phy_addr = pic->dw_y_adr;
+		pic->canvas_config[0].width = canvas_w;
+		pic->canvas_config[0].height = canvas_h;
+		pic->canvas_config[0].block_mode = blkmode;
+		pic->canvas_config[0].endian = 7;
+
+		pic->canvas_config[1].phy_addr = pic->dw_u_v_adr;
+		pic->canvas_config[1].width = canvas_w;
+		pic->canvas_config[1].height = canvas_h;
+		pic->canvas_config[1].block_mode = blkmode;
+		pic->canvas_config[1].endian = 7;
+#endif
+	} else {
+	#ifndef AVS2_10B_MMU
+		if (vdec->parallel_dec == 1) {
+			if (pic->y_canvas_index == -1)
+				pic->y_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id);
+			if (pic->uv_canvas_index == -1)
+				pic->uv_canvas_index = vdec->get_canvas_ex(CORE_MASK_HEVC, vdec->id);
+		} else {
+			pic->y_canvas_index = 128 + pic->index;
+			pic->uv_canvas_index = 128 + pic->index;
+		}
+
+		config_cav_lut_ex(pic->y_canvas_index,
+			pic->mc_y_adr, canvas_w, canvas_h,
+			CANVAS_ADDR_NOWRAP, blkmode, 0x7, VDEC_HEVC);
+		config_cav_lut_ex(pic->uv_canvas_index,
+			pic->mc_u_v_adr,canvas_w, canvas_h,
+			CANVAS_ADDR_NOWRAP, blkmode, 0x7, VDEC_HEVC);
+	#endif
+	}
+}
+
+static void set_frame_info(struct AVS2Decoder_s *dec, struct vframe_s *vf)
+{
+	unsigned int ar = 0;
+	unsigned int pixel_ratio = 0;;
+
+	vf->duration = dec->frame_dur;
+	vf->duration_pulldown = 0;
+	vf->flag = 0;
+	vf->prop.master_display_colour = dec->vf_dp;
+	if (dec->hdr_flag & HDR_CUVA_MASK)
+		dec->video_signal_type |= 1 << 31;
+	vf->signal_type = dec->video_signal_type;
+
+	avs2_print(dec, AVS2_DBG_HDR_INFO,
+			"signal_typesignal_type 0x%x \n",
+			vf->signal_type);
+
+	pixel_ratio = dec->vavs2_amstream_dec_info.ratio;
+
+	if (dec->vavs2_ratio == 0) {
+			/* always stretch to 16:9 */
+			vf->ratio_control |= (0x90 <<
+					DISP_RATIO_ASPECT_RATIO_BIT);
+			vf->sar_width = 1;
+			vf->sar_height = 1;
+		} else {
+			switch (pixel_ratio) {
+			case 1:
+				vf->sar_width = 1;
+				vf->sar_height = 1;
+				ar = (vf->height * dec->vavs2_ratio) / vf->width;
+				break;
+			case 2:
+				vf->sar_width = 4;
+				vf->sar_height = 3;
+				ar = (vf->height * 3 * dec->vavs2_ratio) / (vf->width * 4);
+				break;
+			case 3:
+				vf->sar_width = 16;
+				vf->sar_height = 9;
+				ar = (vf->height * 9 * dec->vavs2_ratio) / (vf->width * 16);
+				break;
+			case 4:
+				vf->sar_width = 221;
+				vf->sar_height = 100;
+				ar = (vf->height * 100 * dec->vavs2_ratio) / (vf->width *
+						221);
+				break;
+			default:
+				vf->sar_width = 1;
+				vf->sar_height = 1;
+				ar = (vf->height * dec->vavs2_ratio) / vf->width;
+				break;
+			}
+		}
+
+	ar = min_t(u32, ar, DISP_RATIO_ASPECT_RATIO_MAX);
+	vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT);
+
+	vf->sidebind_type = dec->sidebind_type;
+	vf->sidebind_channel_id = dec->sidebind_channel_id;
+
+	return;
+}
+
+static int vavs2_vf_states(struct vframe_states *states, void *op_arg)
+{
+	struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)op_arg;
+
+	states->vf_pool_size = VF_POOL_SIZE;
+	states->buf_free_num = kfifo_len(&dec->newframe_q);
+	states->buf_avail_num = kfifo_len(&dec->display_q);
+
+	if (step == 2)
+		states->buf_avail_num = 0;
+	return 0;
+}
+
+static struct vframe_s *vavs2_vf_peek(void *op_arg)
+{
+	struct vframe_s *vf;
+	struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)op_arg;
+	if (step == 2)
+		return NULL;
+
+	if (force_disp_pic_index & 0x100) {
+		if (force_disp_pic_index & 0x200)
+			return NULL;
+		return &dec->vframe_dummy;
+	}
+
+	if (kfifo_len(&dec->display_q) > VF_POOL_SIZE) {
+		avs2_print(dec, AVS2_DBG_BUFMGR,
+			"kfifo len:%d invaild, peek error\n",
+			kfifo_len(&dec->display_q));
+		return NULL;
+	}
+
+	if (kfifo_peek(&dec->display_q, &vf))
+		return vf;
+
+	return NULL;
+}
+
+static struct avs2_frame_s *get_pic_by_index(
+	struct AVS2Decoder_s *dec, int index)
+{
+	int i;
+	struct avs2_frame_s *pic = NULL;
+	if (index == (dec->used_buf_num - 1))
+		pic = dec->avs2_dec.m_bg;
+	else if (index >= 0	&& index < dec->used_buf_num) {
+		for (i = 0; i < dec->used_buf_num; i++) {
+			if (dec->avs2_dec.fref[i]->index == index)
+				pic = dec->avs2_dec.fref[i];
+		}
+	}
+	return pic;
+}
+
+static struct vframe_s *vavs2_vf_get(void *op_arg)
+{
+	struct vframe_s *vf;
+	struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)op_arg;
+	if (step == 2)
+		return NULL;
+	else if (step == 1)
+			step = 2;
+
+	if (force_disp_pic_index & 0x100) {
+		int idx = force_disp_pic_index & 0xff;
+		struct avs2_frame_s *pic = NULL;
+		if (idx >= 0
+			&& idx < dec->avs2_dec.ref_maxbuffer)
+			pic = get_pic_by_index(dec, idx);
+		if (pic == NULL)
+			return NULL;
+		if (force_disp_pic_index & 0x200)
+			return NULL;
+
+		vf = &dec->vframe_dummy;
+
+		set_vframe(dec, vf, pic, 1);
+
+		force_disp_pic_index |= 0x200;
+		return vf;
+	}
+
+	if (kfifo_get(&dec->display_q, &vf)) {
+		uint8_t index = vf->index & 0xff;
+		ATRACE_COUNTER(dec->disp_q_name, kfifo_len(&dec->display_q));
+		if (index < dec->used_buf_num) {
+			struct avs2_frame_s *pic = get_pic_by_index(dec, index);
+			if (pic == NULL &&
+				(debug & AVS2_DBG_PIC_LEAK)) {
+				int i;
+				avs2_print(dec, 0,
+				"%s error index 0x%x pic not exist\n",
+				__func__, index);
+				dump_pic_list(dec);
+				for (i = 0; i < 10; i++) {
+					pic = get_pic_by_index(dec, index);
+					pr_info("pic = %p\n", pic);
+				}
+
+			if (debug & AVS2_DBG_PIC_LEAK)
+				debug |= AVS2_DBG_PIC_LEAK_WAIT;
+			return NULL;
+		}
+		dec->vf_get_count++;
+		if (pic)
+			avs2_print(dec, AVS2_DBG_BUFMGR,
+			"%s index 0x%x pos %d getcount %d type 0x%x w/h %d/%d, pts %d, %lld\n",
+			__func__, index,
+			pic->imgtr_fwRefDistance_bak,
+			dec->vf_get_count,
+			vf->type,
+			vf->width, vf->height,
+			vf->pts,
+			vf->pts_us64);
+		return vf;
+		}
+	}
+	return NULL;
+}
+
+static void vavs2_vf_put(struct vframe_s *vf, void *op_arg)
+{
+	struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)op_arg;
+	uint8_t index;
+
+	if (vf == (&dec->vframe_dummy))
+		return;
+
+	if (!vf)
+		return;
+
+	index = vf->index & 0xff;
+
+	kfifo_put(&dec->newframe_q, (const struct vframe_s *)vf);
+	ATRACE_COUNTER(dec->new_q_name, kfifo_len(&dec->newframe_q));
+	dec->vf_put_count++;
+	avs2_print(dec, AVS2_DBG_BUFMGR,
+		"%s index putcount 0x%x %d\n",
+		__func__, vf->index,
+		dec->vf_put_count);
+
+	if (index < dec->used_buf_num) {
+		unsigned long flags;
+		struct avs2_frame_s *pic;
+
+		lock_buffer(dec, flags);
+		pic = get_pic_by_index(dec, index);
+		if (pic && pic->vf_ref > 0)
+			pic->vf_ref--;
+		else {
+			if (pic)
+				avs2_print(dec, 0,
+					"%s, error pic (index %d) vf_ref is %d\n",
+					__func__, index, pic->vf_ref);
+			else
+				avs2_print(dec, 0,
+					"%s, error pic (index %d) is NULL\n",
+					__func__, index);
+		}
+		if (dec->wait_buf)
+			WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG,
+						0x1);
+		dec->last_put_idx = index;
+		dec->new_frame_displayed++;
+		unlock_buffer(dec, flags);
+	}
+
+}
+
+static int vavs2_event_cb(int type, void *data, void *private_data)
+{
+	struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)private_data;
+
+	if (type & VFRAME_EVENT_RECEIVER_REQ_STATE) {
+		struct provider_state_req_s *req =
+			(struct provider_state_req_s *)data;
+		if (req->req_type == REQ_STATE_SECURE)
+			req->req_result[0] = vdec_secure(hw_to_vdec(dec));
+		else
+			req->req_result[0] = 0xffffffff;
+	} else if (type & VFRAME_EVENT_RECEIVER_GET_AUX_DATA) {
+		struct provider_aux_req_s *req =
+			(struct provider_aux_req_s *)data;
+		unsigned char index;
+		unsigned long flags;
+		struct avs2_frame_s *pic;
+
+		if (!req->vf) {
+			req->aux_size = dec->vf_put_count;
+			return 0;
+		}
+		lock_buffer(dec, flags);
+		index = req->vf->index & 0xff;
+		req->aux_buf = NULL;
+		req->aux_size = 0;
+		req->format = VFORMAT_AVS2;
+		if (index < dec->used_buf_num) {
+			pic = get_pic_by_index(dec, index);
+			req->aux_buf = pic->cuva_data_buf;
+			req->aux_size = pic->cuva_data_size;
+		}
+		unlock_buffer(dec, flags);
+
+		avs2_print(dec, PRINT_FLAG_VDEC_STATUS,
+		"%s pic 0x%p index %d =>size %d\n",
+		__func__, pic, index, req->aux_size);
+	}
+
+	return 0;
+}
+
+static struct avs2_frame_s *get_disp_pic(struct AVS2Decoder_s *dec)
+{
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	struct avs2_frame_s *pic = NULL;
+	int32_t j;
+	int32_t pre_disp_count_min = 0x7fffffff;
+	for (j = 0; j < avs2_dec->ref_maxbuffer; j++) {
+		if (avs2_dec->fref[j]->to_prepare_disp &&
+			avs2_dec->fref[j]->to_prepare_disp <
+			pre_disp_count_min) {
+			pre_disp_count_min =
+				avs2_dec->fref[j]->to_prepare_disp;
+			pic = avs2_dec->fref[j];
+		}
+	}
+	if (pic)
+		pic->to_prepare_disp = 0;
+
+	return pic;
+
+}
+
+
+
+static void fill_frame_info(struct AVS2Decoder_s *dec,
+	struct avs2_frame_s *pic, unsigned int framesize, unsigned int pts)
+{
+	struct vframe_qos_s *vframe_qos = &dec->vframe_qos;
+
+	if (pic->slice_type == I_IMG)
+		vframe_qos->type = 1;
+	else if (pic->slice_type == P_IMG)
+		vframe_qos->type = 2;
+	else if (pic->slice_type == B_IMG)
+		vframe_qos->type = 3;
+/*
+#define SHOW_QOS_INFO
+*/
+	if (input_frame_based(hw_to_vdec(dec)))
+		vframe_qos->size = pic->frame_size;
+	else
+		vframe_qos->size = framesize;
+	vframe_qos->pts = pts;
+#ifdef SHOW_QOS_INFO
+	avs2_print(dec, 0, "slice:%d\n", pic->slice_type);
+#endif
+
+
+	vframe_qos->max_mv = pic->max_mv;
+	vframe_qos->avg_mv = pic->avg_mv;
+	vframe_qos->min_mv = pic->min_mv;
+#ifdef SHOW_QOS_INFO
+	avs2_print(dec, 0, "mv: max:%d,  avg:%d, min:%d\n",
+			vframe_qos->max_mv,
+			vframe_qos->avg_mv,
+			vframe_qos->min_mv);
+#endif
+
+	vframe_qos->max_qp = pic->max_qp;
+	vframe_qos->avg_qp = pic->avg_qp;
+	vframe_qos->min_qp = pic->min_qp;
+#ifdef SHOW_QOS_INFO
+	avs2_print(dec, 0, "qp: max:%d,  avg:%d, min:%d\n",
+			vframe_qos->max_qp,
+			vframe_qos->avg_qp,
+			vframe_qos->min_qp);
+#endif
+
+	vframe_qos->max_skip = pic->max_skip;
+	vframe_qos->avg_skip = pic->avg_skip;
+	vframe_qos->min_skip = pic->min_skip;
+#ifdef SHOW_QOS_INFO
+	avs2_print(dec, 0, "skip: max:%d,	avg:%d, min:%d\n",
+			vframe_qos->max_skip,
+			vframe_qos->avg_skip,
+			vframe_qos->min_skip);
+#endif
+
+	vframe_qos->num++;
+
+}
+
+static void set_vframe(struct AVS2Decoder_s *dec,
+	struct vframe_s *vf, struct avs2_frame_s *pic, u8 dummy)
+{
+	unsigned long flags;
+	int stream_offset;
+	unsigned int frame_size = 0;
+	int pts_discontinue;
+	struct vdec_s *vdec = hw_to_vdec(dec);
+	stream_offset = pic->stream_offset;
+	avs2_print(dec, AVS2_DBG_BUFMGR,
+		"%s index = %d pos = %d\r\n",
+		__func__, pic->index,
+		pic->imgtr_fwRefDistance);
+
+	if (pic->double_write_mode && (pic->double_write_mode & 0x20) == 0)
+		set_canvas(dec, pic);
+
+	display_frame_count[dec->index]++;
+
+	if (!dummy) {
+#ifdef MULTI_INSTANCE_SUPPORT
+		if (vdec_frame_based(vdec)) {
+			vf->pts = pic->pts;
+			vf->pts_us64 = pic->pts64;
+		} else {
+#endif
+			if ((vdec->vbuf.no_parser == 0) || (vdec->vbuf.use_ptsserv)) {
+			/* if (pts_lookup_offset(PTS_TYPE_VIDEO,
+			   stream_offset, &vf->pts, 0) != 0) { */
+				if (pts_lookup_offset_us64
+					(PTS_TYPE_VIDEO, stream_offset,
+					&vf->pts, &frame_size, 0,
+					 &vf->pts_us64) != 0) {
+#ifdef DEBUG_PTS
+					dec->pts_missed++;
+#endif
+					vf->pts = 0;
+					vf->pts_us64 = 0;
+				}
+			}
+		}
+#ifdef DEBUG_PTS
+		else
+			dec->pts_hit++;
+#endif
+		if (pts_unstable)
+			dec->pts_mode = PTS_NONE_REF_USE_DURATION;
+
+		fill_frame_info(dec, pic, frame_size, vf->pts);
+
+		if ((dec->pts_mode == PTS_NORMAL) && (vf->pts != 0)
+			&& dec->get_frame_dur) {
+			int pts_diff = (int)vf->pts - dec->last_lookup_pts;
+
+			if (pts_diff < 0) {
+				dec->pts_mode_switching_count++;
+				dec->pts_mode_recovery_count = 0;
+
+				if (dec->pts_mode_switching_count >=
+					PTS_MODE_SWITCHING_THRESHOLD) {
+					dec->pts_mode =
+						PTS_NONE_REF_USE_DURATION;
+					pr_info
+					("HEVC: switch to n_d mode.\n");
+				}
+
+			} else {
+				int p = PTS_MODE_SWITCHING_RECOVERY_THREASHOLD;
+				dec->pts_mode_recovery_count++;
+				if (dec->pts_mode_recovery_count > p) {
+					dec->pts_mode_switching_count = 0;
+					dec->pts_mode_recovery_count = 0;
+				}
+			}
+		}
+
+		pts_discontinue =
+			(abs(dec->last_pts  - vf->pts) >=
+			 tsync_vpts_discontinuity_margin());
+
+		if (vf->pts != 0)
+			dec->last_lookup_pts = vf->pts;
+
+		if ((dec->pts_mode == PTS_NONE_REF_USE_DURATION)
+			&& ((pic->slice_type != I_IMG) || (!pts_discontinue &&
+			!first_pts_checkin_complete(PTS_TYPE_AUDIO))))
+			vf->pts = dec->last_pts + DUR2PTS(dec->frame_dur);
+		dec->last_pts = vf->pts;
+
+		if (vf->pts_us64 != 0)
+			dec->last_lookup_pts_us64 = vf->pts_us64;
+
+		if ((dec->pts_mode == PTS_NONE_REF_USE_DURATION)
+			&& ((pic->slice_type != I_IMG) || (!pts_discontinue &&
+			!first_pts_checkin_complete(PTS_TYPE_AUDIO)))) {
+			vf->pts_us64 =
+				dec->last_pts_us64 +
+				(DUR2PTS(dec->frame_dur) * 100 / 9);
+		}
+
+		dec->last_pts_us64 = vf->pts_us64;
+		avs2_print(dec, AVS2_DBG_OUT_PTS,
+			"avs2 dec out pts: vf->pts=%d, vf->pts_us64 = %lld\n",
+			vf->pts, vf->pts_us64);
+		}
+
+		vf->index = 0xff00 | pic->index;
+
+		if (pic->double_write_mode & 0x10) {
+			/* double write only */
+			vf->compBodyAddr = 0;
+			vf->compHeadAddr = 0;
+		} else {
+#ifdef AVS2_10B_MMU
+			vf->compBodyAddr = 0;
+			vf->compHeadAddr = pic->header_adr;
+#ifdef AVS2_10B_MMU_DW
+			vf->dwBodyAddr = 0;
+			vf->dwHeadAddr = 0;
+			if (pic->double_write_mode & 0x20) {
+				u32 mode = pic->double_write_mode & 0xf;
+				if (mode == 5 || mode == 3)
+					vf->dwHeadAddr = pic->dw_header_adr;
+				else if ((mode == 1 || mode == 2 || mode == 4)
+					&& ((debug & AVS2_DBG_OUT_PTS) == 0)) {
+					vf->compHeadAddr = pic->dw_header_adr;
+					pr_info("Use dw mmu for display\n");
+				}
+			}
+#endif
+
+#else
+			vf->compBodyAddr = pic->mc_y_adr; /*body adr*/
+			vf->compHeadAddr = pic->mc_y_adr + pic->comp_body_size;
+#endif
+		}
+		if (pic->double_write_mode &&
+			((pic->double_write_mode & 0x20) == 0)) {
+			vf->type = VIDTYPE_PROGRESSIVE |
+				VIDTYPE_VIU_FIELD;
+			vf->type |= VIDTYPE_VIU_NV21;
+			if (pic->double_write_mode == 3) {
+				vf->type |= VIDTYPE_COMPRESS;
+#ifdef AVS2_10B_MMU
+				vf->type |= VIDTYPE_SCATTER;
+#endif
+			}
+#ifdef MULTI_INSTANCE_SUPPORT
+			if (dec->m_ins_flag) {
+					vf->canvas0Addr = vf->canvas1Addr = -1;
+					vf->plane_num = 2;
+					vf->canvas0_config[0] =
+						pic->canvas_config[0];
+					vf->canvas0_config[1] =
+						pic->canvas_config[1];
+
+					vf->canvas1_config[0] =
+						pic->canvas_config[0];
+					vf->canvas1_config[1] =
+						pic->canvas_config[1];
+
+			} else
+#endif
+				vf->canvas0Addr = vf->canvas1Addr =
+					spec2canvas(pic);
+		} else {
+			vf->canvas0Addr = vf->canvas1Addr = 0;
+			vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD;
+#ifdef AVS2_10B_MMU
+			vf->type |= VIDTYPE_SCATTER;
+#endif
+		}
+
+		switch (pic->bit_depth) {
+		case AVS2_BITS_8:
+			vf->bitdepth = BITDEPTH_Y8 |
+				BITDEPTH_U8 | BITDEPTH_V8;
+			break;
+		case AVS2_BITS_10:
+		case AVS2_BITS_12:
+			vf->bitdepth = BITDEPTH_Y10 |
+				BITDEPTH_U10 | BITDEPTH_V10;
+			break;
+		default:
+			vf->bitdepth = BITDEPTH_Y10 |
+				BITDEPTH_U10 | BITDEPTH_V10;
+			break;
+		}
+		if ((vf->type & VIDTYPE_COMPRESS) == 0)
+			vf->bitdepth =
+				BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8;
+		if (pic->bit_depth == AVS2_BITS_8)
+			vf->bitdepth |= BITDEPTH_SAVING_MODE;
+
+		set_frame_info(dec, vf);
+		/* if((vf->width!=pic->width)|
+			(vf->height!=pic->height)) */
+		/* pr_info("aaa: %d/%d, %d/%d\n",
+		   vf->width,vf->height, pic->width,
+			pic->height); */
+		vf->width = pic->pic_w /
+			get_double_write_ratio(pic->double_write_mode);
+		vf->height = pic->pic_h /
+			get_double_write_ratio(pic->double_write_mode);
+		if (force_w_h != 0) {
+			vf->width = (force_w_h >> 16) & 0xffff;
+			vf->height = force_w_h & 0xffff;
+		}
+		if ((pic->double_write_mode & 0x20) &&
+			((pic->double_write_mode & 0xf) == 2 ||
+			(pic->double_write_mode & 0xf) == 4)) {
+			vf->compWidth = pic->pic_w /
+				get_double_write_ratio(
+					pic->double_write_mode & 0xf);
+			vf->compHeight = pic->pic_h /
+				get_double_write_ratio(
+					pic->double_write_mode & 0xf);
+		} else {
+			vf->compWidth = pic->pic_w;
+			vf->compHeight = pic->pic_h;
+		}
+		if (force_fps & 0x100) {
+			u32 rate = force_fps & 0xff;
+			if (rate)
+				vf->duration = 96000/rate;
+			else
+				vf->duration = 0;
+		}
+#ifdef AVS2_10B_MMU
+		if (vf->type & VIDTYPE_SCATTER) {
+#ifdef AVS2_10B_MMU_DW
+		if (pic->double_write_mode & 0x20) {
+			vf->mem_handle =
+				decoder_mmu_box_get_mem_handle(
+					dec->dw_mmu_box, pic->index);
+			vf->mem_head_handle =
+				decoder_bmmu_box_get_mem_handle(
+					dec->bmmu_box,
+					HEADER_BUFFER_IDX(pic->BUF_index));
+			vf->mem_dw_handle = NULL;
+		} else
+#endif
+		{
+			vf->mem_handle = decoder_mmu_box_get_mem_handle(
+				dec->mmu_box,
+				pic->index);
+			vf->mem_head_handle = decoder_bmmu_box_get_mem_handle(
+				dec->bmmu_box,
+				HEADER_BUFFER_IDX(pic->index));
+		}
+		} else {
+			vf->mem_handle = decoder_bmmu_box_get_mem_handle(
+				dec->bmmu_box,
+				VF_BUFFER_IDX(pic->index));
+			vf->mem_head_handle = decoder_bmmu_box_get_mem_handle(
+				dec->bmmu_box,
+				HEADER_BUFFER_IDX(pic->index));
+		}
+#else
+		vf->mem_handle = decoder_bmmu_box_get_mem_handle(
+			dec->bmmu_box,
+			VF_BUFFER_IDX(pic->index));
+#endif
+	if (!vdec->vbuf.use_ptsserv && vdec_stream_based(vdec)) {
+		vf->pts_us64 = stream_offset;
+		vf->pts = 0;
+	}
+	if (!dummy) {
+		lock_buffer(dec, flags);
+		pic->vf_ref = 1;
+		unlock_buffer(dec, flags);
+	}
+	dec->vf_pre_count++;
+}
+
+static inline void dec_update_gvs(struct AVS2Decoder_s *dec)
+{
+	if (dec->gvs->frame_height != dec->frame_height) {
+		dec->gvs->frame_width = dec->frame_width;
+		dec->gvs->frame_height = dec->frame_height;
+	}
+	if (dec->gvs->frame_dur != dec->frame_dur) {
+		dec->gvs->frame_dur = dec->frame_dur;
+		if (dec->frame_dur != 0)
+			dec->gvs->frame_rate = ((96000 * 10 / dec->frame_dur) % 10) < 5 ?
+					96000 / dec->frame_dur : (96000 / dec->frame_dur +1);
+		else
+			dec->gvs->frame_rate = -1;
+	}
+	dec->gvs->status = dec->stat | dec->fatal_error;
+}
+
+static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec)
+{
+#ifndef NO_DISPLAY
+	struct vframe_s *vf = NULL;
+	/*unsigned short slice_type;*/
+	struct avs2_frame_s *pic;
+	struct vdec_s *pvdec = hw_to_vdec(dec);
+	while (1) {
+		pic = get_disp_pic(dec);
+		if (pic == NULL)
+			break;
+
+		if (force_disp_pic_index & 0x100) {
+			/*recycle directly*/
+			continue;
+		}
+
+		if (pic->error_mark) {
+			avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+				"!!!error pic, skip\n",
+				0);
+			continue;
+		}
+
+		if (dec->start_decoding_flag != 0) {
+			if (dec->skip_PB_before_I &&
+				pic->slice_type != I_IMG) {
+				avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+					"!!!slice type %d (not I) skip\n",
+					0, pic->slice_type);
+				continue;
+			}
+			dec->skip_PB_before_I = 0;
+		}
+
+		if (kfifo_get(&dec->newframe_q, &vf) == 0) {
+			pr_info("fatal error, no available buffer slot.");
+			return -1;
+		}
+
+		if (vf) {
+			struct vdec_info tmp4x;
+			int stream_offset = pic->stream_offset;
+			set_vframe(dec, vf, pic, 0);
+			decoder_do_frame_check(pvdec, vf);
+			vdec_vframe_ready(pvdec, vf);
+			kfifo_put(&dec->display_q, (const struct vframe_s *)vf);
+			ATRACE_COUNTER(dec->pts_name, vf->pts);
+			ATRACE_COUNTER(dec->new_q_name, kfifo_len(&dec->newframe_q));
+			ATRACE_COUNTER(dec->disp_q_name, kfifo_len(&dec->display_q));
+
+			dec_update_gvs(dec);
+			/*count info*/
+			vdec_count_info(dec->gvs, 0, stream_offset);
+		if (stream_offset) {
+			if (pic->slice_type == I_IMG) {
+				dec->gvs->i_decoded_frames++;
+			} else if (pic->slice_type == P_IMG) {
+				dec->gvs->p_decoded_frames++;
+			} else if (pic->slice_type == B_IMG) {
+				dec->gvs->b_decoded_frames++;
+			}
+		}
+			memcpy(&tmp4x, dec->gvs, sizeof(struct vdec_info));
+			tmp4x.bit_depth_luma = bit_depth_luma;
+			tmp4x.bit_depth_chroma = bit_depth_chroma;
+			tmp4x.double_write_mode = pic->double_write_mode;
+			vdec_fill_vdec_frame(pvdec, &dec->vframe_qos, &tmp4x, vf, pic->hw_decode_time);
+			pvdec->vdec_fps_detec(pvdec->id);
+			if (without_display_mode == 0) {
+				vf_notify_receiver(dec->provider_name,
+				VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+			} else
+				vavs2_vf_put(vavs2_vf_get(dec), dec);
+		}
+	}
+/*!NO_DISPLAY*/
+#endif
+	return 0;
+}
+
+static void get_rpm_param(union param_u *params)
+{
+	int i;
+	unsigned int data32;
+	if (debug & AVS2_DBG_BUFMGR)
+		pr_info("enter %s\r\n", __func__);
+	for (i = 0; i < (RPM_END - RPM_BEGIN); i++) {
+		do {
+			data32 = READ_VREG(RPM_CMD_REG);
+			/*pr_info("%x\n", data32);*/
+		} while ((data32 & 0x10000) == 0);
+		params->l.data[i] = data32&0xffff;
+		/*pr_info("%x\n", data32);*/
+		WRITE_VREG(RPM_CMD_REG, 0);
+	}
+	if (debug & AVS2_DBG_BUFMGR)
+		pr_info("leave %s\r\n", __func__);
+}
+static void debug_buffer_mgr_more(struct AVS2Decoder_s *dec)
+{
+	int i;
+	if (!(debug & AVS2_DBG_BUFMGR_MORE))
+		return;
+	pr_info("avs2_param: (%d)\n", dec->avs2_dec.img.number);
+	for (i = 0; i < (RPM_END-RPM_BEGIN); i++) {
+		pr_info("%04x ", dec->avs2_dec.param.l.data[i]);
+		if (((i + 1) & 0xf) == 0)
+			pr_info("\n");
+	}
+}
+
+#ifdef AVS2_10B_MMU
+static void avs2_recycle_mmu_buf_tail(struct AVS2Decoder_s *dec)
+{
+	if (dec->cur_fb_idx_mmu != INVALID_IDX) {
+		if (dec->used_4k_num == -1) {
+			dec->used_4k_num =
+			(READ_VREG(HEVC_SAO_MMU_STATUS) >> 16);
+			if (dec->m_ins_flag)
+				hevc_mmu_dma_check(hw_to_vdec(dec));
+			decoder_mmu_box_free_idx_tail(dec->mmu_box,
+			dec->cur_fb_idx_mmu, dec->used_4k_num);
+		}
+		dec->cur_fb_idx_mmu = INVALID_IDX;
+		dec->used_4k_num = -1;
+	}
+}
+
+static void avs2_recycle_mmu_buf(struct AVS2Decoder_s *dec)
+{
+	if (dec->cur_fb_idx_mmu != INVALID_IDX) {
+		decoder_mmu_box_free_idx(dec->mmu_box,
+			dec->cur_fb_idx_mmu);
+
+		dec->cur_fb_idx_mmu = INVALID_IDX;
+		dec->used_4k_num = -1;
+	}
+}
+#endif
+
+static void dec_again_process(struct AVS2Decoder_s *dec)
+{
+	amhevc_stop();
+	dec->dec_result = DEC_RESULT_AGAIN;
+	if (dec->process_state ==
+		PROC_STATE_DECODING) {
+		dec->process_state =
+		PROC_STATE_DECODE_AGAIN;
+	} else if (dec->process_state ==
+		PROC_STATE_HEAD_DONE) {
+		dec->process_state =
+		PROC_STATE_HEAD_AGAIN;
+	}
+	dec->next_again_flag = 1;
+	reset_process_time(dec);
+	vdec_schedule_work(&dec->work);
+}
+
+static uint32_t log2i(uint32_t val)
+{
+	uint32_t ret = -1;
+	while (val != 0) {
+		val >>= 1;
+		ret++;
+	}
+	return ret;
+}
+
+static void check_pic_error(struct AVS2Decoder_s *dec,
+	struct avs2_frame_s *pic)
+{
+	if (pic->decoded_lcu == 0) {
+		pic->decoded_lcu =
+			(READ_VREG(HEVC_PARSER_LCU_START)
+					& 0xffffff) + 1;
+	}
+	if (pic->decoded_lcu != dec->avs2_dec.lcu_total) {
+		avs2_print(dec, AVS2_DBG_BUFMGR,
+			"%s error pic(index %d imgtr_fwRefDistance %d) decoded lcu %d (total %d)\n",
+			__func__, pic->index, pic->imgtr_fwRefDistance,
+			pic->decoded_lcu, dec->avs2_dec.lcu_total);
+		pic->error_mark = 1;
+	} else {
+		avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+			"%s pic(index %d imgtr_fwRefDistance %d) decoded lcu %d (total %d)\n",
+			__func__, pic->index, pic->imgtr_fwRefDistance,
+			pic->decoded_lcu, dec->avs2_dec.lcu_total);
+
+	}
+}
+static void update_decoded_pic(struct AVS2Decoder_s *dec)
+{
+	struct avs2_frame_s *pic = dec->avs2_dec.hc.cur_pic;
+	if (pic) {
+		dec->avs2_dec.hc.cur_pic->decoded_lcu =
+			(READ_VREG(HEVC_PARSER_LCU_START)
+					& 0xffffff) + 1;
+		avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+			"%s pic(index %d imgtr_fwRefDistance %d) decoded lcu %d (total %d)\n",
+			__func__, pic->index, pic->imgtr_fwRefDistance,
+			pic->decoded_lcu, dec->avs2_dec.lcu_total);
+	}
+}
+/* +[SE] [BUG][BUG-171463][chuanqi.wang]: get frame rate by video sequeue*/
+static int get_frame_rate(union param_u *params, struct AVS2Decoder_s *dec)
+{
+	int tmp = 0;
+
+	switch (params->p.frame_rate_code) {
+	case 1:
+	case 2:
+		tmp = 24;
+		break;
+	case 3:
+		tmp =  25;
+		break;
+	case 4:
+	case 5:
+		tmp =  30;
+		break;
+	case 6:
+		tmp =  50;
+		break;
+	case 7:
+	case 8:
+		tmp =  60;
+		break;
+	case 9:
+		tmp =  100;
+		break;
+	case 10:
+		tmp = 120;
+		break;
+	default:
+		tmp =  25;
+		break;
+	}
+
+	if (!params->p.progressive_sequence)
+		tmp = tmp / 2;
+	dec->frame_dur = div_u64(96000ULL, tmp);
+	dec->get_frame_dur = true;
+	/*avs2_print(dec, 0, "avs2 frame_dur:%d,progressive:%d\n", dec->frame_dur, params->p.progressive_sequence);*/
+	return 0;
+}
+
+
+#define HEVC_MV_INFO   0x310d
+#define HEVC_QP_INFO   0x3137
+#define HEVC_SKIP_INFO 0x3136
+
+/* only when we decoded one field or one frame,
+we can call this function to get qos info*/
+static void get_picture_qos_info(struct AVS2Decoder_s *dec)
+{
+	struct avs2_frame_s *picture = dec->avs2_dec.hc.cur_pic;
+	struct vdec_s *vdec = hw_to_vdec(dec);
+	if (!picture) {
+		avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+			"%s decode picture is none exist\n");
+
+		return;
+	}
+	if (vdec->mvfrm) {
+		picture->frame_size = vdec->mvfrm->frame_size;
+		picture->hw_decode_time =
+		local_clock() - vdec->mvfrm->hw_decode_start;
+	}
+
+/*
+#define DEBUG_QOS
+*/
+
+	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) {
+		unsigned char a[3];
+		unsigned char i, j, t;
+		unsigned long  data;
+
+		data = READ_VREG(HEVC_MV_INFO);
+		if (picture->slice_type == I_IMG)
+			data = 0;
+		a[0] = data & 0xff;
+		a[1] = (data >> 8) & 0xff;
+		a[2] = (data >> 16) & 0xff;
+
+		for (i = 0; i < 3; i++)
+			for (j = i+1; j < 3; j++) {
+				if (a[j] < a[i]) {
+					t = a[j];
+					a[j] = a[i];
+					a[i] = t;
+				} else if (a[j] == a[i]) {
+					a[i]++;
+					t = a[j];
+					a[j] = a[i];
+					a[i] = t;
+				}
+			}
+		picture->max_mv = a[2];
+		picture->avg_mv = a[1];
+		picture->min_mv = a[0];
+#ifdef DEBUG_QOS
+		avs2_print(dec, 0, "mv data %x  a[0]= %x a[1]= %x a[2]= %x\n",
+			data, a[0], a[1], a[2]);
+#endif
+
+		data = READ_VREG(HEVC_QP_INFO);
+		a[0] = data & 0x1f;
+		a[1] = (data >> 8) & 0x3f;
+		a[2] = (data >> 16) & 0x7f;
+
+		for (i = 0; i < 3; i++)
+			for (j = i+1; j < 3; j++) {
+				if (a[j] < a[i]) {
+					t = a[j];
+					a[j] = a[i];
+					a[i] = t;
+				} else if (a[j] == a[i]) {
+					a[i]++;
+					t = a[j];
+					a[j] = a[i];
+					a[i] = t;
+				}
+			}
+		picture->max_qp = a[2];
+		picture->avg_qp = a[1];
+		picture->min_qp = a[0];
+#ifdef DEBUG_QOS
+		avs2_print(dec, 0, "qp data %x  a[0]= %x a[1]= %x a[2]= %x\n",
+			data, a[0], a[1], a[2]);
+#endif
+
+		data = READ_VREG(HEVC_SKIP_INFO);
+		a[0] = data & 0x1f;
+		a[1] = (data >> 8) & 0x3f;
+		a[2] = (data >> 16) & 0x7f;
+
+		for (i = 0; i < 3; i++)
+			for (j = i+1; j < 3; j++) {
+				if (a[j] < a[i]) {
+					t = a[j];
+					a[j] = a[i];
+					a[i] = t;
+				} else if (a[j] == a[i]) {
+					a[i]++;
+					t = a[j];
+					a[j] = a[i];
+					a[i] = t;
+				}
+			}
+		picture->max_skip = a[2];
+		picture->avg_skip = a[1];
+		picture->min_skip = a[0];
+
+#ifdef DEBUG_QOS
+		avs2_print(dec, 0,
+			"skip data %x  a[0]= %x a[1]= %x a[2]= %x\n",
+			data, a[0], a[1], a[2]);
+#endif
+	} else {
+		uint32_t blk88_y_count;
+		uint32_t blk88_c_count;
+		uint32_t blk22_mv_count;
+		uint32_t rdata32;
+		int32_t mv_hi;
+		int32_t mv_lo;
+		uint32_t rdata32_l;
+		uint32_t mvx_L0_hi;
+		uint32_t mvy_L0_hi;
+		uint32_t mvx_L1_hi;
+		uint32_t mvy_L1_hi;
+		int64_t value;
+		uint64_t temp_value;
+#ifdef DEBUG_QOS
+		int pic_number = 0;
+#endif
+
+		picture->max_mv = 0;
+		picture->avg_mv = 0;
+		picture->min_mv = 0;
+
+		picture->max_skip = 0;
+		picture->avg_skip = 0;
+		picture->min_skip = 0;
+
+		picture->max_qp = 0;
+		picture->avg_qp = 0;
+		picture->min_qp = 0;
+
+
+
+#ifdef DEBUG_QOS
+		avs2_print(dec, 0, "slice_type:%d, poc:%d\n",
+			picture->slice_type,
+			pic_number);
+#endif
+		/* set rd_idx to 0 */
+	    WRITE_VREG(HEVC_PIC_QUALITY_CTRL, 0);
+
+	    blk88_y_count = READ_VREG(HEVC_PIC_QUALITY_DATA);
+	    if (blk88_y_count == 0) {
+#ifdef DEBUG_QOS
+			avs2_print(dec, 0,
+				"[Picture %d Quality] NO Data yet.\n",
+				pic_number);
+#endif
+			/* reset all counts */
+			WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8));
+			return;
+	    }
+		/* qp_y_sum */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0,
+			"[Picture %d Quality] Y QP AVG : %d (%d/%d)\n",
+			pic_number, rdata32/blk88_y_count,
+			rdata32, blk88_y_count);
+#endif
+		picture->avg_qp = rdata32/blk88_y_count;
+		/* intra_y_count */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0,
+			"[Picture %d Quality] Y intra rate : %d%c (%d)\n",
+			pic_number, rdata32*100/blk88_y_count,
+			'%', rdata32);
+#endif
+		/* skipped_y_count */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0,
+			"[Picture %d Quality] Y skipped rate : %d%c (%d)\n",
+			pic_number, rdata32*100/blk88_y_count,
+			'%', rdata32);
+#endif
+		picture->avg_skip = rdata32*100/blk88_y_count;
+		/* coeff_non_zero_y_count */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0,
+			"[Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n",
+			pic_number, (100 - rdata32*100/(blk88_y_count*1)),
+			'%', rdata32);
+#endif
+		/* blk66_c_count */
+	    blk88_c_count = READ_VREG(HEVC_PIC_QUALITY_DATA);
+	    if (blk88_c_count == 0) {
+#ifdef DEBUG_QOS
+			avs2_print(dec, 0,
+				"[Picture %d Quality] NO Data yet.\n",
+				pic_number);
+#endif
+			/* reset all counts */
+			WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8));
+			return;
+	    }
+		/* qp_c_sum */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0,
+			"[Picture %d Quality] C QP AVG : %d (%d/%d)\n",
+			pic_number, rdata32/blk88_c_count,
+			rdata32, blk88_c_count);
+#endif
+		/* intra_c_count */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0,
+			"[Picture %d Quality] C intra rate : %d%c (%d)\n",
+			pic_number, rdata32*100/blk88_c_count,
+			'%', rdata32);
+#endif
+		/* skipped_cu_c_count */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0,
+			"[Picture %d Quality] C skipped rate : %d%c (%d)\n",
+			pic_number, rdata32*100/blk88_c_count,
+			'%', rdata32);
+#endif
+		/* coeff_non_zero_c_count */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0,
+			"[Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n",
+			pic_number, (100 - rdata32*100/(blk88_c_count*1)),
+			'%', rdata32);
+#endif
+
+		/* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0],
+		1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0, "[Picture %d Quality] Y QP min : %d\n",
+			pic_number, (rdata32>>0)&0xff);
+#endif
+		picture->min_qp = (rdata32>>0)&0xff;
+
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0, "[Picture %d Quality] Y QP max : %d\n",
+			pic_number, (rdata32>>8)&0xff);
+#endif
+		picture->max_qp = (rdata32>>8)&0xff;
+
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0, "[Picture %d Quality] C QP min : %d\n",
+			pic_number, (rdata32>>16)&0xff);
+	    avs2_print(dec, 0, "[Picture %d Quality] C QP max : %d\n",
+			pic_number, (rdata32>>24)&0xff);
+#endif
+
+		/* blk22_mv_count */
+	    blk22_mv_count = READ_VREG(HEVC_PIC_QUALITY_DATA);
+	    if (blk22_mv_count == 0) {
+#ifdef DEBUG_QOS
+			avs2_print(dec, 0,
+				"[Picture %d Quality] NO MV Data yet.\n",
+				pic_number);
+#endif
+			/* reset all counts */
+			WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8));
+			return;
+	    }
+		/* mvy_L1_count[39:32], mvx_L1_count[39:32],
+		mvy_L0_count[39:32], mvx_L0_count[39:32] */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+	    /* should all be 0x00 or 0xff */
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0,
+			"[Picture %d Quality] MV AVG High Bits: 0x%X\n",
+			pic_number, rdata32);
+#endif
+	    mvx_L0_hi = ((rdata32>>0)&0xff);
+	    mvy_L0_hi = ((rdata32>>8)&0xff);
+	    mvx_L1_hi = ((rdata32>>16)&0xff);
+	    mvy_L1_hi = ((rdata32>>24)&0xff);
+
+		/* mvx_L0_count[31:0] */
+	    rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA);
+		temp_value = mvx_L0_hi;
+		temp_value = (temp_value << 32) | rdata32_l;
+
+		if (mvx_L0_hi & 0x80)
+			value = 0xFFFFFFF000000000 | temp_value;
+		else
+			value = temp_value;
+		 value = div_s64(value, blk22_mv_count);
+#ifdef DEBUG_QOS
+		avs2_print(dec, 0,
+			"[Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n",
+			pic_number, (int)value,
+			value, blk22_mv_count);
+#endif
+		picture->avg_mv = value;
+
+		/* mvy_L0_count[31:0] */
+	    rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA);
+		temp_value = mvy_L0_hi;
+		temp_value = (temp_value << 32) | rdata32_l;
+
+		if (mvy_L0_hi & 0x80)
+			value = 0xFFFFFFF000000000 | temp_value;
+		else
+			value = temp_value;
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0,
+			"[Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n",
+			pic_number, rdata32_l/blk22_mv_count,
+			value, blk22_mv_count);
+#endif
+
+		/* mvx_L1_count[31:0] */
+	    rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA);
+		temp_value = mvx_L1_hi;
+		temp_value = (temp_value << 32) | rdata32_l;
+		if (mvx_L1_hi & 0x80)
+			value = 0xFFFFFFF000000000 | temp_value;
+		else
+			value = temp_value;
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0,
+			"[Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n",
+			pic_number, rdata32_l/blk22_mv_count,
+			value, blk22_mv_count);
+#endif
+
+		/* mvy_L1_count[31:0] */
+	    rdata32_l = READ_VREG(HEVC_PIC_QUALITY_DATA);
+		temp_value = mvy_L1_hi;
+		temp_value = (temp_value << 32) | rdata32_l;
+		if (mvy_L1_hi & 0x80)
+			value = 0xFFFFFFF000000000 | temp_value;
+		else
+			value = temp_value;
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0,
+			"[Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n",
+			pic_number, rdata32_l/blk22_mv_count,
+			value, blk22_mv_count);
+#endif
+
+		/* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]}  */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+	    mv_hi = (rdata32>>16)&0xffff;
+	    if (mv_hi & 0x8000)
+			mv_hi = 0x8000 - mv_hi;
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0, "[Picture %d Quality] MVX_L0 MAX : %d\n",
+			pic_number, mv_hi);
+#endif
+		picture->max_mv = mv_hi;
+
+	    mv_lo = (rdata32>>0)&0xffff;
+	    if (mv_lo & 0x8000)
+			mv_lo = 0x8000 - mv_lo;
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0, "[Picture %d Quality] MVX_L0 MIN : %d\n",
+			pic_number, mv_lo);
+#endif
+		picture->min_mv = mv_lo;
+
+#ifdef DEBUG_QOS
+		/* {mvy_L0_max, mvy_L0_min} */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+	    mv_hi = (rdata32>>16)&0xffff;
+	    if (mv_hi & 0x8000)
+			mv_hi = 0x8000 - mv_hi;
+	    avs2_print(dec, 0, "[Picture %d Quality] MVY_L0 MAX : %d\n",
+			pic_number, mv_hi);
+
+
+	    mv_lo = (rdata32>>0)&0xffff;
+	    if (mv_lo & 0x8000)
+			mv_lo = 0x8000 - mv_lo;
+
+	    avs2_print(dec, 0, "[Picture %d Quality] MVY_L0 MIN : %d\n",
+			pic_number, mv_lo);
+
+
+		/* {mvx_L1_max, mvx_L1_min} */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+	    mv_hi = (rdata32>>16)&0xffff;
+	    if (mv_hi & 0x8000)
+			mv_hi = 0x8000 - mv_hi;
+
+	    avs2_print(dec, 0, "[Picture %d Quality] MVX_L1 MAX : %d\n",
+			pic_number, mv_hi);
+
+
+	    mv_lo = (rdata32>>0)&0xffff;
+	    if (mv_lo & 0x8000)
+			mv_lo = 0x8000 - mv_lo;
+
+	    avs2_print(dec, 0, "[Picture %d Quality] MVX_L1 MIN : %d\n",
+			pic_number, mv_lo);
+
+
+		/* {mvy_L1_max, mvy_L1_min} */
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_DATA);
+	    mv_hi = (rdata32>>16)&0xffff;
+	    if (mv_hi & 0x8000)
+			mv_hi = 0x8000 - mv_hi;
+
+	    avs2_print(dec, 0, "[Picture %d Quality] MVY_L1 MAX : %d\n",
+			pic_number, mv_hi);
+
+	    mv_lo = (rdata32>>0)&0xffff;
+	    if (mv_lo & 0x8000)
+			mv_lo = 0x8000 - mv_lo;
+
+	    avs2_print(dec, 0, "[Picture %d Quality] MVY_L1 MIN : %d\n",
+			pic_number, mv_lo);
+#endif
+
+	    rdata32 = READ_VREG(HEVC_PIC_QUALITY_CTRL);
+#ifdef DEBUG_QOS
+	    avs2_print(dec, 0,
+			"[Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n",
+			pic_number, rdata32);
+#endif
+		/* reset all counts */
+	    WRITE_VREG(HEVC_PIC_QUALITY_CTRL, (1<<8));
+	}
+}
+
+static irqreturn_t vavs2_isr_thread_fn(int irq, void *data)
+{
+	struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)data;
+	unsigned int dec_status = dec->dec_status;
+	int i, ret;
+	int32_t start_code = 0;
+
+	/*if (dec->wait_buf)
+		pr_info("set wait_buf to 0\r\n");
+	*/
+
+	avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+		"%s decode_status 0x%x process_state %d lcu 0x%x\n",
+		__func__, dec_status, dec->process_state,
+		READ_VREG(HEVC_PARSER_LCU_START));
+
+#ifndef G12A_BRINGUP_DEBUG
+	if (dec->eos) {
+		PRINT_LINE();
+		goto irq_handled_exit;
+	}
+#endif
+	dec->wait_buf = 0;
+	if (dec_status == AVS2_DECODE_BUFEMPTY) {
+		PRINT_LINE();
+		if (dec->m_ins_flag) {
+			reset_process_time(dec);
+			if (!vdec_frame_based(hw_to_vdec(dec)))
+				dec_again_process(dec);
+			else {
+				dec->dec_result = DEC_RESULT_DONE;
+				reset_process_time(dec);
+				amhevc_stop();
+				vdec_schedule_work(&dec->work);
+			}
+		}
+		goto irq_handled_exit;
+	} else if (dec_status == HEVC_DECPIC_DATA_DONE) {
+		PRINT_LINE();
+		dec->start_decoding_flag |= 0x3;
+		if (dec->m_ins_flag) {
+			set_cuva_data(dec);
+			update_decoded_pic(dec);
+			get_picture_qos_info(dec);
+			reset_process_time(dec);
+			dec->dec_result = DEC_RESULT_DONE;
+			amhevc_stop();
+#if 0 /*def AVS2_10B_MMU*/
+			if (dec->m_ins_flag) {
+				/*avs2_recycle_mmu_buf_tail(dec);*/
+				dec->used_4k_num =
+					(READ_VREG(HEVC_SAO_MMU_STATUS) >> 16);
+			}
+#endif
+
+#if 0
+			/*keep hardware state*/
+			WRITE_VREG(HEVC_MPRED_INT_STATUS, (1<<31));
+			WRITE_VREG(HEVC_PARSER_RESULT_3, 0xffffffff);
+			dec->mpred_abv_start_addr =
+				READ_VREG(HEVC_MPRED_ABV_START_ADDR);
+			/**/
+#endif
+			vdec_schedule_work(&dec->work);
+		}
+		goto irq_handled_exit;
+	}
+	PRINT_LINE();
+#if 0
+	if (dec_status == AVS2_EOS) {
+		if (dec->m_ins_flag)
+			reset_process_time(dec);
+
+		avs2_print(dec, AVS2_DBG_BUFMGR,
+			"AVS2_EOS, flush buffer\r\n");
+
+		avs2_post_process(&dec->avs2_dec);
+		avs2_prepare_display_buf(dec);
+
+		avs2_print(dec, AVS2_DBG_BUFMGR,
+			"send AVS2_10B_DISCARD_NAL\r\n");
+		WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_10B_DISCARD_NAL);
+		if (dec->m_ins_flag) {
+			update_decoded_pic(dec);
+			dec->dec_result = DEC_RESULT_DONE;
+			amhevc_stop();
+			vdec_schedule_work(&dec->work);
+		}
+		goto irq_handled_exit;
+	} else
+#endif
+	if (dec_status == AVS2_DECODE_OVER_SIZE) {
+		avs2_print(dec, 0,
+			"avs2  decode oversize !!\n");
+		debug |= (AVS2_DBG_DIS_LOC_ERROR_PROC |
+			AVS2_DBG_DIS_SYS_ERROR_PROC);
+		dec->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW;
+		if (dec->m_ins_flag)
+			reset_process_time(dec);
+		goto irq_handled_exit;
+	}
+	PRINT_LINE();
+
+	if (dec->m_ins_flag)
+		reset_process_time(dec);
+
+	if (dec_status == AVS2_HEAD_SEQ_READY)
+		start_code = SEQUENCE_HEADER_CODE;
+	else if (dec_status == AVS2_HEAD_PIC_I_READY)
+		start_code = I_PICTURE_START_CODE;
+	else if (dec_status == AVS2_HEAD_PIC_PB_READY)
+		start_code = PB_PICTURE_START_CODE;
+	else if (dec_status == AVS2_STARTCODE_SEARCH_DONE)
+		/*SEQUENCE_END_CODE, VIDEO_EDIT_CODE*/
+		start_code = READ_VREG(CUR_NAL_UNIT_TYPE);
+
+	if (dec->process_state ==
+			PROC_STATE_HEAD_AGAIN
+			) {
+		if ((start_code == I_PICTURE_START_CODE)
+		|| (start_code == PB_PICTURE_START_CODE)) {
+			avs2_print(dec, 0,
+				"PROC_STATE_HEAD_AGAIN error, start_code 0x%x!!!\r\n",
+				start_code);
+			goto irq_handled_exit;
+		} else {
+			avs2_print(dec, AVS2_DBG_BUFMGR,
+				"PROC_STATE_HEAD_AGAIN, start_code 0x%x\r\n",
+				start_code);
+			dec->process_state = PROC_STATE_HEAD_DONE;
+			WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE);
+			goto irq_handled_exit;
+		}
+	} else if (dec->process_state ==
+			PROC_STATE_DECODE_AGAIN) {
+		if ((start_code == I_PICTURE_START_CODE)
+		|| (start_code == PB_PICTURE_START_CODE)) {
+			avs2_print(dec, AVS2_DBG_BUFMGR,
+				"PROC_STATE_DECODE_AGAIN=> decode_slice, start_code 0x%x\r\n",
+				start_code);
+			goto decode_slice;
+		} else {
+			avs2_print(dec, 0,
+				"PROC_STATE_DECODE_AGAIN, start_code 0x%x!!!\r\n",
+				start_code);
+			WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE);
+			goto irq_handled_exit;
+		}
+	}
+
+	if ((start_code == I_PICTURE_START_CODE)
+		|| (start_code == PB_PICTURE_START_CODE)
+		|| (start_code == SEQUENCE_END_CODE)
+		|| (start_code == VIDEO_EDIT_CODE)) {
+		PRINT_LINE();
+
+		if (dec->avs2_dec.hc.cur_pic != NULL) {
+			int32_t ii;
+#ifdef AVS2_10B_MMU
+			avs2_recycle_mmu_buf_tail(dec);
+#endif
+			check_pic_error(dec, dec->avs2_dec.hc.cur_pic);
+			avs2_post_process(&dec->avs2_dec);
+
+			if (debug & AVS2_DBG_PRINT_PIC_LIST)
+				dump_pic_list(dec);
+
+			avs2_prepare_display_buf(dec);
+			dec->avs2_dec.hc.cur_pic = NULL;
+			for (ii = 0; ii < dec->avs2_dec.ref_maxbuffer;
+					ii++) {
+				struct avs2_frame_s *pic =
+					dec->avs2_dec.fref[ii];
+				if (pic->bg_flag == 0 &&
+					pic->is_output == -1 &&
+					pic->mmu_alloc_flag &&
+					pic->vf_ref == 0) {
+					if (pic->refered_by_others == 0) {
+#ifdef AVS2_10B_MMU
+						pic->mmu_alloc_flag = 0;
+						/*release_buffer_4k(
+						dec->avs2_dec.fref[ii]->index);*/
+						decoder_mmu_box_free_idx(dec->mmu_box,
+							pic->index);
+#endif
+#ifndef MV_USE_FIXED_BUF
+						decoder_bmmu_box_free_idx(
+							dec->bmmu_box,
+							MV_BUFFER_IDX(pic->index));
+						pic->mpred_mv_wr_start_addr = 0;
+#endif
+					}
+				}
+			}
+		}
+	}
+
+	if ((dec_status == AVS2_HEAD_PIC_I_READY)
+		|| (dec_status == AVS2_HEAD_PIC_PB_READY)) {
+		PRINT_LINE();
+
+		if (debug & AVS2_DBG_SEND_PARAM_WITH_REG) {
+			get_rpm_param(
+				&dec->avs2_dec.param);
+		} else {
+
+			for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) {
+				int ii;
+				for (ii = 0; ii < 4; ii++)
+					dec->avs2_dec.param.l.data[i + ii] =
+						dec->rpm_ptr[i + 3 - ii];
+			   }
+		}
+#ifdef SANITY_CHECK
+		if (dec->avs2_dec.param.p.num_of_ref_cur >
+			dec->avs2_dec.ref_maxbuffer) {
+			pr_info("Warning: Wrong num_of_ref_cur %d, force to %d\n",
+				dec->avs2_dec.param.p.num_of_ref_cur,
+				dec->avs2_dec.ref_maxbuffer);
+			dec->avs2_dec.param.p.num_of_ref_cur =
+				dec->avs2_dec.ref_maxbuffer;
+		}
+#endif
+		PRINT_LINE();
+
+		debug_buffer_mgr_more(dec);
+		get_frame_rate(&dec->avs2_dec.param, dec);
+
+#if 1 // The video_signal_type is type of uint16_t and result false, so comment it out.
+		if (dec->avs2_dec.param.p.video_signal_type
+				& (1<<30)) {
+			union param_u *pPara;
+
+			avs2_print(dec, 0,
+					"avs2 HDR meta data present\n");
+			pPara = &dec->avs2_dec.param;
+
+			/*clean this flag*/
+			pPara->p.video_signal_type
+				&= ~(1<<30);
+
+			dec->vf_dp.present_flag = 1;
+
+			dec->vf_dp.white_point[0]
+				= pPara->p.white_point_x;
+			avs2_print(dec, AVS2_DBG_HDR_INFO,
+				"white_point[0]:0x%x\n",
+				dec->vf_dp.white_point[0]);
+
+			dec->vf_dp.white_point[1]
+				= pPara->p.white_point_y;
+			avs2_print(dec, AVS2_DBG_HDR_INFO,
+				"white_point[1]:0x%x\n",
+				dec->vf_dp.white_point[1]);
+
+			for (i = 0; i < 3; i++) {
+				dec->vf_dp.primaries[i][0]
+					= pPara->p.display_primaries_x[i];
+				avs2_print(dec, AVS2_DBG_HDR_INFO,
+					"primaries[%d][0]:0x%x\n",
+					i,
+					dec->vf_dp.primaries[i][0]);
+			}
+
+			for (i = 0; i < 3; i++) {
+				dec->vf_dp.primaries[i][1]
+					= pPara->p.display_primaries_y[i];
+				avs2_print(dec, AVS2_DBG_HDR_INFO,
+					"primaries[%d][1]:0x%x\n",
+					i,
+					dec->vf_dp.primaries[i][1]);
+			}
+
+			dec->vf_dp.luminance[0]
+				= pPara->p.max_display_mastering_luminance;
+			avs2_print(dec, AVS2_DBG_HDR_INFO,
+				"luminance[0]:0x%x\n",
+				dec->vf_dp.luminance[0]);
+
+			dec->vf_dp.luminance[1]
+				= pPara->p.min_display_mastering_luminance;
+			avs2_print(dec, AVS2_DBG_HDR_INFO,
+				"luminance[1]:0x%x\n",
+				dec->vf_dp.luminance[1]);
+
+
+			dec->vf_dp.content_light_level.present_flag
+				= 1;
+			dec->vf_dp.content_light_level.max_content
+				= pPara->p.max_content_light_level;
+			avs2_print(dec, AVS2_DBG_HDR_INFO,
+				"max_content:0x%x\n",
+				dec->vf_dp.content_light_level.max_content);
+
+			dec->vf_dp.content_light_level.max_pic_average
+				= pPara->p.max_picture_average_light_level;
+
+			avs2_print(dec, AVS2_DBG_HDR_INFO,
+				"max_pic_average:0x%x\n",
+				dec->vf_dp.content_light_level.max_pic_average);
+		}
+#endif
+
+
+		if (dec->video_ori_signal_type !=
+			((dec->avs2_dec.param.p.video_signal_type << 16)
+			| dec->avs2_dec.param.p.color_description)) {
+			u32 v = dec->avs2_dec.param.p.video_signal_type;
+			u32 c = dec->avs2_dec.param.p.color_description;
+			u32 convert_c = c;
+
+			if (v & 0x2000) {
+				avs2_print(dec, AVS2_DBG_HDR_INFO,
+					"video_signal_type present:\n");
+				avs2_print(dec, AVS2_DBG_HDR_INFO,
+					" %s %s\n",
+					video_format_names[(v >> 10) & 7],
+					((v >> 9) & 1) ?
+						"full_range" : "limited");
+				if (v & 0x100) {
+					u32 transfer;
+					u32 maxtrix;
+
+					avs2_print(dec, AVS2_DBG_HDR_INFO,
+						"color_description present:\n");
+					avs2_print(dec, AVS2_DBG_HDR_INFO,
+						"color_primarie = %d\n",
+						v & 0xff);
+					avs2_print(dec, AVS2_DBG_HDR_INFO,
+						"transfer_characteristic = %d\n",
+						(c >> 8) & 0xff);
+					avs2_print(dec, AVS2_DBG_HDR_INFO,
+						"  matrix_coefficient = %d\n",
+						c & 0xff);
+
+					transfer = (c >> 8) & 0xFF;
+					if (transfer >= 15)
+						avs2_print(dec, AVS2_DBG_HDR_INFO,
+							"unsupport transfer_characteristic\n");
+					else if (transfer  == 14)
+						transfer = 18; /* HLG */
+					else if (transfer == 13)
+						transfer = 32;
+					else if (transfer == 12)
+						transfer = 16;
+					else if (transfer == 11)
+						transfer = 15;
+
+					maxtrix = c & 0xFF;
+					if (maxtrix >= 10)
+						avs2_print(dec, AVS2_DBG_HDR_INFO,
+							"unsupport matrix_coefficient\n");
+					else if (maxtrix == 9)
+						maxtrix = 10;
+					else if (maxtrix == 8)
+						maxtrix = 9;
+
+					convert_c = (transfer << 8) | (maxtrix);
+
+					avs2_print(dec, AVS2_DBG_HDR_INFO,
+						" convered c:0x%x\n",
+						convert_c);
+				}
+			}
+
+			if (enable_force_video_signal_type)
+				dec->video_signal_type
+					= force_video_signal_type;
+			else {
+				dec->video_signal_type
+					= (v << 16) | convert_c;
+
+				dec->video_ori_signal_type
+					= (v << 16) | c;
+			}
+
+			video_signal_type = dec->video_signal_type;
+		}
+	}
+#if 0
+	if ((debug_again & 0x4) &&
+		dec->process_state ==
+		PROC_STATE_INIT) {
+		if (start_code == PB_PICTURE_START_CODE) {
+			dec->process_state = PROC_STATE_TEST1;
+			dec_again_process(dec);
+			goto irq_handled_exit;
+		}
+	}
+#endif
+	PRINT_LINE();
+	avs2_prepare_header(&dec->avs2_dec, start_code);
+
+	if (start_code == SEQUENCE_HEADER_CODE ||
+		start_code == VIDEO_EDIT_CODE ||
+		start_code == SEQUENCE_END_CODE) {
+		if (dec->m_ins_flag &&
+			vdec_frame_based(hw_to_vdec(dec)))
+			dec->start_decoding_flag |= 0x1;
+		dec->process_state = PROC_STATE_HEAD_DONE;
+		WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE);
+	} else if (start_code == I_PICTURE_START_CODE ||
+		start_code == PB_PICTURE_START_CODE) {
+		ret = 0;
+		if (dec->pic_list_init_flag == 0) {
+			int32_t lcu_size_log2 =
+				log2i(dec->avs2_dec.param.p.lcu_size);
+
+			avs2_init_global_buffers(&dec->avs2_dec);
+				/*avs2_dec->m_bg->index is
+				set to dec->used_buf_num - 1*/
+			init_pic_list(dec, lcu_size_log2);
+			init_pic_list_hw(dec);
+		}
+		ret = avs2_process_header(&dec->avs2_dec);
+		if (!dec->m_ins_flag)
+			dec->slice_idx++;
+
+		if (dec->m_ins_flag && ret
+			&& dec->avs2_dec.hc.cur_pic->cuva_data_buf != NULL)
+			release_cuva_data(dec->avs2_dec.hc.cur_pic);
+
+		PRINT_LINE();
+#ifdef I_ONLY_SUPPORT
+		if ((start_code == PB_PICTURE_START_CODE) &&
+			(dec->i_only & 0x2))
+			ret = -2;
+#endif
+
+		if (ret >= 0) {
+#ifdef AVS2_10B_MMU
+			if (dec->mmu_enable) {
+				ret = avs2_alloc_mmu(dec,
+					dec->avs2_dec.hc.cur_pic->index,
+					dec->avs2_dec.img.width,
+					dec->avs2_dec.img.height,
+					dec->avs2_dec.input.sample_bit_depth,
+					dec->frame_mmu_map_addr);
+				if (ret >= 0) {
+					dec->cur_fb_idx_mmu =
+						dec->avs2_dec.hc.cur_pic->index;
+					dec->avs2_dec.hc.cur_pic->mmu_alloc_flag = 1;
+				} else
+					pr_err("can't alloc need mmu1,idx %d ret =%d\n",
+						dec->avs2_dec.hc.cur_pic->index,
+						ret);
+			}
+#endif
+#ifdef AVS2_10B_MMU_DW
+			if (dec->dw_mmu_enable) {
+				ret = avs2_alloc_dw_mmu(dec,
+					dec->avs2_dec.hc.cur_pic->index,
+					dec->avs2_dec.img.width,
+					dec->avs2_dec.img.height,
+					dec->avs2_dec.input.sample_bit_depth,
+					dec->dw_frame_mmu_map_addr);
+				if (ret >= 0) {
+					dec->cur_fb_idx_mmu =
+						dec->avs2_dec.hc.cur_pic->index;
+					dec->avs2_dec.hc.cur_pic->mmu_alloc_flag = 1;
+				} else
+					pr_err("can't alloc need dw mmu1,idx %d ret =%d\n",
+						dec->avs2_dec.hc.cur_pic->index,
+						ret);
+			}
+#endif
+		}
+
+#ifndef MV_USE_FIXED_BUF
+		if (ret >= 0 && dec->avs2_dec.hc.cur_pic->
+			mpred_mv_wr_start_addr == 0) {
+			unsigned long buf_addr;
+			unsigned mv_buf_size = get_mv_buf_size(
+				dec,
+				dec->avs2_dec.hc.cur_pic->pic_w,
+				dec->avs2_dec.hc.cur_pic->pic_h);
+			int i = dec->avs2_dec.hc.cur_pic->index;
+			/*if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)
+				mv_buf_size = 0x120000 * 4;*/
+			if (decoder_bmmu_box_alloc_buf_phy
+			(dec->bmmu_box,
+			MV_BUFFER_IDX(i),
+			mv_buf_size,
+			DRIVER_NAME,
+			&buf_addr) < 0)
+				ret = -1;
+			else
+				dec->avs2_dec.hc.cur_pic->
+				mpred_mv_wr_start_addr
+				= buf_addr;
+		}
+#endif
+		if (ret < 0) {
+			avs2_print(dec, AVS2_DBG_BUFMGR,
+				"avs2_bufmgr_process=> %d, AVS2_10B_DISCARD_NAL\r\n",
+			 ret);
+			WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_10B_DISCARD_NAL);
+	#ifdef AVS2_10B_MMU
+			if (dec->mmu_enable)
+				avs2_recycle_mmu_buf(dec);
+	#endif
+			if (dec->m_ins_flag) {
+				dec->dec_result = DEC_RESULT_DONE;
+				amhevc_stop();
+				vdec_schedule_work(&dec->work);
+			}
+
+			goto irq_handled_exit;
+		} else {
+			PRINT_LINE();
+			dec->avs2_dec.hc.cur_pic->stream_offset =
+			READ_VREG(HEVC_SHIFT_BYTE_COUNT);
+			/*
+			struct PIC_BUFFER_CONFIG_s *cur_pic
+				= &cm->cur_frame->buf;
+			cur_pic->decode_idx = dec->frame_count;
+			*/
+			if (!dec->m_ins_flag) {
+				dec->frame_count++;
+				decode_frame_count[dec->index]
+					= dec->frame_count;
+			}
+			/*MULTI_INSTANCE_SUPPORT*/
+			if (dec->chunk) {
+				dec->avs2_dec.hc.cur_pic->pts =
+				dec->chunk->pts;
+				dec->avs2_dec.hc.cur_pic->pts64 =
+				dec->chunk->pts64;
+			}
+			/**/
+			dec->avs2_dec.hc.cur_pic->bit_depth
+				= dec->avs2_dec.input.sample_bit_depth;
+			dec->avs2_dec.hc.cur_pic->double_write_mode
+				= get_double_write_mode(dec);
+decode_slice:
+			PRINT_LINE();
+
+			config_mc_buffer(dec);
+			config_mcrcc_axi_hw(dec);
+			config_mpred_hw(dec);
+			config_dblk_hw(dec);
+			config_sao_hw(dec);
+			config_alf_hw(dec);
+			config_other_hw(dec);
+
+			avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+				"=>fref0 imgtr_fwRefDistance %d, fref1 imgtr_fwRefDistance %d, dis2/dis3/dis4 %d %d %d  img->tr %d\n",
+			    dec->avs2_dec.fref[0]->imgtr_fwRefDistance,
+			    dec->avs2_dec.fref[1]->imgtr_fwRefDistance,
+			dec->avs2_dec.fref[2]->imgtr_fwRefDistance,
+			dec->avs2_dec.fref[3]->imgtr_fwRefDistance,
+			dec->avs2_dec.fref[4]->imgtr_fwRefDistance,
+			dec->avs2_dec.img.tr);
+
+			if ((debug_again & 0x2) &&
+				dec->process_state ==
+				PROC_STATE_INIT) {
+				dec->process_state = PROC_STATE_DECODING;
+				dec_again_process(dec);
+				goto irq_handled_exit;
+			}
+
+			dec->process_state = PROC_STATE_DECODING;
+
+			WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE);
+
+		}
+
+		if (dec->m_ins_flag)
+			start_process_time(dec);
+	}
+irq_handled_exit:
+	PRINT_LINE();
+	dec->process_busy = 0;
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t vavs2_isr(int irq, void *data)
+{
+	int i;
+	unsigned int dec_status;
+	struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)data;
+	uint debug_tag;
+
+	WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1);
+
+	dec_status = READ_VREG(HEVC_DEC_STATUS_REG);
+
+	if (!dec)
+		return IRQ_HANDLED;
+	if (dec->init_flag == 0)
+		return IRQ_HANDLED;
+	if (dec->process_busy)/*on process.*/
+		return IRQ_HANDLED;
+	dec->dec_status = dec_status;
+	dec->process_busy = 1;
+	if (debug & AVS2_DBG_IRQ_EVENT)
+		avs2_print(dec, 0,
+			"avs2 isr dec status  = 0x%x, lcu 0x%x shiftbyte 0x%x (%x %x lev %x, wr %x, rd %x)\n",
+			dec_status, READ_VREG(HEVC_PARSER_LCU_START),
+			READ_VREG(HEVC_SHIFT_BYTE_COUNT),
+			READ_VREG(HEVC_STREAM_START_ADDR),
+			READ_VREG(HEVC_STREAM_END_ADDR),
+			READ_VREG(HEVC_STREAM_LEVEL),
+			READ_VREG(HEVC_STREAM_WR_PTR),
+			READ_VREG(HEVC_STREAM_RD_PTR)
+		);
+
+	debug_tag = READ_HREG(DEBUG_REG1);
+	if (debug_tag & 0x10000) {
+		dma_sync_single_for_cpu(
+			amports_get_dma_device(),
+			dec->lmem_phy_addr,
+			LMEM_BUF_SIZE,
+			DMA_FROM_DEVICE);
+
+		pr_info("LMEM<tag %x>:\n", READ_HREG(DEBUG_REG1));
+		for (i = 0; i < 0x400; i += 4) {
+			int ii;
+			if ((i & 0xf) == 0)
+				pr_info("%03x: ", i);
+			for (ii = 0; ii < 4; ii++) {
+				pr_info("%04x ",
+					   dec->lmem_ptr[i + 3 - ii]);
+			}
+			if (((i + ii) & 0xf) == 0)
+				pr_info("\n");
+		}
+
+		if (((udebug_pause_pos & 0xffff)
+			== (debug_tag & 0xffff)) &&
+			(udebug_pause_decode_idx == 0 ||
+			udebug_pause_decode_idx == dec->decode_idx) &&
+			(udebug_pause_val == 0 ||
+			udebug_pause_val == READ_HREG(DEBUG_REG2))) {
+			udebug_pause_pos &= 0xffff;
+			dec->ucode_pause_pos = udebug_pause_pos;
+		} else if (debug_tag & 0x20000)
+			dec->ucode_pause_pos = 0xffffffff;
+		if (dec->ucode_pause_pos)
+			reset_process_time(dec);
+		else
+			WRITE_HREG(DEBUG_REG1, 0);
+	} else if (debug_tag != 0) {
+		pr_info(
+			"dbg%x: %x lcu %x\n", READ_HREG(DEBUG_REG1),
+			   READ_HREG(DEBUG_REG2),
+			   READ_VREG(HEVC_PARSER_LCU_START));
+		if (((udebug_pause_pos & 0xffff)
+			== (debug_tag & 0xffff)) &&
+			(udebug_pause_decode_idx == 0 ||
+			udebug_pause_decode_idx == dec->decode_idx) &&
+			(udebug_pause_val == 0 ||
+			udebug_pause_val == READ_HREG(DEBUG_REG2))) {
+			udebug_pause_pos &= 0xffff;
+			dec->ucode_pause_pos = udebug_pause_pos;
+		}
+		if (dec->ucode_pause_pos)
+			reset_process_time(dec);
+		else
+			WRITE_HREG(DEBUG_REG1, 0);
+		dec->process_busy = 0;
+		return IRQ_HANDLED;
+	}
+
+	if (!dec->m_ins_flag) {
+		if (dec->error_flag == 1) {
+			dec->error_flag = 2;
+			dec->process_busy = 0;
+			return IRQ_HANDLED;
+		} else if (dec->error_flag == 3) {
+			dec->process_busy = 0;
+			return IRQ_HANDLED;
+		}
+
+		if ((dec->pic_list_init_flag) &&
+			get_free_buf_count(dec) <= 0) {
+			/*
+			if (dec->wait_buf == 0)
+				pr_info("set wait_buf to 1\r\n");
+			*/
+			dec->wait_buf = 1;
+			dec->process_busy = 0;
+			if (debug & AVS2_DBG_IRQ_EVENT)
+				avs2_print(dec, 0, "wait_buf\n");
+			return IRQ_HANDLED;
+		} else if (force_disp_pic_index) {
+			dec->process_busy = 0;
+			return IRQ_HANDLED;
+		}
+	}
+	return IRQ_WAKE_THREAD;
+}
+
+static void vavs2_put_timer_func(struct timer_list *timer)
+{
+	struct AVS2Decoder_s *dec = container_of(timer,
+		struct AVS2Decoder_s, timer);
+	uint8_t empty_flag;
+	unsigned int buf_level;
+
+	enum receviver_start_e state = RECEIVER_INACTIVE;
+	if (dec->m_ins_flag) {
+		if (hw_to_vdec(dec)->next_status
+			== VDEC_STATUS_DISCONNECTED) {
+			dec->dec_result = DEC_RESULT_FORCE_EXIT;
+			vdec_schedule_work(&dec->work);
+			avs2_print(dec, AVS2_DBG_BUFMGR,
+				"vdec requested to be disconnected\n");
+			return;
+		}
+	}
+	if (dec->init_flag == 0) {
+		if (dec->stat & STAT_TIMER_ARM) {
+			timer->expires = jiffies + PUT_INTERVAL;
+			add_timer(&dec->timer);
+		}
+		return;
+	}
+	if (dec->m_ins_flag == 0) {
+		if (vf_get_receiver(dec->provider_name)) {
+			state =
+				vf_notify_receiver(dec->provider_name,
+					VFRAME_EVENT_PROVIDER_QUREY_STATE,
+					NULL);
+			if ((state == RECEIVER_STATE_NULL)
+				|| (state == RECEIVER_STATE_NONE))
+				state = RECEIVER_INACTIVE;
+		} else
+			state = RECEIVER_INACTIVE;
+
+		empty_flag = (READ_VREG(HEVC_PARSER_INT_STATUS) >> 6) & 0x1;
+		/* error watchdog */
+		if (empty_flag == 0) {
+			/* decoder has input */
+			if ((debug & AVS2_DBG_DIS_LOC_ERROR_PROC) == 0) {
+
+				buf_level = READ_VREG(HEVC_STREAM_LEVEL);
+				/* receiver has no buffer to recycle */
+				if ((state == RECEIVER_INACTIVE) &&
+					(kfifo_is_empty(&dec->display_q) &&
+					 buf_level > 0x200)
+					) {
+						WRITE_VREG
+						(HEVC_ASSIST_MBOX0_IRQ_REG,
+						 0x1);
+				}
+			}
+
+			if ((debug & AVS2_DBG_DIS_SYS_ERROR_PROC) == 0) {
+				/* receiver has no buffer to recycle */
+				/*if ((state == RECEIVER_INACTIVE) &&
+					(kfifo_is_empty(&dec->display_q))) {
+				pr_info("avs2 something error,need reset\n");
+				}*/
+			}
+		}
+	} else {
+		if (
+			(decode_timeout_val > 0) &&
+			(dec->start_process_time > 0) &&
+			((1000 * (jiffies - dec->start_process_time) / HZ)
+				> decode_timeout_val)
+		) {
+			int current_lcu_idx =
+				READ_VREG(HEVC_PARSER_LCU_START)
+				& 0xffffff;
+			if (dec->last_lcu_idx == current_lcu_idx) {
+				if (dec->decode_timeout_count > 0)
+					dec->decode_timeout_count--;
+				if (dec->decode_timeout_count == 0) {
+					if (input_frame_based(
+						hw_to_vdec(dec)) ||
+					(READ_VREG(HEVC_STREAM_LEVEL) > 0x200))
+						timeout_process(dec);
+					else {
+						avs2_print(dec, 0,
+							"timeout & empty, again\n");
+						dec_again_process(dec);
+					}
+				}
+			} else {
+				start_process_time(dec);
+				dec->last_lcu_idx = current_lcu_idx;
+			}
+		}
+	}
+
+	if ((dec->ucode_pause_pos != 0) &&
+		(dec->ucode_pause_pos != 0xffffffff) &&
+		udebug_pause_pos != dec->ucode_pause_pos) {
+		dec->ucode_pause_pos = 0;
+		WRITE_HREG(DEBUG_REG1, 0);
+	}
+	if (debug & AVS2_DBG_DUMP_DATA) {
+		debug &= ~AVS2_DBG_DUMP_DATA;
+		avs2_print(dec, 0,
+			"%s: chunk size 0x%x off 0x%x sum 0x%x\n",
+			__func__,
+			dec->chunk->size,
+			dec->chunk->offset,
+			get_data_check_sum(dec, dec->chunk->size)
+			);
+		dump_data(dec, dec->chunk->size);
+	}
+	if (debug & AVS2_DBG_DUMP_PIC_LIST) {
+		dump_pic_list(dec);
+		debug &= ~AVS2_DBG_DUMP_PIC_LIST;
+	}
+	if (debug & AVS2_DBG_TRIG_SLICE_SEGMENT_PROC) {
+		WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1);
+		debug &= ~AVS2_DBG_TRIG_SLICE_SEGMENT_PROC;
+	}
+	if (debug & AVS2_DBG_DUMP_RPM_BUF) {
+		int i;
+
+		pr_info("RPM:\n");
+		for (i = 0; i < RPM_BUF_SIZE; i += 4) {
+			int ii;
+			if ((i & 0xf) == 0)
+				pr_info("%03x: ", i);
+			for (ii = 0; ii < 4; ii++) {
+				pr_info("%04x ",
+					   dec->lmem_ptr[i + 3 - ii]);
+			}
+			if (((i + ii) & 0xf) == 0)
+				pr_info("\n");
+		}
+		debug &= ~AVS2_DBG_DUMP_RPM_BUF;
+	}
+	if (debug & AVS2_DBG_DUMP_LMEM_BUF) {
+		int i;
+
+		pr_info("LMEM:\n");
+		for (i = 0; i < LMEM_BUF_SIZE; i += 4) {
+			int ii;
+			if ((i & 0xf) == 0)
+				pr_info("%03x: ", i);
+			for (ii = 0; ii < 4; ii++) {
+				pr_info("%04x ",
+					   dec->lmem_ptr[i + 3 - ii]);
+			}
+			if (((i + ii) & 0xf) == 0)
+				pr_info("\n");
+		}
+		debug &= ~AVS2_DBG_DUMP_LMEM_BUF;
+	}
+	/*if (debug & AVS2_DBG_HW_RESET) {
+	}*/
+
+	if (radr != 0) {
+		if (rval != 0) {
+			WRITE_VREG(radr, rval);
+			pr_info("WRITE_VREG(%x,%x)\n", radr, rval);
+		} else
+			pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr));
+		rval = 0;
+		radr = 0;
+	}
+	if (pop_shorts != 0) {
+		int i;
+		u32 sum = 0;
+		pr_info("pop stream 0x%x shorts\r\n", pop_shorts);
+		for (i = 0; i < pop_shorts; i++) {
+			u32 data =
+			(READ_HREG(HEVC_SHIFTED_DATA) >> 16);
+			WRITE_HREG(HEVC_SHIFT_COMMAND,
+			(1<<7)|16);
+			if ((i & 0xf) == 0)
+				pr_info("%04x:", i);
+			pr_info("%04x ", data);
+			if (((i + 1) & 0xf) == 0)
+				pr_info("\r\n");
+			sum += data;
+		}
+		pr_info("\r\nsum = %x\r\n", sum);
+		pop_shorts = 0;
+	}
+	if (dbg_cmd != 0) {
+		if (dbg_cmd == 1) {
+			u32 disp_laddr;
+			if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB &&
+				get_double_write_mode(dec) == 0) {
+				disp_laddr =
+					READ_VCBUS_REG(AFBC_BODY_BADDR) << 4;
+			} else {
+				struct canvas_s cur_canvas;
+				canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0)
+					& 0xff), &cur_canvas);
+				disp_laddr = cur_canvas.addr;
+			}
+			pr_info("current displayed buffer address %x\r\n",
+				disp_laddr);
+		}
+		dbg_cmd = 0;
+	}
+	/*don't changed at start.*/
+	if (dec->get_frame_dur && dec->show_frame_num > 60 &&
+		dec->frame_dur > 0 && dec->saved_resolution !=
+		frame_width * frame_height *
+			(96000 / dec->frame_dur)) {
+		int fps = 96000 / dec->frame_dur;
+		if (hevc_source_changed(VFORMAT_AVS2,
+			frame_width, frame_height, fps) > 0)
+			dec->saved_resolution = frame_width *
+			frame_height * fps;
+	}
+
+	timer->expires = jiffies + PUT_INTERVAL;
+	add_timer(timer);
+}
+
+
+int vavs2_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
+{
+	struct AVS2Decoder_s *dec =
+		(struct AVS2Decoder_s *)vdec->private;
+
+	if (!dec)
+		return -1;
+
+	vstatus->frame_width = dec->frame_width;
+	vstatus->frame_height = dec->frame_height;
+
+	if (dec->frame_dur != 0)
+		vstatus->frame_rate = ((96000 * 10 / dec->frame_dur) % 10) < 5 ?
+		                    96000 / dec->frame_dur : (96000 / dec->frame_dur +1);
+	else
+		vstatus->frame_rate = -1;
+	vstatus->error_count = 0;
+	vstatus->status = dec->stat | dec->fatal_error;
+	vstatus->frame_dur = dec->frame_dur;
+	vstatus->bit_rate = dec->gvs->bit_rate;
+	vstatus->frame_data = dec->gvs->frame_data;
+	vstatus->total_data = dec->gvs->total_data;
+	vstatus->frame_count = dec->gvs->frame_count;
+	vstatus->error_frame_count = dec->gvs->error_frame_count;
+	vstatus->drop_frame_count = dec->gvs->drop_frame_count;
+	vstatus->i_decoded_frames = dec->gvs->i_decoded_frames;
+	vstatus->i_lost_frames =  dec->gvs->i_lost_frames;
+	vstatus->i_concealed_frames =  dec->gvs->i_concealed_frames;
+	vstatus->p_decoded_frames =  dec->gvs->p_decoded_frames;
+	vstatus->p_lost_frames =  dec->gvs->p_lost_frames;
+	vstatus->p_concealed_frames =  dec->gvs->p_concealed_frames;
+	vstatus->b_decoded_frames =  dec->gvs->b_decoded_frames;
+	vstatus->b_lost_frames =  dec->gvs->b_lost_frames;
+	vstatus->b_concealed_frames =  dec->gvs->b_concealed_frames;
+	vstatus->total_data = dec->gvs->total_data;
+	vstatus->samp_cnt = dec->gvs->samp_cnt;
+	vstatus->offset = dec->gvs->offset;
+	snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
+		"%s", DRIVER_NAME);
+	return 0;
+}
+
+int vavs2_set_isreset(struct vdec_s *vdec, int isreset)
+{
+	is_reset = isreset;
+	return 0;
+}
+
+static void vavs2_prot_init(struct AVS2Decoder_s *dec)
+{
+	unsigned int data32;
+
+	avs2_config_work_space_hw(dec);
+	if (dec->pic_list_init_flag)
+		init_pic_list_hw(dec);
+
+	avs2_init_decoder_hw(dec);
+
+#if 1
+	avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+		"%s\n", __func__);
+	data32 = READ_VREG(HEVC_STREAM_CONTROL);
+	data32 = data32 |
+		(1 << 0)/*stream_fetch_enable*/
+		;
+	WRITE_VREG(HEVC_STREAM_CONTROL, data32);
+#if 0
+	data32 = READ_VREG(HEVC_SHIFT_STARTCODE);
+	if (data32 != 0x00000100) {
+		pr_info("avs2 prot init error %d\n", __LINE__);
+		return;
+	}
+	data32 = READ_VREG(HEVC_SHIFT_EMULATECODE);
+	if (data32 != 0x00000300) {
+		pr_info("avs2 prot init error %d\n", __LINE__);
+		return;
+	}
+	WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x12345678);
+	WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x9abcdef0);
+	data32 = READ_VREG(HEVC_SHIFT_STARTCODE);
+	if (data32 != 0x12345678) {
+		pr_info("avs2 prot init error %d\n", __LINE__);
+		return;
+	}
+	data32 = READ_VREG(HEVC_SHIFT_EMULATECODE);
+	if (data32 != 0x9abcdef0) {
+		pr_info("avs2 prot init error %d\n", __LINE__);
+		return;
+	}
+#endif
+	WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x00000100);
+	WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x00000000);
+#endif
+
+
+
+	WRITE_VREG(HEVC_WAIT_FLAG, 1);
+
+	/* WRITE_VREG(HEVC_MPSR, 1); */
+
+	/* clear mailbox interrupt */
+	WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1);
+
+	/* enable mailbox interrupt */
+	WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 1);
+
+	/* disable PSCALE for hardware sharing */
+	WRITE_VREG(HEVC_PSCALE_CTRL, 0);
+
+	WRITE_VREG(DEBUG_REG1, 0x0);
+	/*check vps/sps/pps/i-slice in ucode*/
+	WRITE_VREG(NAL_SEARCH_CTL, 0x8);
+
+	WRITE_VREG(DECODE_STOP_POS, udebug_flag);
+
+	config_cuva_buf(dec);
+}
+
+#ifdef I_ONLY_SUPPORT
+static int vavs2_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
+{
+	struct AVS2Decoder_s *dec =
+		(struct AVS2Decoder_s *)vdec->private;
+	if (i_only_flag & 0x100)
+		return 0;
+	if (trickmode == TRICKMODE_I || trickmode == TRICKMODE_I_HEVC)
+		dec->i_only = 0x3;
+	else if (trickmode == TRICKMODE_NONE)
+		dec->i_only = 0x0;
+	return 0;
+}
+#endif
+
+static int vavs2_local_init(struct AVS2Decoder_s *dec)
+{
+	int i;
+	int ret;
+	int width, height;
+
+	dec->vavs2_ratio = dec->vavs2_amstream_dec_info.ratio;
+
+	dec->gvs = vzalloc(sizeof(struct vdec_info));
+	if (NULL == dec->gvs) {
+		avs2_print(dec, 0,
+			"the struct of vdec status malloc failed.\n");
+		return -1;
+	}
+#ifdef DEBUG_PTS
+	dec->pts_missed = 0;
+	dec->pts_hit = 0;
+#endif
+	dec->new_frame_displayed = 0;
+	dec->last_put_idx = -1;
+	dec->saved_resolution = 0;
+	dec->get_frame_dur = false;
+	on_no_keyframe_skiped = 0;
+	width = dec->vavs2_amstream_dec_info.width;
+	height = dec->vavs2_amstream_dec_info.height;
+	dec->frame_dur =
+		(dec->vavs2_amstream_dec_info.rate ==
+		 0) ? 3600 : dec->vavs2_amstream_dec_info.rate;
+	if (width && height)
+		dec->frame_ar = height * 0x100 / width;
+/*
+TODO:FOR VERSION
+*/
+	avs2_print(dec, AVS2_DBG_BUFMGR,
+		"avs2: ver (%d,%d) decinfo: %dx%d rate=%d\n", avs2_version,
+		   0, width, height, dec->frame_dur);
+
+	if (dec->frame_dur == 0)
+		dec->frame_dur = 96000 / 24;
+#ifdef I_ONLY_SUPPORT
+	if (i_only_flag & 0x100)
+		dec->i_only = i_only_flag & 0xff;
+	else if ((unsigned long) dec->vavs2_amstream_dec_info.param
+		& 0x08)
+		dec->i_only = 0x7;
+	else
+		dec->i_only = 0x0;
+#endif
+	INIT_KFIFO(dec->display_q);
+	INIT_KFIFO(dec->newframe_q);
+
+
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		const struct vframe_s *vf = &dec->vfpool[i];
+		dec->vfpool[i].index = -1;
+		kfifo_put(&dec->newframe_q, vf);
+	}
+
+
+	ret = avs2_local_init(dec);
+
+	return ret;
+}
+
+
+static s32 vavs2_init(struct vdec_s *vdec)
+{
+	int ret = -1, size = -1;
+	int fw_size = 0x1000 * 16;
+	struct firmware_s *fw = NULL;
+	struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)vdec->private;
+
+	timer_setup(&dec->timer, vavs2_put_timer_func, 0);
+
+	dec->stat |= STAT_TIMER_INIT;
+	if (vavs2_local_init(dec) < 0)
+		return -EBUSY;
+
+	vdec_set_vframe_comm(vdec, DRIVER_NAME);
+
+	fw = vmalloc(sizeof(struct firmware_s) + fw_size);
+	if (IS_ERR_OR_NULL(fw))
+		return -ENOMEM;
+
+	size = get_firmware_data(VIDEO_DEC_AVS2_MMU, fw->data);
+	if (size < 0) {
+		pr_err("get firmware fail.\n");
+		vfree(fw);
+		return -1;
+	}
+
+	fw->len = fw_size;
+
+	if (dec->m_ins_flag) {
+		dec->timer.expires = jiffies + PUT_INTERVAL;
+
+		/*add_timer(&dec->timer);
+
+		dec->stat |= STAT_TIMER_ARM;
+		dec->stat |= STAT_ISR_REG;*/
+
+		INIT_WORK(&dec->work, avs2_work);
+		dec->fw = fw;
+
+		return 0;
+	}
+
+	amhevc_enable();
+
+	ret = amhevc_loadmc_ex(VFORMAT_AVS2, NULL, fw->data);
+	if (ret < 0) {
+		amhevc_disable();
+		vfree(fw);
+		pr_err("AVS2: the %s fw loading failed, err: %x\n",
+			tee_enabled() ? "TEE" : "local", ret);
+		return -EBUSY;
+	}
+
+	vfree(fw);
+
+	dec->stat |= STAT_MC_LOAD;
+
+	/* enable AMRISC side protocol */
+	vavs2_prot_init(dec);
+
+	if (vdec_request_threaded_irq(VDEC_IRQ_0,
+				vavs2_isr,
+				vavs2_isr_thread_fn,
+				IRQF_ONESHOT,/*run thread on this irq disabled*/
+				"vavs2-irq", (void *)dec)) {
+		pr_info("vavs2 irq register error.\n");
+		amhevc_disable();
+		return -ENOENT;
+	}
+
+	dec->stat |= STAT_ISR_REG;
+
+	dec->provider_name = PROVIDER_NAME;
+	vf_provider_init(&vavs2_vf_prov, PROVIDER_NAME,
+				&vavs2_vf_provider, dec);
+	vf_reg_provider(&vavs2_vf_prov);
+	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL);
+	if (dec->frame_dur != 0) {
+		if (!is_reset)
+			vf_notify_receiver(dec->provider_name,
+					VFRAME_EVENT_PROVIDER_FR_HINT,
+					(void *)
+					((unsigned long)dec->frame_dur));
+	}
+	dec->stat |= STAT_VF_HOOK;
+
+	dec->timer.expires = jiffies + PUT_INTERVAL;
+	add_timer(&dec->timer);
+
+	dec->stat |= STAT_TIMER_ARM;
+
+	/* dec->stat |= STAT_KTHREAD; */
+	dec->process_busy = 0;
+	avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+		"%d, vavs2_init, RP=0x%x\n",
+		__LINE__, READ_VREG(HEVC_STREAM_RD_PTR));
+	return 0;
+}
+
+static int vmavs2_stop(struct AVS2Decoder_s *dec)
+{
+	dec->init_flag = 0;
+	dec->first_sc_checked = 0;
+	if (dec->stat & STAT_TIMER_ARM) {
+		del_timer_sync(&dec->timer);
+		dec->stat &= ~STAT_TIMER_ARM;
+	}
+
+	if (dec->stat & STAT_VF_HOOK) {
+		if (!is_reset)
+			vf_notify_receiver(dec->provider_name,
+					VFRAME_EVENT_PROVIDER_FR_END_HINT,
+					NULL);
+
+		vf_unreg_provider(&vavs2_vf_prov);
+		dec->stat &= ~STAT_VF_HOOK;
+	}
+	avs2_local_uninit(dec);
+	reset_process_time(dec);
+	cancel_work_sync(&dec->work);
+	uninit_mmu_buffers(dec);
+	if (dec->fw) {
+		vfree(dec->fw);
+		dec->fw = NULL;
+	}
+
+	return 0;
+}
+
+
+static int vavs2_stop(struct AVS2Decoder_s *dec)
+{
+
+	dec->init_flag = 0;
+	dec->first_sc_checked = 0;
+	if (dec->stat & STAT_VDEC_RUN) {
+		amhevc_stop();
+		dec->stat &= ~STAT_VDEC_RUN;
+	}
+
+	if (dec->stat & STAT_ISR_REG) {
+		if (!dec->m_ins_flag)
+			WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0);
+		vdec_free_irq(VDEC_IRQ_0, (void *)dec);
+		dec->stat &= ~STAT_ISR_REG;
+	}
+
+	if (dec->stat & STAT_TIMER_ARM) {
+		del_timer_sync(&dec->timer);
+		dec->stat &= ~STAT_TIMER_ARM;
+	}
+
+	if (dec->stat & STAT_VF_HOOK) {
+		if (!is_reset)
+			vf_notify_receiver(dec->provider_name,
+					VFRAME_EVENT_PROVIDER_FR_END_HINT,
+					NULL);
+
+		vf_unreg_provider(&vavs2_vf_prov);
+		dec->stat &= ~STAT_VF_HOOK;
+	}
+	avs2_local_uninit(dec);
+
+	if (dec->m_ins_flag)
+		cancel_work_sync(&dec->work);
+	else
+		amhevc_disable();
+	uninit_mmu_buffers(dec);
+
+	return 0;
+}
+
+static int amvdec_avs2_mmu_init(struct AVS2Decoder_s *dec)
+{
+	int tvp_flag = vdec_secure(hw_to_vdec(dec)) ?
+		CODEC_MM_FLAGS_TVP : 0;
+	int buf_size = 48;
+
+	dec->need_cache_size = buf_size * SZ_1M;
+	dec->sc_start_time = get_jiffies_64();
+#ifdef AVS2_10B_MMU
+	if (dec->mmu_enable) {
+		dec->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME,
+			dec->index, FRAME_BUFFERS,
+			dec->need_cache_size,
+			tvp_flag
+			);
+		if (!dec->mmu_box) {
+			pr_err("avs2 alloc mmu box failed!!\n");
+			return -1;
+		}
+	}
+#endif
+#ifdef AVS2_10B_MMU_DW
+	if (dec->dw_mmu_enable) {
+		dec->dw_mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME,
+			dec->index, FRAME_BUFFERS,
+			dec->need_cache_size,
+			tvp_flag
+			);
+		if (!dec->dw_mmu_box) {
+			pr_err("avs2 alloc dw mmu box failed!!\n");
+			dec->dw_mmu_enable = 0;
+		}
+	}
+#endif
+	dec->bmmu_box = decoder_bmmu_box_alloc_box(
+			DRIVER_NAME,
+			dec->index,
+			MAX_BMMU_BUFFER_NUM,
+			4 + PAGE_SHIFT,
+			CODEC_MM_FLAGS_CMA_CLEAR |
+			CODEC_MM_FLAGS_FOR_VDECODER |
+			tvp_flag);
+	if (!dec->bmmu_box) {
+		pr_err("avs2 alloc bmmu box failed!!\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int amvdec_avs2_probe(struct platform_device *pdev)
+{
+	struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
+	/*struct BUF_s BUF[MAX_BUF_NUM];*/
+	struct AVS2Decoder_s *dec = &gAVS2Decoder;
+	int ret;
+	pr_info("%s\n", __func__);
+
+	dec = vzalloc(sizeof(struct AVS2Decoder_s));
+	if (!dec)
+		return -ENOMEM;
+
+	pdata->private = dec;
+	platform_set_drvdata(pdev, pdata);
+
+	mutex_lock(&vavs2_mutex);
+
+	dec->init_flag = 0;
+	dec->first_sc_checked = 0;
+	dec->eos = 0;
+	dec->start_process_time = 0;
+	dec->timeout_num = 0;
+	dec->fatal_error = 0;
+	dec->show_frame_num = 0;
+	if (pdata == NULL) {
+		avs2_print(dec, 0,
+			"\namvdec_avs2 memory resource undefined.\n");
+		mutex_unlock(&vavs2_mutex);
+		return -EFAULT;
+	}
+	dec->m_ins_flag = 0;
+	dec->platform_dev = pdev;
+	platform_set_drvdata(pdev, pdata);
+
+#ifdef AVS2_10B_MMU_DW
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T5D) {
+		dec->dw_mmu_enable =
+			(get_double_write_mode(dec) & 0x20) ? 1 : 0;
+	} else {
+		dec->dw_mmu_enable = 0;
+	}
+#endif
+	if (amvdec_avs2_mmu_init(dec) < 0) {
+		mutex_unlock(&vavs2_mutex);
+		pr_err("avs2 alloc bmmu box failed!!\n");
+		return -1;
+	}
+
+	ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, WORK_SPACE_BUF_ID,
+			work_buf_size, DRIVER_NAME, &pdata->mem_start);
+	if (ret < 0) {
+		uninit_mmu_buffers(dec);
+		mutex_unlock(&vavs2_mutex);
+		return ret;
+	}
+	dec->buf_size = work_buf_size;
+
+	dec->buf_start = pdata->mem_start;
+
+
+	if (debug) {
+		avs2_print(dec, 0,
+			"===AVS2 decoder mem resource 0x%lx size 0x%x\n",
+			   pdata->mem_start, dec->buf_size);
+	}
+
+	if (pdata->sys_info) {
+		dec->vavs2_amstream_dec_info = *pdata->sys_info;
+		dec->frame_width = dec->vavs2_amstream_dec_info.width;
+		dec->frame_height = dec->vavs2_amstream_dec_info.height;
+	} else {
+		dec->vavs2_amstream_dec_info.width = 0;
+		dec->vavs2_amstream_dec_info.height = 0;
+		dec->vavs2_amstream_dec_info.rate = 30;
+	}
+	dec->cma_dev = pdata->cma_dev;
+
+	dec->endian = HEVC_CONFIG_LITTLE_ENDIAN;
+	if (is_support_vdec_canvas())
+		dec->endian = HEVC_CONFIG_BIG_ENDIAN;
+	if (endian)
+		dec->endian = endian;
+
+	pdata->private = dec;
+	pdata->dec_status = vavs2_dec_status;
+	/*pdata->set_isreset = vavs2_set_isreset;*/
+	is_reset = 0;
+	if (vavs2_init(pdata) < 0) {
+		pr_info("\namvdec_avs2 init failed.\n");
+		avs2_local_uninit(dec);
+		uninit_mmu_buffers(dec);
+		pdata->dec_status = NULL;
+		mutex_unlock(&vavs2_mutex);
+		return -ENODEV;
+	}
+	/*set the max clk for smooth playing...*/
+	hevc_source_changed(VFORMAT_AVS2,
+			4096, 2048, 60);
+	mutex_unlock(&vavs2_mutex);
+
+	return 0;
+}
+
+static int amvdec_avs2_remove(struct platform_device *pdev)
+{
+	struct AVS2Decoder_s *dec = &gAVS2Decoder;
+	if (debug)
+		pr_info("amvdec_avs2_remove\n");
+
+	mutex_lock(&vavs2_mutex);
+
+	vavs2_stop(dec);
+
+
+	hevc_source_changed(VFORMAT_AVS2, 0, 0, 0);
+
+
+#ifdef DEBUG_PTS
+	pr_info("pts missed %ld, pts hit %ld, duration %d\n",
+		   dec->pts_missed, dec->pts_hit, dec->frame_dur);
+#endif
+
+	mutex_unlock(&vavs2_mutex);
+
+	return 0;
+}
+
+/****************************************/
+
+static struct platform_driver amvdec_avs2_driver = {
+	.probe = amvdec_avs2_probe,
+	.remove = amvdec_avs2_remove,
+#ifdef CONFIG_PM
+	.suspend = amhevc_suspend,
+	.resume = amhevc_resume,
+#endif
+	.driver = {
+		.name = DRIVER_NAME,
+	}
+};
+
+static struct codec_profile_t amvdec_avs2_profile = {
+	.name = "avs2",
+	.profile = ""
+};
+
+static struct codec_profile_t amvdec_avs2_profile_mult;
+
+static unsigned char get_data_check_sum
+	(struct AVS2Decoder_s *dec, int size)
+{
+	int jj;
+	int sum = 0;
+	u8 *data = NULL;
+
+	if (!dec->chunk->block->is_mapped)
+		data = codec_mm_vmap(dec->chunk->block->start +
+			dec->chunk->offset, size);
+	else
+		data = ((u8 *)dec->chunk->block->start_virt) +
+			dec->chunk->offset;
+
+	for (jj = 0; jj < size; jj++)
+		sum += data[jj];
+
+	if (!dec->chunk->block->is_mapped)
+		codec_mm_unmap_phyaddr(data);
+	return sum;
+}
+
+static void dump_data(struct AVS2Decoder_s *dec, int size)
+{
+	int jj;
+	u8 *data = NULL;
+	int padding_size = dec->chunk->offset &
+		(VDEC_FIFO_ALIGN - 1);
+
+	if (!dec->chunk->block->is_mapped)
+		data = codec_mm_vmap(dec->chunk->block->start +
+			dec->chunk->offset, size);
+	else
+		data = ((u8 *)dec->chunk->block->start_virt) +
+			dec->chunk->offset;
+
+	avs2_print(dec, 0, "padding: ");
+	for (jj = padding_size; jj > 0; jj--)
+		avs2_print_cont(dec,
+			0,
+			"%02x ", *(data - jj));
+	avs2_print_cont(dec, 0, "data adr %p\n",
+		data);
+
+	for (jj = 0; jj < size; jj++) {
+		if ((jj & 0xf) == 0)
+			avs2_print(dec,
+				0,
+				"%06x:", jj);
+		avs2_print_cont(dec,
+			0,
+			"%02x ", data[jj]);
+		if (((jj + 1) & 0xf) == 0)
+			avs2_print(dec,
+			 0,
+				"\n");
+	}
+	avs2_print(dec,
+	 0,
+		"\n");
+
+	if (!dec->chunk->block->is_mapped)
+		codec_mm_unmap_phyaddr(data);
+}
+
+static void avs2_work(struct work_struct *work)
+{
+	struct AVS2Decoder_s *dec = container_of(work,
+		struct AVS2Decoder_s, work);
+	struct vdec_s *vdec = hw_to_vdec(dec);
+	/* finished decoding one frame or error,
+	 * notify vdec core to switch context
+	 */
+	avs2_print(dec, PRINT_FLAG_VDEC_DETAIL,
+		"%s dec_result %d %x %x %x\n",
+		__func__,
+		dec->dec_result,
+		READ_VREG(HEVC_STREAM_LEVEL),
+		READ_VREG(HEVC_STREAM_WR_PTR),
+		READ_VREG(HEVC_STREAM_RD_PTR));
+
+	if (((dec->dec_result == DEC_RESULT_GET_DATA) ||
+		(dec->dec_result == DEC_RESULT_GET_DATA_RETRY))
+		&& (hw_to_vdec(dec)->next_status !=
+		VDEC_STATUS_DISCONNECTED)) {
+		if (!vdec_has_more_input(vdec)) {
+			dec->dec_result = DEC_RESULT_EOS;
+			vdec_schedule_work(&dec->work);
+			return;
+		}
+
+		if (dec->dec_result == DEC_RESULT_GET_DATA) {
+			avs2_print(dec, PRINT_FLAG_VDEC_STATUS,
+				"%s DEC_RESULT_GET_DATA %x %x %x\n",
+				__func__,
+				READ_VREG(HEVC_STREAM_LEVEL),
+				READ_VREG(HEVC_STREAM_WR_PTR),
+				READ_VREG(HEVC_STREAM_RD_PTR));
+			vdec_vframe_dirty(vdec, dec->chunk);
+			vdec_clean_input(vdec);
+		}
+
+		if (get_free_buf_count(dec) >=
+			run_ready_min_buf_num) {
+			int r;
+			int decode_size;
+			r = vdec_prepare_input(vdec, &dec->chunk);
+			if (r < 0) {
+				dec->dec_result = DEC_RESULT_GET_DATA_RETRY;
+
+				avs2_print(dec,
+					PRINT_FLAG_VDEC_DETAIL,
+					"amvdec_vh265: Insufficient data\n");
+
+				vdec_schedule_work(&dec->work);
+				return;
+			}
+			dec->dec_result = DEC_RESULT_NONE;
+			avs2_print(dec, PRINT_FLAG_VDEC_STATUS,
+				"%s: chunk size 0x%x sum 0x%x\n",
+				__func__, r,
+				(debug & PRINT_FLAG_VDEC_STATUS) ?
+				get_data_check_sum(dec, r) : 0
+				);
+			if (debug & PRINT_FLAG_VDEC_DATA)
+				dump_data(dec, dec->chunk->size);
+
+			decode_size = dec->chunk->size +
+				(dec->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+
+			WRITE_VREG(HEVC_DECODE_SIZE,
+				READ_VREG(HEVC_DECODE_SIZE) + decode_size);
+
+			vdec_enable_input(vdec);
+
+			WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE);
+
+			start_process_time(dec);
+
+		} else{
+			dec->dec_result = DEC_RESULT_GET_DATA_RETRY;
+
+			avs2_print(dec, PRINT_FLAG_VDEC_DETAIL,
+				"amvdec_vh265: Insufficient data\n");
+
+			vdec_schedule_work(&dec->work);
+		}
+		return;
+	} else if (dec->dec_result == DEC_RESULT_DONE) {
+		/* if (!dec->ctx_valid)
+			dec->ctx_valid = 1; */
+		dec->slice_idx++;
+		dec->frame_count++;
+		dec->process_state = PROC_STATE_INIT;
+		decode_frame_count[dec->index] = dec->frame_count;
+
+#ifdef AVS2_10B_MMU
+		if (dec->mmu_enable)
+			dec->used_4k_num = (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16);
+#endif
+		avs2_print(dec, PRINT_FLAG_VDEC_STATUS,
+			"%s (===> %d) dec_result %d %x %x %x shiftbytes 0x%x decbytes 0x%x\n",
+			__func__,
+			dec->frame_count,
+			dec->dec_result,
+			READ_VREG(HEVC_STREAM_LEVEL),
+			READ_VREG(HEVC_STREAM_WR_PTR),
+			READ_VREG(HEVC_STREAM_RD_PTR),
+			READ_VREG(HEVC_SHIFT_BYTE_COUNT),
+			READ_VREG(HEVC_SHIFT_BYTE_COUNT) -
+			dec->start_shift_bytes
+			);
+		vdec_vframe_dirty(hw_to_vdec(dec), dec->chunk);
+	} else if (dec->dec_result == DEC_RESULT_AGAIN) {
+		/*
+			stream base: stream buf empty or timeout
+			frame base: vdec_prepare_input fail
+		*/
+		if (!vdec_has_more_input(vdec)) {
+			dec->dec_result = DEC_RESULT_EOS;
+			vdec_schedule_work(&dec->work);
+			return;
+		}
+	} else if (dec->dec_result == DEC_RESULT_EOS) {
+		avs2_print(dec, 0,
+			"%s: end of stream\n",
+			__func__);
+		dec->eos = 1;
+		if ( dec->avs2_dec.hc.cur_pic != NULL) {
+			check_pic_error(dec, dec->avs2_dec.hc.cur_pic);
+			avs2_post_process(&dec->avs2_dec);
+			avs2_prepare_display_buf(dec);
+		}
+		vdec_vframe_dirty(hw_to_vdec(dec), dec->chunk);
+	} else if (dec->dec_result == DEC_RESULT_FORCE_EXIT) {
+		avs2_print(dec, PRINT_FLAG_VDEC_STATUS,
+			"%s: force exit\n",
+			__func__);
+		if (dec->stat & STAT_VDEC_RUN) {
+			amhevc_stop();
+			dec->stat &= ~STAT_VDEC_RUN;
+		}
+
+		if (dec->stat & STAT_ISR_REG) {
+			if (!dec->m_ins_flag)
+				WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0);
+			vdec_free_irq(VDEC_IRQ_0, (void *)dec);
+			dec->stat &= ~STAT_ISR_REG;
+		}
+	}
+
+	if (dec->stat & STAT_TIMER_ARM) {
+		del_timer_sync(&dec->timer);
+		dec->stat &= ~STAT_TIMER_ARM;
+	}
+	/* mark itself has all HW resource released and input released */
+	if (vdec->parallel_dec ==1)
+		vdec_core_finish_run(vdec, CORE_MASK_HEVC);
+	else
+		vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
+
+	if (dec->vdec_cb)
+		dec->vdec_cb(hw_to_vdec(dec), dec->vdec_cb_arg);
+}
+
+static int avs2_hw_ctx_restore(struct AVS2Decoder_s *dec)
+{
+	/* new to do ... */
+	vavs2_prot_init(dec);
+	return 0;
+}
+
+static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
+{
+	struct AVS2Decoder_s *dec =
+		(struct AVS2Decoder_s *)vdec->private;
+	int tvp = vdec_secure(hw_to_vdec(dec)) ?
+		CODEC_MM_FLAGS_TVP : 0;
+	unsigned long ret = 0;
+	avs2_print(dec,
+		PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__);
+	if (debug & AVS2_DBG_PIC_LEAK_WAIT)
+		return ret;
+
+	if (dec->eos)
+		return ret;
+	if (!dec->first_sc_checked) {
+		int size = decoder_mmu_box_sc_check(dec->mmu_box, tvp);
+		dec->first_sc_checked = 1;
+		avs2_print(dec, 0, "vavs2 cached=%d  need_size=%d speed= %d ms\n",
+			size, (dec->need_cache_size >> PAGE_SHIFT),
+					(int)(get_jiffies_64() - dec->sc_start_time) * 1000/HZ);
+	}
+
+	if (dec->next_again_flag &&
+		(!vdec_frame_based(vdec))) {
+		u32 parser_wr_ptr =
+			STBUF_READ(&vdec->vbuf, get_wp);
+		if (parser_wr_ptr >= dec->pre_parser_wr_ptr &&
+			(parser_wr_ptr - dec->pre_parser_wr_ptr) <
+			again_threshold) {
+			int r = vdec_sync_input(vdec);
+			avs2_print(dec,
+			PRINT_FLAG_VDEC_DETAIL, "%s buf lelvel:%x\n", __func__, r);
+			return 0;
+		}
+	}
+/*
+	if (vdec_stream_based(vdec) && (dec->pic_list_init_flag == 0)
+		&& pre_decode_buf_level != 0) {
+		u32 rp, wp, level;
+
+		rp = STBUF_READ(&vdec->vbuf, get_rp);
+		wp = STBUF_READ(&vdec->vbuf, get_wp);
+		if (wp < rp)
+			level = vdec->input.size + wp - rp;
+		else
+			level = wp - rp;
+
+		if (level < pre_decode_buf_level)
+			return 0;
+	}
+*/
+
+	if ((dec->pic_list_init_flag == 0) ||
+		get_free_buf_count(dec) >=
+		run_ready_min_buf_num)
+		ret = 1;
+#ifdef CONSTRAIN_MAX_BUF_NUM
+	if (dec->pic_list_init_flag) {
+		if (run_ready_max_vf_only_num > 0 &&
+			get_vf_ref_only_buf_count(dec) >=
+			run_ready_max_vf_only_num
+			)
+			ret = 0;
+		if (run_ready_display_q_num > 0 &&
+			kfifo_len(&dec->display_q) >=
+			run_ready_display_q_num)
+			ret = 0;
+
+		if (run_ready_max_buf_num == 0xff &&
+			get_used_buf_count(dec) >=
+			dec->avs2_dec.ref_maxbuffer)
+			ret = 0;
+		else if (run_ready_max_buf_num &&
+			get_used_buf_count(dec) >=
+			run_ready_max_buf_num)
+			ret = 0;
+	}
+#endif
+	if (ret)
+		not_run_ready[dec->index] = 0;
+	else
+		not_run_ready[dec->index]++;
+
+	if (vdec->parallel_dec == 1)
+		return ret ? CORE_MASK_HEVC : 0;
+	else
+		return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0;
+}
+
+static void run(struct vdec_s *vdec, unsigned long mask,
+	void (*callback)(struct vdec_s *, void *), void *arg)
+{
+	struct AVS2Decoder_s *dec =
+		(struct AVS2Decoder_s *)vdec->private;
+	int r;
+
+	run_count[dec->index]++;
+	dec->vdec_cb_arg = arg;
+	dec->vdec_cb = callback;
+	/* dec->chunk = vdec_prepare_input(vdec); */
+	hevc_reset_core(vdec);
+
+	if (vdec_stream_based(vdec)) {
+		dec->pre_parser_wr_ptr =
+			STBUF_READ(&vdec->vbuf, get_wp);
+		dec->next_again_flag = 0;
+	}
+
+	r = vdec_prepare_input(vdec, &dec->chunk);
+	if (r < 0) {
+		input_empty[dec->index]++;
+
+		dec->dec_result = DEC_RESULT_AGAIN;
+
+		avs2_print(dec, PRINT_FLAG_VDEC_DETAIL,
+			"ammvdec_vh265: Insufficient data\n");
+
+		vdec_schedule_work(&dec->work);
+		return;
+	}
+	input_empty[dec->index] = 0;
+	dec->dec_result = DEC_RESULT_NONE;
+	dec->start_shift_bytes = READ_VREG(HEVC_SHIFT_BYTE_COUNT);
+
+	if (debug & PRINT_FLAG_VDEC_STATUS) {
+		int ii;
+		avs2_print(dec, 0,
+			"%s (%d): size 0x%x (0x%x 0x%x) sum 0x%x (%x %x %x %x %x) bytes 0x%x",
+			__func__,
+			dec->frame_count, r,
+			dec->chunk ? dec->chunk->size : 0,
+			dec->chunk ? dec->chunk->offset : 0,
+			dec->chunk ? ((vdec_frame_based(vdec) &&
+			(debug & PRINT_FLAG_VDEC_STATUS)) ?
+			get_data_check_sum(dec, r) : 0) : 0,
+		READ_VREG(HEVC_STREAM_START_ADDR),
+		READ_VREG(HEVC_STREAM_END_ADDR),
+		READ_VREG(HEVC_STREAM_LEVEL),
+		READ_VREG(HEVC_STREAM_WR_PTR),
+		READ_VREG(HEVC_STREAM_RD_PTR),
+		dec->start_shift_bytes);
+		if (vdec_frame_based(vdec) && dec->chunk) {
+			u8 *data = NULL;
+			if (!dec->chunk->block->is_mapped)
+				data = codec_mm_vmap(dec->chunk->block->start +
+					dec->chunk->offset, 8);
+			else
+				data = ((u8 *)dec->chunk->block->start_virt) +
+					dec->chunk->offset;
+
+			avs2_print_cont(dec, 0, "data adr %p:",
+				data);
+			for (ii = 0; ii < 8; ii++)
+				avs2_print_cont(dec, 0, "%02x ",
+					data[ii]);
+			if (!dec->chunk->block->is_mapped)
+				codec_mm_unmap_phyaddr(data);
+		}
+		avs2_print_cont(dec, 0, "\r\n");
+	}
+	if (vdec->mc_loaded) {
+		/*firmware have load before,
+		  and not changes to another.
+		  ignore reload.
+		*/
+	} else if (amhevc_loadmc_ex(VFORMAT_AVS2, NULL, dec->fw->data) < 0) {
+		vdec->mc_loaded = 0;
+		amhevc_disable();
+		avs2_print(dec, 0,
+			"%s: Error amvdec_loadmc fail\n", __func__);
+		dec->dec_result = DEC_RESULT_FORCE_EXIT;
+		vdec_schedule_work(&dec->work);
+		return;
+	} else {
+		vdec->mc_loaded = 1;
+		vdec->mc_type = VFORMAT_AVS2;
+	}
+
+
+	if (avs2_hw_ctx_restore(dec) < 0) {
+		vdec_schedule_work(&dec->work);
+		return;
+	}
+
+	vdec_enable_input(vdec);
+
+	WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_SEARCH_NEW_PIC);
+
+	if (vdec_frame_based(vdec) && dec->chunk) {
+		if (debug & PRINT_FLAG_VDEC_DATA)
+			dump_data(dec, dec->chunk->size);
+
+		WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0);
+		r = dec->chunk->size +
+			(dec->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+		if (vdec->mvfrm)
+			vdec->mvfrm->frame_size = dec->chunk->size;
+	}
+
+	WRITE_VREG(HEVC_DECODE_SIZE, r);
+	WRITE_VREG(HEVC_DECODE_COUNT, dec->slice_idx);
+	dec->init_flag = 1;
+
+	avs2_print(dec, PRINT_FLAG_VDEC_DETAIL,
+		"%s: start hevc (%x %x %x)\n",
+		__func__,
+		READ_VREG(HEVC_DEC_STATUS_REG),
+		READ_VREG(HEVC_MPC_E),
+		READ_VREG(HEVC_MPSR));
+
+	start_process_time(dec);
+	mod_timer(&dec->timer, jiffies);
+	dec->stat |= STAT_TIMER_ARM;
+	dec->stat |= STAT_ISR_REG;
+	if (vdec->mvfrm)
+		vdec->mvfrm->hw_decode_start = local_clock();
+	amhevc_start();
+	dec->stat |= STAT_VDEC_RUN;
+}
+
+static void reset(struct vdec_s *vdec)
+{
+
+	struct AVS2Decoder_s *dec =
+		(struct AVS2Decoder_s *)vdec->private;
+
+	avs2_print(dec,
+		PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__);
+
+}
+
+static irqreturn_t avs2_irq_cb(struct vdec_s *vdec, int irq)
+{
+	struct AVS2Decoder_s *dec =
+		(struct AVS2Decoder_s *)vdec->private;
+	return vavs2_isr(0, dec);
+}
+
+static irqreturn_t avs2_threaded_irq_cb(struct vdec_s *vdec, int irq)
+{
+	struct AVS2Decoder_s *dec =
+		(struct AVS2Decoder_s *)vdec->private;
+	return vavs2_isr_thread_fn(0, dec);
+}
+
+static void avs2_dump_state(struct vdec_s *vdec)
+{
+	struct AVS2Decoder_s *dec =
+		(struct AVS2Decoder_s *)vdec->private;
+	int i;
+	avs2_print(dec, 0, "====== %s\n", __func__);
+
+	avs2_print(dec, 0,
+		"width/height (%d/%d), used_buf_num %d\n",
+		dec->avs2_dec.img.width,
+		dec->avs2_dec.img.height,
+		dec->used_buf_num
+		);
+
+	avs2_print(dec, 0,
+		"is_framebase(%d), eos %d, dec_result 0x%x dec_frm %d disp_frm %d run %d not_run_ready %d input_empty %d\n",
+		input_frame_based(vdec),
+		dec->eos,
+		dec->dec_result,
+		decode_frame_count[dec->index],
+		display_frame_count[dec->index],
+		run_count[dec->index],
+		not_run_ready[dec->index],
+		input_empty[dec->index]
+		);
+
+	if (vf_get_receiver(vdec->vf_provider_name)) {
+		enum receviver_start_e state =
+		vf_notify_receiver(vdec->vf_provider_name,
+			VFRAME_EVENT_PROVIDER_QUREY_STATE,
+			NULL);
+		avs2_print(dec, 0,
+			"\nreceiver(%s) state %d\n",
+			vdec->vf_provider_name,
+			state);
+	}
+
+	avs2_print(dec, 0,
+	"%s, newq(%d/%d), dispq(%d/%d), vf prepare/get/put (%d/%d/%d), free_buf_count %d (min %d for run_ready)\n",
+	__func__,
+	kfifo_len(&dec->newframe_q),
+	VF_POOL_SIZE,
+	kfifo_len(&dec->display_q),
+	VF_POOL_SIZE,
+	dec->vf_pre_count,
+	dec->vf_get_count,
+	dec->vf_put_count,
+	get_free_buf_count(dec),
+	run_ready_min_buf_num
+	);
+
+	dump_pic_list(dec);
+
+	for (i = 0; i < MAX_BUF_NUM; i++) {
+		avs2_print(dec, 0,
+			"mv_Buf(%d) start_adr 0x%x size 0x%x used %d\n",
+			i,
+			dec->m_mv_BUF[i].start_adr,
+			dec->m_mv_BUF[i].size,
+			dec->m_mv_BUF[i].used_flag);
+	}
+
+	avs2_print(dec, 0,
+		"HEVC_DEC_STATUS_REG=0x%x\n",
+		READ_VREG(HEVC_DEC_STATUS_REG));
+	avs2_print(dec, 0,
+		"HEVC_MPC_E=0x%x\n",
+		READ_VREG(HEVC_MPC_E));
+	avs2_print(dec, 0,
+		"DECODE_MODE=0x%x\n",
+		READ_VREG(DECODE_MODE));
+	avs2_print(dec, 0,
+		"NAL_SEARCH_CTL=0x%x\n",
+		READ_VREG(NAL_SEARCH_CTL));
+	avs2_print(dec, 0,
+		"HEVC_PARSER_LCU_START=0x%x\n",
+		READ_VREG(HEVC_PARSER_LCU_START));
+	avs2_print(dec, 0,
+		"HEVC_DECODE_SIZE=0x%x\n",
+		READ_VREG(HEVC_DECODE_SIZE));
+	avs2_print(dec, 0,
+		"HEVC_SHIFT_BYTE_COUNT=0x%x\n",
+		READ_VREG(HEVC_SHIFT_BYTE_COUNT));
+	avs2_print(dec, 0,
+		"HEVC_STREAM_START_ADDR=0x%x\n",
+		READ_VREG(HEVC_STREAM_START_ADDR));
+	avs2_print(dec, 0,
+		"HEVC_STREAM_END_ADDR=0x%x\n",
+		READ_VREG(HEVC_STREAM_END_ADDR));
+	avs2_print(dec, 0,
+		"HEVC_STREAM_LEVEL=0x%x\n",
+		READ_VREG(HEVC_STREAM_LEVEL));
+	avs2_print(dec, 0,
+		"HEVC_STREAM_WR_PTR=0x%x\n",
+		READ_VREG(HEVC_STREAM_WR_PTR));
+	avs2_print(dec, 0,
+		"HEVC_STREAM_RD_PTR=0x%x\n",
+		READ_VREG(HEVC_STREAM_RD_PTR));
+	avs2_print(dec, 0,
+		"PARSER_VIDEO_RP=0x%x\n",
+		STBUF_READ(&vdec->vbuf, get_rp));
+	avs2_print(dec, 0,
+		"PARSER_VIDEO_WP=0x%x\n",
+		STBUF_READ(&vdec->vbuf, get_wp));
+
+	if (input_frame_based(vdec) &&
+		(debug & PRINT_FLAG_VDEC_DATA)
+		) {
+		int jj;
+		if (dec->chunk && dec->chunk->block &&
+			dec->chunk->size > 0) {
+			u8 *data = NULL;
+			if (!dec->chunk->block->is_mapped)
+				data = codec_mm_vmap(dec->chunk->block->start +
+					dec->chunk->offset, dec->chunk->size);
+			else
+				data = ((u8 *)dec->chunk->block->start_virt) +
+					dec->chunk->offset;
+			avs2_print(dec, 0,
+				"frame data size 0x%x\n",
+				dec->chunk->size);
+			for (jj = 0; jj < dec->chunk->size; jj++) {
+				if ((jj & 0xf) == 0)
+					avs2_print(dec, 0,
+						"%06x:", jj);
+				avs2_print_cont(dec, 0,
+					"%02x ", data[jj]);
+				if (((jj + 1) & 0xf) == 0)
+					avs2_print_cont(dec, 0,
+						"\n");
+			}
+
+			if (!dec->chunk->block->is_mapped)
+				codec_mm_unmap_phyaddr(data);
+		}
+	}
+
+}
+
+static int ammvdec_avs2_probe(struct platform_device *pdev)
+{
+	struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
+	int ret;
+	int config_val;
+	int i;
+	struct vframe_content_light_level_s content_light_level;
+	struct vframe_master_display_colour_s vf_dp;
+	/*struct BUF_s BUF[MAX_BUF_NUM];*/
+	struct AVS2Decoder_s *dec = NULL;
+
+	pr_info("%s\n", __func__);
+	if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5D) {
+		pr_info("%s, chip id %d is not support avs2\n",
+			__func__, get_cpu_major_id());
+		return -1;
+	}
+	if (pdata == NULL) {
+		pr_info("\nammvdec_avs2 memory resource undefined.\n");
+		return -EFAULT;
+	}
+	/*dec = (struct AVS2Decoder_s *)devm_kzalloc(&pdev->dev,
+		sizeof(struct AVS2Decoder_s), GFP_KERNEL);*/
+	memset(&vf_dp, 0, sizeof(struct vframe_master_display_colour_s));
+	dec = vzalloc(sizeof(struct AVS2Decoder_s));
+	if (dec == NULL) {
+		pr_info("\nammvdec_avs2 device data allocation failed\n");
+		return -ENOMEM;
+	}
+	if (pdata->parallel_dec == 1) {
+		int i;
+		for (i = 0; i < AVS2_MAX_BUFFER_NUM; i++) {
+			dec->avs2_dec.frm_pool[i].y_canvas_index = -1;
+			dec->avs2_dec.frm_pool[i].uv_canvas_index = -1;
+		}
+	}
+	pdata->private = dec;
+	pdata->dec_status = vavs2_dec_status;
+#ifdef I_ONLY_SUPPORT
+	pdata->set_trickmode = vavs2_set_trickmode;
+#endif
+	pdata->run_ready = run_ready;
+	pdata->run = run;
+	pdata->reset = reset;
+	pdata->irq_handler = avs2_irq_cb;
+	pdata->threaded_irq_handler = avs2_threaded_irq_cb;
+	pdata->dump_state = avs2_dump_state;
+
+	/*
+	 * memcpy(&BUF[0], &dec->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
+	 * memset(dec, 0, sizeof(struct AVS2Decoder_s));
+	 * memcpy(&dec->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
+	 */
+
+	dec->index = pdev->id;
+	dec->m_ins_flag = 1;
+	if (is_rdma_enable()) {
+		dec->rdma_adr = dma_alloc_coherent(amports_get_dma_device(), RDMA_SIZE, &dec->rdma_phy_adr, GFP_KERNEL);
+		for (i = 0; i < SCALELUT_DATA_WRITE_NUM; i++) {
+			dec->rdma_adr[i * 4] = HEVC_IQIT_SCALELUT_WR_ADDR & 0xfff;
+			dec->rdma_adr[i * 4 + 1] = i;
+			dec->rdma_adr[i * 4 + 2] = HEVC_IQIT_SCALELUT_DATA & 0xfff;
+			dec->rdma_adr[i * 4 + 3] = 0;
+			if (i == SCALELUT_DATA_WRITE_NUM - 1) {
+				dec->rdma_adr[i * 4 + 2] = (HEVC_IQIT_SCALELUT_DATA & 0xfff) | 0x20000;
+			}
+		}
+	}
+
+	snprintf(dec->vdec_name, sizeof(dec->vdec_name),
+		"avs2-%d", dec->index);
+	snprintf(dec->pts_name, sizeof(dec->pts_name),
+		"%s-pts", dec->vdec_name);
+	snprintf(dec->new_q_name, sizeof(dec->new_q_name),
+		"%s-newframe_q", dec->vdec_name);
+	snprintf(dec->disp_q_name, sizeof(dec->disp_q_name),
+		"%s-dispframe_q", dec->vdec_name);
+
+	if (pdata->use_vfm_path) {
+		snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
+			VFM_DEC_PROVIDER_NAME);
+		dec->frameinfo_enable = 1;
+	} else
+		snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
+			MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff);
+
+	vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
+		&vavs2_vf_provider, dec);
+
+	dec->provider_name = pdata->vf_provider_name;
+	platform_set_drvdata(pdev, pdata);
+
+	dec->platform_dev = pdev;
+	dec->video_signal_type = 0;
+	dec->video_ori_signal_type = 0;
+	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TXLX)
+		dec->stat |= VP9_TRIGGER_FRAME_ENABLE;
+
+	if ((debug & IGNORE_PARAM_FROM_CONFIG) == 0 && pdata->config_len) {
+		/*use ptr config for doubel_write_mode, etc*/
+		avs2_print(dec, 0, "pdata->config=%s\n", pdata->config);
+		if (get_config_int(pdata->config, "avs2_double_write_mode",
+				&config_val) == 0)
+			dec->double_write_mode = config_val;
+		else
+			dec->double_write_mode = double_write_mode;
+
+		if (get_config_int(pdata->config, "parm_v4l_buffer_margin",
+			&config_val) == 0)
+			dec->dynamic_buf_margin = config_val;
+		else
+			dec->dynamic_buf_margin = 0;
+
+		if (get_config_int(pdata->config, "sidebind_type",
+				&config_val) == 0)
+			dec->sidebind_type = config_val;
+
+		if (get_config_int(pdata->config, "sidebind_channel_id",
+				&config_val) == 0)
+			dec->sidebind_channel_id = config_val;
+
+		if (get_config_int(pdata->config, "HDRStaticInfo",
+				&vf_dp.present_flag) == 0
+				&& vf_dp.present_flag == 1) {
+			get_config_int(pdata->config, "mG.x",
+					&vf_dp.primaries[0][0]);
+			get_config_int(pdata->config, "mG.y",
+					&vf_dp.primaries[0][1]);
+			get_config_int(pdata->config, "mB.x",
+					&vf_dp.primaries[1][0]);
+			get_config_int(pdata->config, "mB.y",
+					&vf_dp.primaries[1][1]);
+			get_config_int(pdata->config, "mR.x",
+					&vf_dp.primaries[2][0]);
+			get_config_int(pdata->config, "mR.y",
+					&vf_dp.primaries[2][1]);
+			get_config_int(pdata->config, "mW.x",
+					&vf_dp.white_point[0]);
+			get_config_int(pdata->config, "mW.y",
+					&vf_dp.white_point[1]);
+			get_config_int(pdata->config, "mMaxDL",
+					&vf_dp.luminance[0]);
+			get_config_int(pdata->config, "mMinDL",
+					&vf_dp.luminance[1]);
+			vf_dp.content_light_level.present_flag = 1;
+			get_config_int(pdata->config, "mMaxCLL",
+					&content_light_level.max_content);
+			get_config_int(pdata->config, "mMaxFALL",
+					&content_light_level.max_pic_average);
+			vf_dp.content_light_level = content_light_level;
+			dec->video_signal_type = (1 << 29)
+					| (5 << 26)	/* unspecified */
+					| (0 << 25)	/* limit */
+					| (1 << 24)	/* color available */
+					| (9 << 16)	/* 2020 */
+					| (16 << 8)	/* 2084 */
+					| (9 << 0);	/* 2020 */
+		}
+		dec->vf_dp = vf_dp;
+	} else {
+		/*dec->vavs2_amstream_dec_info.width = 0;
+		dec->vavs2_amstream_dec_info.height = 0;
+		dec->vavs2_amstream_dec_info.rate = 30;*/
+		dec->double_write_mode = double_write_mode;
+		dec->dynamic_buf_margin = dynamic_buf_num_margin;
+	}
+	video_signal_type = dec->video_signal_type;
+
+	if (double_write_mode) {
+		dec->double_write_mode = get_double_write_mode(dec);
+	}
+
+	if ((dec->double_write_mode & 0x10) == 0)
+		dec->mmu_enable = 1;
+
+#ifdef AVS2_10B_MMU_DW
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T5D) {
+		dec->dw_mmu_enable =
+			(get_double_write_mode(dec) & 0x20) ? 1 : 0;
+	} else {
+		dec->dw_mmu_enable = 0;
+	}
+#endif
+	if (amvdec_avs2_mmu_init(dec) < 0) {
+		pr_err("avs2 alloc bmmu box failed!!\n");
+		/* devm_kfree(&pdev->dev, (void *)dec); */
+		vfree((void *)dec);
+		return -1;
+	}
+	dec->cma_alloc_count = PAGE_ALIGN(work_buf_size) / PAGE_SIZE;
+	ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, WORK_SPACE_BUF_ID,
+			dec->cma_alloc_count * PAGE_SIZE, DRIVER_NAME,
+			&dec->cma_alloc_addr);
+	if (ret < 0) {
+		uninit_mmu_buffers(dec);
+		/* devm_kfree(&pdev->dev, (void *)dec); */
+		vfree((void *)dec);
+		return ret;
+	}
+	dec->buf_start = dec->cma_alloc_addr;
+	dec->buf_size = work_buf_size;
+
+	dec->init_flag = 0;
+	dec->first_sc_checked = 0;
+	dec->fatal_error = 0;
+	dec->show_frame_num = 0;
+
+	if (debug) {
+		pr_info("===AVS2 decoder mem resource 0x%lx size 0x%x\n",
+			   dec->buf_start,
+			   dec->buf_size);
+	}
+
+	if (pdata->sys_info) {
+		dec->vavs2_amstream_dec_info = *pdata->sys_info;
+		dec->frame_width = dec->vavs2_amstream_dec_info.width;
+		dec->frame_height = dec->vavs2_amstream_dec_info.height;
+	} else {
+		dec->vavs2_amstream_dec_info.width = 0;
+		dec->vavs2_amstream_dec_info.height = 0;
+		dec->vavs2_amstream_dec_info.rate = 30;
+	}
+
+	dec->endian = HEVC_CONFIG_LITTLE_ENDIAN;
+	if (is_support_vdec_canvas())
+		dec->endian = HEVC_CONFIG_BIG_ENDIAN;
+	if (endian)
+		dec->endian = endian;
+
+	dec->cma_dev = pdata->cma_dev;
+	if (vavs2_init(pdata) < 0) {
+		pr_info("\namvdec_avs2 init failed.\n");
+		avs2_local_uninit(dec);
+		uninit_mmu_buffers(dec);
+		/* devm_kfree(&pdev->dev, (void *)dec); */
+		vfree((void *)dec);
+		pdata->dec_status = NULL;
+		return -ENODEV;
+	}
+	vdec_set_prepare_level(pdata, start_decode_buf_level);
+	hevc_source_changed(VFORMAT_AVS2,
+			4096, 2048, 60);
+	if (pdata->parallel_dec == 1)
+		vdec_core_request(pdata, CORE_MASK_HEVC);
+	else {
+		vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+				| CORE_MASK_COMBINE);
+	}
+
+	return 0;
+}
+
+static int ammvdec_avs2_remove(struct platform_device *pdev)
+{
+	struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)
+		(((struct vdec_s *)(platform_get_drvdata(pdev)))->private);
+	struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
+	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+	struct avs2_frame_s *pic;
+	int i;
+
+	if (debug)
+		pr_info("amvdec_avs2_remove\n");
+
+	vmavs2_stop(dec);
+
+	if (pdata->parallel_dec == 1)
+		vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC);
+	else
+		vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC);
+
+	vdec_set_status(hw_to_vdec(dec), VDEC_STATUS_DISCONNECTED);
+	if (pdata->parallel_dec == 1) {
+		for (i = 0; i < AVS2_MAX_BUFFER_NUM; i++) {
+			pdata->free_canvas_ex(dec->avs2_dec.frm_pool[i].y_canvas_index, pdata->id);
+			pdata->free_canvas_ex(dec->avs2_dec.frm_pool[i].uv_canvas_index, pdata->id);
+		}
+	}
+
+	for (i = 0; i < dec->used_buf_num; i++) {
+		if (i == (dec->used_buf_num - 1))
+			pic = avs2_dec->m_bg;
+		else
+			pic = avs2_dec->fref[i];
+		release_cuva_data(pic);
+	}
+
+
+#ifdef DEBUG_PTS
+	pr_info("pts missed %ld, pts hit %ld, duration %d\n",
+		   dec->pts_missed, dec->pts_hit, dec->frame_dur);
+#endif
+	if (is_rdma_enable())
+		dma_free_coherent(amports_get_dma_device(), RDMA_SIZE, dec->rdma_adr, dec->rdma_phy_adr);
+	/* devm_kfree(&pdev->dev, (void *)dec); */
+	vfree((void *)dec);
+	return 0;
+}
+
+static struct platform_driver ammvdec_avs2_driver = {
+	.probe = ammvdec_avs2_probe,
+	.remove = ammvdec_avs2_remove,
+#ifdef CONFIG_PM
+	.suspend = amvdec_suspend,
+	.resume = amvdec_resume,
+#endif
+	.driver = {
+		.name = MULTI_DRIVER_NAME,
+	}
+};
+#endif
+static struct mconfig avs2_configs[] = {
+	MC_PU32("bit_depth_luma", &bit_depth_luma),
+	MC_PU32("bit_depth_chroma", &bit_depth_chroma),
+	MC_PU32("frame_width", &frame_width),
+	MC_PU32("frame_height", &frame_height),
+	MC_PU32("debug", &debug),
+	MC_PU32("radr", &radr),
+	MC_PU32("rval", &rval),
+	MC_PU32("pop_shorts", &pop_shorts),
+	MC_PU32("dbg_cmd", &dbg_cmd),
+	MC_PU32("dbg_skip_decode_index", &dbg_skip_decode_index),
+	MC_PU32("endian", &endian),
+	MC_PU32("step", &step),
+	MC_PU32("udebug_flag", &udebug_flag),
+	MC_PU32("decode_pic_begin", &decode_pic_begin),
+	MC_PU32("slice_parse_begin", &slice_parse_begin),
+	MC_PU32("i_only_flag", &i_only_flag),
+	MC_PU32("error_handle_policy", &error_handle_policy),
+	MC_PU32("buf_alloc_width", &buf_alloc_width),
+	MC_PU32("buf_alloc_height", &buf_alloc_height),
+	MC_PU32("buf_alloc_depth", &buf_alloc_depth),
+	MC_PU32("buf_alloc_size", &buf_alloc_size),
+	MC_PU32("buffer_mode", &buffer_mode),
+	MC_PU32("buffer_mode_dbg", &buffer_mode_dbg),
+	MC_PU32("max_buf_num", &max_buf_num),
+	MC_PU32("dynamic_buf_num_margin", &dynamic_buf_num_margin),
+	MC_PU32("mem_map_mode", &mem_map_mode),
+	MC_PU32("double_write_mode", &double_write_mode),
+	MC_PU32("enable_mem_saving", &enable_mem_saving),
+	MC_PU32("force_w_h", &force_w_h),
+	MC_PU32("force_fps", &force_fps),
+	MC_PU32("max_decoding_time", &max_decoding_time),
+	MC_PU32("on_no_keyframe_skiped", &on_no_keyframe_skiped),
+	MC_PU32("start_decode_buf_level", &start_decode_buf_level),
+	MC_PU32("decode_timeout_val", &decode_timeout_val),
+};
+static struct mconfig_node avs2_node;
+
+static int __init amvdec_avs2_driver_init_module(void)
+{
+
+#ifdef AVS2_10B_MMU
+	struct BuffInfo_s *p_buf_info;
+
+	if (get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_TM2 && !is_cpu_tm2_revb()) {
+		if (vdec_is_support_4k()) {
+			if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)
+				p_buf_info = &amvavs2_workbuff_spec[2];
+			else
+				p_buf_info = &amvavs2_workbuff_spec[1];
+		} else
+			p_buf_info = &amvavs2_workbuff_spec[0];
+	} else { //get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_TM2 || is_cpu_tm2_revb()
+		if (vdec_is_support_4k()) {
+			p_buf_info = &amvavs2_workbuff_spec[5];
+		} else
+			p_buf_info = &amvavs2_workbuff_spec[3];
+	}
+
+	init_buff_spec(NULL, p_buf_info);
+	work_buf_size =
+		(p_buf_info->end_adr - p_buf_info->start_adr
+		 + 0xffff) & (~0xffff);
+
+#endif
+	pr_debug("amvdec_avs2 module init\n");
+
+#ifdef ERROR_HANDLE_DEBUG
+	dbg_nal_skip_flag = 0;
+	dbg_nal_skip_count = 0;
+#endif
+	udebug_flag = 0;
+	decode_pic_begin = 0;
+	slice_parse_begin = 0;
+	step = 0;
+	buf_alloc_size = 0;
+	if (platform_driver_register(&ammvdec_avs2_driver))
+		pr_err("failed to register ammvdec_avs2 driver\n");
+
+	if (platform_driver_register(&amvdec_avs2_driver)) {
+		pr_err("failed to register amvdec_avs2 driver\n");
+		return -ENODEV;
+	}
+
+	if ((get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) ||
+		(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5D)) {
+		amvdec_avs2_profile.name = "avs2_unsupport";
+	} else if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SM1) {
+		if (vdec_is_support_4k())
+			amvdec_avs2_profile.profile =
+				"4k, 10bit, dwrite, compressed";
+		else
+			amvdec_avs2_profile.profile =
+				"10bit, dwrite, compressed";
+	} else {
+		/* cpu id larger than sm1 support 8k */
+		amvdec_avs2_profile.profile =
+				"8k, 10bit, dwrite, compressed";
+	}
+
+	vcodec_profile_register(&amvdec_avs2_profile);
+	amvdec_avs2_profile_mult = amvdec_avs2_profile;
+	amvdec_avs2_profile_mult.name = "mavs2";
+	vcodec_profile_register(&amvdec_avs2_profile_mult);
+
+	INIT_REG_NODE_CONFIGS("media.decoder", &avs2_node,
+		"avs2", avs2_configs, CONFIG_FOR_RW);
+	vcodec_feature_register(VFORMAT_AVS2, 0);
+
+	return 0;
+}
+
+static void __exit amvdec_avs2_driver_remove_module(void)
+{
+	pr_debug("amvdec_avs2 module remove.\n");
+	platform_driver_unregister(&ammvdec_avs2_driver);
+	platform_driver_unregister(&amvdec_avs2_driver);
+}
+
+/****************************************/
+
+module_param(bit_depth_luma, uint, 0664);
+MODULE_PARM_DESC(bit_depth_luma, "\n amvdec_avs2 bit_depth_luma\n");
+
+module_param(bit_depth_chroma, uint, 0664);
+MODULE_PARM_DESC(bit_depth_chroma, "\n amvdec_avs2 bit_depth_chroma\n");
+
+module_param(frame_width, uint, 0664);
+MODULE_PARM_DESC(frame_width, "\n amvdec_avs2 frame_width\n");
+
+module_param(frame_height, uint, 0664);
+MODULE_PARM_DESC(frame_height, "\n amvdec_avs2 frame_height\n");
+
+module_param(debug, uint, 0664);
+MODULE_PARM_DESC(debug, "\n amvdec_avs2 debug\n");
+
+module_param(debug_again, uint, 0664);
+MODULE_PARM_DESC(debug_again, "\n amvdec_avs2 debug_again\n");
+
+module_param(radr, uint, 0664);
+MODULE_PARM_DESC(radr, "\nradr\n");
+
+module_param(rval, uint, 0664);
+MODULE_PARM_DESC(rval, "\nrval\n");
+
+module_param(pop_shorts, uint, 0664);
+MODULE_PARM_DESC(pop_shorts, "\nrval\n");
+
+module_param(dbg_cmd, uint, 0664);
+MODULE_PARM_DESC(dbg_cmd, "\ndbg_cmd\n");
+
+module_param(dbg_skip_decode_index, uint, 0664);
+MODULE_PARM_DESC(dbg_skip_decode_index, "\ndbg_skip_decode_index\n");
+
+module_param(endian, uint, 0664);
+MODULE_PARM_DESC(endian, "\nrval\n");
+
+module_param(step, uint, 0664);
+MODULE_PARM_DESC(step, "\n amvdec_avs2 step\n");
+
+module_param(decode_pic_begin, uint, 0664);
+MODULE_PARM_DESC(decode_pic_begin, "\n amvdec_avs2 decode_pic_begin\n");
+
+module_param(slice_parse_begin, uint, 0664);
+MODULE_PARM_DESC(slice_parse_begin, "\n amvdec_avs2 slice_parse_begin\n");
+
+module_param(i_only_flag, uint, 0664);
+MODULE_PARM_DESC(i_only_flag, "\n amvdec_avs2 i_only_flag\n");
+
+module_param(error_handle_policy, uint, 0664);
+MODULE_PARM_DESC(error_handle_policy, "\n amvdec_avs2 error_handle_policy\n");
+
+module_param(re_search_seq_threshold, uint, 0664);
+MODULE_PARM_DESC(re_search_seq_threshold, "\n amvdec_avs2 re_search_seq_threshold\n");
+
+module_param(buf_alloc_width, uint, 0664);
+MODULE_PARM_DESC(buf_alloc_width, "\n buf_alloc_width\n");
+
+module_param(buf_alloc_height, uint, 0664);
+MODULE_PARM_DESC(buf_alloc_height, "\n buf_alloc_height\n");
+
+module_param(buf_alloc_depth, uint, 0664);
+MODULE_PARM_DESC(buf_alloc_depth, "\n buf_alloc_depth\n");
+
+module_param(buf_alloc_size, uint, 0664);
+MODULE_PARM_DESC(buf_alloc_size, "\n buf_alloc_size\n");
+
+module_param(buffer_mode, uint, 0664);
+MODULE_PARM_DESC(buffer_mode, "\n buffer_mode\n");
+
+module_param(buffer_mode_dbg, uint, 0664);
+MODULE_PARM_DESC(buffer_mode_dbg, "\n buffer_mode_dbg\n");
+/*USE_BUF_BLOCK*/
+module_param(max_buf_num, uint, 0664);
+MODULE_PARM_DESC(max_buf_num, "\n max_buf_num\n");
+
+module_param(dynamic_buf_num_margin, uint, 0664);
+MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n");
+
+#ifdef CONSTRAIN_MAX_BUF_NUM
+module_param(run_ready_max_vf_only_num, uint, 0664);
+MODULE_PARM_DESC(run_ready_max_vf_only_num, "\n run_ready_max_vf_only_num\n");
+
+module_param(run_ready_display_q_num, uint, 0664);
+MODULE_PARM_DESC(run_ready_display_q_num, "\n run_ready_display_q_num\n");
+
+module_param(run_ready_max_buf_num, uint, 0664);
+MODULE_PARM_DESC(run_ready_max_buf_num, "\n run_ready_max_buf_num\n");
+#endif
+
+module_param(mv_buf_margin, uint, 0664);
+MODULE_PARM_DESC(mv_buf_margin, "\n mv_buf_margin\n");
+
+module_param(run_ready_min_buf_num, uint, 0664);
+MODULE_PARM_DESC(run_ready_min_buf_num, "\n run_ready_min_buf_num\n");
+
+/**/
+
+module_param(mem_map_mode, uint, 0664);
+MODULE_PARM_DESC(mem_map_mode, "\n mem_map_mode\n");
+
+module_param(double_write_mode, uint, 0664);
+MODULE_PARM_DESC(double_write_mode, "\n double_write_mode\n");
+
+module_param(enable_mem_saving, uint, 0664);
+MODULE_PARM_DESC(enable_mem_saving, "\n enable_mem_saving\n");
+
+module_param(force_w_h, uint, 0664);
+MODULE_PARM_DESC(force_w_h, "\n force_w_h\n");
+
+module_param(force_fps, uint, 0664);
+MODULE_PARM_DESC(force_fps, "\n force_fps\n");
+
+module_param(max_decoding_time, uint, 0664);
+MODULE_PARM_DESC(max_decoding_time, "\n max_decoding_time\n");
+
+module_param(on_no_keyframe_skiped, uint, 0664);
+MODULE_PARM_DESC(on_no_keyframe_skiped, "\n on_no_keyframe_skiped\n");
+
+
+module_param(start_decode_buf_level, int, 0664);
+MODULE_PARM_DESC(start_decode_buf_level,
+		"\n avs2 start_decode_buf_level\n");
+
+module_param(decode_timeout_val, uint, 0664);
+MODULE_PARM_DESC(decode_timeout_val,
+	"\n avs2 decode_timeout_val\n");
+
+module_param_array(decode_frame_count, uint,
+	&max_decode_instance_num, 0664);
+
+module_param_array(display_frame_count, uint,
+	&max_decode_instance_num, 0664);
+
+module_param_array(max_process_time, uint,
+	&max_decode_instance_num, 0664);
+
+module_param_array(run_count, uint,
+	&max_decode_instance_num, 0664);
+
+module_param_array(input_empty, uint,
+	&max_decode_instance_num, 0664);
+
+module_param_array(not_run_ready, uint,
+	&max_decode_instance_num, 0664);
+
+module_param(video_signal_type, uint, 0664);
+MODULE_PARM_DESC(video_signal_type, "\n amvdec_avs2 video_signal_type\n");
+
+module_param(force_video_signal_type, uint, 0664);
+MODULE_PARM_DESC(force_video_signal_type, "\n amvdec_avs2 force_video_signal_type\n");
+
+module_param(enable_force_video_signal_type, uint, 0664);
+MODULE_PARM_DESC(enable_force_video_signal_type, "\n amvdec_avs2 enable_force_video_signal_type\n");
+
+module_param(force_bufspec, uint, 0664);
+MODULE_PARM_DESC(force_bufspec, "\n amvdec_h265 force_bufspec\n");
+
+module_param(udebug_flag, uint, 0664);
+MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n");
+
+module_param(udebug_pause_pos, uint, 0664);
+MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n");
+
+module_param(udebug_pause_val, uint, 0664);
+MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n");
+
+module_param(udebug_pause_decode_idx, uint, 0664);
+MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n");
+
+module_param(pre_decode_buf_level, int, 0664);
+MODULE_PARM_DESC(pre_decode_buf_level,
+		"\n amvdec_avs2 pre_decode_buf_level\n");
+
+module_param(again_threshold, uint, 0664);
+MODULE_PARM_DESC(again_threshold, "\n again_threshold\n");
+
+
+module_param(force_disp_pic_index, int, 0664);
+MODULE_PARM_DESC(force_disp_pic_index,
+	"\n amvdec_h265 force_disp_pic_index\n");
+
+module_param(without_display_mode, uint, 0664);
+MODULE_PARM_DESC(without_display_mode, "\n without_display_mode\n");
+
+module_param(mv_buf_dynamic_alloc, uint, 0664);
+MODULE_PARM_DESC(mv_buf_dynamic_alloc, "\n mv_buf_dynamic_alloc\n");
+
+module_init(amvdec_avs2_driver_init_module);
+module_exit(amvdec_avs2_driver_remove_module);
+
+MODULE_DESCRIPTION("AMLOGIC avs2 Video Decoder Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Tim Yao <tim.yao@amlogic.com>");
diff --git a/drivers/frame_provider/decoder/avs2/vavs2.h b/drivers/frame_provider/decoder/avs2/vavs2.h
new file mode 100644
index 0000000..071bfb3
--- /dev/null
+++ b/drivers/frame_provider/decoder/avs2/vavs2.h
@@ -0,0 +1,26 @@
+/*
+ * drivers/amlogic/amports/vavs2.h
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+*/
+
+#ifndef VAVS2_H
+#define VAVS2_H
+
+#define AVS2_10B_MMU
+#define AVS2_10B_MMU_DW
+
+void adapt_coef_probs(int pic_count, int prev_kf, int cur_kf, int pre_fc,
+unsigned int *prev_prob, unsigned int *cur_prob, unsigned int *count);
+#endif
diff --git a/drivers/frame_provider/decoder/avs_multi/Makefile b/drivers/frame_provider/decoder/avs_multi/Makefile
new file mode 100644
index 0000000..638cec0
--- /dev/null
+++ b/drivers/frame_provider/decoder/avs_multi/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_AVS_MULTI) += amvdec_mavs.o
+amvdec_mavs-objs += avs_multi.o
diff --git a/drivers/frame_provider/decoder/avs_multi/avs_multi.c b/drivers/frame_provider/decoder/avs_multi/avs_multi.c
new file mode 100644
index 0000000..7dd20bb
--- /dev/null
+++ b/drivers/frame_provider/decoder/avs_multi/avs_multi.c
@@ -0,0 +1,5030 @@
+/*
+ * drivers/amlogic/amports/vavs.c
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/semaphore.h>
+#include <linux/timer.h>
+#include <linux/kfifo.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../../../stream_input/amports/streambuf_reg.h"
+#include "../utils/amvdec.h"
+#include <linux/amlogic/media/registers/register.h>
+#include "../../../stream_input/amports/amports_priv.h"
+#include <linux/dma-mapping.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/slab.h>
+#include "avs_multi.h"
+#include <linux/amlogic/media/codec_mm/configs.h>
+#include "../utils/decoder_mmu_box.h"
+#include "../utils/decoder_bmmu_box.h"
+#include "../utils/firmware.h"
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+#include <linux/amlogic/tee.h>
+#include "../utils/vdec_feature.h"
+
+#define DEBUG_MULTI_FLAG  0
+/*
+#define DEBUG_WITH_SINGLE_MODE
+#define DEBUG_MULTI_WITH_AUTOMODE
+#define DEBUG_MULTI_FRAME_INS
+*/
+
+
+#define USE_DYNAMIC_BUF_NUM
+
+#ifdef DEBUG_WITH_SINGLE_MODE
+#define DRIVER_NAME "amvdec_avs"
+#else
+#define DRIVER_NAME "ammvdec_avs"
+#endif
+
+#define MULTI_DRIVER_NAME "ammvdec_avs"
+
+#define ENABLE_USER_DATA
+
+#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
+#define NV21
+#endif
+
+#define USE_AVS_SEQ_INFO
+#define HANDLE_AVS_IRQ
+#define DEBUG_PTS
+
+#define CHECK_INTERVAL        (HZ/100)
+
+#define I_PICTURE   0
+#define P_PICTURE   1
+#define B_PICTURE   2
+
+#define LMEM_BUF_SIZE (0x500 * 2)
+
+/* #define ORI_BUFFER_START_ADDR   0x81000000 */
+#define ORI_BUFFER_START_ADDR   0x80000000
+
+#define INTERLACE_FLAG          0x80
+#define TOP_FIELD_FIRST_FLAG 0x40
+
+/* protocol registers */
+#define AVS_PIC_RATIO       AV_SCRATCH_0
+#define AVS_PIC_WIDTH      AV_SCRATCH_1
+#define AVS_PIC_HEIGHT     AV_SCRATCH_2
+#define AVS_FRAME_RATE     AV_SCRATCH_3
+
+/*#define AVS_ERROR_COUNT    AV_SCRATCH_6*/
+#define AVS_SOS_COUNT     AV_SCRATCH_7
+#define AVS_BUFFERIN       AV_SCRATCH_8
+#define AVS_BUFFEROUT      AV_SCRATCH_9
+#define AVS_REPEAT_COUNT    AV_SCRATCH_A
+#define AVS_TIME_STAMP      AV_SCRATCH_B
+#define AVS_OFFSET_REG      AV_SCRATCH_C
+#define MEM_OFFSET_REG      AV_SCRATCH_F
+#define AVS_ERROR_RECOVERY_MODE   AV_SCRATCH_G
+#define DECODE_PIC_COUNT     AV_SCRATCH_G
+
+#define DECODE_MODE		AV_SCRATCH_6
+#define DECODE_MODE_SINGLE					0x0
+#define DECODE_MODE_MULTI_FRAMEBASE			0x1
+#define DECODE_MODE_MULTI_STREAMBASE		0x2
+#define DECODE_MODE_MULTI_STREAMBASE_CONT   0x3
+
+#define DECODE_STATUS	AV_SCRATCH_H
+#define DECODE_STATUS_PIC_DONE    0x1
+#define DECODE_STATUS_DECODE_BUF_EMPTY	0x2
+#define DECODE_STATUS_SEARCH_BUF_EMPTY	0x3
+#define DECODE_STATUS_SKIP_PIC_DONE     0x4
+#define DECODE_SEARCH_HEAD	0xff
+
+#define DECODE_STOP_POS		AV_SCRATCH_J
+
+#define DECODE_LMEM_BUF_ADR   AV_SCRATCH_I
+
+#define DECODE_CFG            AV_SCRATCH_K
+
+#define VF_POOL_SIZE        64
+#define PUT_INTERVAL        (HZ/100)
+
+#if 1 /*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8*/
+#define INT_AMVENCODER INT_DOS_MAILBOX_1
+#else
+/* #define AMVENC_DEV_VERSION "AML-MT" */
+#define INT_AMVENCODER INT_MAILBOX_1A
+#endif
+
+#ifdef USE_DYNAMIC_BUF_NUM
+static unsigned int buf_spec_reg[] = {
+	AV_SCRATCH_0,
+	AV_SCRATCH_1,
+	AV_SCRATCH_2,
+	AV_SCRATCH_3,
+	AV_SCRATCH_7, /*AVS_SOS_COUNT*/
+	AV_SCRATCH_D, /*DEBUG_REG2*/
+	AV_SCRATCH_E, /*DEBUG_REG1*/
+	AV_SCRATCH_M  /*user_data_poc_number*/
+};
+#endif
+
+#define DEBUG_REG1	AV_SCRATCH_E
+#define DEBUG_REG2	AV_SCRATCH_D
+
+
+static void check_timer_func(struct timer_list *timer);
+static void vavs_work(struct work_struct *work);
+
+#define DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE 0x0001
+static u32 dec_control = DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE;
+
+
+#define VPP_VD1_POSTBLEND       (1 << 10)
+
+static int debug;
+static unsigned int debug_mask = 0xff;
+
+/*for debug*/
+/*
+	udebug_flag:
+	bit 0, enable ucode print
+	bit 1, enable ucode more print
+	bit 3, enable ucdode detail print
+	bit [31:16] not 0, pos to dump lmem
+		bit 2, pop bits to lmem
+		bit [11:8], pre-pop bits for alignment (when bit 2 is 1)
+
+	avs only:
+	bit [8], disable empty muitl-instance handling
+	bit [9], enable writting of VC1_CONTROL_REG in ucode
+*/
+static u32 udebug_flag;
+/*
+	when udebug_flag[1:0] is not 0
+	udebug_pause_pos not 0,
+		pause position
+*/
+static u32 udebug_pause_pos;
+/*
+	when udebug_flag[1:0] is not 0
+	and udebug_pause_pos is not 0,
+		pause only when DEBUG_REG2 is equal to this val
+*/
+static u32 udebug_pause_val;
+
+static u32 udebug_pause_decode_idx;
+
+static u32 udebug_pause_ins_id;
+
+static u32 force_fps;
+
+#ifdef DEBUG_MULTI_FRAME_INS
+static u32 delay;
+#endif
+
+static u32 step;
+
+static u32 start_decoding_delay;
+
+#define AVS_DEV_NUM        9
+static unsigned int max_decode_instance_num = AVS_DEV_NUM;
+static unsigned int max_process_time[AVS_DEV_NUM];
+static unsigned int max_get_frame_interval[AVS_DEV_NUM];
+static unsigned int run_count[AVS_DEV_NUM];
+static unsigned int ins_udebug_flag[AVS_DEV_NUM];
+#ifdef DEBUG_MULTI_FRAME_INS
+static unsigned int max_run_count[AVS_DEV_NUM];
+#endif
+/*
+error_handle_policy:
+*/
+static unsigned int error_handle_policy = 3;
+
+static u32 again_threshold = 0; /*0x40;*/
+
+static unsigned int decode_timeout_val = 200;
+static unsigned int start_decode_buf_level = 0x8000;
+
+/********************************
+firmware_sel
+    0: use avsp_trans long cabac ucode;
+    1: not use avsp_trans long cabac ucode
+		in ucode:
+		#define USE_EXT_BUFFER_ASSIGNMENT
+		#undef USE_DYNAMIC_BUF_NUM
+********************************/
+static int firmware_sel;
+static int disable_longcabac_trans = 1;
+static int pre_decode_buf_level = 0x800;
+
+
+static struct vframe_s *vavs_vf_peek(void *);
+static struct vframe_s *vavs_vf_get(void *);
+static void vavs_vf_put(struct vframe_s *, void *);
+static int vavs_vf_states(struct vframe_states *states, void *);
+static int vavs_event_cb(int type, void *data, void *private_data);
+
+static const char vavs_dec_id[] = "vavs-dev";
+
+#define PROVIDER_NAME   "decoder.avs"
+static DEFINE_SPINLOCK(lock);
+static DEFINE_MUTEX(vavs_mutex);
+
+static const struct vframe_operations_s vavs_vf_provider = {
+	.peek = vavs_vf_peek,
+	.get = vavs_vf_get,
+	.put = vavs_vf_put,
+	.event_cb = vavs_event_cb,
+	.vf_states = vavs_vf_states,
+};
+/*
+static void *mm_blk_handle;
+*/
+static struct vframe_provider_s vavs_vf_prov;
+
+#define VF_BUF_NUM_MAX 16
+#ifdef DEBUG_MULTI_FRAME_INS
+#define WORKSPACE_SIZE		(16 * SZ_1M)
+#else
+#define WORKSPACE_SIZE		(4 * SZ_1M)
+#endif
+#ifdef AVSP_LONG_CABAC
+#define MAX_BMMU_BUFFER_NUM	(VF_BUF_NUM_MAX + 2)
+#define WORKSPACE_SIZE_A		(MAX_CODED_FRAME_SIZE + LOCAL_HEAP_SIZE)
+#else
+#define MAX_BMMU_BUFFER_NUM	(VF_BUF_NUM_MAX + 1)
+#endif
+
+#define RV_AI_BUFF_START_ADDR	 0x01a00000
+#define LONG_CABAC_RV_AI_BUFF_START_ADDR	 0x00000000
+
+/* 4 buffers not enough for multi inc*/
+static u32 vf_buf_num = 8;
+/*static u32 vf_buf_num_used;*/
+static u32 canvas_base = 128;
+#ifdef NV21
+static int	canvas_num = 2; /*NV21*/
+#else
+static int	canvas_num = 3;
+#endif
+
+#if 0
+static struct vframe_s vfpool[VF_POOL_SIZE];
+/*static struct vframe_s vfpool2[VF_POOL_SIZE];*/
+static struct vframe_s *cur_vfpool;
+static unsigned char recover_flag;
+static s32 vfbuf_use[VF_BUF_NUM_MAX];
+static u32 saved_resolution;
+static u32 frame_width, frame_height, frame_dur, frame_prog;
+static struct timer_list recycle_timer;
+static u32 stat;
+#endif
+static u32 buf_size = 32 * 1024 * 1024;
+#if 0
+static u32 buf_offset;
+static u32 avi_flag;
+static u32 vavs_ratio;
+static u32 pic_type;
+#endif
+static u32 pts_by_offset = 1;
+#if 0
+static u32 total_frame;
+static u32 next_pts;
+static unsigned char throw_pb_flag;
+#ifdef DEBUG_PTS
+static u32 pts_hit, pts_missed, pts_i_hit, pts_i_missed;
+#endif
+#endif
+static u32 radr, rval;
+static u32 dbg_cmd;
+#if 0
+static struct dec_sysinfo vavs_amstream_dec_info;
+static struct vdec_info *gvs;
+static u32 fr_hint_status;
+static struct work_struct notify_work;
+static struct work_struct set_clk_work;
+static bool is_reset;
+#endif
+/*static struct vdec_s *vdec;*/
+
+#ifdef AVSP_LONG_CABAC
+static struct work_struct long_cabac_wd_work;
+void *es_write_addr_virt;
+dma_addr_t es_write_addr_phy;
+
+void *bitstream_read_tmp;
+dma_addr_t bitstream_read_tmp_phy;
+void *avsp_heap_adr;
+static uint long_cabac_busy;
+#endif
+
+#if 0
+#ifdef ENABLE_USER_DATA
+static void *user_data_buffer;
+static dma_addr_t user_data_buffer_phys;
+#endif
+static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE);
+static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE);
+static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE);
+#endif
+static inline u32 index2canvas(u32 index)
+{
+	const u32 canvas_tab[VF_BUF_NUM_MAX] = {
+		0x010100, 0x030302, 0x050504, 0x070706,
+		0x090908, 0x0b0b0a, 0x0d0d0c, 0x0f0f0e,
+		0x111110, 0x131312, 0x151514, 0x171716,
+		0x191918, 0x1b1b1a, 0x1d1d1c, 0x1f1f1e,
+	};
+	const u32 canvas_tab_3[4] = {
+		0x010100, 0x040403, 0x070706, 0x0a0a09
+	};
+
+	if (canvas_num == 2)
+		return canvas_tab[index] + (canvas_base << 16)
+		+ (canvas_base << 8) + canvas_base;
+
+	return canvas_tab_3[index] + (canvas_base << 16)
+		+ (canvas_base << 8) + canvas_base;
+}
+
+static const u32 frame_rate_tab[16] = {
+	96000 / 30,		/* forbidden */
+	96000000 / 23976,	/* 24000/1001 (23.967) */
+	96000 / 24,
+	96000 / 25,
+	9600000 / 2997,		/* 30000/1001 (29.97) */
+	96000 / 30,
+	96000 / 50,
+	9600000 / 5994,		/* 60000/1001 (59.94) */
+	96000 / 60,
+	/* > 8 reserved, use 24 */
+	96000 / 24, 96000 / 24, 96000 / 24, 96000 / 24,
+	96000 / 24, 96000 / 24, 96000 / 24
+};
+
+#define DECODE_BUFFER_NUM_MAX VF_BUF_NUM_MAX
+#define PIC_PTS_NUM 64
+struct buf_pool_s {
+	unsigned detached;
+	struct vframe_s vf;
+};
+
+#define buf_of_vf(vf) container_of(vf, struct buf_pool_s, vf)
+
+struct pic_pts_s {
+	u32 pts;
+	u64 pts64;
+	u64 timestamp;
+	unsigned short decode_pic_count;
+};
+
+struct vdec_avs_hw_s {
+	spinlock_t lock;
+	unsigned char m_ins_flag;
+	struct platform_device *platform_dev;
+	DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE);
+	DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE);
+	DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE);
+	struct buf_pool_s vfpool[VF_POOL_SIZE];
+	s32 vfbuf_use[VF_BUF_NUM_MAX];
+	unsigned char again_flag;
+	unsigned char recover_flag;
+	u32 frame_width;
+	u32 frame_height;
+	u32 frame_dur;
+	u32 frame_prog;
+	u32 saved_resolution;
+	u32 avi_flag;
+	u32 vavs_ratio;
+	u32 pic_type;
+
+	u32 vf_buf_num_used;
+	u32 total_frame;
+	u32 next_pts;
+	unsigned char throw_pb_flag;
+	struct pic_pts_s pic_pts[PIC_PTS_NUM];
+	int pic_pts_wr_pos;
+
+#ifdef DEBUG_PTS
+	u32 pts_hit;
+	u32 pts_missed;
+	u32 pts_i_hit;
+	u32 pts_i_missed;
+#endif
+#ifdef ENABLE_USER_DATA
+	struct work_struct userdata_push_work;
+	void *user_data_buffer;
+	dma_addr_t user_data_buffer_phys;
+#endif
+	dma_addr_t lmem_addr;
+	ulong lmem_phy_addr;
+
+	u32 buf_offset;
+
+	struct dec_sysinfo vavs_amstream_dec_info;
+	struct vdec_info *gvs;
+	u32 fr_hint_status;
+	struct work_struct set_clk_work;
+	bool is_reset;
+
+	/*debug*/
+	u32 ucode_pause_pos;
+	/**/
+	u32 decode_pic_count;
+	u8 reset_decode_flag;
+	u32 display_frame_count;
+	u32 buf_status;
+	u32 pre_parser_wr_ptr;
+		/*
+		buffer_status &= ~buf_recycle_status
+		*/
+	u32 buf_recycle_status;
+	u32 seqinfo;
+	u32 ctx_valid;
+	u32 dec_control;
+	void *mm_blk_handle;
+	struct vframe_chunk_s *chunk;
+	u32 stat;
+	u8 init_flag;
+	unsigned long buf_start;
+	u32 buf_size;
+
+	u32 reg_scratch_0;
+	u32 reg_scratch_1;
+	u32 reg_scratch_2;
+	u32 reg_scratch_3;
+	u32 reg_scratch_4;
+	u32 reg_scratch_5;
+	u32 reg_scratch_6;
+	u32 reg_scratch_7;
+	u32 reg_scratch_8;
+	u32 reg_scratch_9;
+	u32 reg_scratch_A;
+	u32 reg_scratch_B;
+	u32 reg_scratch_C;
+	u32 reg_scratch_D;
+	u32 reg_scratch_E;
+	u32 reg_scratch_F;
+	u32 reg_scratch_G;
+	u32 reg_scratch_H;
+	u32 reg_scratch_I;
+	u32 reg_mb_width;
+	u32 reg_viff_bit_cnt;
+	u32 reg_canvas_addr;
+	u32 reg_dbkr_canvas_addr;
+	u32 reg_dbkw_canvas_addr;
+	u32 reg_anc2_canvas_addr;
+	u32 reg_anc0_canvas_addr;
+	u32 reg_anc1_canvas_addr;
+	u32 reg_anc3_canvas_addr;
+	u32 reg_anc4_canvas_addr;
+	u32 reg_anc5_canvas_addr;
+	u32 slice_ver_pos_pic_type;
+	u32 vc1_control_reg;
+	u32 avs_co_mb_wr_addr;
+	u32 slice_start_byte_01;
+	u32 slice_start_byte_23;
+	u32 vcop_ctrl_reg;
+	u32 iqidct_control;
+	u32 rv_ai_mb_count;
+	u32 slice_qp;
+	u32 dc_scaler;
+	u32 avsp_iq_wq_param_01;
+	u32 avsp_iq_wq_param_23;
+	u32 avsp_iq_wq_param_45;
+	u32 avs_co_mb_rd_addr;
+	u32 dblk_mb_wid_height;
+	u32 mc_pic_w_h;
+	u32 avs_co_mb_rw_ctl;
+	u32 vld_decode_control;
+
+	struct timer_list check_timer;
+	u32 decode_timeout_count;
+	unsigned long int start_process_time;
+	u32 last_vld_level;
+	u32 eos;
+	u32 canvas_spec[DECODE_BUFFER_NUM_MAX];
+	struct canvas_config_s canvas_config[DECODE_BUFFER_NUM_MAX][2];
+
+	s32 refs[2];
+	int dec_result;
+	struct timer_list recycle_timer;
+	struct work_struct work;
+	struct work_struct notify_work;
+	atomic_t error_handler_run;
+	struct work_struct fatal_error_wd_work;
+	void (*vdec_cb)(struct vdec_s *, void *);
+	void *vdec_cb_arg;
+/* for error handling */
+	u32 run_count;
+	u32	not_run_ready;
+	u32	input_empty;
+	u32 prepare_num;
+	u32 put_num;
+	u32 peek_num;
+	u32 get_num;
+	u32 drop_frame_count;
+	u32 buffer_not_ready;
+	int frameinfo_enable;
+	struct firmware_s *fw;
+	u32 old_udebug_flag;
+	u32 decode_status_skip_pic_done_flag;
+	u32 decode_decode_cont_start_code;
+	int vdec_pg_enable_flag;
+	char vdec_name[32];
+	char pts_name[32];
+	char new_q_name[32];
+	char disp_q_name[32];
+};
+
+static void reset_process_time(struct vdec_avs_hw_s *hw);
+static void start_process_time(struct vdec_avs_hw_s *hw);
+static void vavs_save_regs(struct vdec_avs_hw_s *hw);
+
+struct vdec_avs_hw_s *ghw;
+
+#define MULTI_INSTANCE_PROVIDER_NAME    "vdec.avs"
+
+#define DEC_RESULT_NONE     0
+#define DEC_RESULT_DONE     1
+#define DEC_RESULT_AGAIN    2
+#define DEC_RESULT_ERROR    3
+#define DEC_RESULT_FORCE_EXIT 4
+#define DEC_RESULT_EOS 5
+#define DEC_RESULT_GET_DATA         6
+#define DEC_RESULT_GET_DATA_RETRY   7
+#define DEC_RESULT_USERDATA         8
+
+#define DECODE_ID(hw) (hw->m_ins_flag? hw_to_vdec(hw)->id : 0)
+
+#define PRINT_FLAG_ERROR              0x0
+#define PRINT_FLAG_RUN_FLOW           0X0001
+#define PRINT_FLAG_DECODING           0x0002
+#define PRINT_FLAG_PTS                0x0004
+#define PRINT_FLAG_VFRAME_DETAIL	  0x0010
+#define PRINT_FLAG_VLD_DETAIL         0x0020
+#define PRINT_FLAG_DEC_DETAIL         0x0040
+#define PRINT_FLAG_BUFFER_DETAIL      0x0080
+#define PRINT_FLAG_FORCE_DONE         0x0100
+#define PRINT_FLAG_COUNTER            0X0200
+#define PRINT_FRAMEBASE_DATA          0x0400
+#define PRINT_FLAG_PARA_DATA          0x1000
+#define DEBUG_FLAG_PREPARE_MORE_INPUT 0x2000
+#define DEBUG_FLAG_PRINT_REG          0x4000
+#define DEBUG_FLAG_DISABLE_TIMEOUT    0x10000
+#define DEBUG_WAIT_DECODE_DONE_WHEN_STOP 0x20000
+#define DEBUG_PIC_DONE_WHEN_UCODE_PAUSE 0x40000
+
+
+#undef DEBUG_REG
+#ifdef DEBUG_REG
+static void WRITE_VREG_DBG2(unsigned adr, unsigned val)
+{
+	if (debug & DEBUG_FLAG_PRINT_REG)
+		pr_info("%s(%x, %x)\n", __func__, adr, val);
+	if (adr != 0)
+		WRITE_VREG(adr, val);
+}
+
+#undef WRITE_VREG
+#define WRITE_VREG WRITE_VREG_DBG2
+#endif
+
+#undef pr_info
+#define pr_info printk
+static int debug_print(struct vdec_avs_hw_s *hw,
+	int flag, const char *fmt, ...)
+{
+#define AVS_PRINT_BUF		256
+	unsigned char buf[AVS_PRINT_BUF];
+	int len = 0;
+	int index = 0;
+	if (hw)
+		index = hw->m_ins_flag ? DECODE_ID(hw) : 0;
+	if (hw == NULL ||
+		(flag == 0) ||
+		((debug_mask &
+		(1 << index))
+		&& (debug & flag))) {
+		va_list args;
+
+		va_start(args, fmt);
+		if (hw)
+			len = sprintf(buf, "[%d]", index);
+		vsnprintf(buf + len, AVS_PRINT_BUF - len, fmt, args);
+		pr_info("%s", buf);
+		va_end(args);
+	}
+	return 0;
+}
+
+static int debug_print_cont(struct vdec_avs_hw_s *hw,
+	int flag, const char *fmt, ...)
+{
+	unsigned char buf[AVS_PRINT_BUF];
+	int len = 0;
+	int index = 0;
+	if (hw)
+		index = hw->m_ins_flag ? DECODE_ID(hw) : 0;
+	if (hw == NULL ||
+		(flag == 0) ||
+		((debug_mask &
+		(1 << index))
+		&& (debug & flag))) {
+		va_list args;
+
+		va_start(args, fmt);
+		vsnprintf(buf + len, AVS_PRINT_BUF - len, fmt, args);
+		pr_info("%s", buf);
+		va_end(args);
+	}
+	return 0;
+}
+
+static void avs_pts_check_in(struct vdec_avs_hw_s *hw,
+	unsigned short decode_pic_count, struct vframe_chunk_s *chunk)
+{
+	if (chunk)
+		debug_print(hw, PRINT_FLAG_PTS,
+			"%s %d (wr pos %d), pts %d pts64 %ld timestamp %ld\n",
+			__func__, decode_pic_count, hw->pic_pts_wr_pos,
+			chunk->pts, (u64)(chunk->pts64), (u64)(chunk->timestamp));
+	else
+		debug_print(hw, PRINT_FLAG_PTS,
+			"%s %d, chunk is null\n",
+			__func__, decode_pic_count);
+
+	if (chunk) {
+		hw->pic_pts[hw->pic_pts_wr_pos].pts = chunk->pts;
+		hw->pic_pts[hw->pic_pts_wr_pos].pts64 = chunk->pts64;
+		hw->pic_pts[hw->pic_pts_wr_pos].timestamp = chunk->timestamp;
+	} else {
+		hw->pic_pts[hw->pic_pts_wr_pos].pts = 0;
+		hw->pic_pts[hw->pic_pts_wr_pos].pts64 = 0;
+		hw->pic_pts[hw->pic_pts_wr_pos].timestamp = 0;
+	}
+	hw->pic_pts[hw->pic_pts_wr_pos].decode_pic_count
+		= decode_pic_count;
+	hw->pic_pts_wr_pos++;
+	if (hw->pic_pts_wr_pos >= PIC_PTS_NUM)
+		hw->pic_pts_wr_pos = 0;
+	return;
+}
+
+static void clear_pts_buf(struct vdec_avs_hw_s *hw)
+{
+	int i;
+	debug_print(hw, PRINT_FLAG_PTS,
+			"%s\n",	__func__);
+	hw->pic_pts_wr_pos = 0;
+	for (i = 0; i < PIC_PTS_NUM; i++) {
+		hw->pic_pts[hw->pic_pts_wr_pos].pts = 0;
+		hw->pic_pts[hw->pic_pts_wr_pos].pts64 = 0;
+		hw->pic_pts[hw->pic_pts_wr_pos].timestamp = 0;
+		hw->pic_pts[hw->pic_pts_wr_pos].decode_pic_count = 0;
+	}
+}
+
+static int set_vframe_pts(struct vdec_avs_hw_s *hw,
+	unsigned short decode_pic_count, struct vframe_s *vf)
+{
+	int i;
+	int ret = -1;
+	for (i = 0; i < PIC_PTS_NUM; i++) {
+		if (hw->pic_pts[i].decode_pic_count == decode_pic_count) {
+			vf->pts = hw->pic_pts[i].pts;
+			vf->pts_us64 = hw->pic_pts[i].pts64;
+			vf->timestamp = hw->pic_pts[i].timestamp;
+			ret = 0;
+			debug_print(hw, PRINT_FLAG_PTS,
+				"%s %d (rd pos %d), pts %d pts64 %ld timestamp %ld\n",
+				__func__, decode_pic_count, i,
+				vf->pts, vf->pts_us64, vf->timestamp);
+
+			break;
+		}
+	}
+	return ret;
+}
+
+static void avs_vf_notify_receiver(struct vdec_avs_hw_s *hw,
+	const char *provider_name, int event_type, void *data)
+{
+	if (hw->m_ins_flag)
+		vf_notify_receiver(hw_to_vdec(hw)->vf_provider_name,
+			event_type, data);
+	else
+		vf_notify_receiver(provider_name, event_type, data);
+}
+
+static void set_frame_info(struct vdec_avs_hw_s *hw, struct vframe_s *vf,
+	unsigned int *duration)
+{
+	int ar = 0;
+
+	unsigned int pixel_ratio = READ_VREG(AVS_PIC_RATIO);
+	hw->prepare_num++;
+#ifndef USE_AVS_SEQ_INFO
+	if (hw->vavs_amstream_dec_info.width > 0
+		&& hw->vavs_amstream_dec_info.height > 0) {
+		vf->width = hw->vavs_amstream_dec_info.width;
+		vf->height = hw->vavs_amstream_dec_info.height;
+	} else
+#endif
+	{
+		vf->width = READ_VREG(AVS_PIC_WIDTH);
+		vf->height = READ_VREG(AVS_PIC_HEIGHT);
+		hw->frame_width = vf->width;
+		hw->frame_height = vf->height;
+		/* pr_info("%s: (%d,%d)\n", __func__,vf->width, vf->height);*/
+	}
+
+#ifndef USE_AVS_SEQ_INFO
+	if (hw->vavs_amstream_dec_info.rate > 0)
+		*duration = hw->vavs_amstream_dec_info.rate;
+	else
+#endif
+	{
+		*duration = frame_rate_tab[READ_VREG(AVS_FRAME_RATE) & 0xf];
+		/* pr_info("%s: duration = %d\n", __func__, *duration); */
+		hw->frame_dur = *duration;
+		schedule_work(&hw->notify_work);
+	}
+
+	if (hw->vavs_ratio == 0) {
+		/* always stretch to 16:9 */
+		vf->ratio_control |= (0x90 <<
+				DISP_RATIO_ASPECT_RATIO_BIT);
+		vf->sar_width = 1;
+		vf->sar_height = 1;
+	} else {
+		switch (pixel_ratio) {
+		case 1:
+			vf->sar_width = 1;
+			vf->sar_height = 1;
+			ar = (vf->height * hw->vavs_ratio) / vf->width;
+			break;
+		case 2:
+			vf->sar_width = 4;
+			vf->sar_height = 3;
+			ar = (vf->height * 3 * hw->vavs_ratio) / (vf->width * 4);
+			break;
+		case 3:
+			vf->sar_width = 16;
+			vf->sar_height = 9;
+			ar = (vf->height * 9 * hw->vavs_ratio) / (vf->width * 16);
+			break;
+		case 4:
+			vf->sar_width = 221;
+			vf->sar_height = 100;
+			ar = (vf->height * 100 * hw->vavs_ratio) / (vf->width *
+					221);
+			break;
+		default:
+			vf->sar_width = 1;
+			vf->sar_height = 1;
+			ar = (vf->height * hw->vavs_ratio) / vf->width;
+			break;
+		}
+	}
+
+	ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX);
+
+	vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT);
+	/*vf->ratio_control |= DISP_RATIO_FORCECONFIG | DISP_RATIO_KEEPRATIO; */
+
+	vf->flag = 0;
+	buf_of_vf(vf)->detached = 0;
+
+}
+
+#ifdef ENABLE_USER_DATA
+
+/*static struct work_struct userdata_push_work;*/
+/*
+#define DUMP_LAST_REPORTED_USER_DATA
+*/
+static void userdata_push_process(struct vdec_avs_hw_s *hw)
+{
+	unsigned int user_data_flags;
+	unsigned int user_data_wp;
+	unsigned int user_data_length;
+	struct userdata_poc_info_t user_data_poc;
+#ifdef DUMP_LAST_REPORTED_USER_DATA
+	int user_data_len;
+	int wp_start;
+	unsigned char *pdata;
+	int nLeft;
+#endif
+
+	user_data_flags = READ_VREG(AV_SCRATCH_N);
+	user_data_wp = (user_data_flags >> 16) & 0xffff;
+	user_data_length = user_data_flags & 0x7fff;
+
+#ifdef DUMP_LAST_REPORTED_USER_DATA
+	dma_sync_single_for_cpu(amports_get_dma_device(),
+			hw->user_data_buffer_phys, USER_DATA_SIZE,
+			DMA_FROM_DEVICE);
+
+	if (user_data_length & 0x07)
+		user_data_len = (user_data_length + 8) & 0xFFFFFFF8;
+	else
+		user_data_len = user_data_length;
+
+	if (user_data_wp >= user_data_len) {
+		wp_start = user_data_wp - user_data_len;
+
+		pdata = (unsigned char *)hw->user_data_buffer;
+		pdata += wp_start;
+		nLeft = user_data_len;
+		while (nLeft >= 8) {
+			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+				pdata[0], pdata[1], pdata[2], pdata[3],
+				pdata[4], pdata[5], pdata[6], pdata[7]);
+			nLeft -= 8;
+			pdata += 8;
+		}
+	} else {
+		wp_start = user_data_wp +
+			USER_DATA_SIZE - user_data_len;
+
+		pdata = (unsigned char *)hw->user_data_buffer;
+		pdata += wp_start;
+		nLeft = USER_DATA_SIZE - wp_start;
+
+		while (nLeft >= 8) {
+			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+				pdata[0], pdata[1], pdata[2], pdata[3],
+				pdata[4], pdata[5], pdata[6], pdata[7]);
+			nLeft -= 8;
+			pdata += 8;
+		}
+
+		pdata = (unsigned char *)hw->user_data_buffer;
+		nLeft = user_data_wp;
+		while (nLeft >= 8) {
+			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+				pdata[0], pdata[1], pdata[2], pdata[3],
+				pdata[4], pdata[5], pdata[6], pdata[7]);
+			nLeft -= 8;
+			pdata += 8;
+		}
+	}
+#endif
+
+/*
+	pr_info("pocinfo 0x%x, poc %d, wp 0x%x, len %d\n",
+		   READ_VREG(AV_SCRATCH_L), READ_VREG(AV_SCRATCH_M),
+		   user_data_wp, user_data_length);
+*/
+	user_data_poc.poc_info = READ_VREG(AV_SCRATCH_L);
+	user_data_poc.poc_number = READ_VREG(AV_SCRATCH_M);
+
+	WRITE_VREG(AV_SCRATCH_N, 0);
+/*
+	wakeup_userdata_poll(user_data_poc, user_data_wp,
+				(unsigned long)hw->user_data_buffer,
+				USER_DATA_SIZE, user_data_length);
+*/
+}
+
+static void userdata_push_do_work(struct work_struct *work)
+{
+	struct vdec_avs_hw_s *hw =
+	container_of(work, struct vdec_avs_hw_s, userdata_push_work);
+	userdata_push_process(hw);
+}
+
+static u8 UserDataHandler(struct vdec_avs_hw_s *hw)
+{
+	unsigned int user_data_flags;
+
+	user_data_flags = READ_VREG(AV_SCRATCH_N);
+	if (user_data_flags & (1 << 15)) {	/* data ready */
+		if (hw->m_ins_flag) {
+			hw->dec_result = DEC_RESULT_USERDATA;
+			vdec_schedule_work(&hw->work);
+			return 1;
+		} else
+			schedule_work(&hw->userdata_push_work);
+	}
+	return 0;
+}
+#endif
+
+
+static inline void avs_update_gvs(struct vdec_avs_hw_s *hw)
+{
+	if (hw->gvs->frame_height != hw->frame_height) {
+		hw->gvs->frame_width = hw->frame_width;
+		hw->gvs->frame_height = hw->frame_height;
+	}
+	if (hw->gvs->frame_dur != hw->frame_dur) {
+		hw->gvs->frame_dur = hw->frame_dur;
+		if (hw->frame_dur != 0)
+			hw->gvs->frame_rate = ((96000 * 10 / hw->frame_dur) % 10) < 5 ?
+					96000 / hw->frame_dur : (96000 / hw->frame_dur +1);
+		else
+			hw->gvs->frame_rate = -1;
+	}
+
+	hw->gvs->status = hw->stat;
+	hw->gvs->error_count = READ_VREG(AV_SCRATCH_C);
+	hw->gvs->drop_frame_count = hw->drop_frame_count;
+
+}
+
+#ifdef HANDLE_AVS_IRQ
+static irqreturn_t vavs_isr(int irq, void *dev_id)
+#else
+static void vavs_isr(void)
+#endif
+{
+	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+	return IRQ_WAKE_THREAD;
+}
+/*
+ *static int run_flag = 1;
+ *static int step_flag;
+ */
+static int error_recovery_mode;   /*0: blocky  1: mosaic*/
+/*
+ *static uint error_watchdog_threshold=10;
+ *static uint error_watchdog_count;
+ *static uint error_watchdog_buf_threshold = 0x4000000;
+ */
+
+static struct vframe_s *vavs_vf_peek(void *op_arg)
+{
+	struct vframe_s *vf;
+	struct vdec_avs_hw_s *hw =
+	(struct vdec_avs_hw_s *)op_arg;
+	hw->peek_num++;
+	if (step == 2)
+		return NULL;
+	if (hw->recover_flag)
+		return NULL;
+
+	if (kfifo_len(&hw->display_q) > VF_POOL_SIZE) {
+		debug_print(hw, PRINT_FLAG_RUN_FLOW,
+			"kfifo len:%d invaild, peek error\n",
+			kfifo_len(&hw->display_q));
+		return NULL;
+	}
+
+	if (kfifo_peek(&hw->display_q, &vf)) {
+		if (vf) {
+			if (force_fps & 0x100) {
+				u32 rate = force_fps & 0xff;
+
+				if (rate)
+					vf->duration = 96000/rate;
+				else
+					vf->duration = 0;
+			}
+
+		}
+		return vf;
+	}
+
+	return NULL;
+
+}
+
+static struct vframe_s *vavs_vf_get(void *op_arg)
+{
+	struct vframe_s *vf;
+	struct vdec_avs_hw_s *hw =
+	(struct vdec_avs_hw_s *)op_arg;
+	unsigned long flags;
+
+	if (hw->recover_flag)
+		return NULL;
+
+	if (step == 2)
+		return NULL;
+	else if (step == 1)
+		step = 2;
+
+	spin_lock_irqsave(&lock, flags);
+	if (kfifo_get(&hw->display_q, &vf)) {
+		if (vf) {
+			hw->get_num++;
+			if (force_fps & 0x100) {
+				u32 rate = force_fps & 0xff;
+
+				if (rate)
+					vf->duration = 96000/rate;
+				else
+					vf->duration = 0;
+			}
+
+			debug_print(hw, PRINT_FLAG_VFRAME_DETAIL,
+				"%s, index = %d, w %d h %d, type 0x%x detached %d\n",
+				__func__,
+				vf->index,
+				vf->width,
+				vf->height,
+				vf->type,
+				buf_of_vf(vf)->detached);
+		}
+		spin_unlock_irqrestore(&lock, flags);
+		return vf;
+	}
+	spin_unlock_irqrestore(&lock, flags);
+	return NULL;
+
+}
+
+static void vavs_vf_put(struct vframe_s *vf, void *op_arg)
+{
+	int i;
+	struct vdec_avs_hw_s *hw =
+	(struct vdec_avs_hw_s *)op_arg;
+
+	if (vf) {
+		hw->put_num++;
+		debug_print(hw, PRINT_FLAG_VFRAME_DETAIL,
+			"%s, index = %d, w %d h %d, type 0x%x detached 0x%x\n",
+			__func__,
+			vf->index,
+			vf->width,
+			vf->height,
+			vf->type,
+			buf_of_vf(vf)->detached);
+	}
+	if (hw->recover_flag)
+		return;
+
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		if (vf == &hw->vfpool[i].vf)
+			break;
+	}
+	if (i < VF_POOL_SIZE)
+
+		kfifo_put(&hw->recycle_q, (const struct vframe_s *)vf);
+
+}
+
+static int vavs_event_cb(int type, void *data, void *private_data)
+{
+	struct vdec_avs_hw_s *hw = (struct vdec_avs_hw_s *)private_data;
+
+	if (type & VFRAME_EVENT_RECEIVER_REQ_STATE) {
+		struct provider_state_req_s *req =
+			(struct provider_state_req_s *)data;
+		if (req->req_type == REQ_STATE_SECURE)
+			req->req_result[0] = vdec_secure(hw_to_vdec(hw));
+		else
+			req->req_result[0] = 0xffffffff;
+	}
+
+	return 0;
+}
+
+static int vavs_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
+{
+	struct vdec_avs_hw_s *hw =
+	(struct vdec_avs_hw_s *)vdec->private;
+	/*if (!(hw->stat & STAT_VDEC_RUN))
+		return -1;*/
+	if (!hw)
+		return -1;
+
+	vstatus->frame_width = hw->frame_width;
+	vstatus->frame_height = hw->frame_height;
+	if (hw->frame_dur != 0)
+		vstatus->frame_rate = ((96000 * 10 / hw->frame_dur) % 10) < 5 ?
+				96000 / hw->frame_dur : (96000 / hw->frame_dur +1);
+	else
+		vstatus->frame_rate = -1;
+	vstatus->error_count = READ_VREG(AV_SCRATCH_C);
+	vstatus->status = hw->stat;
+	vstatus->bit_rate = hw->gvs->bit_rate;
+	vstatus->frame_dur = hw->frame_dur;
+	vstatus->frame_data = hw->gvs->frame_data;
+	vstatus->total_data = hw->gvs->total_data;
+	vstatus->frame_count = hw->gvs->frame_count;
+	vstatus->error_frame_count = hw->gvs->error_frame_count;
+	vstatus->drop_frame_count = hw->gvs->drop_frame_count;
+	vstatus->i_decoded_frames = hw->gvs->i_decoded_frames;
+	vstatus->i_lost_frames = hw->gvs->i_lost_frames;
+	vstatus->i_concealed_frames = hw->gvs->i_concealed_frames;
+	vstatus->p_decoded_frames = hw->gvs->p_decoded_frames;
+	vstatus->p_lost_frames = hw->gvs->p_lost_frames;
+	vstatus->p_concealed_frames = hw->gvs->p_concealed_frames;
+	vstatus->b_decoded_frames = hw->gvs->b_decoded_frames;
+	vstatus->b_lost_frames = hw->gvs->b_lost_frames;
+	vstatus->b_concealed_frames = hw->gvs->b_concealed_frames;
+	vstatus->total_data = hw->gvs->total_data;
+	vstatus->samp_cnt = hw->gvs->samp_cnt;
+	vstatus->offset = hw->gvs->offset;
+	snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
+		"%s", DRIVER_NAME);
+
+	return 0;
+}
+
+static int vavs_set_isreset(struct vdec_s *vdec, int isreset)
+{
+	struct vdec_avs_hw_s *hw =
+	(struct vdec_avs_hw_s *)vdec->private;
+
+	hw->is_reset = isreset;
+	return 0;
+}
+
+static int vavs_vdec_info_init(struct vdec_avs_hw_s *hw)
+{
+
+	hw->gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL);
+	if (NULL == hw->gvs) {
+		pr_info("the struct of vdec status malloc failed.\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+/****************************************/
+static int vavs_canvas_init(struct vdec_avs_hw_s *hw)
+{
+	int i, ret;
+	u32 canvas_width, canvas_height;
+	u32 decbuf_size, decbuf_y_size, decbuf_uv_size;
+	unsigned long buf_start;
+	int need_alloc_buf_num;
+	struct vdec_s *vdec = NULL;
+
+	if (hw->m_ins_flag)
+		vdec = hw_to_vdec(hw);
+
+	if (buf_size <= 0x00400000) {
+		/* SD only */
+		canvas_width = 768;
+		canvas_height = 576;
+		decbuf_y_size = 0x80000;
+		decbuf_uv_size = 0x20000;
+		decbuf_size = 0x100000;
+	} else {
+		/* HD & SD */
+		canvas_width = 1920;
+		canvas_height = 1088;
+		decbuf_y_size = 0x200000;
+		decbuf_uv_size = 0x80000;
+		decbuf_size = 0x300000;
+	}
+
+#ifdef AVSP_LONG_CABAC
+	need_alloc_buf_num = hw->vf_buf_num_used + 2;
+#else
+	need_alloc_buf_num = hw->vf_buf_num_used + 1;
+#endif
+	for (i = 0; i < need_alloc_buf_num; i++) {
+
+		if (i == (need_alloc_buf_num - 1))
+			decbuf_size = WORKSPACE_SIZE;
+#ifdef AVSP_LONG_CABAC
+		else if (i == (need_alloc_buf_num - 2))
+			decbuf_size = WORKSPACE_SIZE_A;
+#endif
+		ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i,
+				decbuf_size, DRIVER_NAME, &buf_start);
+		if (ret < 0)
+			return ret;
+		if (i == (need_alloc_buf_num - 1)) {
+			if (firmware_sel == 1)
+				hw->buf_offset = buf_start -
+					RV_AI_BUFF_START_ADDR;
+			else
+				hw->buf_offset = buf_start -
+					LONG_CABAC_RV_AI_BUFF_START_ADDR;
+			continue;
+		}
+#ifdef AVSP_LONG_CABAC
+		else if (i == (need_alloc_buf_num - 2)) {
+			avsp_heap_adr = codec_mm_phys_to_virt(buf_start);
+			continue;
+		}
+#endif
+		if (hw->m_ins_flag) {
+			unsigned canvas;
+
+			if (vdec->parallel_dec == 1) {
+				unsigned tmp;
+				if (canvas_u(hw->canvas_spec[i]) == 0xff) {
+					tmp =
+						vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
+					hw->canvas_spec[i] &= ~(0xffff << 8);
+					hw->canvas_spec[i] |= tmp << 8;
+					hw->canvas_spec[i] |= tmp << 16;
+				}
+				if (canvas_y(hw->canvas_spec[i]) == 0xff) {
+					tmp =
+						vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
+					hw->canvas_spec[i] &= ~0xff;
+					hw->canvas_spec[i] |= tmp;
+				}
+				canvas = hw->canvas_spec[i];
+			} else {
+				canvas = vdec->get_canvas(i, 2);
+				hw->canvas_spec[i] = canvas;
+			}
+
+			hw->canvas_config[i][0].phy_addr =
+			buf_start;
+			hw->canvas_config[i][0].width =
+			canvas_width;
+			hw->canvas_config[i][0].height =
+			canvas_height;
+			hw->canvas_config[i][0].block_mode =
+			CANVAS_BLKMODE_32X32;
+
+			hw->canvas_config[i][1].phy_addr =
+			buf_start + decbuf_y_size;
+			hw->canvas_config[i][1].width =
+			canvas_width;
+			hw->canvas_config[i][1].height =
+			canvas_height / 2;
+			hw->canvas_config[i][1].block_mode =
+			CANVAS_BLKMODE_32X32;
+
+		} else {
+#ifdef NV21
+			config_cav_lut_ex(canvas_base + canvas_num * i + 0,
+					buf_start,
+					canvas_width, canvas_height,
+					CANVAS_ADDR_NOWRAP,
+					CANVAS_BLKMODE_32X32, 0, VDEC_1);
+			config_cav_lut_ex(canvas_base + canvas_num * i + 1,
+					buf_start +
+					decbuf_y_size, canvas_width,
+					canvas_height / 2,
+					CANVAS_ADDR_NOWRAP,
+					CANVAS_BLKMODE_32X32, 0, VDEC_1);
+#else
+			config_cav_lut_ex(canvas_num * i + 0,
+					buf_start,
+					canvas_width, canvas_height,
+					CANVAS_ADDR_NOWRAP,
+					CANVAS_BLKMODE_32X32, 0, VDEC_1);
+			config_cav_lut_ex(canvas_num * i + 1,
+					buf_start +
+					decbuf_y_size, canvas_width / 2,
+					canvas_height / 2,
+					CANVAS_ADDR_NOWRAP,
+					CANVAS_BLKMODE_32X32, 0, VDEC_1);
+			config_cav_lut_ex(canvas_num * i + 2,
+					buf_start +
+					decbuf_y_size + decbuf_uv_size,
+					canvas_width / 2, canvas_height / 2,
+					CANVAS_ADDR_NOWRAP,
+					CANVAS_BLKMODE_32X32, 0, VDEC_1);
+#endif
+			debug_print(hw, PRINT_FLAG_VFRAME_DETAIL,
+				"canvas config %d, addr %p\n", i,
+					   (void *)buf_start);
+		}
+	}
+	return 0;
+}
+
+static void vavs_recover(struct vdec_avs_hw_s *hw)
+{
+	vavs_canvas_init(hw);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	READ_VREG(DOS_SW_RESET0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	if (firmware_sel == 1) {
+		WRITE_VREG(POWER_CTL_VLD, 0x10);
+		WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2,
+			MEM_FIFO_CNT_BIT, 2);
+		WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 8,
+			MEM_LEVEL_CNT_BIT, 6);
+	}
+
+
+	if (firmware_sel == 0) {
+		/* fixed canvas index */
+		WRITE_VREG(AV_SCRATCH_0, canvas_base);
+		WRITE_VREG(AV_SCRATCH_1, hw->vf_buf_num_used);
+	} else {
+		int ii;
+#ifndef USE_DYNAMIC_BUF_NUM
+		for (ii = 0; ii < 4; ii++) {
+			WRITE_VREG(AV_SCRATCH_0 + ii,
+				(canvas_base + canvas_num * ii) |
+				((canvas_base + canvas_num * ii + 1)
+					<< 8) |
+				((canvas_base + canvas_num * ii + 1)
+					<< 16)
+			);
+		}
+#else
+		for (ii = 0; ii < hw->vf_buf_num_used; ii += 2) {
+			WRITE_VREG(buf_spec_reg[ii >> 1],
+				(canvas_base + canvas_num * ii) |
+				((canvas_base + canvas_num * ii + 1)
+					<< 8) |
+				((canvas_base + canvas_num * ii + 2)
+					<< 16) |
+				((canvas_base + canvas_num * ii + 3)
+					<< 24)
+			);
+		}
+#endif
+	}
+
+	/* notify ucode the buffer offset */
+	WRITE_VREG(AV_SCRATCH_F, hw->buf_offset);
+
+	/* disable PSCALE for hardware sharing */
+	WRITE_VREG(PSCALE_CTRL, 0);
+
+#ifndef USE_DYNAMIC_BUF_NUM
+	WRITE_VREG(AVS_SOS_COUNT, 0);
+#endif
+	WRITE_VREG(AVS_BUFFERIN, 0);
+	WRITE_VREG(AVS_BUFFEROUT, 0);
+	if (error_recovery_mode)
+		WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 0);
+	else
+		WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 1);
+	/* clear mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+	/* enable mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_MASK, 1);
+#ifndef USE_DYNAMIC_BUF_NUM				/* def DEBUG_UCODE */
+	WRITE_VREG(AV_SCRATCH_D, 0);
+#endif
+
+#ifdef NV21
+	SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17);
+#endif
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
+
+#ifdef PIC_DC_NEED_CLEAR
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31);
+#endif
+
+#ifdef AVSP_LONG_CABAC
+	if (firmware_sel == 0) {
+		WRITE_VREG(LONG_CABAC_DES_ADDR, es_write_addr_phy);
+		WRITE_VREG(LONG_CABAC_REQ, 0);
+		WRITE_VREG(LONG_CABAC_PIC_SIZE, 0);
+		WRITE_VREG(LONG_CABAC_SRC_ADDR, 0);
+	}
+#endif
+	WRITE_VREG(AV_SCRATCH_5, 0);
+
+}
+
+#define MBY_MBX                 MB_MOTION_MODE /*0xc07*/
+#define AVS_CO_MB_WR_ADDR        0xc38
+#define AVS_CO_MB_RW_CTL         0xc3d
+#define AVS_CO_MB_RD_ADDR        0xc39
+#define AVSP_IQ_WQ_PARAM_01                        0x0e19
+#define AVSP_IQ_WQ_PARAM_23                        0x0e1a
+#define AVSP_IQ_WQ_PARAM_45                        0x0e1b
+
+static void vavs_save_regs(struct vdec_avs_hw_s *hw)
+{
+	hw->reg_scratch_0 = READ_VREG(AV_SCRATCH_0);
+	hw->reg_scratch_1 = READ_VREG(AV_SCRATCH_1);
+	hw->reg_scratch_2 = READ_VREG(AV_SCRATCH_2);
+	hw->reg_scratch_3 = READ_VREG(AV_SCRATCH_3);
+	hw->reg_scratch_4 = READ_VREG(AV_SCRATCH_4);
+	hw->reg_scratch_5 = READ_VREG(AV_SCRATCH_5);
+	hw->reg_scratch_6 = READ_VREG(AV_SCRATCH_6);
+	hw->reg_scratch_7 = READ_VREG(AV_SCRATCH_7);
+	hw->reg_scratch_8 = READ_VREG(AV_SCRATCH_8);
+	hw->reg_scratch_9 = READ_VREG(AV_SCRATCH_9);
+	hw->reg_scratch_A = READ_VREG(AV_SCRATCH_A);
+	hw->reg_scratch_B = READ_VREG(AV_SCRATCH_B);
+	hw->reg_scratch_C = READ_VREG(AV_SCRATCH_C);
+	hw->reg_scratch_D = READ_VREG(AV_SCRATCH_D);
+	hw->reg_scratch_E = READ_VREG(AV_SCRATCH_E);
+	hw->reg_scratch_F = READ_VREG(AV_SCRATCH_F);
+	hw->reg_scratch_G = READ_VREG(AV_SCRATCH_G);
+	hw->reg_scratch_H = READ_VREG(AV_SCRATCH_H);
+	hw->reg_scratch_I = READ_VREG(AV_SCRATCH_I);
+
+	hw->reg_mb_width = READ_VREG(MB_WIDTH);
+	hw->reg_viff_bit_cnt = READ_VREG(VIFF_BIT_CNT);
+
+	hw->reg_canvas_addr = READ_VREG(REC_CANVAS_ADDR);
+	hw->reg_dbkr_canvas_addr = READ_VREG(DBKR_CANVAS_ADDR);
+	hw->reg_dbkw_canvas_addr = READ_VREG(DBKW_CANVAS_ADDR);
+	hw->reg_anc2_canvas_addr = READ_VREG(ANC2_CANVAS_ADDR);
+	hw->reg_anc0_canvas_addr = READ_VREG(ANC0_CANVAS_ADDR);
+	hw->reg_anc1_canvas_addr = READ_VREG(ANC1_CANVAS_ADDR);
+	hw->reg_anc3_canvas_addr = READ_VREG(ANC3_CANVAS_ADDR);
+	hw->reg_anc4_canvas_addr = READ_VREG(ANC4_CANVAS_ADDR);
+	hw->reg_anc5_canvas_addr = READ_VREG(ANC5_CANVAS_ADDR);
+
+	hw->slice_ver_pos_pic_type = READ_VREG(SLICE_VER_POS_PIC_TYPE);
+
+	hw->vc1_control_reg = READ_VREG(VC1_CONTROL_REG);
+	hw->avs_co_mb_wr_addr = READ_VREG(AVS_CO_MB_WR_ADDR);
+	hw->slice_start_byte_01 = READ_VREG(SLICE_START_BYTE_01);
+	hw->slice_start_byte_23 = READ_VREG(SLICE_START_BYTE_23);
+	hw->vcop_ctrl_reg = READ_VREG(VCOP_CTRL_REG);
+	hw->iqidct_control = READ_VREG(IQIDCT_CONTROL);
+	hw->rv_ai_mb_count = READ_VREG(RV_AI_MB_COUNT);
+	hw->slice_qp = READ_VREG(SLICE_QP);
+
+	hw->dc_scaler = READ_VREG(DC_SCALER);
+	hw->avsp_iq_wq_param_01 = READ_VREG(AVSP_IQ_WQ_PARAM_01);
+	hw->avsp_iq_wq_param_23 = READ_VREG(AVSP_IQ_WQ_PARAM_23);
+	hw->avsp_iq_wq_param_45 = READ_VREG(AVSP_IQ_WQ_PARAM_45);
+	hw->avs_co_mb_rd_addr = READ_VREG(AVS_CO_MB_RD_ADDR);
+	hw->dblk_mb_wid_height = READ_VREG(DBLK_MB_WID_HEIGHT);
+	hw->mc_pic_w_h = READ_VREG(MC_PIC_W_H);
+	hw->avs_co_mb_rw_ctl = READ_VREG(AVS_CO_MB_RW_CTL);
+
+	hw->vld_decode_control = READ_VREG(VLD_DECODE_CONTROL);
+}
+
+static void vavs_restore_regs(struct vdec_avs_hw_s *hw)
+{
+	debug_print(hw, PRINT_FLAG_DECODING,
+		"%s scratch_8 (AVS_BUFFERIN) 0x%x, decode_pic_count = %d\n",
+		__func__, hw->reg_scratch_8, hw->decode_pic_count);
+
+	WRITE_VREG(AV_SCRATCH_0, hw->reg_scratch_0);
+	WRITE_VREG(AV_SCRATCH_1, hw->reg_scratch_1);
+	WRITE_VREG(AV_SCRATCH_2, hw->reg_scratch_2);
+	WRITE_VREG(AV_SCRATCH_3, hw->reg_scratch_3);
+	WRITE_VREG(AV_SCRATCH_4, hw->reg_scratch_4);
+	WRITE_VREG(AV_SCRATCH_5, hw->reg_scratch_5);
+	WRITE_VREG(AV_SCRATCH_6, hw->reg_scratch_6);
+	WRITE_VREG(AV_SCRATCH_7, hw->reg_scratch_7);
+	WRITE_VREG(AV_SCRATCH_8, hw->reg_scratch_8);
+	WRITE_VREG(AV_SCRATCH_9, hw->reg_scratch_9);
+	WRITE_VREG(AV_SCRATCH_A, hw->reg_scratch_A);
+	WRITE_VREG(AV_SCRATCH_B, hw->reg_scratch_B);
+	WRITE_VREG(AV_SCRATCH_C, hw->reg_scratch_C);
+	WRITE_VREG(AV_SCRATCH_D, hw->reg_scratch_D);
+	WRITE_VREG(AV_SCRATCH_E, hw->reg_scratch_E);
+	WRITE_VREG(AV_SCRATCH_F, hw->reg_scratch_F);
+	WRITE_VREG(AV_SCRATCH_G, hw->reg_scratch_G);
+	WRITE_VREG(AV_SCRATCH_H, hw->reg_scratch_H);
+	WRITE_VREG(AV_SCRATCH_I, hw->reg_scratch_I);
+
+	WRITE_VREG(MB_WIDTH, hw->reg_mb_width);
+	WRITE_VREG(VIFF_BIT_CNT, hw->reg_viff_bit_cnt);
+
+	WRITE_VREG(REC_CANVAS_ADDR, hw->reg_canvas_addr);
+    WRITE_VREG(DBKR_CANVAS_ADDR, hw->reg_dbkr_canvas_addr);
+    WRITE_VREG(DBKW_CANVAS_ADDR, hw->reg_dbkw_canvas_addr);
+    WRITE_VREG(ANC2_CANVAS_ADDR, hw->reg_anc2_canvas_addr);
+    WRITE_VREG(ANC0_CANVAS_ADDR, hw->reg_anc0_canvas_addr);
+    WRITE_VREG(ANC1_CANVAS_ADDR, hw->reg_anc1_canvas_addr);
+    WRITE_VREG(ANC3_CANVAS_ADDR, hw->reg_anc3_canvas_addr);
+    WRITE_VREG(ANC4_CANVAS_ADDR, hw->reg_anc4_canvas_addr);
+    WRITE_VREG(ANC5_CANVAS_ADDR, hw->reg_anc5_canvas_addr);
+
+    WRITE_VREG(SLICE_VER_POS_PIC_TYPE, hw->slice_ver_pos_pic_type);
+
+    WRITE_VREG(VC1_CONTROL_REG, hw->vc1_control_reg);
+    WRITE_VREG(AVS_CO_MB_WR_ADDR, hw->avs_co_mb_wr_addr);
+    WRITE_VREG(SLICE_START_BYTE_01, hw->slice_start_byte_01);
+    WRITE_VREG(SLICE_START_BYTE_23, hw->slice_start_byte_23);
+    WRITE_VREG(VCOP_CTRL_REG, hw->vcop_ctrl_reg);
+    WRITE_VREG(IQIDCT_CONTROL, hw->iqidct_control);
+    WRITE_VREG(RV_AI_MB_COUNT, hw->rv_ai_mb_count);
+    WRITE_VREG(SLICE_QP, hw->slice_qp);
+
+    WRITE_VREG(DC_SCALER, hw->dc_scaler);
+    WRITE_VREG(AVSP_IQ_WQ_PARAM_01, hw->avsp_iq_wq_param_01);
+    WRITE_VREG(AVSP_IQ_WQ_PARAM_23, hw->avsp_iq_wq_param_23);
+    WRITE_VREG(AVSP_IQ_WQ_PARAM_45, hw->avsp_iq_wq_param_45);
+    WRITE_VREG(AVS_CO_MB_RD_ADDR, hw->avs_co_mb_rd_addr);
+    WRITE_VREG(DBLK_MB_WID_HEIGHT, hw->dblk_mb_wid_height);
+    WRITE_VREG(MC_PIC_W_H, hw->mc_pic_w_h);
+    WRITE_VREG(AVS_CO_MB_RW_CTL, hw->avs_co_mb_rw_ctl);
+
+    WRITE_VREG(VLD_DECODE_CONTROL, hw->vld_decode_control);
+
+}
+
+static int vavs_prot_init(struct vdec_avs_hw_s *hw)
+{
+	int r = 0;
+#if DEBUG_MULTI_FLAG > 0
+	if (hw->decode_pic_count == 0) {
+#endif
+#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	READ_VREG(DOS_SW_RESET0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+#else
+	WRITE_RESET_REG(RESET0_REGISTER,
+				   RESET_IQIDCT | RESET_MC | RESET_VLD_PART);
+	READ_RESET_REG(RESET0_REGISTER);
+	WRITE_RESET_REG(RESET0_REGISTER,
+				   RESET_IQIDCT | RESET_MC | RESET_VLD_PART);
+
+	WRITE_RESET_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK);
+#endif
+#if DEBUG_MULTI_FLAG > 0
+	}
+#endif
+	/***************** reset vld   **********************************/
+	WRITE_VREG(POWER_CTL_VLD, 0x10);
+	WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2, MEM_FIFO_CNT_BIT, 2);
+	WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL,	8, MEM_LEVEL_CNT_BIT, 6);
+	/*************************************************************/
+	if (hw->m_ins_flag) {
+		int i;
+		if (hw->decode_pic_count == 0) {
+			r = vavs_canvas_init(hw);
+#ifndef USE_DYNAMIC_BUF_NUM
+			for (i = 0; i < 4; i++) {
+				WRITE_VREG(AV_SCRATCH_0 + i,
+					hw->canvas_spec[i]
+				);
+			}
+#else
+			for (i = 0; i < hw->vf_buf_num_used; i++)
+				WRITE_VREG(buf_spec_reg[i], 0);
+			for (i = 0; i < hw->vf_buf_num_used; i += 2) {
+				WRITE_VREG(buf_spec_reg[i >> 1],
+					(hw->canvas_spec[i] & 0xffff) |
+					((hw->canvas_spec[i + 1] & 0xffff)
+						<< 16)
+				);
+				debug_print(hw, PRINT_FLAG_DECODING,
+					"%s WRITE_VREG(0x%x, 0x%x)\n",
+					__func__, buf_spec_reg[i >> 1], READ_VREG(buf_spec_reg[i >> 1]));
+			}
+#endif
+		} else
+			vavs_restore_regs(hw);
+
+		for (i = 0; i < hw->vf_buf_num_used; i++) {
+			config_cav_lut_ex(canvas_y(hw->canvas_spec[i]),
+				hw->canvas_config[i][0].phy_addr,
+				hw->canvas_config[i][0].width,
+				hw->canvas_config[i][0].height,
+				CANVAS_ADDR_NOWRAP,
+				hw->canvas_config[i][0].block_mode,
+				0, VDEC_1);
+
+			config_cav_lut_ex(canvas_u(hw->canvas_spec[i]),
+				hw->canvas_config[i][1].phy_addr,
+				hw->canvas_config[i][1].width,
+				hw->canvas_config[i][1].height,
+				CANVAS_ADDR_NOWRAP,
+				hw->canvas_config[i][1].block_mode,
+				0, VDEC_1);
+		}
+	} else {
+		r = vavs_canvas_init(hw);
+#ifdef NV21
+		if (firmware_sel == 0) {
+			/* fixed canvas index */
+			WRITE_VREG(AV_SCRATCH_0, canvas_base);
+			WRITE_VREG(AV_SCRATCH_1, hw->vf_buf_num_used);
+		} else {
+			int ii;
+#ifndef USE_DYNAMIC_BUF_NUM
+			for (ii = 0; ii < 4; ii++) {
+				WRITE_VREG(AV_SCRATCH_0 + ii,
+					(canvas_base + canvas_num * ii) |
+					((canvas_base + canvas_num * ii + 1)
+						<< 8) |
+					((canvas_base + canvas_num * ii + 1)
+						<< 16)
+				);
+			}
+#else
+		for (ii = 0; ii < hw->vf_buf_num_used; ii += 2) {
+			WRITE_VREG(buf_spec_reg[ii >> 1],
+				(canvas_base + canvas_num * ii) |
+				((canvas_base + canvas_num * ii + 1)
+					<< 8) |
+				((canvas_base + canvas_num * ii + 2)
+					<< 16) |
+				((canvas_base + canvas_num * ii + 3)
+					<< 24)
+			);
+		}
+#endif
+			/*
+			 *WRITE_VREG(AV_SCRATCH_0, 0x010100);
+			 *WRITE_VREG(AV_SCRATCH_1, 0x040403);
+			 *WRITE_VREG(AV_SCRATCH_2, 0x070706);
+			 *WRITE_VREG(AV_SCRATCH_3, 0x0a0a09);
+			 */
+		}
+#else
+		/* index v << 16 | u << 8 | y */
+		WRITE_VREG(AV_SCRATCH_0, 0x020100);
+		WRITE_VREG(AV_SCRATCH_1, 0x050403);
+		WRITE_VREG(AV_SCRATCH_2, 0x080706);
+		WRITE_VREG(AV_SCRATCH_3, 0x0b0a09);
+#endif
+	}
+	/* notify ucode the buffer offset */
+	if (hw->decode_pic_count == 0)
+		WRITE_VREG(AV_SCRATCH_F, hw->buf_offset);
+
+	/* disable PSCALE for hardware sharing */
+	WRITE_VREG(PSCALE_CTRL, 0);
+
+	if (hw->decode_pic_count == 0) {
+#ifndef USE_DYNAMIC_BUF_NUM
+		WRITE_VREG(AVS_SOS_COUNT, 0);
+#endif
+		WRITE_VREG(AVS_BUFFERIN, 0);
+		WRITE_VREG(AVS_BUFFEROUT, 0);
+	}
+	if (error_recovery_mode)
+		WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 0);
+	else
+		WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 1);
+	/* clear mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+	/* enable mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_MASK, 1);
+#ifndef USE_DYNAMIC_BUF_NUM				/* def DEBUG_UCODE */
+	if (hw->decode_pic_count == 0)
+		WRITE_VREG(AV_SCRATCH_D, 0);
+#endif
+
+#ifdef NV21
+	SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17);
+#endif
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
+
+#ifdef PIC_DC_NEED_CLEAR
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31);
+#endif
+	if (hw->m_ins_flag && start_decoding_delay > 0)
+		msleep(start_decoding_delay);
+
+	//pr_info("+++++++++++++++++++++++++++++++\n");
+	//pr_info("+++++++++++++++++++++++++++++++\n");
+	//pr_info("+++++++++++++++++++++++++++++++\n");
+#ifdef AVSP_LONG_CABAC
+	if (firmware_sel == 0) {
+		WRITE_VREG(LONG_CABAC_DES_ADDR, es_write_addr_phy);
+		WRITE_VREG(LONG_CABAC_REQ, 0);
+		WRITE_VREG(LONG_CABAC_PIC_SIZE, 0);
+		WRITE_VREG(LONG_CABAC_SRC_ADDR, 0);
+	}
+#endif
+
+#ifdef ENABLE_USER_DATA
+	if (hw->decode_pic_count == 0) {
+		WRITE_VREG(AV_SCRATCH_N, (u32)(hw->user_data_buffer_phys - hw->buf_offset));
+		pr_debug("AV_SCRATCH_N = 0x%x\n", READ_VREG(AV_SCRATCH_N));
+	} else
+		WRITE_VREG(AV_SCRATCH_N, 0);
+#endif
+	if (hw->m_ins_flag) {
+		if (vdec_frame_based(hw_to_vdec(hw)))
+			WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_FRAMEBASE);
+		else {
+			if (hw->decode_status_skip_pic_done_flag) {
+				WRITE_VREG(DECODE_CFG, hw->decode_decode_cont_start_code);
+				WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_STREAMBASE_CONT);
+			} else
+				WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_STREAMBASE);
+		}
+		WRITE_VREG(DECODE_LMEM_BUF_ADR, (u32)hw->lmem_phy_addr);
+	} else
+		WRITE_VREG(DECODE_MODE, DECODE_MODE_SINGLE);
+
+	if (ins_udebug_flag[DECODE_ID(hw)] &&
+		(ins_udebug_flag[DECODE_ID(hw)] >> 16) == hw->decode_pic_count) {
+		WRITE_VREG(DECODE_STOP_POS,
+			ins_udebug_flag[DECODE_ID(hw)] & 0xffff);
+	}
+	else
+		WRITE_VREG(DECODE_STOP_POS, udebug_flag);
+	hw->old_udebug_flag = udebug_flag;
+
+	return r;
+}
+
+
+#ifdef AVSP_LONG_CABAC
+static unsigned char es_write_addr[MAX_CODED_FRAME_SIZE]  __aligned(64);
+#endif
+static void vavs_local_init(struct vdec_avs_hw_s *hw)
+{
+	int i;
+
+	hw->vf_buf_num_used = vf_buf_num;
+
+	hw->vavs_ratio = hw->vavs_amstream_dec_info.ratio;
+
+	hw->avi_flag = (unsigned long) hw->vavs_amstream_dec_info.param;
+
+	hw->frame_width = hw->frame_height = hw->frame_dur = hw->frame_prog = 0;
+
+	hw->throw_pb_flag = 1;
+
+	hw->total_frame = 0;
+	hw->saved_resolution = 0;
+	hw->next_pts = 0;
+
+#ifdef DEBUG_PTS
+	hw->pts_hit = hw->pts_missed = hw->pts_i_hit = hw->pts_i_missed = 0;
+#endif
+	INIT_KFIFO(hw->display_q);
+	INIT_KFIFO(hw->recycle_q);
+	INIT_KFIFO(hw->newframe_q);
+
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		const struct vframe_s *vf = &hw->vfpool[i].vf;
+
+		hw->vfpool[i].vf.index = hw->vf_buf_num_used;
+		hw->vfpool[i].vf.bufWidth = 1920;
+		hw->vfpool[i].detached = 0;
+		kfifo_put(&hw->newframe_q, vf);
+	}
+	for (i = 0; i < hw->vf_buf_num_used; i++)
+		hw->vfbuf_use[i] = 0;
+
+	/*cur_vfpool = vfpool;*/
+
+	if (hw->recover_flag == 1)
+		return;
+
+	if (hw->mm_blk_handle) {
+		pr_info("decoder_bmmu_box_free\n");
+		decoder_bmmu_box_free(hw->mm_blk_handle);
+		hw->mm_blk_handle = NULL;
+	}
+
+	hw->mm_blk_handle = decoder_bmmu_box_alloc_box(
+		DRIVER_NAME,
+		0,
+		MAX_BMMU_BUFFER_NUM,
+		4 + PAGE_SHIFT,
+		CODEC_MM_FLAGS_CMA_CLEAR |
+		CODEC_MM_FLAGS_FOR_VDECODER);
+	if (hw->mm_blk_handle == NULL)
+		pr_info("Error, decoder_bmmu_box_alloc_box fail\n");
+
+}
+
+static int vavs_vf_states(struct vframe_states *states, void *op_arg)
+{
+	unsigned long flags;
+	struct vdec_avs_hw_s *hw =
+	(struct vdec_avs_hw_s *)op_arg;
+
+
+	spin_lock_irqsave(&lock, flags);
+	states->vf_pool_size = VF_POOL_SIZE;
+	states->buf_free_num = kfifo_len(&hw->newframe_q);
+	states->buf_avail_num = kfifo_len(&hw->display_q);
+	states->buf_recycle_num = kfifo_len(&hw->recycle_q);
+	if (step == 2)
+		states->buf_avail_num = 0;
+	spin_unlock_irqrestore(&lock, flags);
+	return 0;
+}
+
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+static void vavs_ppmgr_reset(void)
+{
+	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL);
+
+	vavs_local_init(ghw);
+
+	pr_info("vavs: vf_ppmgr_reset\n");
+}
+#endif
+
+static void vavs_local_reset(struct vdec_avs_hw_s *hw)
+{
+	mutex_lock(&vavs_mutex);
+	hw->recover_flag = 1;
+	pr_info("error, local reset\n");
+	amvdec_stop();
+	msleep(100);
+	avs_vf_notify_receiver(hw, PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL);
+	vavs_local_init(hw);
+	vavs_recover(hw);
+
+#ifdef ENABLE_USER_DATA
+	reset_userdata_fifo(1);
+#endif
+
+	amvdec_start();
+	hw->recover_flag = 0;
+#if 0
+	error_watchdog_count = 0;
+
+	pr_info("pc %x stream buf wp %x rp %x level %x\n",
+		READ_VREG(MPC_E),
+		READ_VREG(VLD_MEM_VIFIFO_WP),
+		READ_VREG(VLD_MEM_VIFIFO_RP),
+		READ_VREG(VLD_MEM_VIFIFO_LEVEL));
+#endif
+
+
+
+	mutex_unlock(&vavs_mutex);
+}
+
+#if 0
+static struct work_struct fatal_error_wd_work;
+static struct work_struct notify_work;
+static atomic_t error_handler_run = ATOMIC_INIT(0);
+#endif
+static void vavs_fatal_error_handler(struct work_struct *work)
+{
+	struct vdec_avs_hw_s *hw =
+	container_of(work, struct vdec_avs_hw_s, fatal_error_wd_work);
+	if (debug & AVS_DEBUG_OLD_ERROR_HANDLE) {
+		mutex_lock(&vavs_mutex);
+		pr_info("vavs fatal error reset !\n");
+		amvdec_stop();
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+		vavs_ppmgr_reset();
+#else
+		vf_light_unreg_provider(&vavs_vf_prov);
+		vavs_local_init(hw);
+		vf_reg_provider(&vavs_vf_prov);
+#endif
+		vavs_recover(hw);
+		amvdec_start();
+		mutex_unlock(&vavs_mutex);
+	} else {
+		pr_info("avs fatal_error_handler\n");
+		vavs_local_reset(hw);
+	}
+	atomic_set(&hw->error_handler_run, 0);
+}
+
+static void vavs_notify_work(struct work_struct *work)
+{
+	struct vdec_avs_hw_s *hw =
+	container_of(work, struct vdec_avs_hw_s, notify_work);
+	if (hw->fr_hint_status == VDEC_NEED_HINT) {
+		avs_vf_notify_receiver(hw, PROVIDER_NAME ,
+			VFRAME_EVENT_PROVIDER_FR_HINT ,
+			(void *)((unsigned long)hw->frame_dur));
+		hw->fr_hint_status = VDEC_HINTED;
+	}
+	return;
+}
+
+static void avs_set_clk(struct work_struct *work)
+{
+	struct vdec_avs_hw_s *hw =
+	container_of(work, struct vdec_avs_hw_s, set_clk_work);
+	if (hw->frame_dur > 0 && hw->saved_resolution !=
+		hw->frame_width * hw->frame_height * (96000 / hw->frame_dur)) {
+		int fps = 96000 / hw->frame_dur;
+
+		hw->saved_resolution = hw->frame_width * hw->frame_height * fps;
+		if (firmware_sel == 0 &&
+			(debug & AVS_DEBUG_USE_FULL_SPEED)) {
+			vdec_source_changed(VFORMAT_AVS,
+				4096, 2048, 60);
+		} else {
+			vdec_source_changed(VFORMAT_AVS,
+			hw->frame_width, hw->frame_height, fps);
+		}
+
+	}
+}
+
+#ifdef DEBUG_MULTI_WITH_AUTOMODE
+int delay_count = 0;
+#endif
+static void vavs_put_timer_func(struct timer_list *arg)
+{
+	struct vdec_avs_hw_s *hw = container_of(arg,
+		struct vdec_avs_hw_s, recycle_timer);
+	struct timer_list *timer = &hw->recycle_timer;
+
+#ifndef HANDLE_AVS_IRQ
+	vavs_isr();
+#endif
+#ifdef DEBUG_MULTI_WITH_AUTOMODE
+	if (delay_count > 0) {
+		if (delay_count == 1)
+			amvdec_start();
+		delay_count--;
+	}
+#endif
+	if (READ_VREG(AVS_SOS_COUNT)) {
+		if (!error_recovery_mode) {
+#if 0
+			if (debug & AVS_DEBUG_OLD_ERROR_HANDLE) {
+				mutex_lock(&vavs_mutex);
+				pr_info("vavs fatal error reset !\n");
+				amvdec_stop();
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+				vavs_ppmgr_reset();
+#else
+				vf_light_unreg_provider(&vavs_vf_prov);
+				vavs_local_init();
+				vf_reg_provider(&vavs_vf_prov);
+#endif
+				vavs_recover();
+				amvdec_start();
+				mutex_unlock(&vavs_mutex);
+			} else {
+				vavs_local_reset();
+			}
+#else
+			if (!atomic_read(&hw->error_handler_run)) {
+				atomic_set(&hw->error_handler_run, 1);
+				pr_info("AVS_SOS_COUNT = %d\n",
+					READ_VREG(AVS_SOS_COUNT));
+				pr_info("WP = 0x%x, RP = 0x%x, LEVEL = 0x%x, AVAIL = 0x%x, CUR_PTR = 0x%x\n",
+					READ_VREG(VLD_MEM_VIFIFO_WP),
+					READ_VREG(VLD_MEM_VIFIFO_RP),
+					READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+					READ_VREG(VLD_MEM_VIFIFO_BYTES_AVAIL),
+					READ_VREG(VLD_MEM_VIFIFO_CURR_PTR));
+				schedule_work(&hw->fatal_error_wd_work);
+			}
+#endif
+		}
+	}
+#if 0
+	if (long_cabac_busy == 0 &&
+		error_watchdog_threshold > 0 &&
+		kfifo_len(&hw->display_q) == 0 &&
+		READ_VREG(VLD_MEM_VIFIFO_LEVEL) >
+		error_watchdog_buf_threshold) {
+		pr_info("newq %d dispq %d recyq %d\r\n",
+			kfifo_len(&hw->newframe_q),
+			kfifo_len(&hw->display_q),
+			kfifo_len(&hw->recycle_q));
+		pr_info("pc %x stream buf wp %x rp %x level %x\n",
+			READ_VREG(MPC_E),
+			READ_VREG(VLD_MEM_VIFIFO_WP),
+			READ_VREG(VLD_MEM_VIFIFO_RP),
+			READ_VREG(VLD_MEM_VIFIFO_LEVEL));
+		error_watchdog_count++;
+		if (error_watchdog_count >= error_watchdog_threshold)
+			vavs_local_reset();
+	} else
+		error_watchdog_count = 0;
+#endif
+	if (radr != 0) {
+		if (rval != 0) {
+			WRITE_VREG(radr, rval);
+			pr_info("WRITE_VREG(%x,%x)\n", radr, rval);
+		} else
+			pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr));
+		rval = 0;
+		radr = 0;
+	}
+	if ((hw->ucode_pause_pos != 0) &&
+		(hw->ucode_pause_pos != 0xffffffff) &&
+		udebug_pause_pos != hw->ucode_pause_pos) {
+		hw->ucode_pause_pos = 0;
+		WRITE_VREG(DEBUG_REG1, 0);
+	}
+
+	if (!kfifo_is_empty(&hw->recycle_q) && (READ_VREG(AVS_BUFFERIN) == 0)) {
+		struct vframe_s *vf;
+
+		if (kfifo_get(&hw->recycle_q, &vf)) {
+			if ((vf->index < hw->vf_buf_num_used) &&
+			 (--hw->vfbuf_use[vf->index] == 0)) {
+				debug_print(hw, PRINT_FLAG_DECODING,
+					"%s WRITE_VREG(AVS_BUFFERIN, 0x%x) for vf index of %d\n",
+					__func__,
+					~(1 << vf->index), vf->index);
+				WRITE_VREG(AVS_BUFFERIN, ~(1 << vf->index));
+				vf->index = hw->vf_buf_num_used;
+			}
+				kfifo_put(&hw->newframe_q,
+						  (const struct vframe_s *)vf);
+		}
+
+	}
+
+	schedule_work(&hw->set_clk_work);
+
+	timer->expires = jiffies + PUT_INTERVAL;
+
+	add_timer(timer);
+}
+
+#ifdef AVSP_LONG_CABAC
+
+static void long_cabac_do_work(struct work_struct *work)
+{
+	int status = 0;
+	struct vdec_avs_hw_s *hw = gw;
+#ifdef PERFORMANCE_DEBUG
+	pr_info("enter %s buf level (new %d, display %d, recycle %d)\r\n",
+		__func__,
+		kfifo_len(&hw->newframe_q),
+		kfifo_len(&hw->display_q),
+		kfifo_len(&hw->recycle_q)
+		);
+#endif
+	mutex_lock(&vavs_mutex);
+	long_cabac_busy = 1;
+	while (READ_VREG(LONG_CABAC_REQ)) {
+		if (process_long_cabac() < 0) {
+			status = -1;
+			break;
+		}
+	}
+	long_cabac_busy = 0;
+	mutex_unlock(&vavs_mutex);
+#ifdef PERFORMANCE_DEBUG
+	pr_info("exit %s buf level (new %d, display %d, recycle %d)\r\n",
+		__func__,
+		kfifo_len(&hw->newframe_q),
+		kfifo_len(&hw->display_q),
+		kfifo_len(&hw->recycle_q)
+		);
+#endif
+	if (status < 0) {
+		pr_info("transcoding error, local reset\r\n");
+		vavs_local_reset(hw);
+	}
+
+}
+#endif
+
+#ifdef AVSP_LONG_CABAC
+static void init_avsp_long_cabac_buf(void)
+{
+#if 0
+	es_write_addr_phy = (unsigned long)codec_mm_alloc_for_dma(
+		"vavs",
+		PAGE_ALIGN(MAX_CODED_FRAME_SIZE)/PAGE_SIZE,
+		0, CODEC_MM_FLAGS_DMA_CPU);
+	es_write_addr_virt = codec_mm_phys_to_virt(es_write_addr_phy);
+
+#elif 0
+	es_write_addr_virt =
+		(void *)dma_alloc_coherent(amports_get_dma_device(),
+		 MAX_CODED_FRAME_SIZE, &es_write_addr_phy,
+		GFP_KERNEL);
+#else
+	/*es_write_addr_virt = kmalloc(MAX_CODED_FRAME_SIZE, GFP_KERNEL);
+	 *	es_write_addr_virt = (void *)__get_free_pages(GFP_KERNEL,
+	 *	get_order(MAX_CODED_FRAME_SIZE));
+	 */
+	es_write_addr_virt = &es_write_addr[0];
+	if (es_write_addr_virt == NULL) {
+		pr_err("%s: failed to alloc es_write_addr_virt buffer\n",
+			__func__);
+		return;
+	}
+
+	es_write_addr_phy = dma_map_single(amports_get_dma_device(),
+			es_write_addr_virt,
+			MAX_CODED_FRAME_SIZE, DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(amports_get_dma_device(),
+			es_write_addr_phy)) {
+		pr_err("%s: failed to map es_write_addr_virt buffer\n",
+			__func__);
+		/*kfree(es_write_addr_virt);*/
+		es_write_addr_virt = NULL;
+		return;
+	}
+#endif
+
+
+#ifdef BITSTREAM_READ_TMP_NO_CACHE
+	bitstream_read_tmp =
+		(void *)dma_alloc_coherent(amports_get_dma_device(),
+			SVA_STREAM_BUF_SIZE, &bitstream_read_tmp_phy,
+			 GFP_KERNEL);
+
+#else
+
+	bitstream_read_tmp = kmalloc(SVA_STREAM_BUF_SIZE, GFP_KERNEL);
+		/*bitstream_read_tmp = (void *)__get_free_pages(GFP_KERNEL,
+		 *get_order(MAX_CODED_FRAME_SIZE));
+		 */
+	if (bitstream_read_tmp == NULL) {
+		pr_err("%s: failed to alloc bitstream_read_tmp buffer\n",
+			__func__);
+		return;
+	}
+
+	bitstream_read_tmp_phy = dma_map_single(amports_get_dma_device(),
+			bitstream_read_tmp,
+			SVA_STREAM_BUF_SIZE, DMA_FROM_DEVICE);
+	if (dma_mapping_error(amports_get_dma_device(),
+			bitstream_read_tmp_phy)) {
+		pr_err("%s: failed to map rpm buffer\n", __func__);
+		kfree(bitstream_read_tmp);
+		bitstream_read_tmp = NULL;
+		return;
+	}
+#endif
+}
+#endif
+
+
+static s32 vavs_init(struct vdec_avs_hw_s *hw)
+{
+	int ret, size = -1;
+	struct firmware_s *fw;
+	u32 fw_size = 0x1000 * 16;
+	/*char *buf = vmalloc(0x1000 * 16);
+
+	if (IS_ERR_OR_NULL(buf))
+		return -ENOMEM;
+	*/
+	fw = vmalloc(sizeof(struct firmware_s) + fw_size);
+	if (IS_ERR_OR_NULL(fw))
+		return -ENOMEM;
+
+	pr_info("vavs_init\n");
+	//init_timer(&hw->recycle_timer);
+
+	//hw->stat |= STAT_TIMER_INIT;
+
+	//amvdec_enable();
+
+	//vdec_enable_DMC(NULL);
+
+	vavs_local_init(hw);
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM)
+		size = get_firmware_data(VIDEO_DEC_AVS_MULTI, fw->data);
+	else {
+		if (firmware_sel == 1)
+			size = get_firmware_data(VIDEO_DEC_AVS_NOCABAC, fw->data);
+#ifdef AVSP_LONG_CABAC
+		else {
+			init_avsp_long_cabac_buf();
+			size = get_firmware_data(VIDEO_DEC_AVS_MULTI, fw->data);
+		}
+#endif
+	}
+
+	if (size < 0) {
+		amvdec_disable();
+		pr_err("get firmware fail.");
+		vfree(fw);
+		return -1;
+	}
+
+	fw->len = size;
+	hw->fw = fw;
+
+	if (hw->m_ins_flag) {
+		timer_setup(&hw->check_timer, check_timer_func, 0);
+		//init_timer(&hw->check_timer);
+		//hw->check_timer.data = (ulong) hw;
+		//hw->check_timer.function = check_timer_func;
+		hw->check_timer.expires = jiffies + CHECK_INTERVAL;
+
+
+		//add_timer(&hw->check_timer);
+		hw->stat |= STAT_TIMER_ARM;
+
+		INIT_WORK(&hw->work, vavs_work);
+
+		hw->fw = fw;
+		return 0;
+	}
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM)
+		ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, fw->data);
+	else if (firmware_sel == 1)
+		ret = amvdec_loadmc_ex(VFORMAT_AVS, "avs_no_cabac", fw->data);
+	else
+		ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, fw->data);
+
+	if (ret < 0) {
+		amvdec_disable();
+		/*vfree(buf);*/
+		pr_err("AVS: the %s fw loading failed, err: %x\n",
+			tee_enabled() ? "TEE" : "local", ret);
+		return -EBUSY;
+	}
+
+	/*vfree(buf);*/
+
+	hw->stat |= STAT_MC_LOAD;
+
+
+	/* enable AMRISC side protocol */
+	ret = vavs_prot_init(hw);
+	if (ret < 0)
+		return ret;
+
+#ifdef HANDLE_AVS_IRQ
+	if (vdec_request_irq(VDEC_IRQ_1, vavs_isr,
+			"vavs-irq", (void *)hw)) {
+		amvdec_disable();
+		pr_info("vavs irq register error.\n");
+		return -ENOENT;
+	}
+#endif
+
+	hw->stat |= STAT_ISR_REG;
+
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+	vf_provider_init(&vavs_vf_prov, PROVIDER_NAME, &vavs_vf_provider, hw);
+	vf_reg_provider(&vavs_vf_prov);
+	avs_vf_notify_receiver(hw, PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL);
+#else
+	vf_provider_init(&vavs_vf_prov, PROVIDER_NAME, &vavs_vf_provider, hw);
+	vf_reg_provider(&vavs_vf_prov);
+#endif
+
+	if (hw->vavs_amstream_dec_info.rate != 0) {
+		if (!hw->is_reset)
+			avs_vf_notify_receiver(hw, PROVIDER_NAME,
+					VFRAME_EVENT_PROVIDER_FR_HINT,
+					(void *)((unsigned long)
+					hw->vavs_amstream_dec_info.rate));
+		hw->fr_hint_status = VDEC_HINTED;
+	} else
+		hw->fr_hint_status = VDEC_NEED_HINT;
+
+	hw->stat |= STAT_VF_HOOK;
+
+	timer_setup(&hw->recycle_timer, vavs_put_timer_func, 0);
+	//hw->recycle_timer.data = (ulong)(hw);
+	//hw->recycle_timer.function = vavs_put_timer_func;
+	hw->recycle_timer.expires = jiffies + PUT_INTERVAL;
+
+	add_timer(&hw->recycle_timer);
+
+	hw->stat |= STAT_TIMER_ARM;
+
+#ifdef AVSP_LONG_CABAC
+	if (firmware_sel == 0)
+		INIT_WORK(&long_cabac_wd_work, long_cabac_do_work);
+#endif
+	vdec_source_changed(VFORMAT_AVS,
+					1920, 1080, 30);
+#ifdef DEBUG_MULTI_WITH_AUTOMODE
+	if (start_decoding_delay == 0)
+		amvdec_start();
+	else
+		delay_count = start_decoding_delay/10;
+#else
+	amvdec_start();
+#endif
+	hw->stat |= STAT_VDEC_RUN;
+	return 0;
+}
+
+static int amvdec_avs_probe(struct platform_device *pdev)
+{
+	struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
+	struct vdec_avs_hw_s *hw = NULL;
+
+	if (pdata == NULL) {
+		pr_info("amvdec_avs memory resource undefined.\n");
+		return -EFAULT;
+	}
+
+	hw = (struct vdec_avs_hw_s *)vzalloc(sizeof(struct vdec_avs_hw_s));
+	if (hw == NULL) {
+		pr_info("\nammvdec_avs decoder driver alloc failed\n");
+		return -ENOMEM;
+	}
+	pdata->private = hw;
+	ghw = hw;
+	atomic_set(&hw->error_handler_run, 0);
+	hw->m_ins_flag = 0;
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM || disable_longcabac_trans)
+		firmware_sel = 1;
+
+	if (firmware_sel == 1) {
+#ifndef USE_DYNAMIC_BUF_NUM
+		vf_buf_num = 4;
+#endif
+		canvas_base = 0;
+		canvas_num = 3;
+	} else {
+
+		canvas_base = 128;
+		canvas_num = 2; /*NV21*/
+	}
+
+
+	if (pdata->sys_info)
+		hw->vavs_amstream_dec_info = *pdata->sys_info;
+
+	pr_info("%s (%d,%d) %d\n", __func__, hw->vavs_amstream_dec_info.width,
+		   hw->vavs_amstream_dec_info.height, hw->vavs_amstream_dec_info.rate);
+
+	pdata->dec_status = vavs_dec_status;
+	pdata->set_isreset = vavs_set_isreset;
+	hw->is_reset = 0;
+
+	pdata->user_data_read = NULL;
+	pdata->reset_userdata_fifo = NULL;
+
+	vavs_vdec_info_init(hw);
+
+#ifdef ENABLE_USER_DATA
+	if (NULL == hw->user_data_buffer) {
+		hw->user_data_buffer =
+			dma_alloc_coherent(amports_get_dma_device(),
+				USER_DATA_SIZE,
+				&hw->user_data_buffer_phys, GFP_KERNEL);
+		if (!hw->user_data_buffer) {
+			pr_info("%s: Can not allocate hw->user_data_buffer\n",
+				   __func__);
+			return -ENOMEM;
+		}
+		pr_debug("hw->user_data_buffer = 0x%p, hw->user_data_buffer_phys = 0x%x\n",
+			hw->user_data_buffer, (u32)hw->user_data_buffer_phys);
+	}
+#endif
+	INIT_WORK(&hw->set_clk_work, avs_set_clk);
+	if (vavs_init(hw) < 0) {
+		pr_info("amvdec_avs init failed.\n");
+		kfree(hw->gvs);
+		hw->gvs = NULL;
+		pdata->dec_status = NULL;
+		if (hw->fw)
+			vfree(hw->fw);
+		hw->fw = NULL;
+		return -ENODEV;
+	}
+	/*vdec = pdata;*/
+
+	INIT_WORK(&hw->fatal_error_wd_work, vavs_fatal_error_handler);
+	atomic_set(&hw->error_handler_run, 0);
+#ifdef ENABLE_USER_DATA
+	INIT_WORK(&hw->userdata_push_work, userdata_push_do_work);
+#endif
+	INIT_WORK(&hw->notify_work, vavs_notify_work);
+
+	return 0;
+}
+
+static int amvdec_avs_remove(struct platform_device *pdev)
+{
+	struct vdec_avs_hw_s *hw = ghw;
+
+	cancel_work_sync(&hw->fatal_error_wd_work);
+	atomic_set(&hw->error_handler_run, 0);
+#ifdef ENABLE_USER_DATA
+	cancel_work_sync(&hw->userdata_push_work);
+#endif
+	cancel_work_sync(&hw->notify_work);
+	cancel_work_sync(&hw->set_clk_work);
+	if (hw->stat & STAT_VDEC_RUN) {
+		amvdec_stop();
+		hw->stat &= ~STAT_VDEC_RUN;
+	}
+
+	if (hw->stat & STAT_ISR_REG) {
+		vdec_free_irq(VDEC_IRQ_1, (void *)vavs_dec_id);
+		hw->stat &= ~STAT_ISR_REG;
+	}
+
+	if (hw->stat & STAT_TIMER_ARM) {
+		del_timer_sync(&hw->recycle_timer);
+		hw->stat &= ~STAT_TIMER_ARM;
+	}
+#ifdef AVSP_LONG_CABAC
+	if (firmware_sel == 0) {
+		mutex_lock(&vavs_mutex);
+		cancel_work_sync(&long_cabac_wd_work);
+		mutex_unlock(&vavs_mutex);
+
+		if (es_write_addr_virt) {
+#if 0
+			codec_mm_free_for_dma("vavs", es_write_addr_phy);
+#else
+			dma_unmap_single(amports_get_dma_device(),
+				es_write_addr_phy,
+				MAX_CODED_FRAME_SIZE, DMA_FROM_DEVICE);
+			/*kfree(es_write_addr_virt);*/
+			es_write_addr_virt = NULL;
+#endif
+		}
+
+#ifdef BITSTREAM_READ_TMP_NO_CACHE
+		if (bitstream_read_tmp) {
+			dma_free_coherent(amports_get_dma_device(),
+				SVA_STREAM_BUF_SIZE, bitstream_read_tmp,
+				bitstream_read_tmp_phy);
+			bitstream_read_tmp = NULL;
+		}
+#else
+		if (bitstream_read_tmp) {
+			dma_unmap_single(amports_get_dma_device(),
+				bitstream_read_tmp_phy,
+				SVA_STREAM_BUF_SIZE, DMA_FROM_DEVICE);
+			kfree(bitstream_read_tmp);
+			bitstream_read_tmp = NULL;
+		}
+#endif
+	}
+#endif
+	if (hw->stat & STAT_VF_HOOK) {
+		if (hw->fr_hint_status == VDEC_HINTED && !hw->is_reset)
+			avs_vf_notify_receiver(hw, PROVIDER_NAME,
+				VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL);
+		hw->fr_hint_status = VDEC_NO_NEED_HINT;
+		vf_unreg_provider(&vavs_vf_prov);
+		hw->stat &= ~STAT_VF_HOOK;
+	}
+
+#ifdef ENABLE_USER_DATA
+	if (hw->user_data_buffer != NULL) {
+		dma_free_coherent(
+			amports_get_dma_device(),
+			USER_DATA_SIZE,
+			hw->user_data_buffer,
+			hw->user_data_buffer_phys);
+		hw->user_data_buffer = NULL;
+		hw->user_data_buffer_phys = 0;
+	}
+#endif
+
+	if (hw->fw) {
+		vfree(hw->fw);
+		hw->fw = NULL;
+	}
+
+	//amvdec_disable();
+	//vdec_disable_DMC(NULL);
+
+	hw->pic_type = 0;
+	if (hw->mm_blk_handle) {
+		decoder_bmmu_box_free(hw->mm_blk_handle);
+		hw->mm_blk_handle = NULL;
+	}
+#ifdef DEBUG_PTS
+	pr_debug("pts hit %d, pts missed %d, i hit %d, missed %d\n", hw->pts_hit,
+		   hw->pts_missed, hw->pts_i_hit, hw->pts_i_missed);
+	pr_debug("total frame %d, hw->avi_flag %d, rate %d\n", hw->total_frame, hw->avi_flag,
+		   hw->vavs_amstream_dec_info.rate);
+#endif
+	kfree(hw->gvs);
+	hw->gvs = NULL;
+	vfree(hw);
+	return 0;
+}
+
+/****************************************/
+#if 0
+static struct platform_driver amvdec_avs_driver = {
+	.probe = amvdec_avs_probe,
+	.remove = amvdec_avs_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+	}
+};
+#endif
+
+static void recycle_frames(struct vdec_avs_hw_s *hw);
+
+static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
+{
+	struct vdec_avs_hw_s *hw =
+	(struct vdec_avs_hw_s *)vdec->private;
+	int ret = 1;
+	unsigned buf_busy_mask = (1 << hw->vf_buf_num_used) - 1;
+#ifdef DEBUG_MULTI_FRAME_INS
+	if ((DECODE_ID(hw) == 0) && run_count[0] > run_count[1] &&
+		run_count[1] < max_run_count[1])
+		return 0;
+
+	if ((DECODE_ID(hw) == 1) && run_count[1] >= run_count[0] &&
+		run_count[0] < max_run_count[0])
+		return 0;
+
+	if (max_run_count[DECODE_ID(hw)] > 0 &&
+		run_count[DECODE_ID(hw)] >= max_run_count[DECODE_ID(hw)])
+		return 0;
+#endif
+	if (vdec_stream_based(vdec) && (hw->init_flag == 0)
+		&& pre_decode_buf_level != 0) {
+		u32 rp, wp, level;
+
+		rp = STBUF_READ(&vdec->vbuf, get_rp);
+		wp = STBUF_READ(&vdec->vbuf, get_wp);
+		if (wp < rp)
+			level = vdec->input.size + wp - rp;
+		else
+			level = wp - rp;
+
+		if (level < pre_decode_buf_level) {
+			hw->not_run_ready++;
+			return 0;
+		}
+	}
+
+	if (hw->reset_decode_flag == 0 &&
+		hw->again_flag == 0 &&
+		(hw->buf_status & buf_busy_mask) == buf_busy_mask) {
+		recycle_frames(hw);
+		if (hw->buf_recycle_status == 0)
+			ret = 0;
+	}
+
+	if (again_threshold > 0 &&
+		hw->pre_parser_wr_ptr != 0 &&
+		hw->again_flag &&
+		(!vdec_frame_based(vdec))) {
+		u32 parser_wr_ptr =
+			STBUF_READ(&vdec->vbuf, get_rp);
+		if (parser_wr_ptr >= hw->pre_parser_wr_ptr &&
+			(parser_wr_ptr - hw->pre_parser_wr_ptr) <
+			again_threshold) {
+			int r = vdec_sync_input(vdec);
+				debug_print(hw, PRINT_FLAG_VFRAME_DETAIL,
+					"%s buf lelvel:%x\n",  __func__, r);
+			ret = 0;
+		}
+	}
+
+	if (ret)
+		hw->not_run_ready = 0;
+	else
+		hw->not_run_ready++;
+
+	if (ret != 0) {
+		if (vdec->parallel_dec == 1)
+			return (unsigned long)(CORE_MASK_VDEC_1);
+		else
+			return (unsigned long)(CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
+	} else
+		return 0;
+}
+
+static void vavs_work(struct work_struct *work)
+{
+	struct vdec_avs_hw_s *hw =
+	container_of(work, struct vdec_avs_hw_s, work);
+	struct vdec_s *vdec = hw_to_vdec(hw);
+	if (hw->dec_result != DEC_RESULT_AGAIN)
+		debug_print(hw, PRINT_FLAG_RUN_FLOW,
+	"ammvdec_avs: vavs_work,result=%d,status=%d\n",
+	hw->dec_result, hw_to_vdec(hw)->next_status);
+	hw->again_flag = 0;
+	if (hw->dec_result == DEC_RESULT_USERDATA) {
+		userdata_push_process(hw);
+		return;
+	} else if (hw->dec_result == DEC_RESULT_DONE) {
+
+		if (!hw->ctx_valid)
+			hw->ctx_valid = 1;
+#ifdef DEBUG_MULTI_FRAME_INS
+			msleep(delay);
+#endif
+		vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk);
+	} else if (hw->dec_result == DEC_RESULT_AGAIN
+	&& (hw_to_vdec(hw)->next_status !=
+		VDEC_STATUS_DISCONNECTED)) {
+		/*
+			stream base: stream buf empty or timeout
+			frame base: vdec_prepare_input fail
+		*/
+		hw->again_flag = 1;
+		if (!vdec_has_more_input(hw_to_vdec(hw))) {
+			hw->dec_result = DEC_RESULT_EOS;
+			vdec_schedule_work(&hw->work);
+			return;
+		}
+	}  else if (hw->dec_result == DEC_RESULT_GET_DATA
+		&& (hw_to_vdec(hw)->next_status !=
+		VDEC_STATUS_DISCONNECTED)) {
+		if (!vdec_has_more_input(hw_to_vdec(hw))) {
+			hw->dec_result = DEC_RESULT_EOS;
+			vdec_schedule_work(&hw->work);
+			return;
+		}
+		debug_print(hw, PRINT_FLAG_VLD_DETAIL,
+		"%s DEC_RESULT_GET_DATA %x %x %x\n",
+		__func__,
+		READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+		READ_VREG(VLD_MEM_VIFIFO_WP),
+		READ_VREG(VLD_MEM_VIFIFO_RP));
+		vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk);
+		vdec_clean_input(hw_to_vdec(hw));
+		return;
+	} else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) {
+		debug_print(hw, PRINT_FLAG_ERROR,
+		"%s: force exit\n", __func__);
+		if (hw->stat & STAT_ISR_REG) {
+			amvdec_stop();
+			/*disable mbox interrupt */
+			WRITE_VREG(ASSIST_MBOX1_MASK, 0);
+			vdec_free_irq(VDEC_IRQ_1, (void *)hw);
+			hw->stat &= ~STAT_ISR_REG;
+		}
+	} else if (hw->dec_result == DEC_RESULT_EOS) {
+		debug_print(hw, PRINT_FLAG_DECODING,
+			"%s: end of stream\n", __func__);
+		if (hw->stat & STAT_VDEC_RUN) {
+			amvdec_stop();
+			hw->stat &= ~STAT_VDEC_RUN;
+		}
+		hw->eos = 1;
+		vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk);
+		vdec_clean_input(hw_to_vdec(hw));
+	}
+	if (hw->stat & STAT_VDEC_RUN) {
+#if DEBUG_MULTI_FLAG == 1
+#else
+		amvdec_stop();
+#endif
+		hw->stat &= ~STAT_VDEC_RUN;
+	}
+	/*wait_vmmpeg12_search_done(hw);*/
+	if (hw->stat & STAT_TIMER_ARM) {
+		del_timer_sync(&hw->check_timer);
+		hw->stat &= ~STAT_TIMER_ARM;
+	}
+	if (hw->dec_result == DEC_RESULT_DONE)
+		hw->buf_recycle_status = 0;
+	debug_print(hw, PRINT_FLAG_RUN_FLOW, "work end %d\n", hw->dec_result);
+	if (vdec->parallel_dec == 1)
+		vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1);
+	else
+		vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
+
+	if (hw->vdec_cb) {
+		hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg);
+		debug_print(hw, 0x80000,
+		"%s:\n", __func__);
+	}
+}
+
+
+static void reset_process_time(struct vdec_avs_hw_s *hw)
+{
+	if (!hw->m_ins_flag)
+		return;
+	if (hw->start_process_time) {
+		unsigned process_time =
+			1000 * (jiffies - hw->start_process_time) / HZ;
+		hw->start_process_time = 0;
+		if (process_time > max_process_time[DECODE_ID(hw)])
+			max_process_time[DECODE_ID(hw)] = process_time;
+	}
+}
+static void start_process_time(struct vdec_avs_hw_s *hw)
+{
+	hw->decode_timeout_count = 2;
+	hw->start_process_time = jiffies;
+}
+
+static void handle_decoding_error(struct vdec_avs_hw_s *hw)
+{
+	int i;
+	unsigned long flags;
+	struct vframe_s *vf;
+	spin_lock_irqsave(&lock, flags);
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		vf = &hw->vfpool[i].vf;
+		if (vf->index < hw->vf_buf_num_used) {
+			hw->vfpool[i].detached = 1;
+			hw->vfbuf_use[vf->index] = 0;
+		}
+	}
+	if (error_handle_policy & 0x2) {
+		while (!kfifo_is_empty(&hw->display_q)) {
+			if (kfifo_get(&hw->display_q, &vf)) {
+				if (buf_of_vf(vf)->detached !=0) {
+					debug_print(hw, PRINT_FLAG_DECODING,
+						"%s recycle %d => newframe_q\n",
+						__func__,
+						vf->index);
+					vf->index = hw->vf_buf_num_used;
+					buf_of_vf(vf)->detached = 0;
+					kfifo_put(&hw->newframe_q,
+						(const struct vframe_s *)vf);
+				}
+			}
+
+		}
+	}
+	clear_pts_buf(hw);
+	hw->decode_pic_count = 0;
+	hw->reset_decode_flag = 1;
+	hw->pre_parser_wr_ptr = 0;
+	hw->buf_status = 0;
+	hw->throw_pb_flag = 1;
+	spin_unlock_irqrestore(&lock, flags);
+}
+
+static void timeout_process(struct vdec_avs_hw_s *hw)
+{
+	struct vdec_s *vdec = hw_to_vdec(hw);
+	amvdec_stop();
+	if (error_handle_policy & 0x1) {
+		handle_decoding_error(hw);
+	} else {
+		vavs_save_regs(hw);
+
+		//if (hw->decode_pic_count == 0)
+		hw->decode_pic_count++;
+		if ((hw->decode_pic_count & 0xffff) == 0) {
+		/*make ucode do not handle it as first picture*/
+			hw->decode_pic_count++;
+		}
+	}
+	hw->dec_result = DEC_RESULT_DONE;
+
+	debug_print(hw, PRINT_FLAG_ERROR,
+	"%s decoder timeout, status=%d, level=%d, bit_cnt=0x%x\n",
+	__func__, vdec->status, READ_VREG(VLD_MEM_VIFIFO_LEVEL), READ_VREG(VIFF_BIT_CNT));
+	reset_process_time(hw);
+	vdec_schedule_work(&hw->work);
+}
+
+
+static void recycle_frame_bufferin(struct vdec_avs_hw_s *hw)
+{
+	if (!kfifo_is_empty(&hw->recycle_q) && (READ_VREG(AVS_BUFFERIN) == 0)) {
+		struct vframe_s *vf;
+
+		if (kfifo_get(&hw->recycle_q, &vf)) {
+			if (buf_of_vf(vf)->detached) {
+				debug_print(hw, 0,
+					"%s recycle detached vf, index=%d detched %d used %d\n",
+					__func__, vf->index,
+					buf_of_vf(vf)->detached,
+					hw->vfbuf_use[vf->index]);
+			}
+			if ((vf->index < hw->vf_buf_num_used) &&
+				(buf_of_vf(vf)->detached == 0) &&
+			 (--hw->vfbuf_use[vf->index] == 0)) {
+				hw->buf_recycle_status |= (1 << vf->index);
+				WRITE_VREG(AVS_BUFFERIN, ~(1 << vf->index));
+				debug_print(hw, PRINT_FLAG_DECODING,
+					"%s WRITE_VREG(AVS_BUFFERIN, 0x%x) for vf index of %d => buf_recycle_status 0x%x\n",
+					__func__,
+					READ_VREG(AVS_BUFFERIN), vf->index,
+					hw->buf_recycle_status);
+			}
+			vf->index = hw->vf_buf_num_used;
+			buf_of_vf(vf)->detached = 0;
+			kfifo_put(&hw->newframe_q,
+					  (const struct vframe_s *)vf);
+		}
+
+	}
+
+}
+
+static void recycle_frames(struct vdec_avs_hw_s *hw)
+{
+	while (!kfifo_is_empty(&hw->recycle_q)) {
+		struct vframe_s *vf;
+
+		if (kfifo_get(&hw->recycle_q, &vf)) {
+			if (buf_of_vf(vf)->detached) {
+				debug_print(hw, 0,
+					"%s recycle detached vf, index=%d detched %d used %d\n",
+					__func__, vf->index,
+					buf_of_vf(vf)->detached,
+					hw->vfbuf_use[vf->index]);
+			}
+
+
+			if ((vf->index < hw->vf_buf_num_used) &&
+				(buf_of_vf(vf)->detached == 0) &&
+			 (--hw->vfbuf_use[vf->index] == 0)) {
+				hw->buf_recycle_status |= (1 << vf->index);
+				debug_print(hw, PRINT_FLAG_DECODING,
+					"%s for vf index of %d => buf_recycle_status 0x%x\n",
+					__func__,
+					vf->index,
+					hw->buf_recycle_status);
+			}
+			vf->index = hw->vf_buf_num_used;
+			buf_of_vf(vf)->detached = 0;
+			kfifo_put(&hw->newframe_q,
+				(const struct vframe_s *)vf);
+		}
+
+	}
+
+}
+
+
+static void check_timer_func(struct timer_list *timer)
+{
+	struct vdec_avs_hw_s *hw = container_of(timer,
+		struct vdec_avs_hw_s, check_timer);
+	struct vdec_s *vdec = hw_to_vdec(hw);
+	unsigned int timeout_val = decode_timeout_val;
+	unsigned long flags;
+
+	if (hw->m_ins_flag &&
+		(debug &
+		DEBUG_WAIT_DECODE_DONE_WHEN_STOP) == 0 &&
+		vdec->next_status ==
+		VDEC_STATUS_DISCONNECTED) {
+		hw->dec_result = DEC_RESULT_FORCE_EXIT;
+		vdec_schedule_work(&hw->work);
+		debug_print(hw,
+			0, "vdec requested to be disconnected\n");
+		return;
+	}
+
+	/*recycle*/
+	if (!hw->m_ins_flag) {
+		spin_lock_irqsave(&lock, flags);
+		recycle_frame_bufferin(hw);
+		spin_unlock_irqrestore(&lock, flags);
+	}
+
+	if (hw->m_ins_flag) {
+		if ((READ_VREG(AV_SCRATCH_5) & 0xf) != 0 &&
+			(READ_VREG(AV_SCRATCH_5) & 0xff00) != 0){
+			/*ucode buffer empty*/
+			if ((kfifo_len(&hw->recycle_q) == 0) &&
+				(kfifo_len(&hw->display_q) == 0)) {
+				debug_print(hw,
+					0, "AV_SCRATCH_5=0x%x, recover ucode buffer_status\n",
+					READ_VREG(AV_SCRATCH_5));
+				WRITE_VREG(AV_SCRATCH_5, 0x10);
+				/*let ucode to recover buffer_status*/
+			}
+		}
+	}
+	if (radr != 0) {
+		if (rval != 0) {
+			WRITE_VREG(radr, rval);
+			pr_info("WRITE_VREG(%x,%x)\n", radr, rval);
+		} else
+			pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr));
+		rval = 0;
+		radr = 0;
+	}
+
+	if (udebug_flag != hw->old_udebug_flag) {
+		WRITE_VREG(DECODE_STOP_POS, udebug_flag);
+		hw->old_udebug_flag = udebug_flag;
+	}
+	if (dbg_cmd != 0) {
+		if (dbg_cmd == 1) {
+			int r = vdec_sync_input(vdec);
+			dbg_cmd = 0;
+			pr_info(
+				"vdec_sync_input=>0x%x, (lev %x, wp %x rp %x, prp %x, pwp %x)\n",
+				r,
+				READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+				READ_VREG(VLD_MEM_VIFIFO_WP),
+				READ_VREG(VLD_MEM_VIFIFO_RP),
+				STBUF_READ(&vdec->vbuf, get_rp),
+				STBUF_READ(&vdec->vbuf, get_wp));
+		}
+	}
+
+	if ((debug & DEBUG_FLAG_DISABLE_TIMEOUT) == 0 &&
+		(timeout_val > 0) &&
+		(hw->start_process_time > 0) &&
+		((1000 * (jiffies - hw->start_process_time) / HZ)
+				> timeout_val)) {
+		if (hw->last_vld_level == READ_VREG(VLD_MEM_VIFIFO_LEVEL)) {
+			if (hw->decode_timeout_count > 0)
+				hw->decode_timeout_count--;
+			if (hw->decode_timeout_count == 0)
+				timeout_process(hw);
+		}
+		hw->last_vld_level = READ_VREG(VLD_MEM_VIFIFO_LEVEL);
+	}
+
+	if (READ_VREG(AVS_SOS_COUNT)) {
+		if (!error_recovery_mode) {
+			amvdec_stop();
+			if (error_handle_policy & 0x1) {
+				handle_decoding_error(hw);
+			} else {
+				vavs_save_regs(hw);
+
+				//if (hw->decode_pic_count == 0)
+				hw->decode_pic_count++;
+				if ((hw->decode_pic_count & 0xffff) == 0) {
+				/*make ucode do not handle it as first picture*/
+					hw->decode_pic_count++;
+				}
+			}
+			hw->dec_result = DEC_RESULT_DONE;
+
+			debug_print(hw, PRINT_FLAG_ERROR,
+			"%s decoder error, status=%d, level=%d, AVS_SOS_COUNT=0x%x\n",
+			__func__, vdec->status, READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+			READ_VREG(AVS_SOS_COUNT));
+			reset_process_time(hw);
+			vdec_schedule_work(&hw->work);
+		}
+	}
+
+	if ((hw->ucode_pause_pos != 0) &&
+		(hw->ucode_pause_pos != 0xffffffff) &&
+		udebug_pause_pos != hw->ucode_pause_pos) {
+		hw->ucode_pause_pos = 0;
+		WRITE_VREG(DEBUG_REG1, 0);
+	}
+
+	if (vdec->next_status == VDEC_STATUS_DISCONNECTED) {
+		hw->dec_result = DEC_RESULT_FORCE_EXIT;
+		vdec_schedule_work(&hw->work);
+		pr_info("vdec requested to be disconnected\n");
+		return;
+	}
+
+	mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL);
+}
+
+static int avs_hw_ctx_restore(struct vdec_avs_hw_s *hw)
+{
+	/*int r = 0;*/
+	vavs_prot_init(hw);
+
+	return 0;
+}
+
+static unsigned char get_data_check_sum
+	(struct vdec_avs_hw_s *hw, int size)
+{
+	int jj;
+	int sum = 0;
+	u8 *data = NULL;
+
+	if (!hw->chunk->block->is_mapped)
+		data = codec_mm_vmap(hw->chunk->block->start +
+			hw->chunk->offset, size);
+	else
+		data = ((u8 *)hw->chunk->block->start_virt) +
+			hw->chunk->offset;
+
+	for (jj = 0; jj < size; jj++)
+		sum += data[jj];
+
+	if (!hw->chunk->block->is_mapped)
+		codec_mm_unmap_phyaddr(data);
+	return sum;
+}
+
+static void run(struct vdec_s *vdec, unsigned long mask,
+void (*callback)(struct vdec_s *, void *),
+		void *arg)
+{
+	struct vdec_avs_hw_s *hw =
+	(struct vdec_avs_hw_s *)vdec->private;
+	int save_reg;
+	int size, ret;
+	if (!hw->vdec_pg_enable_flag) {
+		hw->vdec_pg_enable_flag = 1;
+		amvdec_enable();
+	}
+	save_reg = READ_VREG(POWER_CTL_VLD);
+	/* reset everything except DOS_TOP[1] and APB_CBUS[0]*/
+	debug_print(hw, PRINT_FLAG_RUN_FLOW,"run in\n");
+	if (vdec_stream_based(vdec)) {
+		hw->pre_parser_wr_ptr =
+			STBUF_READ(&vdec->vbuf, get_wp);
+	}
+#if 1
+#if DEBUG_MULTI_FLAG > 0
+	if (hw->decode_pic_count == 0) {
+#endif
+	WRITE_VREG(DOS_SW_RESET0, 0xfffffff0);
+	WRITE_VREG(DOS_SW_RESET0, 0);
+	WRITE_VREG(POWER_CTL_VLD, save_reg);
+	hw->run_count++;
+	run_count[DECODE_ID(hw)] = hw->run_count;
+	vdec_reset_core(vdec);
+#if DEBUG_MULTI_FLAG > 0
+	}
+#endif
+#else
+	vdec_reset_core(vdec);
+#endif
+	hw->vdec_cb_arg = arg;
+	hw->vdec_cb = callback;
+
+	size = vdec_prepare_input(vdec, &hw->chunk);
+	if (debug & DEBUG_FLAG_PREPARE_MORE_INPUT) {
+		if (size < start_decode_buf_level) {
+			/*debug_print(hw, PRINT_FLAG_VLD_DETAIL,
+				"DEC_RESULT_AGAIN %x %x %x\n",
+				READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+				READ_VREG(VLD_MEM_VIFIFO_WP),
+				READ_VREG(VLD_MEM_VIFIFO_RP));*/
+
+			hw->input_empty++;
+			hw->dec_result = DEC_RESULT_AGAIN;
+			vdec_schedule_work(&hw->work);
+			return;
+		}
+	} else {
+		if (size < 0) {
+			hw->input_empty++;
+			hw->dec_result = DEC_RESULT_AGAIN;
+			vdec_schedule_work(&hw->work);
+			return;
+		}
+	}
+	if (input_frame_based(vdec)) {
+		u8 *data = NULL;
+
+		if (!hw->chunk->block->is_mapped)
+			data = codec_mm_vmap(hw->chunk->block->start +
+				hw->chunk->offset, size);
+		else
+			data = ((u8 *)hw->chunk->block->start_virt) +
+				hw->chunk->offset;
+
+		if (debug & PRINT_FLAG_RUN_FLOW
+			) {
+			debug_print(hw, 0,
+			"%s decode_pic_count %d buf_recycle_status 0x%x: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n",
+			__func__, hw->decode_pic_count,
+			hw->buf_recycle_status,
+			size, get_data_check_sum(hw, size),
+			data[0], data[1], data[2], data[3],
+			data[4], data[5], data[size - 4],
+			data[size - 3],	data[size - 2],
+			data[size - 1]);
+		}
+		if (debug & PRINT_FRAMEBASE_DATA
+			) {
+			int jj;
+
+			for (jj = 0; jj < size; jj++) {
+				if ((jj & 0xf) == 0)
+					debug_print(hw,
+					PRINT_FRAMEBASE_DATA,
+						"%06x:", jj);
+				debug_print(hw,
+				PRINT_FRAMEBASE_DATA,
+					"%02x ", data[jj]);
+				if (((jj + 1) & 0xf) == 0)
+					debug_print(hw,
+					PRINT_FRAMEBASE_DATA,
+						"\n");
+			}
+		}
+
+		if (!hw->chunk->block->is_mapped)
+			codec_mm_unmap_phyaddr(data);
+	} else
+		debug_print(hw, PRINT_FLAG_RUN_FLOW,
+			"%s decode_pic_count %d buf_recycle_status 0x%x: %x %x %x %x %x size 0x%x\n",
+			__func__,
+			hw->decode_pic_count,
+			hw->buf_recycle_status,
+			READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+			READ_VREG(VLD_MEM_VIFIFO_WP),
+			READ_VREG(VLD_MEM_VIFIFO_RP),
+			STBUF_READ(&vdec->vbuf, get_rp),
+			STBUF_READ(&vdec->vbuf, get_wp),
+			size);
+
+
+	hw->input_empty = 0;
+	debug_print(hw, PRINT_FLAG_RUN_FLOW,
+	"%s,%d, size=%d\n", __func__, __LINE__, size);
+
+	/*vdec_enable_input(vdec);
+		need run after VC1_CONTROL_REG is configured
+	*/
+	hw->init_flag = 1;
+
+	if (hw->chunk)
+		debug_print(hw, PRINT_FLAG_RUN_FLOW,
+		"input chunk offset %d, size %d\n",
+			hw->chunk->offset, hw->chunk->size);
+
+	hw->dec_result = DEC_RESULT_NONE;
+	/*vdec->mc_loaded = 0;*/
+	if (vdec->mc_loaded) {
+	/*firmware have load before,
+	  and not changes to another.
+	  ignore reload.
+	*/
+	} else {
+		ret = amvdec_vdec_loadmc_buf_ex(VFORMAT_AVS, "avs_multi", vdec,
+			hw->fw->data, hw->fw->len);
+		if (ret < 0) {
+			pr_err("[%d] %s: the %s fw loading failed, err: %x\n", vdec->id,
+				hw->fw->name, tee_enabled() ? "TEE" : "local", ret);
+			hw->dec_result = DEC_RESULT_FORCE_EXIT;
+			vdec_schedule_work(&hw->work);
+			return;
+		}
+		vdec->mc_loaded = 1;
+		vdec->mc_type = VFORMAT_AVS;
+	}
+	if (avs_hw_ctx_restore(hw) < 0) {
+		hw->dec_result = DEC_RESULT_ERROR;
+		debug_print(hw, PRINT_FLAG_ERROR,
+		"ammvdec_avs: error HW context restore\n");
+		vdec_schedule_work(&hw->work);
+		return;
+	}
+
+	/*
+		This configureation of VC1_CONTROL_REG will
+		pop bits (even no data in the stream buffer) if input is enabled,
+		so it can only be configured before vdec_enable_input() is called.
+		So move this code from ucode to here
+	*/
+#define DISABLE_DBLK_HCMD   0
+#define DISABLE_MC_HCMD 0
+	WRITE_VREG(VC1_CONTROL_REG, (DISABLE_DBLK_HCMD<<6) |
+		(DISABLE_MC_HCMD<<5) | (1 << 7) | (0xc <<8) | (1<<14));
+	if (vdec_frame_based(vdec)) {
+			size = hw->chunk->size +
+				(hw->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+		}
+
+
+	vdec_enable_input(vdec);
+	/**/
+
+	/*wmb();*/
+	hw->stat |= STAT_MC_LOAD;
+	hw->last_vld_level = 0;
+
+	debug_print(hw, PRINT_FLAG_DECODING,
+		"%s READ_VREG(AVS_BUFFERIN)=0x%x, recycle_q num %d\n",
+		__func__, READ_VREG(AVS_BUFFERIN),
+		kfifo_len(&hw->recycle_q));
+
+	WRITE_VREG(VIFF_BIT_CNT, size * 8);
+	if (hw->reset_decode_flag)
+		WRITE_VREG(DECODE_STATUS, 0);
+	else {
+		recycle_frames(hw);
+		avs_pts_check_in(hw,
+			hw->decode_pic_count & 0xffff,
+			hw->chunk);
+
+		WRITE_VREG(DECODE_STATUS,
+			(hw->decode_pic_count & 0xffff) |
+			((~hw->buf_recycle_status) << 16));
+	}
+
+	hw->reset_decode_flag = 0;
+	//hw->decode_status_skip_pic_done_flag = 0;
+	start_process_time(hw);
+#if DEBUG_MULTI_FLAG == 1
+	if (hw->decode_pic_count > 0)
+		WRITE_VREG(DECODE_STATUS, 0xff);
+	else
+#endif
+	amvdec_start();
+	hw->stat |= STAT_VDEC_RUN;
+
+	hw->stat |= STAT_TIMER_ARM;
+
+	mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL);
+}
+
+static void reset(struct vdec_s *vdec)
+{
+}
+
+static irqreturn_t vmavs_isr_thread_fn(struct vdec_s *vdec, int irq)
+{
+		struct vdec_avs_hw_s *hw =
+			(struct vdec_avs_hw_s *)vdec->private;
+		u32 reg;
+		struct vframe_s *vf = NULL;
+		u32 dur;
+		u32 repeat_count;
+		u32 picture_type;
+		u32 buffer_index;
+		u32 frame_size;
+		bool force_interlaced_frame = false;
+		unsigned int pts, pts_valid = 0, offset = 0;
+		u64 pts_us64;
+		u32 debug_tag;
+		u32 buffer_status_debug;
+		//struct vdec_avs_hw_s *hw = (struct vdec_avs_hw_s *)dev_id;
+
+		/*if (debug & AVS_DEBUG_UCODE) {
+			if (READ_VREG(AV_SCRATCH_E) != 0) {
+				pr_info("dbg%x: %x\n", READ_VREG(AV_SCRATCH_E),
+					   READ_VREG(AV_SCRATCH_D));
+				WRITE_VREG(AV_SCRATCH_E, 0);
+			}
+		}*/
+
+		debug_print(hw, PRINT_FLAG_RUN_FLOW, "READ_VREG(AVS_BUFFEROUT) 0x%x, READ_VREG(DECODE_STATUS) 0x%x READ_VREG(AV_SCRATCH_N) 0x%x, READ_VREG(DEBUG_REG1) 0x%x\n",
+				READ_VREG(AVS_BUFFEROUT),READ_VREG(DECODE_STATUS), READ_VREG(AV_SCRATCH_N), READ_VREG(DEBUG_REG1));
+
+		debug_tag = READ_VREG(DEBUG_REG1);
+		buffer_status_debug = debug_tag >> 16;
+		debug_tag &= 0xffff;
+		/* if (debug_tag & 0x10000) {
+			int i;
+			dma_sync_single_for_cpu(
+				amports_get_dma_device(),
+				hw->lmem_phy_addr,
+				LMEM_BUF_SIZE,
+				DMA_FROM_DEVICE);
+
+			debug_print(hw, 0,
+				"LMEM<tag %x>:\n", debug_tag);
+
+			for (i = 0; i < 0x400; i += 4) {
+				int ii;
+				unsigned short *lmem_ptr = hw->lmem_addr;
+				if ((i & 0xf) == 0)
+					debug_print_cont(hw, 0, "%03x: ", i);
+				for (ii = 0; ii < 4; ii++) {
+					debug_print_cont(hw, 0, "%04x ",
+						   lmem_ptr[i + 3 - ii]);
+				}
+				if (((i + ii) & 0xf) == 0)
+					debug_print_cont(hw, 0, "\n");
+			}
+
+			if (((udebug_pause_pos & 0xffff)
+				== (debug_tag & 0xffff)) &&
+				(udebug_pause_decode_idx == 0 ||
+				udebug_pause_decode_idx == hw->decode_pic_count) &&
+				(udebug_pause_val == 0 ||
+				udebug_pause_val == READ_VREG(DEBUG_REG2))) {
+				udebug_pause_pos &= 0xffff;
+				hw->ucode_pause_pos = udebug_pause_pos;
+			}
+			else if (debug_tag & 0x20000)
+				hw->ucode_pause_pos = 0xffffffff;
+			if (hw->ucode_pause_pos)
+				reset_process_time(hw);
+			else
+				WRITE_VREG(DEBUG_REG1, 0);
+		} else*/ if (debug_tag != 0) {
+			debug_print(hw, 1,
+				"dbg%x: %x buffer_status 0x%x l/w/r %x %x %x bitcnt %x AVAIL %x\n",
+				debug_tag,
+				READ_VREG(DEBUG_REG2),
+				buffer_status_debug,
+				READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+				READ_VREG(VLD_MEM_VIFIFO_WP),
+				READ_VREG(VLD_MEM_VIFIFO_RP),
+				READ_VREG(VIFF_BIT_CNT),
+				READ_VREG(VLD_MEM_VIFIFO_BYTES_AVAIL));
+
+			if (((udebug_pause_pos & 0xffff)
+				== (debug_tag & 0xffff)) &&
+				(udebug_pause_decode_idx == 0 ||
+				udebug_pause_decode_idx == hw->decode_pic_count) &&
+				(udebug_pause_val == 0 ||
+				udebug_pause_val == READ_VREG(DEBUG_REG2)) &&
+				(udebug_pause_ins_id == 0 ||
+					DECODE_ID(hw) == (udebug_pause_ins_id -1))) {
+				udebug_pause_pos &= 0xffff;
+				hw->ucode_pause_pos = udebug_pause_pos;
+				if (debug & DEBUG_PIC_DONE_WHEN_UCODE_PAUSE) {
+					hw->decode_pic_count++;
+					if ((hw->decode_pic_count & 0xffff) == 0) {
+						/*make ucode do not handle it as first picture*/
+						hw->decode_pic_count++;
+					}
+					reset_process_time(hw);
+					hw->dec_result = DEC_RESULT_DONE;
+					amvdec_stop();
+					vavs_save_regs(hw);
+					debug_print(hw, PRINT_FLAG_DECODING,
+						"%s ucode pause, force done, decode_pic_count = %d, bit_cnt=0x%x\n",
+						__func__,
+						hw->decode_pic_count,
+						READ_VREG(VIFF_BIT_CNT));
+					vdec_schedule_work(&hw->work);
+					return IRQ_HANDLED;
+				}
+			}
+			if (hw->ucode_pause_pos)
+				reset_process_time(hw);
+			else
+				WRITE_VREG(DEBUG_REG1, 0);
+			return IRQ_HANDLED;
+		} else {
+			debug_print(hw, PRINT_FLAG_DECODING,
+				"%s decode_status 0x%x, buffer_status 0x%x\n",
+				__func__,
+				READ_VREG(DECODE_STATUS),
+				buffer_status_debug);
+		}
+
+#ifdef AVSP_LONG_CABAC
+		if (firmware_sel == 0 && READ_VREG(LONG_CABAC_REQ)) {
+#ifdef PERFORMANCE_DEBUG
+			pr_info("%s:schedule long_cabac_wd_work\r\n", __func__);
+#endif
+			pr_info("schedule long_cabac_wd_work and requested from %d\n",
+				(READ_VREG(LONG_CABAC_REQ) >> 8)&0xFF);
+			schedule_work(&long_cabac_wd_work);
+		}
+#endif
+
+#ifdef ENABLE_USER_DATA
+		if (UserDataHandler(hw))
+			return IRQ_HANDLED;
+#endif
+		reg = READ_VREG(AVS_BUFFEROUT);
+		if (reg) {
+			unsigned short decode_pic_count
+				= READ_VREG(DECODE_PIC_COUNT);
+			debug_print(hw, PRINT_FLAG_DECODING, "AVS_BUFFEROUT=0x%x decode_pic_count %d\n",
+				reg, decode_pic_count);
+			if (pts_by_offset) {
+				offset = READ_VREG(AVS_OFFSET_REG);
+				debug_print(hw, PRINT_FLAG_DECODING, "AVS OFFSET=%x\n", offset);
+				if ((vdec->vbuf.no_parser == 0) || (vdec->vbuf.use_ptsserv)) {
+					if (pts_lookup_offset_us64(PTS_TYPE_VIDEO, offset, &pts,
+						&frame_size, 0, &pts_us64) == 0) {
+						pts_valid = 1;
+#ifdef DEBUG_PTS
+						hw->pts_hit++;
+#endif
+					} else {
+#ifdef DEBUG_PTS
+						hw->pts_missed++;
+#endif
+					}
+				}
+			}
+
+			repeat_count = READ_VREG(AVS_REPEAT_COUNT);
+#ifdef USE_DYNAMIC_BUF_NUM
+			buffer_index =
+				((reg & 0x7) +
+				(((reg >> 8) & 0x3) << 3) - 1) & 0x1f;
+#else
+			if (firmware_sel == 0)
+				buffer_index =
+					((reg & 0x7) +
+					(((reg >> 8) & 0x3) << 3) - 1) & 0x1f;
+			else
+				buffer_index =
+					((reg & 0x7) - 1) & 3;
+#endif
+			picture_type = (reg >> 3) & 7;
+#ifdef DEBUG_PTS
+			if (picture_type == I_PICTURE) {
+				/* pr_info("I offset 0x%x, pts_valid %d\n",
+				 *	 offset, pts_valid);
+				 */
+				if (!pts_valid)
+					hw->pts_i_missed++;
+				else
+					hw->pts_i_hit++;
+			}
+#endif
+
+			if ((dec_control & DEC_CONTROL_FLAG_FORCE_2500_1080P_INTERLACE)
+				&& hw->frame_width == 1920 && hw->frame_height == 1080) {
+				force_interlaced_frame = true;
+			}
+
+			if (hw->throw_pb_flag && picture_type != I_PICTURE) {
+
+				debug_print(hw, PRINT_FLAG_DECODING,
+					"%s WRITE_VREG(AVS_BUFFERIN, 0x%x) for throwing picture with type of %d\n",
+					__func__,
+					~(1 << buffer_index), picture_type);
+
+				WRITE_VREG(AVS_BUFFERIN, ~(1 << buffer_index));
+			} else if (reg & INTERLACE_FLAG || force_interlaced_frame) {	/* interlace */
+				hw->throw_pb_flag = 0;
+
+				debug_print(hw, PRINT_FLAG_VFRAME_DETAIL,
+					"interlace, picture type %d\n",
+						   picture_type);
+
+				if (kfifo_get(&hw->newframe_q, &vf) == 0) {
+					pr_info
+					("fatal error, no available buffer slot.");
+					return IRQ_HANDLED;
+				}
+				set_frame_info(hw, vf, &dur);
+				vf->bufWidth = 1920;
+				hw->pic_type = 2;
+				if ((picture_type == I_PICTURE) && pts_valid) {
+					vf->pts = pts;
+					vf->pts_us64 = pts_us64;
+					if ((repeat_count > 1) && hw->avi_flag) {
+						/* hw->next_pts = pts +
+						 *	 (hw->vavs_amstream_dec_info.rate *
+						 *	 repeat_count >> 1)*15/16;
+						 */
+						hw->next_pts =
+							pts +
+							(dur * repeat_count >> 1) *
+							15 / 16;
+					} else
+						hw->next_pts = 0;
+				} else {
+					vf->pts = hw->next_pts;
+					if (vf->pts == 0) {
+						vf->pts_us64 = 0;
+					}
+					if ((repeat_count > 1) && hw->avi_flag) {
+						/* vf->duration =
+						 *	 hw->vavs_amstream_dec_info.rate *
+						 *	 repeat_count >> 1;
+						 */
+						vf->duration = dur * repeat_count >> 1;
+						if (hw->next_pts != 0) {
+							hw->next_pts +=
+								((vf->duration) -
+								 ((vf->duration) >> 4));
+						}
+					} else {
+						/* vf->duration =
+						 *	 hw->vavs_amstream_dec_info.rate >> 1;
+						 */
+						vf->duration = dur >> 1;
+						hw->next_pts = 0;
+					}
+				}
+				vf->signal_type = 0;
+				vf->index = buffer_index;
+				vf->duration_pulldown = 0;
+				if (force_interlaced_frame) {
+					vf->type = VIDTYPE_INTERLACE_TOP;
+				}else{
+					vf->type =
+					(reg & TOP_FIELD_FIRST_FLAG)
+					? VIDTYPE_INTERLACE_TOP
+					: VIDTYPE_INTERLACE_BOTTOM;
+					}
+#ifdef NV21
+				vf->type |= VIDTYPE_VIU_NV21;
+#endif
+				if (hw->m_ins_flag) {
+					vf->canvas0Addr = vf->canvas1Addr = -1;
+					vf->plane_num = 2;
+
+					vf->canvas0_config[0] = hw->canvas_config[buffer_index][0];
+					vf->canvas0_config[1] = hw->canvas_config[buffer_index][1];
+
+					vf->canvas1_config[0] = hw->canvas_config[buffer_index][0];
+					vf->canvas1_config[1] = hw->canvas_config[buffer_index][1];
+				} else
+					vf->canvas0Addr = vf->canvas1Addr =
+						index2canvas(buffer_index);
+				vf->type_original = vf->type;
+
+				debug_print(hw, PRINT_FLAG_VFRAME_DETAIL,
+					"buffer_index %d, canvas addr %x\n",
+						   buffer_index, vf->canvas0Addr);
+				vf->pts = (pts_valid)?pts:0;
+				//vf->pts_us64 = (pts_valid) ? pts_us64 : 0;
+				hw->vfbuf_use[buffer_index]++;
+				vf->mem_handle =
+					decoder_bmmu_box_get_mem_handle(
+						hw->mm_blk_handle,
+						buffer_index);
+
+				if (hw->m_ins_flag && vdec_frame_based(hw_to_vdec(hw)))
+					set_vframe_pts(hw, decode_pic_count, vf);
+
+				if (vdec_stream_based(vdec) && (!vdec->vbuf.use_ptsserv)) {
+					vf->pts_us64 =
+						(((u64)vf->duration << 32) & 0xffffffff00000000) | offset;
+					vf->pts = 0;
+				}
+
+				debug_print(hw, PRINT_FLAG_PTS,
+					"interlace1 vf->pts = %d, vf->pts_us64 = %lld, pts_valid = %d\n", vf->pts, vf->pts_us64, pts_valid);
+				vdec_vframe_ready(vdec, vf);
+				kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
+				ATRACE_COUNTER(hw->pts_name, vf->pts);
+				avs_vf_notify_receiver(hw, PROVIDER_NAME,
+						VFRAME_EVENT_PROVIDER_VFRAME_READY,
+						NULL);
+
+				if (kfifo_get(&hw->newframe_q, &vf) == 0) {
+					pr_info("fatal error, no available buffer slot.");
+					return IRQ_HANDLED;
+							}
+				set_frame_info(hw, vf, &dur);
+				vf->bufWidth = 1920;
+				if (force_interlaced_frame)
+					vf->pts = 0;
+				else
+				vf->pts = hw->next_pts;
+
+				if (vf->pts == 0) {
+					vf->pts_us64 = 0;
+				}
+
+				if ((repeat_count > 1) && hw->avi_flag) {
+					/* vf->duration = hw->vavs_amstream_dec_info.rate *
+					 *	 repeat_count >> 1;
+					 */
+					vf->duration = dur * repeat_count >> 1;
+					if (hw->next_pts != 0) {
+						hw->next_pts +=
+							((vf->duration) -
+							 ((vf->duration) >> 4));
+					}
+				} else {
+					/* vf->duration = hw->vavs_amstream_dec_info.rate
+					 *	 >> 1;
+					 */
+					vf->duration = dur >> 1;
+					hw->next_pts = 0;
+				}
+				vf->signal_type = 0;
+				vf->index = buffer_index;
+				vf->duration_pulldown = 0;
+				if (force_interlaced_frame) {
+					vf->type = VIDTYPE_INTERLACE_BOTTOM;
+				} else {
+							vf->type =
+							(reg & TOP_FIELD_FIRST_FLAG) ?
+							VIDTYPE_INTERLACE_BOTTOM :
+							VIDTYPE_INTERLACE_TOP;
+						}
+#ifdef NV21
+				vf->type |= VIDTYPE_VIU_NV21;
+#endif
+				if (hw->m_ins_flag) {
+					vf->canvas0Addr = vf->canvas1Addr = -1;
+					vf->plane_num = 2;
+
+					vf->canvas0_config[0] = hw->canvas_config[buffer_index][0];
+					vf->canvas0_config[1] = hw->canvas_config[buffer_index][1];
+
+					vf->canvas1_config[0] = hw->canvas_config[buffer_index][0];
+					vf->canvas1_config[1] = hw->canvas_config[buffer_index][1];
+				} else
+					vf->canvas0Addr = vf->canvas1Addr =
+						index2canvas(buffer_index);
+				vf->type_original = vf->type;
+				vf->pts_us64 = 0;
+				hw->vfbuf_use[buffer_index]++;
+				vf->mem_handle =
+					decoder_bmmu_box_get_mem_handle(
+						hw->mm_blk_handle,
+						buffer_index);
+
+				if (hw->m_ins_flag && vdec_frame_based(hw_to_vdec(hw)))
+					set_vframe_pts(hw, decode_pic_count, vf);
+
+				if (vdec_stream_based(vdec) && (!vdec->vbuf.use_ptsserv)) {
+					vf->pts_us64 = (u64)-1;
+					vf->pts = 0;
+				}
+				debug_print(hw, PRINT_FLAG_PTS,
+					"interlace2 vf->pts = %d, vf->pts_us64 = %lld, pts_valid = %d\n", vf->pts, vf->pts_us64, pts_valid);
+				vdec_vframe_ready(vdec, vf);
+				kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
+				ATRACE_COUNTER(hw->pts_name, vf->pts);
+				avs_vf_notify_receiver(hw, PROVIDER_NAME,
+						VFRAME_EVENT_PROVIDER_VFRAME_READY,
+						NULL);
+				hw->total_frame++;
+			} else {	/* progressive */
+				hw->throw_pb_flag = 0;
+
+				debug_print(hw, PRINT_FLAG_VFRAME_DETAIL,
+					"progressive picture type %d\n",
+						   picture_type);
+				if (kfifo_get(&hw->newframe_q, &vf) == 0) {
+					pr_info
+					("fatal error, no available buffer slot.");
+					return IRQ_HANDLED;
+				}
+				set_frame_info(hw, vf, &dur);
+				vf->bufWidth = 1920;
+				hw->pic_type = 1;
+
+				if ((picture_type == I_PICTURE) && pts_valid) {
+					vf->pts = pts;
+					if ((repeat_count > 1) && hw->avi_flag) {
+						/* hw->next_pts = pts +
+						 *	 (hw->vavs_amstream_dec_info.rate *
+						 *	 repeat_count)*15/16;
+						 */
+						hw->next_pts =
+							pts +
+							(dur * repeat_count) * 15 / 16;
+					} else
+						hw->next_pts = 0;
+				} else {
+					vf->pts = hw->next_pts;
+					if (vf->pts == 0) {
+						vf->pts_us64 = 0;
+					}
+					if ((repeat_count > 1) && hw->avi_flag) {
+						/* vf->duration =
+						 *	 hw->vavs_amstream_dec_info.rate *
+						 *	 repeat_count;
+						 */
+						vf->duration = dur * repeat_count;
+						if (hw->next_pts != 0) {
+							hw->next_pts +=
+								((vf->duration) -
+								 ((vf->duration) >> 4));
+						}
+					} else {
+						/* vf->duration =
+						 *	 hw->vavs_amstream_dec_info.rate;
+						 */
+						vf->duration = dur;
+						hw->next_pts = 0;
+					}
+				}
+				vf->signal_type = 0;
+				vf->index = buffer_index;
+				vf->duration_pulldown = 0;
+				vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
+#ifdef NV21
+				vf->type |= VIDTYPE_VIU_NV21;
+#endif
+				if (hw->m_ins_flag) {
+					vf->canvas0Addr = vf->canvas1Addr = -1;
+					vf->plane_num = 2;
+
+					vf->canvas0_config[0] = hw->canvas_config[buffer_index][0];
+					vf->canvas0_config[1] = hw->canvas_config[buffer_index][1];
+
+					vf->canvas1_config[0] = hw->canvas_config[buffer_index][0];
+					vf->canvas1_config[1] = hw->canvas_config[buffer_index][1];
+				} else
+					vf->canvas0Addr = vf->canvas1Addr =
+						index2canvas(buffer_index);
+				vf->type_original = vf->type;
+
+				vf->pts = (pts_valid)?pts:0;
+				//vf->pts_us64 = (pts_valid) ? pts_us64 : 0;
+				debug_print(hw, PRINT_FLAG_VFRAME_DETAIL,
+					"buffer_index %d, canvas addr %x\n",
+						   buffer_index, vf->canvas0Addr);
+				debug_print(hw, PRINT_FLAG_PTS,
+					"progressive vf->pts = %d, vf->pts_us64 = %lld, pts_valid = %d\n", vf->pts, vf->pts_us64, pts_valid);
+				hw->vfbuf_use[buffer_index]++;
+				vf->mem_handle =
+					decoder_bmmu_box_get_mem_handle(
+						hw->mm_blk_handle,
+						buffer_index);
+
+				if (hw->m_ins_flag && vdec_frame_based(hw_to_vdec(hw)))
+					set_vframe_pts(hw, decode_pic_count, vf);
+
+				if (vdec_stream_based(vdec) && (!vdec->vbuf.use_ptsserv)) {
+					vf->pts_us64 =
+						(((u64)vf->duration << 32) & 0xffffffff00000000) | offset;
+					vf->pts = 0;
+				}
+				decoder_do_frame_check(hw_to_vdec(hw), vf);
+				vdec_vframe_ready(vdec, vf);
+				kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
+				ATRACE_COUNTER(hw->pts_name, vf->pts);
+				ATRACE_COUNTER(hw->new_q_name, kfifo_len(&hw->newframe_q));
+				ATRACE_COUNTER(hw->disp_q_name, kfifo_len(&hw->display_q));
+				avs_vf_notify_receiver(hw, PROVIDER_NAME,
+						VFRAME_EVENT_PROVIDER_VFRAME_READY,
+						NULL);
+				hw->total_frame++;
+			}
+
+			/*count info*/
+			vdec_count_info(hw->gvs, 0, offset);
+			if (offset) {
+				if (picture_type == I_PICTURE) {
+					hw->gvs->i_decoded_frames++;
+				} else if (picture_type == P_PICTURE) {
+					hw->gvs->p_decoded_frames++;
+				} else if (picture_type == B_PICTURE) {
+					hw->gvs->b_decoded_frames++;
+				}
+			}
+			avs_update_gvs(hw);
+			vdec_fill_vdec_frame(hw_to_vdec(hw), NULL, hw->gvs, vf, 0);
+
+			/* pr_info("PicType = %d, PTS = 0x%x\n",
+			 *	 picture_type, vf->pts);
+			 */
+			WRITE_VREG(AVS_BUFFEROUT, 0);
+		}
+		//WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+
+		if (hw->m_ins_flag) {
+			u32 status_reg = READ_VREG(DECODE_STATUS);
+			u32 decode_status = status_reg & 0xff;
+			if (hw->dec_result == DEC_RESULT_DONE ||
+				hw->dec_result == DEC_RESULT_AGAIN) {
+				debug_print(hw, PRINT_FLAG_DECODING,
+					"%s !!! READ_VREG(DECODE_STATUS) = 0x%x, decode_status 0x%x, buf_status 0x%x, dec_result = 0x%x, decode_pic_count = %d bit_cnt=0x%x\n",
+					__func__, status_reg, decode_status,
+					hw->buf_status,
+					hw->dec_result, hw->decode_pic_count,
+					READ_VREG(VIFF_BIT_CNT));
+				return IRQ_HANDLED;
+			} else if (decode_status == DECODE_STATUS_PIC_DONE ||
+				decode_status == DECODE_STATUS_SKIP_PIC_DONE) {
+				hw->buf_status = (status_reg >> 16) & 0xffff;
+				if (decode_status == DECODE_STATUS_SKIP_PIC_DONE) {
+					hw->decode_status_skip_pic_done_flag = 1;
+					hw->decode_decode_cont_start_code = (status_reg >> 8) & 0xff;
+				} else
+					hw->decode_status_skip_pic_done_flag = 0;
+				hw->decode_pic_count++;
+				if ((hw->decode_pic_count & 0xffff) == 0) {
+					/*make ucode do not handle it as first picture*/
+					hw->decode_pic_count++;
+				}
+				reset_process_time(hw);
+				hw->dec_result = DEC_RESULT_DONE;
+#if DEBUG_MULTI_FLAG == 1
+				WRITE_VREG(DECODE_STATUS, 0);
+#else
+				amvdec_stop();
+#endif
+				vavs_save_regs(hw);
+				debug_print(hw, PRINT_FLAG_DECODING,
+					"%s %s, READ_VREG(DECODE_STATUS) = 0x%x, decode_status 0x%x, buf_status 0x%x, dec_result = 0x%x, decode_pic_count = %d, bit_cnt=0x%x\n",
+					__func__,
+					(decode_status == DECODE_STATUS_PIC_DONE) ?
+					"DECODE_STATUS_PIC_DONE" : "DECODE_STATUS_SKIP_PIC_DONE",
+					status_reg, decode_status,
+					hw->buf_status,
+					hw->dec_result, hw->decode_pic_count,
+					READ_VREG(VIFF_BIT_CNT));
+				vdec_schedule_work(&hw->work);
+				return IRQ_HANDLED;
+			} else if (decode_status == DECODE_STATUS_DECODE_BUF_EMPTY ||
+				decode_status == DECODE_STATUS_SEARCH_BUF_EMPTY) {
+				hw->buf_status = (status_reg >> 16) & 0xffff;
+				reset_process_time(hw);
+#if DEBUG_MULTI_FLAG == 1
+				WRITE_VREG(DECODE_STATUS, 0);
+#else
+				amvdec_stop();
+#endif
+				if (vdec_frame_based(hw_to_vdec(hw))) {
+					hw->dec_result = DEC_RESULT_DONE;
+					//if (hw->decode_pic_count == 0) {
+						hw->decode_pic_count++;
+					//}
+					if ((hw->decode_pic_count & 0xffff) == 0) {
+					/*make ucode do not handle it as first picture*/
+						hw->decode_pic_count++;
+					}
+					vavs_save_regs(hw);
+				} else
+					hw->dec_result = DEC_RESULT_AGAIN;
+
+				debug_print(hw, PRINT_FLAG_DECODING,
+					"%s BUF_EMPTY, READ_VREG(DECODE_STATUS) = 0x%x, decode_status 0x%x, buf_status 0x%x, scratch_8 (AVS_BUFFERIN) 0x%x, dec_result = 0x%x, decode_pic_count = %d, bit_cnt=0x%x, hw->decode_status_skip_pic_done_flag = %d, hw->decode_decode_cont_start_code = 0x%x\n",
+					__func__, status_reg, decode_status,
+					hw->buf_status,
+					hw->reg_scratch_8,
+					hw->dec_result, hw->decode_pic_count,
+					READ_VREG(VIFF_BIT_CNT), hw->decode_status_skip_pic_done_flag, hw->decode_decode_cont_start_code);
+				vdec_schedule_work(&hw->work);
+				return IRQ_HANDLED;
+			}
+		}
+
+
+#ifdef HANDLE_AVS_IRQ
+		return IRQ_HANDLED;
+#else
+		return;
+#endif
+}
+
+static irqreturn_t vmavs_isr(struct vdec_s *vdec, int irq)
+{
+
+	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+	return IRQ_WAKE_THREAD;
+	//return vavs_isr(0, hw);
+
+}
+
+static void vmavs_dump_state(struct vdec_s *vdec)
+{
+	struct vdec_avs_hw_s *hw =
+	(struct vdec_avs_hw_s *)vdec->private;
+	int i;
+	debug_print(hw, 0,
+		"====== %s\n", __func__);
+
+	debug_print(hw, 0,
+		"width/height (%d/%d), dur %d\n",
+		hw->frame_width,
+		hw->frame_height,
+		hw->frame_dur
+		);
+
+	debug_print(hw, 0,
+		"is_framebase(%d), decode_status 0x%x, buf_status 0x%x, buf_recycle_status 0x%x, throw %d, eos %d, state 0x%x, dec_result 0x%x dec_frm %d disp_frm %d run %d not_run_ready %d input_empty %d\n",
+		vdec_frame_based(vdec),
+		READ_VREG(DECODE_STATUS) & 0xff,
+		hw->buf_status,
+		hw->buf_recycle_status,
+		hw->throw_pb_flag,
+		hw->eos,
+		hw->stat,
+		hw->dec_result,
+		hw->decode_pic_count,
+		hw->display_frame_count,
+		hw->run_count,
+		hw->not_run_ready,
+		hw->input_empty
+		);
+
+	if (vf_get_receiver(vdec->vf_provider_name)) {
+		enum receviver_start_e state =
+		vf_notify_receiver(vdec->vf_provider_name,
+			VFRAME_EVENT_PROVIDER_QUREY_STATE,
+			NULL);
+		debug_print(hw, 0,
+			"\nreceiver(%s) state %d\n",
+			vdec->vf_provider_name,
+			state);
+	}
+
+	debug_print(hw, 0,
+	"%s, newq(%d/%d), dispq(%d/%d)recycleq(%d/%d) drop %d vf peek %d, prepare/get/put (%d/%d/%d)\n",
+	__func__,
+	kfifo_len(&hw->newframe_q),
+	VF_POOL_SIZE,
+	kfifo_len(&hw->display_q),
+	VF_POOL_SIZE,
+	kfifo_len(&hw->recycle_q),
+	VF_POOL_SIZE,
+	hw->drop_frame_count,
+	hw->peek_num,
+	hw->prepare_num,
+	hw->get_num,
+	hw->put_num
+	);
+
+	debug_print(hw, 0, "vfbuf_use:\n");
+	for (i = 0; i < hw->vf_buf_num_used; i++)
+		debug_print(hw, 0, "%d: vf_buf_use %d\n",
+			i, hw->vfbuf_use[i]);
+
+	debug_print(hw, 0,
+		"DECODE_STATUS=0x%x\n",
+		READ_VREG(DECODE_STATUS));
+	debug_print(hw, 0,
+		"MPC_E=0x%x\n",
+		READ_VREG(MPC_E));
+	debug_print(hw, 0,
+		"DECODE_MODE=0x%x\n",
+		READ_VREG(DECODE_MODE));
+	debug_print(hw, 0,
+		"wait_buf_status, AV_SCRATCH_5=0x%x\n",
+		READ_VREG(AV_SCRATCH_5));
+	debug_print(hw, 0,
+		"MBY_MBX=0x%x\n",
+		READ_VREG(MBY_MBX));
+	debug_print(hw, 0,
+		"VIFF_BIT_CNT=0x%x\n",
+		READ_VREG(VIFF_BIT_CNT));
+	debug_print(hw, 0,
+		"VLD_MEM_VIFIFO_LEVEL=0x%x\n",
+		READ_VREG(VLD_MEM_VIFIFO_LEVEL));
+	debug_print(hw, 0,
+		"VLD_MEM_VIFIFO_WP=0x%x\n",
+		READ_VREG(VLD_MEM_VIFIFO_WP));
+	debug_print(hw, 0,
+		"VLD_MEM_VIFIFO_RP=0x%x\n",
+		READ_VREG(VLD_MEM_VIFIFO_RP));
+	debug_print(hw, 0,
+		"PARSER_VIDEO_RP=0x%x\n",
+		STBUF_READ(&vdec->vbuf, get_rp));
+	debug_print(hw, 0,
+		"PARSER_VIDEO_WP=0x%x\n",
+		STBUF_READ(&vdec->vbuf, get_wp));
+
+	if (vdec_frame_based(vdec) &&
+		(debug &	PRINT_FRAMEBASE_DATA)
+		) {
+		int jj;
+		if (hw->chunk && hw->chunk->block &&
+			hw->chunk->size > 0) {
+			u8 *data = NULL;
+
+			if (!hw->chunk->block->is_mapped)
+				data = codec_mm_vmap(hw->chunk->block->start +
+					hw->chunk->offset, hw->chunk->size);
+			else
+				data = ((u8 *)hw->chunk->block->start_virt)
+					+ hw->chunk->offset;
+
+			debug_print(hw, 0,
+				"frame data size 0x%x\n",
+				hw->chunk->size);
+			for (jj = 0; jj < hw->chunk->size; jj++) {
+				if ((jj & 0xf) == 0)
+					debug_print(hw,
+					PRINT_FRAMEBASE_DATA,
+						"%06x:", jj);
+				debug_print_cont(hw,
+				PRINT_FRAMEBASE_DATA,
+					"%02x ", data[jj]);
+				if (((jj + 1) & 0xf) == 0)
+					debug_print_cont(hw,
+					PRINT_FRAMEBASE_DATA,
+						"\n");
+			}
+
+			if (!hw->chunk->block->is_mapped)
+				codec_mm_unmap_phyaddr(data);
+		}
+	}
+
+}
+
+ int ammvdec_avs_probe(struct platform_device *pdev)
+{
+	struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
+	struct vdec_avs_hw_s *hw = NULL;
+	int r = 0;
+
+	if (vdec_get_debug_flags() & 0x8)
+		return amvdec_avs_probe(pdev);
+
+	pr_info("ammvdec_avs probe start.\n");
+
+	if (pdata == NULL) {
+		pr_info("ammvdec_avs platform data undefined.\n");
+		return -EFAULT;
+	}
+
+	hw = (struct vdec_avs_hw_s *)vzalloc(sizeof(struct vdec_avs_hw_s));
+	if (hw == NULL) {
+		pr_info("\nammvdec_avs decoder driver alloc failed\n");
+		return -ENOMEM;
+	}
+	/*atomic_set(&hw->error_handler_run, 0);*/
+	hw->m_ins_flag = 1;
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM || disable_longcabac_trans)
+		firmware_sel = 1;
+
+	if (firmware_sel == 1) {
+#ifndef USE_DYNAMIC_BUF_NUM
+		vf_buf_num = 4;
+#endif
+		canvas_base = 0;
+		canvas_num = 3;
+	} else {
+		pr_info("Error, do not support longcabac work around!!!");
+		r = -ENOMEM;
+		goto error1;
+	}
+
+	if (pdata->sys_info)
+		hw->vavs_amstream_dec_info = *pdata->sys_info;
+
+	hw->is_reset = 0;
+	pdata->user_data_read = NULL;
+	pdata->reset_userdata_fifo = NULL;
+
+	pdata->private = hw;
+	pdata->dec_status = vavs_dec_status;
+	pdata->set_isreset = vavs_set_isreset;
+	pdata->run_ready = run_ready;
+	pdata->run = run;
+	pdata->reset = reset;
+	pdata->irq_handler = vmavs_isr;
+	pdata->threaded_irq_handler = vmavs_isr_thread_fn;
+	pdata->dump_state = vmavs_dump_state;
+
+	snprintf(hw->vdec_name, sizeof(hw->vdec_name),
+		"avs-%d", pdev->id);
+	snprintf(hw->pts_name, sizeof(hw->pts_name),
+		"%s-pts", hw->vdec_name);
+	snprintf(hw->new_q_name, sizeof(hw->new_q_name),
+		"%s-newframe_q", hw->vdec_name);
+	snprintf(hw->disp_q_name, sizeof(hw->disp_q_name),
+		"%s-dispframe_q", hw->vdec_name);
+
+	vavs_vdec_info_init(hw);
+
+#ifdef ENABLE_USER_DATA
+	if (NULL == hw->user_data_buffer) {
+		hw->user_data_buffer =
+			dma_alloc_coherent(amports_get_dma_device(),
+				USER_DATA_SIZE,
+				&hw->user_data_buffer_phys, GFP_KERNEL);
+		if (!hw->user_data_buffer) {
+			pr_info("%s: Can not allocate hw->user_data_buffer\n",
+				   __func__);
+			r = -ENOMEM;
+			goto error2;
+		}
+		pr_debug("hw->user_data_buffer = 0x%p, hw->user_data_buffer_phys = 0x%x\n",
+			hw->user_data_buffer, (u32)hw->user_data_buffer_phys);
+	}
+#endif
+	/*hw->lmem_addr = kmalloc(LMEM_BUF_SIZE, GFP_KERNEL);
+	if (hw->lmem_addr == NULL) {
+		pr_err("%s: failed to alloc lmem buffer\n", __func__);
+		return -1;
+	}
+	hw->lmem_phy_addr = dma_map_single(amports_get_dma_device(),
+		hw->lmem_addr, LMEM_BUF_SIZE, DMA_FROM_DEVICE);
+	if (dma_mapping_error(amports_get_dma_device(),
+		hw->lmem_phy_addr)) {
+		pr_err("%s: failed to map lmem buffer\n", __func__);
+		kfree(hw->lmem_addr);
+		hw->lmem_addr = NULL;
+		return -1;
+	}*/
+	/*INIT_WORK(&hw->set_clk_work, avs_set_clk);*/
+	hw->lmem_addr = (dma_addr_t)dma_alloc_coherent(amports_get_dma_device(),
+	               LMEM_BUF_SIZE, (dma_addr_t *)&hw->lmem_phy_addr, GFP_KERNEL);
+	if (hw->lmem_addr == 0) {
+		pr_err("%s: failed to alloc lmem buffer\n", __func__);
+		r = -1;
+		goto error3;
+	}
+
+	if (vavs_init(hw) < 0) {
+		pr_info("amvdec_avs init failed.\n");
+		r = -ENODEV;
+		goto error4;
+	}
+
+	/*INIT_WORK(&hw->fatal_error_wd_work, vavs_fatal_error_handler);
+	atomic_set(&hw->error_handler_run, 0);*/
+#if 0
+#ifdef ENABLE_USER_DATA
+	INIT_WORK(&hw->userdata_push_work, userdata_push_do_work);
+#endif
+#endif
+	INIT_WORK(&hw->notify_work, vavs_notify_work);
+
+	if (pdata->use_vfm_path) {
+		snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
+			    VFM_DEC_PROVIDER_NAME);
+		hw->frameinfo_enable = 1;
+	}
+	else
+		snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
+			MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff);
+	if (pdata->parallel_dec == 1) {
+		int i;
+		for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++)
+			hw->canvas_spec[i] = 0xffffff;
+	}
+	vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
+		&vavs_vf_provider, hw);
+
+	platform_set_drvdata(pdev, pdata);
+
+	hw->platform_dev = pdev;
+
+	vdec_set_prepare_level(pdata, start_decode_buf_level);
+
+	vdec_set_vframe_comm(pdata, DRIVER_NAME);
+
+	if (pdata->parallel_dec == 1)
+		vdec_core_request(pdata, CORE_MASK_VDEC_1);
+	else {
+		vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+					| CORE_MASK_COMBINE);
+	}
+
+	/*INIT_WORK(&hw->userdata_push_work, userdata_push_do_work);*/
+
+	return 0;
+
+error4:
+	dma_free_coherent(amports_get_dma_device(),
+		LMEM_BUF_SIZE, (void *)hw->lmem_addr,
+		hw->lmem_phy_addr);
+error3:
+	dma_free_coherent(
+		amports_get_dma_device(),
+		USER_DATA_SIZE,
+		hw->user_data_buffer,
+		hw->user_data_buffer_phys);
+error2:
+	kfree(hw->gvs);
+	hw->gvs = NULL;
+	pdata->dec_status = NULL;
+error1:
+	vfree(hw);
+	return r;
+}
+
+ int ammvdec_avs_remove(struct platform_device *pdev)
+{
+
+	if (vdec_get_debug_flags() & 0x8)
+		return amvdec_avs_remove(pdev);
+	else {
+		struct vdec_avs_hw_s *hw =
+			(struct vdec_avs_hw_s *)
+			(((struct vdec_s *)(platform_get_drvdata(pdev)))->private);
+		struct vdec_s *vdec = hw_to_vdec(hw);
+		int i;
+
+		if (hw->stat & STAT_VDEC_RUN) {
+			amvdec_stop();
+			hw->stat &= ~STAT_VDEC_RUN;
+		}
+
+		if (hw->stat & STAT_ISR_REG) {
+			vdec_free_irq(VDEC_IRQ_1, (void *)hw);
+			hw->stat &= ~STAT_ISR_REG;
+		}
+
+		if (hw->stat & STAT_TIMER_ARM) {
+			del_timer_sync(&hw->check_timer);
+			hw->stat &= ~STAT_TIMER_ARM;
+		}
+
+		cancel_work_sync(&hw->work);
+		cancel_work_sync(&hw->notify_work);
+
+		if (hw->mm_blk_handle) {
+			decoder_bmmu_box_free(hw->mm_blk_handle);
+			hw->mm_blk_handle = NULL;
+		}
+		if (vdec->parallel_dec == 1)
+			vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1);
+		else
+			vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
+		vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED);
+
+		if (vdec->parallel_dec == 1) {
+			for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+				vdec->free_canvas_ex(canvas_y(hw->canvas_spec[i]), vdec->id);
+				vdec->free_canvas_ex(canvas_u(hw->canvas_spec[i]), vdec->id);
+			}
+		}
+	#ifdef ENABLE_USER_DATA
+		if (hw->user_data_buffer != NULL) {
+			dma_free_coherent(
+				amports_get_dma_device(),
+				USER_DATA_SIZE,
+				hw->user_data_buffer,
+				hw->user_data_buffer_phys);
+			hw->user_data_buffer = NULL;
+			hw->user_data_buffer_phys = 0;
+		}
+	#endif
+		/*if (hw->lmem_addr) {
+			dma_unmap_single(amports_get_dma_device(),
+				hw->lmem_phy_addr, LMEM_BUF_SIZE, DMA_FROM_DEVICE);
+			kfree(hw->lmem_addr);
+			hw->lmem_addr = NULL;
+		}*/
+	if (hw->lmem_addr) {
+		dma_free_coherent(amports_get_dma_device(),
+					LMEM_BUF_SIZE, (void *)hw->lmem_addr,
+					hw->lmem_phy_addr);
+		hw->lmem_addr = 0;
+	}
+
+		if (hw->fw) {
+			vfree(hw->fw);
+			hw->fw = NULL;
+		}
+
+		pr_info("ammvdec_avs removed.\n");
+		if (hw->gvs) {
+			kfree(hw->gvs);
+			hw->gvs = NULL;
+		}
+
+		vfree(hw);
+		return 0;
+	}
+}
+
+
+#ifdef DEBUG_MULTI_WITH_AUTOMODE
+struct stream_buf_s *get_vbuf(void);
+s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec);
+
+
+static s32 vavs_init2(struct vdec_avs_hw_s *hw)
+{
+	int  size = -1;
+	struct firmware_s *fw;
+	u32 fw_size = 0x1000 * 16;
+
+	fw = vmalloc(sizeof(struct firmware_s) + fw_size);
+	if (IS_ERR_OR_NULL(fw))
+		return -ENOMEM;
+
+	pr_info("vavs_init\n");
+
+	amvdec_enable();
+
+
+	vavs_local_init(hw);
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM)
+		size = get_firmware_data(VIDEO_DEC_AVS_MULTI, fw->data);
+	else {
+		if (firmware_sel == 1)
+			size = get_firmware_data(VIDEO_DEC_AVS_NOCABAC, fw->data);
+#ifdef AVSP_LONG_CABAC
+		else {
+			init_avsp_long_cabac_buf();
+			size = get_firmware_data(VIDEO_DEC_AVS_MULTI, fw->data);
+		}
+#endif
+	}
+
+	if (size < 0) {
+		amvdec_disable();
+		pr_err("get firmware fail.");
+		/*vfree(buf);*/
+		return -1;
+	}
+
+	fw->len = size;
+	hw->fw = fw;
+	if (hw->m_ins_flag) {
+		init_timer(&hw->check_timer);
+		hw->check_timer.data = (ulong) hw;
+		hw->check_timer.function = check_timer_func;
+		hw->check_timer.expires = jiffies + CHECK_INTERVAL;
+
+
+		//add_timer(&hw->check_timer);
+		hw->stat |= STAT_TIMER_ARM;
+
+		INIT_WORK(&hw->work, vavs_work);
+
+		hw->fw = fw;
+	}
+	return 0;
+}
+
+unsigned int debug_flag2;
+static int vavs_prot_init2(struct vdec_avs_hw_s *hw, unsigned char post_flag)
+{
+	int r = 0;
+	/*
+	 * 2: assist
+	 * 3: vld_reset
+	 * 4: vld_part_reset
+	 * 5: vfifo reset
+	 * 6: iqidct
+	 * 7: mc
+	 * 8: dblk
+	 * 9: pic_dc
+	 * 10: psc
+	 * 11: mcpu
+	 * 12: ccpu
+	 * 13: ddr
+	 * 14: afifo
+	 */
+	unsigned char run_flag;
+#ifdef OOO
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) /*| (1 << 4)*/);
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	READ_VREG(DOS_SW_RESET0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) /*| (1 << 4)*/);
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+#endif
+	/***************** reset vld   **********************************/
+#ifdef OOO
+	WRITE_VREG(POWER_CTL_VLD, 0x10);
+	WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL, 2, MEM_FIFO_CNT_BIT, 2);
+	WRITE_VREG_BITS(VLD_MEM_VIFIFO_CONTROL,	8, MEM_LEVEL_CNT_BIT, 6);
+#endif
+   if (start_decoding_delay & 0x80000)
+		msleep(start_decoding_delay&0xffff);
+
+if (debug_flag2 & 0x1)
+	run_flag = post_flag;
+else
+	run_flag = !post_flag;
+if (run_flag) {
+	if (hw->m_ins_flag) {
+		int i;
+		if (hw->decode_pic_count == 0) {
+			r = vavs_canvas_init(hw);
+#ifndef USE_DYNAMIC_BUF_NUM
+			for (i = 0; i < 4; i++) {
+				WRITE_VREG(AV_SCRATCH_0 + i,
+					hw->canvas_spec[i]
+				);
+			}
+#else
+		for (i = 0; i < hw->vf_buf_num_used; i += 2) {
+			WRITE_VREG(buf_spec_reg[i >> 1],
+				(hw->canvas_spec[i] & 0xffff) |
+				((hw->canvas_spec[i + 1] & 0xffff)
+					<< 16)
+			);
+		}
+#endif
+		} else
+			vavs_restore_regs(hw);
+
+		for (i = 0; i < hw->vf_buf_num_used; i++) {
+			config_cav_lut_ex(canvas_y(hw->canvas_spec[i]),
+				hw->canvas_config[i][0].phy_addr,
+				hw->canvas_config[i][0].width,
+				hw->canvas_config[i][0].height,
+				CANVAS_ADDR_NOWRAP,
+				hw->canvas_config[i][0].block_mode,
+				0, VDEC_1);
+
+			config_cav_lut_ex(canvas_u(hw->canvas_spec[i]),
+				hw->canvas_config[i][1].phy_addr,
+				hw->canvas_config[i][1].width,
+				hw->canvas_config[i][1].height,
+				CANVAS_ADDR_NOWRAP,
+				hw->canvas_config[i][1].block_mode,
+				0, VDEC_1);
+		}
+	}
+}
+
+if (debug_flag2 & 0x2)
+	run_flag = post_flag;
+else
+	run_flag = !post_flag;
+if (run_flag) {
+
+	/* notify ucode the buffer offset */
+	if (hw->decode_pic_count == 0)
+		WRITE_VREG(AV_SCRATCH_F, hw->buf_offset);
+#ifdef OOO
+	/* disable PSCALE for hardware sharing */
+	WRITE_VREG(PSCALE_CTRL, 0);
+#endif
+	}
+	if (start_decoding_delay & 0x40000)
+		msleep(start_decoding_delay&0xffff);
+
+	if (debug_flag2 & 0x4)
+		run_flag = post_flag;
+	else
+		run_flag = !post_flag;
+	if (run_flag) {
+	if (hw->decode_pic_count == 0) {
+#ifndef USE_DYNAMIC_BUF_NUM
+		WRITE_VREG(AVS_SOS_COUNT, 0);
+#endif
+		WRITE_VREG(AVS_BUFFERIN, 0);
+		WRITE_VREG(AVS_BUFFEROUT, 0);
+	}
+	if (error_recovery_mode)
+		WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 0);
+	else
+		WRITE_VREG(AVS_ERROR_RECOVERY_MODE, 1);
+	/* clear mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+	/* enable mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_MASK, 1);
+}
+
+if (debug_flag2 & 0x8)
+	run_flag = post_flag;
+else
+	run_flag = !post_flag;
+if (run_flag) {
+
+#ifndef USE_DYNAMIC_BUF_NUM				/* def DEBUG_UCODE */
+	if (hw->decode_pic_count == 0)
+		WRITE_VREG(AV_SCRATCH_D, 0);
+#endif
+	if (start_decoding_delay & 0x10000)
+		msleep(start_decoding_delay&0xffff);
+#ifdef NV21
+	SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17);
+#endif
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
+
+	if (start_decoding_delay & 0x20000)
+		msleep(start_decoding_delay&0xffff);
+
+
+#ifdef PIC_DC_NEED_CLEAR
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31);
+#endif
+}
+if (debug_flag2 & 0x10)
+	run_flag = post_flag;
+else
+	run_flag = !post_flag;
+if (run_flag) {
+#ifdef ENABLE_USER_DATA
+	if (firmware_sel == 0) {
+		pr_info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! firmware_sel is 0\n");
+		WRITE_VREG(AV_SCRATCH_N, (u32)(hw->user_data_buffer_phys - hw->buf_offset));
+		pr_debug("AV_SCRATCH_N = 0x%x\n", READ_VREG(AV_SCRATCH_N));
+	}
+#endif
+}
+
+if (debug_flag2 & 0x20)
+	run_flag = post_flag;
+else
+	run_flag = !post_flag;
+if (run_flag) {
+	if (hw->m_ins_flag) {
+		if (vdec_frame_based(hw_to_vdec(hw)))
+			WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_FRAMEBASE);
+		else
+			WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_STREAMBASE);
+		WRITE_VREG(DECODE_LMEM_BUF_ADR, (u32)hw->lmem_phy_addr);
+	} else
+		WRITE_VREG(DECODE_MODE, DECODE_MODE_SINGLE);
+	WRITE_VREG(DECODE_STOP_POS, udebug_flag);
+	hw->old_udebug_flag = udebug_flag;
+}
+	return r;
+}
+
+static void init_hw(struct vdec_s *vdec)
+{
+	struct vdec_avs_hw_s *hw =
+	(struct vdec_avs_hw_s *)vdec->private;
+	int ret;
+	pr_info("%s, %d\n", __func__, __LINE__);
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM)
+		ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, hw->fw->data);
+	else if (firmware_sel == 1)
+		ret = amvdec_loadmc_ex(VFORMAT_AVS, "avs_no_cabac", hw->fw->data);
+	else
+		ret = amvdec_loadmc_ex(VFORMAT_AVS, NULL, hw->fw->data);
+
+	if (ret < 0) {
+		amvdec_disable();
+		/*vfree(buf);*/
+		pr_err("AVS: the %s fw loading failed, err: %x\n",
+			tee_enabled() ? "TEE" : "local", ret);
+	}
+	pr_info("%s, %d\n", __func__, __LINE__);
+
+	/*vfree(buf);*/
+
+	hw->stat |= STAT_MC_LOAD;
+
+	/* enable AMRISC side protocol */
+	ret = vavs_prot_init2(hw, 0);
+	if (ret < 0)
+		return;
+	pr_info("%s, %d\n", __func__, __LINE__);
+
+}
+
+
+static unsigned long run_ready2(struct vdec_s *vdec, unsigned long mask)
+{
+	return 1;
+}
+
+static void run2(struct vdec_s *vdec, unsigned long mask,
+void (*callback)(struct vdec_s *, void *),
+		void *arg)
+{
+	struct vdec_avs_hw_s *hw =
+	(struct vdec_avs_hw_s *)vdec->private;
+	pr_info("%s, %d\n", __func__, __LINE__);
+
+	vavs_prot_init2(hw, 1);
+
+	vdec_source_changed(VFORMAT_AVS,
+					1920, 1080, 30);
+
+	amvdec_start();
+
+	hw->stat |= STAT_VDEC_RUN;
+	pr_info("%s %d\n", __func__, __LINE__);
+
+}
+
+static int ammvdec_avs_probe2(struct platform_device *pdev)
+{
+	struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
+	struct vdec_avs_hw_s *hw = NULL;
+
+	pr_info("ammvdec_avs probe start.\n");
+
+	if (pdata == NULL) {
+		pr_info("ammvdec_avs platform data undefined.\n");
+		return -EFAULT;
+	}
+	pr_info("%s %d\n", __func__, __LINE__);
+
+	hw = (struct vdec_avs_hw_s *)vzalloc(sizeof(struct vdec_avs_hw_s));
+	if (hw == NULL) {
+		pr_info("\nammvdec_avs decoder driver alloc failed\n");
+		return -ENOMEM;
+	}
+	pr_info("%s %d\n", __func__, __LINE__);
+	/*atomic_set(&hw->error_handler_run, 0);*/
+	hw->m_ins_flag = 1;
+	pr_info("%s %d\n", __func__, __LINE__);
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM || disable_longcabac_trans)
+		firmware_sel = 1;
+	pr_info("%s %d\n", __func__, __LINE__);
+
+	if (firmware_sel == 1) {
+#ifndef USE_DYNAMIC_BUF_NUM
+		vf_buf_num = 4;
+#endif
+		canvas_base = 0;
+		canvas_num = 3;
+	} else {
+		pr_info("Error, do not support longcabac work around!!!");
+		return -ENOMEM;
+	}
+	pr_info("%s %d\n", __func__, __LINE__);
+
+	if (pdata->sys_info)
+		hw->vavs_amstream_dec_info = *pdata->sys_info;
+	pr_info("%s %d\n", __func__, __LINE__);
+
+	hw->is_reset = 0;
+	pdata->user_data_read = NULL;
+	pdata->reset_userdata_fifo = NULL;
+
+	pr_info("%s %d\n", __func__, __LINE__);
+
+	pdata->private = hw;
+	pdata->dec_status = vavs_dec_status;
+	pdata->set_isreset = vavs_set_isreset;
+	pdata->run_ready = run_ready2;
+	pdata->run = run2;
+	pdata->reset = reset;
+	pdata->irq_handler = vmavs_isr;
+	pdata->threaded_irq_handler = vmavs_isr_thread_fn;
+	pdata->dump_state = vmavs_dump_state;
+
+	pr_info("%s %d\n", __func__, __LINE__);
+
+	vavs_vdec_info_init(hw);
+
+	pr_info("%s %d\n", __func__, __LINE__);
+
+#ifdef ENABLE_USER_DATA
+	if (NULL == hw->user_data_buffer) {
+		hw->user_data_buffer =
+			dma_alloc_coherent(amports_get_dma_device(),
+				USER_DATA_SIZE,
+				&hw->user_data_buffer_phys, GFP_KERNEL);
+		if (!hw->user_data_buffer) {
+			pr_info("%s: Can not allocate hw->user_data_buffer\n",
+				   __func__);
+			return -ENOMEM;
+		}
+		pr_debug("hw->user_data_buffer = 0x%p, hw->user_data_buffer_phys = 0x%x\n",
+			hw->user_data_buffer, (u32)hw->user_data_buffer_phys);
+	}
+#endif
+	hw->lmem_addr = kmalloc(LMEM_BUF_SIZE, GFP_KERNEL);
+	if (hw->lmem_addr == NULL) {
+		pr_err("%s: failed to alloc lmem buffer\n", __func__);
+		return -1;
+	}
+	hw->lmem_phy_addr = dma_map_single(amports_get_dma_device(),
+		hw->lmem_addr, LMEM_BUF_SIZE, DMA_FROM_DEVICE);
+	if (dma_mapping_error(amports_get_dma_device(),
+		hw->lmem_phy_addr)) {
+		pr_err("%s: failed to map lmem buffer\n", __func__);
+		kfree(hw->lmem_addr);
+		hw->lmem_addr = NULL;
+		return -1;
+	}
+
+	pr_info("%s %d\n", __func__, __LINE__);
+
+	/*INIT_WORK(&hw->set_clk_work, avs_set_clk);*/
+
+	pr_info("%s %d\n", __func__, __LINE__);
+
+	if (vavs_init2(hw) < 0) {
+		pr_info("amvdec_avs init failed.\n");
+		kfree(hw->gvs);
+		hw->gvs = NULL;
+		pdata->dec_status = NULL;
+		return -ENODEV;
+	}
+	/*vdec = pdata;*/
+	pr_info("%s, %d\n", __func__, __LINE__);
+
+if (hw->m_ins_flag) {
+	INIT_WORK(&hw->notify_work, vavs_notify_work);
+#if 1
+	if (pdata->use_vfm_path) {
+		snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
+			    VFM_DEC_PROVIDER_NAME);
+		hw->frameinfo_enable = 1;
+	}
+	else
+		snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
+			MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff);
+	if (pdata->parallel_dec == 1) {
+		int i;
+		for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++)
+			hw->canvas_spec[i] = 0xffffff;
+	}
+	vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
+		&vavs_vf_provider, hw);
+
+	platform_set_drvdata(pdev, pdata);
+
+	hw->platform_dev = pdev;
+
+	vdec_set_prepare_level(pdata, start_decode_buf_level);
+
+	if (pdata->parallel_dec == 1)
+		vdec_core_request(pdata, CORE_MASK_VDEC_1);
+	else {
+		vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+					| CORE_MASK_COMBINE);
+	}
+	pr_info("%s, %d\n", __func__, __LINE__);
+#endif
+}else{
+	/*INIT_WORK(&hw->fatal_error_wd_work, vavs_fatal_error_handler);
+	atomic_set(&hw->error_handler_run, 0);*/
+#ifdef ENABLE_USER_DATA
+	INIT_WORK(&hw->userdata_push_work, userdata_push_do_work);
+#endif
+	INIT_WORK(&hw->notify_work, vavs_notify_work);
+}
+
+	init_hw(pdata);
+	return 0;
+}
+
+static int ammvdec_avs_remove2(struct platform_device *pdev)
+{
+	struct vdec_avs_hw_s *hw = ghw;
+
+	cancel_work_sync(&hw->fatal_error_wd_work);
+	atomic_set(&hw->error_handler_run, 0);
+#ifdef ENABLE_USER_DATA
+	cancel_work_sync(&hw->userdata_push_work);
+#endif
+	cancel_work_sync(&hw->notify_work);
+	cancel_work_sync(&hw->set_clk_work);
+	if (hw->stat & STAT_VDEC_RUN) {
+		amvdec_stop();
+		hw->stat &= ~STAT_VDEC_RUN;
+	}
+
+	if (hw->stat & STAT_ISR_REG) {
+		vdec_free_irq(VDEC_IRQ_1, (void *)vavs_dec_id);
+		hw->stat &= ~STAT_ISR_REG;
+	}
+
+	if (hw->stat & STAT_TIMER_ARM) {
+		del_timer_sync(&hw->recycle_timer);
+		hw->stat &= ~STAT_TIMER_ARM;
+	}
+#ifdef AVSP_LONG_CABAC
+	if (firmware_sel == 0) {
+		mutex_lock(&vavs_mutex);
+		cancel_work_sync(&long_cabac_wd_work);
+		mutex_unlock(&vavs_mutex);
+
+		if (es_write_addr_virt) {
+#if 0
+			codec_mm_free_for_dma("vavs", es_write_addr_phy);
+#else
+			dma_unmap_single(amports_get_dma_device(),
+				es_write_addr_phy,
+				MAX_CODED_FRAME_SIZE, DMA_FROM_DEVICE);
+			/*kfree(es_write_addr_virt);*/
+			es_write_addr_virt = NULL;
+#endif
+		}
+
+#ifdef BITSTREAM_READ_TMP_NO_CACHE
+		if (bitstream_read_tmp) {
+			dma_free_coherent(amports_get_dma_device(),
+				SVA_STREAM_BUF_SIZE, bitstream_read_tmp,
+				bitstream_read_tmp_phy);
+			bitstream_read_tmp = NULL;
+		}
+#else
+		if (bitstream_read_tmp) {
+			dma_unmap_single(amports_get_dma_device(),
+				bitstream_read_tmp_phy,
+				SVA_STREAM_BUF_SIZE, DMA_FROM_DEVICE);
+			kfree(bitstream_read_tmp);
+			bitstream_read_tmp = NULL;
+		}
+#endif
+	}
+#endif
+	if (hw->stat & STAT_VF_HOOK) {
+		if (hw->fr_hint_status == VDEC_HINTED && !hw->is_reset)
+			avs_vf_notify_receiver(hw, PROVIDER_NAME,
+				VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL);
+		hw->fr_hint_status = VDEC_NO_NEED_HINT;
+		vf_unreg_provider(&vavs_vf_prov);
+		hw->stat &= ~STAT_VF_HOOK;
+	}
+
+#ifdef ENABLE_USER_DATA
+	if (hw->user_data_buffer != NULL) {
+		dma_free_coherent(
+			amports_get_dma_device(),
+			USER_DATA_SIZE,
+			hw->user_data_buffer,
+			hw->user_data_buffer_phys);
+		hw->user_data_buffer = NULL;
+		hw->user_data_buffer_phys = 0;
+	}
+#endif
+
+	if (hw->fw) {
+		vfree(hw->fw);
+		hw->fw = NULL;
+	}
+
+	amvdec_disable();
+	/*vdec_disable_DMC(NULL);*/
+
+	hw->pic_type = 0;
+	if (hw->mm_blk_handle) {
+		decoder_bmmu_box_free(hw->mm_blk_handle);
+		hw->mm_blk_handle = NULL;
+	}
+#ifdef DEBUG_PTS
+	pr_debug("pts hit %d, pts missed %d, i hit %d, missed %d\n", hw->pts_hit,
+		   hw->pts_missed, hw->pts_i_hit, hw->pts_i_missed);
+	pr_debug("total frame %d, hw->avi_flag %d, rate %d\n", hw->total_frame, hw->avi_flag,
+		   hw->vavs_amstream_dec_info.rate);
+#endif
+	kfree(hw->gvs);
+	hw->gvs = NULL;
+	vfree(hw);
+	return 0;
+}
+#endif
+
+static struct platform_driver ammvdec_avs_driver = {
+#ifdef DEBUG_MULTI_WITH_AUTOMODE
+	.probe = ammvdec_avs_probe2,
+	.remove = ammvdec_avs_remove2,
+#else
+	.probe = ammvdec_avs_probe,
+	.remove = ammvdec_avs_remove,
+#endif
+#ifdef CONFIG_PM
+	.suspend = amvdec_suspend,
+	.resume = amvdec_resume,
+#endif
+	.driver = {
+		.name = MULTI_DRIVER_NAME,
+	}
+};
+
+static struct codec_profile_t ammvdec_avs_profile = {
+	.name = "mavs",
+	.profile = ""
+};
+
+static struct mconfig mavs_configs[] = {
+	/*MC_PU32("stat", &stat),
+	MC_PU32("debug_flag", &debug_flag),
+	MC_PU32("error_recovery_mode", &error_recovery_mode),
+	MC_PU32("hw->pic_type", &hw->pic_type),
+	MC_PU32("radr", &radr),
+	MC_PU32("vf_buf_num", &vf_buf_num),
+	MC_PU32("vf_buf_num_used", &vf_buf_num_used),
+	MC_PU32("canvas_base", &canvas_base),
+	MC_PU32("firmware_sel", &firmware_sel),
+	*/
+};
+static struct mconfig_node mavs_node;
+
+
+static int __init ammvdec_avs_driver_init_module(void)
+{
+	pr_debug("ammvdec_avs module init\n");
+
+	if (platform_driver_register(&ammvdec_avs_driver))
+		pr_err("failed to register ammvdec_avs driver\n");
+#ifdef DEBUG_WITH_SINGLE_MODE
+	if (platform_driver_register(&amvdec_avs_driver)) {
+		pr_info("failed to register amvdec_avs driver\n");
+		return -ENODEV;
+	}
+#else
+	//amvdec_avs_driver = amvdec_avs_driver;
+#endif
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB)
+		ammvdec_avs_profile.profile = "mavs+";
+
+	vcodec_profile_register(&ammvdec_avs_profile);
+	INIT_REG_NODE_CONFIGS("media.decoder", &mavs_node,
+		"mavs", mavs_configs, CONFIG_FOR_RW);
+	vcodec_feature_register(VFORMAT_AVS, 0);
+	return 0;
+}
+
+
+
+static void __exit ammvdec_avs_driver_remove_module(void)
+{
+	pr_debug("ammvdec_avs module remove.\n");
+
+	platform_driver_unregister(&ammvdec_avs_driver);
+#ifdef DEBUG_WITH_SINGLE_MODE
+	platform_driver_unregister(&amvdec_avs_driver);
+#endif
+}
+
+/****************************************/
+/*
+module_param(stat, uint, 0664);
+MODULE_PARM_DESC(stat, "\n amvdec_avs stat\n");
+*/
+/******************************************
+ *module_param(run_flag, uint, 0664);
+ *MODULE_PARM_DESC(run_flag, "\n run_flag\n");
+ *
+ *module_param(step_flag, uint, 0664);
+ *MODULE_PARM_DESC(step_flag, "\n step_flag\n");
+ *******************************************
+ */
+module_param(step, uint, 0664);
+MODULE_PARM_DESC(step, "\n step\n");
+
+module_param(debug, uint, 0664);
+MODULE_PARM_DESC(debug, "\n debug\n");
+
+module_param(debug_mask, uint, 0664);
+MODULE_PARM_DESC(debug_mask, "\n debug_mask\n");
+
+module_param(error_recovery_mode, uint, 0664);
+MODULE_PARM_DESC(error_recovery_mode, "\n error_recovery_mode\n");
+
+/******************************************
+ *module_param(error_watchdog_threshold, uint, 0664);
+ *MODULE_PARM_DESC(error_watchdog_threshold, "\n error_watchdog_threshold\n");
+ *
+ *module_param(error_watchdog_buf_threshold, uint, 0664);
+ *MODULE_PARM_DESC(error_watchdog_buf_threshold,
+ *			"\n error_watchdog_buf_threshold\n");
+ *******************************************
+ */
+/*
+module_param(pic_type, uint, 0444);
+MODULE_PARM_DESC(pic_type, "\n amdec_vas picture type\n");
+*/
+module_param(radr, uint, 0664);
+MODULE_PARM_DESC(radr, "\nradr\n");
+
+module_param(rval, uint, 0664);
+MODULE_PARM_DESC(rval, "\nrval\n");
+
+module_param(dbg_cmd, uint, 0664);
+MODULE_PARM_DESC(dbg_cmd, "\n dbg_cmd\n");
+
+module_param(vf_buf_num, uint, 0664);
+MODULE_PARM_DESC(vf_buf_num, "\nvf_buf_num\n");
+
+/*
+module_param(vf_buf_num_used, uint, 0664);
+MODULE_PARM_DESC(vf_buf_num_used, "\nvf_buf_num_used\n");
+*/
+module_param(canvas_base, uint, 0664);
+MODULE_PARM_DESC(canvas_base, "\ncanvas_base\n");
+
+
+module_param(firmware_sel, uint, 0664);
+MODULE_PARM_DESC(firmware_sel, "\n firmware_sel\n");
+
+module_param(disable_longcabac_trans, uint, 0664);
+MODULE_PARM_DESC(disable_longcabac_trans, "\n disable_longcabac_trans\n");
+
+module_param(dec_control, uint, 0664);
+MODULE_PARM_DESC(dec_control, "\n amvdec_vavs decoder control\n");
+
+module_param(start_decode_buf_level, int, 0664);
+MODULE_PARM_DESC(start_decode_buf_level,
+		"\n avs start_decode_buf_level\n");
+
+module_param(decode_timeout_val, uint, 0664);
+MODULE_PARM_DESC(decode_timeout_val,
+	"\n avs decode_timeout_val\n");
+
+module_param(error_handle_policy, uint, 0664);
+MODULE_PARM_DESC(error_handle_policy,
+	"\n avs error_handle_policy\n");
+
+module_param(again_threshold, uint, 0664);
+MODULE_PARM_DESC(again_threshold, "\n again_threshold\n");
+
+module_param(udebug_flag, uint, 0664);
+MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n");
+
+module_param(udebug_pause_pos, uint, 0664);
+MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n");
+
+module_param(udebug_pause_val, uint, 0664);
+MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n");
+
+module_param(udebug_pause_decode_idx, uint, 0664);
+MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n");
+
+module_param(udebug_pause_ins_id, uint, 0664);
+MODULE_PARM_DESC(udebug_pause_ins_id, "\n udebug_pause_ins_id\n");
+
+module_param(start_decoding_delay, uint, 0664);
+MODULE_PARM_DESC(start_decoding_delay, "\n start_decoding_delay\n");
+
+module_param(pre_decode_buf_level, int, 0664);
+MODULE_PARM_DESC(pre_decode_buf_level,
+				"\n ammvdec_mavs pre_decode_buf_level\n");
+
+
+#ifdef DEBUG_MULTI_WITH_AUTOMODE
+module_param(debug_flag2, uint, 0664);
+MODULE_PARM_DESC(debug_flag2, "\n debug_flag2\n");
+#endif
+module_param(force_fps, uint, 0664);
+MODULE_PARM_DESC(force_fps, "\n force_fps\n");
+
+#ifdef DEBUG_MULTI_FRAME_INS
+module_param(delay, uint, 0664);
+MODULE_PARM_DESC(delay, "\n delay\n");
+
+module_param_array(max_run_count, uint, &max_decode_instance_num, 0664);
+
+#endif
+
+module_param_array(ins_udebug_flag, uint, &max_decode_instance_num, 0664);
+
+module_param_array(max_process_time, uint, &max_decode_instance_num, 0664);
+
+module_param_array(run_count, uint, &max_decode_instance_num, 0664);
+
+module_param_array(max_get_frame_interval, uint,
+	&max_decode_instance_num, 0664);
+
+
+module_init(ammvdec_avs_driver_init_module);
+module_exit(ammvdec_avs_driver_remove_module);
+
+MODULE_DESCRIPTION("AMLOGIC AVS Video Decoder Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Qi Wang <qi.wang@amlogic.com>");
diff --git a/drivers/frame_provider/decoder/avs_multi/avs_multi.h b/drivers/frame_provider/decoder/avs_multi/avs_multi.h
new file mode 100644
index 0000000..8922b40
--- /dev/null
+++ b/drivers/frame_provider/decoder/avs_multi/avs_multi.h
@@ -0,0 +1,90 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#ifndef AVS_H_
+#define AVS_H_
+
+#ifdef CONFIG_AMLOGIC_AVSP_LONG_CABAC
+#define AVSP_LONG_CABAC
+#endif
+/*#define BITSTREAM_READ_TMP_NO_CACHE*/
+
+#ifdef AVSP_LONG_CABAC
+#define MAX_CODED_FRAME_SIZE 1500000         /*!< bytes for one frame*/
+#define LOCAL_HEAP_SIZE    (1024*1024*10)
+/*
+ *#define MAX_CODED_FRAME_SIZE  240000
+ *#define MAX_CODED_FRAME_SIZE  700000
+ */
+#define SVA_STREAM_BUF_SIZE 1024
+
+extern void *es_write_addr_virt;
+extern dma_addr_t es_write_addr_phy;
+
+extern void *bitstream_read_tmp;
+extern dma_addr_t bitstream_read_tmp_phy;
+extern void *avsp_heap_adr;
+
+int avs_get_debug_flag(void);
+
+int process_long_cabac(void);
+
+/* bit [6] - skip_mode_flag
+ * bit [5:4] - picture_type
+ * bit [3] - picture_structure (0-Field, 1-Frame)
+ * bit [2] - fixed_picture_qp
+ * bit [1] - progressive_sequence
+ * bit [0] - active
+ */
+#define LONG_CABAC_REQ        AV_SCRATCH_K
+#define LONG_CABAC_SRC_ADDR   AV_SCRATCH_H
+#define LONG_CABAC_DES_ADDR   AV_SCRATCH_I
+/* bit[31:16] - vertical_size
+ * bit[15:0] - horizontal_size
+ */
+#define LONG_CABAC_PIC_SIZE   AV_SCRATCH_J
+
+#endif
+
+/*
+ *#define PERFORMANCE_DEBUG
+ *#define DUMP_DEBUG
+ */
+#define AVS_DEBUG_PRINT         0x01
+#define AVS_DEBUG_OLD_ERROR_HANDLE	0x10
+#define AVS_DEBUG_USE_FULL_SPEED 0x80
+#define AEC_DUMP				0x100
+#define STREAM_INFO_DUMP		0x200
+#define SLICE_INFO_DUMP			0x400
+#define MB_INFO_DUMP			0x800
+#define MB_NUM_DUMP				0x1000
+#define BLOCK_NUM_DUMP			0x2000
+#define COEFF_DUMP				0x4000
+#define ES_DUMP					0x8000
+#define DQUANT_DUMP				0x10000
+#define STREAM_INFO_DUMP_MORE   0x20000
+#define STREAM_INFO_DUMP_MORE2  0x40000
+
+extern void *es_write_addr_virt;
+extern void *bitstream_read_tmp;
+extern dma_addr_t bitstream_read_tmp_phy;
+int read_bitstream(unsigned char *Buf, int size);
+int u_v(int LenInBits, char *tracestring);
+
+#endif
diff --git a/drivers/frame_provider/decoder/h264/Makefile b/drivers/frame_provider/decoder/h264/Makefile
new file mode 100644
index 0000000..b7c85ee
--- /dev/null
+++ b/drivers/frame_provider/decoder/h264/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H264) += amvdec_h264.o
+amvdec_h264-objs += vh264.o
+
+obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H264_MVC) += amvdec_h264mvc.o
+amvdec_h264mvc-objs += vh264_mvc.o
+
diff --git a/drivers/frame_provider/decoder/h264/vh264.c b/drivers/frame_provider/decoder/h264/vh264.c
new file mode 100644
index 0000000..55f0581
--- /dev/null
+++ b/drivers/frame_provider/decoder/h264/vh264.c
@@ -0,0 +1,4509 @@
+/*
+ * drivers/amlogic/media/frame_provider/decoder/h264/vh264.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#define DEBUG
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/kfifo.h>
+#include <linux/platform_device.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/media/frame_sync/tsync.h>
+#include <linux/workqueue.h>
+#include <linux/dma-mapping.h>
+#include <linux/atomic.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include "../../../stream_input/amports/amports_priv.h"
+#include <linux/amlogic/media/canvas/canvas.h>
+#include "../utils/vdec.h"
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../utils/amvdec.h"
+#include "vh264.h"
+#include "../../../stream_input/amports/streambuf.h"
+#include <linux/delay.h>
+#include <linux/amlogic/media/video_sink/video.h>
+//#include <linux/amlogic/tee.h>
+#include <uapi/linux/tee.h>
+#include <linux/amlogic/media/ge2d/ge2d.h>
+#include "../utils/decoder_mmu_box.h"
+#include "../utils/decoder_bmmu_box.h"
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/amlogic/media/codec_mm/configs.h>
+#include "../utils/firmware.h"
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+#include <linux/uaccess.h>
+
+#define DRIVER_NAME "amvdec_h264"
+#define MODULE_NAME "amvdec_h264"
+#define MEM_NAME "codec_264"
+#define HANDLE_H264_IRQ
+
+#if 0
+/* currently, only iptv supports this function*/
+#define SUPPORT_BAD_MACRO_BLOCK_REDUNDANCY
+#endif
+
+/* #define DEBUG_PTS */
+#if 0 /* MESON_CPU_TYPE <= MESON_CPU_TYPE_MESON6TV */
+#define DROP_B_FRAME_FOR_1080P_50_60FPS
+#endif
+#define RATE_MEASURE_NUM 8
+#define RATE_CORRECTION_THRESHOLD 5
+#define RATE_24_FPS  4004	/* 23.97 */
+#define RATE_25_FPS  3840	/* 25 */
+#define DUR2PTS(x) ((x)*90/96)
+#define PTS2DUR(x) ((x)*96/90)
+#define DUR2PTS_REM(x) (x*90 - DUR2PTS(x)*96)
+#define FIX_FRAME_RATE_CHECK_IDRFRAME_NUM 2
+#define VDEC_CLOCK_ADJUST_FRAME 30
+
+static inline bool close_to(int a, int b, int m)
+{
+	return (abs(a - b) < m) ? true : false;
+}
+
+static DEFINE_MUTEX(vh264_mutex);
+#define DEF_BUF_START_ADDR            0x1000000
+#define V_BUF_ADDR_OFFSET_NEW         (0x1ee000)
+#define V_BUF_ADDR_OFFSET             (0x13e000)
+
+#define PIC_SINGLE_FRAME        0
+#define PIC_TOP_BOT_TOP         1
+#define PIC_BOT_TOP_BOT         2
+#define PIC_DOUBLE_FRAME        3
+#define PIC_TRIPLE_FRAME        4
+#define PIC_TOP_BOT              5
+#define PIC_BOT_TOP              6
+#define PIC_INVALID              7
+
+#define EXTEND_SAR                      0xff
+
+#define VF_POOL_SIZE        64
+#define VF_BUF_NUM          24
+#define WORKSPACE_BUF_NUM	2
+#define PUT_INTERVAL        (HZ/100)
+#define NO_DISP_WD_COUNT    (3 * HZ / PUT_INTERVAL)
+
+#define SWITCHING_STATE_OFF       0
+#define SWITCHING_STATE_ON_CMD3   1
+#define SWITCHING_STATE_ON_CMD1   2
+#define SWITCHING_STATE_ON_CMD1_PENDING   3
+
+
+#define DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE 0x0001
+#define DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE  0x0002
+#define DEC_CONTROL_FLAG_DISABLE_FAST_POC              0x0004
+
+#define INCPTR(p) ptr_atomic_wrap_inc(&p)
+
+#define SLICE_TYPE_I 2
+#define SLICE_TYPE_P 5
+#define SLICE_TYPE_B 6
+
+struct buffer_spec_s {
+	unsigned int y_addr;
+	unsigned int u_addr;
+	unsigned int v_addr;
+
+	int y_canvas_index;
+	int u_canvas_index;
+	int v_canvas_index;
+
+	unsigned int y_canvas_width;
+	unsigned int u_canvas_width;
+	unsigned int v_canvas_width;
+
+	unsigned int y_canvas_height;
+	unsigned int u_canvas_height;
+	unsigned int v_canvas_height;
+
+	unsigned long phy_addr;
+	int alloc_count;
+};
+
+#define spec2canvas(x)  \
+	(((x)->v_canvas_index << 16) | \
+	 ((x)->u_canvas_index << 8)  | \
+	 ((x)->y_canvas_index << 0))
+
+static struct vframe_s *vh264_vf_peek(void *);
+static struct vframe_s *vh264_vf_get(void *);
+static void vh264_vf_put(struct vframe_s *, void *);
+static int vh264_vf_states(struct vframe_states *states, void *);
+static int vh264_event_cb(int type, void *data, void *private_data);
+
+static void vh264_prot_init(void);
+static int vh264_local_init(void);
+static void vh264_put_timer_func(struct timer_list *timer);
+static void stream_switching_done(void);
+
+static const char vh264_dec_id[] = "vh264-dev";
+
+#define PROVIDER_NAME   "decoder.h264"
+
+static const struct vframe_operations_s vh264_vf_provider_ops = {
+	.peek = vh264_vf_peek,
+	.get = vh264_vf_get,
+	.put = vh264_vf_put,
+	.event_cb = vh264_event_cb,
+	.vf_states = vh264_vf_states,
+};
+
+static struct vframe_provider_s vh264_vf_prov;
+/*TODO irq*/
+#if 1
+static u32 frame_width, frame_height, frame_dur, frame_prog, frame_packing_type,
+	   last_duration;
+static u32 saved_resolution;
+static u32 last_mb_width, last_mb_height;
+#else
+static u32 frame_buffer_size;
+static u32 frame_width, frame_height, frame_dur, frame_prog, last_duration;
+static u32 last_mb_width, last_mb_height;
+static u32 frame_packing_type;
+#endif
+static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE);
+static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE);
+static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE);
+static DECLARE_KFIFO(delay_display_q, struct vframe_s *, VF_POOL_SIZE);
+
+static struct vframe_s vfpool[VF_POOL_SIZE];
+static s32 vfbuf_use[VF_BUF_NUM];
+static struct buffer_spec_s buffer_spec[VF_BUF_NUM];
+static struct buffer_spec_s fense_buffer_spec[2];
+/* disp buf + keep buf+ fense buf + workspace  */
+
+#define MAX_BLK_BUFFERS (VF_BUF_NUM + 2 + WORKSPACE_BUF_NUM)
+#define VF_BUFFER_IDX(n) (WORKSPACE_BUF_NUM  + n)
+#define FENSE_BUFFER_IDX(n) (WORKSPACE_BUF_NUM + VF_BUF_NUM + n)
+
+#define USER_DATA_RUND_SIZE		(USER_DATA_SIZE + 4096)
+static struct vframe_s fense_vf[2];
+
+static struct timer_list recycle_timer;
+static u32 stat;
+static s32 buf_offset;
+static u32 pts_outside;
+static u32 sync_outside;
+static u32 dec_control;
+static u32 vh264_ratio;
+static u32 vh264_rotation;
+static u32 use_idr_framerate;
+static u32 high_bandwidth;
+
+static u32 seq_info;
+static u32 timing_info_present_flag;
+static u32 fixed_frame_rate_flag;
+static u32 fixed_frame_rate_check_count;
+static u32 aspect_ratio_info;
+static u32 num_units_in_tick;
+static u32 time_scale;
+static u32 h264_ar;
+static u32 decoder_debug_flag;
+static u32 dpb_size_adj = 6;
+static u32 fr_hint_status;
+
+#ifdef DROP_B_FRAME_FOR_1080P_50_60FPS
+static u32 last_interlaced;
+#endif
+static bool is_4k;
+static unsigned char h264_first_pts_ready;
+static bool h264_first_valid_pts_ready;
+static u32 h264pts1, h264pts2;
+static u32 h264_pts_count, duration_from_pts_done, duration_on_correcting;
+static u32 vh264_error_count;
+static u32 vh264_no_disp_count;
+static u32 fatal_error_flag;
+static u32 fatal_error_reset;
+static u32 max_refer_buf = 1;
+static u32 decoder_force_reset;
+static unsigned int no_idr_error_count;
+static unsigned int no_idr_error_max = 60;
+static unsigned int canvas_mode;
+
+#ifdef SUPPORT_BAD_MACRO_BLOCK_REDUNDANCY
+/* 0~128*/
+static u32 bad_block_scale;
+#endif
+static u32 enable_userdata_debug;
+
+static unsigned int enable_switch_fense = 1;
+#define EN_SWITCH_FENCE() (enable_switch_fense && !is_4k)
+static struct vframe_qos_s s_vframe_qos;
+static int frame_count;
+
+#if 0
+static u32 vh264_no_disp_wd_count;
+#endif
+static u32 vh264_running;
+static s32 vh264_stream_switching_state;
+static s32 vh264_eos;
+static struct vframe_s *p_last_vf;
+static s32 iponly_early_mode;
+static void *mm_blk_handle;
+static int tvp_flag;
+static bool is_reset;
+
+/*TODO irq*/
+#if 1
+static u32 last_pts, last_pts_remainder;
+#else
+static u32 last_pts;
+#endif
+static bool check_pts_discontinue;
+static u32 wait_buffer_counter;
+static u32 video_signal_from_vui;
+
+static uint error_recovery_mode;
+static uint error_recovery_mode_in = 3;
+static uint error_recovery_mode_use = 3;
+
+static uint mb_total = 0, mb_width = 0, mb_height;
+static uint saved_idc_level;
+#define UCODE_IP_ONLY 2
+#define UCODE_IP_ONLY_PARAM 1
+static uint ucode_type;
+
+#ifdef DEBUG_PTS
+static unsigned long pts_missed, pts_hit;
+#endif
+static uint debugfirmware;
+
+static atomic_t vh264_active = ATOMIC_INIT(0);
+static int vh264_reset;
+static struct work_struct error_wd_work;
+static struct work_struct stream_switching_work;
+static struct work_struct set_parameter_work;
+static struct work_struct notify_work;
+static struct work_struct set_clk_work;
+static struct work_struct userdata_push_work;
+
+struct h264_qos_data_node_t {
+	struct list_head list;
+
+	uint32_t b_offset;
+	int poc;
+	/* picture qos infomation*/
+	int max_qp;
+	int avg_qp;
+	int min_qp;
+	int max_skip;
+	int avg_skip;
+	int min_skip;
+	int max_mv;
+	int min_mv;
+	int avg_mv;
+};
+
+/*qos data records list waiting for match with picture that be display*/
+static struct list_head picture_qos_list;
+/*free qos data records list*/
+static struct list_head free_qos_nodes_list;
+#define MAX_FREE_QOS_NODES		64
+static struct h264_qos_data_node_t free_nodes[MAX_FREE_QOS_NODES];
+static struct work_struct qos_work;
+static struct dec_sysinfo vh264_amstream_dec_info;
+static dma_addr_t mc_dma_handle;
+static void *mc_cpu_addr;
+static u32 first_offset;
+static u32 first_pts;
+static u32 first_frame_size;
+static u64 first_pts64;
+static bool first_pts_cached;
+static void *sei_data_buffer;
+static dma_addr_t sei_data_buffer_phys;
+static int clk_adj_frame_count;
+
+#define MC_OFFSET_HEADER    0x0000
+#define MC_OFFSET_DATA      0x1000
+#define MC_OFFSET_MMCO      0x2000
+#define MC_OFFSET_LIST      0x3000
+#define MC_OFFSET_SLICE     0x4000
+
+#define MC_TOTAL_SIZE       (20*SZ_1K)
+#define MC_SWAP_SIZE        (4*SZ_1K)
+
+#define MODE_ERROR 0
+#define MODE_FULL  1
+
+static DEFINE_SPINLOCK(lock);
+static DEFINE_SPINLOCK(prepare_lock);
+static DEFINE_SPINLOCK(recycle_lock);
+
+static bool block_display_q;
+static int vh264_stop(int mode);
+static s32 vh264_init(void);
+
+
+#define DFS_HIGH_THEASHOLD 3
+
+static bool pts_discontinue;
+
+static struct ge2d_context_s *ge2d_videoh264_context;
+
+static struct vdec_info *gvs;
+
+static struct vdec_s *vdec_h264;
+
+static int ge2d_videoh264task_init(void)
+{
+	if (ge2d_videoh264_context == NULL)
+		ge2d_videoh264_context = create_ge2d_work_queue();
+
+	if (ge2d_videoh264_context == NULL) {
+		pr_info("create_ge2d_work_queue video task failed\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int ge2d_videoh264task_release(void)
+{
+	if (ge2d_videoh264_context) {
+		destroy_ge2d_work_queue(ge2d_videoh264_context);
+		ge2d_videoh264_context = NULL;
+	}
+	return 0;
+}
+
+static int ge2d_canvas_dup(struct canvas_s *srcy, struct canvas_s *srcu,
+		struct canvas_s *des, int format, u32 srcindex,
+		u32 desindex)
+{
+
+	struct config_para_ex_s ge2d_config;
+	/* pr_info("[%s]h264 ADDR srcy[0x%lx] srcu[0x%lx] des[0x%lx]\n",
+	 *	   __func__, srcy->addr, srcu->addr, des->addr);
+	 */
+	memset(&ge2d_config, 0, sizeof(struct config_para_ex_s));
+
+	ge2d_config.alu_const_color = 0;
+	ge2d_config.bitmask_en = 0;
+	ge2d_config.src1_gb_alpha = 0;
+
+	ge2d_config.src_planes[0].addr = srcy->addr;
+	ge2d_config.src_planes[0].w = srcy->width;
+	ge2d_config.src_planes[0].h = srcy->height;
+
+	ge2d_config.src_planes[1].addr = srcu->addr;
+	ge2d_config.src_planes[1].w = srcu->width;
+	ge2d_config.src_planes[1].h = srcu->height;
+
+	ge2d_config.dst_planes[0].addr = des->addr;
+	ge2d_config.dst_planes[0].w = des->width;
+	ge2d_config.dst_planes[0].h = des->height;
+
+	ge2d_config.src_para.canvas_index = srcindex;
+	ge2d_config.src_para.mem_type = CANVAS_TYPE_INVALID;
+	ge2d_config.src_para.format = format;
+	ge2d_config.src_para.fill_color_en = 0;
+	ge2d_config.src_para.fill_mode = 0;
+	ge2d_config.src_para.color = 0;
+	ge2d_config.src_para.top = 0;
+	ge2d_config.src_para.left = 0;
+	ge2d_config.src_para.width = srcy->width;
+	ge2d_config.src_para.height = srcy->height;
+
+	ge2d_config.dst_para.canvas_index = desindex;
+	ge2d_config.dst_para.mem_type = CANVAS_TYPE_INVALID;
+	ge2d_config.dst_para.format = format;
+	ge2d_config.dst_para.fill_color_en = 0;
+	ge2d_config.dst_para.fill_mode = 0;
+	ge2d_config.dst_para.color = 0;
+	ge2d_config.dst_para.top = 0;
+	ge2d_config.dst_para.left = 0;
+	ge2d_config.dst_para.width = srcy->width;
+	ge2d_config.dst_para.height = srcy->height;
+
+	if (ge2d_context_config_ex(ge2d_videoh264_context, &ge2d_config) < 0) {
+		pr_info("ge2d_context_config_ex failed\n");
+		return -1;
+	}
+
+	stretchblt_noalpha(ge2d_videoh264_context, 0, 0, srcy->width,
+			srcy->height, 0, 0, srcy->width, srcy->height);
+
+	return 0;
+}
+
+static inline int fifo_level(void)
+{
+	return VF_POOL_SIZE - kfifo_len(&newframe_q);
+}
+
+
+void spec_set_canvas(struct buffer_spec_s *spec,
+		unsigned int width, unsigned int height)
+{
+	int endian;
+
+	endian = (canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0;
+	config_cav_lut_ex(spec->y_canvas_index,
+			spec->y_addr,
+			width, height,
+			CANVAS_ADDR_NOWRAP, canvas_mode, endian, VDEC_1);
+
+	config_cav_lut_ex(spec->u_canvas_index,
+			spec->u_addr,
+			width, height / 2,
+			CANVAS_ADDR_NOWRAP, canvas_mode, endian, VDEC_1);
+
+}
+
+static void vh264_notify_work(struct work_struct *work)
+{
+	pr_info("frame duration changed %d\n", frame_dur);
+	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT,
+		(void *)((unsigned long)frame_dur));
+
+	return;
+}
+
+static void prepare_display_q(void)
+{
+	unsigned long flags;
+	int count;
+
+	spin_lock_irqsave(&prepare_lock, flags);
+
+	if (block_display_q) {
+		spin_unlock_irqrestore(&prepare_lock, flags);
+		return;
+	}
+
+	spin_unlock_irqrestore(&prepare_lock, flags);
+
+	count  = (int)VF_POOL_SIZE -
+		kfifo_len(&delay_display_q) -
+		kfifo_len(&display_q) -
+		kfifo_len(&recycle_q) -
+		kfifo_len(&newframe_q);
+
+	if ((vh264_stream_switching_state != SWITCHING_STATE_OFF)
+		|| !EN_SWITCH_FENCE())
+		count = 0;
+	else
+		count = (count < 2) ? 0 : 2;
+
+	while (kfifo_len(&delay_display_q) > count) {
+		struct vframe_s *vf;
+
+		if (kfifo_get(&delay_display_q, &vf)) {
+			kfifo_put(&display_q,
+				(const struct vframe_s *)vf);
+			ATRACE_COUNTER(MODULE_NAME, vf->pts);
+			vf_notify_receiver(PROVIDER_NAME,
+				VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+		}
+	}
+}
+
+static struct vframe_s *vh264_vf_peek(void *op_arg)
+{
+	struct vframe_s *vf;
+
+	if (kfifo_peek(&display_q, &vf))
+		return vf;
+
+	return NULL;
+}
+
+static struct vframe_s *vh264_vf_get(void *op_arg)
+{
+	struct vframe_s *vf;
+
+	if (kfifo_get(&display_q, &vf))
+		return vf;
+
+	return NULL;
+}
+static bool vf_valid_check(struct vframe_s *vf) {
+	int i;
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		if (vf == &vfpool[i])
+			return true;
+	}
+	pr_info(" invalid vf been put, vf = %p\n", vf);
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		pr_info("www valid vf[%d]= %p \n", i, &vfpool[i]);
+	}
+	return false;
+}
+
+static void vh264_vf_put(struct vframe_s *vf, void *op_arg)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&recycle_lock, flags);
+
+	if ((vf != &fense_vf[0]) && (vf != &fense_vf[1])) {
+		if (vf && (vf_valid_check(vf) == true))
+			kfifo_put(&recycle_q, (const struct vframe_s *)vf);
+	}
+	spin_unlock_irqrestore(&recycle_lock, flags);
+}
+
+static int vh264_event_cb(int type, void *data, void *private_data)
+{
+	if (type & VFRAME_EVENT_RECEIVER_RESET) {
+		unsigned long flags;
+
+		amvdec_stop();
+#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+		vf_light_unreg_provider(&vh264_vf_prov);
+#endif
+		spin_lock_irqsave(&lock, flags);
+		vh264_local_init();
+		vh264_prot_init();
+		spin_unlock_irqrestore(&lock, flags);
+#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+		vf_reg_provider(&vh264_vf_prov);
+#endif
+		amvdec_start();
+	}
+	return 0;
+}
+
+static int vh264_vf_states(struct vframe_states *states, void *op_arg)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&lock, flags);
+
+	states->vf_pool_size = VF_POOL_SIZE;
+	states->buf_free_num = kfifo_len(&newframe_q);
+	states->buf_avail_num = kfifo_len(&display_q) +
+				kfifo_len(&delay_display_q);
+	states->buf_recycle_num = kfifo_len(&recycle_q);
+
+	spin_unlock_irqrestore(&lock, flags);
+
+	return 0;
+}
+
+#if 0
+static tvin_trans_fmt_t convert_3d_format(u32 type)
+{
+	const tvin_trans_fmt_t conv_tab[] = {
+		0,		/* checkerboard */
+		0,		/* column alternation */
+		TVIN_TFMT_3D_LA,	/* row alternation */
+		TVIN_TFMT_3D_LRH_OLER,	/* side by side */
+		TVIN_TFMT_3D_FA	/* top bottom */
+	};
+
+	return (type <= 4) ? conv_tab[type] : 0;
+}
+#endif
+
+
+
+#define DUMP_CC_AS_ASCII
+
+#ifdef DUMP_CC_AS_ASCII
+static int vbi_to_ascii(int c)
+{
+	if (c < 0)
+		return '?';
+
+	c &= 0x7F;
+
+	if (c < 0x20 || c >= 0x7F)
+		return '.';
+
+	return c;
+}
+
+static void dump_cc_ascii(const uint8_t *buf, unsigned int vpts, int poc)
+{
+	int cc_flag;
+	int cc_count;
+	int i;
+	int szAscii[32];
+	int index = 0;
+
+	cc_flag = buf[1] & 0x40;
+	if (!cc_flag) {
+		pr_info("### cc_flag is invalid\n");
+		return;
+	}
+	cc_count = buf[1] & 0x1f;
+
+	for (i = 0; i < cc_count; ++i) {
+		unsigned int b0;
+		unsigned int cc_valid;
+		unsigned int cc_type;
+		unsigned char cc_data1;
+		unsigned char cc_data2;
+
+		b0 = buf[3 + i * 3];
+		cc_valid = b0 & 4;
+		cc_type = b0 & 3;
+		cc_data1 = buf[4 + i * 3];
+		cc_data2 = buf[5 + i * 3];
+
+
+		if (cc_type == 0) {
+			/* NTSC pair, Line 21 */
+			szAscii[index++] = vbi_to_ascii(cc_data1);
+			szAscii[index++] = vbi_to_ascii(cc_data2);
+			if ((!cc_valid) || (i >= 3))
+				break;
+		}
+	}
+
+	if (index > 0 && index <= 8) {
+		char pr_buf[128];
+		int len;
+
+		sprintf(pr_buf, "push vpts:0x%x, poc:%d :", vpts, poc);
+		len = strlen(pr_buf);
+		for (i=0;i<index;i++)
+			sprintf(pr_buf + len + i*2, "%c ", szAscii[i]);
+		pr_info("%s\n", pr_buf);
+	}
+
+}
+#endif
+
+/*
+#define DUMP_USER_DATA_HEX
+*/
+#ifdef DUMP_USER_DATA_HEX
+static void print_data(unsigned char *pdata, int len)
+{
+	int nLeft;
+	char buf[128];
+
+	nLeft = len;
+	while (nLeft >= 16) {
+		int i;
+
+		for (i=0;i<16;i++)
+			sprintf(buf+i*3, "%02x ", pdata[i]);
+
+		pr_info("%s\n", buf);
+		nLeft -= 16;
+		pdata += 16;
+	}
+
+	while (nLeft >= 8) {
+		int i;
+		for (i=0;i<nLeft;i++)
+			sprintf(buf+i*3, "%02x ", pdata[i]);
+
+		pr_info("%s\n", buf);
+		nLeft -= 8;
+		pdata += 8;
+	}
+}
+#endif
+
+
+
+static void aml_swap_data(uint8_t *user_data, int ud_size)
+{
+	int swap_blocks, i, j, k, m;
+	unsigned char c_temp;
+
+	/* swap byte order */
+	swap_blocks = ud_size / 8;
+	for (i = 0; i < swap_blocks; i++) {
+		j = i * 8;
+		k = j + 7;
+		for (m = 0; m < 4; m++) {
+			c_temp = user_data[j];
+			user_data[j++] = user_data[k];
+			user_data[k--] = c_temp;
+		}
+	}
+}
+
+
+static void udr_dump_data(unsigned int user_data_wp,
+						unsigned int user_data_length,
+						unsigned int pts,
+						int poc)
+{
+	unsigned char *pdata;
+	int user_data_len;
+	int wp_start;
+	int nLeft;
+	unsigned char szBuf[256];
+	int nOffset;
+
+	dma_sync_single_for_cpu(amports_get_dma_device(),
+			sei_data_buffer_phys, USER_DATA_SIZE,
+			DMA_FROM_DEVICE);
+
+	if (user_data_length & 0x07)
+		user_data_len = (user_data_length + 8) & 0xFFFFFFF8;
+	else
+		user_data_len = user_data_length;
+
+	if (user_data_wp >= user_data_len) {
+		wp_start = user_data_wp - user_data_len;
+
+		pdata = (unsigned char *)sei_data_buffer;
+		pdata += wp_start;
+		nLeft = user_data_len;
+
+		memset(szBuf, 0, 256);
+		memcpy(szBuf, pdata, user_data_len);
+	} else {
+		wp_start = user_data_wp +
+			USER_DATA_SIZE - user_data_len;
+
+		pdata = (unsigned char *)sei_data_buffer;
+		pdata += wp_start;
+		nLeft = USER_DATA_SIZE - wp_start;
+
+		memset(szBuf, 0, 256);
+		memcpy(szBuf, pdata, nLeft);
+		nOffset = nLeft;
+
+		pdata = (unsigned char *)sei_data_buffer;
+		nLeft = user_data_wp;
+		memcpy(szBuf+nOffset, pdata, nLeft);
+	}
+
+	aml_swap_data(szBuf, user_data_len);
+
+#ifdef DUMP_USER_DATA_HEX
+	print_data(szBuf, user_data_len);
+#endif
+
+#ifdef DUMP_CC_AS_ASCII
+	dump_cc_ascii(szBuf+7, pts, poc);
+#endif
+}
+
+
+struct vh264_userdata_recored_t {
+	struct userdata_meta_info_t meta_info;
+	u32 rec_start;
+	u32 rec_len;
+};
+
+#define USERDATA_FIFO_NUM    256
+
+struct vh264_userdata_info_t {
+	struct vh264_userdata_recored_t records[USERDATA_FIFO_NUM];
+	u8 *data_buf;
+	u8 *data_buf_end;
+	u32 buf_len;
+	u32 read_index;
+	u32 write_index;
+	u32 last_wp;
+};
+
+static struct vh264_userdata_info_t *p_userdata_mgr;
+
+static DEFINE_MUTEX(userdata_mutex);
+
+
+void vh264_crate_userdata_manager(u8 *userdata_buf, int buf_len)
+{
+	p_userdata_mgr = (struct vh264_userdata_info_t *)
+		vmalloc(sizeof(struct vh264_userdata_info_t));
+	if (p_userdata_mgr) {
+		memset(p_userdata_mgr, 0,
+			sizeof(struct vh264_userdata_info_t));
+		p_userdata_mgr->data_buf = userdata_buf;
+		p_userdata_mgr->buf_len = buf_len;
+		p_userdata_mgr->data_buf_end = userdata_buf + buf_len;
+	}
+}
+
+void vh264_destroy_userdata_manager(void)
+{
+	if (p_userdata_mgr) {
+		vfree(p_userdata_mgr);
+		p_userdata_mgr = NULL;
+	}
+}
+
+/*
+#define DUMP_USER_DATA
+*/
+#ifdef DUMP_USER_DATA
+
+#define MAX_USER_DATA_SIZE		3145728
+static void *user_data_buf;
+static unsigned char *pbuf_start;
+static int total_len;
+static int bskip;
+static int n_userdata_id;
+
+
+static void print_mem_data(unsigned char *pdata,
+						int len,
+						unsigned int flag,
+						unsigned int duration,
+						unsigned int vpts,
+						unsigned int vpts_valid,
+						int rec_id)
+{
+	int nLeft;
+
+	nLeft = len;
+#if 0
+	pr_info("%d len = %d, flag = %d, duration = %d, vpts = 0x%x, vpts_valid = %d\n",
+				rec_id,	len, flag,
+				duration, vpts, vpts_valid);
+#endif
+	pr_info("%d len = %d, flag = %d, vpts = 0x%x\n",
+				rec_id,	len, flag, vpts);
+
+
+	while (nLeft >= 16) {
+		pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+			pdata[0], pdata[1], pdata[2], pdata[3],
+			pdata[4], pdata[5], pdata[6], pdata[7],
+			pdata[8], pdata[9], pdata[10], pdata[11],
+			pdata[12], pdata[13], pdata[14], pdata[15]);
+		nLeft -= 16;
+		pdata += 16;
+	}
+
+
+	while (nLeft > 0) {
+		pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+			pdata[0], pdata[1], pdata[2], pdata[3],
+			pdata[4], pdata[5], pdata[6], pdata[7]);
+		nLeft -= 8;
+		pdata += 8;
+	}
+}
+
+
+static void dump_data(u8 *pdata,
+						unsigned int user_data_length,
+						unsigned int flag,
+						unsigned int duration,
+						unsigned int vpts,
+						unsigned int vpts_valid,
+						int rec_id)
+{
+	unsigned char szBuf[256];
+
+
+	memset(szBuf, 0, 256);
+	memcpy(szBuf, pdata, user_data_length);
+/*
+	aml_swap_data(szBuf, user_data_length);
+*/
+
+	print_mem_data(szBuf, user_data_length,
+				flag, duration, vpts,
+				vpts_valid, rec_id);
+
+#ifdef DEBUG_CC_DUMP_ASCII
+	dump_cc_ascii(szBuf+7);
+#endif
+}
+
+static void push_to_buf(u8 *pdata, int len, struct userdata_meta_info_t *pmeta)
+{
+	u32 *pLen;
+	int info_cnt;
+	u8 *pbuf_end;
+
+	if (!user_data_buf)
+		return;
+
+	if (bskip) {
+		pr_info("over size, skip\n");
+		return;
+	}
+	info_cnt = 0;
+	pLen = (u32 *)pbuf_start;
+
+	*pLen = len;
+	pbuf_start += sizeof(u32);
+	info_cnt++;
+	pLen++;
+
+	*pLen = pmeta->duration;
+	pbuf_start += sizeof(u32);
+	info_cnt++;
+	pLen++;
+
+	*pLen = pmeta->flags;
+	pbuf_start += sizeof(u32);
+	info_cnt++;
+	pLen++;
+
+	*pLen = pmeta->vpts;
+	pbuf_start += sizeof(u32);
+	info_cnt++;
+	pLen++;
+
+	*pLen = pmeta->vpts_valid;
+	pbuf_start += sizeof(u32);
+	info_cnt++;
+	pLen++;
+
+
+	*pLen = n_userdata_id;
+	pbuf_start += sizeof(u32);
+	info_cnt++;
+	pLen++;
+
+
+
+	pbuf_end = (u8 *)sei_data_buffer + USER_DATA_SIZE;
+	if (pdata + len > pbuf_end) {
+		int first_section_len;
+
+		first_section_len = pbuf_end - pdata;
+		memcpy(pbuf_start, pdata, first_section_len);
+		pdata = (u8 *)sei_data_buffer;
+		pbuf_start += first_section_len;
+		memcpy(pbuf_start, pdata, len - first_section_len);
+		pbuf_start += len - first_section_len;
+	} else {
+		memcpy(pbuf_start, pdata, len);
+		pbuf_start += len;
+	}
+
+	total_len += len + info_cnt * sizeof(u32);
+	if (total_len >= MAX_USER_DATA_SIZE-4096)
+		bskip = 1;
+}
+
+
+static void dump_userdata_info(
+					void *puser_data,
+					int len,
+					struct userdata_meta_info_t *pmeta)
+{
+	u8 *pstart;
+
+	pstart = (u8 *)puser_data;
+
+
+	push_to_buf(pstart, len, pmeta);
+}
+
+static void show_user_data_buf(void)
+{
+	u8 *pbuf;
+	int len;
+	unsigned int flag;
+	unsigned int duration;
+	unsigned int vpts;
+	unsigned int vpts_valid;
+	int rec_id;
+
+	pr_info("show user data buf\n");
+	pbuf = user_data_buf;
+
+	while (pbuf < pbuf_start) {
+		u32 *pLen;
+
+		pLen = (u32 *)pbuf;
+
+		len = *pLen;
+		pLen++;
+		pbuf += sizeof(u32);
+
+		duration = *pLen;
+		pLen++;
+		pbuf += sizeof(u32);
+
+		flag = *pLen;
+		pLen++;
+		pbuf += sizeof(u32);
+
+		vpts = *pLen;
+		pLen++;
+		pbuf += sizeof(u32);
+
+		vpts_valid = *pLen;
+		pLen++;
+		pbuf += sizeof(u32);
+
+		rec_id = *pLen;
+		pLen++;
+		pbuf += sizeof(u32);
+
+		dump_data(pbuf, len, flag, duration, vpts, vpts_valid, rec_id);
+		pbuf += len;
+		msleep(30);
+	}
+}
+
+static int vh264_init_userdata_dump(void)
+{
+	user_data_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL);
+	if (user_data_buf)
+		return 1;
+	else
+		return 0;
+}
+
+static void vh264_dump_userdata(void)
+{
+	if (user_data_buf) {
+		show_user_data_buf();
+		kfree(user_data_buf);
+		user_data_buf = NULL;
+	}
+}
+
+static void vh264_reset_user_data_buf(void)
+{
+	total_len = 0;
+	pbuf_start = user_data_buf;
+	bskip = 0;
+	n_userdata_id = 0;
+}
+#endif
+
+static void vh264_add_userdata(struct userdata_meta_info_t meta_info, int wp)
+{
+	struct vh264_userdata_recored_t *p_userdata_rec;
+	int data_length;
+
+	mutex_lock(&userdata_mutex);
+
+	if (p_userdata_mgr) {
+		if (wp > p_userdata_mgr->last_wp)
+			data_length = wp - p_userdata_mgr->last_wp;
+		else
+			data_length = wp + p_userdata_mgr->buf_len -
+				p_userdata_mgr->last_wp;
+
+		if (data_length & 0x7)
+			data_length = (((data_length + 8) >> 3) << 3);
+#if 0
+		pr_info("wakeup_push: ri:%d, wi:%d, data_len:%d, last_wp:%d, wp:%d, id = %d\n",
+			p_userdata_mgr->read_index,
+			p_userdata_mgr->write_index,
+			data_length,
+			p_userdata_mgr->last_wp,
+			wp,
+			n_userdata_id);
+#endif
+		p_userdata_rec = p_userdata_mgr->records +
+			p_userdata_mgr->write_index;
+		p_userdata_rec->meta_info = meta_info;
+		p_userdata_rec->rec_start = p_userdata_mgr->last_wp;
+		p_userdata_rec->rec_len = data_length;
+		p_userdata_mgr->last_wp = wp;
+
+#ifdef DUMP_USER_DATA
+		dump_userdata_info(p_userdata_mgr->data_buf +
+			p_userdata_rec->rec_start,
+			data_length,
+			&meta_info);
+		n_userdata_id++;
+#endif
+
+		p_userdata_mgr->write_index++;
+		if (p_userdata_mgr->write_index >= USERDATA_FIFO_NUM)
+			p_userdata_mgr->write_index = 0;
+	}
+	mutex_unlock(&userdata_mutex);
+
+	vdec_wakeup_userdata_poll(vdec_h264);
+}
+
+static int vh264_user_data_read(struct vdec_s *vdec,
+				struct userdata_param_t *puserdata_para)
+{
+	int rec_ri, rec_wi;
+	int rec_len;
+	u8 *rec_data_start;
+	u8 *pdest_buf;
+	struct vh264_userdata_recored_t *p_userdata_rec;
+	u32 data_size;
+	u32 res;
+	int copy_ok = 1;
+
+
+	pdest_buf = puserdata_para->pbuf_addr;
+
+
+	mutex_lock(&userdata_mutex);
+
+	if (!p_userdata_mgr) {
+		mutex_unlock(&userdata_mutex);
+		return 0;
+	}
+/*
+	pr_info("ri = %d, wi = %d\n",
+		p_userdata_mgr->read_index,
+		p_userdata_mgr->write_index);
+*/
+	rec_ri = p_userdata_mgr->read_index;
+	rec_wi = p_userdata_mgr->write_index;
+
+	if (rec_ri == rec_wi) {
+		mutex_unlock(&userdata_mutex);
+		return 0;
+	}
+
+	p_userdata_rec = p_userdata_mgr->records + rec_ri;
+
+	rec_len = p_userdata_rec->rec_len;
+	rec_data_start = p_userdata_rec->rec_start + p_userdata_mgr->data_buf;
+/*
+	pr_info("rec_len:%d, rec_start:%d, buf_len:%d\n",
+		p_userdata_rec->rec_len,
+		p_userdata_rec->rec_start,
+		puserdata_para->buf_len);
+*/
+	if (rec_len <= puserdata_para->buf_len) {
+		/* dvb user data buffer is enought to copy the whole recored. */
+		data_size = rec_len;
+		if (rec_data_start + data_size
+			> p_userdata_mgr->data_buf_end) {
+			int first_section_len;
+
+			first_section_len = p_userdata_mgr->buf_len -
+				p_userdata_rec->rec_start;
+			res = (u32)copy_to_user((void *)pdest_buf,
+							(void *)rec_data_start,
+							first_section_len);
+			if (res) {
+				pr_info("p1 read not end res=%d, request=%d\n",
+					res, first_section_len);
+				copy_ok = 0;
+
+				p_userdata_rec->rec_len -=
+					first_section_len - res;
+				p_userdata_rec->rec_start +=
+					first_section_len - res;
+				puserdata_para->data_size =
+					first_section_len - res;
+			} else {
+				res = (u32)copy_to_user(
+					(void *)(pdest_buf+first_section_len),
+					(void *)p_userdata_mgr->data_buf,
+					data_size - first_section_len);
+				if (res) {
+					pr_info("p2 read not end res=%d, request=%d\n",
+						res, data_size);
+					copy_ok = 0;
+				}
+				p_userdata_rec->rec_len -=
+					data_size - res;
+				p_userdata_rec->rec_start =
+					data_size - first_section_len - res;
+				puserdata_para->data_size =
+					data_size - res;
+			}
+		} else {
+			res = (u32)copy_to_user((void *)pdest_buf,
+						(void *)rec_data_start,
+						data_size);
+			if (res) {
+				pr_info("p3 read not end res=%d, request=%d\n",
+					res, data_size);
+				copy_ok = 0;
+			}
+			p_userdata_rec->rec_len -= data_size - res;
+			p_userdata_rec->rec_start += data_size - res;
+			puserdata_para->data_size = data_size - res;
+		}
+
+		if (copy_ok) {
+			p_userdata_mgr->read_index++;
+			if (p_userdata_mgr->read_index >= USERDATA_FIFO_NUM)
+				p_userdata_mgr->read_index = 0;
+		}
+	} else {
+		/* dvb user data buffer is not enought
+		to copy the whole recored. */
+		data_size = puserdata_para->buf_len;
+		if (rec_data_start + data_size
+			> p_userdata_mgr->data_buf_end) {
+			int first_section_len;
+
+			first_section_len = p_userdata_mgr->buf_len
+						- p_userdata_rec->rec_start;
+			res = (u32)copy_to_user((void *)pdest_buf,
+						(void *)rec_data_start,
+						first_section_len);
+			if (res) {
+				pr_info("p4 read not end res=%d, request=%d\n",
+					res, first_section_len);
+				copy_ok = 0;
+				p_userdata_rec->rec_len -=
+					first_section_len - res;
+				p_userdata_rec->rec_start +=
+					first_section_len - res;
+				puserdata_para->data_size =
+					first_section_len - res;
+			} else {
+				/* first secton copy is ok*/
+				res = (u32)copy_to_user(
+					(void *)(pdest_buf+first_section_len),
+					(void *)p_userdata_mgr->data_buf,
+					data_size - first_section_len);
+				if (res) {
+					pr_info("p5 read not end res=%d, request=%d\n",
+						res,
+						data_size - first_section_len);
+					copy_ok = 0;
+				}
+
+				p_userdata_rec->rec_len -= data_size - res;
+				p_userdata_rec->rec_start =
+					data_size - first_section_len - res;
+				puserdata_para->data_size = data_size - res;
+			}
+		} else {
+			res = (u32)copy_to_user((void *)pdest_buf,
+							(void *)rec_data_start,
+							data_size);
+			if (res) {
+				pr_info("p6 read not end res=%d, request=%d\n",
+					res, data_size);
+				copy_ok = 0;
+			}
+
+			p_userdata_rec->rec_len -= data_size - res;
+			p_userdata_rec->rec_start += data_size - res;
+			puserdata_para->data_size = data_size - res;
+		}
+
+		if (copy_ok) {
+			p_userdata_mgr->read_index++;
+			if (p_userdata_mgr->read_index
+				>= USERDATA_FIFO_NUM)
+				p_userdata_mgr->read_index = 0;
+		}
+
+	}
+	puserdata_para->meta_info = p_userdata_rec->meta_info;
+
+	if (p_userdata_mgr->read_index <= p_userdata_mgr->write_index)
+		puserdata_para->meta_info.records_in_que =
+			p_userdata_mgr->write_index -
+			p_userdata_mgr->read_index;
+	else
+		puserdata_para->meta_info.records_in_que =
+			p_userdata_mgr->write_index +
+			USERDATA_FIFO_NUM -
+			p_userdata_mgr->read_index;
+
+	puserdata_para->version = (0<<24|0<<16|0<<8|1);
+
+	mutex_unlock(&userdata_mutex);
+
+	return 1;
+}
+
+static void vh264_wakeup_userdata_poll(struct vdec_s *vdec)
+{
+	amstream_wakeup_userdata_poll(vdec);
+}
+
+static void vh264_reset_userdata_fifo(struct vdec_s *vdec, int bInit)
+{
+	mutex_lock(&userdata_mutex);
+
+	if (p_userdata_mgr) {
+		pr_info("h264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n",
+			bInit, p_userdata_mgr->read_index,
+			p_userdata_mgr->write_index);
+		p_userdata_mgr->read_index = 0;
+		p_userdata_mgr->write_index = 0;
+
+		if (bInit)
+			p_userdata_mgr->last_wp = 0;
+	}
+
+	mutex_unlock(&userdata_mutex);
+}
+
+static void h264_reset_qos_mgr(void)
+{
+	int i;
+
+	pr_info("h264_reset_qos_mgr\n");
+
+	INIT_LIST_HEAD(&free_qos_nodes_list);
+	INIT_LIST_HEAD(&picture_qos_list);
+
+	for (i = 0; i < MAX_FREE_QOS_NODES; i++) {
+		free_nodes[i].b_offset = 0xFFFFFFFF;
+
+		list_add_tail(&free_nodes[i].list,
+				&free_qos_nodes_list);
+	}
+}
+
+
+static void load_qos_data(int pic_number, uint32_t b_offset)
+{
+	uint32_t blk88_y_count;
+	uint32_t blk88_c_count;
+	uint32_t blk22_mv_count;
+	uint32_t rdata32;
+	int32_t mv_hi;
+	int32_t mv_lo;
+	uint32_t rdata32_l;
+	uint32_t mvx_L0_hi;
+	uint32_t mvy_L0_hi;
+	uint32_t mvx_L1_hi;
+	uint32_t mvy_L1_hi;
+	int64_t value;
+	uint64_t temp_value;
+/*
+#define DEBUG_QOS
+*/
+#define SUPPORT_NODE
+
+#ifdef SUPPORT_NODE
+	struct h264_qos_data_node_t *node;
+	struct h264_qos_data_node_t *tmp;
+	int bFoundNode = 0;
+
+	node = NULL;
+	if (!list_empty(&picture_qos_list)) {
+		list_for_each_entry_safe(node, tmp, &picture_qos_list, list) {
+			if (node->b_offset == b_offset) {
+				bFoundNode = 1;
+				break;
+			}
+		}
+	}
+	/*
+	pr_info("bFoundNode = %d, node:0x%p\n", bFoundNode, node);
+	*/
+	if (!bFoundNode) {
+		if (!list_empty(&free_qos_nodes_list)) {
+			node = list_entry(
+					free_qos_nodes_list.next,
+					struct h264_qos_data_node_t,
+					list);
+			/*
+			pr_info("get a node:0x%p\n", node);
+			*/
+		} else {
+			pr_info("there is no qos data node avaible\n");
+
+			return;
+		}
+	}
+
+	node->b_offset = b_offset;
+	node->poc = pic_number;
+
+	node->max_mv = 0;
+	node->avg_mv = 0;
+	node->min_mv = 0;
+
+	node->max_skip = 0;
+	node->avg_skip = 0;
+	node->min_skip = 0;
+
+	node->max_qp = 0;
+	node->avg_qp = 0;
+	node->min_qp = 0;
+#endif
+
+
+
+
+
+
+	/* set rd_idx to 0 */
+	WRITE_VREG(VDEC_PIC_QUALITY_CTRL, 0);
+	blk88_y_count = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	if (blk88_y_count == 0) {
+#ifdef DEBUG_QOS
+		pr_info(" [Picture %d Quality] NO Data yet.\n",
+			pic_number);
+#endif
+		/* reset all counts */
+		WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8));
+
+#ifdef SUPPORT_NODE
+		list_move(&node->list, &picture_qos_list);
+#endif
+		return;
+	}
+	/* qp_y_sum */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] Y QP AVG : %d (%d/%d)\n",
+		pic_number, rdata32/blk88_y_count,
+		rdata32, blk88_y_count);
+#endif
+#ifdef SUPPORT_NODE
+	node->avg_qp = rdata32/blk88_y_count;
+#endif
+
+	/* intra_y_count */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] Y intra rate : %d%c (%d)\n",
+		pic_number, rdata32*100/blk88_y_count,
+		'%', rdata32);
+#endif
+	/* skipped_y_count */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] Y skipped rate : %d%c (%d)\n",
+		pic_number, rdata32*100/blk88_y_count,
+		'%', rdata32);
+#endif
+#ifdef SUPPORT_NODE
+	node->avg_skip = rdata32*100/blk88_y_count;
+#endif
+	/* coeff_non_zero_y_count */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n",
+		pic_number, (100 - rdata32*100/(blk88_y_count*1)),
+		'%', rdata32);
+#endif
+	/* blk66_c_count */
+	blk88_c_count = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	if (blk88_c_count == 0) {
+#ifdef DEBUG_QOS
+		pr_info(" [Picture %d Quality] NO Data yet.\n",
+			pic_number);
+#endif
+		/* reset all counts */
+		WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8));
+
+#ifdef SUPPORT_NODE
+		list_move(&node->list, &picture_qos_list);
+#endif
+		return;
+	}
+	/* qp_c_sum */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] C QP AVG : %d (%d/%d)\n",
+		pic_number, rdata32/blk88_c_count,
+		rdata32, blk88_c_count);
+#endif
+	/* intra_c_count */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] C intra rate : %d%c (%d)\n",
+		pic_number, rdata32*100/blk88_c_count,
+		'%', rdata32);
+#endif
+	/* skipped_cu_c_count */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] C skipped rate : %d%c (%d)\n",
+		pic_number, rdata32*100/blk88_c_count,
+		'%', rdata32);
+#endif
+	/* coeff_non_zero_c_count */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n",
+		pic_number, (100 - rdata32*100/(blk88_c_count*1)),
+		'%', rdata32);
+#endif
+
+	/* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0],
+	1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] Y QP min : %d\n",
+		pic_number, (rdata32>>0)&0xff);
+#endif
+#ifdef SUPPORT_NODE
+	node->min_qp = (rdata32>>0)&0xff;
+#endif
+
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] Y QP max : %d\n",
+		pic_number, (rdata32>>8)&0xff);
+#endif
+#ifdef SUPPORT_NODE
+	node->max_qp = (rdata32>>8)&0xff;
+#endif
+
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] C QP min : %d\n",
+		pic_number, (rdata32>>16)&0xff);
+	pr_info(" [Picture %d Quality] C QP max : %d\n",
+		pic_number, (rdata32>>24)&0xff);
+#endif
+
+	/* blk22_mv_count */
+	blk22_mv_count = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	if (blk22_mv_count == 0) {
+#ifdef DEBUG_QOS
+		pr_info(" [Picture %d Quality] NO MV Data yet.\n",
+			pic_number);
+#endif
+		/* reset all counts */
+		WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8));
+#ifdef SUPPORT_NODE
+		list_move(&node->list, &picture_qos_list);
+#endif
+		return;
+	}
+	/* mvy_L1_count[39:32], mvx_L1_count[39:32],
+	mvy_L0_count[39:32], mvx_L0_count[39:32] */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	/* should all be 0x00 or 0xff */
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] MV AVG High Bits: 0x%X\n",
+		pic_number, rdata32);
+#endif
+	mvx_L0_hi = ((rdata32>>0)&0xff);
+	mvy_L0_hi = ((rdata32>>8)&0xff);
+	mvx_L1_hi = ((rdata32>>16)&0xff);
+	mvy_L1_hi = ((rdata32>>24)&0xff);
+
+	/* mvx_L0_count[31:0] */
+	rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	temp_value = mvx_L0_hi;
+	temp_value = (temp_value << 32) | rdata32_l;
+
+	if (mvx_L0_hi & 0x80)
+		value = 0xFFFFFFF000000000 | temp_value;
+	else
+		value = temp_value;
+	value = div_s64(value, blk22_mv_count);
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n",
+		pic_number, (int)(value),
+		value, blk22_mv_count);
+#endif
+#ifdef SUPPORT_NODE
+	node->avg_mv = value;
+#endif
+
+	/* mvy_L0_count[31:0] */
+	rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	temp_value = mvy_L0_hi;
+	temp_value = (temp_value << 32) | rdata32_l;
+
+	if (mvy_L0_hi & 0x80)
+		value = 0xFFFFFFF000000000 | temp_value;
+	else
+		value = temp_value;
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n",
+		pic_number, rdata32_l/blk22_mv_count,
+		value, blk22_mv_count);
+#endif
+
+	/* mvx_L1_count[31:0] */
+	rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	temp_value = mvx_L1_hi;
+	temp_value = (temp_value << 32) | rdata32_l;
+	if (mvx_L1_hi & 0x80)
+		value = 0xFFFFFFF000000000 | temp_value;
+	else
+		value = temp_value;
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n",
+		pic_number, rdata32_l/blk22_mv_count,
+		value, blk22_mv_count);
+#endif
+
+	/* mvy_L1_count[31:0] */
+	rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	temp_value = mvy_L1_hi;
+	temp_value = (temp_value << 32) | rdata32_l;
+	if (mvy_L1_hi & 0x80)
+		value = 0xFFFFFFF000000000 | temp_value;
+	else
+		value = temp_value;
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n",
+		pic_number, rdata32_l/blk22_mv_count,
+		value, blk22_mv_count);
+#endif
+
+	/* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]}  */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	mv_hi = (rdata32>>16)&0xffff;
+	if (mv_hi & 0x8000)
+		mv_hi = 0x8000 - mv_hi;
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] MVX_L0 MAX : %d\n",
+		pic_number, mv_hi);
+#endif
+#ifdef SUPPORT_NODE
+	node->max_mv = mv_hi;
+#endif
+
+	mv_lo = (rdata32>>0)&0xffff;
+	if (mv_lo & 0x8000)
+		mv_lo = 0x8000 - mv_lo;
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] MVX_L0 MIN : %d\n",
+		pic_number, mv_lo);
+#endif
+#ifdef SUPPORT_NODE
+	node->min_mv = mv_lo;
+#endif
+
+#ifdef DEBUG_QOS
+	/* {mvy_L0_max, mvy_L0_min} */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	mv_hi = (rdata32>>16)&0xffff;
+	if (mv_hi & 0x8000)
+		mv_hi = 0x8000 - mv_hi;
+	pr_info(" [Picture %d Quality] MVY_L0 MAX : %d\n",
+		pic_number, mv_hi);
+
+
+	mv_lo = (rdata32>>0)&0xffff;
+	if (mv_lo & 0x8000)
+		mv_lo = 0x8000 - mv_lo;
+
+	pr_info(" [Picture %d Quality] MVY_L0 MIN : %d\n",
+		pic_number, mv_lo);
+
+
+	/* {mvx_L1_max, mvx_L1_min} */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	mv_hi = (rdata32>>16)&0xffff;
+	if (mv_hi & 0x8000)
+		mv_hi = 0x8000 - mv_hi;
+
+	pr_info(" [Picture %d Quality] MVX_L1 MAX : %d\n",
+		pic_number, mv_hi);
+
+
+	mv_lo = (rdata32>>0)&0xffff;
+	if (mv_lo & 0x8000)
+		mv_lo = 0x8000 - mv_lo;
+
+	pr_info(" [Picture %d Quality] MVX_L1 MIN : %d\n",
+		pic_number, mv_lo);
+
+
+	/* {mvy_L1_max, mvy_L1_min} */
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	mv_hi = (rdata32>>16)&0xffff;
+	if (mv_hi & 0x8000)
+		mv_hi = 0x8000 - mv_hi;
+
+	pr_info(" [Picture %d Quality] MVY_L1 MAX : %d\n",
+		pic_number, mv_hi);
+
+	mv_lo = (rdata32>>0)&0xffff;
+	if (mv_lo & 0x8000)
+		mv_lo = 0x8000 - mv_lo;
+
+	pr_info(" [Picture %d Quality] MVY_L1 MIN : %d\n",
+		pic_number, mv_lo);
+#endif
+
+	rdata32 = READ_VREG(VDEC_PIC_QUALITY_CTRL);
+#ifdef DEBUG_QOS
+	pr_info(" [Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n",
+		pic_number, rdata32);
+#endif
+	/* reset all counts */
+	WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8));
+#ifdef SUPPORT_NODE
+	list_move(&node->list, &picture_qos_list);
+#endif
+}
+
+void search_qos_node(struct vframe_qos_s *picture_qos, uint32_t b_offset)
+{
+	struct h264_qos_data_node_t *node;
+	struct h264_qos_data_node_t *tmp;
+
+	if (!list_empty(&picture_qos_list)) {
+		list_for_each_entry_safe(node, tmp, &picture_qos_list, list) {
+			if (node->b_offset == b_offset) {
+
+				picture_qos->avg_mv = node->avg_mv;
+				picture_qos->min_mv = node->min_mv;
+				picture_qos->max_mv = node->max_mv;
+
+				picture_qos->avg_skip = node->avg_skip;
+				picture_qos->min_skip = node->min_skip;
+				picture_qos->max_skip = node->max_skip;
+
+				picture_qos->avg_qp = node->avg_qp;
+				picture_qos->min_qp = node->min_qp;
+				picture_qos->max_qp = node->max_qp;
+
+#if 0
+				pr_info("POC:%d, mv: max:%d,  avg:%d, min:%d\n"
+					"qp: max:%d,  avg:%d, min:%d\n"
+					"skip: max:%d,  avg:%d, min:%d\n",
+					node->poc,
+					picture_qos->max_mv,
+					picture_qos->avg_mv,
+					picture_qos->min_mv,
+					picture_qos->max_qp,
+					picture_qos->avg_qp,
+					picture_qos->min_qp,
+					picture_qos->max_skip,
+					picture_qos->avg_skip,
+					picture_qos->min_skip);
+#endif
+				node->b_offset = 0xFFFFFFFF;
+				list_move(&node->list, &free_qos_nodes_list);
+
+				break;
+			}
+		}
+	}
+}
+
+static void qos_do_work(struct work_struct *work)
+{
+	uint32_t poc;
+	uint32_t bOffset;
+
+
+	poc = READ_VREG(AV_SCRATCH_M);
+	bOffset = READ_VREG(AV_SCRATCH_L);
+/*
+	pr_info("poc:%d, bOffset:0x%x\n", poc, bOffset);
+*/
+	load_qos_data(poc, bOffset);
+
+
+	WRITE_VREG(AV_SCRATCH_0, 0);
+}
+
+static void userdata_push_do_work(struct work_struct *work)
+{
+	unsigned int sei_itu35_flags;
+	unsigned int sei_itu35_wp;
+	unsigned int sei_itu35_data_length;
+
+	struct userdata_meta_info_t meta_info;
+	u32 offset, pts;
+	u64 pts_us64 = 0;
+	u32 slice_type;
+	u32 reg;
+	u32 poc_number;
+	u32 picture_struct;
+
+	memset(&meta_info, 0, sizeof(meta_info));
+
+	meta_info.duration = frame_dur;
+
+	reg = READ_VREG(AV_SCRATCH_M);
+	poc_number = reg & 0x7FFFFFF;
+	if ((poc_number >> 16) == 0x7FF)
+		poc_number = (reg & 0x7FFFFFF) - 0x8000000;
+
+	slice_type = (reg >> 29) & 0x7;
+	switch (slice_type) {
+	case SLICE_TYPE_I:
+			meta_info.flags |= 1<<7;
+			break;
+	case SLICE_TYPE_P:
+			meta_info.flags |= 3<<7;
+			break;
+	case SLICE_TYPE_B:
+			meta_info.flags |= 2<<7;
+			break;
+	}
+	meta_info.poc_number = poc_number;
+	picture_struct = (reg >> 27) & 0x3;
+
+	meta_info.flags |= (VFORMAT_H264 << 3) | (picture_struct << 12);
+
+
+	offset = READ_VREG(AV_SCRATCH_L);
+
+	if (pts_pickout_offset_us64
+			 (PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) != 0) {
+		pr_info("pts pick outfailed, offset:0x%x\n", offset);
+		pts = -1;
+		meta_info.vpts_valid = 0;
+	} else
+		meta_info.vpts_valid = 1;
+	meta_info.vpts = pts;
+/*
+	pr_info("offset:0x%x, vpts:0x%x, slice:%d, poc:%d\n",
+		offset, pts, slice_type,
+		poc_number);
+*/
+	sei_itu35_flags = READ_VREG(AV_SCRATCH_J);
+	sei_itu35_wp = (sei_itu35_flags >> 16) & 0xffff;
+	sei_itu35_data_length = sei_itu35_flags & 0x7fff;
+
+	if (enable_userdata_debug)
+		udr_dump_data(sei_itu35_wp,
+			sei_itu35_data_length,
+			pts, poc_number);
+
+
+	vh264_add_userdata(meta_info, sei_itu35_wp);
+
+	WRITE_VREG(AV_SCRATCH_J, 0);
+}
+
+
+static void set_frame_info(struct vframe_s *vf)
+{
+	vf->width = frame_width;
+	vf->height = frame_height;
+	vf->duration = frame_dur;
+	vf->ratio_control =
+		(min(h264_ar, (u32) DISP_RATIO_ASPECT_RATIO_MAX)) <<
+		DISP_RATIO_ASPECT_RATIO_BIT;
+	vf->orientation = vh264_rotation;
+	vf->flag = 0;
+
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER_3D_PROCESS
+	vf->trans_fmt = 0;
+	if ((vf->trans_fmt == TVIN_TFMT_3D_LRF) ||
+		(vf->trans_fmt == TVIN_TFMT_3D_LA)) {
+		vf->left_eye.start_x = 0;
+		vf->left_eye.start_y = 0;
+		vf->left_eye.width = frame_width / 2;
+		vf->left_eye.height = frame_height;
+
+		vf->right_eye.start_x = 0;
+		vf->right_eye.start_y = 0;
+		vf->right_eye.width = frame_width / 2;
+		vf->right_eye.height = frame_height;
+	} else if ((vf->trans_fmt == TVIN_TFMT_3D_LRH_OLER) ||
+			   (vf->trans_fmt == TVIN_TFMT_3D_TB)) {
+		vf->left_eye.start_x = 0;
+		vf->left_eye.start_y = 0;
+		vf->left_eye.width = frame_width / 2;
+		vf->left_eye.height = frame_height;
+
+		vf->right_eye.start_x = 0;
+		vf->right_eye.start_y = 0;
+		vf->right_eye.width = frame_width / 2;
+		vf->right_eye.height = frame_height;
+	}
+#endif
+
+}
+
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+static void vh264_ppmgr_reset(void)
+{
+	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL);
+
+	vh264_local_init();
+
+	pr_info("vh264dec: vf_ppmgr_reset\n");
+}
+#endif
+
+static int get_max_dpb_size(int level_idc, int mb_width, int mb_height)
+{
+	int size, r;
+
+	switch (level_idc) {
+	case 10:
+		r = 1485;
+		break;
+	case 11:
+		r = 3375;
+		break;
+	case 12:
+	case 13:
+	case 20:
+		r = 8910;
+		break;
+	case 21:
+		r = 17820;
+		break;
+	case 22:
+	case 30:
+		r = 30375;
+		break;
+	case 31:
+		r = 67500;
+		break;
+	case 32:
+		r = 76800;
+		break;
+	case 40:
+	case 41:
+	case 42:
+		r = 122880;
+		break;
+	case 50:
+		r = 414000;
+		break;
+	case 51:
+	case 52:
+		r = 691200;
+		break;
+	default:
+		return 0;
+		}
+		size = (mb_width * mb_height +
+				(mb_width * mb_height / 2)) * 256 * 10;
+		r = (r * 1024 + size-1) / size;
+		r = min(r, 16);
+		/*pr_info("max_dpb %d size:%d\n", r, size);*/
+		return r;
+}
+static void vh264_set_params(struct work_struct *work)
+{
+	int aspect_ratio_info_present_flag, aspect_ratio_idc;
+	int max_dpb_size, actual_dpb_size, max_reference_size;
+	int i, mb_mv_byte, ret;
+	unsigned long addr;
+	unsigned int post_canvas, buf_size, endian;
+	unsigned int frame_mbs_only_flag;
+	unsigned int chroma_format_idc, chroma444, video_signal;
+	unsigned int crop_infor, crop_bottom, crop_right, level_idc;
+	if (!atomic_read(&vh264_active))
+		return;
+	mutex_lock(&vh264_mutex);
+	if (vh264_stream_switching_state == SWITCHING_STATE_ON_CMD1)
+		vh264_stream_switching_state = SWITCHING_STATE_ON_CMD1_PENDING;
+	post_canvas = get_post_canvas();
+	clk_adj_frame_count = 0;
+	/* set to max decoder clock rate at the beginning */
+
+	if (vdec_is_support_4k())
+		vdec_source_changed(VFORMAT_H264, 3840, 2160, 60);
+	else
+		vdec_source_changed(VFORMAT_H264, 1920, 1080, 29);
+
+	timing_info_present_flag = 0;
+	mb_width = READ_VREG(AV_SCRATCH_1);
+	seq_info = READ_VREG(AV_SCRATCH_2);
+	aspect_ratio_info = READ_VREG(AV_SCRATCH_3);
+	num_units_in_tick = READ_VREG(AV_SCRATCH_4);
+	time_scale = READ_VREG(AV_SCRATCH_5);
+	level_idc = READ_VREG(AV_SCRATCH_A);
+	if (level_idc > 0)
+		saved_idc_level = level_idc;
+	else if (saved_idc_level > 0)
+		level_idc = saved_idc_level;
+	video_signal = READ_VREG(AV_SCRATCH_H);
+	video_signal_from_vui =
+				((video_signal & 0xffff) << 8) |
+				((video_signal & 0xff0000) >> 16) |
+				((video_signal & 0x3f000000));
+/*
+ *	pr_info("video_signal_type_present_flag 0x%x\n",
+ *				(video_signal_from_vui >> 29) & 1);
+ *	pr_info("video_format  0x%x\n",
+ *				(video_signal_from_vui >> 26) & 7);
+ *	pr_info("video_full_range_flag  0x%x\n",
+ *				(video_signal_from_vui >> 25) & 1);
+ *	pr_info("color_description_present_flag  0x%x\n",
+ *				(video_signal_from_vui >> 24) & 1);
+ *	pr_info("color_primaries	0x%x\n",
+ *				(video_signal_from_vui >> 16) & 0xff);
+ *	pr_info("transfer_characteristic	0x%x\n",
+ *				(video_signal_from_vui >> 8) & 0xff);
+ *	pr_info("matrix_coefficient	0x%x\n",
+ *				video_signal_from_vui  & 0xff);
+ */
+
+	mb_total = (mb_width >> 8) & 0xffff;
+	max_reference_size = (mb_width >> 24) & 0x7f;
+	mb_mv_byte = (mb_width & 0x80000000) ? 24 : 96;
+	if (ucode_type == UCODE_IP_ONLY_PARAM)
+		mb_mv_byte = 96;
+	mb_width = mb_width & 0xff;
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) {
+		if (!mb_width && mb_total)
+			mb_width = 256;
+	}
+	if (mb_width)
+		mb_height = mb_total / mb_width;
+	last_duration = 0;
+	/* AV_SCRATCH_2
+	 *  bit 15: frame_mbs_only_flag
+	 *  bit 13-14: chroma_format_idc
+	 */
+	frame_mbs_only_flag = (seq_info >> 15) & 0x01;
+	chroma_format_idc = (seq_info >> 13) & 0x03;
+	chroma444 = (chroma_format_idc == 3) ? 1 : 0;
+
+	/* @AV_SCRATCH_6.31-16 =  (left  << 8 | right ) << 1
+	 *   @AV_SCRATCH_6.15-0   =  (top << 8  | bottom ) <<
+	 * (2 - frame_mbs_only_flag)
+	 */
+	crop_infor = READ_VREG(AV_SCRATCH_6);
+	crop_bottom = (crop_infor & 0xff) >> (2 - frame_mbs_only_flag);
+	crop_right = ((crop_infor >> 16) & 0xff) >> (2 - frame_mbs_only_flag);
+
+	/* if width or height from outside is not equal to mb, then use mb */
+	/* add: for seeking stream with other resolution */
+	if ((last_mb_width && (last_mb_width != mb_width))
+		|| (mb_width != ((frame_width + 15) >> 4)))
+		frame_width = 0;
+	if ((last_mb_height && (last_mb_height != mb_height))
+		|| (mb_height != ((frame_height + 15) >> 4)))
+		frame_height = 0;
+	last_mb_width = mb_width;
+	last_mb_height = mb_height;
+
+	if ((frame_width == 0) || (frame_height == 0) || crop_infor) {
+		frame_width = mb_width << 4;
+		frame_height = mb_height << 4;
+		if (frame_mbs_only_flag) {
+			frame_height =
+				frame_height - (2 >> chroma444) *
+				min(crop_bottom,
+					(unsigned int)((8 << chroma444) - 1));
+			frame_width =
+				frame_width - (2 >> chroma444) * min(crop_right,
+						(unsigned
+						 int)((8 << chroma444) - 1));
+		} else {
+			frame_height =
+				frame_height - (4 >> chroma444) *
+				min(crop_bottom,
+					(unsigned int)((8 << chroma444)
+							  - 1));
+			frame_width =
+				frame_width - (4 >> chroma444) * min(crop_right,
+						(unsigned
+						 int)((8 <<
+							   chroma444)
+							  - 1));
+		}
+#if 0
+		pr_info
+		("frame_mbs_only_flag %d, crop_bottom %d,  frame_height %d, ",
+		 frame_mbs_only_flag, crop_bottom, frame_height);
+		pr_info
+		("mb_height %d,crop_right %d, frame_width %d, mb_width %d\n",
+		 mb_height, crop_right, frame_width, mb_width);
+#endif
+		if (frame_height == 1088)
+			frame_height = 1080;
+	}
+
+	mb_width = (mb_width + 3) & 0xfffffffc;
+	mb_height = (mb_height + 3) & 0xfffffffc;
+	mb_total = mb_width * mb_height;
+
+	 /*max_reference_size <= max_dpb_size <= actual_dpb_size*/
+	 is_4k = (mb_total > 8160) ? true:false;
+
+
+	max_dpb_size = get_max_dpb_size(level_idc, mb_width, mb_height);
+	if (max_dpb_size < max_reference_size)
+		max_dpb_size = max_reference_size;
+	if (max_dpb_size > 15
+		&& get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB
+		&& (codec_mm_get_total_size() < 80 * SZ_1M)) {
+				actual_dpb_size
+				= max_reference_size + dpb_size_adj;
+			if (actual_dpb_size > VF_BUF_NUM)
+				actual_dpb_size = VF_BUF_NUM;
+	} else {
+		actual_dpb_size = max_dpb_size + dpb_size_adj;
+		actual_dpb_size = min(actual_dpb_size, VF_BUF_NUM);
+	}
+	max_reference_size++;
+	pr_info("actual_dpb_size %d max_dpb_size %d max_ref %d\n",
+				actual_dpb_size, max_dpb_size,
+				max_reference_size);
+	buf_size = mb_total * mb_mv_byte * max_reference_size;
+
+	ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, 1,
+		buf_size, DRIVER_NAME, &addr);
+
+	if (ret < 0) {
+		fatal_error_flag =
+			DECODER_FATAL_ERROR_NO_MEM;
+		vh264_running = 0;
+		mutex_unlock(&vh264_mutex);
+		return;
+	}
+
+	WRITE_VREG(AV_SCRATCH_1, addr);
+	WRITE_VREG(AV_SCRATCH_3, post_canvas);
+	WRITE_VREG(AV_SCRATCH_4, addr + buf_size);
+
+	if (!(READ_VREG(AV_SCRATCH_F) & 0x1)) {
+		for (i = 0; i < actual_dpb_size; i++) {
+#ifdef DOUBLE_WRITE
+				int page_count =
+				PAGE_ALIGN((mb_total << 8) + (mb_total
+						<< 7) +	(mb_total << 6) +
+						(mb_total << 5)) / PAGE_SIZE;
+#else
+				int page_count =
+					PAGE_ALIGN((mb_total << 8) +
+						(mb_total << 7)) / PAGE_SIZE;
+#endif
+
+			ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle,
+				VF_BUFFER_IDX(i),
+				page_count << PAGE_SHIFT,
+				DRIVER_NAME, &buffer_spec[i].phy_addr);
+
+			if (ret < 0) {
+				buffer_spec[i].alloc_count = 0;
+				fatal_error_flag =
+				DECODER_FATAL_ERROR_NO_MEM;
+				vh264_running = 0;
+				mutex_unlock(&vh264_mutex);
+				return;
+			}
+
+			addr = buffer_spec[i].phy_addr;
+			buffer_spec[i].alloc_count = page_count;
+
+			if (i <= 21) {
+				buffer_spec[i].y_addr = addr;
+				addr += mb_total << 8;
+				buffer_spec[i].u_addr = addr;
+				buffer_spec[i].v_addr = addr;
+				addr += mb_total << 7;
+				vfbuf_use[i] = 0;
+
+				buffer_spec[i].y_canvas_index = 128 + i * 2;
+				buffer_spec[i].u_canvas_index = 128 + i * 2 + 1;
+				buffer_spec[i].v_canvas_index = 128 + i * 2 + 1;
+
+				buffer_spec[i].y_canvas_width = mb_width << 4;
+				buffer_spec[i].y_canvas_height = mb_height << 4;
+				buffer_spec[i].u_canvas_width = mb_width << 4;
+				buffer_spec[i].u_canvas_height = mb_height << 4;
+				buffer_spec[i].v_canvas_width = mb_width << 4;
+				buffer_spec[i].v_canvas_height = mb_height << 4;
+
+				endian = (canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0;
+				config_cav_lut_ex(128 + i * 2,
+						buffer_spec[i].y_addr,
+						mb_width << 4, mb_height << 4,
+						CANVAS_ADDR_NOWRAP,
+						canvas_mode, endian, VDEC_1);
+				config_cav_lut_ex(128 + i * 2 + 1,
+						buffer_spec[i].u_addr,
+						mb_width << 4, mb_height << 3,
+						CANVAS_ADDR_NOWRAP,
+						canvas_mode, endian, VDEC_1);
+				WRITE_VREG(ANC0_CANVAS_ADDR + i,
+						spec2canvas(&buffer_spec[i]));
+				} else {
+				buffer_spec[i].y_canvas_index =
+					2 * (i - 21) + 4;
+				buffer_spec[i].y_addr = addr;
+				addr += mb_total << 8;
+				buffer_spec[i].u_canvas_index =
+					2 * (i - 21) + 5;
+				buffer_spec[i].v_canvas_index =
+					2 * (i - 21) + 5;
+				buffer_spec[i].u_addr = addr;
+				addr += mb_total << 7;
+				vfbuf_use[i] = 0;
+
+				buffer_spec[i].y_canvas_width = mb_width << 4;
+				buffer_spec[i].y_canvas_height = mb_height << 4;
+				buffer_spec[i].u_canvas_width = mb_width << 4;
+				buffer_spec[i].u_canvas_height = mb_height << 4;
+				buffer_spec[i].v_canvas_width = mb_width << 4;
+				buffer_spec[i].v_canvas_height = mb_height << 4;
+
+				spec_set_canvas(&buffer_spec[i]
+					, mb_width << 4, mb_height << 4);
+				WRITE_VREG(ANC0_CANVAS_ADDR + i
+					, spec2canvas(&buffer_spec[i]));
+			}
+		}
+		} else {
+			fatal_error_flag =
+					DECODER_FATAL_ERROR_NO_MEM;
+			vh264_running = 0;
+			mutex_unlock(&vh264_mutex);
+			pr_err("never be here!!\n");
+			return;
+		}
+
+	timing_info_present_flag = seq_info & 0x2;
+	fixed_frame_rate_flag = 0;
+	aspect_ratio_info_present_flag = seq_info & 0x1;
+	aspect_ratio_idc = (seq_info >> 16) & 0xff;
+
+	if (timing_info_present_flag) {
+		fixed_frame_rate_flag = seq_info & 0x40;
+
+		if (((num_units_in_tick * 120) >= time_scale
+			 && ((!sync_outside) || (!frame_dur))) &&
+				num_units_in_tick
+			&& time_scale) {
+			if (use_idr_framerate || !frame_dur
+				|| !duration_from_pts_done || vh264_running) {
+				u32 frame_dur_es =
+					div_u64(96000ULL * 2 *
+							num_units_in_tick,
+							time_scale);
+
+				/* hack to avoid use ES frame duration
+				 *   when it's half of the rate from
+				 *  system info
+				 */
+				/* sometimes the encoder is given a wrong
+				 * frame rate but the system side information
+				 *is more reliable
+				 */
+				if ((frame_dur * 2) != frame_dur_es) {
+					frame_dur = frame_dur_es;
+					if (fr_hint_status == VDEC_NEED_HINT) {
+						schedule_work(&notify_work);
+						fr_hint_status = VDEC_HINTED;
+					}
+				}
+			}
+		}
+	} else
+		pr_info("H.264: timing_info not present\n");
+
+	if (aspect_ratio_info_present_flag) {
+		if (aspect_ratio_idc == EXTEND_SAR) {
+			h264_ar =
+				div_u64(256ULL * (aspect_ratio_info >> 16) *
+						frame_height,
+						(aspect_ratio_info & 0xffff) *
+						frame_width);
+		} else {
+			/* pr_info("v264dec: aspect_ratio_idc = %d\n",
+			 *  aspect_ratio_idc);
+			 */
+
+			switch (aspect_ratio_idc) {
+			case 1:
+				h264_ar = 0x100 * frame_height / frame_width;
+				break;
+			case 2:
+				h264_ar = 0x100 * frame_height * 11 /
+					(frame_width * 12);
+				break;
+			case 3:
+				h264_ar = 0x100 * frame_height * 11 /
+					(frame_width * 10);
+				break;
+			case 4:
+				h264_ar = 0x100 * frame_height * 11 /
+					(frame_width * 16);
+				break;
+			case 5:
+				h264_ar = 0x100 * frame_height * 33 /
+					(frame_width * 40);
+				break;
+			case 6:
+				h264_ar = 0x100 * frame_height * 11 /
+					(frame_width * 24);
+				break;
+			case 7:
+				h264_ar = 0x100 * frame_height * 11 /
+					(frame_width * 20);
+				break;
+			case 8:
+				h264_ar = 0x100 * frame_height * 11 /
+					(frame_width * 32);
+				break;
+			case 9:
+				h264_ar = 0x100 * frame_height * 33 /
+					(frame_width * 80);
+				break;
+			case 10:
+				h264_ar = 0x100 * frame_height * 11 /
+					(frame_width * 18);
+				break;
+			case 11:
+				h264_ar = 0x100 * frame_height * 11 /
+					(frame_width * 15);
+				break;
+			case 12:
+				h264_ar = 0x100 * frame_height * 33 /
+					(frame_width * 64);
+				break;
+			case 13:
+				h264_ar = 0x100 * frame_height * 99 /
+					(frame_width * 160);
+				break;
+			case 14:
+				h264_ar = 0x100 * frame_height * 3 /
+					(frame_width * 4);
+				break;
+			case 15:
+				h264_ar = 0x100 * frame_height * 2 /
+					(frame_width * 3);
+				break;
+			case 16:
+				h264_ar = 0x100 * frame_height * 1 /
+					(frame_width * 2);
+				break;
+			default:
+				if (vh264_ratio >> 16) {
+					h264_ar = (frame_height *
+							(vh264_ratio & 0xffff) *
+							0x100 +
+							((vh264_ratio >> 16) *
+							 frame_width / 2)) /
+						((vh264_ratio >> 16) *
+						 frame_width);
+				} else {
+					h264_ar = frame_height * 0x100 /
+						frame_width;
+				}
+				break;
+			}
+		}
+	} else {
+		pr_info("v264dec: aspect_ratio not available from source\n");
+		if (vh264_ratio >> 16) {
+			/* high 16 bit is width, low 16 bit is height */
+			h264_ar =
+				((vh264_ratio & 0xffff) * frame_height * 0x100 +
+				 (vh264_ratio >> 16) * frame_width / 2) /
+				((vh264_ratio >> 16) * frame_width);
+		} else
+			h264_ar = frame_height * 0x100 / frame_width;
+	}
+
+	WRITE_VREG(AV_SCRATCH_0,
+			(max_reference_size << 24) | (actual_dpb_size << 16) |
+			(max_dpb_size << 8));
+	if (vh264_stream_switching_state != SWITCHING_STATE_OFF) {
+		vh264_stream_switching_state = SWITCHING_STATE_OFF;
+		pr_info("Leaving switching mode.\n");
+	}
+	mutex_unlock(&vh264_mutex);
+}
+
+static unsigned int pts_inc_by_duration(
+		unsigned int *new_pts, unsigned int *new_pts_rem)
+{
+	unsigned int r, rem;
+
+	r = last_pts + DUR2PTS(frame_dur);
+	rem = last_pts_remainder + DUR2PTS_REM(frame_dur);
+
+	if (rem >= 96) {
+		r++;
+		rem -= 96;
+	}
+
+	if (new_pts)
+		*new_pts = r;
+	if (new_pts_rem)
+		*new_pts_rem = rem;
+
+	return r;
+}
+static inline bool vh264_isr_parser(struct vframe_s *vf,
+		unsigned int  pts_valid, unsigned int buffer_index,
+		unsigned int pts)
+{
+	unsigned int pts_duration = 0;
+
+	if (h264_first_pts_ready == 0) {
+		if (pts_valid == 0) {
+			vfbuf_use[buffer_index]++;
+			vf->index = buffer_index;
+			kfifo_put(&recycle_q,
+					(const struct vframe_s *)vf);
+			return false;
+		}
+
+		h264pts1 = pts;
+		h264_pts_count = 0;
+		h264_first_pts_ready = 1;
+	} else {
+		if (pts < h264pts1) {
+			if (h264_pts_count > 24) {
+				pr_info("invalid h264pts1, reset\n");
+				h264pts1 = pts;
+				h264_pts_count = 0;
+			}
+		}
+		if (pts_valid && (pts > h264pts1) && (h264_pts_count > 24)
+				&& (duration_from_pts_done == 0)) {
+			unsigned int
+				old_duration = frame_dur;
+			h264pts2 = pts;
+
+			pts_duration = (h264pts2 - h264pts1) * 16 /
+				(h264_pts_count * 15);
+
+			if ((pts_duration != frame_dur)
+					&& (!pts_outside)) {
+				if (use_idr_framerate) {
+					bool pts_c_24 = close_to(pts_duration,
+						RATE_24_FPS,
+						RATE_CORRECTION_THRESHOLD);
+					bool frm_c_25 = close_to(frame_dur,
+						RATE_25_FPS,
+						RATE_CORRECTION_THRESHOLD);
+					bool pts_c_25 = close_to(pts_duration,
+						  RATE_25_FPS,
+						  RATE_CORRECTION_THRESHOLD);
+					bool frm_c_24 = close_to(frame_dur,
+						  RATE_24_FPS,
+						  RATE_CORRECTION_THRESHOLD);
+					if ((pts_c_24 && frm_c_25)
+						|| (pts_c_25 && frm_c_24)) {
+						pr_info
+						("H.264:Correct frame dur ");
+						pr_info
+						(" from %d to duration based ",
+							 frame_dur);
+						pr_info
+						("on PTS %d ---\n",
+							 pts_duration);
+						frame_dur = pts_duration;
+						duration_from_pts_done = 1;
+					} else if (((frame_dur < 96000 / 240)
+						&& (pts_duration > 96000 / 240))
+						|| (!duration_on_correcting &&
+						!frm_c_25 && !frm_c_24)) {
+						/* fft: if the frame rate is
+						 *  not regular, use the
+						 * calculate rate insteadof.
+						 */
+						pr_info
+						("H.264:Correct frame dur ");
+						pr_info
+						(" from %d to duration based ",
+							 frame_dur);
+						pr_info
+						("on PTS %d ---\n",
+							 pts_duration);
+						frame_dur = pts_duration;
+						duration_on_correcting = 1;
+					}
+				} else {
+					if (close_to(pts_duration,
+							frame_dur, 2000)) {
+						frame_dur = pts_duration;
+						pr_info
+						("used calculate frame rate,");
+						pr_info("on duration =%d\n",
+							 frame_dur);
+					} else {
+						pr_info
+						("don't use calculate frame ");
+						pr_info
+						("rate pts_duration =%d\n",
+							 pts_duration);
+					}
+				}
+			}
+
+			if (duration_from_pts_done == 0) {
+				if (close_to
+						(pts_duration,
+						 old_duration,
+						 RATE_CORRECTION_THRESHOLD)) {
+					pr_info
+					("finished correct frame dur");
+					pr_info
+					(" new=%d,old_duration=%d,cnt=%d\n",
+						 pts_duration,
+						 old_duration,
+						 h264_pts_count);
+					duration_from_pts_done = 1;
+				} else {	/*not the same,redo it. */
+					if (!close_to(pts_duration,
+						 old_duration, 1000) &&
+						!close_to(pts_duration,
+						frame_dur, 1000) &&
+						close_to(pts_duration,
+						last_duration, 200)) {
+						/* yangle: frame_dur must
+						 *  wrong,recover it.
+						 */
+						frame_dur = pts_duration;
+					}
+
+					pr_info
+					("restart correct frame duration ");
+					pr_info
+					("new=%d,old_duration=%d,cnt=%d\n",
+						 pts_duration,
+						 old_duration,
+						 h264_pts_count);
+					h264pts1 = h264pts2;
+					h264_pts_count = 0;
+					duration_from_pts_done = 0;
+			}
+		}
+		    last_duration = pts_duration;
+		}
+	}
+	return true;
+}
+
+static inline void h264_update_gvs(void)
+{
+	u32 ratio_control;
+	u32 ar;
+
+	if (gvs->frame_height != frame_height) {
+		gvs->frame_width = frame_width;
+		gvs->frame_height = frame_height;
+	}
+	if (gvs->frame_dur != frame_dur) {
+		gvs->frame_dur = frame_dur;
+		if (frame_dur != 0)
+			gvs->frame_rate = 96000 / frame_dur;
+		else
+			gvs->frame_rate = -1;
+	}
+	gvs->error_count = READ_VREG(AV_SCRATCH_D);
+	gvs->status = stat;
+	if (fatal_error_reset)
+		gvs->status |= fatal_error_flag;
+	ar = min_t(u32,
+			h264_ar,
+			DISP_RATIO_ASPECT_RATIO_MAX);
+	ratio_control =
+		ar << DISP_RATIO_ASPECT_RATIO_BIT;
+	gvs->ratio_control = ratio_control;
+}
+
+#ifdef HANDLE_H264_IRQ
+static irqreturn_t vh264_isr(int irq, void *dev_id)
+#else
+static void vh264_isr(void)
+#endif
+{
+	unsigned int buffer_index;
+	struct vframe_s *vf;
+	unsigned int cpu_cmd;
+	unsigned int pts, pts_lookup_save, pts_valid_save, pts_valid = 0;
+	unsigned int pts_us64_valid = 0;
+	unsigned int  framesize;
+	u64 pts_us64;
+	bool force_interlaced_frame = false;
+	unsigned int sei_itu35_flags;
+
+	static const unsigned int idr_num =
+		FIX_FRAME_RATE_CHECK_IDRFRAME_NUM;
+	static const unsigned int flg_1080_itl =
+		DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE;
+	static const unsigned int flg_576_itl =
+		DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE;
+
+	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+	if (0 == (stat & STAT_VDEC_RUN)) {
+		pr_info("decoder is not running\n");
+#ifdef HANDLE_H264_IRQ
+		return IRQ_HANDLED;
+#else
+		return;
+#endif
+	}
+
+	cpu_cmd = READ_VREG(AV_SCRATCH_0);
+
+#ifdef DROP_B_FRAME_FOR_1080P_50_60FPS
+	if ((frame_dur < 2004) &&
+		(frame_width >= 1400) &&
+		(frame_height >= 1000) && (last_interlaced == 0))
+		SET_VREG_MASK(AV_SCRATCH_F, 0x8);
+#endif
+	if ((decoder_force_reset == 1)
+			|| ((error_recovery_mode != 1)
+			&& (no_idr_error_count >= no_idr_error_max)
+			&& (ucode_type != UCODE_IP_ONLY_PARAM))) {
+		vh264_running = 0;
+		pr_info("force reset decoder  %d!!!\n", no_idr_error_count);
+		schedule_work(&error_wd_work);
+		decoder_force_reset = 0;
+		no_idr_error_count = 0;
+	} else if ((cpu_cmd & 0xff) == 1) {
+		if (unlikely
+			(vh264_running
+			 && (kfifo_len(&newframe_q) != VF_POOL_SIZE))) {
+			/* a cmd 1 sent during decoding w/o getting a cmd 3. */
+			/* should not happen but the original code has such
+			 *  case, do the same process
+			 */
+			if ((READ_VREG(AV_SCRATCH_1) & 0xff)
+				== 1) {/*invalid mb_width*/
+				vh264_running = 0;
+				fatal_error_flag = DECODER_FATAL_ERROR_UNKNOWN;
+			/* this is fatal error, need restart */
+				pr_info("cmd 1 fatal error happened\n");
+				schedule_work(&error_wd_work);
+			} else {
+			vh264_stream_switching_state = SWITCHING_STATE_ON_CMD1;
+			pr_info("Enter switching mode cmd1.\n");
+			schedule_work(&stream_switching_work);
+			}
+			return IRQ_HANDLED;
+		}
+		pr_info("Enter set parameter cmd1.\n");
+		schedule_work(&set_parameter_work);
+		return IRQ_HANDLED;
+	} else if ((cpu_cmd & 0xff) == 2) {
+		int frame_mb_only, pic_struct_present, pic_struct, prog_frame,
+			poc_sel, idr_flag, eos, error;
+		int i, status, num_frame, b_offset;
+		int current_error_count, slice_type;
+
+		vh264_running = 1;
+		vh264_no_disp_count = 0;
+		num_frame = (cpu_cmd >> 8) & 0xff;
+		frame_mb_only = seq_info & 0x8000;
+		pic_struct_present = seq_info & 0x10;
+
+		current_error_count = READ_VREG(AV_SCRATCH_D);
+		if (vh264_error_count != current_error_count) {
+			/* pr_info("decoder error happened, count %d\n",
+			 *   current_error_count);
+			 */
+			vh264_error_count = current_error_count;
+		}
+
+		for (i = 0; (i < num_frame) && (!vh264_eos); i++) {
+			status = READ_VREG(AV_SCRATCH_1 + i);
+			buffer_index = status & 0x1f;
+			error = status & 0x200;
+			slice_type = (READ_VREG(AV_SCRATCH_H) >> (i * 4)) & 0xf;
+
+			if ((error_recovery_mode_use & 2) && error)
+				check_pts_discontinue = true;
+			if (ucode_type == UCODE_IP_ONLY_PARAM
+				&& iponly_early_mode)
+				continue;
+			if ((p_last_vf != NULL)
+				&& (p_last_vf->index == buffer_index))
+				continue;
+
+			if (buffer_index >= VF_BUF_NUM)
+				continue;
+
+			pic_struct = (status >> 5) & 0x7;
+			prog_frame = status & 0x100;
+			poc_sel = status & 0x200;
+			idr_flag = status & 0x400;
+			frame_packing_type = (status >> 12) & 0x7;
+			eos = (status >> 15) & 1;
+
+			if (eos)
+				vh264_eos = 1;
+
+			b_offset = (status >> 16) & 0xffff;
+
+			if (error)
+				no_idr_error_count++;
+			if (idr_flag ||
+				(!error && (slice_type != SLICE_TYPE_I)))
+				no_idr_error_count = 0;
+
+			if (decoder_debug_flag) {
+				pr_info
+				("slice_type %x idr %x error %x count %d",
+					slice_type, idr_flag, error,
+					no_idr_error_count);
+				pr_info(" prog %x pic_struct %x offset %x\n",
+				prog_frame, pic_struct,	b_offset);
+			}
+#ifdef DROP_B_FRAME_FOR_1080P_50_60FPS
+			last_interlaced = prog_frame ? 0 : 1;
+#endif
+			if (kfifo_get(&newframe_q, &vf) == 0) {
+				pr_info
+				("fatal error, no available buffer slot.");
+				return IRQ_HANDLED;
+			}
+
+			if (clk_adj_frame_count < (VDEC_CLOCK_ADJUST_FRAME + 1))
+				clk_adj_frame_count++;
+
+			set_frame_info(vf);
+
+			switch (i) {
+			case 0:
+				b_offset |=
+					(READ_VREG(AV_SCRATCH_A) & 0xffff)
+					<< 16;
+				break;
+			case 1:
+				b_offset |=
+					READ_VREG(AV_SCRATCH_A) & 0xffff0000;
+				break;
+			case 2:
+				b_offset |=
+					(READ_VREG(AV_SCRATCH_B) & 0xffff)
+					<< 16;
+				break;
+			case 3:
+				b_offset |=
+					READ_VREG(AV_SCRATCH_B) & 0xffff0000;
+				break;
+			case 4:
+				b_offset |=
+					(READ_VREG(AV_SCRATCH_C) & 0xffff)
+					<< 16;
+				break;
+			case 5:
+				b_offset |=
+					READ_VREG(AV_SCRATCH_C) & 0xffff0000;
+				break;
+			default:
+				break;
+			}
+
+			if (error)
+				gvs->drop_frame_count++;
+
+			/* add 64bit pts us ; */
+			if (unlikely
+				((b_offset == first_offset)
+				 && (first_pts_cached))) {
+				pts = first_pts;
+				pts_us64 = first_pts64;
+				framesize = first_frame_size;
+				first_pts_cached = false;
+				pts_valid = 1;
+				pts_us64_valid = 1;
+#ifdef DEBUG_PTS
+				pts_hit++;
+#endif
+			} else if (pts_lookup_offset_us64
+					(PTS_TYPE_VIDEO, b_offset, &pts,
+					&framesize, 0, &pts_us64) == 0) {
+				pts_valid = 1;
+				pts_us64_valid = 1;
+#ifdef DEBUG_PTS
+				pts_hit++;
+#endif
+			} else {
+				pts_valid = 0;
+				pts_us64_valid = 0;
+				framesize = 0;
+#ifdef DEBUG_PTS
+				pts_missed++;
+#endif
+			}
+
+			if (idr_flag)
+				s_vframe_qos.type = 4;
+			else if (slice_type == SLICE_TYPE_I)
+				s_vframe_qos.type = 1;
+			else if (slice_type == SLICE_TYPE_P)
+				s_vframe_qos.type = 2;
+			else if (slice_type == SLICE_TYPE_B || slice_type == 8)
+				s_vframe_qos.type = 3;
+
+			s_vframe_qos.size = framesize;
+
+			if (pts_valid)
+				s_vframe_qos.pts = pts;
+			else
+				s_vframe_qos.pts = last_pts + DUR2PTS(frame_dur);
+#ifndef ENABLE_SEI_ITU_T35
+			if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) {
+				u32 reg_data;
+				if (i) {
+					reg_data = READ_VREG(AV_SCRATCH_N);
+					s_vframe_qos.max_mv
+						= (reg_data >> 16) & 0xffff;
+					s_vframe_qos.avg_mv
+						= (reg_data >> 8) & 0xff;
+					s_vframe_qos.min_mv
+						=  reg_data & 0xff;
+					reg_data = READ_VREG(AV_SCRATCH_L);
+					s_vframe_qos.max_qp
+						= (reg_data >> 16) & 0xff;
+					s_vframe_qos.avg_qp
+						= (reg_data >> 8) & 0xff;
+					s_vframe_qos.min_qp
+						=  reg_data & 0xff;
+					reg_data = READ_VREG(AV_SCRATCH_M);
+					s_vframe_qos.max_skip
+						= (reg_data >> 16) & 0xff;
+					s_vframe_qos.avg_skip
+						= (reg_data >> 8) & 0xff;
+					s_vframe_qos.min_skip
+						=  reg_data & 0xff;
+				} else {
+					reg_data = READ_VREG(AV_SCRATCH_J);
+					s_vframe_qos.max_mv
+						= (reg_data >> 16) & 0xffff;
+					s_vframe_qos.avg_mv
+						= (reg_data >> 8) & 0xff;
+					s_vframe_qos.min_mv
+						=  reg_data & 0xff;
+					reg_data = READ_VREG(AV_SCRATCH_I);
+					s_vframe_qos.max_qp
+						= (reg_data >> 16) & 0xff;
+					s_vframe_qos.avg_qp
+						= (reg_data >> 8) & 0xff;
+					s_vframe_qos.min_qp
+						=  reg_data & 0xff;
+					reg_data = READ_VREG(AV_SCRATCH_K);
+					s_vframe_qos.max_skip
+						= (reg_data >> 16) & 0xff;
+					s_vframe_qos.avg_skip
+						= (reg_data >> 8) & 0xff;
+					s_vframe_qos.min_skip
+						=  reg_data & 0xff;
+				}
+				if (decoder_debug_flag&0x2) {
+					pr_info("max_mv %d    avg_mv %d  min_mv %d slice_type %d offset %x   i =  %d\n",
+						s_vframe_qos.max_mv,
+						s_vframe_qos.avg_mv,
+						s_vframe_qos.min_mv,
+						slice_type,
+						b_offset,
+						i);
+					pr_info("max_qp %d    avg_qp %d  min_qp %d\n",
+						s_vframe_qos.max_qp,
+						s_vframe_qos.avg_qp,
+						s_vframe_qos.min_qp);
+					pr_info("max_skip %d  avg_skip %d  min_skip %d\n",
+						s_vframe_qos.max_skip,
+						s_vframe_qos.avg_skip,
+						s_vframe_qos.min_skip);
+				}
+			} else
+				search_qos_node(&s_vframe_qos, b_offset);
+#endif
+			frame_count++;
+
+			s_vframe_qos.num = frame_count;
+			//vdec_fill_frame_info(&s_vframe_qos, 1);
+
+			/* on second IDR frame,check the diff between pts
+			 *  compute from duration and pts from lookup ,
+			 * if large than frame_dur,we think it is uncorrect.
+			 */
+			pts_lookup_save = pts;
+			pts_valid_save = pts_valid;
+			if (fixed_frame_rate_flag
+				&& (fixed_frame_rate_check_count <=
+					idr_num)) {
+				if (idr_flag && pts_valid) {
+					fixed_frame_rate_check_count++;
+					/* pr_info("diff:%d\n",
+					 *   last_pts - pts_lookup_save);
+					 */
+					if ((fixed_frame_rate_check_count ==
+						idr_num) &&
+						(abs(pts - (last_pts +
+							 DUR2PTS(frame_dur))) >
+							 DUR2PTS(frame_dur))) {
+						fixed_frame_rate_flag = 0;
+						pr_info("pts sync mode play\n");
+					}
+
+					if (fixed_frame_rate_flag
+						&& (fixed_frame_rate_check_count
+							> idr_num)) {
+						pr_info
+						("fix_frame_rate mode play\n");
+					}
+				}
+			}
+
+			if (READ_VREG(AV_SCRATCH_F) & 2) {
+				/* for I only mode, ignore the PTS information
+				 *   and only uses frame duration for each I
+				 *  frame decoded
+				 */
+				if (p_last_vf)
+					pts_valid = 0;
+				/* also skip frame duration calculation
+				 *  based on PTS
+				 */
+				duration_from_pts_done = 1;
+				/* and add a default duration for 1/30 second
+				 *  if there is no valid frame
+				 * duration available
+				 */
+				if (frame_dur == 0)
+					frame_dur = 96000 / 30;
+			}
+
+			if (sync_outside == 0) {
+				if (!vh264_isr_parser(vf,
+						pts_valid, buffer_index, pts))
+					continue;
+
+				h264_pts_count++;
+			} else {
+				if (!idr_flag)
+					pts_valid = 0;
+			}
+
+			if (pts_valid && !pts_discontinue) {
+				pts_discontinue =
+					(abs(last_pts - pts) >=
+					 tsync_vpts_discontinuity_margin());
+			}
+			/* if use_idr_framerate or fixed frame rate, only
+			 *  use PTS for IDR frames except for pts discontinue
+			 */
+			if (timing_info_present_flag &&
+				frame_dur &&
+				(use_idr_framerate ||
+				 (fixed_frame_rate_flag != 0))
+				&& pts_valid && h264_first_valid_pts_ready
+				&& (!pts_discontinue)) {
+				pts_valid =
+					(slice_type == SLICE_TYPE_I) ? 1 : 0;
+			}
+
+			if (!h264_first_valid_pts_ready && pts_valid) {
+				h264_first_valid_pts_ready = true;
+				last_pts = pts - DUR2PTS(frame_dur);
+				last_pts_remainder = 0;
+			}
+			/* calculate PTS of next frame and smooth
+			 *  PTS for fixed rate source
+			 */
+			if (pts_valid) {
+				if ((fixed_frame_rate_flag) &&
+					(!pts_discontinue) &&
+					(abs(pts_inc_by_duration(NULL, NULL)
+					     - pts)
+					 < DUR2PTS(frame_dur))) {
+					pts = pts_inc_by_duration(&pts,
+							&last_pts_remainder);
+				} else
+					last_pts_remainder = 0;
+
+			} else {
+				if (fixed_frame_rate_flag && !pts_discontinue &&
+				(fixed_frame_rate_check_count > idr_num) &&
+				pts_valid_save && (sync_outside == 0) &&
+				(abs(pts_inc_by_duration(NULL, NULL) - pts)
+				 > DUR2PTS(frame_dur))) {
+					duration_from_pts_done = 0;
+					pr_info("recalc frame_dur\n");
+				} else
+					pts = pts_inc_by_duration(&pts,
+						&last_pts_remainder);
+				pts_valid = 1;
+			}
+
+			if ((dec_control &
+				 flg_1080_itl)
+				&& (frame_width == 1920)
+				&& (frame_height >= 1080)
+				&& (vf->duration == 3203))
+				force_interlaced_frame = true;
+			else if ((dec_control &
+					  flg_576_itl)
+					 && (frame_width == 720)
+					 && (frame_height == 576)
+					 && (vf->duration == 3840))
+				force_interlaced_frame = true;
+
+			/* for frames with PTS, check if there is PTS
+			 *  discontinue based on previous frames
+			 * (including error frames),
+			 * force no VPTS discontinue reporting if we saw
+			 *errors earlier but only once.
+			 */
+
+			/*count info*/
+			h264_update_gvs();
+			vdec_count_info(gvs, error, b_offset);
+			vdec_fill_vdec_frame(vdec_h264, &s_vframe_qos, gvs, vf, 0);
+
+			if ((pts_valid) && (check_pts_discontinue)
+					&& (!error)) {
+				if (pts_discontinue) {
+					vf->flag = 0;
+					check_pts_discontinue = false;
+				} else if ((pts - last_pts) < 90000) {
+					vf->flag = VFRAME_FLAG_NO_DISCONTINUE;
+					check_pts_discontinue = false;
+				}
+			}
+
+			last_pts = pts;
+
+			if (fixed_frame_rate_flag
+				&& (fixed_frame_rate_check_count <=
+					idr_num)
+				&& (sync_outside == 0)
+				&& pts_valid_save)
+				pts = pts_lookup_save;
+
+			if (pic_struct_present) {
+				if ((pic_struct == PIC_TOP_BOT)
+					|| (pic_struct == PIC_BOT_TOP))
+					prog_frame = 0;
+			}
+
+			if ((!force_interlaced_frame)
+				&& (prog_frame
+					|| (pic_struct_present
+						&& pic_struct
+						<= PIC_TRIPLE_FRAME))) {
+				if (pic_struct_present) {
+					if (pic_struct == PIC_TOP_BOT_TOP
+						|| pic_struct
+						== PIC_BOT_TOP_BOT) {
+						vf->duration +=
+							vf->duration >> 1;
+					} else if (pic_struct ==
+							   PIC_DOUBLE_FRAME)
+						vf->duration += vf->duration;
+					else if (pic_struct ==
+							 PIC_TRIPLE_FRAME) {
+						vf->duration +=
+							vf->duration << 1;
+					}
+				}
+
+				last_pts =
+					last_pts + DUR2PTS(vf->duration -
+							frame_dur);
+
+				vf->index = buffer_index;
+				vf->type =
+					VIDTYPE_PROGRESSIVE |
+					VIDTYPE_VIU_FIELD |
+					VIDTYPE_VIU_NV21;
+				vf->duration_pulldown = 0;
+				vf->signal_type = video_signal_from_vui;
+				vf->index = buffer_index;
+				vf->pts = (pts_valid) ? pts : 0;
+				if (pts_us64_valid == 1)
+					vf->pts_us64 = pts_us64;
+				else
+				vf->pts_us64 = div64_u64(((u64)vf->pts)*100, 9);
+				vf->canvas0Addr = vf->canvas1Addr =
+					spec2canvas(&buffer_spec[buffer_index]);
+				vf->type_original = vf->type;
+				vfbuf_use[buffer_index]++;
+				vf->mem_handle =
+					decoder_bmmu_box_get_mem_handle(
+						mm_blk_handle,
+						VF_BUFFER_IDX(buffer_index));
+				decoder_do_frame_check(NULL, vf);
+				if ((error_recovery_mode_use & 2) && error) {
+					kfifo_put(&recycle_q,
+						(const struct vframe_s *)vf);
+				} else {
+					p_last_vf = vf;
+					pts_discontinue = false;
+					kfifo_put(&delay_display_q,
+						  (const struct vframe_s *)vf);
+				}
+			} else {
+				if (pic_struct_present
+					&& pic_struct == PIC_TOP_BOT)
+					vf->type = VIDTYPE_INTERLACE_TOP;
+				else if (pic_struct_present
+						 && pic_struct == PIC_BOT_TOP)
+					vf->type = VIDTYPE_INTERLACE_BOTTOM;
+				else {
+					vf->type =
+						poc_sel ?
+						VIDTYPE_INTERLACE_BOTTOM :
+						VIDTYPE_INTERLACE_TOP;
+				}
+				vf->type |= VIDTYPE_VIU_NV21;
+				vf->type |= VIDTYPE_INTERLACE_FIRST;
+
+				high_bandwidth |=
+				((codec_mm_get_total_size() < 80 * SZ_1M)
+				& ((READ_VREG(AV_SCRATCH_N) & 0xf) == 3)
+				& ((frame_width * frame_height) >= 1920*1080));
+				if (high_bandwidth)
+					vf->flag |= VFRAME_FLAG_HIGH_BANDWIDTH;
+
+				vf->duration >>= 1;
+				vf->duration_pulldown = 0;
+				vf->signal_type = video_signal_from_vui;
+				vf->index = buffer_index;
+				vf->pts = (pts_valid) ? pts : 0;
+				if (pts_us64_valid == 1)
+					vf->pts_us64 = pts_us64;
+				else
+				vf->pts_us64 = div64_u64(((u64)vf->pts)*100, 9);
+				vf->canvas0Addr = vf->canvas1Addr =
+					spec2canvas(&buffer_spec[buffer_index]);
+				vf->type_original = vf->type;
+				vfbuf_use[buffer_index]++;
+				vf->ready_jiffies64 = jiffies_64;
+				vf->mem_handle =
+					decoder_bmmu_box_get_mem_handle(
+						mm_blk_handle,
+						VF_BUFFER_IDX(buffer_index));
+				decoder_do_frame_check(NULL, vf);
+				if ((error_recovery_mode_use & 2) && error) {
+					kfifo_put(&recycle_q,
+						(const struct vframe_s *)vf);
+					continue;
+				} else {
+					pts_discontinue = false;
+					kfifo_put(&delay_display_q,
+						(const struct vframe_s *)vf);
+				}
+
+				if (READ_VREG(AV_SCRATCH_F) & 2)
+					continue;
+
+				if (kfifo_get(&newframe_q, &vf) == 0) {
+					pr_info
+					("fatal error, no avail buffer slot.");
+					return IRQ_HANDLED;
+				}
+
+				set_frame_info(vf);
+
+				if (pic_struct_present
+					&& pic_struct == PIC_TOP_BOT)
+					vf->type = VIDTYPE_INTERLACE_BOTTOM;
+				else if (pic_struct_present
+						 && pic_struct == PIC_BOT_TOP)
+					vf->type = VIDTYPE_INTERLACE_TOP;
+				else {
+					vf->type =
+						poc_sel ?
+						VIDTYPE_INTERLACE_TOP :
+						VIDTYPE_INTERLACE_BOTTOM;
+				}
+
+				vf->type |= VIDTYPE_VIU_NV21;
+				vf->duration >>= 1;
+				vf->duration_pulldown = 0;
+				vf->signal_type = video_signal_from_vui;
+				vf->index = buffer_index;
+				vf->pts = 0;
+				vf->pts_us64 = 0;
+				vf->canvas0Addr = vf->canvas1Addr =
+					spec2canvas(&buffer_spec[buffer_index]);
+				vf->type_original = vf->type;
+				vfbuf_use[buffer_index]++;
+				if (high_bandwidth)
+					vf->flag |= VFRAME_FLAG_HIGH_BANDWIDTH;
+
+				p_last_vf = vf;
+				vf->ready_jiffies64 = jiffies_64;
+				vf->mem_handle =
+					decoder_bmmu_box_get_mem_handle(
+						mm_blk_handle,
+						VF_BUFFER_IDX(buffer_index));
+				kfifo_put(&delay_display_q,
+						(const struct vframe_s *)vf);
+			}
+		}
+
+		WRITE_VREG(AV_SCRATCH_0, 0);
+	} else if ((cpu_cmd & 0xff) == 3) {
+		vh264_running = 1;
+		vh264_stream_switching_state = SWITCHING_STATE_ON_CMD3;
+
+		pr_info("Enter switching mode cmd3.\n");
+		schedule_work(&stream_switching_work);
+
+	} else if ((cpu_cmd & 0xff) == 4) {
+		vh264_running = 1;
+		/* reserved for slice group */
+		WRITE_VREG(AV_SCRATCH_0, 0);
+	} else if ((cpu_cmd & 0xff) == 5) {
+		vh264_running = 1;
+		/* reserved for slice group */
+		WRITE_VREG(AV_SCRATCH_0, 0);
+	} else if ((cpu_cmd & 0xff) == 6) {
+		vh264_running = 0;
+		fatal_error_flag = DECODER_FATAL_ERROR_UNKNOWN;
+		/* this is fatal error, need restart */
+		pr_info("fatal error happend\n");
+		amvdec_stop();
+		if (!fatal_error_reset)
+			schedule_work(&error_wd_work);
+	} else if ((cpu_cmd & 0xff) == 7) {
+		vh264_running = 0;
+		frame_width = (READ_VREG(AV_SCRATCH_1) + 1) * 16;
+		pr_info("Over decoder supported size, width = %d\n",
+			   frame_width);
+		fatal_error_flag = DECODER_FATAL_ERROR_SIZE_OVERFLOW;
+	} else if ((cpu_cmd & 0xff) == 8) {
+		vh264_running = 0;
+		frame_height = (READ_VREG(AV_SCRATCH_1) + 1) * 16;
+		pr_info("Over decoder supported size, height = %d\n",
+			   frame_height);
+		fatal_error_flag = DECODER_FATAL_ERROR_SIZE_OVERFLOW;
+	} else if ((cpu_cmd & 0xff) == 9) {
+		first_offset = READ_VREG(AV_SCRATCH_1);
+		if (pts_lookup_offset_us64
+			(PTS_TYPE_VIDEO, first_offset, &first_pts,
+			&first_frame_size, 0,
+			 &first_pts64) == 0)
+			first_pts_cached = true;
+		WRITE_VREG(AV_SCRATCH_0, 0);
+	} else if ((cpu_cmd & 0xff) == 0xa) {
+		int b_offset;
+		unsigned int frame_size;
+
+		b_offset = READ_VREG(AV_SCRATCH_2);
+		buffer_index = READ_VREG(AV_SCRATCH_1);
+		/*pr_info("iponly output %d  b_offset %x\n",
+		 *	buffer_index,b_offset);
+		 */
+		if (kfifo_get(&newframe_q, &vf) == 0) {
+			WRITE_VREG(AV_SCRATCH_0, 0);
+			pr_info
+			("fatal error, no available buffer slot.");
+			return IRQ_HANDLED;
+		}
+		if (pts_lookup_offset_us64 (PTS_TYPE_VIDEO, b_offset,
+				&pts, &frame_size,
+				0, &pts_us64) != 0)
+			vf->pts_us64 = vf->pts = 0;
+		else {
+			vf->pts_us64 = pts_us64;
+			vf->pts = pts;
+		}
+		set_frame_info(vf);
+		vf->type = VIDTYPE_PROGRESSIVE |
+				VIDTYPE_VIU_FIELD |
+				VIDTYPE_VIU_NV21;
+		vf->duration_pulldown = 0;
+		vf->signal_type = video_signal_from_vui;
+		vf->index = buffer_index;
+		vf->canvas0Addr = vf->canvas1Addr =
+				spec2canvas(&buffer_spec[buffer_index]);
+		vf->type_original = vf->type;
+		vf->mem_handle = decoder_bmmu_box_get_mem_handle(
+			mm_blk_handle,
+					VF_BUFFER_IDX(buffer_index));
+		vfbuf_use[buffer_index]++;
+		p_last_vf = vf;
+		pts_discontinue = false;
+		iponly_early_mode = 1;
+		decoder_do_frame_check(NULL, vf);
+		kfifo_put(&delay_display_q,
+			(const struct vframe_s *)vf);
+		WRITE_VREG(AV_SCRATCH_0, 0);
+	} else if ((cpu_cmd & 0xff) == 0xB) {
+		schedule_work(&qos_work);
+	}
+
+	sei_itu35_flags = READ_VREG(AV_SCRATCH_J);
+	if (sei_itu35_flags & (1 << 15)) {	/* data ready */
+#ifdef ENABLE_SEI_ITU_T35
+		schedule_work(&userdata_push_work);
+#else
+		/* necessary if enabled itu_t35 in ucode*/
+		WRITE_VREG(AV_SCRATCH_J, 0);
+#endif
+	}
+
+#ifdef HANDLE_H264_IRQ
+	return IRQ_HANDLED;
+#else
+	return;
+#endif
+}
+
+static void vh264_set_clk(struct work_struct *work)
+{
+		int fps = 96000 / frame_dur;
+
+		if (frame_dur < 10) /*dur is too small ,think it errors fps*/
+			fps = 60;
+		saved_resolution = frame_width * frame_height * fps;
+		vdec_source_changed(VFORMAT_H264,
+			frame_width, frame_height, fps);
+}
+
+static void vh264_put_timer_func(struct timer_list *timer)
+{
+	unsigned int wait_buffer_status;
+	unsigned int wait_i_pass_frames;
+	unsigned int reg_val;
+
+	enum receviver_start_e state = RECEIVER_INACTIVE;
+
+	if (vh264_reset) {
+		pr_info("operation forbidden in timer !\n");
+		goto exit;
+	}
+
+	prepare_display_q();
+
+	if (vf_get_receiver(PROVIDER_NAME)) {
+		state =
+			vf_notify_receiver(PROVIDER_NAME,
+					VFRAME_EVENT_PROVIDER_QUREY_STATE,
+					NULL);
+		if ((state == RECEIVER_STATE_NULL)
+			|| (state == RECEIVER_STATE_NONE)) {
+			/* receiver has no event_cb or receiver's
+			 *  event_cb does not process this event
+			 */
+			state = RECEIVER_INACTIVE;
+		}
+	} else
+		state = RECEIVER_INACTIVE;
+#ifndef HANDLE_H264_IRQ
+	vh264_isr();
+#endif
+
+	if (vh264_stream_switching_state != SWITCHING_STATE_OFF)
+		wait_buffer_counter = 0;
+	else {
+		reg_val = READ_VREG(AV_SCRATCH_9);
+		wait_buffer_status = reg_val & (1 << 31);
+		wait_i_pass_frames = reg_val & 0xff;
+		if (wait_buffer_status) {
+			if (kfifo_is_empty(&display_q) &&
+				kfifo_is_empty(&delay_display_q) &&
+				kfifo_is_empty(&recycle_q) &&
+				(state == RECEIVER_INACTIVE)) {
+				pr_info("$$$$decoder is waiting for buffer\n");
+				if (++wait_buffer_counter > 4) {
+					amvdec_stop();
+					schedule_work(&error_wd_work);
+				}
+			} else
+				wait_buffer_counter = 0;
+		} else if (wait_i_pass_frames > 1000) {
+			pr_info("i passed frames > 1000\n");
+			amvdec_stop();
+			schedule_work(&error_wd_work);
+		}
+	}
+
+#if 0
+	if (!wait_buffer_status) {
+		if (vh264_no_disp_count++ > NO_DISP_WD_COUNT) {
+			pr_info("$$$decoder did not send frame out\n");
+			amvdec_stop();
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+			vh264_ppmgr_reset();
+#else
+			vf_light_unreg_provider(PROVIDER_NAME);
+			vh264_local_init();
+			vf_reg_provider(vh264_vf_prov);
+#endif
+			vh264_prot_init();
+			amvdec_start();
+
+			vh264_no_disp_count = 0;
+			vh264_no_disp_wd_count++;
+		}
+	}
+#endif
+
+	while (!kfifo_is_empty(&recycle_q) &&
+		   ((READ_VREG(AV_SCRATCH_7) == 0)
+			|| (READ_VREG(AV_SCRATCH_8) == 0))
+		   && (vh264_stream_switching_state == SWITCHING_STATE_OFF)) {
+		struct vframe_s *vf;
+
+		if (kfifo_get(&recycle_q, &vf)) {
+			if (vf->index < VF_BUF_NUM) {
+				if (--vfbuf_use[vf->index] == 0) {
+					if (READ_VREG(AV_SCRATCH_7) == 0) {
+						WRITE_VREG(AV_SCRATCH_7,
+								vf->index + 1);
+					} else {
+						WRITE_VREG(AV_SCRATCH_8,
+								vf->index + 1);
+					}
+				}
+
+				vf->index = VF_BUF_NUM;
+				kfifo_put(&newframe_q,
+						(const struct vframe_s *)vf);
+			}
+		}
+	}
+
+	if (vh264_stream_switching_state != SWITCHING_STATE_OFF) {
+		while (!kfifo_is_empty(&recycle_q)) {
+			struct vframe_s *vf;
+
+			if (kfifo_get(&recycle_q, &vf)) {
+				if (vf->index < VF_BUF_NUM) {
+					vf->index = VF_BUF_NUM;
+					kfifo_put(&newframe_q,
+						(const struct vframe_s *)vf);
+				}
+			}
+		}
+
+		WRITE_VREG(AV_SCRATCH_7, 0);
+		WRITE_VREG(AV_SCRATCH_8, 0);
+
+		if (kfifo_len(&newframe_q) == VF_POOL_SIZE)
+			stream_switching_done();
+	}
+
+	if (ucode_type != UCODE_IP_ONLY_PARAM &&
+		(clk_adj_frame_count > VDEC_CLOCK_ADJUST_FRAME) &&
+		frame_dur > 0 && saved_resolution !=
+		frame_width * frame_height * (96000 / frame_dur))
+		schedule_work(&set_clk_work);
+
+exit:
+	timer->expires = jiffies + PUT_INTERVAL;
+
+	add_timer(timer);
+}
+
+int vh264_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
+{
+	u32 ratio_control;
+	u32 ar;
+
+	if (!(stat & STAT_VDEC_RUN))
+		return -1;
+
+	vstatus->frame_width = frame_width;
+	vstatus->frame_height = frame_height;
+	if (frame_dur != 0)
+		vstatus->frame_rate = 96000 / frame_dur;
+	else
+		vstatus->frame_rate = -1;
+	vstatus->error_count = READ_VREG(AV_SCRATCH_D);
+	vstatus->status = stat;
+	if (fatal_error_reset)
+		vstatus->status |= fatal_error_flag;
+	vstatus->bit_rate = gvs->bit_rate;
+	vstatus->frame_dur = frame_dur;
+	vstatus->frame_data = gvs->frame_data;
+	vstatus->total_data = gvs->total_data;
+	vstatus->frame_count = gvs->frame_count;
+	vstatus->error_frame_count = gvs->error_frame_count;
+	vstatus->drop_frame_count = gvs->drop_frame_count;
+	vstatus->total_data = gvs->total_data;
+	vstatus->samp_cnt = gvs->samp_cnt;
+	vstatus->offset = gvs->offset;
+	ar = min_t(u32,
+			h264_ar,
+			DISP_RATIO_ASPECT_RATIO_MAX);
+	ratio_control =
+		ar << DISP_RATIO_ASPECT_RATIO_BIT;
+	vstatus->ratio_control = ratio_control;
+
+	snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
+		"%s", DRIVER_NAME);
+
+	return 0;
+}
+
+static int vh264_vdec_info_init(void)
+{
+	gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL);
+	if (NULL == gvs) {
+		pr_info("the struct of vdec status malloc failed.\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+int vh264_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
+{
+	if (trickmode == TRICKMODE_I) {
+		WRITE_VREG(AV_SCRATCH_F,
+				   (READ_VREG(AV_SCRATCH_F) & 0xfffffffc) | 2);
+		trickmode_i = 1;
+	} else if (trickmode == TRICKMODE_NONE) {
+		WRITE_VREG(AV_SCRATCH_F, READ_VREG(AV_SCRATCH_F) & 0xfffffffc);
+		trickmode_i = 0;
+	}
+
+	return 0;
+}
+
+int vh264_set_isreset(struct vdec_s *vdec, int isreset)
+{
+	is_reset = isreset;
+	return 0;
+}
+
+static void vh264_prot_init(void)
+{
+	ulong timeout = jiffies + HZ;
+
+	while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) {
+		if (time_after(jiffies, timeout)) {
+			pr_info("%s DCAC_DMA_CTRL time out\n", __func__);
+			break;
+		}
+	}
+
+	timeout = jiffies + HZ;
+	while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) {
+		if (time_after(jiffies, timeout)) {
+			pr_info("%s LMEM_DMA_CTRL time out\n", __func__);
+			break;
+		}
+	}
+
+#if 1				/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	READ_VREG(DOS_SW_RESET0);
+	READ_VREG(DOS_SW_RESET0);
+	READ_VREG(DOS_SW_RESET0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	READ_VREG(DOS_SW_RESET0);
+	READ_VREG(DOS_SW_RESET0);
+	READ_VREG(DOS_SW_RESET0);
+
+#else
+	WRITE_RESET_REG(RESET0_REGISTER,
+				   RESET_IQIDCT | RESET_MC | RESET_VLD_PART);
+	READ_RESET_REG(RESET0_REGISTER);
+	WRITE_RESET_REG(RESET0_REGISTER,
+				   RESET_IQIDCT | RESET_MC | RESET_VLD_PART);
+
+	WRITE_RESET_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK);
+#endif
+
+	WRITE_VREG(POWER_CTL_VLD,
+			   READ_VREG(POWER_CTL_VLD) |
+			   (0 << 10) | (1 << 9) | (1 << 6));
+
+	/* disable PSCALE for hardware sharing */
+	WRITE_VREG(PSCALE_CTRL, 0);
+
+	WRITE_VREG(AV_SCRATCH_0, 0);
+	WRITE_VREG(AV_SCRATCH_1, buf_offset);
+	if (!tee_enabled())
+		WRITE_VREG(AV_SCRATCH_G, mc_dma_handle);
+	WRITE_VREG(AV_SCRATCH_7, 0);
+	WRITE_VREG(AV_SCRATCH_8, 0);
+	WRITE_VREG(AV_SCRATCH_9, 0);
+	WRITE_VREG(AV_SCRATCH_N, 0);
+
+#ifdef SUPPORT_BAD_MACRO_BLOCK_REDUNDANCY
+	if (bad_block_scale > 128)
+		bad_block_scale = 128;
+	WRITE_VREG(AV_SCRATCH_A, bad_block_scale);
+#endif
+
+	error_recovery_mode_use =
+		(error_recovery_mode !=
+		 0) ? error_recovery_mode : error_recovery_mode_in;
+	WRITE_VREG(AV_SCRATCH_F,
+			   (READ_VREG(AV_SCRATCH_F) & 0xffffffc3) |
+			   (READ_VREG(AV_SCRATCH_F) & 0xffffff43) |
+			   ((error_recovery_mode_use & 0x1) << 4));
+	if (dec_control & DEC_CONTROL_FLAG_DISABLE_FAST_POC)
+		SET_VREG_MASK(AV_SCRATCH_F, 1 << 7);
+	/* clear mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+	/* enable mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_MASK, 1);
+
+	SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17);
+	if (ucode_type == UCODE_IP_ONLY_PARAM)
+		SET_VREG_MASK(AV_SCRATCH_F, 1 << 6);
+	else
+		CLEAR_VREG_MASK(AV_SCRATCH_F, 1 << 6);
+
+	WRITE_VREG(AV_SCRATCH_I, (u32)(sei_data_buffer_phys - buf_offset));
+	WRITE_VREG(AV_SCRATCH_J, 0);
+	/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
+	if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) && !is_meson_mtvd_cpu()) {
+		/* pr_info("vh264 meson8 prot init\n"); */
+		WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa);
+	}
+	/* #endif */
+}
+
+static int vh264_local_init(void)
+{
+	int i, ret;
+	u32 size;
+	unsigned long buf_start;
+	vh264_ratio = vh264_amstream_dec_info.ratio;
+	/* vh264_ratio = 0x100; */
+
+	vh264_rotation = (((unsigned long) vh264_amstream_dec_info.param)
+				>> 16) & 0xffff;
+
+	frame_prog = 0;
+	frame_width = vh264_amstream_dec_info.width;
+	frame_height = vh264_amstream_dec_info.height;
+	frame_dur = vh264_amstream_dec_info.rate;
+	pts_outside = ((unsigned long) vh264_amstream_dec_info.param) & 0x01;
+	sync_outside = ((unsigned long) vh264_amstream_dec_info.param & 0x02)
+			>> 1;
+	use_idr_framerate = ((unsigned long) vh264_amstream_dec_info.param
+				& 0x04) >> 2;
+	max_refer_buf = !(((unsigned long) vh264_amstream_dec_info.param
+				& 0x10) >> 4);
+	if (!vh264_reset) {
+		if (mm_blk_handle) {
+			decoder_bmmu_box_free(mm_blk_handle);
+			mm_blk_handle = NULL;
+		}
+
+		mm_blk_handle = decoder_bmmu_box_alloc_box(
+			DRIVER_NAME,
+			0,
+			MAX_BLK_BUFFERS,
+			4 + PAGE_SHIFT,
+			CODEC_MM_FLAGS_CMA_CLEAR |
+			CODEC_MM_FLAGS_FOR_VDECODER |
+			tvp_flag);
+	}
+	pr_info
+	("H264 sysinfo: %dx%d duration=%d, pts_outside=%d \n",
+	 frame_width, frame_height, frame_dur, pts_outside);
+	pr_debug("sync_outside=%d, use_idr_framerate=%d\n",
+	 sync_outside, use_idr_framerate);
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB)
+		size = V_BUF_ADDR_OFFSET_NEW;
+	else
+		size = V_BUF_ADDR_OFFSET;
+
+	ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, 0,
+		size, DRIVER_NAME, &buf_start);
+	if (ret < 0)
+		return ret;
+
+	buf_offset = buf_start - DEF_BUF_START_ADDR;
+
+	if ((unsigned long) vh264_amstream_dec_info.param & 0x08)
+		ucode_type = UCODE_IP_ONLY_PARAM;
+	else
+		ucode_type = 0;
+
+	if ((unsigned long) vh264_amstream_dec_info.param & 0x20)
+		error_recovery_mode_in = 1;
+	else
+		error_recovery_mode_in = 3;
+
+	if (!vh264_running) {
+		last_mb_width = 0;
+		last_mb_height = 0;
+	}
+
+	for (i = 0; i < VF_BUF_NUM; i++)
+		vfbuf_use[i] = 0;
+
+	INIT_KFIFO(display_q);
+	INIT_KFIFO(delay_display_q);
+	INIT_KFIFO(recycle_q);
+	INIT_KFIFO(newframe_q);
+
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		const struct vframe_s *vf = &vfpool[i];
+
+		vfpool[i].index = VF_BUF_NUM;
+		vfpool[i].bufWidth = 1920;
+		kfifo_put(&newframe_q, vf);
+	}
+
+#ifdef DROP_B_FRAME_FOR_1080P_50_60FPS
+	last_interlaced = 1;
+#endif
+	h264_first_pts_ready = 0;
+	h264_first_valid_pts_ready = false;
+	h264pts1 = 0;
+	h264pts2 = 0;
+	h264_pts_count = 0;
+	duration_from_pts_done = 0;
+	vh264_error_count = READ_VREG(AV_SCRATCH_D);
+
+	p_last_vf = NULL;
+	check_pts_discontinue = false;
+	last_pts = 0;
+	wait_buffer_counter = 0;
+	vh264_no_disp_count = 0;
+	fatal_error_flag = 0;
+	high_bandwidth = 0;
+	vh264_stream_switching_state = SWITCHING_STATE_OFF;
+#ifdef DEBUG_PTS
+	pts_missed = 0;
+	pts_hit = 0;
+#endif
+	pts_discontinue = false;
+	no_idr_error_count = 0;
+
+	vh264_reset_userdata_fifo(vdec_h264, 1);
+	h264_reset_qos_mgr();
+
+	if (enable_switch_fense) {
+		for (i = 0; i < ARRAY_SIZE(fense_buffer_spec); i++) {
+			struct buffer_spec_s *s = &fense_buffer_spec[i];
+			s->alloc_count = 3 * SZ_1M / PAGE_SIZE;
+			ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle,
+				FENSE_BUFFER_IDX(i),
+				3 * SZ_1M, DRIVER_NAME, &s->phy_addr);
+
+			if (ret < 0) {
+				fatal_error_flag =
+				DECODER_FATAL_ERROR_NO_MEM;
+				vh264_running = 0;
+				return ret;
+			}
+			s->y_canvas_index = 2 * i;
+			s->u_canvas_index = 2 * i + 1;
+			s->v_canvas_index = 2 * i + 1;
+		}
+	}
+	return 0;
+}
+
+static s32 vh264_init(void)
+{
+	int ret = 0;
+	int trickmode_fffb = 0;
+	int firmwareloaded = 0;
+
+	/* pr_info("\nvh264_init\n"); */
+	timer_setup(&recycle_timer, vh264_put_timer_func, 0);
+
+	stat |= STAT_TIMER_INIT;
+
+	vh264_running = 0;/* init here to reset last_mb_width&last_mb_height */
+	vh264_eos = 0;
+	duration_on_correcting = 0;
+	first_pts = 0;
+	first_pts64 = 0;
+	first_offset = 0;
+	first_pts_cached = false;
+	fixed_frame_rate_check_count = 0;
+	fr_hint_status = VDEC_NO_NEED_HINT;
+	saved_resolution = 0;
+	iponly_early_mode = 0;
+	saved_idc_level = 0;
+
+	frame_count = 0;
+	memset(&s_vframe_qos, 0, sizeof(s_vframe_qos));
+	/*init vdec status*/
+	ret = vh264_vdec_info_init();
+	if (0 != ret)
+		return -ret;
+
+	ret = vh264_local_init();
+	if (ret < 0)
+		return ret;
+	query_video_status(0, &trickmode_fffb);
+
+	amvdec_enable();
+	if (!firmwareloaded && tee_enabled()) {
+		ret = amvdec_loadmc_ex(VFORMAT_H264, NULL, NULL);
+		if (ret < 0) {
+			amvdec_disable();
+			pr_err("H264: the %s fw loading failed, err: %x\n",
+				tee_enabled() ? "TEE" : "local", ret);
+			return ret;
+		}
+	} else {
+	/* -- ucode loading (amrisc and swap code) */
+	mc_cpu_addr =
+		dma_alloc_coherent(amports_get_dma_device(), MC_TOTAL_SIZE,
+				&mc_dma_handle, GFP_KERNEL);
+	if (!mc_cpu_addr) {
+		amvdec_disable();
+		del_timer_sync(&recycle_timer);
+		pr_err("vh264_init: Can not allocate mc memory.\n");
+		return -ENOMEM;
+	}
+
+	pr_debug("264 ucode swap area: phyaddr %p, cpu vaddr %p\n",
+		(void *)mc_dma_handle, mc_cpu_addr);
+	if (debugfirmware) {
+		int r0, r1, r2, r3, r4, r5;
+		char firmwarename[32];
+
+		pr_debug("start load debug %d firmware ...\n", debugfirmware);
+
+		snprintf(firmwarename, 32, "%s%d", "vh264_mc", debugfirmware);
+		r0 = amvdec_loadmc_ex(VFORMAT_H264, firmwarename, NULL);
+
+#define DEBUGGET_FW(t, name, buf, size, ret)\
+		do {\
+			snprintf(firmwarename, 32, "%s%d", name,\
+				debugfirmware);\
+			ret = get_decoder_firmware_data(t,\
+				firmwarename, buf, size);\
+		} while (0)
+		/*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_HEADER, vh264_header_mc,
+		 *MC_SWAP_SIZE);
+		 */
+		DEBUGGET_FW(VFORMAT_H264, "vh264_header_mc",
+			(u8 *) mc_cpu_addr + MC_OFFSET_HEADER,
+			MC_SWAP_SIZE, r1);
+
+		/*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_DATA, vh264_data_mc,
+		 *MC_SWAP_SIZE);
+		 */
+		DEBUGGET_FW(VFORMAT_H264, "vh264_data_mc",
+			(u8 *) mc_cpu_addr + MC_OFFSET_DATA, MC_SWAP_SIZE, r2);
+		/*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_MMCO, vh264_mmco_mc,
+		 *MC_SWAP_SIZE);
+		 */
+		DEBUGGET_FW(VFORMAT_H264, "vh264_mmco_mc",
+			(u8 *) mc_cpu_addr + MC_OFFSET_MMCO, MC_SWAP_SIZE, r3);
+		/*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_LIST, vh264_list_mc,
+		 *MC_SWAP_SIZE);
+		 */
+		DEBUGGET_FW(VFORMAT_H264, "vh264_list_mc",
+			(u8 *) mc_cpu_addr + MC_OFFSET_LIST, MC_SWAP_SIZE, r4);
+		/*memcpy((u8 *) mc_cpu_addr + MC_OFFSET_SLICE, vh264_slice_mc,
+		 *MC_SWAP_SIZE);
+		 */
+		DEBUGGET_FW(VFORMAT_H264, "vh264_slice_mc",
+			(u8 *) mc_cpu_addr + MC_OFFSET_SLICE, MC_SWAP_SIZE, r5);
+
+		if (r0 < 0 || r1 < 0 || r2 < 0 || r3 < 0 || r4 < 0 || r5 < 0) {
+			pr_err("264 load debugfirmware err %d,%d,%d,%d,%d,%d\n",
+			r0, r1, r2, r3, r4, r5);
+			amvdec_disable();
+			if (mc_cpu_addr) {
+				dma_free_coherent(amports_get_dma_device(),
+					MC_TOTAL_SIZE, mc_cpu_addr,
+					mc_dma_handle);
+				mc_cpu_addr = NULL;
+			}
+			return -EBUSY;
+		}
+		firmwareloaded = 1;
+	} else {
+		int ret = -1;
+		char *buf = vmalloc(0x1000 * 16);
+
+		if (IS_ERR_OR_NULL(buf))
+			return -ENOMEM;
+
+		if (get_firmware_data(VIDEO_DEC_H264, buf) < 0) {
+			pr_err("get firmware fail.");
+			vfree(buf);
+			return -1;
+		}
+
+		ret = amvdec_loadmc_ex(VFORMAT_H264, NULL, buf);
+		memcpy((u8 *) mc_cpu_addr + MC_OFFSET_HEADER,
+			buf + 0x4000, MC_SWAP_SIZE);
+		memcpy((u8 *) mc_cpu_addr + MC_OFFSET_DATA,
+			buf + 0x2000, MC_SWAP_SIZE);
+		memcpy((u8 *) mc_cpu_addr + MC_OFFSET_MMCO,
+			buf + 0x6000, MC_SWAP_SIZE);
+		memcpy((u8 *) mc_cpu_addr + MC_OFFSET_LIST,
+			buf + 0x3000, MC_SWAP_SIZE);
+		memcpy((u8 *) mc_cpu_addr + MC_OFFSET_SLICE,
+			buf + 0x5000, MC_SWAP_SIZE);
+
+		vfree(buf);
+
+		if (ret < 0) {
+			amvdec_disable();
+			if (mc_cpu_addr) {
+				dma_free_coherent(amports_get_dma_device(),
+					MC_TOTAL_SIZE, mc_cpu_addr,
+					mc_dma_handle);
+				mc_cpu_addr = NULL;
+			}
+			pr_err("H264: the %s fw loading failed, err: %x\n",
+				tee_enabled() ? "TEE" : "local", ret);
+			return -EBUSY;
+		}
+	}
+	}
+
+	stat |= STAT_MC_LOAD;
+
+	/* enable AMRISC side protocol */
+	vh264_prot_init();
+
+#ifdef HANDLE_H264_IRQ
+	/*TODO irq */
+
+	if (vdec_request_irq(VDEC_IRQ_1, vh264_isr,
+			"vh264-irq", (void *)vh264_dec_id)) {
+		pr_err("vh264 irq register error.\n");
+		amvdec_disable();
+		return -ENOENT;
+	}
+#endif
+
+	stat |= STAT_ISR_REG;
+
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+	vf_provider_init(&vh264_vf_prov, PROVIDER_NAME, &vh264_vf_provider_ops,
+					 NULL);
+	vf_reg_provider(&vh264_vf_prov);
+	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL);
+#else
+	vf_provider_init(&vh264_vf_prov, PROVIDER_NAME, &vh264_vf_provider_ops,
+					 NULL);
+	vf_reg_provider(&vh264_vf_prov);
+#endif
+
+	if (frame_dur != 0) {
+		if (!is_reset) {
+			vf_notify_receiver(PROVIDER_NAME,
+					VFRAME_EVENT_PROVIDER_FR_HINT,
+					(void *)((unsigned long)frame_dur));
+			fr_hint_status = VDEC_HINTED;
+		}
+	} else
+		fr_hint_status = VDEC_NEED_HINT;
+
+	stat |= STAT_VF_HOOK;
+
+	recycle_timer.expires = jiffies + PUT_INTERVAL;
+	add_timer(&recycle_timer);
+
+	stat |= STAT_TIMER_ARM;
+
+	vh264_stream_switching_state = SWITCHING_STATE_OFF;
+
+	stat |= STAT_VDEC_RUN;
+	wmb();			/* Ensure fetchbuf  contents visible */
+
+	/* -- start decoder */
+	amvdec_start();
+
+	init_userdata_fifo();
+
+	return 0;
+}
+
+static int vh264_stop(int mode)
+{
+
+
+	if (stat & STAT_VDEC_RUN) {
+		amvdec_stop();
+		stat &= ~STAT_VDEC_RUN;
+	}
+
+	if (stat & STAT_ISR_REG) {
+		WRITE_VREG(ASSIST_MBOX1_MASK, 0);
+		/*TODO irq */
+
+		vdec_free_irq(VDEC_IRQ_1, (void *)vh264_dec_id);
+
+		stat &= ~STAT_ISR_REG;
+	}
+
+	if (stat & STAT_TIMER_ARM) {
+		del_timer_sync(&recycle_timer);
+		stat &= ~STAT_TIMER_ARM;
+	}
+
+	if (stat & STAT_VF_HOOK) {
+		if (mode == MODE_FULL) {
+			if (fr_hint_status == VDEC_HINTED)
+				vf_notify_receiver(PROVIDER_NAME,
+					VFRAME_EVENT_PROVIDER_FR_END_HINT,
+					NULL);
+			fr_hint_status = VDEC_NO_NEED_HINT;
+		}
+
+		vf_unreg_provider(&vh264_vf_prov);
+		stat &= ~STAT_VF_HOOK;
+	}
+
+	if (stat & STAT_MC_LOAD) {
+		if (mc_cpu_addr != NULL) {
+			dma_free_coherent(amports_get_dma_device(),
+					MC_TOTAL_SIZE, mc_cpu_addr,
+					mc_dma_handle);
+			mc_cpu_addr = NULL;
+		}
+	}
+	if (sei_data_buffer != NULL) {
+		dma_free_coherent(
+			amports_get_dma_device(),
+			USER_DATA_RUND_SIZE,
+			sei_data_buffer,
+			sei_data_buffer_phys);
+		sei_data_buffer = NULL;
+		sei_data_buffer_phys = 0;
+	}
+	amvdec_disable();
+	if (mm_blk_handle) {
+		decoder_bmmu_box_free(mm_blk_handle);
+		mm_blk_handle = NULL;
+	}
+	memset(&fense_buffer_spec, 0, sizeof(fense_buffer_spec));
+	memset(&buffer_spec, 0, sizeof(buffer_spec));
+	return 0;
+}
+
+static void wait_vh264_search_done(void)
+{
+	u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP);
+	int count = 0;
+	do {
+		usleep_range(100, 500);
+		if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP))
+			break;
+		if (count > 2000) {
+			pr_info("%s, timeout  count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n",
+					__func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP));
+			break;
+		} else
+			vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP);
+		count++;
+	} while (1);
+}
+
+
+static void error_do_work(struct work_struct *work)
+{
+
+	/*
+	 * we need to lock vh264_stop/vh264_init.
+	 * because we will call amvdec_h264_remove on this step;
+	 * then we may call more than once on
+	 * free_irq/deltimer/..and some other.
+	 */
+	if (atomic_read(&vh264_active)) {
+		amvdec_stop();
+		do {
+			msleep(50);
+		} while (vh264_stream_switching_state != SWITCHING_STATE_OFF);
+		wait_vh264_search_done();
+		vh264_reset  = 1;
+#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+		vh264_ppmgr_reset();
+#else
+		vf_light_unreg_provider(&vh264_vf_prov);
+
+		vh264_local_init();
+
+		vf_reg_provider(&vh264_vf_prov);
+#endif
+		vh264_prot_init();
+		amvdec_start();
+		vh264_reset  = 0;
+	}
+}
+
+static void stream_switching_done(void)
+{
+	int state = vh264_stream_switching_state;
+
+	WRITE_VREG(AV_SCRATCH_7, 0);
+	WRITE_VREG(AV_SCRATCH_8, 0);
+	WRITE_VREG(AV_SCRATCH_9, 0);
+
+	if (state == SWITCHING_STATE_ON_CMD1) {
+		pr_info("Enter set parameter cmd1 switching_state %x.\n",
+					vh264_stream_switching_state);
+		schedule_work(&set_parameter_work);
+		return;
+	} else if (state == SWITCHING_STATE_ON_CMD1_PENDING)
+		return;
+
+	vh264_stream_switching_state = SWITCHING_STATE_OFF;
+
+	wmb();			/* Ensure fetchbuf  contents visible */
+
+	if (state == SWITCHING_STATE_ON_CMD3)
+		WRITE_VREG(AV_SCRATCH_0, 0);
+
+	pr_info("Leaving switching mode.\n");
+}
+
+/* construt a new frame as a copy of last frame so frame receiver can
+ * release all buffer resources to decoder.
+ */
+static void stream_switching_do(struct work_struct *work)
+{
+	int mb_total_num, mb_width_num, mb_height_num, i = 0;
+	struct vframe_s *vf = NULL;
+	u32 y_index, u_index, src_index, des_index, y_desindex, u_desindex;
+	struct canvas_s csy, csu, cyd;
+	unsigned long flags;
+	bool delay = true;
+
+	if (!atomic_read(&vh264_active))
+		return;
+
+	if (vh264_stream_switching_state == SWITCHING_STATE_OFF)
+		return;
+
+	spin_lock_irqsave(&prepare_lock, flags);
+
+	block_display_q = true;
+
+	spin_unlock_irqrestore(&prepare_lock, flags);
+
+	mb_total_num = mb_total;
+	mb_width_num = mb_width;
+	mb_height_num = mb_height;
+
+	while (is_4k || kfifo_len(&delay_display_q) > 2) {
+		if (kfifo_get(&delay_display_q, &vf)) {
+			kfifo_put(&display_q,
+				(const struct vframe_s *)vf);
+			ATRACE_COUNTER(MODULE_NAME, vf->pts);
+			vf_notify_receiver(PROVIDER_NAME,
+				VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+		} else
+			break;
+	}
+
+	if (!kfifo_get(&delay_display_q, &vf)) {
+		vf = p_last_vf;
+		delay = false;
+	}
+
+	while (vf) {
+		int buffer_index;
+
+		buffer_index = vf->index & 0xff;
+
+		/* construct a clone of the frame from last frame */
+
+#if 0
+
+		pr_info("src yaddr[0x%x] index[%d] width[%d] heigth[%d]\n",
+			buffer_spec[buffer_index].y_addr,
+			buffer_spec[buffer_index].y_canvas_index,
+			buffer_spec[buffer_index].y_canvas_width,
+			buffer_spec[buffer_index].y_canvas_height);
+
+		pr_info("src uaddr[0x%x] index[%d] width[%d] heigth[%d]\n",
+			buffer_spec[buffer_index].u_addr,
+			buffer_spec[buffer_index].u_canvas_index,
+			buffer_spec[buffer_index].u_canvas_width,
+			buffer_spec[buffer_index].u_canvas_height);
+#endif
+		if (EN_SWITCH_FENCE()) {
+			y_index = buffer_spec[buffer_index].y_canvas_index;
+			u_index = buffer_spec[buffer_index].u_canvas_index;
+
+			canvas_read(y_index, &csy);
+			canvas_read(u_index, &csu);
+
+			config_cav_lut_ex(fense_buffer_spec[i].y_canvas_index,
+				fense_buffer_spec[i].phy_addr,
+				mb_width_num << 4, mb_height_num << 4,
+				CANVAS_ADDR_NOWRAP,
+				CANVAS_BLKMODE_LINEAR, 0, VDEC_1);
+			config_cav_lut_ex(fense_buffer_spec[i].u_canvas_index,
+				fense_buffer_spec[i].phy_addr +
+				(mb_total_num << 8),
+				mb_width_num << 4, mb_height_num << 3,
+				CANVAS_ADDR_NOWRAP,
+				CANVAS_BLKMODE_LINEAR, 0, VDEC_1);
+
+			y_desindex = fense_buffer_spec[i].y_canvas_index;
+			u_desindex = fense_buffer_spec[i].u_canvas_index;
+
+			canvas_read(y_desindex, &cyd);
+
+			src_index = ((y_index & 0xff) |
+				((u_index << 8) & 0x0000ff00));
+			des_index = ((y_desindex & 0xff) |
+				((u_desindex << 8) & 0x0000ff00));
+
+			ge2d_canvas_dup(&csy, &csu, &cyd,
+				GE2D_FORMAT_M24_NV21,
+				src_index,
+				des_index);
+		}
+		vf->mem_handle = decoder_bmmu_box_get_mem_handle(
+			mm_blk_handle,
+			FENSE_BUFFER_IDX(i));
+		fense_vf[i] = *vf;
+		fense_vf[i].index = -1;
+
+		if (EN_SWITCH_FENCE())
+			fense_vf[i].canvas0Addr =
+				spec2canvas(&fense_buffer_spec[i]);
+		else
+			fense_vf[i].flag |= VFRAME_FLAG_SWITCHING_FENSE;
+
+		/* send clone to receiver */
+		kfifo_put(&display_q,
+			(const struct vframe_s *)&fense_vf[i]);
+		ATRACE_COUNTER(MODULE_NAME, fense_vf[i].pts);
+		/* early recycle frames for last session */
+		if (delay)
+			vh264_vf_put(vf, NULL);
+
+		vf_notify_receiver(PROVIDER_NAME,
+			VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+
+		i++;
+
+		if (!kfifo_get(&delay_display_q, &vf))
+			break;
+	}
+
+	block_display_q = false;
+
+	pr_info("Switching fense frame post\n");
+}
+
+static int amvdec_h264_probe(struct platform_device *pdev)
+{
+	struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
+
+	mutex_lock(&vh264_mutex);
+
+	if (pdata == NULL) {
+		pr_info("\namvdec_h264 memory resource undefined.\n");
+		mutex_unlock(&vh264_mutex);
+		return -EFAULT;
+	}
+	canvas_mode = pdata->canvas_mode;
+	tvp_flag = vdec_secure(pdata) ? CODEC_MM_FLAGS_TVP : 0;
+	if (pdata->sys_info)
+		vh264_amstream_dec_info = *pdata->sys_info;
+	if (sei_data_buffer == NULL) {
+		sei_data_buffer =
+			dma_alloc_coherent(amports_get_dma_device(),
+				USER_DATA_RUND_SIZE,
+				&sei_data_buffer_phys, GFP_KERNEL);
+		if (!sei_data_buffer) {
+			pr_info("%s: Can not allocate sei_data_buffer\n",
+				   __func__);
+			mutex_unlock(&vh264_mutex);
+			return -ENOMEM;
+		}
+		/* pr_info("buffer 0x%x, phys 0x%x, remap 0x%x\n",
+		 *   sei_data_buffer, sei_data_buffer_phys,
+		 * (u32)sei_data_buffer_remap);
+		 */
+	}
+	pdata->dec_status = vh264_dec_status;
+	pdata->set_trickmode = vh264_set_trickmode;
+	pdata->set_isreset = vh264_set_isreset;
+
+	pdata->user_data_read = vh264_user_data_read;
+	pdata->reset_userdata_fifo = vh264_reset_userdata_fifo;
+	pdata->wakeup_userdata_poll = vh264_wakeup_userdata_poll;
+
+	is_reset = 0;
+	clk_adj_frame_count = 0;
+	if (vh264_init() < 0) {
+		pr_info("\namvdec_h264 init failed.\n");
+		kfree(gvs);
+		gvs = NULL;
+		pdata->dec_status = NULL;
+		mutex_unlock(&vh264_mutex);
+		return -ENODEV;
+	}
+	vdec_h264 = pdata;
+	vh264_crate_userdata_manager(sei_data_buffer, USER_DATA_SIZE);
+	vh264_reset_userdata_fifo(vdec_h264, 1);
+
+#ifdef DUMP_USER_DATA
+	vh264_init_userdata_dump();
+	vh264_reset_user_data_buf();
+#endif
+
+	INIT_WORK(&error_wd_work, error_do_work);
+	INIT_WORK(&stream_switching_work, stream_switching_do);
+	INIT_WORK(&set_parameter_work, vh264_set_params);
+	INIT_WORK(&notify_work, vh264_notify_work);
+	INIT_WORK(&set_clk_work, vh264_set_clk);
+	INIT_WORK(&userdata_push_work, userdata_push_do_work);
+	INIT_WORK(&qos_work, qos_do_work);
+
+	atomic_set(&vh264_active, 1);
+
+	mutex_unlock(&vh264_mutex);
+	vdec_set_vframe_comm(pdata, DRIVER_NAME);
+
+	return 0;
+}
+
+static int amvdec_h264_remove(struct platform_device *pdev)
+{
+	atomic_set(&vh264_active, 0);
+	cancel_work_sync(&set_parameter_work);
+	cancel_work_sync(&error_wd_work);
+	cancel_work_sync(&stream_switching_work);
+	cancel_work_sync(&notify_work);
+	cancel_work_sync(&userdata_push_work);
+	cancel_work_sync(&qos_work);
+
+
+	vh264_stop(MODE_FULL);
+	wait_vh264_search_done();
+	vdec_source_changed(VFORMAT_H264, 0, 0, 0);
+#ifdef DUMP_USER_DATA
+	vh264_dump_userdata();
+#endif
+	vh264_destroy_userdata_manager();
+	atomic_set(&vh264_active, 0);
+#ifdef DEBUG_PTS
+	pr_info
+	("pts missed %ld, pts hit %ld, pts_outside %d, duration %d, ",
+	 pts_missed, pts_hit, pts_outside, frame_dur);
+	pr_info("sync_outside %d, use_idr_framerate %d\n",
+			sync_outside, use_idr_framerate);
+#endif
+	kfree(gvs);
+	gvs = NULL;
+	cancel_work_sync(&set_clk_work);
+	mutex_unlock(&vh264_mutex);
+	return 0;
+}
+
+/****************************************/
+
+static struct platform_driver amvdec_h264_driver = {
+	.probe = amvdec_h264_probe,
+	.remove = amvdec_h264_remove,
+#ifdef CONFIG_PM
+	.suspend = amvdec_suspend,
+	.resume = amvdec_resume,
+#endif
+	.driver = {
+		.name = DRIVER_NAME,
+	}
+};
+
+static struct codec_profile_t amvdec_h264_profile = {
+	.name = "h264",
+	.profile = ""
+};
+
+
+static struct mconfig h264_configs[] = {
+	MC_PU32("stat", &stat),
+	MC_PU32("error_recovery_mode", &error_recovery_mode),
+	MC_PU32("sync_outside", &sync_outside),
+	MC_PU32("dec_control", &dec_control),
+	MC_PU32("fatal_error_reset", &fatal_error_reset),
+	MC_PU32("max_refer_buf", &max_refer_buf),
+	MC_PU32("ucode_type", &ucode_type),
+	MC_PU32("debugfirmware", &debugfirmware),
+	MC_PU32("fixed_frame_rate_flag", &fixed_frame_rate_flag),
+	MC_PU32("decoder_debug_flag", &decoder_debug_flag),
+	MC_PU32("dpb_size_adj", &dpb_size_adj),
+	MC_PU32("decoder_force_reset", &decoder_force_reset),
+	MC_PU32("no_idr_error_max", &no_idr_error_max),
+	MC_PU32("enable_switch_fense", &enable_switch_fense),
+};
+static struct mconfig_node h264_node;
+
+
+static int __init amvdec_h264_driver_init_module(void)
+{
+	pr_debug("amvdec_h264 module init\n");
+
+	ge2d_videoh264task_init();
+
+	if (platform_driver_register(&amvdec_h264_driver)) {
+		pr_err("failed to register amvdec_h264 driver\n");
+		return -ENODEV;
+	}
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB
+		&& (codec_mm_get_total_size() > 80 * SZ_1M) &&
+		get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5D) {
+		amvdec_h264_profile.profile = "4k";
+	}
+	vcodec_profile_register(&amvdec_h264_profile);
+	INIT_REG_NODE_CONFIGS("media.decoder", &h264_node,
+		"h264", h264_configs, CONFIG_FOR_RW);
+	return 0;
+}
+
+static void __exit amvdec_h264_driver_remove_module(void)
+{
+	pr_debug("amvdec_h264 module remove.\n");
+
+	platform_driver_unregister(&amvdec_h264_driver);
+
+	ge2d_videoh264task_release();
+}
+
+/****************************************/
+
+module_param(stat, uint, 0664);
+MODULE_PARM_DESC(stat, "\n amvdec_h264 stat\n");
+module_param(error_recovery_mode, uint, 0664);
+MODULE_PARM_DESC(error_recovery_mode, "\n amvdec_h264 error_recovery_mode\n");
+module_param(sync_outside, uint, 0664);
+MODULE_PARM_DESC(sync_outside, "\n amvdec_h264 sync_outside\n");
+module_param(dec_control, uint, 0664);
+MODULE_PARM_DESC(dec_control, "\n amvdec_h264 decoder control\n");
+module_param(frame_count, uint, 0664);
+MODULE_PARM_DESC(frame_count,
+		"\n amvdec_h264 decoded total count\n");
+module_param(fatal_error_reset, uint, 0664);
+MODULE_PARM_DESC(fatal_error_reset,
+		"\n amvdec_h264 decoder reset when fatal error happens\n");
+module_param(max_refer_buf, uint, 0664);
+MODULE_PARM_DESC(max_refer_buf,
+		"\n amvdec_h264 dec buffering or not for reference frame\n");
+module_param(ucode_type, uint, 0664);
+MODULE_PARM_DESC(ucode_type,
+		"\n amvdec_h264 dec buffering or not for reference frame\n");
+module_param(debugfirmware, uint, 0664);
+MODULE_PARM_DESC(debugfirmware, "\n amvdec_h264 debug load firmware\n");
+module_param(fixed_frame_rate_flag, uint, 0664);
+MODULE_PARM_DESC(fixed_frame_rate_flag,
+				 "\n amvdec_h264 fixed_frame_rate_flag\n");
+module_param(decoder_debug_flag, uint, 0664);
+MODULE_PARM_DESC(decoder_debug_flag,
+				 "\n amvdec_h264 decoder_debug_flag\n");
+
+module_param(dpb_size_adj, uint, 0664);
+MODULE_PARM_DESC(dpb_size_adj,
+				 "\n amvdec_h264 dpb_size_adj\n");
+
+
+module_param(decoder_force_reset, uint, 0664);
+MODULE_PARM_DESC(decoder_force_reset,
+		"\n amvdec_h264 decoder force reset\n");
+module_param(no_idr_error_max, uint, 0664);
+MODULE_PARM_DESC(no_idr_error_max,
+		"\n print no_idr_error_max\n");
+module_param(enable_switch_fense, uint, 0664);
+MODULE_PARM_DESC(enable_switch_fense,
+		"\n enable switch fense\n");
+
+#ifdef SUPPORT_BAD_MACRO_BLOCK_REDUNDANCY
+module_param(bad_block_scale, uint, 0664);
+MODULE_PARM_DESC(bad_block_scale,
+				"\n print bad_block_scale\n");
+#endif
+
+module_param(enable_userdata_debug, uint, 0664);
+MODULE_PARM_DESC(enable_userdata_debug,
+		"\n enable_userdata_debug\n");
+
+
+module_init(amvdec_h264_driver_init_module);
+module_exit(amvdec_h264_driver_remove_module);
+
+MODULE_DESCRIPTION("AMLOGIC H264 Video Decoder Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Chen Zhang <chen.zhang@amlogic.com>");
diff --git a/drivers/frame_provider/decoder/h264/vh264.h b/drivers/frame_provider/decoder/h264/vh264.h
new file mode 100644
index 0000000..6c8e4ad
--- /dev/null
+++ b/drivers/frame_provider/decoder/h264/vh264.h
@@ -0,0 +1,27 @@
+/*
+ * drivers/amlogic/media/frame_provider/decoder/h264/vh264.h
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef VH264_H
+#define VH264_H
+
+extern int query_video_status(int type, int *value);
+
+/* extern s32 vh264_init(void); */
+
+extern s32 vh264_release(void);
+
+#endif /* VMPEG4_H */
diff --git a/drivers/frame_provider/decoder/h264/vh264_mvc.c b/drivers/frame_provider/decoder/h264/vh264_mvc.c
new file mode 100644
index 0000000..4827e38
--- /dev/null
+++ b/drivers/frame_provider/decoder/h264/vh264_mvc.c
@@ -0,0 +1,1918 @@
+/*
+ * drivers/amlogic/amports/vh264mvc.c
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/platform_device.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/workqueue.h>
+#include <linux/dma-mapping.h>
+#include <linux/atomic.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../../../stream_input/amports/amports_priv.h"
+#include "../utils/vdec.h"
+#include "../utils/amvdec.h"
+#include "../utils/decoder_mmu_box.h"
+#include "../utils/decoder_bmmu_box.h"
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include <linux/amlogic/media/codec_mm/configs.h>
+#include "../utils/firmware.h"
+#include "../utils/config_parser.h"
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+
+#define TIME_TASK_PRINT_ENABLE  0x100
+#define PUT_PRINT_ENABLE    0x200
+
+#define DRIVER_NAME "amvdec_h264mvc"
+#define MODULE_NAME "amvdec_h264mvc"
+
+#define HANDLE_h264mvc_IRQ
+
+#define DEBUG_PTS
+#define DEBUG_SKIP
+
+#define PUT_INTERVAL        (HZ/100)
+
+#define STAT_TIMER_INIT     0x01
+#define STAT_MC_LOAD        0x02
+#define STAT_ISR_REG        0x04
+#define STAT_VF_HOOK        0x08
+#define STAT_TIMER_ARM      0x10
+#define STAT_VDEC_RUN       0x20
+
+#define DROPPING_THREAD_HOLD    4
+#define DROPPING_FIRST_WAIT     16
+#define DISPLAY_INVALID_POS    -65536
+
+#define INIT_DROP_FRAME_CNT    8
+
+static int vh264mvc_vf_states(struct vframe_states *states, void *);
+static struct vframe_s *vh264mvc_vf_peek(void *);
+static struct vframe_s *vh264mvc_vf_get(void *);
+static void vh264mvc_vf_put(struct vframe_s *, void *);
+static int vh264mvc_event_cb(int type, void *data, void *private_data);
+
+static void vh264mvc_prot_init(void);
+static int vh264mvc_local_init(void);
+static void vh264mvc_put_timer_func(struct timer_list *timer);
+
+static const char vh264mvc_dec_id[] = "vh264mvc-dev";
+
+#define PROVIDER_NAME   "decoder.h264mvc"
+
+static struct vdec_info *gvs;
+static struct work_struct alloc_work;
+static struct work_struct set_clk_work;
+
+static DEFINE_MUTEX(vh264_mvc_mutex);
+
+static const struct vframe_operations_s vh264mvc_vf_provider = {
+	.peek = vh264mvc_vf_peek,
+	.get = vh264mvc_vf_get,
+	.put = vh264mvc_vf_put,
+	.event_cb = vh264mvc_event_cb,
+	.vf_states = vh264mvc_vf_states,
+};
+
+static struct vframe_provider_s vh264mvc_vf_prov;
+
+static struct vdec_s *vdec = NULL;
+static u32 frame_width, frame_height, frame_dur;
+static u32 saved_resolution;
+static struct timer_list recycle_timer;
+static u32 stat;
+static u32 pts_outside;
+static u32 sync_outside;
+static u32 vh264mvc_ratio;
+static u32 h264mvc_ar;
+static u32 no_dropping_cnt;
+static s32 init_drop_cnt;
+spinlock_t mvc_rp_lock;
+
+#ifdef DEBUG_SKIP
+static unsigned long view_total, view_dropped;
+#endif
+
+#ifdef DEBUG_PTS
+static unsigned long pts_missed, pts_hit;
+#endif
+
+static atomic_t vh264mvc_active = ATOMIC_INIT(0);
+static struct work_struct error_wd_work;
+
+static struct dec_sysinfo vh264mvc_amstream_dec_info;
+static dma_addr_t mc_dma_handle;
+static void *mc_cpu_addr;
+
+static DEFINE_SPINLOCK(lock);
+
+static int vh264mvc_stop(void);
+static s32 vh264mvc_init(void);
+
+/***************************
+ *   new
+ **************************
+ */
+
+/* bit[3:0] command : */
+/* 0 - command finished */
+/* (DATA0 - {level_idc_mmco, max_reference_frame_num, width, height} */
+/* 1 - alloc view_0 display_buffer and reference_data_area */
+/* 2 - alloc view_1 display_buffer and reference_data_area */
+#define MAILBOX_COMMAND         AV_SCRATCH_0
+#define MAILBOX_DATA_0          AV_SCRATCH_1
+#define MAILBOX_DATA_1          AV_SCRATCH_2
+#define MAILBOX_DATA_2          AV_SCRATCH_3
+#define CANVAS_START            AV_SCRATCH_6
+#define BUFFER_RECYCLE          AV_SCRATCH_7
+#define DROP_CONTROL            AV_SCRATCH_8
+#define PICTURE_COUNT           AV_SCRATCH_9
+#define DECODE_STATUS           AV_SCRATCH_A
+#define SPS_STATUS              AV_SCRATCH_B
+#define PPS_STATUS              AV_SCRATCH_C
+#define SIM_RESERV_D            AV_SCRATCH_D
+#define WORKSPACE_START         AV_SCRATCH_E
+#define SIM_RESERV_F            AV_SCRATCH_F
+#define DECODE_ERROR_CNT        AV_SCRATCH_G
+#define CURRENT_UCODE           AV_SCRATCH_H
+#define CURRENT_SPS_PPS         AV_SCRATCH_I/* bit[15:9]-SPS, bit[8:0]-PPS */
+#define DECODE_SKIP_PICTURE     AV_SCRATCH_J
+#define UCODE_START_ADDR        AV_SCRATCH_K
+#define SIM_RESERV_L            AV_SCRATCH_L
+#define REF_START_VIEW_0        AV_SCRATCH_M
+#define REF_START_VIEW_1        AV_SCRATCH_N
+
+/********************************************
+ *  Mailbox command
+ ********************************************/
+#define CMD_FINISHED               0
+#define CMD_ALLOC_VIEW_0           1
+#define CMD_ALLOC_VIEW_1           2
+#define CMD_FRAME_DISPLAY          3
+#define CMD_FATAL_ERROR            4
+
+#define CANVAS_INDEX_START       0x78
+/* /AMVDEC_H264MVC_CANVAS_INDEX */
+
+#define MC_TOTAL_SIZE        (28*SZ_1K)
+#define MC_SWAP_SIZE         (4*SZ_1K)
+
+unsigned int DECODE_BUFFER_START = 0x00200000;
+unsigned int DECODE_BUFFER_END = 0x05000000;
+
+/* #define DISPLAY_BUFFER_NUM         4 */
+static unsigned int dynamic_buf_num_margin = 8;
+
+#define DECODE_BUFFER_NUM_MAX    16
+#define MAX_BMMU_BUFFER_NUM	(DECODE_BUFFER_NUM_MAX + dynamic_buf_num_margin)
+#define TOTAL_BMMU_BUFF_NUM     (MAX_BMMU_BUFFER_NUM * 2 + 3)
+#define VF_BUFFER_IDX(n) (2  + n)
+
+#define DECODER_WORK_SPACE_SIZE 0xa0000
+
+
+static unsigned int ANC_CANVAS_ADDR;
+static unsigned int index;
+static unsigned long ref_start_addr[2];
+static unsigned int max_dec_frame_buffering[2];
+static unsigned int total_dec_frame_buffering[2];
+
+static unsigned int dpb_size, ref_size;
+
+static int display_buff_id;
+static int display_view_id;
+static int display_POC;
+static int stream_offset;
+
+#define video_domain_addr(adr) (adr&0x7fffffff)
+static unsigned long work_space_adr;
+
+struct buffer_spec_s {
+	unsigned int y_addr;
+	unsigned int u_addr;
+	unsigned int v_addr;
+
+	int y_canvas_index;
+	int u_canvas_index;
+	int v_canvas_index;
+
+	struct page *alloc_pages;
+	unsigned long phy_addr;
+	int alloc_count;
+};
+/*
+static struct buffer_spec_s buffer_spec0[MAX_BMMU_BUFFER_NUM];
+static struct buffer_spec_s buffer_spec1[MAX_BMMU_BUFFER_NUM];
+*/
+static struct buffer_spec_s *buffer_spec0;
+static struct buffer_spec_s *buffer_spec1;
+static void *mm_blk_handle;
+
+/*
+ *    dbg_mode:
+ *    bit 0: 1, print debug information
+ *    bit 4: 1, recycle buffer without displaying;
+ *    bit 5: 1, buffer single frame step , set dbg_cmd to 1 to step
+ *
+ */
+static int dbg_mode;
+static int dbg_cmd;
+static int view_mode =
+	3;	/* 0, left; 1 ,right ; 2, left<->right 3, right<->left */
+static int drop_rate = 2;
+static int drop_thread_hold;
+/**/
+
+struct mvc_buf_s {
+	struct list_head list;
+	struct vframe_s vframe;
+	int display_POC;
+	int view0_buff_id;
+	int view1_buff_id;
+	int view0_drop;
+	int view1_drop;
+	int stream_offset;
+	unsigned int pts;
+} /*mvc_buf_t */;
+
+#define spec2canvas(x)  \
+	(((x)->v_canvas_index << 16) | \
+	 ((x)->u_canvas_index << 8)  | \
+	 ((x)->y_canvas_index << 0))
+
+#define to_mvcbuf(vf)   \
+	container_of(vf, struct mvc_buf_s, vframe)
+
+static int vf_buf_init_flag;
+
+static void init_vf_buf(void)
+{
+
+	vf_buf_init_flag = 1;
+}
+
+static void uninit_vf_buf(void)
+{
+
+}
+
+/* #define QUEUE_SUPPORT */
+
+struct mvc_info_s {
+	int view0_buf_id;
+	int view1_buf_id;
+	int view0_drop;
+	int view1_drop;
+	int display_pos;
+	int used;
+	int slot;
+	unsigned int stream_offset;
+};
+
+#define VF_POOL_SIZE        20
+static struct vframe_s vfpool[VF_POOL_SIZE];
+static struct mvc_info_s vfpool_idx[VF_POOL_SIZE];
+static s32 view0_vfbuf_use[DECODE_BUFFER_NUM_MAX];
+static s32 view1_vfbuf_use[DECODE_BUFFER_NUM_MAX];
+
+static s32 fill_ptr, get_ptr, putting_ptr, put_ptr;
+static s32 dirty_frame_num;
+static s32 enable_recycle;
+
+static s32 init_drop_frame_id[INIT_DROP_FRAME_CNT];
+#define INCPTR(p) ptr_atomic_wrap_inc(&p)
+static inline void ptr_atomic_wrap_inc(u32 *ptr)
+{
+	u32 i = *ptr;
+
+	i++;
+
+	if (i >= VF_POOL_SIZE)
+		i = 0;
+
+	*ptr = i;
+}
+
+static void set_frame_info(struct vframe_s *vf)
+{
+	unsigned int ar = 0;
+
+	vf->width = frame_width;
+	vf->height = frame_height;
+	vf->duration = frame_dur;
+	vf->duration_pulldown = 0;
+
+	if (vh264mvc_ratio == 0) {
+		/* always stretch to 16:9 */
+		vf->ratio_control |= (0x90 <<
+				DISP_RATIO_ASPECT_RATIO_BIT);
+		vf->sar_height = 1;
+		vf->sar_width = 1;
+	} else {
+		/* h264mvc_ar = ((float)frame_height/frame_width)
+		 *customer_ratio;
+		 */
+		switch (h264mvc_ar) {
+		case 1:
+			ar = 0x3ff;
+			vf->sar_height = 1;
+			vf->sar_width = 1;
+			break;
+		case 2:
+			ar = 0x3ff;
+			vf->sar_height = 11;
+			vf->sar_width = 12;
+			break;
+		case 3:
+			ar = 0x3ff;
+			vf->sar_height = 11;
+			vf->sar_width = 10;
+			break;
+		case 4:
+			ar = 0x3ff;
+			vf->sar_height = 11;
+			vf->sar_width = 16;
+			break;
+		case 5:
+			ar = 0x3ff;
+			vf->sar_height = 33;
+			vf->sar_width = 40;
+			break;
+		case 6:
+			ar = 0x3ff;
+			vf->sar_height = 11;
+			vf->sar_width = 24;
+			break;
+		case 7:
+			ar = 0x3ff;
+			vf->sar_height = 11;
+			vf->sar_width = 20;
+			break;
+		case 8:
+			ar = 0x3ff;
+			vf->sar_height = 11;
+			vf->sar_width = 32;
+			break;
+		case 9:
+			ar = 0x3ff;
+			vf->sar_height = 33;
+			vf->sar_width = 80;
+			break;
+		case 10:
+			ar = 0x3ff;
+			vf->sar_height = 11;
+			vf->sar_width = 18;
+			break;
+		case 11:
+			ar = 0x3ff;
+			vf->sar_height = 11;
+			vf->sar_width = 15;
+			break;
+		case 12:
+			ar = 0x3ff;
+			vf->sar_height = 33;
+			vf->sar_width = 64;
+			break;
+		case 13:
+			ar = 0x3ff;
+			vf->sar_height = 99;
+			vf->sar_width = 160;
+			break;
+		case 14:
+			ar = 0x3ff;
+			vf->sar_height = 3;
+			vf->sar_width = 4;
+			break;
+		case 15:
+			ar = 0x3ff;
+			vf->sar_height = 2;
+			vf->sar_width = 3;
+			break;
+		case 16:
+			ar = 0x3ff;
+			vf->sar_height = 1;
+			vf->sar_width = 2;
+			break;
+		default:
+			ar = 0x3ff;
+			vf->sar_height = 1;
+			vf->sar_width = 1;
+			break;
+		}
+	}
+	ar =  min_t(u32, ar, DISP_RATIO_ASPECT_RATIO_MAX);
+
+	vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT);
+}
+
+static int vh264mvc_vf_states(struct vframe_states *states, void *op_arg)
+{
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&lock, flags);
+	states->vf_pool_size = VF_POOL_SIZE;
+
+	i = put_ptr - fill_ptr;
+	if (i < 0)
+		i += VF_POOL_SIZE;
+	states->buf_free_num = i;
+
+	i = putting_ptr - put_ptr;
+	if (i < 0)
+		i += VF_POOL_SIZE;
+	states->buf_recycle_num = i;
+
+	i = fill_ptr - get_ptr;
+	if (i < 0)
+		i += VF_POOL_SIZE;
+	states->buf_avail_num = i;
+
+	spin_unlock_irqrestore(&lock, flags);
+	return 0;
+}
+
+void send_drop_cmd(void)
+{
+	int ready_cnt = 0;
+	int temp_get_ptr = get_ptr;
+	int temp_fill_ptr = fill_ptr;
+
+	while (temp_get_ptr != temp_fill_ptr) {
+		if ((vfpool_idx[temp_get_ptr].view0_buf_id >= 0)
+			&& (vfpool_idx[temp_get_ptr].view1_buf_id >= 0)
+			&& (vfpool_idx[temp_get_ptr].view0_drop == 0)
+			&& (vfpool_idx[temp_get_ptr].view1_drop == 0))
+			ready_cnt++;
+		INCPTR(temp_get_ptr);
+	}
+	if (dbg_mode & 0x40) {
+		pr_info("ready_cnt is %d ; no_dropping_cnt is %d\n", ready_cnt,
+			   no_dropping_cnt);
+	}
+	if ((no_dropping_cnt >= DROPPING_FIRST_WAIT)
+		&& (ready_cnt < drop_thread_hold))
+		WRITE_VREG(DROP_CONTROL, (1 << 31) | (drop_rate));
+	else
+		WRITE_VREG(DROP_CONTROL, 0);
+}
+
+#if 0
+int get_valid_frame(void)
+{
+	int ready_cnt = 0;
+	int temp_get_ptr = get_ptr;
+	int temp_fill_ptr = fill_ptr;
+
+	while (temp_get_ptr != temp_fill_ptr) {
+		if ((vfpool_idx[temp_get_ptr].view0_buf_id >= 0)
+			&& (vfpool_idx[temp_get_ptr].view1_buf_id >= 0)
+			&& (vfpool_idx[temp_get_ptr].view0_drop == 0)
+			&& (vfpool_idx[temp_get_ptr].view1_drop == 0))
+			ready_cnt++;
+		INCPTR(temp_get_ptr);
+	}
+	return ready_cnt;
+}
+#endif
+static struct vframe_s *vh264mvc_vf_peek(void *op_arg)
+{
+
+	if (get_ptr == fill_ptr)
+		return NULL;
+	send_drop_cmd();
+	return &vfpool[get_ptr];
+
+}
+
+static struct vframe_s *vh264mvc_vf_get(void *op_arg)
+{
+	struct vframe_s *vf;
+	int view0_buf_id;
+	int view1_buf_id;
+	struct buffer_spec_s *buf_spec_0, *buf_spec_1;
+
+	if (get_ptr == fill_ptr)
+		return NULL;
+
+	view0_buf_id = vfpool_idx[get_ptr].view0_buf_id;
+	view1_buf_id = vfpool_idx[get_ptr].view1_buf_id;
+	vf = &vfpool[get_ptr];
+
+	if ((view0_buf_id >= 0) && (view1_buf_id >= 0)) {
+		if (view_mode == 0 || view_mode == 1) {
+			vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
+
+			buf_spec_0 = (view_mode == 0) ? (&buffer_spec0[view0_buf_id]) :
+					(&buffer_spec1[view1_buf_id]);
+			vf->canvas0Addr = vf->canvas1Addr = spec2canvas(buf_spec_0);
+
+			if (is_support_vdec_canvas()) {
+				vf->canvas0Addr = vf->canvas1Addr = -1;
+				vf->canvas0_config[0].block_mode = CANVAS_BLKMODE_32X32;
+				vf->canvas0_config[0].phy_addr = buf_spec_0->y_addr;
+				vf->canvas0_config[0].width = vdec_cav_get_width(buf_spec_0->y_canvas_index);
+				vf->canvas0_config[0].height = vdec_cav_get_height(buf_spec_0->y_canvas_index);
+				vf->canvas0_config[1].block_mode = CANVAS_BLKMODE_32X32;
+				vf->canvas0_config[1].phy_addr = buf_spec_0->u_addr;
+				vf->canvas0_config[1].width = vdec_cav_get_width(buf_spec_0->u_canvas_index);
+				vf->canvas0_config[1].height = vdec_cav_get_height(buf_spec_0->u_canvas_index);
+				vf->canvas0_config[2].block_mode = CANVAS_BLKMODE_32X32;
+				vf->canvas0_config[2].phy_addr = buf_spec_0->v_addr;
+				vf->canvas0_config[2].width = vdec_cav_get_width(buf_spec_0->v_canvas_index);
+				vf->canvas0_config[2].height = vdec_cav_get_height(buf_spec_0->v_canvas_index);
+				vf->plane_num = 3;
+			}
+		} else {
+			vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_MVC;
+
+			vf->left_eye.start_x = 0;
+			vf->left_eye.start_y = 0;
+			vf->left_eye.width = vf->width;
+			vf->left_eye.height = vf->height;
+			vf->right_eye.start_x = 0;
+			vf->right_eye.start_y = 0;
+			vf->right_eye.width = vf->width;
+			vf->right_eye.height = vf->height;
+			//vf->trans_fmt = TVIN_TFMT_3D_TB;
+
+			if (view_mode == 2) {
+				buf_spec_0 = &buffer_spec1[view1_buf_id];
+				buf_spec_1 = &buffer_spec0[view0_buf_id];
+			} else {
+				buf_spec_0 = &buffer_spec0[view0_buf_id];
+				buf_spec_1 = &buffer_spec1[view1_buf_id];
+			}
+			if (is_support_vdec_canvas()) {
+				vf->canvas0Addr = vf->canvas1Addr = -1;
+				vf->canvas0_config[0].block_mode = CANVAS_BLKMODE_32X32;
+				vf->canvas0_config[0].phy_addr = buf_spec_0->y_addr;
+				vf->canvas0_config[0].width = vdec_cav_get_width(buf_spec_0->y_canvas_index);
+				vf->canvas0_config[0].height = vdec_cav_get_height(buf_spec_0->y_canvas_index);
+				vf->canvas0_config[1].block_mode = CANVAS_BLKMODE_32X32;
+				vf->canvas0_config[1].phy_addr = buf_spec_0->u_addr;
+				vf->canvas0_config[1].width = vdec_cav_get_width(buf_spec_0->u_canvas_index);
+				vf->canvas0_config[1].height = vdec_cav_get_height(buf_spec_0->u_canvas_index);
+				vf->canvas0_config[2].block_mode = CANVAS_BLKMODE_32X32;
+				vf->canvas0_config[2].phy_addr = buf_spec_0->v_addr;
+				vf->canvas0_config[2].width = vdec_cav_get_width(buf_spec_0->v_canvas_index);
+				vf->canvas0_config[2].height = vdec_cav_get_height(buf_spec_0->v_canvas_index);
+
+				vf->canvas1_config[0].block_mode = CANVAS_BLKMODE_32X32;
+				vf->canvas1_config[0].phy_addr = buf_spec_1->y_addr;
+				vf->canvas1_config[0].width = vdec_cav_get_width(buf_spec_1->y_canvas_index);
+				vf->canvas1_config[0].height = vdec_cav_get_height(buf_spec_1->y_canvas_index);
+				vf->canvas1_config[1].block_mode = CANVAS_BLKMODE_32X32;
+				vf->canvas1_config[1].phy_addr = buf_spec_1->u_addr;
+				vf->canvas1_config[1].width = vdec_cav_get_width(buf_spec_1->u_canvas_index);
+				vf->canvas1_config[1].height = vdec_cav_get_height(buf_spec_1->u_canvas_index);
+				vf->canvas1_config[2].block_mode = CANVAS_BLKMODE_32X32;
+				vf->canvas1_config[2].phy_addr = buf_spec_1->v_addr;
+				vf->canvas1_config[2].width = vdec_cav_get_width(buf_spec_1->v_canvas_index);
+				vf->canvas1_config[2].height = vdec_cav_get_height(buf_spec_1->v_canvas_index);
+				vf->plane_num = 3;
+			} else {
+				vf->canvas0Addr = spec2canvas(buf_spec_0);
+				vf->canvas1Addr = spec2canvas(buf_spec_1);
+			}
+		}
+	}
+
+	vf->type_original = vf->type;
+	if (((vfpool_idx[get_ptr].view0_drop != 0)
+		 || (vfpool_idx[get_ptr].view1_drop != 0))
+		&& ((no_dropping_cnt >= DROPPING_FIRST_WAIT)))
+		vf->frame_dirty = 1;
+	else
+		vf->frame_dirty = 0;
+
+	INCPTR(get_ptr);
+
+	if (frame_width == 0)
+		frame_width = vh264mvc_amstream_dec_info.width;
+	if (frame_height == 0)
+		frame_height = vh264mvc_amstream_dec_info.height;
+
+	vf->width = frame_width;
+	vf->height = frame_height;
+
+	if ((no_dropping_cnt < DROPPING_FIRST_WAIT) && (vf->frame_dirty == 0))
+		no_dropping_cnt++;
+	return vf;
+
+}
+
+static void vh264mvc_vf_put(struct vframe_s *vf, void *op_arg)
+{
+
+	if (vf_buf_init_flag == 0)
+		return;
+	if (vf->frame_dirty) {
+
+		vf->frame_dirty = 0;
+		dirty_frame_num++;
+		enable_recycle = 0;
+		if (dbg_mode & PUT_PRINT_ENABLE) {
+			pr_info("invalid: dirty_frame_num is !!! %d\n",
+				   dirty_frame_num);
+		}
+	} else {
+		INCPTR(putting_ptr);
+		while (dirty_frame_num > 0) {
+			INCPTR(putting_ptr);
+			dirty_frame_num--;
+		}
+		enable_recycle = 1;
+		if (dbg_mode & PUT_PRINT_ENABLE) {
+			pr_info("valid: dirty_frame_num is @@@ %d\n",
+				   dirty_frame_num);
+		}
+		/* send_drop_cmd(); */
+	}
+
+}
+
+static int vh264mvc_event_cb(int type, void *data, void *private_data)
+{
+	if (type & VFRAME_EVENT_RECEIVER_RESET) {
+		unsigned long flags;
+
+		amvdec_stop();
+#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+		vf_light_unreg_provider(&vh264mvc_vf_prov);
+#endif
+		spin_lock_irqsave(&lock, flags);
+		vh264mvc_local_init();
+		vh264mvc_prot_init();
+		spin_unlock_irqrestore(&lock, flags);
+#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
+		vf_reg_provider(&vh264mvc_vf_prov);
+#endif
+		amvdec_start();
+	}
+	return 0;
+}
+
+/**/
+static long init_canvas(int view_index, int refbuf_size, long dpb_size,
+		int dpb_number,	int mb_width, int mb_height,
+		struct buffer_spec_s *buffer_spec)
+{
+
+	unsigned long addr;
+	int i, j, bmmu_index;
+	int mb_total, ret = -1;
+	/* cav_con canvas; */
+	mb_total = mb_width * mb_height;
+	mutex_lock(&vh264_mvc_mutex);
+
+	for (j = 0; j < (dpb_number + 1); j++) {
+		int page_count;
+		if (j == 0) {
+			if (!view_index)
+				bmmu_index = 1;
+			else
+				bmmu_index =  dpb_number + 2;
+
+			ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle,
+				bmmu_index, refbuf_size, DRIVER_NAME,
+				&ref_start_addr[view_index]);
+
+			if (ret < 0) {
+				mutex_unlock(&vh264_mvc_mutex);
+				return ret;
+			}
+
+			continue;
+		}
+		 /* canvas buf */
+		WRITE_VREG(ANC_CANVAS_ADDR,
+				index | ((index + 1) << 8) |
+				((index + 2) << 16));
+		ANC_CANVAS_ADDR++;
+
+			i = j - 1;
+		if (!view_index)
+			bmmu_index = VF_BUFFER_IDX(i);
+		else
+			bmmu_index	= VF_BUFFER_IDX(i) + dpb_number + 1;
+#ifdef DOUBLE_WRITE
+		 page_count = PAGE_ALIGN((mb_total << 8) + (mb_total << 7) +
+				(mb_total << 6) + (mb_total << 5)) / PAGE_SIZE;
+#else
+		 page_count = PAGE_ALIGN((mb_total << 8) +
+				(mb_total << 7)) / PAGE_SIZE;
+#endif
+
+		ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle,
+			bmmu_index, page_count << PAGE_SHIFT,
+			DRIVER_NAME, &buffer_spec[i].phy_addr);
+
+		if (ret < 0) {
+			buffer_spec[i].alloc_count = 0;
+			mutex_unlock(&vh264_mvc_mutex);
+			return ret;
+		}
+
+		addr = buffer_spec[i].phy_addr;
+		buffer_spec[i].alloc_count = page_count;
+		buffer_spec[i].y_addr = addr;
+		buffer_spec[i].y_canvas_index = index;
+		config_cav_lut_ex(index, addr,
+			mb_width << 4, mb_height << 4,
+			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32, 0, VDEC_1);
+
+		addr += mb_total << 8;
+		index++;
+		buffer_spec[i].u_addr = addr;
+		buffer_spec[i].u_canvas_index = index;
+		config_cav_lut_ex(index, addr, mb_width << 3, mb_height << 3,
+				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32, 0, VDEC_1);
+
+		addr += mb_total << 6;
+		index++;
+		buffer_spec[i].v_addr = addr;
+		buffer_spec[i].v_canvas_index = index;
+		config_cav_lut_ex(index, addr, mb_width << 3, mb_height << 3,
+				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32, 0, VDEC_1);
+
+		index++;
+	}
+	mutex_unlock(&vh264_mvc_mutex);
+	return 0;
+}
+
+static int get_max_dec_frame_buf_size(int level_idc,
+		int max_reference_frame_num, int mb_width,
+		int mb_height)
+{
+	int pic_size = mb_width * mb_height * 384;
+
+	int size = 0;
+
+	switch (level_idc) {
+	case 9:
+		size = 152064;
+		break;
+	case 10:
+		size = 152064;
+		break;
+	case 11:
+		size = 345600;
+		break;
+	case 12:
+		size = 912384;
+		break;
+	case 13:
+		size = 912384;
+		break;
+	case 20:
+		size = 912384;
+		break;
+	case 21:
+		size = 1824768;
+		break;
+	case 22:
+		size = 3110400;
+		break;
+	case 30:
+		size = 3110400;
+		break;
+	case 31:
+		size = 6912000;
+		break;
+	case 32:
+		size = 7864320;
+		break;
+	case 40:
+		size = 12582912;
+		break;
+	case 41:
+		size = 12582912;
+		break;
+	case 42:
+		size = 13369344;
+		break;
+	case 50:
+		size = 42393600;
+		break;
+	case 51:
+		size = 70778880;
+		break;
+	default:
+		break;
+	}
+
+	size /= pic_size;
+	size = size + 1;	/* For MVC need onr more buffer */
+	if (max_reference_frame_num > size)
+		size = max_reference_frame_num;
+	if (size > DECODE_BUFFER_NUM_MAX)
+		size = DECODE_BUFFER_NUM_MAX;
+
+	return size;
+}
+
+int check_in_list(int pos, int *slot)
+{
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		if ((vfpool_idx[i].display_pos == pos)
+			&& (vfpool_idx[i].used == 0)) {
+			ret = 1;
+			*slot = vfpool_idx[i].slot;
+			break;
+		}
+	}
+	return ret;
+}
+
+static void do_alloc_work(struct work_struct *work)
+{
+	int level_idc, max_reference_frame_num, mb_width, mb_height;
+	int refbuf_size;
+	int ret = READ_VREG(MAILBOX_COMMAND);
+
+	switch (ret & 0xff) {
+	case CMD_ALLOC_VIEW_0:
+		if (dbg_mode & 0x1) {
+			pr_info
+			("Start H264 display buffer for view 0\n");
+		}
+
+		ret = READ_VREG(MAILBOX_DATA_0);
+		level_idc = (ret >> 24) & 0xff;
+		max_reference_frame_num = (ret >> 16) & 0xff;
+		mb_width = (ret >> 8) & 0xff;
+		mb_height = (ret >> 0) & 0xff;
+		max_dec_frame_buffering[0] =
+			get_max_dec_frame_buf_size(level_idc,
+					max_reference_frame_num,
+					mb_width, mb_height);
+
+		total_dec_frame_buffering[0] =
+			max_dec_frame_buffering[0] + dynamic_buf_num_margin;
+
+		mb_width = (mb_width + 3) & 0xfffffffc;
+		mb_height = (mb_height + 3) & 0xfffffffc;
+
+		dpb_size = mb_width * mb_height * 384;
+		ref_size = mb_width * mb_height * 96;
+
+		if (dbg_mode & 0x1) {
+			pr_info("dpb_size: 0x%x\n", dpb_size);
+			pr_info("ref_size: 0x%x\n", ref_size);
+			pr_info("total_dec_frame_buffering[0] : 0x%x\n",
+				   total_dec_frame_buffering[0]);
+			pr_info("max_reference_frame_num: 0x%x\n",
+				   max_reference_frame_num);
+		}
+		refbuf_size
+			= ref_size * (max_reference_frame_num + 1) * 2;
+
+		if (is_support_vdec_canvas())
+			index = 0;
+		else
+			index = CANVAS_INDEX_START;
+		ANC_CANVAS_ADDR = ANC0_CANVAS_ADDR;
+
+		ret =
+			init_canvas(0, refbuf_size, dpb_size,
+				total_dec_frame_buffering[0], mb_width,
+				mb_height, buffer_spec0);
+
+		if (ret < 0) {
+			pr_info(" Un-expected memory alloc problem\n");
+			return;
+		}
+
+		WRITE_VREG(REF_START_VIEW_0,
+				   video_domain_addr(ref_start_addr[0]));
+		WRITE_VREG(MAILBOX_DATA_0,
+			   (max_dec_frame_buffering[0] << 8) |
+			   (total_dec_frame_buffering[0] << 0));
+		WRITE_VREG(MAILBOX_DATA_1, ref_size);
+		WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED);
+
+		if (dbg_mode & 0x1) {
+			pr_info
+			("End H264 display buffer for view 0\n");
+		}
+		if (frame_width == 0) {
+			if (vh264mvc_amstream_dec_info.width)
+				frame_width = vh264mvc_amstream_dec_info.width;
+			else
+				frame_width = mb_width << 4;
+		}
+		if (frame_height == 0) {
+			frame_height = mb_height << 4;
+			if (frame_height == 1088)
+				frame_height = 1080;
+		}
+		break;
+	case CMD_ALLOC_VIEW_1:
+		if (dbg_mode & 0x1) {
+			pr_info
+			("Start H264 display buffer for view 1\n");
+		}
+
+		ret = READ_VREG(MAILBOX_DATA_0);
+		level_idc = (ret >> 24) & 0xff;
+		max_reference_frame_num = (ret >> 16) & 0xff;
+		mb_width = (ret >> 8) & 0xff;
+		mb_height = (ret >> 0) & 0xff;
+		max_dec_frame_buffering[1] =
+			get_max_dec_frame_buf_size(level_idc,
+					max_reference_frame_num,
+					mb_width, mb_height);
+		if (max_dec_frame_buffering[1] != max_dec_frame_buffering[0]) {
+			pr_info
+			(" Warning: view0/1 max_dec_frame_buffering ");
+			pr_info("different : 0x%x/0x%x, Use View0\n",
+			 max_dec_frame_buffering[0],
+			 max_dec_frame_buffering[1]);
+			max_dec_frame_buffering[1] = max_dec_frame_buffering[0];
+		}
+
+		total_dec_frame_buffering[1] =
+			max_dec_frame_buffering[1] + dynamic_buf_num_margin;
+
+		mb_width = (mb_width + 3) & 0xfffffffc;
+		mb_height = (mb_height + 3) & 0xfffffffc;
+
+		dpb_size = mb_width * mb_height * 384;
+		ref_size = mb_width * mb_height * 96;
+		refbuf_size = ref_size * (max_reference_frame_num + 1) * 2;
+		if (dbg_mode & 0x1) {
+			pr_info("dpb_size: 0x%x\n", dpb_size);
+			pr_info("ref_size: 0x%x\n", ref_size);
+			pr_info("total_dec_frame_buffering[1] : 0x%x\n",
+				   total_dec_frame_buffering[1]);
+			pr_info("max_reference_frame_num: 0x%x\n",
+				   max_reference_frame_num);
+		}
+
+		if (is_support_vdec_canvas())
+			index = total_dec_frame_buffering[0] * 3;
+		else
+			index = CANVAS_INDEX_START + total_dec_frame_buffering[0] * 3;
+		ANC_CANVAS_ADDR =
+			ANC0_CANVAS_ADDR + total_dec_frame_buffering[0];
+
+		ret = init_canvas(1, refbuf_size, dpb_size,
+				total_dec_frame_buffering[1], mb_width,
+				mb_height, buffer_spec1);
+
+		if (ret < 0) {
+			pr_info(" Un-expected memory alloc problem\n");
+			return;
+		}
+
+		WRITE_VREG(REF_START_VIEW_1,
+				   video_domain_addr(ref_start_addr[1]));
+		WRITE_VREG(MAILBOX_DATA_0,
+			   (max_dec_frame_buffering[1] << 8) |
+			   (total_dec_frame_buffering[1] << 0));
+		WRITE_VREG(MAILBOX_DATA_1, ref_size);
+		WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED);
+
+		if (dbg_mode & 0x1) {
+			pr_info
+			("End H264 buffer allocation for view 1\n");
+		}
+		if (frame_width == 0) {
+			if (vh264mvc_amstream_dec_info.width)
+				frame_width = vh264mvc_amstream_dec_info.width;
+			else
+				frame_width = mb_width << 4;
+		}
+		if (frame_height == 0) {
+			frame_height = mb_height << 4;
+			if (frame_height == 1088)
+				frame_height = 1080;
+		}
+	break;
+	}
+
+}
+
+static void mvc_set_rp(void) {
+	unsigned long flags;
+
+	spin_lock_irqsave(&mvc_rp_lock, flags);
+	STBUF_WRITE(&vdec->vbuf, set_rp,
+		READ_VREG(VLD_MEM_VIFIFO_RP));
+	spin_unlock_irqrestore(&mvc_rp_lock, flags);
+}
+
+#ifdef HANDLE_h264mvc_IRQ
+static irqreturn_t vh264mvc_isr(int irq, void *dev_id)
+#else
+static void vh264mvc_isr(void)
+#endif
+{
+	int drop_status;
+	struct vframe_s *vf;
+	unsigned int pts, pts_valid = 0;
+	u64 pts_us64;
+	u32 frame_size;
+	int ret = READ_VREG(MAILBOX_COMMAND);
+
+	mvc_set_rp();
+
+	/* pr_info("vh264mvc_isr, cmd =%x\n", ret); */
+	switch (ret & 0xff) {
+	case CMD_ALLOC_VIEW_0:
+	case CMD_ALLOC_VIEW_1:
+		schedule_work(&alloc_work);
+		break;
+	case CMD_FRAME_DISPLAY:
+		ret = READ_VREG(MAILBOX_DATA_0);
+		display_buff_id = (ret >> 0) & 0x3f;
+		display_view_id = (ret >> 6) & 0x3;
+		drop_status = (ret >> 8) & 0x1;
+		display_POC = READ_VREG(MAILBOX_DATA_1);
+		stream_offset = READ_VREG(MAILBOX_DATA_2);
+		/* if (display_view_id == 0) */
+		WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED);
+
+#ifdef DEBUG_SKIP
+		view_total++;
+		if (drop_status)
+			view_dropped++;
+#endif
+		if (dbg_mode & 0x1) {
+			pr_info
+			(" H264 display frame ready - View : %x, Buffer : %x\n",
+			 display_view_id, display_buff_id);
+			pr_info
+			(" H264 display frame POC -- Buffer : %x, POC : %x\n",
+			 display_buff_id, display_POC);
+			pr_info("H264 display frame ready\n");
+		}
+		if (dbg_mode & 0x10) {
+			if ((dbg_mode & 0x20) == 0) {
+				while (READ_VREG(BUFFER_RECYCLE) != 0)
+					;
+				WRITE_VREG(BUFFER_RECYCLE,
+						   (display_view_id << 8) |
+						   (display_buff_id + 1));
+				display_buff_id = -1;
+				display_view_id = -1;
+				display_POC = -1;
+			}
+		} else {
+			unsigned char in_list_flag = 0;
+
+			int slot = 0;
+
+			in_list_flag = check_in_list(display_POC, &slot);
+
+			if ((dbg_mode & 0x40) && (drop_status)) {
+				pr_info
+				("drop_status:%dview_id=%d,buff_id=%d,",
+				 drop_status, display_view_id, display_buff_id);
+				 pr_info
+				("offset=%d, display_POC = %d,fill_ptr=0x%x\n",
+				 stream_offset, display_POC, fill_ptr);
+			}
+
+			if ((in_list_flag) && (stream_offset != 0)) {
+				pr_info
+				("error case ,display_POC is %d, slot is %d\n",
+				 display_POC, slot);
+				in_list_flag = 0;
+			}
+			if (!in_list_flag) {
+				if (display_view_id == 0) {
+					vfpool_idx[fill_ptr].view0_buf_id =
+						display_buff_id;
+					view0_vfbuf_use[display_buff_id]++;
+					vfpool_idx[fill_ptr].stream_offset =
+						stream_offset;
+					vfpool_idx[fill_ptr].view0_drop =
+						drop_status;
+				}
+				if (display_view_id == 1) {
+					vfpool_idx[fill_ptr].view1_buf_id =
+						display_buff_id;
+					vfpool_idx[fill_ptr].view1_drop =
+						drop_status;
+					view1_vfbuf_use[display_buff_id]++;
+				}
+				vfpool_idx[fill_ptr].slot = fill_ptr;
+				vfpool_idx[fill_ptr].display_pos = display_POC;
+
+			} else {
+				if (display_view_id == 0) {
+					vfpool_idx[slot].view0_buf_id =
+						display_buff_id;
+					view0_vfbuf_use[display_buff_id]++;
+					vfpool_idx[slot].stream_offset =
+						stream_offset;
+					vfpool_idx[slot].view0_drop =
+						drop_status;
+
+				}
+				if (display_view_id == 1) {
+					vfpool_idx[slot].view1_buf_id =
+						display_buff_id;
+					view1_vfbuf_use[display_buff_id]++;
+					vfpool_idx[slot].view1_drop =
+						drop_status;
+				}
+				vf = &vfpool[slot];
+
+				if (display_view_id == 0) {
+					vf->mem_handle =
+					decoder_bmmu_box_get_mem_handle(
+						mm_blk_handle,
+						VF_BUFFER_IDX(display_buff_id));
+
+				} else if (display_view_id == 1) {
+					vf->mem_head_handle =
+					decoder_bmmu_box_get_mem_handle(
+						mm_blk_handle,
+						VF_BUFFER_IDX(display_buff_id));
+
+					vf->mem_handle =
+					decoder_bmmu_box_get_mem_handle(
+						mm_blk_handle,
+						VF_BUFFER_IDX(display_buff_id)
+						+ total_dec_frame_buffering[0]
+						+ 1);
+				}
+
+
+
+				if (vfpool_idx[slot].stream_offset == 0) {
+					pr_info
+					("error case, invalid stream offset\n");
+				}
+				if (pts_lookup_offset_us64
+					(PTS_TYPE_VIDEO,
+					 vfpool_idx[slot].stream_offset, &pts,
+					 &frame_size,
+					 0x10000, &pts_us64) == 0)
+					pts_valid = 1;
+				else
+					pts_valid = 0;
+				vf->pts = (pts_valid) ? pts : 0;
+				vf->pts_us64 = (pts_valid) ? pts_us64 : 0;
+				/* vf->pts =  vf->pts_us64 ? vf->pts_us64
+				 *   : vf->pts ;
+				 */
+				/* vf->pts =  vf->pts_us64; */
+				if (dbg_mode & 0x80)
+					pr_info("vf->pts:%d\n", vf->pts);
+				vfpool_idx[slot].used = 1;
+				INCPTR(fill_ptr);
+				set_frame_info(vf);
+
+				gvs->frame_dur = frame_dur;
+				vdec_count_info(gvs, 0,
+						vfpool_idx[slot].stream_offset);
+
+				vf_notify_receiver(PROVIDER_NAME,
+					VFRAME_EVENT_PROVIDER_VFRAME_READY,
+					NULL);
+
+			}
+		}
+		break;
+	case CMD_FATAL_ERROR:
+		pr_info("fatal error !!!\n");
+		schedule_work(&error_wd_work);
+		break;
+	default:
+		break;
+	}
+#ifdef HANDLE_h264mvc_IRQ
+	return IRQ_HANDLED;
+#else
+	return;
+#endif
+}
+
+static void vh264_mvc_set_clk(struct work_struct *work)
+{
+	if (frame_dur > 0 && saved_resolution !=
+		frame_width * frame_height * (96000 / frame_dur)) {
+		int fps = 96000 / frame_dur;
+
+		saved_resolution = frame_width * frame_height * fps;
+		vdec_source_changed(VFORMAT_H264MVC,
+			frame_width, frame_height, fps * 2);
+	}
+}
+
+static void vh264mvc_put_timer_func(struct timer_list *timer)
+{
+	int valid_frame = 0;
+
+	mvc_set_rp();
+
+	if (enable_recycle == 0) {
+		if (dbg_mode & TIME_TASK_PRINT_ENABLE) {
+			/* valid_frame = get_valid_frame(); */
+			pr_info("dirty_frame_num is %d , valid frame is %d\n",
+				   dirty_frame_num, valid_frame);
+
+		}
+		/* goto RESTART; */
+	}
+
+	while ((putting_ptr != put_ptr) && (READ_VREG(BUFFER_RECYCLE) == 0)) {
+		int view0_buf_id = vfpool_idx[put_ptr].view0_buf_id;
+		int view1_buf_id = vfpool_idx[put_ptr].view1_buf_id;
+
+		if ((view0_buf_id >= 0) &&
+				(view0_vfbuf_use[view0_buf_id] == 1)) {
+			if (dbg_mode & 0x100) {
+				pr_info
+				("round 0: put_ptr is %d ;view0_buf_id is %d\n",
+				 put_ptr, view0_buf_id);
+			}
+			WRITE_VREG(BUFFER_RECYCLE,
+					   (0 << 8) | (view0_buf_id + 1));
+			view0_vfbuf_use[view0_buf_id] = 0;
+			vfpool_idx[put_ptr].view0_buf_id = -1;
+			vfpool_idx[put_ptr].view0_drop = 0;
+		} else if ((view1_buf_id >= 0)
+				   && (view1_vfbuf_use[view1_buf_id] == 1)) {
+			if (dbg_mode & 0x100) {
+				pr_info
+				("round 1: put_ptr is %d ;view1_buf_id %d==\n",
+				 put_ptr, view1_buf_id);
+			}
+			WRITE_VREG(BUFFER_RECYCLE,
+					   (1 << 8) | (view1_buf_id + 1));
+			view1_vfbuf_use[view1_buf_id] = 0;
+			vfpool_idx[put_ptr].display_pos = DISPLAY_INVALID_POS;
+			vfpool_idx[put_ptr].view1_buf_id = -1;
+			vfpool_idx[put_ptr].view1_drop = 0;
+			vfpool_idx[put_ptr].used = 0;
+			INCPTR(put_ptr);
+		}
+	}
+
+	schedule_work(&set_clk_work);
+
+	/* RESTART: */
+	timer->expires = jiffies + PUT_INTERVAL;
+
+	add_timer(timer);
+}
+
+int vh264mvc_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
+{
+	vstatus->frame_width = frame_width;
+	vstatus->frame_height = frame_height;
+	if (frame_dur != 0)
+		vstatus->frame_rate = 96000 / frame_dur;
+	else
+		vstatus->frame_rate = -1;
+	vstatus->error_count = READ_VREG(AV_SCRATCH_D);
+	vstatus->status = stat;
+	vstatus->bit_rate = gvs->bit_rate;
+	vstatus->frame_dur = frame_dur;
+	vstatus->frame_data = gvs->frame_data;
+	vstatus->total_data = gvs->total_data;
+	vstatus->frame_count = gvs->frame_count;
+	vstatus->error_frame_count = gvs->error_frame_count;
+	vstatus->drop_frame_count = gvs->drop_frame_count;
+	vstatus->total_data = gvs->total_data;
+	vstatus->samp_cnt = gvs->samp_cnt;
+	vstatus->offset = gvs->offset;
+	snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
+		"%s", DRIVER_NAME);
+
+	return 0;
+}
+
+static int vh264mvc_vdec_info_init(void)
+{
+	gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL);
+	if (NULL == gvs) {
+		pr_info("the struct of vdec status malloc failed.\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+int vh264mvc_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
+{
+	if (trickmode == TRICKMODE_I) {
+		WRITE_VREG(AV_SCRATCH_F,
+				   (READ_VREG(AV_SCRATCH_F) & 0xfffffffc) | 2);
+		trickmode_i = 1;
+	} else if (trickmode == TRICKMODE_NONE) {
+		WRITE_VREG(AV_SCRATCH_F, READ_VREG(AV_SCRATCH_F) & 0xfffffffc);
+		trickmode_i = 0;
+	}
+
+	return 0;
+}
+
+static void H264_DECODE_INIT(void)
+{
+	int i;
+
+	i = READ_VREG(DECODE_SKIP_PICTURE);
+
+#if 1				/* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	READ_VREG(DOS_SW_RESET0);
+	READ_VREG(DOS_SW_RESET0);
+	READ_VREG(DOS_SW_RESET0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	READ_VREG(DOS_SW_RESET0);
+	READ_VREG(DOS_SW_RESET0);
+	READ_VREG(DOS_SW_RESET0);
+
+#else
+	WRITE_RESET_REG(RESET0_REGISTER,
+				   RESET_IQIDCT | RESET_MC | RESET_VLD_PART);
+	READ_RESET_REG(RESET0_REGISTER);
+	WRITE_RESET_REG(RESET0_REGISTER,
+				   RESET_IQIDCT | RESET_MC | RESET_VLD_PART);
+	WRITE_RESET_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK);
+#endif
+
+	/* Wait for some time for RESET */
+	READ_VREG(DECODE_SKIP_PICTURE);
+	READ_VREG(DECODE_SKIP_PICTURE);
+
+	WRITE_VREG(DECODE_SKIP_PICTURE, i);
+
+	/* fill_weight_pred */
+	WRITE_VREG(MC_MPORT_CTRL, 0x0300);
+	for (i = 0; i < 192; i++)
+		WRITE_VREG(MC_MPORT_DAT, 0x100);
+	WRITE_VREG(MC_MPORT_CTRL, 0);
+
+	WRITE_VREG(MB_WIDTH, 0xff);	/* invalid mb_width */
+
+	/* set slice start to 0x000000 or 0x000001 for check more_rbsp_data */
+	WRITE_VREG(SLICE_START_BYTE_01, 0x00000000);
+	WRITE_VREG(SLICE_START_BYTE_23, 0x01010000);
+	/* set to mpeg2 to enable mismatch logic */
+	WRITE_VREG(MPEG1_2_REG, 1);
+	/* disable COEF_GT_64 , error_m4_table and voff_rw_err */
+	WRITE_VREG(VLD_ERROR_MASK, 0x1011);
+
+	/* Config MCPU Amrisc interrupt */
+	WRITE_VREG(ASSIST_AMR1_INT0, 0x1);	/* viu_vsync_int */
+	WRITE_VREG(ASSIST_AMR1_INT1, 0x5);	/* mbox_isr */
+	WRITE_VREG(ASSIST_AMR1_INT2, 0x8);	/* vld_isr */
+	WRITE_VREG(ASSIST_AMR1_INT3, 0x15);	/* vififo_empty */
+	WRITE_VREG(ASSIST_AMR1_INT4, 0xd);	/* rv_ai_mb_finished_int */
+	WRITE_VREG(ASSIST_AMR1_INT7, 0x14);	/* dcac_dma_done */
+
+	/* Config MCPU Amrisc interrupt */
+	WRITE_VREG(ASSIST_AMR1_INT5, 0x9);	/* MCPU interrupt */
+	WRITE_VREG(ASSIST_AMR1_INT6, 0x17);	/* CCPU interrupt */
+
+	WRITE_VREG(CPC_P, 0xc00);	/* CCPU Code will start from 0xc00 */
+	WRITE_VREG(CINT_VEC_BASE, (0xc20 >> 5));
+#if 0
+	WRITE_VREG(POWER_CTL_VLD,
+			READ_VREG(POWER_CTL_VLD) | (0 << 10) |
+			(1 << 9) | (1 << 6));
+#else
+	WRITE_VREG(POWER_CTL_VLD, ((1 << 10) |	/* disable cabac_step_2 */
+				(1 << 9) |	/* viff_drop_flag_en */
+				(1 << 6)	/* h264_000003_en */
+							  )
+			  );
+#endif
+	WRITE_VREG(M4_CONTROL_REG, (1 << 13));	/* H264_DECODE_INFO - h264_en */
+
+	if (is_support_vdec_canvas())
+		WRITE_VREG(CANVAS_START, 0);
+	else
+		WRITE_VREG(CANVAS_START, CANVAS_INDEX_START);
+#if 1
+	/* Start Address of Workspace (UCODE, temp_data...) */
+	WRITE_VREG(WORKSPACE_START,
+			   video_domain_addr(work_space_adr));
+#else
+	/* Start Address of Workspace (UCODE, temp_data...) */
+	WRITE_VREG(WORKSPACE_START,
+			0x05000000);
+#endif
+	/* Clear all sequence parameter set available */
+	WRITE_VREG(SPS_STATUS, 0);
+	/* Clear all picture parameter set available */
+	WRITE_VREG(PPS_STATUS, 0);
+	/* Set current microcode to NULL */
+	WRITE_VREG(CURRENT_UCODE, 0xff);
+	/* Set current SPS/PPS to NULL */
+	WRITE_VREG(CURRENT_SPS_PPS, 0xffff);
+	/* Set decode status to DECODE_START_HEADER */
+	WRITE_VREG(DECODE_STATUS, 1);
+}
+
+static void vh264mvc_prot_init(void)
+{
+	while (READ_VREG(DCAC_DMA_CTRL) & 0x8000)
+		;
+	while (READ_VREG(LMEM_DMA_CTRL) & 0x8000)
+		;		/* reg address is 0x350 */
+	/* clear mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+	/* enable mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_MASK, 1);
+
+	/* disable PSCALE for hardware sharing */
+	WRITE_VREG(PSCALE_CTRL, 0);
+
+	H264_DECODE_INIT();
+
+#if 1				/* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
+	WRITE_VREG(DOS_SW_RESET0, (1 << 11));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	READ_VREG(DOS_SW_RESET0);
+	READ_VREG(DOS_SW_RESET0);
+	READ_VREG(DOS_SW_RESET0);
+
+#else
+	WRITE_RESET_REG(RESET0_REGISTER, 0x80);	/* RESET MCPU */
+#endif
+
+	WRITE_VREG(MAILBOX_COMMAND, 0);
+	WRITE_VREG(BUFFER_RECYCLE, 0);
+	WRITE_VREG(DROP_CONTROL, 0);
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17);
+
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
+
+#if 1				/* /MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
+	WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa);
+#endif
+}
+
+static int vh264mvc_local_init(void)
+{
+	int i, size, ret;
+	display_buff_id = -1;
+	display_view_id = -1;
+	display_POC = -1;
+	no_dropping_cnt = 0;
+	init_drop_cnt = INIT_DROP_FRAME_CNT;
+
+	for (i = 0; i < INIT_DROP_FRAME_CNT; i++)
+		init_drop_frame_id[i] = 0;
+
+#ifdef DEBUG_PTS
+	pts_missed = 0;
+	pts_hit = 0;
+#endif
+
+#ifdef DEBUG_SKIP
+	view_total = 0;
+	view_dropped = 0;
+#endif
+
+	/* vh264mvc_ratio = vh264mvc_amstream_dec_info.ratio; */
+	vh264mvc_ratio = 0x100;
+
+	/* frame_width = vh264mvc_amstream_dec_info.width; */
+	/* frame_height = vh264mvc_amstream_dec_info.height; */
+	frame_dur = vh264mvc_amstream_dec_info.rate;
+	if (frame_dur == 0)
+		frame_dur = 96000 / 24;
+
+	pts_outside = ((unsigned long) vh264mvc_amstream_dec_info.param) & 0x01;
+	sync_outside = ((unsigned long) vh264mvc_amstream_dec_info.param & 0x02)
+			>> 1;
+	INIT_WORK(&alloc_work, do_alloc_work);
+
+	max_dec_frame_buffering[0] = -1;
+	max_dec_frame_buffering[1] = -1;
+	fill_ptr = get_ptr = put_ptr = putting_ptr = 0;
+	dirty_frame_num = 0;
+	for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) {
+		view0_vfbuf_use[i] = 0;
+		view1_vfbuf_use[i] = 0;
+	}
+
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		vfpool_idx[i].display_pos = -1;
+		vfpool_idx[i].view0_buf_id = DISPLAY_INVALID_POS;
+		vfpool_idx[i].view1_buf_id = -1;
+		vfpool_idx[i].view0_drop = 0;
+		vfpool_idx[i].view1_drop = 0;
+		vfpool_idx[i].used = 0;
+	}
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		memset(&vfpool[i], 0, sizeof(struct vframe_s));
+		vfpool[i].index = i;
+	}
+	init_vf_buf();
+
+	if (mm_blk_handle) {
+		decoder_bmmu_box_free(mm_blk_handle);
+		mm_blk_handle = NULL;
+	}
+
+	mm_blk_handle = decoder_bmmu_box_alloc_box(
+		DRIVER_NAME,
+		0,
+		TOTAL_BMMU_BUFF_NUM,
+		4 + PAGE_SHIFT,
+		CODEC_MM_FLAGS_CMA_CLEAR |
+		CODEC_MM_FLAGS_FOR_VDECODER);
+
+	size = DECODER_WORK_SPACE_SIZE;
+	ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, 0,
+		size, DRIVER_NAME, &work_space_adr);
+
+	return ret;
+}
+
+static s32 vh264mvc_init(void)
+{
+	int ret = -1;
+	char *buf = vmalloc(0x1000 * 16);
+
+	if (buf == NULL)
+		return -ENOMEM;
+
+	pr_info("\nvh264mvc_init\n");
+	timer_setup(&recycle_timer, vh264mvc_put_timer_func, 0);
+
+	stat |= STAT_TIMER_INIT;
+
+	ret = vh264mvc_vdec_info_init();
+	if (0 != ret) {
+		vfree(buf);
+		return -ret;
+	}
+
+	ret = vh264mvc_local_init();
+	if (ret < 0) {
+		vfree(buf);
+		return ret;
+	}
+
+	amvdec_enable();
+
+	if (tee_enabled()) {
+		ret = amvdec_loadmc_ex(VFORMAT_H264MVC, NULL, buf);
+		if (ret != 0) {
+			amvdec_disable();
+			vfree(buf);
+			pr_err("H264_MVC: the %s fw loading failed, err: %x\n",
+				tee_enabled() ? "TEE" : "local", ret);
+			return -1;
+		}
+	} else {
+		/* -- ucode loading (amrisc and swap code) */
+		mc_cpu_addr = dma_alloc_coherent(amports_get_dma_device(),
+			MC_TOTAL_SIZE, &mc_dma_handle, GFP_KERNEL);
+		if (!mc_cpu_addr) {
+			amvdec_disable();
+			vfree(buf);
+			pr_err("vh264_mvc init: Can not allocate mc memory.\n");
+			return -ENOMEM;
+		}
+
+		WRITE_VREG(UCODE_START_ADDR, mc_dma_handle);
+
+		if (get_firmware_data(VIDEO_DEC_H264_MVC, buf) < 0) {
+			pr_err("get firmware fail.");
+			vfree(buf);
+			return -1;
+		}
+
+		ret = amvdec_loadmc_ex(VFORMAT_H264MVC, NULL, buf);
+
+		/*header*/
+		memcpy((u8 *) mc_cpu_addr, buf + 0x1000, 0x1000);
+		/*mmco*/
+		memcpy((u8 *) mc_cpu_addr + 0x1000, buf + 0x2000, 0x2000);
+		/*slice*/
+		memcpy((u8 *) mc_cpu_addr + 0x3000, buf + 0x4000, 0x3000);
+
+		if (ret < 0) {
+			amvdec_disable();
+
+			dma_free_coherent(amports_get_dma_device(),
+					MC_TOTAL_SIZE,
+					mc_cpu_addr, mc_dma_handle);
+			mc_cpu_addr = NULL;
+			return -EBUSY;
+		}
+	}
+	vfree(buf);
+
+	stat |= STAT_MC_LOAD;
+
+	/* enable AMRISC side protocol */
+	vh264mvc_prot_init();
+
+#ifdef HANDLE_h264mvc_IRQ
+	if (vdec_request_irq(VDEC_IRQ_1, vh264mvc_isr,
+			"vh264mvc-irq", (void *)vh264mvc_dec_id)) {
+		pr_info("vh264mvc irq register error.\n");
+		amvdec_disable();
+		return -ENOENT;
+	}
+#endif
+
+	stat |= STAT_ISR_REG;
+
+	vf_provider_init(&vh264mvc_vf_prov, PROVIDER_NAME,
+					 &vh264mvc_vf_provider, NULL);
+	vf_reg_provider(&vh264mvc_vf_prov);
+	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL);
+
+	stat |= STAT_VF_HOOK;
+
+	recycle_timer.expires = jiffies + PUT_INTERVAL;
+	add_timer(&recycle_timer);
+
+	stat |= STAT_TIMER_ARM;
+
+	amvdec_start();
+
+	stat |= STAT_VDEC_RUN;
+
+	return 0;
+}
+
+static int vh264mvc_stop(void)
+{
+	if (stat & STAT_VDEC_RUN) {
+		amvdec_stop();
+		stat &= ~STAT_VDEC_RUN;
+	}
+
+	if (stat & STAT_ISR_REG) {
+		WRITE_VREG(ASSIST_MBOX1_MASK, 0);
+#ifdef HANDLE_h264mvc_IRQ
+		vdec_free_irq(VDEC_IRQ_1, (void *)vh264mvc_dec_id);
+#endif
+		stat &= ~STAT_ISR_REG;
+	}
+
+	if (stat & STAT_TIMER_ARM) {
+		del_timer_sync(&recycle_timer);
+		stat &= ~STAT_TIMER_ARM;
+	}
+
+	if (stat & STAT_VF_HOOK) {
+		ulong flags;
+
+		spin_lock_irqsave(&lock, flags);
+		spin_unlock_irqrestore(&lock, flags);
+		vf_unreg_provider(&vh264mvc_vf_prov);
+		stat &= ~STAT_VF_HOOK;
+	}
+
+	if (stat & STAT_MC_LOAD) {
+		if (mc_cpu_addr != NULL) {
+			dma_free_coherent(amports_get_dma_device(),
+				MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle);
+			mc_cpu_addr = NULL;
+		}
+
+		stat &= ~STAT_MC_LOAD;
+	}
+
+	amvdec_disable();
+
+	if (mm_blk_handle) {
+		decoder_bmmu_box_free(mm_blk_handle);
+		mm_blk_handle = NULL;
+	}
+	uninit_vf_buf();
+	return 0;
+}
+
+static void error_do_work(struct work_struct *work)
+{
+	if (atomic_read(&vh264mvc_active)) {
+		vh264mvc_stop();
+		vh264mvc_init();
+	}
+}
+
+static int amvdec_h264mvc_probe(struct platform_device *pdev)
+{
+	struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
+	int config_val = 0;
+
+	pr_info("amvdec_h264mvc probe start.\n");
+	mutex_lock(&vh264_mvc_mutex);
+
+#if 0
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		pr_info("\namvdec_h264mvc memory resource undefined.\n");
+		return -EFAULT;
+	}
+#endif
+
+	if (pdata == NULL) {
+		mutex_unlock(&vh264_mvc_mutex);
+		pr_info("\namvdec_h264mvc memory resource undefined.\n");
+		return -EFAULT;
+	}
+
+	if (pdata->sys_info)
+		vh264mvc_amstream_dec_info = *pdata->sys_info;
+
+	if (pdata->config_len) {
+		pr_info("pdata->config: %s\n", pdata->config);
+		if (get_config_int(pdata->config, "parm_v4l_buffer_margin",
+			&config_val) == 0)
+			dynamic_buf_num_margin = config_val;
+	}
+
+	pdata->dec_status = vh264mvc_dec_status;
+	/* pdata->set_trickmode = vh264mvc_set_trickmode; */
+
+	buffer_spec0 = (struct buffer_spec_s *)vzalloc(
+		sizeof(struct buffer_spec_s) * MAX_BMMU_BUFFER_NUM * 2);
+	if (NULL == buffer_spec0)
+		return -ENOMEM;
+	buffer_spec1 = &buffer_spec0[MAX_BMMU_BUFFER_NUM];
+
+	if (vh264mvc_init() < 0) {
+		pr_info("\namvdec_h264mvc init failed.\n");
+		kfree(gvs);
+		gvs = NULL;
+		vfree(buffer_spec0);
+		buffer_spec0 = NULL;
+		mutex_unlock(&vh264_mvc_mutex);
+		return -ENODEV;
+	}
+
+	INIT_WORK(&error_wd_work, error_do_work);
+	INIT_WORK(&set_clk_work, vh264_mvc_set_clk);
+	spin_lock_init(&mvc_rp_lock);
+
+	vdec = pdata;
+
+	atomic_set(&vh264mvc_active, 1);
+
+	mutex_unlock(&vh264_mvc_mutex);
+
+	pr_info("amvdec_h264mvc probe end.\n");
+
+	return 0;
+}
+
+static int amvdec_h264mvc_remove(struct platform_device *pdev)
+{
+	pr_info("amvdec_h264mvc_remove\n");
+	cancel_work_sync(&alloc_work);
+	cancel_work_sync(&error_wd_work);
+	cancel_work_sync(&set_clk_work);
+	vh264mvc_stop();
+	frame_width = 0;
+	frame_height = 0;
+	vdec_source_changed(VFORMAT_H264MVC, 0, 0, 0);
+	atomic_set(&vh264mvc_active, 0);
+
+#ifdef DEBUG_PTS
+	pr_info
+	("pts missed %ld, pts hit %ld, pts_outside %d, ",
+	 pts_missed, pts_hit, pts_outside);
+	 pr_info("duration %d, sync_outside %d\n",
+	 frame_dur, sync_outside);
+#endif
+
+#ifdef DEBUG_SKIP
+	pr_info("view_total = %ld, dropped %ld\n", view_total, view_dropped);
+#endif
+	vfree(buffer_spec0);
+	buffer_spec0 = NULL;
+	kfree(gvs);
+	gvs = NULL;
+
+	return 0;
+}
+
+/****************************************/
+
+static struct platform_driver amvdec_h264mvc_driver = {
+	.probe = amvdec_h264mvc_probe,
+	.remove = amvdec_h264mvc_remove,
+#ifdef CONFIG_PM
+	.suspend = amvdec_suspend,
+	.resume = amvdec_resume,
+#endif
+	.driver = {
+		.name = DRIVER_NAME,
+	}
+};
+
+static struct codec_profile_t amvdec_hmvc_profile = {
+	.name = "hmvc",
+	.profile = ""
+};
+static struct codec_profile_t amvdec_hmvc_profile_single;
+
+static struct mconfig h264mvc_configs[] = {
+	MC_PU32("stat", &stat),
+	MC_PU32("dbg_mode", &dbg_mode),
+	MC_PU32("view_mode", &view_mode),
+	MC_PU32("dbg_cmd", &dbg_cmd),
+	MC_PU32("drop_rate", &drop_rate),
+	MC_PU32("drop_thread_hold", &drop_thread_hold),
+};
+static struct mconfig_node h264mvc_node;
+
+static int __init amvdec_h264mvc_driver_init_module(void)
+{
+	pr_debug("amvdec_h264mvc module init\n");
+
+	if (platform_driver_register(&amvdec_h264mvc_driver)) {
+		pr_err("failed to register amvdec_h264mvc driver\n");
+		return -ENODEV;
+	}
+
+	vcodec_profile_register(&amvdec_hmvc_profile);
+	amvdec_hmvc_profile_single = amvdec_hmvc_profile;
+	amvdec_hmvc_profile_single.name = "h264mvc";
+	vcodec_profile_register(&amvdec_hmvc_profile_single);
+	INIT_REG_NODE_CONFIGS("media.decoder", &h264mvc_node,
+		"h264mvc", h264mvc_configs, CONFIG_FOR_RW);
+	return 0;
+}
+
+static void __exit amvdec_h264mvc_driver_remove_module(void)
+{
+	pr_debug("amvdec_h264mvc module remove.\n");
+
+	platform_driver_unregister(&amvdec_h264mvc_driver);
+}
+
+/****************************************/
+
+module_param(stat, uint, 0664);
+MODULE_PARM_DESC(stat, "\n amvdec_h264mvc stat\n");
+
+module_param(dbg_mode, uint, 0664);
+MODULE_PARM_DESC(dbg_mode, "\n amvdec_h264mvc dbg mode\n");
+
+module_param(dynamic_buf_num_margin, uint, 0664);
+MODULE_PARM_DESC(dynamic_buf_num_margin, "\n amvdec_h264mvc dynamic_buf_num_margin\n");
+
+module_param(view_mode, uint, 0664);
+MODULE_PARM_DESC(view_mode, "\n amvdec_h264mvc view mode\n");
+
+module_param(dbg_cmd, uint, 0664);
+MODULE_PARM_DESC(dbg_cmd, "\n amvdec_h264mvc cmd mode\n");
+
+module_param(drop_rate, uint, 0664);
+MODULE_PARM_DESC(drop_rate, "\n amvdec_h264mvc drop rate\n");
+
+module_param(drop_thread_hold, uint, 0664);
+MODULE_PARM_DESC(drop_thread_hold, "\n amvdec_h264mvc drop thread hold\n");
+module_init(amvdec_h264mvc_driver_init_module);
+module_exit(amvdec_h264mvc_driver_remove_module);
+
+MODULE_DESCRIPTION("AMLOGIC h264mvc Video Decoder Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Chen Zhang <chen.zhang@amlogic.com>");
diff --git a/drivers/frame_provider/decoder/h264_multi/Makefile b/drivers/frame_provider/decoder/h264_multi/Makefile
new file mode 100644
index 0000000..21dfb6a
--- /dev/null
+++ b/drivers/frame_provider/decoder/h264_multi/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H264_MULTI) += amvdec_mh264.o
+amvdec_mh264-objs += vmh264.o h264_dpb.o
diff --git a/drivers/frame_provider/decoder/h264_multi/h264_dpb.c b/drivers/frame_provider/decoder/h264_multi/h264_dpb.c
new file mode 100644
index 0000000..52d9611
--- /dev/null
+++ b/drivers/frame_provider/decoder/h264_multi/h264_dpb.c
@@ -0,0 +1,6008 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#define DEBUG
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../utils/vdec.h"
+#include "../utils/amvdec.h"
+
+#include "h264_dpb.h"
+
+#define FRAME_NUM_MAX_SIZE 0x10000
+
+#undef pr_info
+#define pr_info printk
+int dpb_print(int index, int debug_flag, const char *fmt, ...)
+{
+	if (((h264_debug_flag & debug_flag) &&
+		((1 << index) & h264_debug_mask))
+		|| (debug_flag == PRINT_FLAG_ERROR)) {
+		unsigned char *buf = kzalloc(512, GFP_ATOMIC);
+		int len = 0;
+		va_list args;
+
+		if (!buf)
+			return 0;
+
+		va_start(args, fmt);
+		len = sprintf(buf, "%d: ", index);
+		vsnprintf(buf + len, 512-len, fmt, args);
+		pr_debug("%s", buf);
+		va_end(args);
+		kfree(buf);
+	}
+	return 0;
+}
+
+int dpb_print_cont(int index, int debug_flag, const char *fmt, ...)
+{
+	if (((h264_debug_flag & debug_flag) &&
+		((1 << index) & h264_debug_mask))
+		|| (debug_flag == PRINT_FLAG_ERROR)) {
+		unsigned char *buf = kzalloc(512, GFP_ATOMIC);
+		int len = 0;
+		va_list args;
+
+		if (!buf)
+			return 0;
+
+		va_start(args, fmt);
+		vsnprintf(buf + len, 512-len, fmt, args);
+		pr_info("%s", buf);
+		va_end(args);
+		kfree(buf);
+	}
+	return 0;
+}
+
+unsigned char dpb_is_debug(int index, int debug_flag)
+{
+	if (((h264_debug_flag & debug_flag) &&
+		((1 << index) & h264_debug_mask))
+		|| (debug_flag == PRINT_FLAG_ERROR))
+		return 1;
+	return 0;
+}
+
+#define CHECK_VALID(list_size, mark) {\
+	if (list_size > MAX_LIST_SIZE || list_size < 0) { \
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_ERROR, \
+		"%s(%d): listXsize[%d] %d is larger than max size\r\n",\
+		__func__, __LINE__, mark, list_size);\
+		list_size = 0; \
+		p_H264_Dpb->dpb_error_flag = __LINE__;\
+	} \
+	}
+
+static struct DecRefPicMarking_s
+	dummy_dec_ref_pic_marking_buffer
+	[DEC_REF_PIC_MARKING_BUFFER_NUM_MAX];
+static struct StorablePicture dummy_pic;
+static struct FrameStore dummy_fs;
+static struct StorablePicture *get_new_pic(
+	struct h264_dpb_stru *p_H264_Dpb,
+	enum PictureStructure structure, unsigned char is_output);
+
+
+static void init_dummy_fs(void)
+{
+	dummy_fs.frame = &dummy_pic;
+	dummy_fs.top_field = &dummy_pic;
+	dummy_fs.bottom_field = &dummy_pic;
+
+	dummy_pic.top_field = &dummy_pic;
+	dummy_pic.bottom_field = &dummy_pic;
+	dummy_pic.frame = &dummy_pic;
+
+	dummy_pic.dec_ref_pic_marking_buffer =
+		&dummy_dec_ref_pic_marking_buffer[0];
+}
+
+enum {
+	LIST_0 = 0,
+	LIST_1 = 1,
+	BI_PRED = 2,
+	BI_PRED_L0 = 3,
+	BI_PRED_L1 = 4
+};
+
+void ref_pic_list_reordering(struct h264_dpb_stru *p_H264_Dpb,
+				struct Slice *currSlice)
+{
+	/* struct VideoParameters *p_Vid = currSlice->p_Vid;
+	 *   byte dP_nr = assignSE2partition[currSlice->dp_mode][SE_HEADER];
+	 *   DataPartition *partition = &(currSlice->partArr[dP_nr]);
+	 *   Bitstream *currStream = partition->bitstream;
+	 */
+	int i, j, val;
+	unsigned short *reorder_cmd =
+		&p_H264_Dpb->dpb_param.mmco.l0_reorder_cmd[0];
+	/* alloc_ref_pic_list_reordering_buffer(currSlice); */
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s\n", __func__);
+	if (currSlice->slice_type != I_SLICE &&
+		currSlice->slice_type != SI_SLICE) {
+		/* val = currSlice->ref_pic_list_reordering_flag[LIST_0] =
+		 *	read_u_1 ("SH: ref_pic_list_reordering_flag_l0",
+		 *		currStream, &p_Dec->UsedBits);
+		 */
+		if (reorder_cmd[0] != 3) {
+			val = currSlice->
+				ref_pic_list_reordering_flag[LIST_0] = 1;
+		} else {
+			val = currSlice->
+				ref_pic_list_reordering_flag[LIST_0] = 0;
+		}
+		if (val) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+				"%s, ref_pic_list_reordering_flag[LIST_0] is 1\n",
+				__func__);
+
+			j = 0;
+			i = 0;
+			do {
+				val = currSlice->
+				modification_of_pic_nums_idc[LIST_0][i] =
+					      reorder_cmd[j++];
+				/* read_ue_v(
+				 *	"SH: modification_of_pic_nums_idc_l0",
+				 *	currStream, &p_Dec->UsedBits);
+				 */
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					"%d(%d):val %x\n", i, j, val);
+				if (j >= 66) {
+					currSlice->
+					ref_pic_list_reordering_flag[LIST_0] =
+					0; /* by rain */
+					dpb_print(p_H264_Dpb->decoder_index,
+						PRINT_FLAG_ERROR,
+						"%s error\n", __func__);
+					break;
+				}
+				if (val == 0 || val == 1) {
+					currSlice->
+					abs_diff_pic_num_minus1[LIST_0][i] =
+					reorder_cmd[j++];
+					/* read_ue_v("SH: "
+					 *"abs_diff_pic_num_minus1_l0",
+					 *currStream, &p_Dec->UsedBits);
+					 */
+				} else {
+					if (val == 2) {
+						currSlice->
+						long_term_pic_idx[LIST_0][i] =
+						reorder_cmd[j++];
+						/* read_ue_v(
+						 *"SH: long_term_pic_idx_l0",
+						 *currStream,
+						 *&p_Dec->UsedBits);
+						 */
+					}
+				}
+				i++;
+				/* assert (i>currSlice->
+				 *	num_ref_idx_active[LIST_0]);
+				 */
+				if (
+
+/*
+ *				     i>currSlice->num_ref_idx_active[LIST_0] ||
+ */
+					i >= REORDERING_COMMAND_MAX_SIZE) {
+					dpb_print(p_H264_Dpb->decoder_index,
+						PRINT_FLAG_DPB_DETAIL,
+						"%s error %d %d\n",
+						__func__, i,
+						currSlice->
+						num_ref_idx_active[LIST_0]);
+					currSlice->
+					ref_pic_list_reordering_flag[LIST_0] =
+					0; /* by rain */
+					break;
+				}
+				if (j >= 66) {
+					dpb_print(p_H264_Dpb->decoder_index,
+						PRINT_FLAG_ERROR, "%s error\n",
+						__func__);
+					currSlice->
+					ref_pic_list_reordering_flag[LIST_0] =
+					0; /* by rain */
+					break;
+				}
+
+			} while (val != 3);
+		}
+	}
+
+	if (currSlice->slice_type == B_SLICE) {
+		reorder_cmd = &p_H264_Dpb->dpb_param.mmco.l1_reorder_cmd[0];
+		/* val = currSlice->ref_pic_list_reordering_flag[LIST_1]
+		 *= read_u_1 ("SH: ref_pic_list_reordering_flag_l1",
+		 *currStream,
+		 *&p_Dec->UsedBits);
+		 */
+
+		if (reorder_cmd[0] != 3) {
+			val =
+			currSlice->ref_pic_list_reordering_flag[LIST_1] = 1;
+		} else {
+			val =
+			currSlice->ref_pic_list_reordering_flag[LIST_1] = 0;
+		}
+
+		if (val) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+				"%s, ref_pic_list_reordering_flag[LIST_1] is 1\n",
+				__func__);
+
+			j = 0;
+			i = 0;
+			do {
+				val = currSlice->
+				modification_of_pic_nums_idc[LIST_1][i] =
+				reorder_cmd[j++];
+				/* read_ue_v(
+				 *"SH: modification_of_pic_nums_idc_l1",
+				 *currStream,
+				 *&p_Dec->UsedBits);
+				 */
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					"%d(%d):val %x\n",
+					i, j, val);
+				if (j >= 66) {
+					dpb_print(p_H264_Dpb->decoder_index,
+						PRINT_FLAG_ERROR, "%s error\n",
+						__func__);
+					currSlice->
+					ref_pic_list_reordering_flag[LIST_1] =
+					0;  /* by rain */
+					break;
+				}
+				if (val == 0 || val == 1) {
+					currSlice->
+					abs_diff_pic_num_minus1[LIST_1][i] =
+						reorder_cmd[j++];
+					/* read_ue_v(
+					 *"SH: abs_diff_pic_num_minus1_l1",
+					 *currStream, &p_Dec->UsedBits);
+					 */
+				} else {
+					if (val == 2) {
+						currSlice->
+						long_term_pic_idx[LIST_1][i] =
+						reorder_cmd[j++];
+						/* read_ue_v(
+						 *"SH: long_term_pic_idx_l1",
+						 *currStream,
+						 *&p_Dec->UsedBits);
+						 */
+					}
+				}
+				i++;
+				/* assert(i>currSlice->
+				 *	num_ref_idx_active[LIST_1]);
+				 */
+				if (
+				/*i>currSlice->num_ref_idx_active[LIST_1] || */
+					i >= REORDERING_COMMAND_MAX_SIZE) {
+					dpb_print(p_H264_Dpb->decoder_index,
+						PRINT_FLAG_DPB_DETAIL,
+						"%s error %d %d\n",
+						__func__, i,
+						currSlice->
+						num_ref_idx_active[LIST_0]);
+					currSlice->
+					ref_pic_list_reordering_flag[LIST_1] =
+					0;  /* by rain */
+					break;
+				}
+				if (j >= 66) {
+					dpb_print(p_H264_Dpb->decoder_index,
+						PRINT_FLAG_ERROR,
+						"%s error\n", __func__);
+					break;
+				}
+			} while (val != 3);
+		}
+	}
+
+	/* set reference index of redundant slices. */
+	/*
+	 *if (currSlice->redundant_pic_cnt &&
+	 *(currSlice->slice_type != I_SLICE))
+	 *{
+	 *  currSlice->redundant_slice_ref_idx =
+	 *	currSlice->abs_diff_pic_num_minus1[LIST_0][0] + 1;
+	 *}
+	 */
+}
+
+void slice_prepare(struct h264_dpb_stru *p_H264_Dpb,
+		struct DecodedPictureBuffer *p_Dpb,
+		struct VideoParameters *p_Vid,
+		struct SPSParameters *sps, struct Slice *pSlice)
+{
+	int i, j;
+	/* p_Vid->active_sps = sps; */
+	unsigned short *mmco_cmd = &p_H264_Dpb->dpb_param.mmco.mmco_cmd[0];
+	/* for decode_poc */
+	sps->pic_order_cnt_type =
+		p_H264_Dpb->dpb_param.l.data[PIC_ORDER_CNT_TYPE];
+	sps->log2_max_pic_order_cnt_lsb_minus4 =
+		p_H264_Dpb->dpb_param.l.data[LOG2_MAX_PIC_ORDER_CNT_LSB] - 4;
+	sps->num_ref_frames_in_pic_order_cnt_cycle =
+		p_H264_Dpb->
+		dpb_param.l.data[NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE];
+	for (i = 0; i < 128; i++)
+		sps->offset_for_ref_frame[i] =
+			(short) p_H264_Dpb->
+			dpb_param.mmco.offset_for_ref_frame_base[i];
+	sps->offset_for_non_ref_pic =
+		(short) p_H264_Dpb->dpb_param.l.data[OFFSET_FOR_NON_REF_PIC];
+	sps->offset_for_top_to_bottom_field =
+		(short) p_H264_Dpb->dpb_param.l.data
+		[OFFSET_FOR_TOP_TO_BOTTOM_FIELD];
+
+	pSlice->frame_num = p_H264_Dpb->dpb_param.dpb.frame_num;
+	pSlice->idr_flag =
+		(p_H264_Dpb->dpb_param.dpb.NAL_info_mmco & 0x1f)
+		== 5 ? 1 : 0;
+	pSlice->nal_reference_idc =
+		(p_H264_Dpb->dpb_param.dpb.NAL_info_mmco >> 5)
+		& 0x3;
+	pSlice->pic_order_cnt_lsb =
+		p_H264_Dpb->dpb_param.dpb.pic_order_cnt_lsb;
+	pSlice->field_pic_flag = 0;
+	pSlice->bottom_field_flag = 0;
+	pSlice->delta_pic_order_cnt_bottom = val(
+		p_H264_Dpb->dpb_param.dpb.delta_pic_order_cnt_bottom);
+	pSlice->delta_pic_order_cnt[0] = val(
+		p_H264_Dpb->dpb_param.dpb.delta_pic_order_cnt_0);
+	pSlice->delta_pic_order_cnt[1] = val(
+		p_H264_Dpb->dpb_param.dpb.delta_pic_order_cnt_1);
+
+	p_Vid->last_has_mmco_5 = 0;
+	/* last memory_management_control_operation is 5 */
+	p_Vid->last_pic_bottom_field = 0;
+	p_Vid->max_frame_num = 1 <<
+	(p_H264_Dpb->dpb_param.l.data[LOG2_MAX_FRAME_NUM]);
+
+	/**/
+	pSlice->structure = (p_H264_Dpb->
+		dpb_param.l.data[NEW_PICTURE_STRUCTURE] == 3) ?
+		FRAME : p_H264_Dpb->dpb_param.l.data[NEW_PICTURE_STRUCTURE];
+	if (pSlice->structure == FRAME) {
+		pSlice->field_pic_flag = 0;
+		pSlice->bottom_field_flag = 0;
+	} else {
+		pSlice->field_pic_flag = 1;
+		if (pSlice->structure == TOP_FIELD)
+			pSlice->bottom_field_flag = 0;
+		else
+			pSlice->bottom_field_flag = 1;
+	}
+	pSlice->pic_struct = p_H264_Dpb->dpb_param.l.data[PICTURE_STRUCT];
+
+	sps->num_ref_frames = p_H264_Dpb->
+		dpb_param.l.data[MAX_REFERENCE_FRAME_NUM];
+	sps->profile_idc =
+		 (p_H264_Dpb->dpb_param.l.data[PROFILE_IDC_MMCO] >> 8) & 0xff;
+	/*sps->max_dpb_size = p_H264_Dpb->dpb_param.l.data[MAX_DPB_SIZE];*/
+	if (pSlice->idr_flag) {
+		pSlice->long_term_reference_flag = mmco_cmd[0] & 1;
+		pSlice->no_output_of_prior_pics_flag = (mmco_cmd[0] >> 1) & 1;
+		dpb_print(p_H264_Dpb->decoder_index,
+		PRINT_FLAG_DPB_DETAIL,
+		"IDR: long_term_reference_flag %d no_output_of_prior_pics_flag %d\r\n",
+		pSlice->long_term_reference_flag,
+		pSlice->no_output_of_prior_pics_flag);
+
+		p_H264_Dpb->long_term_reference_flag = pSlice->long_term_reference_flag;
+
+		dpb_print(p_H264_Dpb->decoder_index,
+		PRINT_FLAG_DPB_DETAIL,
+		"idr set pre_frame_num(%d) to frame_num (%d)\n",
+		p_Vid->pre_frame_num, pSlice->frame_num);
+
+		p_Vid->pre_frame_num = pSlice->frame_num;
+	} else if (p_H264_Dpb->mDPB.first_pic_done == 0) {
+		/* by rain
+		 handle the case when first slice is I instead of IDR
+		*/
+		p_Vid->pre_frame_num = pSlice->frame_num;
+	}
+	/* pSlice->adaptive_ref_pic_buffering_flag; */
+	sps->log2_max_frame_num_minus4 =
+		p_H264_Dpb->dpb_param.l.data[LOG2_MAX_FRAME_NUM] - 4;
+	sps->frame_num_gap_allowed = p_H264_Dpb->dpb_param.l.data[FRAME_NUM_GAP_ALLOWED];
+
+	p_Vid->non_conforming_stream =
+		p_H264_Dpb->dpb_param.l.data[NON_CONFORMING_STREAM];
+	p_Vid->recovery_point =
+		p_H264_Dpb->dpb_param.l.data[RECOVERY_POINT];
+	switch (p_H264_Dpb->dpb_param.l.data[SLICE_TYPE]) {
+	case I_Slice:
+		pSlice->slice_type = I_SLICE;
+		break;
+	case P_Slice:
+		pSlice->slice_type = P_SLICE;
+		break;
+	case B_Slice:
+		pSlice->slice_type = B_SLICE;
+		break;
+	default:
+		pSlice->slice_type = NUM_SLICE_TYPES;
+		break;
+	}
+
+	pSlice->num_ref_idx_active[LIST_0] =
+		p_H264_Dpb->dpb_param.dpb.num_ref_idx_l0_active_minus1 +
+		1;
+	/* p_H264_Dpb->dpb_param.l.data[PPS_NUM_REF_IDX_L0_ACTIVE_MINUS1]; */
+	pSlice->num_ref_idx_active[LIST_1] =
+		p_H264_Dpb->dpb_param.dpb.num_ref_idx_l1_active_minus1 +
+		1;
+	/* p_H264_Dpb->dpb_param.l.data[PPS_NUM_REF_IDX_L1_ACTIVE_MINUS1]; */
+
+	pSlice->p_Vid = p_Vid;
+	pSlice->p_Dpb = p_Dpb;
+	/*
+	p_H264_Dpb->colocated_buf_size =
+		p_H264_Dpb->dpb_param.l.data[FRAME_SIZE_IN_MB] * 96;*/
+	pSlice->first_mb_in_slice =
+		p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE];
+	pSlice->mode_8x8_flags = p_H264_Dpb->dpb_param.l.data[MODE_8X8_FLAGS];
+	pSlice->picture_structure_mmco =
+		p_H264_Dpb->dpb_param.dpb.picture_structure_mmco;
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+	"%s slice_type is %d, num_ref_idx_active[0,1]=%d,%d nal_reference_idc %d pic struct 0x%x(mmco stru 0x%x)\n",
+		  __func__, pSlice->slice_type,
+		  pSlice->num_ref_idx_active[LIST_0],
+		  pSlice->num_ref_idx_active[LIST_1],
+		  pSlice->nal_reference_idc,
+		  pSlice->structure,
+		  pSlice->picture_structure_mmco);
+#ifdef ERROR_CHECK
+	if (pSlice->num_ref_idx_active[LIST_0] >= MAX_LIST_SIZE) {
+		pSlice->num_ref_idx_active[LIST_0] = MAX_LIST_SIZE - 1;
+		p_H264_Dpb->dpb_error_flag = __LINE__;
+	}
+	if (pSlice->num_ref_idx_active[LIST_1] >= MAX_LIST_SIZE) {
+		pSlice->num_ref_idx_active[LIST_1] = MAX_LIST_SIZE - 1;
+		p_H264_Dpb->dpb_error_flag = __LINE__;
+	}
+#endif
+
+#if 1
+	/* dec_ref_pic_marking_buffer */
+	pSlice->adaptive_ref_pic_buffering_flag = 0;
+	if (pSlice->nal_reference_idc) {
+		for (i = 0, j = 0; i < 44; j++) {
+			unsigned short val;
+			struct DecRefPicMarking_s *tmp_drpm =
+				&pSlice->dec_ref_pic_marking_buffer[j];
+			memset(tmp_drpm, 0, sizeof(struct DecRefPicMarking_s));
+			val = tmp_drpm->
+				memory_management_control_operation =
+					mmco_cmd[i++];
+			tmp_drpm->Next = NULL;
+			if (j > 0) {
+				pSlice->
+				dec_ref_pic_marking_buffer[j - 1].Next =
+					tmp_drpm;
+			}
+			if (val == 0 || i >= 44)
+				break;
+			pSlice->adaptive_ref_pic_buffering_flag = 1;
+			if ((val == 1) || (val == 3)) {
+				tmp_drpm->difference_of_pic_nums_minus1 =
+					mmco_cmd[i++];
+			}
+			if (val == 2)
+				tmp_drpm->long_term_pic_num = mmco_cmd[i++];
+			if (i >= 44)
+				break;
+			if ((val == 3) || (val == 6))
+				tmp_drpm->long_term_frame_idx = mmco_cmd[i++];
+			if (val == 4) {
+				tmp_drpm->max_long_term_frame_idx_plus1 =
+					mmco_cmd[i++];
+			}
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+				"dec_ref_pic_marking_buffer[%d]:operation %x diff_pic_minus1 %x long_pic_num %x long_frame_idx %x max_long_frame_idx_plus1 %x\n",
+				j,
+				tmp_drpm->memory_management_control_operation,
+				tmp_drpm->difference_of_pic_nums_minus1,
+				tmp_drpm->long_term_pic_num,
+				tmp_drpm->long_term_frame_idx,
+				tmp_drpm->max_long_term_frame_idx_plus1);
+		}
+	}
+
+	ref_pic_list_reordering(p_H264_Dpb, pSlice);
+#endif
+
+	/*VUI*/
+	p_H264_Dpb->vui_status = p_H264_Dpb->dpb_param.l.data[VUI_STATUS];
+	p_H264_Dpb->aspect_ratio_idc =
+		p_H264_Dpb->dpb_param.l.data[ASPECT_RATIO_IDC];
+	p_H264_Dpb->aspect_ratio_sar_width =
+		p_H264_Dpb->dpb_param.l.data[ASPECT_RATIO_SAR_WIDTH];
+	p_H264_Dpb->aspect_ratio_sar_height =
+		p_H264_Dpb->dpb_param.l.data[ASPECT_RATIO_SAR_HEIGHT];
+
+	p_H264_Dpb->fixed_frame_rate_flag = p_H264_Dpb->dpb_param.l.data[
+		FIXED_FRAME_RATE_FLAG];
+	p_H264_Dpb->num_units_in_tick =
+		p_H264_Dpb->dpb_param.l.data[NUM_UNITS_IN_TICK];
+	p_H264_Dpb->time_scale = p_H264_Dpb->dpb_param.l.data[TIME_SCALE] |
+		(p_H264_Dpb->dpb_param.l.data[TIME_SCALE + 1] << 16);
+
+	p_H264_Dpb->bitstream_restriction_flag =
+		(p_H264_Dpb->dpb_param.l.data[SPS_FLAGS2] >> 3) & 0x1;
+	p_H264_Dpb->num_reorder_frames =
+		p_H264_Dpb->dpb_param.l.data[NUM_REORDER_FRAMES];
+	p_H264_Dpb->max_dec_frame_buffering =
+		p_H264_Dpb->dpb_param.l.data[MAX_BUFFER_FRAME];
+
+	/**/
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s return\n", __func__);
+}
+
+static void decode_poc(struct VideoParameters *p_Vid, struct Slice *pSlice)
+{
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Vid,
+					struct h264_dpb_stru, mVideo);
+	struct SPSParameters *active_sps = p_Vid->active_sps;
+	int i;
+	/* for POC mode 0: */
+	unsigned int MaxPicOrderCntLsb = (1 <<
+		(active_sps->log2_max_pic_order_cnt_lsb_minus4 + 4));
+
+	dpb_print(p_H264_Dpb->decoder_index,
+		PRINT_FLAG_DEBUG_POC,
+		"%s:pic_order_cnt_type %d, idr_flag %d last_has_mmco_5 %d last_pic_bottom_field %d pic_order_cnt_lsb %d PrevPicOrderCntLsb %d\r\n",
+		__func__,
+		active_sps->pic_order_cnt_type,
+		pSlice->idr_flag,
+		p_Vid->last_has_mmco_5,
+		p_Vid->last_pic_bottom_field,
+		pSlice->pic_order_cnt_lsb,
+		p_Vid->PrevPicOrderCntLsb
+	);
+
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DEBUG_POC,
+	"%s:field_pic_flag %d, bottom_field_flag %d frame_num %d PreviousFrameNum %d PreviousFrameNumOffset %d ax_frame_num %d num_ref_frames_in_pic_order_cnt_cycle %d offset_for_non_ref_pic %d\r\n",
+		__func__,
+		pSlice->field_pic_flag,
+		pSlice->bottom_field_flag,
+		pSlice->frame_num,
+		p_Vid->PreviousFrameNum,
+		p_Vid->PreviousFrameNumOffset,
+		p_Vid->max_frame_num,
+		active_sps->num_ref_frames_in_pic_order_cnt_cycle,
+		active_sps->offset_for_non_ref_pic
+	);
+
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DEBUG_POC,
+	"%s: delta_pic_order_cnt %d %d nal_reference_idc %d\r\n",
+	__func__,
+	pSlice->delta_pic_order_cnt[0], pSlice->delta_pic_order_cnt[1],
+	pSlice->nal_reference_idc
+	);
+
+
+	switch (active_sps->pic_order_cnt_type) {
+	case 0: /* POC MODE 0 */
+		/* 1st */
+		if (pSlice->idr_flag) {
+			p_Vid->PrevPicOrderCntMsb = 0;
+			p_Vid->PrevPicOrderCntLsb = 0;
+		} else {
+			if (p_Vid->last_has_mmco_5) {
+				if (p_Vid->last_pic_bottom_field) {
+					p_Vid->PrevPicOrderCntMsb = 0;
+					p_Vid->PrevPicOrderCntLsb = 0;
+				} else {
+					p_Vid->PrevPicOrderCntMsb = 0;
+					p_Vid->PrevPicOrderCntLsb =
+						pSlice->toppoc;
+				}
+			}
+		}
+		/* Calculate the MSBs of current picture */
+		if (pSlice->pic_order_cnt_lsb < p_Vid->PrevPicOrderCntLsb &&
+		    (p_Vid->PrevPicOrderCntLsb - pSlice->pic_order_cnt_lsb) >=
+		    (MaxPicOrderCntLsb / 2))
+			pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb +
+					MaxPicOrderCntLsb;
+		else if (pSlice->pic_order_cnt_lsb >
+				p_Vid->PrevPicOrderCntLsb &&
+			 (pSlice->pic_order_cnt_lsb -
+				p_Vid->PrevPicOrderCntLsb)  >
+				 (MaxPicOrderCntLsb / 2))
+			pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb -
+					MaxPicOrderCntLsb;
+		else
+			pSlice->PicOrderCntMsb = p_Vid->PrevPicOrderCntMsb;
+
+		/* 2nd */
+		if (pSlice->field_pic_flag == 0) {
+			/* frame pix */
+			pSlice->toppoc = pSlice->PicOrderCntMsb +
+					pSlice->pic_order_cnt_lsb;
+			pSlice->bottompoc = pSlice->toppoc +
+					pSlice->delta_pic_order_cnt_bottom;
+			pSlice->ThisPOC = pSlice->framepoc =
+				(pSlice->toppoc < pSlice->bottompoc) ?
+				 pSlice->toppoc : pSlice->bottompoc;
+					/* POC200301 */
+		} else if (pSlice->bottom_field_flag == 0) {
+			/* top field */
+			pSlice->ThisPOC = pSlice->toppoc =
+				pSlice->PicOrderCntMsb +
+				pSlice->pic_order_cnt_lsb;
+		} else {
+			/* bottom field */
+			pSlice->ThisPOC = pSlice->bottompoc =
+				pSlice->PicOrderCntMsb +
+				pSlice->pic_order_cnt_lsb;
+		}
+		pSlice->framepoc = pSlice->ThisPOC;
+
+		p_Vid->ThisPOC = pSlice->ThisPOC;
+
+		/* if ( pSlice->frame_num != p_Vid->PreviousFrameNum)
+		 *	Seems redundant
+		 */
+		p_Vid->PreviousFrameNum = pSlice->frame_num;
+
+		if (pSlice->nal_reference_idc) {
+			p_Vid->PrevPicOrderCntLsb = pSlice->pic_order_cnt_lsb;
+			p_Vid->PrevPicOrderCntMsb = pSlice->PicOrderCntMsb;
+		}
+
+		break;
+
+	case 1: /* POC MODE 1 */
+		/* 1st */
+		if (pSlice->idr_flag) {
+			p_Vid->FrameNumOffset = 0;   /* first pix of IDRGOP */
+			if (pSlice->frame_num)
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					"frame_num not equal to zero in IDR picture %d",
+					-1020);
+		} else {
+			if (p_Vid->last_has_mmco_5) {
+				p_Vid->PreviousFrameNumOffset = 0;
+				p_Vid->PreviousFrameNum = 0;
+			}
+			if (pSlice->frame_num < p_Vid->PreviousFrameNum) {
+				/* not first pix of IDRGOP */
+				p_Vid->FrameNumOffset =
+					p_Vid->PreviousFrameNumOffset +
+						p_Vid->max_frame_num;
+			} else {
+				p_Vid->FrameNumOffset =
+					p_Vid->PreviousFrameNumOffset;
+			}
+		}
+
+		/* 2nd */
+		if (active_sps->num_ref_frames_in_pic_order_cnt_cycle)
+			pSlice->AbsFrameNum =
+				p_Vid->FrameNumOffset + pSlice->frame_num;
+		else
+			pSlice->AbsFrameNum = 0;
+		if ((!pSlice->nal_reference_idc) && pSlice->AbsFrameNum > 0)
+			pSlice->AbsFrameNum--;
+
+		/* 3rd */
+		p_Vid->ExpectedDeltaPerPicOrderCntCycle = 0;
+
+		if (active_sps->num_ref_frames_in_pic_order_cnt_cycle)
+			for (i = 0; i < (int) active_sps->
+				num_ref_frames_in_pic_order_cnt_cycle; i++) {
+				p_Vid->ExpectedDeltaPerPicOrderCntCycle +=
+					active_sps->offset_for_ref_frame[i];
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DEBUG_POC,
+					"%s: offset_for_ref_frame %d\r\n",
+					__func__,
+					active_sps->
+					offset_for_ref_frame[i]);
+			}
+
+		if (pSlice->AbsFrameNum) {
+			p_Vid->PicOrderCntCycleCnt =
+				(pSlice->AbsFrameNum - 1) /
+				active_sps->
+				num_ref_frames_in_pic_order_cnt_cycle;
+			p_Vid->FrameNumInPicOrderCntCycle =
+				(pSlice->AbsFrameNum - 1) %
+				active_sps->
+				num_ref_frames_in_pic_order_cnt_cycle;
+			p_Vid->ExpectedPicOrderCnt =
+				p_Vid->PicOrderCntCycleCnt *
+				p_Vid->ExpectedDeltaPerPicOrderCntCycle;
+			for (i = 0; i <= (int)p_Vid->
+				FrameNumInPicOrderCntCycle; i++) {
+				p_Vid->ExpectedPicOrderCnt +=
+					active_sps->offset_for_ref_frame[i];
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DEBUG_POC,
+					"%s: offset_for_ref_frame %d\r\n",
+					__func__,
+					active_sps->
+					offset_for_ref_frame[i]);
+			}
+		} else
+			p_Vid->ExpectedPicOrderCnt = 0;
+
+		if (!pSlice->nal_reference_idc)
+			p_Vid->ExpectedPicOrderCnt +=
+				active_sps->offset_for_non_ref_pic;
+
+		if (pSlice->field_pic_flag == 0) {
+			/* frame pix */
+			pSlice->toppoc = p_Vid->ExpectedPicOrderCnt +
+				pSlice->delta_pic_order_cnt[0];
+			pSlice->bottompoc = pSlice->toppoc +
+				active_sps->offset_for_top_to_bottom_field +
+				pSlice->delta_pic_order_cnt[1];
+			pSlice->ThisPOC = pSlice->framepoc =
+				(pSlice->toppoc < pSlice->bottompoc) ?
+				pSlice->toppoc : pSlice->bottompoc;
+				/* POC200301 */
+		} else if (pSlice->bottom_field_flag == 0) {
+			/* top field */
+			pSlice->ThisPOC = pSlice->toppoc =
+				p_Vid->ExpectedPicOrderCnt +
+				pSlice->delta_pic_order_cnt[0];
+		} else {
+			/* bottom field */
+			pSlice->ThisPOC = pSlice->bottompoc =
+				p_Vid->ExpectedPicOrderCnt +
+				active_sps->offset_for_top_to_bottom_field +
+				pSlice->delta_pic_order_cnt[0];
+		}
+		pSlice->framepoc = pSlice->ThisPOC;
+
+		p_Vid->PreviousFrameNum = pSlice->frame_num;
+		p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset;
+
+		break;
+
+
+	case 2: /* POC MODE 2 */
+		if (pSlice->idr_flag) { /* IDR picture */
+			p_Vid->FrameNumOffset = 0;   /* first pix of IDRGOP */
+			pSlice->ThisPOC = pSlice->framepoc = pSlice->toppoc =
+				pSlice->bottompoc = 0;
+			if (pSlice->frame_num)
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					"frame_num not equal to zero in IDR picture %d",
+					-1020);
+		} else {
+			if (p_Vid->last_has_mmco_5) {
+				p_Vid->PreviousFrameNum = 0;
+				p_Vid->PreviousFrameNumOffset = 0;
+			}
+			if (pSlice->frame_num < p_Vid->PreviousFrameNum)
+				p_Vid->FrameNumOffset =
+					p_Vid->PreviousFrameNumOffset +
+					p_Vid->max_frame_num;
+			else
+				p_Vid->FrameNumOffset =
+					p_Vid->PreviousFrameNumOffset;
+
+			pSlice->AbsFrameNum = p_Vid->FrameNumOffset +
+				pSlice->frame_num;
+			if (!pSlice->nal_reference_idc)
+				pSlice->ThisPOC =
+					(2 * pSlice->AbsFrameNum - 1);
+			else
+				pSlice->ThisPOC = (2 * pSlice->AbsFrameNum);
+
+			if (pSlice->field_pic_flag == 0)
+				pSlice->toppoc = pSlice->bottompoc =
+					pSlice->framepoc = pSlice->ThisPOC;
+			else if (pSlice->bottom_field_flag == 0)
+				pSlice->toppoc = pSlice->framepoc =
+				pSlice->ThisPOC;
+			else
+				pSlice->bottompoc = pSlice->framepoc =
+				pSlice->ThisPOC;
+		}
+
+		p_Vid->PreviousFrameNum = pSlice->frame_num;
+		p_Vid->PreviousFrameNumOffset = p_Vid->FrameNumOffset;
+		break;
+
+
+	default:
+		/* error must occurs */
+		/* assert( 1==0 ); */
+		break;
+	}
+}
+
+void fill_frame_num_gap(struct VideoParameters *p_Vid, struct Slice *currSlice)
+{
+	struct h264_dpb_stru *p_H264_Dpb =
+		container_of(p_Vid, struct h264_dpb_stru, mVideo);
+	struct SPSParameters *active_sps = p_Vid->active_sps;
+	int CurrFrameNum;
+	int UnusedShortTermFrameNum;
+	struct StorablePicture *picture = NULL;
+	int tmp1 = currSlice->delta_pic_order_cnt[0];
+	int tmp2 = currSlice->delta_pic_order_cnt[1];
+	int ret;
+
+	currSlice->delta_pic_order_cnt[0] =
+		currSlice->delta_pic_order_cnt[1] = 0;
+
+	dpb_print(p_H264_Dpb->decoder_index,
+		PRINT_FLAG_DPB_DETAIL,
+		"A gap in frame number is found, try to fill it.(pre_frame_num %d, max_frame_num %d\n",
+		p_Vid->pre_frame_num, p_Vid->max_frame_num
+	);
+
+	UnusedShortTermFrameNum = (p_Vid->pre_frame_num + 1)
+		% p_Vid->max_frame_num;
+	CurrFrameNum = currSlice->frame_num; /*p_Vid->frame_num;*/
+
+	while (CurrFrameNum != UnusedShortTermFrameNum) {
+		/*pr_err("CurrFrameNum = %d, UnusedShortTermFrameNum = %d\n", CurrFrameNum, UnusedShortTermFrameNum);*/
+		/*picture = alloc_storable_picture
+		 *(p_Vid, FRAME, p_Vid->width,
+		 *p_Vid->height,
+		 *p_Vid->width_cr,
+		 *p_Vid->height_cr, 1);
+		 */
+		picture = get_new_pic(p_H264_Dpb,
+			p_H264_Dpb->mSlice.structure,
+		/*p_Vid->width, p_Vid->height,
+		 *p_Vid->width_cr,
+		p_Vid->height_cr,*/ 1);
+
+		if (picture == NULL) {
+			struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_ERROR,
+				"%s Error: get_new_pic return NULL\r\n",
+				__func__);
+			/*h264_debug_flag |= PRINT_FLAG_DUMP_DPB;*/
+			dump_dpb(p_Dpb, 0);
+			return;
+		}
+
+		picture->colocated_buf_index = -1;
+		picture->buf_spec_num = -1;
+		picture->buf_spec_is_alloced = 0;
+
+		picture->coded_frame = 1;
+		picture->pic_num = UnusedShortTermFrameNum;
+		picture->frame_num = UnusedShortTermFrameNum;
+		picture->non_existing = 1;
+		picture->is_output = 1;
+		picture->used_for_reference = 1;
+		picture->adaptive_ref_pic_buffering_flag = 0;
+		#if (MVC_EXTENSION_ENABLE)
+		picture->view_id = currSlice->view_id;
+		#endif
+
+		currSlice->frame_num = UnusedShortTermFrameNum;
+		if (active_sps->pic_order_cnt_type != 0) {
+			/*decode_poc(p_Vid, p_Vid->ppSliceList[0]);*/
+			decode_poc(&p_H264_Dpb->mVideo, &p_H264_Dpb->mSlice);
+		}
+		picture->top_poc    = currSlice->toppoc;
+		picture->bottom_poc = currSlice->bottompoc;
+		picture->frame_poc  = currSlice->framepoc;
+		picture->poc        = currSlice->framepoc;
+
+		ret = store_picture_in_dpb(p_H264_Dpb, picture, 0);
+		if (ret == -1) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_ERROR,
+				"%s Error: store_picture_in_dpb failed, break\n",
+				__func__);
+			release_picture(p_H264_Dpb, picture);
+			bufmgr_force_recover(p_H264_Dpb);
+			return;
+		} else if (ret == -2)
+			release_picture(p_H264_Dpb, picture);
+
+		picture = NULL;
+		p_Vid->pre_frame_num = UnusedShortTermFrameNum;
+		UnusedShortTermFrameNum =
+			(UnusedShortTermFrameNum + 1) %
+			p_Vid->max_frame_num;
+	}
+	currSlice->delta_pic_order_cnt[0] = tmp1;
+	currSlice->delta_pic_order_cnt[1] = tmp2;
+	currSlice->frame_num = CurrFrameNum;
+}
+
+void dpb_init_global(struct h264_dpb_stru *p_H264_Dpb,
+	int id, int actual_dpb_size, int max_reference_size)
+{
+	int i;
+
+	init_dummy_fs();
+
+	memset(&p_H264_Dpb->mDPB, 0, sizeof(struct DecodedPictureBuffer));
+
+	memset(&p_H264_Dpb->mSlice, 0, sizeof(struct Slice));
+	memset(&p_H264_Dpb->mVideo, 0, sizeof(struct VideoParameters));
+	memset(&p_H264_Dpb->mSPS, 0, sizeof(struct SPSParameters));
+
+	for (i = 0; i < DPB_SIZE_MAX; i++) {
+		memset(&(p_H264_Dpb->mFrameStore[i]), 0,
+			sizeof(struct FrameStore));
+	}
+
+	for (i = 0; i < MAX_PIC_BUF_NUM; i++) {
+		memset(&(p_H264_Dpb->m_PIC[i]), 0,
+			sizeof(struct StorablePicture));
+		p_H264_Dpb->m_PIC[i].index = i;
+	}
+	p_H264_Dpb->decoder_index = id;
+
+    /* make sure dpb_init_global
+     *can be called during decoding
+     *(in DECODE_STATE_IDLE or DECODE_STATE_READY state)
+     */
+	p_H264_Dpb->mDPB.size = actual_dpb_size;
+	p_H264_Dpb->max_reference_size = max_reference_size;
+	p_H264_Dpb->poc_even_odd_flag = 0;
+}
+
+static void init_picture(struct h264_dpb_stru *p_H264_Dpb,
+			 struct Slice *currSlice,
+			 struct StorablePicture *dec_picture)
+{
+	/* struct VideoParameters *p_Vid = &(p_H264_Dpb->mVideo); */
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		  "%s dec_picture %p\n", __func__, dec_picture);
+	dec_picture->top_poc = currSlice->toppoc;
+	dec_picture->bottom_poc = currSlice->bottompoc;
+	dec_picture->frame_poc = currSlice->framepoc;
+	switch (currSlice->structure) {
+	case TOP_FIELD: {
+		dec_picture->poc = currSlice->toppoc;
+		/* p_Vid->number *= 2; */
+		break;
+	}
+	case BOTTOM_FIELD: {
+		dec_picture->poc = currSlice->bottompoc;
+		/* p_Vid->number = p_Vid->number * 2 + 1; */
+		break;
+	}
+	case FRAME: {
+		dec_picture->poc = currSlice->framepoc;
+		break;
+	}
+	default:
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			  "p_Vid->structure not initialized %d\n", 235);
+	}
+
+	/* dec_picture->slice_type = p_Vid->type; */
+	dec_picture->used_for_reference = (currSlice->nal_reference_idc != 0);
+	dec_picture->idr_flag = currSlice->idr_flag;
+	dec_picture->no_output_of_prior_pics_flag =
+		currSlice->no_output_of_prior_pics_flag;
+	dec_picture->long_term_reference_flag =
+		currSlice->long_term_reference_flag;
+#if 1
+	dec_picture->adaptive_ref_pic_buffering_flag =
+		currSlice->adaptive_ref_pic_buffering_flag;
+	dec_picture->dec_ref_pic_marking_buffer =
+		&currSlice->dec_ref_pic_marking_buffer[0];
+#endif
+	/* currSlice->dec_ref_pic_marking_buffer   = NULL; */
+
+	/* dec_picture->mb_aff_frame_flag = currSlice->mb_aff_frame_flag; */
+	/* dec_picture->PicWidthInMbs     = p_Vid->PicWidthInMbs; */
+
+	/* p_Vid->get_mb_block_pos =
+	 *	dec_picture->mb_aff_frame_flag ? get_mb_block_pos_mbaff :
+	 *	get_mb_block_pos_normal;
+	 */
+	/* p_Vid->getNeighbour     =
+	 *	dec_picture->mb_aff_frame_flag ? getAffNeighbour :
+	 *	getNonAffNeighbour;
+	 */
+
+	dec_picture->pic_num   = currSlice->frame_num;
+	dec_picture->frame_num = currSlice->frame_num;
+
+	/* dec_picture->recovery_frame =
+	 *	(unsigned int) ((int) currSlice->frame_num ==
+	 *	p_Vid->recovery_frame_num);
+	 */
+
+	dec_picture->coded_frame = (currSlice->structure == FRAME);
+
+	/* dec_picture->chroma_format_idc = active_sps->chroma_format_idc; */
+
+	/* dec_picture->frame_mbs_only_flag =
+	 *	active_sps->frame_mbs_only_flag;
+	 */
+	/* dec_picture->frame_cropping_flag =
+	 *	active_sps->frame_cropping_flag;
+	 */
+
+	if ((currSlice->picture_structure_mmco & 0x3) == 3) {
+		dec_picture->mb_aff_frame_flag = 1;
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			"%s, picture_structure_mmco is %x, set mb_aff_frame_flag to 1\n",
+			__func__,
+			currSlice->picture_structure_mmco);
+	}
+
+	if (currSlice->pic_struct < PIC_INVALID) {
+		dec_picture->pic_struct = currSlice->pic_struct;
+	} else {
+		dec_picture->pic_struct = PIC_INVALID;
+	}
+
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			  "%s pic_struct = %d\n", __func__, dec_picture->pic_struct);
+}
+
+void dump_pic(struct h264_dpb_stru *p_H264_Dpb)
+{
+	int ii;
+	struct StorablePicture *pic;
+	for (ii = 0; ii < MAX_PIC_BUF_NUM; ii++) {
+		pic = &(p_H264_Dpb->m_PIC[ii]);
+		if (pic->is_used) {
+			dpb_print(p_H264_Dpb->decoder_index, 0,
+				"pic(%d,%d) poc %d is_used %d bufspec %d colbuf %d for_ref %d long_term %d pre_out %d output %d nonexist %d data_flag 0x%x\n",
+				ii, pic->index,
+				pic->poc,
+				pic->is_used,
+				pic->buf_spec_num,
+				pic->colocated_buf_index,
+				pic->used_for_reference,
+				pic->is_long_term,
+				pic->pre_output,
+				pic->is_output,
+				pic->non_existing,
+				pic->data_flag);
+		}
+	}
+}
+
+/*
+static void is_pic_used_by_dpb(struct h264_dpb_stru *p_H264_Dpb,
+	struct StorablePicture *pic)
+{
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+	unsigned i;
+	for (i = 0; i < p_Dpb->used_size; i++) {
+		if (p_Dpb->fs[i]->top_field == pic ||
+			p_Dpb->fs[i]->bottom_field == pic ||
+			p_Dpb->fs[i]->frame == pic
+			)
+			break;
+	}
+	if (i < p_Dpb->used_size)
+		return 1;
+	return 0;
+}
+*/
+
+static struct StorablePicture *get_new_pic(struct h264_dpb_stru *p_H264_Dpb,
+		enum PictureStructure structure, unsigned char is_output)
+{
+	struct StorablePicture *s = NULL;
+	struct StorablePicture *pic;
+	struct VideoParameters *p_Vid = &(p_H264_Dpb->mVideo);
+	/* recycle un-used pic */
+	int ii = 0;
+
+	for (ii = 0; ii < MAX_PIC_BUF_NUM; ii++) {
+		pic = &(p_H264_Dpb->m_PIC[ii]);
+		if (pic->is_used == 0) {
+			pic->is_used = 1;
+			s = pic;
+			break;
+		}
+	}
+
+	if (s) {
+		s->buf_spec_is_alloced = 0;
+		s->pic_num   = 0;
+		s->frame_num = 0;
+		s->long_term_frame_idx = 0;
+		s->long_term_pic_num   = 0;
+		s->used_for_reference  = 0;
+		s->is_long_term        = 0;
+		s->non_existing        = 0;
+		s->is_output           = 0;
+		s->pre_output          = 0;
+		s->max_slice_id        = 0;
+		s->data_flag &= ~(ERROR_FLAG | NODISP_FLAG);
+#if (MVC_EXTENSION_ENABLE)
+		s->view_id = -1;
+#endif
+
+		s->structure = structure;
+
+#if 0
+		s->size_x = size_x;
+		s->size_y = size_y;
+		s->size_x_cr = size_x_cr;
+		s->size_y_cr = size_y_cr;
+		s->size_x_m1 = size_x - 1;
+		s->size_y_m1 = size_y - 1;
+		s->size_x_cr_m1 = size_x_cr - 1;
+		s->size_y_cr_m1 = size_y_cr - 1;
+
+		s->top_field    = p_Vid->no_reference_picture;
+		s->bottom_field = p_Vid->no_reference_picture;
+		s->frame        = p_Vid->no_reference_picture;
+#endif
+		/* s->dec_ref_pic_marking_buffer = NULL; */
+
+		s->coded_frame  = 0;
+		s->mb_aff_frame_flag  = 0;
+
+		s->top_poc = s->bottom_poc = s->poc = 0;
+		s->seiHasTone_mapping = 0;
+		s->frame_mbs_only_flag = p_Vid->active_sps->frame_mbs_only_flag;
+
+		if (!p_Vid->active_sps->frame_mbs_only_flag &&
+			structure != FRAME) {
+			int i, j;
+
+			for (j = 0; j < MAX_NUM_SLICES; j++) {
+				for (i = 0; i < 2; i++) {
+					/* s->listX[j][i] =
+					 *calloc(MAX_LIST_SIZE,
+					 *sizeof (struct StorablePicture *));
+					 *+1 for reordering   ???
+
+					 *if (NULL == s->listX[j][i])
+					 *no_mem_exit("alloc_storable_picture:
+					 *s->listX[i]");
+					 */
+				}
+			}
+		}
+	} else
+		p_H264_Dpb->buf_alloc_fail = 1;
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			"%s %p\n", __func__, s);
+	return s;
+}
+
+static void free_picture(struct h264_dpb_stru *p_H264_Dpb,
+			 struct StorablePicture *pic)
+{
+	if (pic == NULL || pic->index < 0 ||
+		pic->index >= MAX_PIC_BUF_NUM)
+		return;
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			"%s %p %d\n", __func__, pic, pic->index);
+	/* assert(pic->index<MAX_PIC_BUF_NUM); */
+	p_H264_Dpb->m_PIC[pic->index].is_used = 0;
+}
+
+static void gen_field_ref_ids(struct VideoParameters *p_Vid,
+			      struct StorablePicture *p)
+{
+	int i, j;
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Vid,
+					struct h264_dpb_stru, mVideo);
+	/* ! Generate Frame parameters from field information. */
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+					"%s\n", __func__);
+
+	/* copy the list; */
+	for (j = 0; j < p_Vid->iSliceNumOfCurrPic; j++) {
+		if (p->listX[j][LIST_0]) {
+			p->listXsize[j][LIST_0] =
+				p_Vid->ppSliceList[j]->listXsize[LIST_0];
+			for (i = 0; i < p->listXsize[j][LIST_0]; i++)
+				p->listX[j][LIST_0][i] =
+				p_Vid->ppSliceList[j]->listX[LIST_0][i];
+		}
+		if (p->listX[j][LIST_1]) {
+			p->listXsize[j][LIST_1] =
+				p_Vid->ppSliceList[j]->listXsize[LIST_1];
+			for (i = 0; i < p->listXsize[j][LIST_1]; i++)
+				p->listX[j][LIST_1][i] =
+				p_Vid->ppSliceList[j]->listX[LIST_1][i];
+		}
+	}
+}
+
+static void init_dpb(struct h264_dpb_stru *p_H264_Dpb, int type)
+{
+	unsigned int i;
+	struct VideoParameters *p_Vid  = &p_H264_Dpb->mVideo;
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+	struct SPSParameters *active_sps = &p_H264_Dpb->mSPS;
+
+	p_Vid->active_sps = active_sps;
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s\n", __func__);
+
+	p_Dpb->p_Vid = p_Vid;
+	if (p_Dpb->init_done) {
+		/* free_dpb(p_Dpb); */
+		if (p_Vid->no_reference_picture) {
+			free_picture(p_H264_Dpb, p_Vid->no_reference_picture);
+			p_Vid->no_reference_picture = NULL;
+		}
+		p_Dpb->init_done = 0;
+	}
+
+	/* p_Dpb->size = 10; //active_sps->max_dpb_size; //16;
+	 *   getDpbSize(p_Vid, active_sps) +
+	 *	p_Vid->p_Inp->dpb_plus[type==2? 1: 0];
+	 *   p_Dpb->size = active_sps->max_dpb_size; //16;
+	 *   getDpbSize(p_Vid, active_sps) +
+	 *	p_Vid->p_Inp->dpb_plus[type==2? 1: 0];
+	 *   p_Dpb->size initialzie in vh264.c
+	 */
+	p_Dpb->num_ref_frames = active_sps->num_ref_frames;
+	/* p_Dpb->num_ref_frames initialzie in vh264.c */
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		  "%s dpb_size is %d  num_ref_frames = %d (%d)\n",
+		  __func__, p_Dpb->size,
+		  p_Dpb->num_ref_frames,
+		  active_sps->num_ref_frames);
+	if (active_sps->num_ref_frames == 0xffff) {
+		dpb_print(p_H264_Dpb->decoder_index, 0,
+		  "!!!Warning, num_ref_frames = %d is invalid\n",
+		  active_sps->num_ref_frames);
+	}
+
+#if 0
+	/* ??? */
+#if (MVC_EXTENSION_ENABLE)
+	if ((unsigned int)active_sps->max_dec_frame_buffering <
+	    active_sps->num_ref_frames) {
+#else
+	if (p_Dpb->size < active_sps->num_ref_frames) {
+#endif
+		error(
+		"DPB size at specified level is smaller than the specified number of reference frames. This is not allowed.\n",
+		1000);
+	}
+#endif
+
+	p_Dpb->used_size = 0;
+	p_Dpb->last_picture = NULL;
+
+	p_Dpb->ref_frames_in_buffer = 0;
+	p_Dpb->ltref_frames_in_buffer = 0;
+
+#if 0
+	p_Dpb->fs = calloc(p_Dpb->size, sizeof(struct FrameStore *));
+	if (NULL == p_Dpb->fs)
+		no_mem_exit("init_dpb: p_Dpb->fs");
+
+	p_Dpb->fs_ref = calloc(p_Dpb->size, sizeof(struct FrameStore *));
+	if (NULL == p_Dpb->fs_ref)
+		no_mem_exit("init_dpb: p_Dpb->fs_ref");
+
+	p_Dpb->fs_ltref = calloc(p_Dpb->size, sizeof(struct FrameStore *));
+	if (NULL == p_Dpb->fs_ltref)
+		no_mem_exit("init_dpb: p_Dpb->fs_ltref");
+#endif
+
+#if (MVC_EXTENSION_ENABLE)
+	p_Dpb->fs_ilref = calloc(1, sizeof(struct FrameStore *));
+	if (NULL == p_Dpb->fs_ilref)
+		no_mem_exit("init_dpb: p_Dpb->fs_ilref");
+#endif
+
+	for (i = 0; i < p_Dpb->size; i++) {
+		p_Dpb->fs[i] = &(p_H264_Dpb->mFrameStore[i]);
+		/* alloc_frame_store(); */
+		p_Dpb->fs[i]->index       = i;
+		p_Dpb->fs_ref[i]   = NULL;
+		p_Dpb->fs_ltref[i] = NULL;
+		p_Dpb->fs[i]->layer_id = 0; /* MVC_INIT_VIEW_ID; */
+#if (MVC_EXTENSION_ENABLE)
+		p_Dpb->fs[i]->view_id = MVC_INIT_VIEW_ID;
+		p_Dpb->fs[i]->inter_view_flag[0] =
+			p_Dpb->fs[i]->inter_view_flag[1] = 0;
+		p_Dpb->fs[i]->anchor_pic_flag[0] =
+			p_Dpb->fs[i]->anchor_pic_flag[1] = 0;
+#endif
+	}
+#if (MVC_EXTENSION_ENABLE)
+	if (type == 2) {
+		p_Dpb->fs_ilref[0] = alloc_frame_store();
+		/* These may need some cleanups */
+		p_Dpb->fs_ilref[0]->view_id = MVC_INIT_VIEW_ID;
+		p_Dpb->fs_ilref[0]->inter_view_flag[0] =
+			p_Dpb->fs_ilref[0]->inter_view_flag[1] = 0;
+		p_Dpb->fs_ilref[0]->anchor_pic_flag[0] =
+			p_Dpb->fs_ilref[0]->anchor_pic_flag[1] = 0;
+		/* given that this is in a different buffer,
+		 *	do we even need proc_flag anymore?
+		 */
+	} else
+		p_Dpb->fs_ilref[0] = NULL;
+#endif
+
+	/*
+	 *for (i = 0; i < 6; i++)
+	 *{
+	 *currSlice->listX[i] =
+	 *	calloc(MAX_LIST_SIZE, sizeof (struct StorablePicture *));
+	 *	+1 for reordering
+	 *if (NULL == currSlice->listX[i])
+	 *no_mem_exit("init_dpb: currSlice->listX[i]");
+	 *}
+	 */
+	/* allocate a dummy storable picture */
+	if (!p_Vid->no_reference_picture) {
+		p_Vid->no_reference_picture = get_new_pic(p_H264_Dpb,
+					      FRAME,
+		/*p_Vid->width, p_Vid->height,
+		 *p_Vid->width_cr, p_Vid->height_cr,
+		 */
+		1);
+		p_Vid->no_reference_picture->top_field =
+			p_Vid->no_reference_picture;
+		p_Vid->no_reference_picture->bottom_field =
+			p_Vid->no_reference_picture;
+		p_Vid->no_reference_picture->frame =
+			p_Vid->no_reference_picture;
+	}
+	p_Dpb->last_output_poc = INT_MIN;
+
+#if (MVC_EXTENSION_ENABLE)
+	p_Dpb->last_output_view_id = -1;
+#endif
+
+	p_Vid->last_has_mmco_5 = 0;
+
+	init_colocate_buf(p_H264_Dpb, p_H264_Dpb->max_reference_size);
+
+	p_Dpb->init_done = 1;
+
+#if 0
+/* ??? */
+	/* picture error concealment */
+	if (p_Vid->conceal_mode != 0 && !p_Vid->last_out_fs)
+		p_Vid->last_out_fs = alloc_frame_store();
+#endif
+}
+
+static void dpb_split_field(struct h264_dpb_stru *p_H264_Dpb,
+			    struct FrameStore *fs)
+{
+	struct StorablePicture *fs_top = NULL, *fs_btm = NULL;
+	struct StorablePicture *frame = fs->frame;
+
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s %p %p\n", __func__, fs, frame);
+
+	fs->poc = frame->poc;
+
+	if (!frame->frame_mbs_only_flag) {
+		fs_top = fs->top_field = get_new_pic(p_H264_Dpb,
+			TOP_FIELD,
+			/* frame->size_x, frame->size_y,
+			 *frame->size_x_cr, frame->size_y_cr,
+			 */
+			1);
+		fs_btm = fs->bottom_field = get_new_pic(p_H264_Dpb,
+			BOTTOM_FIELD,
+			/*frame->size_x, frame->size_y,
+			 *frame->size_x_cr, frame->size_y_cr,
+			 */
+			1);
+		if (fs_top == NULL || fs_btm == NULL)
+			return;
+#if 1
+/* rain */
+		fs_top->buf_spec_num = frame->buf_spec_num;
+		fs_btm->buf_spec_num = frame->buf_spec_num;
+
+		fs_top->colocated_buf_index = frame->colocated_buf_index;
+		fs_btm->colocated_buf_index = frame->colocated_buf_index;
+
+		fs_top->data_flag = frame->data_flag;
+		fs_btm->data_flag = frame->data_flag;
+#endif
+		fs_top->poc = frame->top_poc;
+		fs_btm->poc = frame->bottom_poc;
+
+#if (MVC_EXTENSION_ENABLE)
+		fs_top->view_id = frame->view_id;
+		fs_btm->view_id = frame->view_id;
+#endif
+
+		fs_top->frame_poc =  frame->frame_poc;
+
+		fs_top->bottom_poc = fs_btm->bottom_poc =  frame->bottom_poc;
+		fs_top->top_poc    = fs_btm->top_poc    =  frame->top_poc;
+		fs_btm->frame_poc  = frame->frame_poc;
+
+		fs_top->used_for_reference = fs_btm->used_for_reference
+					     = frame->used_for_reference;
+		fs_top->is_long_term = fs_btm->is_long_term
+				       = frame->is_long_term;
+		fs->long_term_frame_idx = fs_top->long_term_frame_idx
+					  = fs_btm->long_term_frame_idx
+					    = frame->long_term_frame_idx;
+
+		fs_top->coded_frame = fs_btm->coded_frame = 1;
+		fs_top->mb_aff_frame_flag = fs_btm->mb_aff_frame_flag
+					    = frame->mb_aff_frame_flag;
+
+		frame->top_field    = fs_top;
+		frame->bottom_field = fs_btm;
+		frame->frame         = frame;
+		fs_top->bottom_field = fs_btm;
+		fs_top->frame        = frame;
+		fs_top->top_field = fs_top;
+		fs_btm->top_field = fs_top;
+		fs_btm->frame     = frame;
+		fs_btm->bottom_field = fs_btm;
+
+#if (MVC_EXTENSION_ENABLE)
+		fs_top->view_id = fs_btm->view_id = fs->view_id;
+		fs_top->inter_view_flag = fs->inter_view_flag[0];
+		fs_btm->inter_view_flag = fs->inter_view_flag[1];
+#endif
+
+		fs_top->chroma_format_idc = fs_btm->chroma_format_idc =
+						    frame->chroma_format_idc;
+		fs_top->iCodingType = fs_btm->iCodingType = frame->iCodingType;
+	} else {
+		fs->top_field       = NULL;
+		fs->bottom_field    = NULL;
+		frame->top_field    = NULL;
+		frame->bottom_field = NULL;
+		frame->frame = frame;
+	}
+
+}
+
+
+static void dpb_combine_field(struct h264_dpb_stru *p_H264_Dpb,
+			      struct FrameStore *fs)
+{
+
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			"%s\n", __func__);
+
+	if (!fs->frame) {
+		fs->frame = get_new_pic(p_H264_Dpb,
+			FRAME,
+			/* fs->top_field->size_x, fs->top_field->size_y*2,
+			 *fs->top_field->size_x_cr, fs->top_field->size_y_cr*2,
+			 */
+			1);
+	}
+	if (!fs->frame)
+		return;
+#if 1
+/* rain */
+	fs->frame->buf_spec_num = fs->top_field->buf_spec_num;
+	fs->frame->colocated_buf_index = fs->top_field->colocated_buf_index;
+	fs->frame->data_flag = fs->top_field->data_flag;
+	fs->frame->slice_type = fs->top_field->slice_type;
+	if (fs->bottom_field)
+		fs->frame->data_flag |= (fs->bottom_field->data_flag & 0xf0);
+#endif
+
+	if (fs->bottom_field) {
+		fs->poc = fs->frame->poc = fs->frame->frame_poc = imin(
+				fs->top_field->poc, fs->bottom_field->poc);
+
+		fs->bottom_field->frame_poc = fs->top_field->frame_poc = fs->frame->poc;
+
+		fs->bottom_field->top_poc = fs->frame->top_poc = fs->top_field->poc;
+		fs->top_field->bottom_poc = fs->frame->bottom_poc =
+				fs->bottom_field->poc;
+
+		fs->frame->used_for_reference = (fs->top_field->used_for_reference &&
+						 fs->bottom_field->used_for_reference);
+		fs->frame->is_long_term = (fs->top_field->is_long_term &&
+					   fs->bottom_field->is_long_term);
+	}
+
+	if (fs->frame->is_long_term)
+		fs->frame->long_term_frame_idx = fs->long_term_frame_idx;
+
+	fs->frame->top_field    = fs->top_field;
+	if (fs->bottom_field)
+		fs->frame->bottom_field = fs->bottom_field;
+	fs->frame->frame = fs->frame;
+
+	fs->frame->coded_frame = 0;
+
+	fs->frame->chroma_format_idc = fs->top_field->chroma_format_idc;
+	fs->frame->frame_cropping_flag = fs->top_field->frame_cropping_flag;
+	if (fs->frame->frame_cropping_flag) {
+		fs->frame->frame_crop_top_offset =
+			fs->top_field->frame_crop_top_offset;
+		fs->frame->frame_crop_bottom_offset =
+			fs->top_field->frame_crop_bottom_offset;
+		fs->frame->frame_crop_left_offset =
+			fs->top_field->frame_crop_left_offset;
+		fs->frame->frame_crop_right_offset =
+			fs->top_field->frame_crop_right_offset;
+	}
+	if (fs->bottom_field) {
+		fs->top_field->frame = fs->bottom_field->frame = fs->frame;
+		fs->top_field->top_field = fs->top_field;
+		fs->top_field->bottom_field = fs->bottom_field;
+		fs->bottom_field->top_field = fs->top_field;
+		fs->bottom_field->bottom_field = fs->bottom_field;
+	}
+
+	/**/
+#if (MVC_EXTENSION_ENABLE)
+	fs->frame->view_id = fs->view_id;
+#endif
+	fs->frame->iCodingType = fs->top_field->iCodingType;
+	if (fs->bottom_field && fs->top_field->poc < fs->bottom_field->poc) {
+		fs->pts = fs->top_field->pts;
+		fs->pts64 = fs->top_field->pts64;
+		/*SWPL-7105 fix */
+		if ((fs->frame->slice_type == B_SLICE)
+			&& (!fs->bottom_field->pts) &&(!fs->bottom_field->pts64)) {
+			fs->pts =  0;
+			fs->pts64 = 0;
+		}
+		fs->offset_delimiter = fs->top_field->offset_delimiter;
+		fs->decoded_frame_size = fs->top_field->pic_size + fs->bottom_field->pic_size;
+	} else if (fs->bottom_field) {
+		fs->pts = fs->bottom_field->pts;
+		fs->pts64 = fs->bottom_field->pts64;
+		fs->offset_delimiter = fs->bottom_field->offset_delimiter;
+		fs->decoded_frame_size = fs->top_field->pic_size + fs->bottom_field->pic_size;
+	}
+	/* FIELD_CODING ;*/
+}
+
+static void calculate_frame_no(struct VideoParameters *p_Vid,
+			       struct StorablePicture *p)
+{
+#if 0
+/* ??? */
+	InputParameters *p_Inp = p_Vid->p_Inp;
+	/* calculate frame number */
+	int psnrPOC = p_Vid->active_sps->mb_adaptive_frame_field_flag ?
+		p->poc / (p_Inp->poc_scale) : p->poc / (p_Inp->poc_scale);
+
+	if (psnrPOC == 0) { /* && p_Vid->psnr_number) */
+		p_Vid->idr_psnr_number =
+		p_Vid->g_nFrame * p_Vid->ref_poc_gap / (p_Inp->poc_scale);
+	}
+	p_Vid->psnr_number = imax(p_Vid->psnr_number,
+		p_Vid->idr_psnr_number + psnrPOC);
+
+	p_Vid->frame_no = p_Vid->idr_psnr_number + psnrPOC;
+#endif
+}
+
+static void insert_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb,
+				  struct FrameStore *fs,
+				  struct StorablePicture *p,
+				  unsigned char data_flag)
+{
+	struct vdec_frames_s *mvfrm = p_H264_Dpb->vdec->mvfrm;
+	struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo;
+	/* InputParameters *p_Inp = p_Vid->p_Inp;
+	 *   dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+	 *	"insert (%s) pic with frame_num #%d, poc %d\n",
+	 *	(p->structure == FRAME)?"FRAME":
+	 *	(p->structure == TOP_FIELD)?"TOP_FIELD":
+	 *	"BOTTOM_FIELD", p->pic_num, p->poc);
+	 *   assert (p!=NULL);
+	 *   assert (fs!=NULL);
+	 */
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s %p %p\n", __func__, fs, p);
+	p_H264_Dpb->dpb_frame_count++;
+	fs->dpb_frame_count = p_H264_Dpb->dpb_frame_count;
+#if 1
+/* rain */
+/* p->buf_spec_num = fs->index; */
+	p->data_flag = data_flag;
+	fs->data_flag |= data_flag;
+	fs->buf_spec_num = p->buf_spec_num;
+	fs->colocated_buf_index = p->colocated_buf_index;
+#endif
+	p->slice_type = p_H264_Dpb->mSlice.slice_type;
+	switch (p->structure) {
+	case FRAME:
+		fs->frame = p;
+		fs->is_used = 3;
+		fs->slice_type = p->slice_type;
+		fs->frame_size = p->frame_size;
+		fs->offset_delimiter = p->offset_delimiter;
+		fs->decoded_frame_size = p->pic_size;
+		if (p->used_for_reference) {
+			fs->is_reference = 3;
+			fs->is_orig_reference = 3;
+			if (p->is_long_term) {
+				fs->is_long_term = 3;
+				fs->long_term_frame_idx =
+					p->long_term_frame_idx;
+			}
+		}
+		fs->pts = p->pts;
+		fs->pts64 = p->pts64;
+		fs->layer_id = p->layer_id;
+#if (MVC_EXTENSION_ENABLE)
+		fs->view_id = p->view_id;
+		fs->inter_view_flag[0] = fs->inter_view_flag[1] =
+			p->inter_view_flag;
+		fs->anchor_pic_flag[0] = fs->anchor_pic_flag[1] =
+			p->anchor_pic_flag;
+#endif
+		/* generate field views */
+		/* return; */
+		dpb_split_field(p_H264_Dpb, fs);
+		/* return; */
+		break;
+	case TOP_FIELD:
+		fs->top_field = p;
+		fs->is_used |= 1;
+		fs->layer_id = p->layer_id;
+		if (fs->frame_size == 0) {
+			fs->slice_type = p->slice_type;
+//			fs->pts = p->pts;
+//			fs->pts64 = p->pts64;
+		}
+		fs->frame_size += p->frame_size;
+#if (MVC_EXTENSION_ENABLE)
+		fs->view_id = p->view_id;
+		fs->inter_view_flag[0] = p->inter_view_flag;
+		fs->anchor_pic_flag[0] = p->anchor_pic_flag;
+#endif
+		if (p->used_for_reference) {
+			fs->is_reference |= 1;
+			fs->is_orig_reference |= 1;
+			if (p->is_long_term) {
+				fs->is_long_term |= 1;
+				fs->long_term_frame_idx =
+					p->long_term_frame_idx;
+			}
+		}
+		if (fs->is_used == 3) {
+			/* generate frame view */
+			dpb_combine_field(p_H264_Dpb, fs);
+		} else {
+			fs->poc = p->poc;
+		}
+		gen_field_ref_ids(p_Vid, p);
+		break;
+	case BOTTOM_FIELD:
+		fs->bottom_field = p;
+		fs->is_used |= 2;
+		fs->layer_id = p->layer_id;
+		if (fs->frame_size == 0) {
+			fs->slice_type = p->slice_type;
+//			fs->pts = p->pts;
+//			fs->pts64 = p->pts64;
+		}
+		fs->frame_size += p->frame_size;
+#if (MVC_EXTENSION_ENABLE)
+		fs->view_id = p->view_id;
+		fs->inter_view_flag[1] = p->inter_view_flag;
+		fs->anchor_pic_flag[1] = p->anchor_pic_flag;
+#endif
+		if (p->used_for_reference) {
+			fs->is_reference |= 2;
+			fs->is_orig_reference |= 2;
+			if (p->is_long_term) {
+				fs->is_long_term |= 2;
+				fs->long_term_frame_idx =
+					p->long_term_frame_idx;
+			}
+		}
+		if (fs->is_used == 3) {
+			/* generate frame view */
+			dpb_combine_field(p_H264_Dpb, fs);
+		} else {
+			fs->poc = p->poc;
+		}
+		gen_field_ref_ids(p_Vid, p);
+		break;
+	}
+	fs->frame_num = p->pic_num;
+	fs->recovery_frame = p->recovery_frame;
+
+	fs->is_output = p->is_output;
+	fs->pre_output = p->pre_output;
+
+	/* picture qos infomation*/
+	fs->max_mv = p->max_mv;
+	fs->avg_mv = p->avg_mv;
+	fs->min_mv = p->min_mv;
+
+	fs->max_qp = p->max_qp;
+	fs->avg_qp = p->avg_qp;
+	fs->min_qp = p->min_qp;
+
+	fs->max_skip = p->max_skip;
+	fs->avg_skip = p->avg_skip;
+	fs->min_skip = p->min_skip;
+
+	if (fs->is_used == 3) {
+		calculate_frame_no(p_Vid, p);
+#if 0
+/* ??? */
+	if (-1 != p_Vid->p_ref && !p_Inp->silent)
+		find_snr(p_Vid, fs->frame, &p_Vid->p_ref);
+#endif
+	//fs->pts = p->pts;
+	//fs->pts64 = p->pts64;
+	}
+	fs->timestamp = p->timestamp;
+	if (mvfrm) {
+		fs->frame_size2 = mvfrm->frame_size;
+		fs->hw_decode_time = mvfrm->hw_decode_time;
+	}
+}
+
+void reset_frame_store(struct h264_dpb_stru *p_H264_Dpb,
+			      struct FrameStore *f)
+{
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s\n", __func__);
+
+	if (f) {
+		if (f->frame) {
+			free_picture(p_H264_Dpb, f->frame);
+			f->frame = NULL;
+		}
+		if (f->top_field) {
+			free_picture(p_H264_Dpb, f->top_field);
+			f->top_field = NULL;
+		}
+		if (f->bottom_field) {
+			free_picture(p_H264_Dpb, f->bottom_field);
+			f->bottom_field = NULL;
+		}
+
+		/**/
+		f->is_used      = 0;
+		f->is_reference = 0;
+		f->is_long_term = 0;
+		f->is_orig_reference = 0;
+
+		f->is_output = 0;
+		f->pre_output = 0;
+		f->show_frame   = false;
+
+		f->frame        = NULL;
+		f->top_field    = NULL;
+		f->bottom_field = NULL;
+
+		/* free(f); */
+	}
+}
+
+void unmark_for_reference(struct DecodedPictureBuffer *p_Dpb,
+				 struct FrameStore *fs)
+{
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
+				struct h264_dpb_stru, mDPB);
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s %p %p %p %p\n", __func__,
+		fs, fs->frame, fs->top_field, fs->bottom_field);
+	/* return; */
+	if (fs->is_used & 1) {
+		if (fs->top_field)
+			fs->top_field->used_for_reference = 0;
+	}
+	if (fs->is_used & 2) {
+		if (fs->bottom_field)
+			fs->bottom_field->used_for_reference = 0;
+	}
+	if (fs->is_used == 3) {
+		if (fs->top_field && fs->bottom_field) {
+			fs->top_field->used_for_reference = 0;
+			fs->bottom_field->used_for_reference = 0;
+		}
+		fs->frame->used_for_reference = 0;
+	}
+
+	fs->is_reference = 0;
+
+}
+
+static void unmark_for_long_term_reference(struct FrameStore *fs)
+{
+	if (fs->is_used & 1) {
+		if (fs->top_field) {
+			fs->top_field->used_for_reference = 0;
+			fs->top_field->is_long_term = 0;
+		}
+	}
+	if (fs->is_used & 2) {
+		if (fs->bottom_field) {
+			fs->bottom_field->used_for_reference = 0;
+			fs->bottom_field->is_long_term = 0;
+		}
+	}
+	if (fs->is_used == 3) {
+		if (fs->top_field && fs->bottom_field) {
+			fs->top_field->used_for_reference = 0;
+			fs->top_field->is_long_term = 0;
+			fs->bottom_field->used_for_reference = 0;
+			fs->bottom_field->is_long_term = 0;
+		}
+		fs->frame->used_for_reference = 0;
+		fs->frame->is_long_term = 0;
+	}
+
+	fs->is_reference = 0;
+	fs->is_long_term = 0;
+}
+
+int get_long_term_flag_by_buf_spec_num(struct h264_dpb_stru *p_H264_Dpb,
+	int buf_spec_num)
+{
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+	unsigned int i;
+
+	for (i = 0; i < p_Dpb->used_size; i++) {
+		if (p_Dpb->fs[i]->buf_spec_num == buf_spec_num)
+			return p_Dpb->fs[i]->is_long_term;
+	}
+	return -1;
+}
+
+static void update_pic_num(struct h264_dpb_stru *p_H264_Dpb)
+{
+	unsigned int i;
+	struct Slice *currSlice = &p_H264_Dpb->mSlice;
+	struct VideoParameters *p_Vid = currSlice->p_Vid;
+	struct DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb;
+	struct SPSParameters *active_sps = p_Vid->active_sps;
+	int add_top = 0, add_bottom = 0;
+	int max_frame_num = 1 << (active_sps->log2_max_frame_num_minus4 + 4);
+
+	if (currSlice->structure == FRAME) {
+		for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+			if (p_Dpb->fs_ref[i] == NULL ||
+				p_Dpb->fs_ref[i]->frame == NULL) {
+				p_H264_Dpb->dpb_error_flag = __LINE__;
+				continue;
+			}
+#endif
+			if (p_Dpb->fs_ref[i]->is_used == 3) {
+				if ((p_Dpb->fs_ref[i]->frame->
+					used_for_reference) &&
+				    (!p_Dpb->fs_ref[i]->frame->
+					is_long_term)) {
+					if (p_Dpb->fs_ref[i]->frame_num >
+						currSlice->frame_num) {
+						p_Dpb->fs_ref[i]->
+						frame_num_wrap =
+						p_Dpb->fs_ref[i]->frame_num
+							- max_frame_num;
+					} else {
+						p_Dpb->fs_ref[i]->
+						frame_num_wrap =
+						p_Dpb->fs_ref[i]->frame_num;
+					}
+					p_Dpb->fs_ref[i]->frame->pic_num =
+					p_Dpb->fs_ref[i]->frame_num_wrap;
+				}
+			}
+		}
+		/* update long_term_pic_num */
+		for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+			if (p_Dpb->fs_ltref[i] == NULL ||
+				p_Dpb->fs_ltref[i]->frame == NULL) {
+				p_H264_Dpb->dpb_error_flag = __LINE__;
+				continue;
+			}
+#endif
+			if (p_Dpb->fs_ltref[i]->is_used == 3) {
+				if (p_Dpb->fs_ltref[i]->frame->is_long_term) {
+					p_Dpb->fs_ltref[i]->frame->
+						long_term_pic_num =
+						p_Dpb->fs_ltref[i]->frame->
+							long_term_frame_idx;
+				}
+			}
+		}
+	} else {
+		if (currSlice->structure == TOP_FIELD) {
+			add_top    = 1;
+			add_bottom = 0;
+		} else {
+			add_top    = 0;
+			add_bottom = 1;
+		}
+
+		for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+			if (p_Dpb->fs_ref[i] == NULL) {
+				p_H264_Dpb->dpb_error_flag = __LINE__;
+				continue;
+			}
+#endif
+			if (p_Dpb->fs_ref[i]->is_reference) {
+				if (p_Dpb->fs_ref[i]->frame_num > currSlice->
+					frame_num) {
+					p_Dpb->fs_ref[i]->frame_num_wrap =
+					p_Dpb->fs_ref[i]->frame_num -
+					max_frame_num;
+				} else {
+					p_Dpb->fs_ref[i]->frame_num_wrap =
+					p_Dpb->fs_ref[i]->frame_num;
+				}
+				if (p_Dpb->fs_ref[i]->is_reference & 1) {
+#ifdef ERROR_CHECK
+					if (p_Dpb->fs_ref[i]->top_field
+						== NULL) {
+						p_H264_Dpb->dpb_error_flag =
+							__LINE__;
+						continue;
+					}
+#endif
+					p_Dpb->fs_ref[i]->top_field->
+					pic_num = (2 * p_Dpb->fs_ref[i]->
+						frame_num_wrap) + add_top;
+				}
+				if (p_Dpb->fs_ref[i]->is_reference & 2) {
+#ifdef ERROR_CHECK
+					if (p_Dpb->fs_ref[i]->bottom_field
+						== NULL) {
+						p_H264_Dpb->dpb_error_flag =
+							__LINE__;
+						continue;
+					}
+#endif
+					p_Dpb->fs_ref[i]->bottom_field->
+					pic_num = (2 * p_Dpb->fs_ref[i]->
+						frame_num_wrap) + add_bottom;
+				}
+			}
+		}
+		/* update long_term_pic_num */
+		for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+			if (p_Dpb->fs_ltref[i] == NULL) {
+				p_H264_Dpb->dpb_error_flag = __LINE__;
+				continue;
+			}
+#endif
+			if (p_Dpb->fs_ltref[i]->is_long_term & 1) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ltref[i]->top_field == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				p_Dpb->fs_ltref[i]->top_field->
+					long_term_pic_num = 2 *
+					p_Dpb->fs_ltref[i]->top_field->
+					long_term_frame_idx + add_top;
+			}
+			if (p_Dpb->fs_ltref[i]->is_long_term & 2) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ltref[i]->bottom_field == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				p_Dpb->fs_ltref[i]->bottom_field->
+					long_term_pic_num = 2 *
+					p_Dpb->fs_ltref[i]->bottom_field->
+					long_term_frame_idx + add_bottom;
+			}
+		}
+	}
+}
+
+static void remove_frame_from_dpb(struct h264_dpb_stru *p_H264_Dpb, int pos)
+{
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+	struct FrameStore *fs = p_Dpb->fs[pos];
+	struct FrameStore *tmp;
+	unsigned int i;
+
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s pos %d %p\n", __func__, pos, fs);
+
+	/* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+	 *	"remove frame with frame_num #%d\n", fs->frame_num);
+	 */
+	switch (fs->is_used) {
+	case 3:
+		free_picture(p_H264_Dpb, fs->frame);
+		free_picture(p_H264_Dpb, fs->top_field);
+		free_picture(p_H264_Dpb, fs->bottom_field);
+		fs->frame = NULL;
+		fs->top_field = NULL;
+		fs->bottom_field = NULL;
+		break;
+	case 2:
+		free_picture(p_H264_Dpb, fs->bottom_field);
+		fs->bottom_field = NULL;
+		break;
+	case 1:
+		free_picture(p_H264_Dpb, fs->top_field);
+		fs->top_field = NULL;
+		break;
+	case 0:
+		break;
+	default:
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			  "invalid frame store type %x", 500);
+	}
+	fs->data_flag = 0;
+	fs->is_used = 0;
+	fs->is_long_term = 0;
+	fs->is_reference = 0;
+	fs->is_orig_reference = 0;
+	fs->frame_size = 0;
+	/* move empty framestore to end of buffer */
+	tmp = p_Dpb->fs[pos];
+
+	for (i = pos; i < p_Dpb->used_size - 1; i++)
+		p_Dpb->fs[i] = p_Dpb->fs[i + 1];
+	p_Dpb->fs[p_Dpb->used_size - 1] = tmp;
+
+	if (p_Dpb->used_size)
+		p_Dpb->used_size--;
+}
+
+int is_used_for_reference(struct FrameStore *fs)
+{
+	if (fs->is_reference)
+		return 1;
+
+	if (fs->is_used == 3) { /* frame */
+		if (fs->frame->used_for_reference)
+			return 1;
+	}
+
+	if (fs->is_used & 1) { /* top field */
+		if (fs->top_field) {
+			if (fs->top_field->used_for_reference)
+				return 1;
+		}
+	}
+
+	if (fs->is_used & 2) { /* bottom field */
+		if (fs->bottom_field) {
+			if (fs->bottom_field->used_for_reference)
+				return 1;
+		}
+	}
+	return 0;
+}
+
+static int remove_unused_frame_from_dpb(struct h264_dpb_stru *p_H264_Dpb)
+{
+	unsigned int i;
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+	/* check for frames that were already output and no longer
+	 *	used for reference
+	 */
+	for (i = 0; i < p_Dpb->used_size; i++) {
+		if ((!is_used_for_reference(p_Dpb->fs[i])) &&
+		    (p_Dpb->fs[i]->colocated_buf_index >= 0)) {
+			dpb_print(p_H264_Dpb->decoder_index,
+			PRINT_FLAG_DPB_DETAIL,
+			"release_colocate_buf[%d] for fs[%d]\n",
+			p_Dpb->fs[i]->colocated_buf_index, i);
+
+			release_colocate_buf(p_H264_Dpb,
+				p_Dpb->fs[i]->colocated_buf_index); /* rain */
+			p_Dpb->fs[i]->colocated_buf_index = -1;
+		}
+	}
+
+	for (i = 0; i < p_Dpb->used_size; i++) {
+		if (p_Dpb->fs[i]->is_output &&
+			(!is_used_for_reference(p_Dpb->fs[i]))) {
+			release_buf_spec_num(p_H264_Dpb->vdec,
+				p_Dpb->fs[i]->buf_spec_num);
+			p_Dpb->fs[i]->buf_spec_num = -1;
+			remove_frame_from_dpb(p_H264_Dpb, i);
+
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "%s[%d]\n",
+				__func__, i);
+
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int unmark_one_error_out_frame(struct h264_dpb_stru *p_H264_Dpb)
+{
+	int ret = 0;
+	unsigned i;
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+
+	for (i = 0; i < p_Dpb->used_size; i++) {
+		if (p_Dpb->fs[i]->is_output &&
+			((p_Dpb->fs[i]->data_flag & ERROR_FLAG) ||
+			(p_Dpb->fs[i]->data_flag & NULL_FLAG))
+			) {
+			unmark_for_reference(p_Dpb, p_Dpb->fs[i]);
+
+			ret = 1;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int unmark_one_out_frame(struct h264_dpb_stru *p_H264_Dpb)
+{
+	int ret = 0;
+	unsigned i;
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+
+	for (i = 0; i < p_Dpb->used_size; i++) {
+		if (p_Dpb->fs[i]->is_output) {
+			unmark_for_reference(p_Dpb, p_Dpb->fs[i]);
+
+			ret = 1;
+		}
+	}
+	return ret;
+}
+/*
+	force_flag,
+		1, remove one error buf (is_out is 1) if there is no un-used buf
+		2, remove one buf (is_out is 1) if there is no un-used buf
+*/
+void bufmgr_h264_remove_unused_frame(struct h264_dpb_stru *p_H264_Dpb,
+	u8 force_flag)
+{
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+	int ret = 0;
+	unsigned char removed_flag = 0;
+	do {
+		ret = remove_unused_frame_from_dpb(p_H264_Dpb);
+		if (ret != 0)
+			removed_flag = 1;
+	} while (ret != 0);
+	if (removed_flag) {
+		dpb_print(p_H264_Dpb->decoder_index,
+			PRINT_FLAG_DPB_DETAIL, "%s\r\n", __func__);
+		dump_dpb(p_Dpb, 0);
+	} else if (force_flag == 2) {
+		if (unmark_one_out_frame(p_H264_Dpb)) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				0, "%s, Warnning, force unmark one frame\r\n",
+				__func__);
+			update_ref_list(p_Dpb);
+			remove_unused_frame_from_dpb(p_H264_Dpb);
+			dump_dpb(p_Dpb, 0);
+		}
+	} else if (force_flag == 1) {
+		if (unmark_one_error_out_frame(p_H264_Dpb)) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				0, "%s, unmark error frame\r\n",
+				__func__);
+			update_ref_list(p_Dpb);
+			remove_unused_frame_from_dpb(p_H264_Dpb);
+			dump_dpb(p_Dpb, 0);
+		}
+	}
+}
+
+#ifdef OUTPUT_BUFFER_IN_C
+int is_there_unused_frame_from_dpb(struct DecodedPictureBuffer *p_Dpb)
+{
+	unsigned int i;
+
+	/* check for frames that were already output and no longer
+	 * used for reference
+	 */
+	for (i = 0; i < p_Dpb->used_size; i++) {
+		if (p_Dpb->fs[i]->is_output &&
+			(!is_used_for_reference(p_Dpb->fs[i]))) {
+			return 1;
+		}
+	}
+	return 0;
+}
+#endif
+
+static void get_smallest_poc(struct DecodedPictureBuffer *p_Dpb, int *poc,
+			     int *pos)
+{
+	unsigned int i;
+	unsigned long flags;
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
+				struct h264_dpb_stru, mDPB);
+	struct vdec_s *vdec= (struct vdec_s *)p_H264_Dpb->vdec;
+	void *p = vh264_get_bufspec_lock(vdec);
+	dpb_print(p_H264_Dpb->decoder_index,
+		PRINT_FLAG_DPB_DETAIL, "%s\n", __func__);
+	if (p_Dpb->used_size < 1) {
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			  "Cannot determine smallest POC, DPB empty. %d\n",
+			 150);
+	}
+
+	*pos = -1;
+	*poc = INT_MAX;
+	if (p == NULL)
+		return;
+	spin_lock_irqsave(p, flags);
+	for (i = 0; i < p_Dpb->used_size; i++) {
+#ifdef OUTPUT_BUFFER_IN_C
+		/* rain */
+		if ((*poc > p_Dpb->fs[i]->poc) &&
+			(!p_Dpb->fs[i]->is_output) &&
+			(!p_Dpb->fs[i]->pre_output)) {
+#else
+		if ((*poc > p_Dpb->fs[i]->poc) && (!p_Dpb->fs[i]->is_output)) {
+#endif
+			*poc = p_Dpb->fs[i]->poc;
+			*pos = i;
+		}
+	}
+	spin_unlock_irqrestore(p, flags);
+}
+
+int output_frames(struct h264_dpb_stru *p_H264_Dpb, unsigned char flush_flag)
+{
+	int poc, pos;
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+	int i;
+	int none_displayed_num = 0;
+	unsigned char fast_output_flag = 0;
+	if (!flush_flag) {
+		for (i = 0; i < p_Dpb->used_size; i++) {
+			if ((!p_Dpb->fs[i]->is_output) &&
+				(!p_Dpb->fs[i]->pre_output) &&((p_Dpb->fs[i]->is_used == 3
+				||p_Dpb->fs[i]->data_flag & ERROR_FLAG )))  {
+				none_displayed_num++;
+				if ((p_H264_Dpb->first_insert_frame == FirstInsertFrm_IDLE ||
+					p_H264_Dpb->first_insert_frame == FirstInsertFrm_RESET)
+					&&  (p_Dpb->fs[i]->is_used == 3)
+					&& (p_Dpb->last_output_poc == INT_MIN)) {
+					if (p_H264_Dpb->first_insert_frame == FirstInsertFrm_IDLE)
+						fast_output_flag = 1;
+					p_H264_Dpb->first_insert_frame = FirstInsertFrm_OUT;
+					p_H264_Dpb->first_output_poc = p_Dpb->fs[i]->poc;
+					dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+						"%s first insert frame i %d  poc %d frame_num %x\n",
+						__func__, i, p_Dpb->fs[i]->poc,  p_Dpb->fs[i]->frame_num);
+				}
+
+				/*check poc even/odd*/
+				if (p_H264_Dpb->poc_even_odd_flag == 0 &&
+					p_H264_Dpb->decode_pic_count >= 3)
+					p_H264_Dpb->poc_even_odd_flag = 2;
+				if (p_Dpb->fs[i]->poc & 0x1)
+					p_H264_Dpb->poc_even_odd_flag = 1;
+				/**/
+
+				if ((p_H264_Dpb->fast_output_enable & 0x1) &&
+					(p_Dpb->fs[i]->data_flag & IDR_FLAG))
+					fast_output_flag = 1;
+				if ((p_H264_Dpb->fast_output_enable & 0x2) &&
+					((p_Dpb->fs[i]->poc -
+						p_Dpb->last_output_poc)
+					== 1))
+					fast_output_flag = 1;
+				if ((p_H264_Dpb->fast_output_enable & 0x4) &&
+					(p_H264_Dpb->poc_even_odd_flag == 2) &&
+					 (p_Dpb->fs[i]->is_used == 3) &&
+					((p_Dpb->fs[i]->poc -
+						p_Dpb->last_output_poc)
+					== 2))
+					fast_output_flag = 1;
+			}
+		}
+		if (fast_output_flag)
+			;
+		else if (none_displayed_num <
+			p_H264_Dpb->reorder_output)
+			return 0;
+	}
+
+	get_smallest_poc(p_Dpb, &poc, &pos);
+
+	if (pos == -1)
+		return 0;
+#if 0
+	if (is_used_for_reference(p_Dpb->fs[pos]))
+		return 0;
+#endif
+	if (p_H264_Dpb->first_insert_frame == FirstInsertFrm_OUT) {
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			"%s pos %d pos->poc %d  first_output_poc %d \n",
+			__func__, pos, p_Dpb->fs[pos]->poc, p_H264_Dpb->first_output_poc);
+
+		if (p_Dpb->fs[pos]->poc < p_H264_Dpb->first_output_poc)
+			p_Dpb->fs[pos]->data_flag |= NODISP_FLAG;
+		else if (p_Dpb->last_output_poc != INT_MIN)
+			p_H264_Dpb->first_insert_frame = FirstInsertFrm_SKIPDONE;
+
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			"%s first_insert_frame %d \n", __func__, p_H264_Dpb->first_insert_frame);
+	}
+	if (prepare_display_buf(p_H264_Dpb->vdec, p_Dpb->fs[pos]) >= 0) {
+		if (!p_H264_Dpb->without_display_mode &&
+				p_Dpb->fs[pos]->show_frame != false)
+			p_Dpb->fs[pos]->pre_output = 1;
+	} else {
+		if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) {
+			dpb_print(p_H264_Dpb->decoder_index, 0,
+			"%s[%d] poc:%d last_output_poc:%d poc_even_odd_flag:%d\n",
+			__func__, pos, poc,
+			p_Dpb->last_output_poc,
+			p_H264_Dpb->poc_even_odd_flag);
+			dump_dpb(p_Dpb, 1);
+		}
+		return 0;
+	}
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s[%d] poc %d last_output_poc %d poc_even_odd_flag %d\n",
+		__func__, pos, poc,
+		p_Dpb->last_output_poc,
+		p_H264_Dpb->poc_even_odd_flag);
+
+	p_Dpb->last_output_poc = poc;
+	return 1;
+
+}
+
+
+void flush_dpb(struct h264_dpb_stru *p_H264_Dpb)
+{
+	/* struct VideoParameters *p_Vid = p_Dpb->p_Vid; */
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+	unsigned int i;
+
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s\n", __func__);
+
+	/* diagnostics */
+	/* dpb_print(p_H264_Dpb->decoder_index,
+	 *PRINT_FLAG_DPB_DETAIL,
+	 *"Flush remaining frames from the dpb."
+	 *"p_Dpb->size = %d, p_Dpb->used_size = %d\n",
+	 *p_Dpb->size, p_Dpb->used_size);
+	 */
+
+	if (!p_Dpb->init_done)
+		return;
+/*  if(p_Vid->conceal_mode == 0) */
+#if 0
+/* ??? */
+	if (p_Vid->conceal_mode != 0)
+		conceal_non_ref_pics(p_Dpb, 0);
+#endif
+	/* mark all frames unused */
+	for (i = 0; i < p_Dpb->used_size; i++) {
+#if MVC_EXTENSION_ENABLE
+		assert(p_Dpb->fs[i]->view_id == p_Dpb->layer_id);
+#endif
+		unmark_for_reference(p_Dpb, p_Dpb->fs[i]);
+
+	}
+
+	while (remove_unused_frame_from_dpb(p_H264_Dpb))
+		;
+
+	/* output frames in POC order */
+	while (output_frames(p_H264_Dpb, 1))
+		;
+
+
+	p_Dpb->last_output_poc = INT_MIN;
+}
+
+static int is_short_term_reference(struct DecodedPictureBuffer *p_Dpb,
+				   struct FrameStore *fs)
+{
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
+			struct h264_dpb_stru, mDPB);
+	if (fs->is_used == 3) { /* frame */
+		if ((fs->frame->used_for_reference) &&
+			(!fs->frame->is_long_term)) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "[[%s 1]]",
+				__func__);
+			return 1;
+		}
+	}
+
+	if (fs->is_used & 1) { /* top field */
+		if (fs->top_field) {
+			if ((fs->top_field->used_for_reference) &&
+				(!fs->top_field->is_long_term)) {
+				dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "[[%s 2]]",
+				__func__);
+				return 1;
+			}
+		}
+	}
+
+	if (fs->is_used & 2) { /* bottom field */
+		if (fs->bottom_field) {
+			if ((fs->bottom_field->used_for_reference) &&
+			    (!fs->bottom_field->is_long_term)) {
+				dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "[[%s 3]]",
+				__func__);
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
+static int is_long_term_reference(struct FrameStore *fs)
+{
+
+	if (fs->is_used == 3) { /* frame */
+		if ((fs->frame->used_for_reference) &&
+			(fs->frame->is_long_term)) {
+			return 1;
+		}
+	}
+
+	if (fs->is_used & 1) { /* top field */
+		if (fs->top_field) {
+			if ((fs->top_field->used_for_reference) &&
+				(fs->top_field->is_long_term)) {
+				return 1;
+			}
+		}
+	}
+
+	if (fs->is_used & 2) { /* bottom field */
+		if (fs->bottom_field) {
+			if ((fs->bottom_field->used_for_reference) &&
+			    (fs->bottom_field->is_long_term)) {
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
+void update_ref_list(struct DecodedPictureBuffer *p_Dpb)
+{
+	unsigned int i, j;
+
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
+		struct h264_dpb_stru, mDPB);
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s (%d, %d)\n", __func__, p_Dpb->size, p_Dpb->used_size);
+	for (i = 0, j = 0; i < p_Dpb->used_size; i++) {
+#if 1
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			  "fs[%d]: fs %p frame %p is_reference %d %d %d\n",
+			  i, p_Dpb->fs[i], p_Dpb->fs[i]->frame,
+			  p_Dpb->fs[i]->frame != NULL ?
+			  p_Dpb->fs[i]->frame->used_for_reference : 0,
+			  p_Dpb->fs[i]->top_field != NULL ?
+			  p_Dpb->fs[i]->top_field->used_for_reference :
+			  0,
+			  p_Dpb->fs[i]->bottom_field != NULL ?
+			  p_Dpb->fs[i]->bottom_field->used_for_reference : 0);
+#endif
+		if (is_short_term_reference(p_Dpb, p_Dpb->fs[i])) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+			"fs_ref[%d]=fs[%d]: fs %p\n", j, i, p_Dpb->fs[i]);
+			p_Dpb->fs_ref[j++] = p_Dpb->fs[i];
+		}
+	}
+
+	p_Dpb->ref_frames_in_buffer = j;
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s dpb size is %d, %d\n", __func__, p_Dpb->size, j);
+	while (j < p_Dpb->size) {
+		/* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		 *"fs_ref[%d]=null\n", j);
+		 */
+		p_Dpb->fs_ref[j++] = NULL;
+	}
+#ifdef ERROR_CHECK
+	for (i = 0; i < DPB_SIZE_MAX; i++) {
+		if (p_Dpb->fs_ref[i] == NULL)
+			p_Dpb->fs_ref[i] = &dummy_fs;
+	}
+#endif
+}
+
+static void update_ltref_list(struct DecodedPictureBuffer *p_Dpb)
+{
+	unsigned int i, j;
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
+		struct h264_dpb_stru, mDPB);
+
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s\n", __func__);
+	for (i = 0, j = 0; i < p_Dpb->used_size; i++) {
+		if (is_long_term_reference(p_Dpb->fs[i]))
+			p_Dpb->fs_ltref[j++] = p_Dpb->fs[i];
+	}
+
+	p_Dpb->ltref_frames_in_buffer = j;
+
+	while (j < p_Dpb->size)
+		p_Dpb->fs_ltref[j++] = NULL;
+#ifdef ERROR_CHECK
+	for (i = 0; i < DPB_SIZE_MAX; i++) {
+		if (p_Dpb->fs_ltref[i] == NULL)
+			p_Dpb->fs_ltref[i] = &dummy_fs;
+	}
+#endif
+}
+
+static void idr_memory_management(struct h264_dpb_stru *p_H264_Dpb,
+				  struct StorablePicture *p)
+{
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+	"%s ref_frames_in_buffer %d ltref_frames_in_buffer %d\n",
+	__func__, p_Dpb->ref_frames_in_buffer,
+	p_Dpb->ltref_frames_in_buffer);
+
+
+	if (p->no_output_of_prior_pics_flag) {
+		int i;
+		for (i = 0; i < p_Dpb->used_size; i++) {
+			unmark_for_reference(p_Dpb, p_Dpb->fs[i]);
+			if (p_Dpb->fs[i]->is_long_term)
+				unmark_for_long_term_reference(p_Dpb->fs[i]);
+			if (!p_Dpb->fs[i]->is_output && !p_Dpb->fs[i]->pre_output)
+				set_frame_output_flag(p_H264_Dpb, i);
+		}
+#if 0
+		/*???*/
+		/* free all stored pictures */
+		int i;
+
+		for (i = 0; i < p_Dpb->used_size; i++) {
+			/* reset all reference settings
+			 * free_frame_store(p_Dpb->fs[i]);
+			 * p_Dpb->fs[i] = alloc_frame_store();
+			 */
+			reset_frame_store(p_H264_Dpb, p_Dpb->fs[i]); /* ??? */
+		}
+		for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++)
+			p_Dpb->fs_ref[i] = NULL;
+		for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++)
+			p_Dpb->fs_ltref[i] = NULL;
+		p_Dpb->used_size = 0;
+#endif
+	} else {
+		flush_dpb(p_H264_Dpb);
+	}
+	p_Dpb->last_picture = NULL;
+
+	update_ref_list(p_Dpb);
+	update_ltref_list(p_Dpb);
+	p_Dpb->last_output_poc = INT_MIN;
+
+	if (p->long_term_reference_flag) {
+		p_Dpb->max_long_term_pic_idx = 0;
+		p->is_long_term           = 1;
+		p->long_term_frame_idx    = 0;
+	} else {
+		p_Dpb->max_long_term_pic_idx = -1;
+		p->is_long_term           = 0;
+	}
+
+#if (MVC_EXTENSION_ENABLE)
+	p_Dpb->last_output_view_id = -1;
+#endif
+
+}
+
+static void sliding_window_memory_management(
+		struct DecodedPictureBuffer *p_Dpb,
+		struct StorablePicture *p)
+{
+	unsigned int i;
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
+		struct h264_dpb_stru, mDPB);
+	unsigned char slide_flag = 0;
+	unsigned int sliding_margin = imax(
+		1, p_Dpb->num_ref_frames) - p_Dpb->ltref_frames_in_buffer;
+	/* assert (!p->idr_flag); */
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+	"%s ref_frames_in_buffer %d ltref_frames_in_buffer %d\n",
+	__func__, p_Dpb->ref_frames_in_buffer,
+	p_Dpb->ltref_frames_in_buffer);
+	/* if this is a reference pic with sliding window,
+	   unmark first ref frame */
+	if (p_Dpb->ref_frames_in_buffer == sliding_margin)
+		slide_flag = 1;
+	/*else if ((h264_error_proc_policy & 0x8) &&
+		(p_Dpb->ref_frames_in_buffer > sliding_margin))
+		slide_flag = 1;*/
+
+	if (slide_flag) {
+		for (i = 0; i < p_Dpb->used_size; i++) {
+			if (p_Dpb->fs[i]->is_reference &&
+				(!(p_Dpb->fs[i]->is_long_term))) {
+				dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "unmark %d\n", i);
+				unmark_for_reference(p_Dpb, p_Dpb->fs[i]);
+				update_ref_list(p_Dpb);
+				break;
+			}
+		}
+	}
+
+	p->is_long_term = 0;
+}
+
+static void check_num_ref(struct DecodedPictureBuffer *p_Dpb)
+{
+	if ((int)(p_Dpb->ltref_frames_in_buffer +
+			p_Dpb->ref_frames_in_buffer) >
+			imax(1, p_Dpb->num_ref_frames)) {
+		struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
+					 struct h264_dpb_stru, mDPB);
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			  "Max. number of reference frames exceeded. Invalid stream. lt %d ref %d mum_ref %d\n",
+			  p_Dpb->ltref_frames_in_buffer,
+			  p_Dpb->ref_frames_in_buffer,
+			  p_Dpb->num_ref_frames);
+	}
+}
+
+void dump_dpb(struct DecodedPictureBuffer *p_Dpb, u8 force)
+{
+	unsigned int i;
+	unsigned char *buf = NULL;
+	unsigned int buf_size = 512, len = 0;
+	struct h264_dpb_stru *p_H264_Dpb =
+		container_of(p_Dpb, struct h264_dpb_stru, mDPB);
+
+#define DPB_STRCAT(args...)  do {	\
+		len += snprintf(buf + len,	\
+			buf_size - len, ##args);\
+	} while (0)
+
+	if ((h264_debug_flag & PRINT_FLAG_DUMP_DPB) == 0 &&
+		force == 0)
+		return;
+
+	buf = kzalloc(buf_size, GFP_ATOMIC);
+	if (buf == NULL)
+		return;
+
+	for (i = 0; i < p_Dpb->used_size; i++) {
+		len = 0;
+		memset(buf, 0, buf_size);
+		DPB_STRCAT("fn=%d  is_used %d ",
+			p_Dpb->fs[i]->frame_num,
+			p_Dpb->fs[i]->is_used);
+
+		if (p_Dpb->fs[i]->is_used & 1) {
+			if (p_Dpb->fs[i]->top_field)
+				DPB_STRCAT("T: poc=%d  pic_num=%d ",
+				p_Dpb->fs[i]->top_field->poc,
+				p_Dpb->fs[i]->top_field->pic_num);
+			else
+				DPB_STRCAT("T: poc=%d  ",
+				p_Dpb->fs[i]->frame->top_poc);
+		}
+		if (p_Dpb->fs[i]->is_used & 2) {
+			if (p_Dpb->fs[i]->bottom_field)
+				DPB_STRCAT("B: poc=%d  pic_num=%d ",
+				p_Dpb->fs[i]->bottom_field->poc,
+				p_Dpb->fs[i]->bottom_field->pic_num);
+			else
+				DPB_STRCAT("B: poc=%d  ",
+				p_Dpb->fs[i]->frame->bottom_poc);
+		}
+		if (p_Dpb->fs[i]->is_used == 3) {
+			if (p_Dpb->fs[i]->frame != NULL)
+				DPB_STRCAT("F: poc=%d pic_num=%d ",
+				p_Dpb->fs[i]->frame->poc,
+				p_Dpb->fs[i]->frame->pic_num);
+			else
+				DPB_STRCAT("fs[%d] frame is null ", i);
+		}
+		DPB_STRCAT("G: poc=%d)  ", p_Dpb->fs[i]->poc);
+		if (p_Dpb->fs[i]->is_reference)
+			DPB_STRCAT("ref (%d) ", p_Dpb->fs[i]->is_reference);
+		if (p_Dpb->fs[i]->is_long_term)
+			DPB_STRCAT("lt_ref (%d) ", p_Dpb->fs[i]->is_reference);
+		if (p_Dpb->fs[i]->is_output)
+			DPB_STRCAT("out(displayed)  ");
+		if (p_Dpb->fs[i]->pre_output)
+			DPB_STRCAT("pre_output(in dispq or displaying)  ");
+		if (p_Dpb->fs[i]->is_used == 3) {
+			if (p_Dpb->fs[i]->frame != NULL && p_Dpb->fs[i]->frame->non_existing)
+				DPB_STRCAT("non_existing  ");
+			else
+				DPB_STRCAT("fs[%d] frame is null ", i);
+		}
+		DPB_STRCAT("dpb_frame_count %d  ",
+			p_Dpb->fs[i]->dpb_frame_count);
+
+#if (MVC_EXTENSION_ENABLE)
+		if (p_Dpb->fs[i]->is_reference)
+			DPB_STRCAT("view_id (%d) ", p_Dpb->fs[i]->view_id);
+#endif
+		if (p_Dpb->fs[i]->data_flag) {
+			DPB_STRCAT("data_flag(0x%x)",
+			p_Dpb->fs[i]->data_flag);
+		}
+		DPB_STRCAT(" bufspec %d\n",
+			p_Dpb->fs[i]->buf_spec_num);
+		dpb_print(p_H264_Dpb->decoder_index, 0, "%s", buf);
+	}
+
+	kfree(buf);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    adaptive memory management
+ *
+ ************************************************************************
+ */
+
+static int get_pic_num_x(struct StorablePicture *p,
+			 int difference_of_pic_nums_minus1)
+{
+	int currPicNum;
+
+	if (p->structure == FRAME)
+		currPicNum = p->frame_num;
+	else
+		currPicNum = 2 * p->frame_num + 1;
+
+	return currPicNum - (difference_of_pic_nums_minus1 + 1);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Adaptive Memory Management: Mark short term picture unused
+ ************************************************************************
+ */
+static void mm_unmark_short_term_for_reference(struct DecodedPictureBuffer
+		*p_Dpb, struct StorablePicture *p,
+		int difference_of_pic_nums_minus1)
+{
+	struct h264_dpb_stru *p_H264_Dpb =
+		container_of(p_Dpb, struct h264_dpb_stru, mDPB);
+	int picNumX;
+
+	unsigned int i;
+
+	picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1);
+
+	for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+		if (p_Dpb->fs_ref[i] == NULL) {
+			p_H264_Dpb->dpb_error_flag = __LINE__;
+			continue;
+		}
+#endif
+		if (p->structure == FRAME) {
+			if ((p_Dpb->fs_ref[i]->is_reference == 3) &&
+			    (p_Dpb->fs_ref[i]->is_long_term == 0)) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i]->frame == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if (p_Dpb->fs_ref[i]->frame->pic_num ==
+					picNumX) {
+					unmark_for_reference(p_Dpb,
+						p_Dpb->fs_ref[i]);
+					return;
+				}
+			}
+		} else {
+			if ((p_Dpb->fs_ref[i]->is_reference & 1) &&
+			    (!(p_Dpb->fs_ref[i]->is_long_term & 1))) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i]->top_field == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if (p_Dpb->fs_ref[i]->top_field->pic_num ==
+					picNumX) {
+					p_Dpb->fs_ref[i]->
+					top_field->used_for_reference = 0;
+					p_Dpb->fs_ref[i]->is_reference &= 2;
+					if ((p_Dpb->fs_ref[i]->is_used == 3)
+#ifdef ERROR_CHECK
+						&& p_Dpb->fs_ref[i]->frame
+#endif
+					) {
+						p_Dpb->fs_ref[i]->frame->
+							used_for_reference = 0;
+					}
+					return;
+				}
+			}
+			if ((p_Dpb->fs_ref[i]->is_reference & 2) &&
+			    (!(p_Dpb->fs_ref[i]->is_long_term & 2))) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i]->bottom_field == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if (p_Dpb->fs_ref[i]->bottom_field->pic_num ==
+					picNumX) {
+					p_Dpb->fs_ref[i]->bottom_field->
+					used_for_reference = 0;
+					p_Dpb->fs_ref[i]->is_reference &= 1;
+					if ((p_Dpb->fs_ref[i]->is_used == 3)
+#ifdef ERROR_CHECK
+						&& p_Dpb->fs_ref[i]->frame
+#endif
+						) {
+						p_Dpb->fs_ref[i]->frame->
+						used_for_reference = 0;
+					}
+					return;
+				}
+			}
+		}
+	}
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Adaptive Memory Management: Mark long term picture unused
+ ************************************************************************
+ */
+static void mm_unmark_long_term_for_reference(struct DecodedPictureBuffer
+		*p_Dpb, struct StorablePicture *p, int long_term_pic_num)
+{
+	unsigned int i;
+
+	for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
+		if (p->structure == FRAME) {
+			if ((p_Dpb->fs_ltref[i]->is_reference == 3) &&
+			    (p_Dpb->fs_ltref[i]->is_long_term == 3)) {
+				if (p_Dpb->fs_ltref[i]->frame->
+					long_term_pic_num ==
+					long_term_pic_num) {
+					unmark_for_long_term_reference(
+						p_Dpb->fs_ltref[i]);
+				}
+			}
+		} else {
+			if ((p_Dpb->fs_ltref[i]->is_reference & 1) &&
+			    ((p_Dpb->fs_ltref[i]->is_long_term & 1))) {
+				if (p_Dpb->fs_ltref[i]->top_field->
+					long_term_pic_num ==
+					long_term_pic_num) {
+					p_Dpb->fs_ltref[i]->top_field->
+						used_for_reference = 0;
+					p_Dpb->fs_ltref[i]->top_field->
+						is_long_term = 0;
+					p_Dpb->fs_ltref[i]->is_reference &= 2;
+					p_Dpb->fs_ltref[i]->is_long_term &= 2;
+					if (p_Dpb->fs_ltref[i]->is_used == 3) {
+						p_Dpb->fs_ltref[i]->frame->
+							used_for_reference = 0;
+						p_Dpb->fs_ltref[i]->frame->
+							is_long_term = 0;
+					}
+					return;
+				}
+			}
+			if ((p_Dpb->fs_ltref[i]->is_reference & 2) &&
+			    ((p_Dpb->fs_ltref[i]->is_long_term & 2))) {
+				if (p_Dpb->fs_ltref[i]->bottom_field->
+					long_term_pic_num ==
+					long_term_pic_num) {
+					p_Dpb->fs_ltref[i]->bottom_field->
+						used_for_reference = 0;
+					p_Dpb->fs_ltref[i]->bottom_field->
+						is_long_term = 0;
+					p_Dpb->fs_ltref[i]->is_reference &= 1;
+					p_Dpb->fs_ltref[i]->is_long_term &= 1;
+					if (p_Dpb->fs_ltref[i]->is_used == 3) {
+						p_Dpb->fs_ltref[i]->frame->
+							used_for_reference = 0;
+						p_Dpb->fs_ltref[i]->frame->
+							is_long_term = 0;
+					}
+					return;
+				}
+			}
+		}
+	}
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Mark a long-term reference frame or complementary
+ *    field pair unused for referemce
+ ************************************************************************
+ */
+static void unmark_long_term_frame_for_reference_by_frame_idx(
+	struct DecodedPictureBuffer *p_Dpb, int long_term_frame_idx)
+{
+	unsigned int i;
+
+	for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
+		if (p_Dpb->fs_ltref[i]->long_term_frame_idx ==
+			long_term_frame_idx)
+			unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
+	}
+}
+
+
+static void unmark1(struct DecodedPictureBuffer *p_Dpb,
+	unsigned int curr_frame_num, int i)
+{
+	if (p_Dpb->last_picture) {
+		/*if ((p_Dpb->last_picture != p_Dpb->fs_ltref[i]) ||
+			p_Dpb->last_picture->frame_num != curr_frame_num) {*/
+			unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
+		/*} else {
+			unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
+		}*/
+	}
+}
+
+static void unmark2(struct DecodedPictureBuffer *p_Dpb,
+	int curr_pic_num, int i)
+{
+	if ((p_Dpb->fs_ltref[i]->frame_num) !=
+		(unsigned int)(curr_pic_num >> 1))
+		unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
+}
+
+static void unmark3_top(struct DecodedPictureBuffer *p_Dpb,
+	unsigned int curr_frame_num, int curr_pic_num, int mark_current, int i)
+{
+	if (p_Dpb->fs_ltref[i]->is_long_term == 3) {
+		unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
+	} else {
+		if (p_Dpb->fs_ltref[i]->is_long_term == 1) {
+			unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
+		} else {
+			if (mark_current)
+				unmark1(p_Dpb, curr_frame_num, i);
+			else
+				unmark2(p_Dpb, curr_pic_num, i);
+		}
+	}
+}
+
+static void unmark3_bottom(struct DecodedPictureBuffer *p_Dpb,
+	unsigned int curr_frame_num, int curr_pic_num, int mark_current, int i)
+{
+	if (p_Dpb->fs_ltref[i]->is_long_term == 2) {
+		unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
+	} else {
+		if (mark_current)
+			unmark1(p_Dpb, curr_frame_num, i);
+		else
+			unmark2(p_Dpb, curr_pic_num, i);
+	}
+}
+
+static void unmark_long_term_field_for_reference_by_frame_idx(
+	struct DecodedPictureBuffer *p_Dpb, enum PictureStructure structure,
+	int long_term_frame_idx, int mark_current, unsigned int curr_frame_num,
+	int curr_pic_num)
+{
+	struct VideoParameters *p_Vid = p_Dpb->p_Vid;
+	unsigned int i;
+
+	/* assert(structure!=FRAME); */
+	if (curr_pic_num < 0)
+		curr_pic_num += (2 * p_Vid->max_frame_num);
+
+	for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
+		if (p_Dpb->fs_ltref[i]->long_term_frame_idx ==
+			long_term_frame_idx) {
+			if (structure == TOP_FIELD)
+				unmark3_top(p_Dpb, curr_frame_num,
+					curr_pic_num, mark_current, i);
+
+			if (structure == BOTTOM_FIELD)
+				unmark3_bottom(p_Dpb, curr_frame_num,
+					curr_pic_num, mark_current, i);
+		}
+	}
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    mark a picture as long-term reference
+ ************************************************************************
+ */
+static void mark_pic_long_term(struct DecodedPictureBuffer *p_Dpb,
+			       struct StorablePicture *p,
+			       int long_term_frame_idx, int picNumX)
+{
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
+				struct h264_dpb_stru, mDPB);
+	unsigned int i;
+	int add_top, add_bottom;
+
+	if (p->structure == FRAME) {
+		for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+			if (p_Dpb->fs_ref[i] == NULL) {
+				p_H264_Dpb->dpb_error_flag = __LINE__;
+				continue;
+			}
+#endif
+			if (p_Dpb->fs_ref[i]->is_reference == 3) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i]->frame == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if ((!p_Dpb->fs_ref[i]->frame->
+					is_long_term) &&
+				    (p_Dpb->fs_ref[i]->frame->pic_num ==
+					picNumX)) {
+					p_Dpb->fs_ref[i]->
+						long_term_frame_idx =
+					p_Dpb->fs_ref[i]->frame->
+						long_term_frame_idx =
+						long_term_frame_idx;
+					p_Dpb->fs_ref[i]->frame->
+						long_term_pic_num =
+						long_term_frame_idx;
+					p_Dpb->fs_ref[i]->frame->
+						is_long_term = 1;
+
+					if (p_Dpb->fs_ref[i]->top_field &&
+					    p_Dpb->fs_ref[i]->bottom_field) {
+						p_Dpb->fs_ref[i]->top_field->
+						long_term_frame_idx =
+							p_Dpb->fs_ref[i]->
+							bottom_field->
+							long_term_frame_idx =
+							long_term_frame_idx;
+						p_Dpb->fs_ref[i]->top_field->
+							long_term_pic_num =
+							long_term_frame_idx;
+						p_Dpb->fs_ref[i]->
+							bottom_field->
+							long_term_pic_num =
+							long_term_frame_idx;
+
+						p_Dpb->fs_ref[i]->top_field->
+							is_long_term =
+							p_Dpb->fs_ref[i]->
+							bottom_field->
+							is_long_term
+							= 1;
+
+					}
+					p_Dpb->fs_ref[i]->is_long_term = 3;
+					return;
+				}
+			}
+		}
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			  "Warning: reference frame for long term marking not found\n");
+	} else {
+		if (p->structure == TOP_FIELD) {
+			add_top    = 1;
+			add_bottom = 0;
+		} else {
+			add_top    = 0;
+			add_bottom = 1;
+		}
+		for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+			if (p_Dpb->fs_ref[i] == NULL) {
+				p_H264_Dpb->dpb_error_flag = __LINE__;
+				continue;
+			}
+#endif
+			if (p_Dpb->fs_ref[i]->is_reference & 1) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i]->top_field == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if ((!p_Dpb->fs_ref[i]->top_field->
+					is_long_term) &&
+				    (p_Dpb->fs_ref[i]->top_field->pic_num ==
+					picNumX)) {
+					if ((p_Dpb->fs_ref[i]->
+						is_long_term) &&
+					    (p_Dpb->fs_ref[i]->
+						long_term_frame_idx !=
+						long_term_frame_idx)) {
+						dpb_print(p_H264_Dpb->
+						decoder_index,
+						PRINT_FLAG_DPB_DETAIL,
+						"Warning: assigning long_term_frame_idx different from other field\n");
+					}
+
+					p_Dpb->fs_ref[i]->
+						long_term_frame_idx =
+						p_Dpb->fs_ref[i]->top_field->
+						long_term_frame_idx
+						= long_term_frame_idx;
+					p_Dpb->fs_ref[i]->top_field->
+						long_term_pic_num =
+						2 * long_term_frame_idx +
+						add_top;
+					p_Dpb->fs_ref[i]->top_field->
+						is_long_term = 1;
+					p_Dpb->fs_ref[i]->is_long_term |= 1;
+					if ((p_Dpb->fs_ref[i]->is_long_term
+						== 3)
+#ifdef ERROR_CHECK
+						&& p_Dpb->fs_ref[i]->frame
+#endif
+						) {
+						p_Dpb->fs_ref[i]->frame->
+							is_long_term = 1;
+						p_Dpb->fs_ref[i]->frame->
+							long_term_frame_idx =
+							p_Dpb->fs_ref[i]->
+							frame->
+							long_term_pic_num =
+							long_term_frame_idx;
+					}
+					return;
+				}
+			}
+			if (p_Dpb->fs_ref[i]->is_reference & 2) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i]->bottom_field == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if ((!p_Dpb->fs_ref[i]->bottom_field->
+					is_long_term) &&
+				    (p_Dpb->fs_ref[i]->bottom_field->pic_num
+					== picNumX)) {
+					if ((p_Dpb->fs_ref[i]->
+						is_long_term) &&
+					    (p_Dpb->fs_ref[i]->
+						long_term_frame_idx !=
+						long_term_frame_idx)) {
+						dpb_print(p_H264_Dpb->
+						decoder_index,
+						PRINT_FLAG_DPB_DETAIL,
+						"Warning: assigning long_term_frame_idx different from other field\n");
+					}
+
+					p_Dpb->fs_ref[i]->
+						long_term_frame_idx =
+						p_Dpb->fs_ref[i]->bottom_field
+						->long_term_frame_idx
+						= long_term_frame_idx;
+					p_Dpb->fs_ref[i]->bottom_field->
+						long_term_pic_num = 2 *
+						long_term_frame_idx +
+						add_bottom;
+					p_Dpb->fs_ref[i]->bottom_field->
+						is_long_term = 1;
+					p_Dpb->fs_ref[i]->is_long_term |= 2;
+					if ((p_Dpb->fs_ref[i]->
+						is_long_term == 3)
+#ifdef ERROR_CHECK
+						&& p_Dpb->fs_ref[i]->frame
+#endif
+						) {
+						p_Dpb->fs_ref[i]->frame->
+							is_long_term = 1;
+						p_Dpb->fs_ref[i]->frame->
+							long_term_frame_idx =
+							p_Dpb->fs_ref[i]->
+							frame->
+							long_term_pic_num =
+							long_term_frame_idx;
+					}
+					return;
+				}
+			}
+		}
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			  "Warning: reference field for long term marking not found\n");
+	}
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Assign a long term frame index to a short term picture
+ ************************************************************************
+ */
+static void mm_assign_long_term_frame_idx(struct DecodedPictureBuffer *p_Dpb,
+		struct StorablePicture *p, int difference_of_pic_nums_minus1,
+		int long_term_frame_idx)
+{
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
+			struct h264_dpb_stru, mDPB);
+	int picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1);
+
+	/* remove frames/fields with same long_term_frame_idx */
+	if (p->structure == FRAME) {
+		unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb,
+				long_term_frame_idx);
+	} else {
+		unsigned int i;
+		enum PictureStructure structure = FRAME;
+
+		for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+			if (p_Dpb->fs_ref[i] == NULL) {
+				p_H264_Dpb->dpb_error_flag = __LINE__;
+				continue;
+			}
+#endif
+			if (p_Dpb->fs_ref[i]->is_reference & 1) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i]->top_field == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if (p_Dpb->fs_ref[i]->top_field->
+					pic_num == picNumX) {
+					structure = TOP_FIELD;
+					break;
+				}
+			}
+			if (p_Dpb->fs_ref[i]->is_reference & 2) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i]->bottom_field == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if (p_Dpb->fs_ref[i]->bottom_field->
+					pic_num == picNumX) {
+					structure = BOTTOM_FIELD;
+					break;
+				}
+			}
+		}
+		if (structure == FRAME) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				  PRINT_FLAG_DPB_DETAIL,
+				  "field for long term marking not found %d",
+				  200);
+		}
+
+		unmark_long_term_field_for_reference_by_frame_idx(p_Dpb,
+				structure,
+				long_term_frame_idx, 0, 0, picNumX);
+	}
+
+	mark_pic_long_term(p_Dpb, p, long_term_frame_idx, picNumX);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Set new max long_term_frame_idx
+ ************************************************************************
+ */
+static void mm_update_max_long_term_frame_idx(struct DecodedPictureBuffer
+		*p_Dpb, int max_long_term_frame_idx_plus1)
+{
+	unsigned int i;
+
+	p_Dpb->max_long_term_pic_idx = max_long_term_frame_idx_plus1 - 1;
+
+	/* check for invalid frames */
+	for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
+		if (p_Dpb->fs_ltref[i]->long_term_frame_idx >
+			p_Dpb->max_long_term_pic_idx) {
+			unmark_for_long_term_reference(p_Dpb->fs_ltref[i]);
+		}
+	}
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Mark all long term reference pictures unused for reference
+ ************************************************************************
+ */
+static void mm_unmark_all_long_term_for_reference(struct DecodedPictureBuffer
+		*p_Dpb)
+{
+	mm_update_max_long_term_frame_idx(p_Dpb, 0);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Mark all short term reference pictures unused for reference
+ ************************************************************************
+ */
+static void mm_unmark_all_short_term_for_reference(struct DecodedPictureBuffer
+		*p_Dpb)
+{
+	unsigned int i;
+
+	for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++)
+		unmark_for_reference(p_Dpb, p_Dpb->fs_ref[i]);
+	update_ref_list(p_Dpb);
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Mark the current picture used for long term reference
+ ************************************************************************
+ */
+static void mm_mark_current_picture_long_term(struct DecodedPictureBuffer
+		*p_Dpb, struct StorablePicture *p, int long_term_frame_idx)
+{
+	/* remove long term pictures with same long_term_frame_idx */
+	if (p->structure == FRAME) {
+		unmark_long_term_frame_for_reference_by_frame_idx(p_Dpb,
+				long_term_frame_idx);
+	} else {
+		unmark_long_term_field_for_reference_by_frame_idx(p_Dpb,
+				p->structure, long_term_frame_idx,
+				1, p->pic_num, 0);
+	}
+
+	p->is_long_term = 1;
+	p->long_term_frame_idx = long_term_frame_idx;
+}
+
+static void adaptive_memory_management(struct h264_dpb_stru *p_H264_Dpb,
+				       struct StorablePicture *p)
+{
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+	struct DecRefPicMarking_s *tmp_drpm;
+	struct VideoParameters *p_Vid = p_Dpb->p_Vid;
+
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+				"%s\n", __func__);
+	p_Vid->last_has_mmco_5 = 0;
+
+	/* assert (!p->idr_flag); */
+	/* assert (p->adaptive_ref_pic_buffering_flag); */
+
+	while (p->dec_ref_pic_marking_buffer) {
+		tmp_drpm = p->dec_ref_pic_marking_buffer;
+		switch (tmp_drpm->memory_management_control_operation) {
+		case 0:
+			if (tmp_drpm->Next != NULL)
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_ERROR,
+					"error, memory_management_control_operation = 0 not last operation in buffer\n");
+			break;
+		case 1:
+			mm_unmark_short_term_for_reference(p_Dpb, p,
+				tmp_drpm->difference_of_pic_nums_minus1);
+			update_ref_list(p_Dpb);
+			break;
+		case 2:
+			mm_unmark_long_term_for_reference(p_Dpb, p,
+				tmp_drpm->long_term_pic_num);
+			update_ltref_list(p_Dpb);
+			break;
+		case 3:
+			mm_assign_long_term_frame_idx(p_Dpb, p,
+				tmp_drpm->difference_of_pic_nums_minus1,
+				tmp_drpm->long_term_frame_idx);
+			update_ref_list(p_Dpb);
+			update_ltref_list(p_Dpb);
+			break;
+		case 4:
+			mm_update_max_long_term_frame_idx(p_Dpb,
+				tmp_drpm->max_long_term_frame_idx_plus1);
+			update_ltref_list(p_Dpb);
+			break;
+		case 5:
+			mm_unmark_all_short_term_for_reference(p_Dpb);
+			mm_unmark_all_long_term_for_reference(p_Dpb);
+			p_Vid->last_has_mmco_5 = 1;
+			break;
+		case 6:
+			mm_mark_current_picture_long_term(p_Dpb, p,
+				tmp_drpm->long_term_frame_idx);
+			check_num_ref(p_Dpb);
+			break;
+		default:
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_ERROR,
+				"error, invalid memory_management_control_operation in buffer\n");
+		}
+		p->dec_ref_pic_marking_buffer = tmp_drpm->Next;
+		/* free (tmp_drpm); */
+	}
+	if (p_Vid->last_has_mmco_5) {
+		p->pic_num = p->frame_num = 0;
+
+		switch (p->structure) {
+		case TOP_FIELD: {
+			/* p->poc = p->top_poc = p_Vid->toppoc =0; */
+			p->poc = p->top_poc = 0;
+			break;
+		}
+		case BOTTOM_FIELD: {
+			/* p->poc = p->bottom_poc = p_Vid->bottompoc = 0; */
+			p->poc = p->bottom_poc = 0;
+			break;
+		}
+		case FRAME: {
+			p->top_poc    -= p->poc;
+			p->bottom_poc -= p->poc;
+
+			/* p_Vid->toppoc = p->top_poc; */
+			/* p_Vid->bottompoc = p->bottom_poc; */
+
+			p->poc = imin(p->top_poc, p->bottom_poc);
+			/* p_Vid->framepoc = p->poc; */
+			break;
+		}
+		}
+		/* currSlice->ThisPOC = p->poc; */
+#if (MVC_EXTENSION_ENABLE)
+		if (p->view_id == 0) {
+			flush_dpb(p_Vid->p_Dpb_layer[0]);
+			flush_dpb(p_Vid->p_Dpb_layer[1]);
+		} else {
+			flush_dpb(p_Dpb);
+		}
+#else
+		flush_dpb(p_H264_Dpb);
+#endif
+	}
+}
+
+
+int store_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb,
+			  struct StorablePicture *p,
+			  unsigned char data_flag)
+{
+	/* struct VideoParameters *p_Vid = p_Dpb->p_Vid; */
+	struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo;
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+	unsigned int i, frame_outside_count = 0;
+#if 0
+	int poc, pos;
+#endif
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s p_Vid %p\n", __func__, p_Vid);
+
+	/* picture error concealment */
+
+	/* diagnostics */
+	/* dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+	 *	"Storing (%s) non-ref pic with frame_num #%d\n",
+	 *	(p->type == FRAME)?"FRAME":(p->type == TOP_FIELD)?
+	 *	"TOP_FIELD":"BOTTOM_FIELD", p->pic_num);
+	 */
+	/* if frame, check for new store, */
+	/* assert (p!=NULL); */
+
+	p_Vid->last_has_mmco_5 = 0;
+	p_Vid->last_pic_bottom_field = (p->structure == BOTTOM_FIELD);
+	if (p->idr_flag) {
+		idr_memory_management(p_H264_Dpb, p);
+		if (p_H264_Dpb->first_insert_frame == FirstInsertFrm_OUT)
+			p_H264_Dpb->first_insert_frame = FirstInsertFrm_SKIPDONE;
+#if 0
+/* ??? */
+		/* picture error concealment */
+		memset(p_Vid->pocs_in_dpb, 0, sizeof(int) * 100);
+#endif
+	} else {
+#if 1
+/* ??? */
+		/* adaptive memory management */
+		if (p->used_for_reference &&
+			(p->adaptive_ref_pic_buffering_flag))
+			adaptive_memory_management(p_H264_Dpb, p);
+#endif
+	}
+
+	if ((p->structure == TOP_FIELD) || (p->structure == BOTTOM_FIELD)) {
+		/* check for frame store with same pic_number */
+		if (p_Dpb->last_picture) {
+			if ((int)p_Dpb->last_picture->frame_num ==
+				p->pic_num) {
+				if (((p->structure == TOP_FIELD) &&
+				    (p_Dpb->last_picture->is_used == 2)) ||
+				    ((p->structure == BOTTOM_FIELD) &&
+				    (p_Dpb->last_picture->is_used == 1))) {
+					if ((p->used_for_reference &&
+					    (p_Dpb->last_picture->
+						is_orig_reference != 0)) ||
+					    (!p->used_for_reference &&
+						(p_Dpb->last_picture->
+						is_orig_reference == 0))) {
+						insert_picture_in_dpb(
+							p_H264_Dpb,
+							p_Dpb->last_picture,
+							p, data_flag);
+						update_ref_list(p_Dpb);
+						update_ltref_list(p_Dpb);
+						dump_dpb(p_Dpb, 0);
+						p_Dpb->last_picture = NULL;
+						return 0;
+					}
+				}
+			}
+		}
+	}
+	/* this is a frame or a field which has no stored
+	 * complementary field
+	 */
+
+	/* sliding window, if necessary */
+	if ((!p->idr_flag) && (p->used_for_reference &&
+			       (!p->adaptive_ref_pic_buffering_flag))) {
+		sliding_window_memory_management(p_Dpb, p);
+	}
+
+	/* picture error concealment */
+	if (p_Vid->conceal_mode != 0) {
+		for (i = 0; i < p_Dpb->size; i++)
+			if (p_Dpb->fs[i]->is_reference)
+				p_Dpb->fs[i]->concealment_reference = 1;
+	}
+
+	while (remove_unused_frame_from_dpb(p_H264_Dpb))
+		;
+
+	while (output_frames(p_H264_Dpb, 0))
+		;
+
+	/* check for duplicate frame number in short term reference buffer */
+	if ((p->used_for_reference) && (!p->is_long_term)) {
+		for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+			if (p_Dpb->fs_ref[i] == NULL)
+				continue;
+#endif
+			if (p_Dpb->fs_ref[i]->frame_num == p->frame_num) {
+				dpb_print(p_H264_Dpb->decoder_index,
+					  PRINT_FLAG_DPB_DETAIL,
+					  "duplicate frame_num in short-term reference picture buffer %d\n",
+					   500);
+				if (p_Dpb->fs_ref[i]->dpb_frame_count == p_H264_Dpb->dpb_frame_count) {
+					dpb_print(p_H264_Dpb->decoder_index,
+							  0, "duplicate frame, no insert to dpb\n");
+					return -2;
+				} else {
+					dpb_print(p_H264_Dpb->decoder_index,
+						  0, "duplicate frame_num release defore ref\n");
+					unmark_for_reference(p_Dpb, p_Dpb->fs_ref[i]);
+					update_ref_list(p_Dpb);
+				}
+			}
+		}
+	}
+	/* store at end of buffer */
+
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		  "%s p_Dpb->used_size %d\n", __func__, p_Dpb->used_size);
+	if (p_Dpb->used_size >= p_Dpb->size) {
+		dpb_print(p_H264_Dpb->decoder_index,
+			PRINT_FLAG_ERROR,
+			"%s Error: used_sizd %d is large than dpb size\r\n",
+			__func__, p_Dpb->used_size);
+		/*h264_debug_flag |= PRINT_FLAG_DUMP_DPB;*/
+		dump_dpb(p_Dpb, 0);
+		return -1;
+	}
+
+	insert_picture_in_dpb(p_H264_Dpb, p_Dpb->fs[p_Dpb->used_size],
+		p, data_flag);
+
+	/* picture error concealment */
+	if (p->idr_flag)
+		p_Vid->earlier_missing_poc = 0;
+
+	if (p->structure != FRAME)
+		p_Dpb->last_picture = p_Dpb->fs[p_Dpb->used_size];
+	else
+		p_Dpb->last_picture = NULL;
+
+	p_Dpb->used_size++;
+#if 0
+/* ??? */
+	if (p_Vid->conceal_mode != 0)
+		p_Vid->pocs_in_dpb[p_Dpb->used_size - 1] = p->poc;
+#endif
+	update_ref_list(p_Dpb);
+	update_ltref_list(p_Dpb);
+
+	check_num_ref(p_Dpb);
+	for (i = 0; i < p_Dpb->used_size; i++) {
+		if (p_Dpb->fs[i]->pre_output)
+			frame_outside_count++;
+	}
+
+	if (p_H264_Dpb->fast_output_enable == H264_OUTPUT_MODE_FAST)
+		i = 1;
+	else
+		i = 0;
+
+	if (i || (p_H264_Dpb->first_insert_frame < FirstInsertFrm_SKIPDONE)) {
+		while (output_frames(p_H264_Dpb, i))
+			;
+	}
+
+	dump_dpb(p_Dpb, 0);
+	p_Dpb->first_pic_done = 1; /*by rain*/
+
+	return 0;
+}
+
+void bufmgr_post(struct h264_dpb_stru *p_H264_Dpb)
+{
+	/*VideoParameters *p_Vid = p_Dpb->p_Vid;*/
+	struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo;
+
+	if (p_Vid->last_has_mmco_5)
+		p_Vid->pre_frame_num = 0;
+}
+/**********************************
+ *
+ *   Initialize reference lists
+ **********************************
+ */
+#define __COMPARE(context, p1, p2) comp(p1, p2)
+#define __SHORTSORT(lo, hi, width, comp, context) \
+	shortsort(lo, hi, width, comp)
+#define CUTOFF 8            /* testing shows that this is good value */
+#define STKSIZ (8*sizeof(void *) - 2)
+
+#undef swap
+static void swap(
+	char *a,
+	char *b,
+	size_t width
+)
+{
+	char tmp;
+
+	if (a != b)
+		/* Do the swap one character at a time to avoid potential
+		 *   alignment problems.
+		 */
+		while (width--) {
+			tmp = *a;
+			*a++ = *b;
+			*b++ = tmp;
+		}
+}
+
+static void shortsort(
+	char *lo,
+	char *hi,
+	size_t width,
+	int (*comp)(const void *, const void *)
+)
+{
+	char *p, *max;
+
+	/* Note: in assertions below, i and j are alway inside original
+	 *   bound of array to sort.
+	 */
+
+	while (hi > lo) {
+		/* A[i] <= A[j] for i <= j, j > hi */
+		max = lo;
+		for (p = lo + width; p <= hi; p += width) {
+			/* A[i] <= A[max] for lo <= i < p */
+			if (__COMPARE(context, p, max) > 0)
+				max = p;
+			/* A[i] <= A[max] for lo <= i <= p */
+		}
+
+		/* A[i] <= A[max] for lo <= i <= hi */
+
+		swap(max, hi, width);
+
+		/* A[i] <= A[hi] for i <= hi, so A[i] <= A[j] for i <= j,
+		 *   j >= hi
+		 */
+
+		hi -= width;
+
+		/* A[i] <= A[j] for i <= j, j > hi, loop top condition
+		 *   established
+		 */
+	}
+	/* A[i] <= A[j] for i <= j, j > lo, which implies A[i] <= A[j]
+	 *   for i < j, so array is sorted
+	 */
+}
+
+static void qsort(
+	void *base,
+	size_t num,
+	size_t width,
+	int (*comp)(const void *, const void *)
+)
+{
+	char *lo, *hi;              /* ends of sub-array currently sorting */
+	char *mid;                  /* points to middle of subarray */
+	char *loguy, *higuy;        /* traveling pointers for partition step */
+	size_t size;                /* size of the sub-array */
+	char *lostk[STKSIZ], *histk[STKSIZ];
+	int stkptr;
+
+/*  stack for saving sub-array to be
+ *					processed
+ */
+#if 0
+	/* validation section */
+	_VALIDATE_RETURN_VOID(base != NULL || num == 0, EINVAL);
+	_VALIDATE_RETURN_VOID(width > 0, EINVAL);
+	_VALIDATE_RETURN_VOID(comp != NULL, EINVAL);
+#endif
+	if (num < 2)
+		return;                 /* nothing to do */
+
+	stkptr = 0;                 /* initialize stack */
+
+	lo = (char *)base;
+	hi = (char *)base + width * (num - 1);      /* initialize limits */
+
+	/* this entry point is for pseudo-recursion calling: setting
+	 * lo and hi and jumping to here is like recursion, but stkptr is
+	 * preserved, locals aren't, so we preserve stuff on the stack
+	 */
+recurse:
+
+	size = (hi - lo) / width + 1;        /* number of el's to sort */
+
+	/* below a certain size, it is faster to use a O(n^2) sorting method */
+	if (size <= CUTOFF) {
+		__SHORTSORT(lo, hi, width, comp, context);
+	} else {
+		/* First we pick a partitioning element.  The efficiency of
+		 * the algorithm demands that we find one that is approximately
+		 * the median of the values, but also that we select one fast.
+		 * We choose the median of the first, middle, and last
+		 * elements, to avoid bad performance in the face of already
+		 * sorted data, or data that is made up of multiple sorted
+		 * runs appended together.  Testing shows that a
+		 * median-of-three algorithm provides better performance than
+		 * simply picking the middle element for the latter case.
+		 */
+
+		mid = lo + (size / 2) * width;      /* find middle element */
+
+		/* Sort the first, middle, last elements into order */
+		if (__COMPARE(context, lo, mid) > 0)
+			swap(lo, mid, width);
+		if (__COMPARE(context, lo, hi) > 0)
+			swap(lo, hi, width);
+		if (__COMPARE(context, mid, hi) > 0)
+			swap(mid, hi, width);
+
+		/* We now wish to partition the array into three pieces, one
+		 * consisting of elements <= partition element, one of elements
+		 * equal to the partition element, and one of elements > than
+		 * it. This is done below; comments indicate conditions
+		 * established at every step.
+		 */
+
+		loguy = lo;
+		higuy = hi;
+
+		/* Note that higuy decreases and loguy increases on every
+		 *   iteration, so loop must terminate.
+		 */
+		for (;;) {
+			/* lo <= loguy < hi, lo < higuy <= hi,
+			 *   A[i] <= A[mid] for lo <= i <= loguy,
+			 *   A[i] > A[mid] for higuy <= i < hi,
+			 *   A[hi] >= A[mid]
+			 */
+
+			/* The doubled loop is to avoid calling comp(mid,mid),
+			 *   since some existing comparison funcs don't work
+			 *   when passed the same value for both pointers.
+			 */
+
+			if (mid > loguy) {
+				do  {
+					loguy += width;
+				} while (loguy < mid &&
+					__COMPARE(context, loguy, mid) <= 0);
+			}
+			if (mid <= loguy) {
+				do  {
+					loguy += width;
+				} while (loguy <= hi &&
+					__COMPARE(context, loguy, mid) <= 0);
+			}
+
+			/* lo < loguy <= hi+1, A[i] <= A[mid] for
+			 *   lo <= i < loguy,
+			 *   either loguy > hi or A[loguy] > A[mid]
+			 */
+
+			do  {
+				higuy -= width;
+			} while (higuy > mid &&
+					__COMPARE(context, higuy, mid) > 0);
+
+			/* lo <= higuy < hi, A[i] > A[mid] for higuy < i < hi,
+			 *   either higuy == lo or A[higuy] <= A[mid]
+			 */
+
+			if (higuy < loguy)
+				break;
+
+			/* if loguy > hi or higuy == lo, then we would have
+			 *   exited, so A[loguy] > A[mid], A[higuy] <= A[mid],
+			 *   loguy <= hi, higuy > lo
+			 */
+
+			swap(loguy, higuy, width);
+
+			/* If the partition element was moved, follow it.
+			 *   Only need to check for mid == higuy, since before
+			 *   the swap, A[loguy] > A[mid] implies loguy != mid.
+			 */
+
+			if (mid == higuy)
+				mid = loguy;
+
+			/* A[loguy] <= A[mid], A[higuy] > A[mid]; so condition
+			 *   at top of loop is re-established
+			 */
+		}
+
+		/*     A[i] <= A[mid] for lo <= i < loguy,
+		 *       A[i] > A[mid] for higuy < i < hi,
+		 *       A[hi] >= A[mid]
+		 *       higuy < loguy
+		 *   implying:
+		 *       higuy == loguy-1
+		 *       or higuy == hi - 1, loguy == hi + 1, A[hi] == A[mid]
+		 */
+
+		/* Find adjacent elements equal to the partition element.  The
+		 *   doubled loop is to avoid calling comp(mid,mid), since some
+		 *   existing comparison funcs don't work when passed the same
+		 *   value for both pointers.
+		 */
+
+		higuy += width;
+		if (mid < higuy) {
+			do  {
+				higuy -= width;
+			} while (higuy > mid &&
+				__COMPARE(context, higuy, mid) == 0);
+		}
+		if (mid >= higuy) {
+			do  {
+				higuy -= width;
+			} while (higuy > lo &&
+				__COMPARE(context, higuy, mid) == 0);
+		}
+
+		/* OK, now we have the following:
+		 *      higuy < loguy
+		 *      lo <= higuy <= hi
+		 *      A[i]  <= A[mid] for lo <= i <= higuy
+		 *      A[i]  == A[mid] for higuy < i < loguy
+		 *      A[i]  >  A[mid] for loguy <= i < hi
+		 *      A[hi] >= A[mid]
+		 */
+
+		/* We've finished the partition, now we want to sort the
+		 *   subarrays [lo, higuy] and [loguy, hi].
+		 *   We do the smaller one first to minimize stack usage.
+		 *   We only sort arrays of length 2 or more.
+		 */
+
+		if (higuy - lo >= hi - loguy) {
+			if (lo < higuy) {
+				lostk[stkptr] = lo;
+				histk[stkptr] = higuy;
+				++stkptr;
+			}                    /* save big recursion for later */
+
+			if (loguy < hi) {
+				lo = loguy;
+				goto recurse;          /* do small recursion */
+			}
+		} else {
+			if (loguy < hi) {
+				lostk[stkptr] = loguy;
+				histk[stkptr] = hi;
+				++stkptr;    /* save big recursion for later */
+			}
+
+			if (lo < higuy) {
+				hi = higuy;
+				goto recurse;          /* do small recursion */
+			}
+		}
+	}
+
+	/* We have sorted the array, except for any pending sorts on the stack.
+	 *   Check if there are any, and do them.
+	 */
+
+	--stkptr;
+	if (stkptr >= 0) {
+		lo = lostk[stkptr];
+		hi = histk[stkptr];
+		goto recurse;           /* pop subarray from stack */
+	} else
+		return;                 /* all subarrays done */
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    compares two stored pictures by picture number for qsort in
+ *    descending order
+ *
+ ************************************************************************
+ */
+static inline int compare_pic_by_pic_num_desc(const void *arg1,
+		const void *arg2)
+{
+	int pic_num1 = (*(struct StorablePicture **)arg1)->pic_num;
+	int pic_num2 = (*(struct StorablePicture **)arg2)->pic_num;
+
+	if (pic_num1 < pic_num2)
+		return 1;
+	if (pic_num1 > pic_num2)
+		return -1;
+	else
+		return 0;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    compares two stored pictures by picture number for qsort in
+ *    descending order
+ *
+ ************************************************************************
+ */
+static inline int compare_pic_by_lt_pic_num_asc(const void *arg1,
+		const void *arg2)
+{
+	int long_term_pic_num1 =
+		(*(struct StorablePicture **)arg1)->long_term_pic_num;
+	int long_term_pic_num2 =
+		(*(struct StorablePicture **)arg2)->long_term_pic_num;
+
+	if (long_term_pic_num1 < long_term_pic_num2)
+		return -1;
+	if (long_term_pic_num1 > long_term_pic_num2)
+		return 1;
+	else
+		return 0;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    compares two frame stores by pic_num for qsort in descending order
+ *
+ ************************************************************************
+ */
+static inline int compare_fs_by_frame_num_desc(const void *arg1,
+		const void *arg2)
+{
+	int frame_num_wrap1 = (*(struct FrameStore **)arg1)->frame_num_wrap;
+	int frame_num_wrap2 = (*(struct FrameStore **)arg2)->frame_num_wrap;
+
+	if (frame_num_wrap1 < frame_num_wrap2)
+		return 1;
+	if (frame_num_wrap1 > frame_num_wrap2)
+		return -1;
+	else
+		return 0;
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    compares two frame stores by lt_pic_num for qsort in descending order
+ *
+ ************************************************************************
+ */
+static inline int compare_fs_by_lt_pic_idx_asc(const void *arg1,
+		const void *arg2)
+{
+	int long_term_frame_idx1 =
+		(*(struct FrameStore **)arg1)->long_term_frame_idx;
+	int long_term_frame_idx2 =
+		(*(struct FrameStore **)arg2)->long_term_frame_idx;
+
+	if (long_term_frame_idx1 < long_term_frame_idx2)
+		return -1;
+	else if (long_term_frame_idx1 > long_term_frame_idx2)
+		return 1;
+	else
+		return 0;
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    compares two stored pictures by poc for qsort in ascending order
+ *
+ ************************************************************************
+ */
+static inline int compare_pic_by_poc_asc(const void *arg1, const void *arg2)
+{
+	int poc1 = (*(struct StorablePicture **)arg1)->poc;
+	int poc2 = (*(struct StorablePicture **)arg2)->poc;
+
+	if (poc1 < poc2)
+		return -1;
+	else if (poc1 > poc2)
+		return 1;
+	else
+		return 0;
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    compares two stored pictures by poc for qsort in descending order
+ *
+ ************************************************************************
+ */
+static inline int compare_pic_by_poc_desc(const void *arg1, const void *arg2)
+{
+	int poc1 = (*(struct StorablePicture **)arg1)->poc;
+	int poc2 = (*(struct StorablePicture **)arg2)->poc;
+
+	if (poc1 < poc2)
+		return 1;
+	else if (poc1 > poc2)
+		return -1;
+	else
+		return 0;
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    compares two frame stores by poc for qsort in ascending order
+ *
+ ************************************************************************
+ */
+static inline int compare_fs_by_poc_asc(const void *arg1, const void *arg2)
+{
+	int poc1 = (*(struct FrameStore **)arg1)->poc;
+	int poc2 = (*(struct FrameStore **)arg2)->poc;
+
+	if (poc1 < poc2)
+		return -1;
+	else if (poc1 > poc2)
+		return 1;
+	else
+		return 0;
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    compares two frame stores by poc for qsort in descending order
+ *
+ ************************************************************************
+ */
+static inline int compare_fs_by_poc_desc(const void *arg1, const void *arg2)
+{
+	int poc1 = (*(struct FrameStore **)arg1)->poc;
+	int poc2 = (*(struct FrameStore **)arg2)->poc;
+
+	if (poc1 < poc2)
+		return 1;
+	else if (poc1 > poc2)
+		return -1;
+	else
+		return 0;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    returns true, if picture is short term reference picture
+ *
+ ************************************************************************
+ */
+static inline int is_short_ref(struct StorablePicture *s)
+{
+#ifdef ERROR_CHECK
+	return (s &&
+		(s->used_for_reference) && (!(s->is_long_term)));
+#else
+	return (s->used_for_reference) && (!(s->is_long_term));
+#endif
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    returns true, if picture is long term reference picture
+ *
+ ************************************************************************
+ */
+static inline int is_long_ref(struct StorablePicture *s)
+{
+#ifdef ERROR_CHECK
+	return (s &&
+		s->used_for_reference) && (s->is_long_term);
+#else
+	return (s->used_for_reference) && (s->is_long_term);
+#endif
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Initialize reference lists for a P Slice
+ *
+ ************************************************************************
+ */
+/*!
+ ************************************************************************
+ * \brief
+ *    Generates a alternating field list from a given FrameStore list
+ *
+ ************************************************************************
+ */
+static void gen_pic_list_from_frame_list(enum PictureStructure currStructure,
+		struct FrameStore **fs_list, int list_idx,
+		struct StorablePicture **list,
+		char *list_size, int long_term)
+{
+	int top_idx = 0;
+	int bot_idx = 0;
+
+	int (*is_ref)(struct StorablePicture *s) = (long_term) ? is_long_ref :
+			is_short_ref;
+
+
+	if (currStructure == TOP_FIELD) {
+		while ((top_idx < list_idx) || (bot_idx < list_idx)) {
+			for (; top_idx < list_idx; top_idx++) {
+				if (fs_list[top_idx]->is_used & 1) {
+					if (is_ref(fs_list[top_idx]->
+						top_field)) {
+						/* short term ref pic */
+						list[(short) *list_size] =
+						fs_list[top_idx]->top_field;
+						(*list_size)++;
+						top_idx++;
+						break;
+					}
+				}
+			}
+			for (; bot_idx < list_idx; bot_idx++) {
+				if (fs_list[bot_idx]->is_used & 2) {
+					if (is_ref(fs_list[bot_idx]->
+						bottom_field)) {
+						/* short term ref pic */
+						list[(short) *list_size] =
+						fs_list[bot_idx]->bottom_field;
+						(*list_size)++;
+						bot_idx++;
+						break;
+					}
+				}
+			}
+		}
+	}
+	if (currStructure == BOTTOM_FIELD) {
+		while ((top_idx < list_idx) || (bot_idx < list_idx)) {
+			for (; bot_idx < list_idx; bot_idx++) {
+				if (fs_list[bot_idx]->is_used & 2) {
+					if (is_ref(fs_list[bot_idx]->
+						bottom_field)) {
+						/* short term ref pic */
+						list[(short) *list_size] =
+						fs_list[bot_idx]->bottom_field;
+						(*list_size)++;
+						bot_idx++;
+						break;
+					}
+				}
+			}
+			for (; top_idx < list_idx; top_idx++) {
+				if (fs_list[top_idx]->is_used & 1) {
+					if (is_ref(fs_list[top_idx]->
+						top_field)) {
+						/* short term ref pic */
+						list[(short) *list_size] =
+						fs_list[top_idx]->top_field;
+						(*list_size)++;
+						top_idx++;
+						break;
+					}
+				}
+			}
+		}
+	}
+}
+
+static void init_lists_p_slice(struct Slice *currSlice)
+{
+	struct VideoParameters *p_Vid = currSlice->p_Vid;
+	struct DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb;
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
+				struct h264_dpb_stru, mDPB);
+
+	unsigned int i;
+
+	int list0idx = 0;
+	int listltidx = 0;
+
+	struct FrameStore **fs_list0;
+	struct FrameStore **fs_listlt;
+
+#if (MVC_EXTENSION_ENABLE)
+	currSlice->listinterviewidx0 = 0;
+	currSlice->listinterviewidx1 = 0;
+#endif
+
+	if (currSlice->structure == FRAME) {
+		for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+			if (p_Dpb->fs_ref[i] == NULL ||
+				p_Dpb->fs_ref[i]->frame == NULL) {
+				p_H264_Dpb->dpb_error_flag = __LINE__;
+				continue;
+			}
+#endif
+			if (p_Dpb->fs_ref[i]->is_used == 3) {
+				if ((p_Dpb->fs_ref[i]->frame->
+					used_for_reference) &&
+				    (!p_Dpb->fs_ref[i]->frame->
+					is_long_term)) {
+					currSlice->listX[0][list0idx++] =
+					p_Dpb->fs_ref[i]->frame;
+				}
+			}
+		}
+		/* order list 0 by PicNum */
+		qsort((void *)currSlice->listX[0], list0idx,
+			sizeof(struct StorablePicture *),
+			compare_pic_by_pic_num_desc);
+		currSlice->listXsize[0] = (char) list0idx;
+		CHECK_VALID(currSlice->listXsize[0], 0);
+		if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+				  "listX[0] (PicNum): ");
+			for (i = 0; i < list0idx; i++) {
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL, "%d  ",
+					currSlice->listX[0][i]->pic_num);
+			}
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "\n");
+		}
+		/* long term handling */
+		for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
+			if (p_Dpb->fs_ltref[i]->is_used == 3) {
+				if (p_Dpb->fs_ltref[i]->frame->is_long_term) {
+					currSlice->listX[0][list0idx++] =
+						p_Dpb->fs_ltref[i]->frame;
+				}
+			}
+		}
+		qsort((void *)&currSlice->listX[0][
+			(short) currSlice->listXsize[0]],
+			list0idx - currSlice->listXsize[0],
+			sizeof(struct StorablePicture *),
+			compare_pic_by_lt_pic_num_asc);
+		currSlice->listXsize[0] = (char) list0idx;
+		CHECK_VALID(currSlice->listXsize[0], 0);
+	} else {
+#if 0
+		fs_list0 = calloc(p_Dpb->size, sizeof(struct FrameStore *));
+		if (fs_list0 == NULL)
+			no_mem_exit("init_lists: fs_list0");
+		fs_listlt = calloc(p_Dpb->size, sizeof(struct FrameStore *));
+		if (fs_listlt == NULL)
+			no_mem_exit("init_lists: fs_listlt");
+#else
+		fs_list0 = &(p_Dpb->fs_list0[0]);
+		fs_listlt = &(p_Dpb->fs_listlt[0]);
+#endif
+		for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+			if (p_Dpb->fs_ref[i] == NULL) {
+				p_H264_Dpb->dpb_error_flag = __LINE__;
+				continue;
+			}
+#endif
+			if (p_Dpb->fs_ref[i]->is_reference)
+				fs_list0[list0idx++] = p_Dpb->fs_ref[i];
+		}
+
+		qsort((void *)fs_list0, list0idx, sizeof(struct FrameStore *),
+		      compare_fs_by_frame_num_desc);
+
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			  "fs_list0 (FrameNum): ");
+		for (i = 0; i < list0idx; i++) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				  PRINT_FLAG_DPB_DETAIL, "%d  ",
+				  fs_list0[i]->frame_num_wrap);
+		}
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			  "\n");
+
+		currSlice->listXsize[0] = 0;
+		gen_pic_list_from_frame_list(currSlice->structure, fs_list0,
+						list0idx, currSlice->listX[0],
+						&currSlice->listXsize[0], 0);
+
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			  "listX[0] (PicNum): ");
+		for (i = 0; i < currSlice->listXsize[0]; i++) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "%d  ",
+				currSlice->listX[0][i]->pic_num);
+		}
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			  "\n");
+
+		/* long term handling */
+		for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++)
+			fs_listlt[listltidx++] = p_Dpb->fs_ltref[i];
+
+		qsort((void *)fs_listlt, listltidx, sizeof(struct FrameStore *),
+		      compare_fs_by_lt_pic_idx_asc);
+
+		gen_pic_list_from_frame_list(currSlice->structure, fs_listlt,
+					listltidx, currSlice->listX[0],
+					&currSlice->listXsize[0], 1);
+
+		/* free(fs_list0); */
+		/* free(fs_listlt); */
+	}
+	currSlice->listXsize[1] = 0;
+
+
+	/* set max size */
+	currSlice->listXsize[0] = (char) imin(currSlice->listXsize[0],
+			currSlice->num_ref_idx_active[LIST_0]);
+	currSlice->listXsize[1] = (char) imin(currSlice->listXsize[1],
+			currSlice->num_ref_idx_active[LIST_1]);
+	CHECK_VALID(currSlice->listXsize[0], 0);
+	CHECK_VALID(currSlice->listXsize[1], 1);
+
+	/* set the unused list entries to NULL */
+	for (i = currSlice->listXsize[0]; i < (MAX_LIST_SIZE); i++)
+		currSlice->listX[0][i] = p_Vid->no_reference_picture;
+	for (i = currSlice->listXsize[1]; i < (MAX_LIST_SIZE); i++)
+		currSlice->listX[1][i] = p_Vid->no_reference_picture;
+
+#if PRINTREFLIST
+#if (MVC_EXTENSION_ENABLE)
+	/* print out for h264_debug_flag purpose */
+	if ((p_Vid->profile_idc == MVC_HIGH ||
+		p_Vid->profile_idc == STEREO_HIGH) &&
+	    currSlice->current_slice_nr == 0) {
+		if (currSlice->listXsize[0] > 0) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "\n");
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+				  " ** (CurViewID:%d %d) %s Ref Pic List 0 ****\n",
+				currSlice->view_id,
+				currSlice->ThisPOC,
+				currSlice->structure == FRAME ? "FRM" :
+				  (currSlice->structure == TOP_FIELD ?
+					"TOP" : "BOT"));
+			for (i = 0; i < (unsigned int)(currSlice->
+				listXsize[0]); i++) { /* ref list 0 */
+				dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+				"   %2d -> POC: %4d PicNum: %4d ViewID: %d\n",
+				i,
+				currSlice->listX[0][i]->poc,
+				currSlice->listX[0][i]->pic_num,
+				currSlice->listX[0][i]->view_id);
+			}
+		}
+	}
+#endif
+#endif
+}
+
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Initialize reference lists
+ *
+ ************************************************************************
+ */
+static void init_mbaff_lists(struct h264_dpb_stru *p_H264_Dpb,
+			     struct Slice *currSlice)
+{
+	unsigned int j;
+	int i;
+	struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo;
+	for (i = 2; i < 6; i++) {
+		for (j = 0; j < MAX_LIST_SIZE; j++)
+			currSlice->listX[i][j] = p_Vid->no_reference_picture;
+		currSlice->listXsize[i] = 0;
+	}
+
+	for (i = 0; i < currSlice->listXsize[0]; i++) {
+#ifdef ERROR_CHECK
+		if (currSlice->listX[0][i] == NULL) {
+			p_H264_Dpb->dpb_error_flag = __LINE__;
+			pr_info(
+			"error currSlice->listX[0][%d] is NULL\r\n", i);
+			break;
+		}
+#endif
+		currSlice->listX[2][2 * i] =
+			currSlice->listX[0][i]->top_field;
+		currSlice->listX[2][2 * i + 1] =
+			currSlice->listX[0][i]->bottom_field;
+		currSlice->listX[4][2 * i] =
+			currSlice->listX[0][i]->bottom_field;
+		currSlice->listX[4][2 * i + 1] =
+			currSlice->listX[0][i]->top_field;
+	}
+	currSlice->listXsize[2] = currSlice->listXsize[4] =
+		currSlice->listXsize[0] * 2;
+
+	for (i = 0; i < currSlice->listXsize[1]; i++) {
+#ifdef ERROR_CHECK
+		if (currSlice->listX[1][i] == NULL) {
+			p_H264_Dpb->dpb_error_flag = __LINE__;
+			pr_info(
+			"error currSlice->listX[1][%d] is NULL\r\n", i);
+			break;
+		}
+#endif
+		currSlice->listX[3][2 * i] =
+			currSlice->listX[1][i]->top_field;
+		currSlice->listX[3][2 * i + 1] =
+			currSlice->listX[1][i]->bottom_field;
+		currSlice->listX[5][2 * i] =
+			currSlice->listX[1][i]->bottom_field;
+		currSlice->listX[5][2 * i + 1] =
+			currSlice->listX[1][i]->top_field;
+	}
+	currSlice->listXsize[3] = currSlice->listXsize[5] =
+		currSlice->listXsize[1] * 2;
+}
+
+
+
+static void init_lists_i_slice(struct Slice *currSlice)
+{
+
+#if (MVC_EXTENSION_ENABLE)
+	currSlice->listinterviewidx0 = 0;
+	currSlice->listinterviewidx1 = 0;
+#endif
+
+	currSlice->listXsize[0] = 0;
+	currSlice->listXsize[1] = 0;
+}
+
+static void init_lists_b_slice(struct Slice *currSlice)
+{
+	struct VideoParameters *p_Vid = currSlice->p_Vid;
+	struct DecodedPictureBuffer *p_Dpb = currSlice->p_Dpb;
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
+		struct h264_dpb_stru, mDPB);
+
+	unsigned int i;
+	int j;
+
+	int list0idx = 0;
+	int list0idx_1 = 0;
+	int listltidx = 0;
+
+	struct FrameStore **fs_list0;
+	struct FrameStore **fs_list1;
+	struct FrameStore **fs_listlt;
+
+#if (MVC_EXTENSION_ENABLE)
+	currSlice->listinterviewidx0 = 0;
+	currSlice->listinterviewidx1 = 0;
+#endif
+
+	{
+		/* B-Slice */
+		if (currSlice->structure == FRAME) {
+			for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i] == NULL ||
+					p_Dpb->fs_ref[i]->frame == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if ((p_Dpb->fs_ref[i]->is_used == 3) &&
+					((p_Dpb->fs_ref[i]->frame->
+					used_for_reference) &&
+					(!p_Dpb->fs_ref[i]->frame->
+					is_long_term)) &&
+					(currSlice->framepoc >=
+					p_Dpb->fs_ref[i]->frame->poc)) {
+					/* !KS use >= for error
+					 *	concealment
+					 */
+					currSlice->listX[0][list0idx++] =
+						p_Dpb->fs_ref[i]->frame;
+				}
+			}
+			qsort((void *)currSlice->listX[0], list0idx,
+				sizeof(struct StorablePicture *),
+				compare_pic_by_poc_desc);
+
+			/* get the backward reference picture
+			 *   (POC>current POC) in list0;
+			 */
+			list0idx_1 = list0idx;
+			for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i] == NULL ||
+					p_Dpb->fs_ref[i]->frame == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if ((p_Dpb->fs_ref[i]->is_used == 3) &&
+					((p_Dpb->fs_ref[i]->frame->
+					used_for_reference) &&
+					(!p_Dpb->fs_ref[i]->frame->
+					is_long_term)) &&
+					(currSlice->framepoc <
+					p_Dpb->fs_ref[i]->frame->poc)) {
+					currSlice->
+					listX[0][list0idx++] =
+						p_Dpb->fs_ref[i]->frame;
+				}
+			}
+			qsort((void *)&currSlice->listX[0][list0idx_1],
+				list0idx - list0idx_1,
+				sizeof(struct StorablePicture *),
+				compare_pic_by_poc_asc);
+
+			for (j = 0; j < list0idx_1; j++) {
+				currSlice->
+				listX[1][list0idx - list0idx_1 + j] =
+					currSlice->listX[0][j];
+			}
+			for (j = list0idx_1; j < list0idx; j++) {
+				currSlice->listX[1][j - list0idx_1] =
+					currSlice->listX[0][j];
+			}
+
+			currSlice->listXsize[0] = currSlice->listXsize[1] =
+				(char) list0idx;
+			CHECK_VALID(currSlice->listXsize[0], 0);
+			CHECK_VALID(currSlice->listXsize[1], 1);
+
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+				"listX[0] (PicNum): ");
+			for (i = 0; i < currSlice->listXsize[0]; i++) {
+				dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "%d  ",
+				currSlice->listX[0][i]->pic_num);
+			}
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "\n");
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+				"listX[1] (PicNum): ");
+			for (i = 0; i < currSlice->listXsize[1]; i++) {
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL, "%d  ",
+					currSlice->listX[1][i]->pic_num);
+			}
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "\n");
+			/* dpb_print(p_H264_Dpb->decoder_index,
+			 *	PRINT_FLAG_DPB_DETAIL,
+			 *	"currSlice->listX[0] currPoc=%d (Poc): ",
+			 *	p_Vid->framepoc);
+			 *   for (i=0; i<currSlice->listXsize[0]; i++) {
+			 *	dpb_print(p_H264_Dpb->decoder_index,
+			 *		PRINT_FLAG_DPB_DETAIL,
+			 *		"%d  ", currSlice->listX[0][i]->poc);
+			 *   }
+			 *   dpb_print(p_H264_Dpb->decoder_index,
+			 *	PRINT_FLAG_DPB_DETAIL, "\n");
+			 *   dpb_print(p_H264_Dpb->decoder_index,
+			 *	PRINT_FLAG_DPB_DETAIL,
+			 *	"currSlice->listX[1] currPoc=%d (Poc): ",
+			 *	p_Vid->framepoc);
+			 *   for (i=0; i<currSlice->listXsize[1]; i++) {
+			 *	dpb_print(p_H264_Dpb->decoder_index,
+			 *	PRINT_FLAG_DPB_DETAIL,
+			 *	"%d  ",
+			 *	currSlice->listX[1][i]->poc);
+			 *   }
+			 *   dpb_print(p_H264_Dpb->decoder_index,
+			 *	PRINT_FLAG_DPB_DETAIL, "\n");
+			 */
+
+			/* long term handling */
+			for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
+				if (p_Dpb->fs_ltref[i]->is_used == 3) {
+					if (p_Dpb->fs_ltref[i]->frame->
+						is_long_term) {
+						currSlice->
+						listX[0][list0idx] =
+						p_Dpb->fs_ltref[i]->frame;
+						currSlice->
+						listX[1][list0idx++] =
+						p_Dpb->fs_ltref[i]->frame;
+					}
+				}
+			}
+			qsort((void *)&currSlice->
+				listX[0][(short) currSlice->listXsize[0]],
+				list0idx - currSlice->listXsize[0],
+				sizeof(struct StorablePicture *),
+				compare_pic_by_lt_pic_num_asc);
+			qsort((void *)&currSlice->
+				listX[1][(short) currSlice->listXsize[0]],
+				list0idx - currSlice->listXsize[0],
+				sizeof(struct StorablePicture *),
+				compare_pic_by_lt_pic_num_asc);
+			currSlice->listXsize[0] = currSlice->listXsize[1] =
+				(char) list0idx;
+			CHECK_VALID(currSlice->listXsize[0], 0);
+			CHECK_VALID(currSlice->listXsize[1], 1);
+		} else {
+#if 0
+			fs_list0 = calloc(p_Dpb->size,
+				sizeof(struct FrameStore *));
+			if (fs_list0 == NULL)
+				no_mem_exit("init_lists: fs_list0");
+			fs_list1 = calloc(p_Dpb->size,
+				sizeof(struct FrameStore *));
+			if (fs_list1 == NULL)
+				no_mem_exit("init_lists: fs_list1");
+			fs_listlt = calloc(p_Dpb->size,
+				sizeof(struct FrameStore *));
+			if (fs_listlt == NULL)
+				no_mem_exit("init_lists: fs_listlt");
+#else
+			fs_list0 = &(p_Dpb->fs_list0[0]);
+			fs_list1 = &(p_Dpb->fs_list1[0]);
+			fs_listlt = &(p_Dpb->fs_listlt[0]);
+
+#endif
+			currSlice->listXsize[0] = 0;
+			currSlice->listXsize[1] = 1;
+
+			for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i] == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if (p_Dpb->fs_ref[i]->is_used) {
+					if (currSlice->ThisPOC >=
+						p_Dpb->fs_ref[i]->poc) {
+						fs_list0[list0idx++] =
+							p_Dpb->fs_ref[i];
+					}
+				}
+			}
+			qsort((void *)fs_list0, list0idx,
+				sizeof(struct FrameStore *),
+				compare_fs_by_poc_desc);
+			list0idx_1 = list0idx;
+			for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i] == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if (p_Dpb->fs_ref[i]->is_used) {
+					if (currSlice->ThisPOC <
+						p_Dpb->fs_ref[i]->poc) {
+						fs_list0[list0idx++] =
+							p_Dpb->fs_ref[i];
+					}
+				}
+			}
+			qsort((void *)&fs_list0[list0idx_1],
+				list0idx - list0idx_1,
+				sizeof(struct FrameStore *),
+				compare_fs_by_poc_asc);
+
+			for (j = 0; j < list0idx_1; j++) {
+				fs_list1[list0idx - list0idx_1 + j] =
+				fs_list0[j];
+			}
+			for (j = list0idx_1; j < list0idx; j++)
+				fs_list1[j - list0idx_1] = fs_list0[j];
+
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+				"fs_list0 currPoc=%d (Poc): ",
+				currSlice->ThisPOC);
+			for (i = 0; i < list0idx; i++) {
+				dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "%d  ",
+				fs_list0[i]->poc);
+			}
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "\n");
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+				"fs_list1 currPoc=%d (Poc): ",
+				currSlice->ThisPOC);
+			for (i = 0; i < list0idx; i++) {
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL, "%d  ",
+					fs_list1[i]->poc);
+			}
+			dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL, "\n");
+
+			currSlice->listXsize[0] = 0;
+			currSlice->listXsize[1] = 0;
+			gen_pic_list_from_frame_list(currSlice->structure,
+						fs_list0, list0idx,
+						currSlice->listX[0],
+						&currSlice->listXsize[0], 0);
+			gen_pic_list_from_frame_list(currSlice->structure,
+						fs_list1, list0idx,
+						currSlice->listX[1],
+						&currSlice->listXsize[1], 0);
+
+			/* dpb_print(p_H264_Dpb->decoder_index,
+			 *	PRINT_FLAG_DPB_DETAIL,
+			 *	"currSlice->listX[0] currPoc=%d (Poc): ",
+			 *	p_Vid->framepoc);
+			 *  for (i=0; i<currSlice->listXsize[0]; i++) {
+			 *	dpb_print(p_H264_Dpb->decoder_index,
+			 *	PRINT_FLAG_DPB_DETAIL, "%d  ",
+			 *	currSlice->listX[0][i]->poc);
+			 *  }
+			 *  dpb_print(p_H264_Dpb->decoder_index,
+			 *	PRINT_FLAG_DPB_DETAIL, "\n");
+			 */
+			/* dpb_print(p_H264_Dpb->decoder_index,
+			 *	PRINT_FLAG_DPB_DETAIL,
+			 *	"currSlice->listX[1] currPoc=%d (Poc): ",
+			 *	p_Vid->framepoc);
+			 *  for (i=0; i<currSlice->listXsize[1]; i++) {
+			 *	dpb_print(p_H264_Dpb->decoder_index,
+			 *	PRINT_FLAG_DPB_DETAIL, "%d  ",
+			 *	currSlice->listX[1][i]->poc);
+			 *  }
+			 *  dpb_print(p_H264_Dpb->decoder_index,
+			 *	PRINT_FLAG_DPB_DETAIL,
+			 *	"\n");
+			 */
+
+			/* long term handling */
+			for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++)
+				fs_listlt[listltidx++] = p_Dpb->fs_ltref[i];
+
+			qsort((void *)fs_listlt, listltidx,
+				sizeof(struct FrameStore *),
+				compare_fs_by_lt_pic_idx_asc);
+
+			gen_pic_list_from_frame_list(currSlice->structure,
+				fs_listlt, listltidx,
+				currSlice->listX[0],
+				&currSlice->listXsize[0], 1);
+			gen_pic_list_from_frame_list(currSlice->structure,
+				fs_listlt, listltidx,
+				currSlice->listX[1],
+				&currSlice->listXsize[1], 1);
+
+			/* free(fs_list0); */
+			/* free(fs_list1); */
+			/* free(fs_listlt); */
+		}
+	}
+
+	if ((currSlice->listXsize[0] == currSlice->listXsize[1]) &&
+	    (currSlice->listXsize[0] > 1)) {
+		/* check if lists are identical,
+		 *if yes swap first two elements of currSlice->listX[1]
+		 */
+		int diff = 0;
+
+		for (j = 0; j < currSlice->listXsize[0]; j++) {
+			if (currSlice->listX[0][j] !=
+				currSlice->listX[1][j]) {
+				diff = 1;
+				break;
+			}
+		}
+		if (!diff) {
+			struct StorablePicture *tmp_s =
+				currSlice->listX[1][0];
+			currSlice->listX[1][0] = currSlice->listX[1][1];
+			currSlice->listX[1][1] = tmp_s;
+		}
+	}
+
+	/* set max size */
+	currSlice->listXsize[0] = (char) imin(currSlice->listXsize[0],
+		currSlice->num_ref_idx_active[LIST_0]);
+	currSlice->listXsize[1] = (char) imin(currSlice->listXsize[1],
+		currSlice->num_ref_idx_active[LIST_1]);
+	CHECK_VALID(currSlice->listXsize[0], 0);
+	CHECK_VALID(currSlice->listXsize[1], 1);
+
+	/* set the unused list entries to NULL */
+	for (i = currSlice->listXsize[0]; i < (MAX_LIST_SIZE); i++)
+		currSlice->listX[0][i] = p_Vid->no_reference_picture;
+	for (i = currSlice->listXsize[1]; i < (MAX_LIST_SIZE); i++)
+		currSlice->listX[1][i] = p_Vid->no_reference_picture;
+
+#if PRINTREFLIST
+#if (MVC_EXTENSION_ENABLE)
+	/* print out for h264_debug_flag purpose */
+	if ((p_Vid->profile_idc == MVC_HIGH ||
+	    p_Vid->profile_idc == STEREO_HIGH) &&
+	    currSlice->current_slice_nr == 0) {
+		if ((currSlice->listXsize[0] > 0) ||
+		    (currSlice->listXsize[1] > 0))
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "\n");
+		if (currSlice->listXsize[0] > 0) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+				" ** (CurViewID:%d %d) %s Ref Pic List 0 ****\n",
+				currSlice->view_id,
+				currSlice->ThisPOC,
+				currSlice->structure == FRAME ? "FRM" :
+				(currSlice->structure == TOP_FIELD ?
+				"TOP" : "BOT"));
+			for (i = 0; i < (unsigned int)(currSlice->
+				listXsize[0]); i++) { /* ref list 0 */
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					"   %2d -> POC: %4d PicNum: %4d ViewID: %d\n",
+					i,
+					currSlice->listX[0][i]->poc,
+					currSlice->listX[0][i]->pic_num,
+					currSlice->listX[0][i]->view_id);
+			}
+		}
+		if (currSlice->listXsize[1] > 0) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+				" ** (CurViewID:%d %d) %s Ref Pic List 1 ****\n",
+				currSlice->view_id,
+				currSlice->ThisPOC,
+				currSlice->structure == FRAME ? "FRM" :
+				(currSlice->structure == TOP_FIELD ? "TOP" :
+				"BOT"));
+			for (i = 0; i < (unsigned int)(currSlice->
+				listXsize[1]); i++) { /* ref list 1 */
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					"   %2d -> POC: %4d PicNum: %4d	ViewID: %d\n",
+					i,
+					currSlice->listX[1][i]->poc,
+					currSlice->listX[1][i]->pic_num,
+					currSlice->listX[1][i]->view_id);
+			}
+		}
+	}
+#endif
+#endif
+}
+
+static struct StorablePicture *get_short_term_pic(struct Slice *currSlice,
+		struct DecodedPictureBuffer *p_Dpb, int picNum)
+{
+	unsigned int i;
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Dpb,
+		struct h264_dpb_stru, mDPB);
+	for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+		if (currSlice->structure == FRAME) {
+#ifdef ERROR_CHECK
+			if (p_Dpb->fs_ref[i] == NULL) {
+				p_H264_Dpb->dpb_error_flag = __LINE__;
+				continue;
+			}
+#endif
+			if (p_Dpb->fs_ref[i]->is_reference == 3) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i]->frame == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if ((!p_Dpb->fs_ref[i]->frame->
+					is_long_term) &&
+				    (p_Dpb->fs_ref[i]->frame->
+					pic_num == picNum))
+					return p_Dpb->fs_ref[i]->frame;
+			}
+		} else {
+#ifdef ERROR_CHECK
+			if (p_Dpb->fs_ref[i] == NULL) {
+				p_H264_Dpb->dpb_error_flag = __LINE__;
+				continue;
+			}
+#endif
+			if (p_Dpb->fs_ref[i]->is_reference & 1) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i]->top_field == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if ((!p_Dpb->fs_ref[i]->top_field->
+					is_long_term) &&
+				    (p_Dpb->fs_ref[i]->top_field->
+					pic_num == picNum))
+					return p_Dpb->fs_ref[i]->top_field;
+			}
+			if (p_Dpb->fs_ref[i]->is_reference & 2) {
+#ifdef ERROR_CHECK
+				if (p_Dpb->fs_ref[i]->bottom_field == NULL) {
+					p_H264_Dpb->dpb_error_flag = __LINE__;
+					continue;
+				}
+#endif
+				if ((!p_Dpb->fs_ref[i]->bottom_field->
+					is_long_term) &&
+				    (p_Dpb->fs_ref[i]->bottom_field->
+					pic_num == picNum))
+					return p_Dpb->fs_ref[i]->bottom_field;
+			}
+		}
+	}
+
+	return currSlice->p_Vid->no_reference_picture;
+}
+
+
+static void reorder_short_term(struct Slice *currSlice, int cur_list,
+				int num_ref_idx_lX_active_minus1,
+				int picNumLX, int *refIdxLX)
+{
+	struct h264_dpb_stru *p_H264_Dpb = container_of(currSlice->p_Vid,
+					struct h264_dpb_stru, mVideo);
+
+	struct StorablePicture **RefPicListX = currSlice->listX[cur_list];
+	int cIdx, nIdx;
+
+	struct StorablePicture *picLX;
+
+	picLX = get_short_term_pic(currSlice, currSlice->p_Dpb, picNumLX);
+
+	for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX;
+		cIdx--) {
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			"%s: RefPicListX[ %d ] = RefPicListX[ %d ]\n",
+			__func__, cIdx, cIdx - 1);
+		RefPicListX[cIdx] = RefPicListX[cIdx - 1];
+	}
+
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s: RefPicListX[ %d ] = pic %x (%d)\n", __func__,
+		*refIdxLX, picLX, picNumLX);
+
+	RefPicListX[(*refIdxLX)++] = picLX;
+
+	nIdx = *refIdxLX;
+
+	for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1;
+		cIdx++) {
+		if (RefPicListX[cIdx])
+			if ((RefPicListX[cIdx]->is_long_term) ||
+			    (RefPicListX[cIdx]->pic_num != picNumLX)) {
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					"%s: RefPicListX[ %d ] = RefPicListX[ %d ]\n",
+					__func__, nIdx, cIdx);
+				RefPicListX[nIdx++] = RefPicListX[cIdx];
+			}
+	}
+}
+
+
+static struct StorablePicture *get_long_term_pic(struct Slice *currSlice,
+		struct DecodedPictureBuffer *p_Dpb, int LongtermPicNum)
+{
+	unsigned int i;
+
+	for (i = 0; i < p_Dpb->ltref_frames_in_buffer; i++) {
+		if (currSlice->structure == FRAME) {
+			if (p_Dpb->fs_ltref[i]->is_reference == 3)
+				if ((p_Dpb->fs_ltref[i]->frame) &&
+					(p_Dpb->fs_ltref[i]->frame->
+					is_long_term) &&
+				    (p_Dpb->fs_ltref[i]->frame->
+					long_term_pic_num ==
+					LongtermPicNum))
+					return p_Dpb->fs_ltref[i]->frame;
+		} else {
+			if (p_Dpb->fs_ltref[i]->is_reference & 1)
+				if ((p_Dpb->fs_ltref[i]->top_field) &&
+					(p_Dpb->fs_ltref[i]->top_field->
+					is_long_term) &&
+				    (p_Dpb->fs_ltref[i]->top_field->
+					long_term_pic_num == LongtermPicNum))
+					return p_Dpb->fs_ltref[i]->top_field;
+
+			if (p_Dpb->fs_ltref[i]->is_reference & 2)
+				if ((p_Dpb->fs_ltref[i]->bottom_field) &&
+					(p_Dpb->fs_ltref[i]->bottom_field->
+					is_long_term) &&
+				    (p_Dpb->fs_ltref[i]->bottom_field->
+					long_term_pic_num ==
+					LongtermPicNum))
+					return p_Dpb->fs_ltref[i]->
+						bottom_field;
+		}
+	}
+	return NULL;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ *    Reordering process for long-term reference pictures
+ *
+ ************************************************************************
+ */
+static void reorder_long_term(struct Slice *currSlice,
+				struct StorablePicture **RefPicListX,
+				int num_ref_idx_lX_active_minus1,
+			      int LongTermPicNum, int *refIdxLX)
+{
+	int cIdx, nIdx;
+
+	struct StorablePicture *picLX;
+
+	picLX = get_long_term_pic(currSlice, currSlice->p_Dpb, LongTermPicNum);
+
+	for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX; cIdx--)
+		RefPicListX[cIdx] = RefPicListX[cIdx - 1];
+
+	RefPicListX[(*refIdxLX)++] = picLX;
+
+	nIdx = *refIdxLX;
+
+	for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1;
+		cIdx++) {
+		if (RefPicListX[cIdx]) {
+			if ((!RefPicListX[cIdx]->is_long_term) ||
+			    (RefPicListX[cIdx]->long_term_pic_num !=
+				LongTermPicNum))
+				RefPicListX[nIdx++] = RefPicListX[cIdx];
+		}
+	}
+}
+
+static void reorder_ref_pic_list(struct Slice *currSlice, int cur_list)
+{
+	int *modification_of_pic_nums_idc =
+		currSlice->modification_of_pic_nums_idc[cur_list];
+	int *abs_diff_pic_num_minus1 =
+		currSlice->abs_diff_pic_num_minus1[cur_list];
+	int *long_term_pic_idx = currSlice->long_term_pic_idx[cur_list];
+	int num_ref_idx_lX_active_minus1 =
+		currSlice->num_ref_idx_active[cur_list] - 1;
+
+	struct VideoParameters *p_Vid = currSlice->p_Vid;
+	int i;
+
+	int maxPicNum, currPicNum, picNumLXNoWrap, picNumLXPred, picNumLX;
+	int refIdxLX = 0;
+
+	if (currSlice->structure == FRAME) {
+		maxPicNum  = p_Vid->max_frame_num;
+		currPicNum = currSlice->frame_num;
+	} else {
+		maxPicNum  = 2 * p_Vid->max_frame_num;
+		currPicNum = 2 * currSlice->frame_num + 1;
+	}
+
+	picNumLXPred = currPicNum;
+
+	for (i = 0;  i < REORDERING_COMMAND_MAX_SIZE &&
+		modification_of_pic_nums_idc[i] != 3; i++) {
+		if (modification_of_pic_nums_idc[i] > 3) {
+			struct h264_dpb_stru *p_H264_Dpb =
+			container_of(p_Vid, struct h264_dpb_stru, mVideo);
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_ERROR,
+				"error, Invalid modification_of_pic_nums_idc command\n");
+			/*h264_debug_flag = 0x1f;*/
+			break;
+		}
+		if (modification_of_pic_nums_idc[i] < 2) {
+			if (modification_of_pic_nums_idc[i] == 0) {
+				if (picNumLXPred - (abs_diff_pic_num_minus1[i]
+					+ 1) < 0)
+					picNumLXNoWrap = picNumLXPred -
+					(abs_diff_pic_num_minus1[i] + 1) +
+					maxPicNum;
+				else
+					picNumLXNoWrap = picNumLXPred -
+					(abs_diff_pic_num_minus1[i] + 1);
+			} else { /* (modification_of_pic_nums_idc[i] == 1) */
+				if (picNumLXPred + (abs_diff_pic_num_minus1[i]
+					+ 1)  >=  maxPicNum)
+					picNumLXNoWrap = picNumLXPred +
+					(abs_diff_pic_num_minus1[i] + 1) -
+					maxPicNum;
+				else
+					picNumLXNoWrap = picNumLXPred +
+					(abs_diff_pic_num_minus1[i] + 1);
+			}
+			picNumLXPred = picNumLXNoWrap;
+
+			if (picNumLXNoWrap > currPicNum)
+				picNumLX = picNumLXNoWrap - maxPicNum;
+			else
+				picNumLX = picNumLXNoWrap;
+
+#if (MVC_EXTENSION_ENABLE)
+			reorder_short_term(currSlice, cur_list,
+					num_ref_idx_lX_active_minus1, picNumLX,
+					&refIdxLX, -1);
+#else
+			reorder_short_term(currSlice, cur_list,
+					num_ref_idx_lX_active_minus1, picNumLX,
+					&refIdxLX);
+#endif
+		} else { /* (modification_of_pic_nums_idc[i] == 2) */
+#if (MVC_EXTENSION_ENABLE)
+			reorder_long_term(currSlice, currSlice->listX[cur_list],
+					num_ref_idx_lX_active_minus1,
+					long_term_pic_idx[i], &refIdxLX, -1);
+#else
+			reorder_long_term(currSlice, currSlice->listX[cur_list],
+					num_ref_idx_lX_active_minus1,
+					long_term_pic_idx[i], &refIdxLX);
+#endif
+		}
+
+	}
+	/* that's a definition */
+	currSlice->listXsize[cur_list] =
+		(char)(num_ref_idx_lX_active_minus1 + 1);
+}
+
+static void reorder_lists(struct Slice *currSlice)
+{
+	struct VideoParameters *p_Vid = currSlice->p_Vid;
+	struct h264_dpb_stru *p_H264_Dpb = container_of(p_Vid,
+		struct h264_dpb_stru, mVideo);
+	int i;
+
+	if ((currSlice->slice_type != I_SLICE) &&
+		(currSlice->slice_type != SI_SLICE)) {
+		if (currSlice->ref_pic_list_reordering_flag[LIST_0])
+			reorder_ref_pic_list(currSlice, LIST_0);
+		if (p_Vid->no_reference_picture ==
+		    currSlice->
+			listX[0][currSlice->num_ref_idx_active[LIST_0] - 1]) {
+			if (p_Vid->non_conforming_stream)
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					"RefPicList0[ %d ] is equal to 'no reference picture'\n",
+					currSlice->
+					num_ref_idx_active[LIST_0] - 1);
+			else
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					"RefPicList0 [ num_ref_idx_l0_active_minus1 ] is equal to 'no reference picture', invalid bitstream %d\n",
+					500);
+		}
+		/* that's a definition */
+		currSlice->listXsize[0] =
+			(char) imin(currSlice->listXsize[0],
+			currSlice->num_ref_idx_active[LIST_0]);
+		CHECK_VALID(currSlice->listXsize[0], 0);
+		if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+				"listX[0] reorder (PicNum): ");
+			for (i = 0; i < currSlice->listXsize[0]; i++) {
+				dpb_print_cont(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL, "%d  ",
+					currSlice->listX[0][i]->pic_num);
+			}
+			dpb_print_cont(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "\n");
+		}
+	}
+
+	if (currSlice->slice_type == B_SLICE) {
+		if (currSlice->ref_pic_list_reordering_flag[LIST_1])
+			reorder_ref_pic_list(currSlice, LIST_1);
+		if (p_Vid->no_reference_picture ==
+		    currSlice->listX[1][currSlice->
+			num_ref_idx_active[LIST_1] - 1]) {
+			if (p_Vid->non_conforming_stream)
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					"RefPicList1[ %d ] is equal to 'no reference picture'\n",
+					currSlice->
+					num_ref_idx_active[LIST_1] - 1);
+			else
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					"RefPicList1 [ num_ref_idx_l1_active_minus1 ] is equal to 'no reference picture', invalid bitstream %d\n",
+					500);
+		}
+		/* that's a definition */
+		currSlice->listXsize[1] =
+			(char)currSlice->num_ref_idx_active[LIST_1];
+		if (h264_debug_flag & PRINT_FLAG_DPB_DETAIL) {
+			dpb_print(p_H264_Dpb->decoder_index,
+			PRINT_FLAG_DPB_DETAIL,
+				  "listX[1] reorder (PicNum): ");
+			for (i = 0; i < currSlice->listXsize[1]; i++) {
+				if (currSlice->listX[1][i])
+					dpb_print_cont(p_H264_Dpb->decoder_index,
+						PRINT_FLAG_DPB_DETAIL, "%d  ",
+						currSlice->listX[1][i]->pic_num);
+			}
+			dpb_print_cont(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL, "\n");
+		}
+	}
+
+	/* free_ref_pic_list_reordering_buffer(currSlice); */
+
+	if (currSlice->slice_type == P_SLICE) {
+#if PRINTREFLIST
+		unsigned int i;
+#if (MVC_EXTENSION_ENABLE)
+		/* print out for h264_debug_flag purpose */
+		if ((p_Vid->profile_idc == MVC_HIGH ||
+			p_Vid->profile_idc == STEREO_HIGH) &&
+			currSlice->current_slice_nr == 0) {
+			if (currSlice->listXsize[0] > 0
+				&& (h264_debug_flag & PRINT_FLAG_DPB_DETAIL)) {
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL, "\n");
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					  " ** (FinalViewID:%d) %s Ref Pic List 0 ****\n",
+					currSlice->view_id,
+					currSlice->structure == FRAME ?
+					"FRM" :
+					(currSlice->structure == TOP_FIELD ?
+					"TOP" : "BOT"));
+				for (i = 0; i < (unsigned int)(currSlice->
+					listXsize[0]); i++) { /* ref list 0 */
+					dpb_print(p_H264_Dpb->decoder_index,
+						PRINT_FLAG_DPB_DETAIL,
+						"   %2d -> POC: %4d PicNum: %4d ViewID: %d\n",
+						i,
+						currSlice->listX[0][i]->poc,
+						currSlice->listX[0][i]->
+							pic_num,
+						currSlice->listX[0][i]->
+							view_id);
+				}
+			}
+		}
+#endif
+#endif
+	} else if (currSlice->slice_type == B_SLICE) {
+#if PRINTREFLIST
+		unsigned int i;
+#if (MVC_EXTENSION_ENABLE)
+		/* print out for h264_debug_flag purpose */
+		if ((p_Vid->profile_idc == MVC_HIGH ||
+			p_Vid->profile_idc == STEREO_HIGH) &&
+		    currSlice->current_slice_nr == 0) {
+			if ((currSlice->listXsize[0] > 0) ||
+				(currSlice->listXsize[1] > 0))
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL, "\n");
+			if (currSlice->listXsize[0] > 0
+				&& (h264_debug_flag & PRINT_FLAG_DPB_DETAIL)) {
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					" ** (FinalViewID:%d) %s Ref Pic List 0 ****\n",
+					currSlice->view_id,
+					currSlice->structure == FRAME ?
+					"FRM" :
+					(currSlice->structure == TOP_FIELD ?
+					"TOP" : "BOT"));
+				for (i = 0; i < (unsigned int)(currSlice->
+					listXsize[0]); i++) { /* ref list 0 */
+					dpb_print(p_H264_Dpb->decoder_index,
+						PRINT_FLAG_DPB_DETAIL,
+						"   %2d -> POC: %4d PicNum: %4d ViewID: %d\n",
+						i,
+						currSlice->listX[0][i]->poc,
+						currSlice->listX[0][i]->
+							pic_num,
+						currSlice->listX[0][i]->
+							view_id);
+				}
+			}
+			if (currSlice->listXsize[1] > 0
+				 && (h264_debug_flag & PRINT_FLAG_DPB_DETAIL)) {
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_DPB_DETAIL,
+					" ** (FinalViewID:%d) %s Ref Pic List 1 ****\n",
+					currSlice->view_id,
+					currSlice->structure == FRAME ?
+					"FRM" :
+					(currSlice->structure == TOP_FIELD ?
+					"TOP" : "BOT"));
+				for (i = 0; i < (unsigned int)(currSlice->
+					listXsize[1]); i++) { /* ref list 1 */
+					dpb_print(p_H264_Dpb->decoder_index,
+						PRINT_FLAG_DPB_DETAIL,
+						"   %2d -> POC: %4d PicNum: %4d ViewID: %d\n",
+						i,
+						currSlice->listX[1][i]->poc,
+						currSlice->listX[1][i]->
+							pic_num,
+						currSlice->listX[1][i]->
+							view_id);
+				}
+			}
+		}
+#endif
+
+#endif
+	}
+}
+
+void init_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int count)
+{
+	p_H264_Dpb->colocated_buf_map = 0;
+	p_H264_Dpb->colocated_buf_count = count;
+}
+
+int allocate_colocate_buf(struct h264_dpb_stru *p_H264_Dpb)
+{
+	int i;
+
+	for (i = 0; i < p_H264_Dpb->colocated_buf_count; i++) {
+		if (((p_H264_Dpb->colocated_buf_map >> i) & 0x1) == 0) {
+			p_H264_Dpb->colocated_buf_map |= (1 << i);
+			break;
+		}
+	}
+	if (i == p_H264_Dpb->colocated_buf_count) {
+		i = -1;
+		p_H264_Dpb->buf_alloc_fail = 1;
+	}
+	return i;
+}
+
+int release_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int index)
+{
+	if (index >= 0) {
+		if (index >= p_H264_Dpb->colocated_buf_count) {
+			dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_ERROR,
+				"%s error, index %d is bigger than buf count %d\n",
+				__func__, index,
+				p_H264_Dpb->colocated_buf_count);
+		} else {
+			if (((p_H264_Dpb->colocated_buf_map >>
+				index) & 0x1) == 0x1) {
+				p_H264_Dpb->colocated_buf_map &=
+					(~(1 << index));
+			} else {
+				dpb_print(p_H264_Dpb->decoder_index,
+					PRINT_FLAG_ERROR,
+					"%s error, index %d is not allocated\n",
+					__func__, index);
+			}
+		}
+	}
+	return 0;
+}
+
+void set_frame_output_flag(struct h264_dpb_stru *p_H264_Dpb, int index)
+{
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+
+	p_H264_Dpb->mFrameStore[index].is_output = 1;
+	p_H264_Dpb->mFrameStore[index].pre_output = 0;
+	p_H264_Dpb->mFrameStore[index].show_frame = false;
+	dump_dpb(p_Dpb, 0);
+}
+
+#if 0
+void init_old_slice(OldSliceParams *p_old_slice)
+{
+	p_old_slice->field_pic_flag = 0;
+	p_old_slice->pps_id         = INT_MAX;
+	p_old_slice->frame_num      = INT_MAX;
+	p_old_slice->nal_ref_idc    = INT_MAX;
+	p_old_slice->idr_flag       = 0;
+
+	p_old_slice->pic_oder_cnt_lsb          = UINT_MAX;
+	p_old_slice->delta_pic_oder_cnt_bottom = INT_MAX;
+
+	p_old_slice->delta_pic_order_cnt[0] = INT_MAX;
+	p_old_slice->delta_pic_order_cnt[1] = INT_MAX;
+}
+
+
+void copy_slice_info(struct Slice *currSlice, OldSliceParams *p_old_slice)
+{
+	struct VideoParameters *p_Vid = currSlice->p_Vid;
+
+	p_old_slice->pps_id         = currSlice->pic_parameter_set_id;
+	p_old_slice->frame_num      = currSlice->frame_num;
+	/* p_Vid->frame_num; */
+	p_old_slice->field_pic_flag =
+		currSlice->field_pic_flag;
+	/* p_Vid->field_pic_flag; */
+
+	if (currSlice->field_pic_flag)
+		p_old_slice->bottom_field_flag = currSlice->bottom_field_flag;
+
+	p_old_slice->nal_ref_idc = currSlice->nal_reference_idc;
+	p_old_slice->idr_flag    = (byte) currSlice->idr_flag;
+
+	if (currSlice->idr_flag)
+		p_old_slice->idr_pic_id = currSlice->idr_pic_id;
+
+	if (p_Vid->active_sps->pic_order_cnt_type == 0) {
+		p_old_slice->pic_oder_cnt_lsb =
+			currSlice->pic_order_cnt_lsb;
+		p_old_slice->delta_pic_oder_cnt_bottom =
+			currSlice->delta_pic_order_cnt_bottom;
+	}
+
+	if (p_Vid->active_sps->pic_order_cnt_type == 1) {
+		p_old_slice->delta_pic_order_cnt[0] =
+			currSlice->delta_pic_order_cnt[0];
+		p_old_slice->delta_pic_order_cnt[1] =
+			currSlice->delta_pic_order_cnt[1];
+	}
+#if (MVC_EXTENSION_ENABLE)
+	p_old_slice->view_id = currSlice->view_id;
+	p_old_slice->inter_view_flag = currSlice->inter_view_flag;
+	p_old_slice->anchor_pic_flag = currSlice->anchor_pic_flag;
+#endif
+	p_old_slice->layer_id = currSlice->layer_id;
+}
+
+int is_new_picture(StorablePicture *dec_picture, struct Slice *currSlice,
+		   OldSliceParams *p_old_slice)
+{
+	struct VideoParameters *p_Vid = currSlice->p_Vid;
+
+	int result = 0;
+
+	result |= (dec_picture == NULL);
+
+	result |= (p_old_slice->pps_id != currSlice->pic_parameter_set_id);
+
+	result |= (p_old_slice->frame_num != currSlice->frame_num);
+
+	result |= (p_old_slice->field_pic_flag != currSlice->field_pic_flag);
+
+	if (currSlice->field_pic_flag && p_old_slice->field_pic_flag) {
+		result |= (p_old_slice->bottom_field_flag !=
+				currSlice->bottom_field_flag);
+	}
+
+	result |= (p_old_slice->nal_ref_idc !=
+			currSlice->nal_reference_idc) &&
+		  ((p_old_slice->nal_ref_idc == 0) ||
+			(currSlice->nal_reference_idc == 0));
+	result |= (p_old_slice->idr_flag    != currSlice->idr_flag);
+
+	if (currSlice->idr_flag && p_old_slice->idr_flag)
+		result |= (p_old_slice->idr_pic_id != currSlice->idr_pic_id);
+
+	if (p_Vid->active_sps->pic_order_cnt_type == 0) {
+		result |= (p_old_slice->pic_oder_cnt_lsb !=
+			   currSlice->pic_order_cnt_lsb);
+		if (p_Vid->active_pps->
+			bottom_field_pic_order_in_frame_present_flag  ==  1 &&
+		    !currSlice->field_pic_flag) {
+			result |= (p_old_slice->delta_pic_oder_cnt_bottom !=
+				   currSlice->delta_pic_order_cnt_bottom);
+		}
+	}
+
+	if (p_Vid->active_sps->pic_order_cnt_type == 1) {
+		if (!p_Vid->active_sps->delta_pic_order_always_zero_flag) {
+			result |= (p_old_slice->delta_pic_order_cnt[0] !=
+				   currSlice->delta_pic_order_cnt[0]);
+			if (p_Vid->active_pps->
+			bottom_field_pic_order_in_frame_present_flag  ==  1 &&
+			    !currSlice->field_pic_flag) {
+				result |= (p_old_slice->
+					delta_pic_order_cnt[1] !=
+					currSlice->delta_pic_order_cnt[1]);
+			}
+		}
+	}
+
+#if (MVC_EXTENSION_ENABLE)
+	result |= (currSlice->view_id != p_old_slice->view_id);
+	result |= (currSlice->inter_view_flag != p_old_slice->inter_view_flag);
+	result |= (currSlice->anchor_pic_flag != p_old_slice->anchor_pic_flag);
+#endif
+	result |= (currSlice->layer_id != p_old_slice->layer_id);
+	return result;
+}
+#else
+int is_new_picture(struct StorablePicture *dec_picture,
+		   struct h264_dpb_stru *p_H264_Dpb,
+		   struct OldSliceParams *p_old_slice)
+{
+	int ret = 0;
+
+	if (p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE] == 0)
+		ret = 1;
+	return ret;
+}
+
+#endif
+
+/*
+* release bufspec and pic for picture not in dpb buf
+*/
+int release_picture(struct h264_dpb_stru *p_H264_Dpb,
+		   struct StorablePicture *pic)
+{
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+
+	if (p_Dpb->last_picture == NULL) {
+		if (pic->colocated_buf_index >= 0) {
+			release_colocate_buf(p_H264_Dpb,
+			pic->colocated_buf_index);
+			pic->colocated_buf_index = -1;
+		}
+		release_buf_spec_num(p_H264_Dpb->vdec, pic->buf_spec_num);
+	} else {
+		if (pic->buf_spec_is_alloced == 1)
+			release_buf_spec_num(p_H264_Dpb->vdec,
+				pic->buf_spec_num);
+	}
+
+	free_picture(p_H264_Dpb, pic);
+	return 0;
+}
+
+#ifdef ERROR_HANDLE_TEST
+/*
+*  remove all pictures in dpb and release bufspec/pic of them
+*/
+void remove_dpb_pictures(struct h264_dpb_stru *p_H264_Dpb)
+{
+	/* struct VideoParameters *p_Vid = p_Dpb->p_Vid; */
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+	struct Slice *currSlice = &p_H264_Dpb->mSlice;
+	unsigned  i, j;
+
+	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s\n", __func__);
+
+	if (!p_Dpb->init_done)
+		return;
+
+	for (i = 0; i < p_Dpb->used_size; i++) {
+		if (p_Dpb->fs[i]->colocated_buf_index >= 0) {
+			dpb_print(p_H264_Dpb->decoder_index,
+			PRINT_FLAG_DPB_DETAIL,
+			"release_colocate_buf[%d] for fs[%d]\n",
+			p_Dpb->fs[i]->colocated_buf_index, i);
+
+			release_colocate_buf(p_H264_Dpb,
+				p_Dpb->fs[i]->colocated_buf_index); /* rain */
+			p_Dpb->fs[i]->colocated_buf_index = -1;
+		}
+		if (!p_Dpb->fs[i]->pre_output) {
+			release_buf_spec_num(p_H264_Dpb->vdec,
+				p_Dpb->fs[i]->buf_spec_num);
+			p_Dpb->fs[i]->buf_spec_num = -1;
+		}
+		remove_frame_from_dpb(p_H264_Dpb, i);
+	}
+
+	for (i = 0; i < p_Dpb->used_size; i++) {
+		p_Dpb->fs_ref[i] = NULL;
+		p_Dpb->fs_ltref[i] = NULL;
+		p_Dpb->fs_list0[i] = NULL;
+		p_Dpb->fs_list1[i] = NULL;
+		p_Dpb->fs_listlt[i] = NULL;
+	}
+	for (i = 0; i < 2; i++) {
+		currSlice->listXsize[i] = 0;
+		for (j = 0; j < (MAX_LIST_SIZE * 2); j++)
+			currSlice->listX[i][j] = NULL;
+	}
+	p_Dpb->ref_frames_in_buffer = 0;
+	p_Dpb->ltref_frames_in_buffer = 0;
+	p_Dpb->last_output_poc = INT_MIN;
+}
+#endif
+
+static void check_frame_store_same_pic_num(struct DecodedPictureBuffer *p_Dpb,
+	struct StorablePicture *p, struct Slice *currSlice)
+{
+	if (p_Dpb->last_picture) {
+		if ((int)p_Dpb->last_picture->frame_num == p->pic_num) {
+			if (((p->structure == TOP_FIELD) &&
+				(p_Dpb->last_picture->is_used == 2)) ||
+			    ((p->structure == BOTTOM_FIELD) &&
+				(p_Dpb->last_picture->is_used == 1))) {
+				if ((p->used_for_reference &&
+					(p_Dpb->last_picture->
+					is_orig_reference != 0)) ||
+				    (!p->used_for_reference &&
+					(p_Dpb->last_picture->
+					is_orig_reference == 0))) {
+					p->buf_spec_num =
+						p_Dpb->last_picture->
+						buf_spec_num;
+					p->buf_spec_is_alloced = 0;
+					p->colocated_buf_index = p_Dpb->
+						last_picture->
+						colocated_buf_index;
+					if (currSlice->structure ==
+						TOP_FIELD) {
+						p->bottom_poc =
+							p_Dpb->last_picture->
+							bottom_field->poc;
+					} else {
+						p->top_poc =
+							p_Dpb->last_picture->
+							top_field->poc;
+					}
+					p->frame_poc = imin(p->bottom_poc,
+						p->top_poc);
+				}
+			}
+		}
+	}
+}
+
+int h264_slice_header_process(struct h264_dpb_stru *p_H264_Dpb, int *frame_num_gap)
+{
+
+	int new_pic_flag = 0;
+	struct Slice *currSlice = &p_H264_Dpb->mSlice;
+	struct VideoParameters *p_Vid = &p_H264_Dpb->mVideo;
+	struct DecodedPictureBuffer *p_Dpb =
+				&p_H264_Dpb->mDPB;
+#if 0
+	new_pic_flag = is_new_picture(p_H264_Dpb->mVideo.dec_picture,
+				      p_H264_Dpb,
+				      &p_H264_Dpb->mVideo.old_slice);
+
+	if (new_pic_flag) { /* new picture */
+		if (p_H264_Dpb->mVideo.dec_picture) {
+			store_picture_in_dpb(p_H264_Dpb,
+				p_H264_Dpb->mVideo.dec_picture);
+			/* dump_dpb(&p_H264_Dpb->mDPB); */
+		}
+	}
+#else
+	new_pic_flag = (p_H264_Dpb->mVideo.dec_picture == NULL);
+#endif
+	p_H264_Dpb->buf_alloc_fail = 0;
+	p_H264_Dpb->dpb_error_flag = 0;
+	slice_prepare(p_H264_Dpb, &p_H264_Dpb->mDPB, &p_H264_Dpb->mVideo,
+		      &p_H264_Dpb->mSPS, &p_H264_Dpb->mSlice);
+
+	if (p_Dpb->num_ref_frames != p_H264_Dpb->mSPS.num_ref_frames) {
+		dpb_print(p_H264_Dpb->decoder_index, 0,
+		"num_ref_frames change from %d to %d\r\n",
+			p_Dpb->num_ref_frames, p_H264_Dpb->mSPS.num_ref_frames);
+		p_Dpb->num_ref_frames = p_H264_Dpb->mSPS.num_ref_frames;
+	}
+	/* if (p_Vid->active_sps != sps) { */
+	if (p_H264_Dpb->mDPB.init_done == 0) {
+		/*init_global_buffers(p_Vid, 0);
+		 *		 ** * *if (!p_Vid->no_output_of_prior_pics_flag)
+		 ** * *{
+		 ** * *    flush_dpb(p_Vid->p_Dpb_layer[0]);
+		 ** * *}
+		 ** * *init_dpb(p_Vid, p_Vid->p_Dpb_layer[0], 0);
+		 */
+		init_dpb(p_H264_Dpb, 0);
+	}
+
+
+	if (new_pic_flag) { /* new picture */
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"check frame_num gap: cur frame_num %d pre_frame_num %d max_frmae_num %d\r\n",
+		currSlice->frame_num,
+		p_Vid->pre_frame_num,
+		p_Vid->max_frame_num);
+		if (p_Vid->recovery_point == 0 &&
+			p_Vid->max_frame_num <= FRAME_NUM_MAX_SIZE &&
+			currSlice->frame_num != p_Vid->pre_frame_num &&
+			currSlice->frame_num !=
+			(p_Vid->pre_frame_num + 1) % p_Vid->max_frame_num) {
+			struct SPSParameters *active_sps = p_Vid->active_sps;
+			/*if (active_sps->
+			 *gaps_in_frame_num_value_allowed_flag
+			 *== 0) {
+			 *  error("An unintentional
+			 *  loss of pictures occurs! Exit\n",
+			 *  100);
+			 *}
+			 *if (p_Vid->conceal_mode == 0)
+			 */
+			 if (active_sps->frame_num_gap_allowed)
+				fill_frame_num_gap(p_Vid, currSlice);
+			*frame_num_gap = 1;
+		}
+
+		if (currSlice->nal_reference_idc) {
+			dpb_print(p_H264_Dpb->decoder_index,
+				PRINT_FLAG_DPB_DETAIL,
+			"nal_reference_idc not 0, set pre_frame_num(%d) to frame_num (%d)\n",
+			p_Vid->pre_frame_num, currSlice->frame_num);
+			p_Vid->pre_frame_num = currSlice->frame_num;
+		}
+
+		decode_poc(&p_H264_Dpb->mVideo, &p_H264_Dpb->mSlice);
+		p_H264_Dpb->mVideo.dec_picture = get_new_pic(p_H264_Dpb,
+						 p_H264_Dpb->mSlice.structure,
+						/*p_Vid->width, p_Vid->height,
+						 *  p_Vid->width_cr,
+						 *  p_Vid->height_cr,
+						 */
+						 1);
+		if (p_H264_Dpb->mVideo.dec_picture) {
+			u32 offset_lo, offset_hi;
+			struct DecodedPictureBuffer *p_Dpb =
+				&p_H264_Dpb->mDPB;
+			struct StorablePicture *p =
+				p_H264_Dpb->mVideo.dec_picture;
+			init_picture(p_H264_Dpb, &p_H264_Dpb->mSlice,
+				p_H264_Dpb->mVideo.dec_picture);
+#if 1
+			/* rain */
+			offset_lo  =
+			p_H264_Dpb->dpb_param.l.data[OFFSET_DELIMITER_LO];
+			offset_hi  =
+			p_H264_Dpb->dpb_param.l.data[OFFSET_DELIMITER_HI];
+			p_H264_Dpb->mVideo.dec_picture->offset_delimiter =
+				(offset_lo	| offset_hi << 16);
+			p_H264_Dpb->mVideo.dec_picture->buf_spec_num  = -1;
+			p_H264_Dpb->mVideo.dec_picture->
+				colocated_buf_index = -1;
+			update_pic_num(p_H264_Dpb);
+
+			if ((currSlice->structure == TOP_FIELD) ||
+			    (currSlice->structure == BOTTOM_FIELD)) {
+				/* check for frame store with same
+				 *   pic_number
+				 */
+				check_frame_store_same_pic_num(p_Dpb, p,
+					currSlice);
+			}
+
+			if (p_H264_Dpb->mVideo.dec_picture->buf_spec_num ==
+				-1) {
+				p_H264_Dpb->mVideo.dec_picture->buf_spec_num =
+					get_free_buf_idx(p_H264_Dpb->vdec);
+				if (p_H264_Dpb->mVideo.dec_picture->buf_spec_num
+					< 0) {
+					p_H264_Dpb->buf_alloc_fail = 1;
+					p_H264_Dpb->mVideo.dec_picture->
+						buf_spec_is_alloced = 0;
+				} else
+					p_H264_Dpb->mVideo.dec_picture->
+						buf_spec_is_alloced = 1;
+
+				if (p_H264_Dpb->mVideo.dec_picture->
+					used_for_reference) {
+					p_H264_Dpb->mVideo.dec_picture->
+						colocated_buf_index =
+						allocate_colocate_buf(
+							p_H264_Dpb);
+				}
+			}
+#endif
+			if (post_picture_early(p_H264_Dpb->vdec,
+				p_H264_Dpb->mVideo.dec_picture->buf_spec_num))
+				return -1;
+		}
+	}
+
+
+
+	if (p_H264_Dpb->mSlice.slice_type == P_SLICE)
+		init_lists_p_slice(&p_H264_Dpb->mSlice);
+	else if (p_H264_Dpb->mSlice.slice_type == B_SLICE)
+		init_lists_b_slice(&p_H264_Dpb->mSlice);
+	else
+		init_lists_i_slice(&p_H264_Dpb->mSlice);
+
+	reorder_lists(&p_H264_Dpb->mSlice);
+
+	if (p_H264_Dpb->mSlice.structure == FRAME)
+		init_mbaff_lists(p_H264_Dpb, &p_H264_Dpb->mSlice);
+
+	if (new_pic_flag)
+		return 1;
+
+	return 0;
+}
+
+enum PictureStructure get_cur_slice_picture_struct(
+	struct h264_dpb_stru *p_H264_Dpb)
+{
+	struct Slice *currSlice = &p_H264_Dpb->mSlice;
+	return currSlice->structure;
+}
+
+static unsigned char is_pic_in_dpb(struct h264_dpb_stru *p_H264_Dpb,
+	struct StorablePicture *pic)
+{
+	unsigned char ret = 0;
+	int i;
+	struct DecodedPictureBuffer *p_Dpb =
+				&p_H264_Dpb->mDPB;
+	for (i = 0; i < p_Dpb->used_size; i++) {
+		if (p_Dpb->fs[i]->top_field == pic ||
+			p_Dpb->fs[i]->bottom_field == pic ||
+			p_Dpb->fs[i]->frame == pic) {
+			ret = 1;
+			break;
+		}
+	}
+	return ret;
+}
+
+int dpb_check_ref_list_error(
+	struct h264_dpb_stru *p_H264_Dpb)
+{
+	int i;
+	/*int j;*/
+	struct Slice *currSlice = &p_H264_Dpb->mSlice;
+	/* in first output, ignore ref check */
+	if ((p_H264_Dpb->first_insert_frame == FirstInsertFrm_OUT) &&
+		(p_H264_Dpb->mVideo.dec_picture) &&
+		p_H264_Dpb->first_output_poc > p_H264_Dpb->mVideo.dec_picture->poc) {
+
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+			"p_H264_Dpb->first_output_poc %d, p_H264_Dpb->mVideo.dec_picture->poc %d\n",
+			p_H264_Dpb->first_output_poc, p_H264_Dpb->mVideo.dec_picture->poc);
+		return 0;
+	}
+	if ((currSlice->slice_type != I_SLICE) &&
+		(currSlice->slice_type != SI_SLICE)) {
+		for (i = 0; i < currSlice->listXsize[0]; i++) {
+			/*for (j = i + 1; j < currSlice->listXsize[0]; j++) {
+				if(currSlice->listX[0][i]->pic_num ==
+					currSlice->listX[0][j]->pic_num)
+					return 1;
+			}*/
+			if (currSlice->listX[0][i] == NULL)
+				return 5;
+			if (!is_pic_in_dpb(p_H264_Dpb,
+				currSlice->listX[0][i]))
+				return 1;
+			if (currSlice->listX[0][i]->frame &&
+				currSlice->listX[0][i]->frame->non_existing)
+				return 3;
+		}
+	}
+
+	if (currSlice->slice_type == B_SLICE) {
+		for (i = 0; i < currSlice->listXsize[1]; i++) {
+			/*for (j = i + 1; j < currSlice->listXsize[1]; j++) {
+				if(currSlice->listX[1][i]->pic_num ==
+					currSlice->listX[1][j]->pic_num)
+					return 2;
+			}
+			for (j = 0; j < currSlice->listXsize[0]; j++) {
+				if(currSlice->listX[1][i]->pic_num ==
+					currSlice->listX[0][j]->pic_num)
+					return 3;
+			}*/
+			if (currSlice->listX[1][i] == NULL)
+				return 6;
+			if (!is_pic_in_dpb(p_H264_Dpb,
+				currSlice->listX[1][i]))
+				return 2;
+			if (currSlice->listX[1][i]->frame &&
+				currSlice->listX[1][i]->frame->non_existing)
+				return 4;
+#if 0
+			if (currSlice->listXsize[0] == 1 &&
+				currSlice->listXsize[1] == 1 &&
+				currSlice->listX[1][0] ==
+				currSlice->listX[0][0])
+				return 3;
+#endif
+		}
+	}
+	return 0;
+}
+
diff --git a/drivers/frame_provider/decoder/h264_multi/h264_dpb.h b/drivers/frame_provider/decoder/h264_multi/h264_dpb.h
new file mode 100644
index 0000000..8b3e8bb
--- /dev/null
+++ b/drivers/frame_provider/decoder/h264_multi/h264_dpb.h
@@ -0,0 +1,1005 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* 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.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#ifndef H264_DPB_H_
+#define H264_DPB_H_
+
+#define ERROR_CHECK
+
+#define OUTPUT_BUFFER_IN_C
+
+#define PRINT_FLAG_ERROR              0x0
+#define PRINT_FLAG_VDEC_STATUS        0X0001
+#define PRINT_FLAG_UCODE_EVT          0x0002
+#define PRINT_FLAG_MMU_DETAIL		0x0004
+#define PRINT_FLAG_ERRORFLAG_DBG	0x0008
+#define PRINT_FLAG_DPB_DETAIL         0x0010
+#define PRINT_FLAG_DEC_DETAIL         0x0020
+#define PRINT_FLAG_VDEC_DETAIL        0x0040
+#define PRINT_FLAG_DUMP_DPB           0x0080
+#define PRINT_FRAMEBASE_DATA          0x0100
+#define PRINT_FLAG_DEBUG_POC          0x0200
+#define RRINT_FLAG_RPM                0x0400
+#define DEBUG_DISABLE_RUNREADY_RMBUF  0x0800
+#define PRINT_FLAG_DUMP_BUFSPEC       0x1000
+#define PRINT_FLAG_FCC_STATUS         0x2000
+#define PRINT_FLAG_SEI_DETAIL         0x4000
+#define PRINT_FLAG_V4L_DETAIL         0x8000
+#define DISABLE_ERROR_HANDLE          0x10000
+#define DEBUG_DUMP_STAT               0x80000
+#define DEBUG_TIMEOUT_DEC_STAT        0x800000
+
+/*setting canvas mode and endian.
+  if this flag is set, value of canvas mode
+  will according to the value of mem_map_mode.
+  endian will be forced set to 0 in
+  CANVAS_BLKMODE_LINEAR mode.
+  otherwise picture will display abnormal.
+  if this flag is not set, value of canvas mode
+  will be determined by the user speace config.
+  endian will be set 7 in CANVAS_BLKMODE_LINEAR mode.
+*/
+#define IGNORE_PARAM_FROM_CONFIG      0x8000000
+
+#define MVC_EXTENSION_ENABLE 0
+#define PRINTREFLIST  0
+
+#define MAX_LIST_SIZE 33
+
+#define H264_OUTPUT_MODE_NORMAL 0x4
+#define H264_OUTPUT_MODE_FAST   0x8
+
+//#define FALSE 0
+
+#define H264_SLICE_HEAD_DONE         0x01
+#define H264_PIC_DATA_DONE          0x02
+/*#define H264_SPS_DONE               0x03*/
+/*#define H264_PPS_DONE               0x04*/
+/*#define H264_SLICE_DATA_DONE        0x05*/
+/*#define H264_DATA_END               0x06*/
+
+#define H264_CONFIG_REQUEST         0x11
+#define H264_DATA_REQUEST           0x12
+#define H264_WRRSP_REQUEST          0x13
+#define H264_WRRSP_DONE             0x14
+
+#define H264_DECODE_BUFEMPTY        0x20
+#define H264_DECODE_TIMEOUT         0x21
+#define H264_SEARCH_BUFEMPTY        0x22
+#define H264_DECODE_OVER_SIZE       0x23
+
+#define VIDEO_SIGNAL_LOW						0x26
+#define VIDEO_SIGNAL_HIGHT						0x27
+
+
+#define H264_FIND_NEXT_PIC_NAL              0x50
+#define H264_FIND_NEXT_DVEL_NAL             0x51
+#define H264_AUX_DATA_READY					0x52
+
+#define H264_SEI_DATA_READY					0x53
+#define H264_SEI_DATA_DONE					0x54
+
+    /* 0x8x, search state*/
+#define H264_STATE_SEARCH_AFTER_SPS  0x80
+#define H264_STATE_SEARCH_AFTER_PPS  0x81
+#define H264_STATE_PARSE_SLICE_HEAD  0x82
+#define H264_STATE_SEARCH_HEAD       0x83
+  /**/
+#define H264_ACTION_SEARCH_HEAD     0xf0
+#define H264_ACTION_DECODE_SLICE    0xf1
+#define H264_ACTION_CONFIG_DONE     0xf2
+#define H264_ACTION_DECODE_NEWPIC   0xf3
+#define H264_ACTION_DECODE_START    0xff
+
+#define RPM_BEGIN			0x0
+#define RPM_END				0x400
+
+#define val(s) (s[0]|(s[1]<<16))
+
+#define FRAME_IN_DPB	24
+#define DPB_OFFSET		0x100
+#define MMCO_OFFSET		0x200
+union param {
+#if 0
+#define H_TIME_STAMP_START	0X00
+#define H_TIME_STAMP_END	0X17
+#define PTS_ZERO_0		0X18
+#define PTS_ZERO_1		0X19
+#endif
+#define FIXED_FRAME_RATE_FLAG                   0X21
+
+#define OFFSET_DELIMITER_LO                     0x2f
+#define OFFSET_DELIMITER_HI                     0x30
+
+
+#define SLICE_IPONLY_BREAK						0X5C
+#define PREV_MAX_REFERENCE_FRAME_NUM					0X5D
+#define EOS								0X5E
+#define FRAME_PACKING_TYPE						0X5F
+#define OLD_POC_PAR_1							0X60
+#define OLD_POC_PAR_2							0X61
+#define PREV_MBX							0X62
+#define PREV_MBY							0X63
+#define ERROR_SKIP_MB_NUM						0X64
+#define ERROR_MB_STATUS							0X65
+#define L0_PIC0_STATUS							0X66
+#define TIMEOUT_COUNTER							0X67
+#define BUFFER_SIZE							0X68
+#define BUFFER_SIZE_HI							0X69
+#define CROPPING_LEFT_RIGHT						0X6A
+#define CROPPING_TOP_BOTTOM						0X6B
+#if 1
+ /* sps_flags2:
+ *bit 3, bitstream_restriction_flag
+ *bit 2, pic_struct_present_flag
+ *bit 1, vcl_hrd_parameters_present_flag
+ *bit 0, nal_hrd_parameters_present_flag
+ */
+#define SPS_FLAGS2						0x6c
+#define NUM_REORDER_FRAMES				0x6d
+#else
+#define POC_SELECT_NEED_SWAP						0X6C
+#define POC_SELECT_SWAP							0X6D
+#endif
+#define MAX_BUFFER_FRAME						0X6E
+
+#define NON_CONFORMING_STREAM						0X70
+#define RECOVERY_POINT							0X71
+#define POST_CANVAS							0X72
+#define POST_CANVAS_H							0X73
+#define SKIP_PIC_COUNT							0X74
+#define TARGET_NUM_SCALING_LIST						0X75
+#define FF_POST_ONE_FRAME						0X76
+#define PREVIOUS_BIT_CNT						0X77
+#define MB_NOT_SHIFT_COUNT						0X78
+#define PIC_STATUS							0X79
+#define FRAME_COUNTER							0X7A
+#define NEW_SLICE_TYPE							0X7B
+#define NEW_PICTURE_STRUCTURE						0X7C
+#define NEW_FRAME_NUM							0X7D
+#define NEW_IDR_PIC_ID							0X7E
+#define IDR_PIC_ID							0X7F
+
+/* h264 LOCAL */
+#define NAL_UNIT_TYPE							0X80
+#define NAL_REF_IDC							0X81
+#define SLICE_TYPE							0X82
+#define LOG2_MAX_FRAME_NUM						0X83
+#define FRAME_MBS_ONLY_FLAG						0X84
+#define PIC_ORDER_CNT_TYPE						0X85
+#define LOG2_MAX_PIC_ORDER_CNT_LSB					0X86
+#define PIC_ORDER_PRESENT_FLAG						0X87
+#define REDUNDANT_PIC_CNT_PRESENT_FLAG					0X88
+#define PIC_INIT_QP_MINUS26						0X89
+#define DEBLOCKING_FILTER_CONTROL_PRESENT_FLAG				0X8A
+#define NUM_SLICE_GROUPS_MINUS1						0X8B
+#define MODE_8X8_FLAGS							0X8C
+#define ENTROPY_CODING_MODE_FLAG					0X8D
+#define SLICE_QUANT							0X8E
+#define TOTAL_MB_HEIGHT							0X8F
+#define PICTURE_STRUCTURE						0X90
+#define TOP_INTRA_TYPE							0X91
+#define RV_AI_STATUS							0X92
+#define AI_READ_START							0X93
+#define AI_WRITE_START							0X94
+#define AI_CUR_BUFFER							0X95
+#define AI_DMA_BUFFER							0X96
+#define AI_READ_OFFSET							0X97
+#define AI_WRITE_OFFSET							0X98
+#define AI_WRITE_OFFSET_SAVE						0X99
+#define RV_AI_BUFF_START						0X9A
+#define I_PIC_MB_COUNT							0X9B
+#define AI_WR_DCAC_DMA_CTRL						0X9C
+#define SLICE_MB_COUNT							0X9D
+#define PICTYPE								0X9E
+#define SLICE_GROUP_MAP_TYPE						0X9F
+#define MB_TYPE								0XA0
+#define MB_AFF_ADDED_DMA						0XA1
+#define PREVIOUS_MB_TYPE						0XA2
+#define WEIGHTED_PRED_FLAG						0XA3
+#define WEIGHTED_BIPRED_IDC						0XA4
+/* bit 3:2 - PICTURE_STRUCTURE
+ * bit 1 - MB_ADAPTIVE_FRAME_FIELD_FLAG
+ * bit 0 - FRAME_MBS_ONLY_FLAG
+ */
+#define MBFF_INFO							0XA5
+#define TOP_INTRA_TYPE_TOP						0XA6
+
+#define RV_AI_BUFF_INC							0xa7
+
+#define DEFAULT_MB_INFO_LO						0xa8
+
+/* 0 -- no need to read
+ * 1 -- need to wait Left
+ * 2 -- need to read Intra
+ * 3 -- need to read back MV
+ */
+#define NEED_READ_TOP_INFO						0xa9
+/* 0 -- idle
+ * 1 -- wait Left
+ * 2 -- reading top Intra
+ * 3 -- reading back MV
+ */
+#define READ_TOP_INFO_STATE						0xaa
+#define DCAC_MBX							0xab
+#define TOP_MB_INFO_OFFSET						0xac
+#define TOP_MB_INFO_RD_IDX						0xad
+#define TOP_MB_INFO_WR_IDX						0xae
+
+#define VLD_NO_WAIT     0
+#define VLD_WAIT_BUFFER 1
+#define VLD_WAIT_HOST   2
+#define VLD_WAIT_GAP	3
+
+#define VLD_WAITING							0xaf
+
+#define MB_X_NUM							0xb0
+/* #define MB_WIDTH							0xb1 */
+#define MB_HEIGHT							0xb2
+#define MBX								0xb3
+#define TOTAL_MBY							0xb4
+#define INTR_MSK_SAVE							0xb5
+
+/* #define has_time_stamp						0xb6 */
+#define NEED_DISABLE_PPE						0xb6
+#define IS_NEW_PICTURE							0XB7
+#define PREV_NAL_REF_IDC						0XB8
+#define PREV_NAL_UNIT_TYPE						0XB9
+#define FRAME_MB_COUNT							0XBA
+#define SLICE_GROUP_UCODE						0XBB
+#define SLICE_GROUP_CHANGE_RATE						0XBC
+#define SLICE_GROUP_CHANGE_CYCLE_LEN					0XBD
+#define DELAY_LENGTH							0XBE
+#define PICTURE_STRUCT							0XBF
+/* #define pre_picture_struct						0xc0 */
+#define DCAC_PREVIOUS_MB_TYPE						0xc1
+
+#define TIME_STAMP							0XC2
+#define H_TIME_STAMP							0XC3
+#define VPTS_MAP_ADDR							0XC4
+#define H_VPTS_MAP_ADDR							0XC5
+
+/*#define MAX_DPB_SIZE							0XC6*/
+#define PIC_INSERT_FLAG							0XC7
+
+#define TIME_STAMP_START						0XC8
+#define TIME_STAMP_END							0XDF
+
+#define OFFSET_FOR_NON_REF_PIC						0XE0
+#define OFFSET_FOR_TOP_TO_BOTTOM_FIELD					0XE2
+#define MAX_REFERENCE_FRAME_NUM						0XE4
+#define FRAME_NUM_GAP_ALLOWED						0XE5
+#define NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE				0XE6
+#define PROFILE_IDC_MMCO						0XE7
+#define LEVEL_IDC_MMCO							0XE8
+#define FRAME_SIZE_IN_MB						0XE9
+#define DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG				0XEA
+#define PPS_NUM_REF_IDX_L0_ACTIVE_MINUS1				0XEB
+#define PPS_NUM_REF_IDX_L1_ACTIVE_MINUS1				0XEC
+#define CURRENT_SPS_ID							0XED
+#define CURRENT_PPS_ID							0XEE
+/* bit 0 - sequence parameter set may change
+ * bit 1 - picture parameter set may change
+ * bit 2 - new dpb just inited
+ * bit 3 - IDR picture not decoded yet
+ * bit 5:4 - 0: mb level code loaded 1: picture
+ * level code loaded 2: slice level code loaded
+ */
+#define DECODE_STATUS							0XEF
+#define FIRST_MB_IN_SLICE						0XF0
+#define PREV_MB_WIDTH							0XF1
+#define PREV_FRAME_SIZE_IN_MB						0XF2
+/*#define MAX_REFERENCE_FRAME_NUM_IN_MEM		0XF3*/
+/* bit 0 - aspect_ratio_info_present_flag
+ * bit 1 - timing_info_present_flag
+ * bit 2 - nal_hrd_parameters_present_flag
+ * bit 3 - vcl_hrd_parameters_present_flag
+ * bit 4 - pic_struct_present_flag
+ * bit 5 - bitstream_restriction_flag
+ */
+#define VUI_STATUS							0XF4
+#define ASPECT_RATIO_IDC						0XF5
+#define ASPECT_RATIO_SAR_WIDTH						0XF6
+#define ASPECT_RATIO_SAR_HEIGHT						0XF7
+#define NUM_UNITS_IN_TICK						0XF8
+#define TIME_SCALE							0XFA
+#define CURRENT_PIC_INFO						0XFC
+#define DPB_BUFFER_INFO							0XFD
+#define	REFERENCE_POOL_INFO						0XFE
+#define REFERENCE_LIST_INFO						0XFF
+	struct{
+		unsigned short data[RPM_END-RPM_BEGIN];
+	} l;
+	struct{
+		unsigned short dump[DPB_OFFSET];
+		unsigned short dpb_base[FRAME_IN_DPB<<3];
+
+		unsigned short dpb_max_buffer_frame;
+		unsigned short actual_dpb_size;
+
+		unsigned short colocated_buf_status;
+
+		unsigned short num_forward_short_term_reference_pic;
+		unsigned short num_short_term_reference_pic;
+		unsigned short num_reference_pic;
+
+		unsigned short current_dpb_index;
+		unsigned short current_decoded_frame_num;
+		unsigned short current_reference_frame_num;
+
+		unsigned short l0_size;
+		unsigned short l1_size;
+
+		/* [6:5] : nal_ref_idc */
+		/* [4:0] : nal_unit_type */
+		unsigned short NAL_info_mmco;
+
+		/* [1:0] : 00 - top field, 01 - bottom field,
+		 *   10 - frame, 11 - mbaff frame
+		 */
+		unsigned short picture_structure_mmco;
+
+		unsigned short frame_num;
+		unsigned short pic_order_cnt_lsb;
+
+		unsigned short num_ref_idx_l0_active_minus1;
+		unsigned short num_ref_idx_l1_active_minus1;
+
+		unsigned short PrevPicOrderCntLsb;
+		unsigned short PreviousFrameNum;
+
+		/* 32 bits variables */
+		unsigned short delta_pic_order_cnt_bottom[2];
+		unsigned short	delta_pic_order_cnt_0[2];
+		unsigned short delta_pic_order_cnt_1[2];
+
+		unsigned short PrevPicOrderCntMsb[2];
+		unsigned short PrevFrameNumOffset[2];
+
+		unsigned short frame_pic_order_cnt[2];
+		unsigned short top_field_pic_order_cnt[2];
+		unsigned short bottom_field_pic_order_cnt[2];
+
+		unsigned short colocated_mv_addr_start[2];
+		unsigned short colocated_mv_addr_end[2];
+		unsigned short colocated_mv_wr_addr[2];
+
+		unsigned short frame_crop_left_offset;
+		unsigned short frame_crop_right_offset;
+		unsigned short frame_crop_top_offset;
+		unsigned short frame_crop_bottom_offset;
+		unsigned short chroma_format_idc;
+	} dpb;
+	struct {
+		unsigned short dump[MMCO_OFFSET];
+
+		/* array base address for offset_for_ref_frame */
+		unsigned short offset_for_ref_frame_base[128];
+
+		/* 0 - Index in DPB
+		 * 1 - Picture Flag
+		 *  [    2] : 0 - short term reference,
+		 *            1 - long term reference
+		 *  [    1] : bottom field
+		 *  [    0] : top field
+		 * 2 - Picture Number (short term or long term) low 16 bits
+		 * 3 - Picture Number (short term or long term) high 16 bits
+		 */
+		unsigned short	reference_base[128];
+
+		/* command and parameter, until command is 3 */
+		unsigned short l0_reorder_cmd[66];
+		unsigned short l1_reorder_cmd[66];
+
+		/* command and parameter, until command is 0 */
+		unsigned short mmco_cmd[44];
+
+		unsigned short l0_base[40];
+		unsigned short l1_base[40];
+	} mmco;
+	struct {
+		/* from ucode lmem, do not change this struct */
+	} p;
+};
+
+
+struct StorablePicture;
+struct VideoParameters;
+struct DecodedPictureBuffer;
+
+/* New enum for field processing */
+enum PictureStructure {
+	FRAME,
+	TOP_FIELD,
+	BOTTOM_FIELD
+};
+
+typedef enum {
+	PIC_SINGLE_FRAME = 0,
+	PIC_TOP,
+	PIC_BOT,
+	PIC_TOP_BOT,
+	PIC_BOT_TOP,
+	PIC_TOP_BOT_TOP = 5,
+	PIC_BOT_TOP_BOT,
+	PIC_DOUBLE_FRAME,
+	PIC_TRIPLE_FRAME,
+	PIC_INVALID,
+} PicStruct_E;
+
+#define I_Slice                               2
+#define P_Slice                               5
+#define B_Slice                               6
+#define P_Slice_0                             0
+#define B_Slice_1                             1
+#define I_Slice_7                             7
+
+enum SliceType {
+	P_SLICE = 0,
+	B_SLICE = 1,
+	I_SLICE = 2,
+	SP_SLICE = 3,
+	SI_SLICE = 4,
+	NUM_SLICE_TYPES = 5
+};
+
+enum ProfileIDC {
+	FREXT_CAVLC444 = 44,   /*!< YUV 4:4:4/14 "CAVLC 4:4:4"*/
+	BASELINE       = 66,   /*!< YUV 4:2:0/8  "Baseline"*/
+	MAIN           = 77,   /*!< YUV 4:2:0/8  "Main"*/
+	EXTENDED       = 88,   /*!< YUV 4:2:0/8  "Extended"*/
+	FREXT_HP       = 100,  /*!< YUV 4:2:0/8  "High"*/
+	FREXT_Hi10P    = 110,  /*!< YUV 4:2:0/10 "High 10"*/
+	FREXT_Hi422    = 122,  /*!< YUV 4:2:2/10 "High 4:2:2"*/
+	FREXT_Hi444    = 244,  /*!< YUV 4:4:4/14 "High 4:4:4"*/
+	MVC_HIGH       = 118,  /*!< YUV 4:2:0/8  "Multiview High"*/
+	STEREO_HIGH    = 128   /*!< YUV 4:2:0/8  "Stereo High"*/
+};
+
+enum FirstInsertFrm_State {
+	FirstInsertFrm_IDLE = 0,
+	FirstInsertFrm_OUT = 1,
+	FirstInsertFrm_RESET = 2,
+	FirstInsertFrm_SKIPDONE = 3,
+};
+
+
+struct SPSParameters {
+	unsigned int profile_idc;
+	unsigned int level_idc;
+	int pic_order_cnt_type;
+	int log2_max_pic_order_cnt_lsb_minus4;
+	int num_ref_frames_in_pic_order_cnt_cycle;
+	short offset_for_ref_frame[128];
+	short offset_for_non_ref_pic;
+	short offset_for_top_to_bottom_field;
+
+	/**/
+	int frame_mbs_only_flag;
+	int num_ref_frames;
+	int max_dpb_size;
+	int log2_max_frame_num_minus4;
+	int frame_num_gap_allowed;
+};
+
+#define DEC_REF_PIC_MARKING_BUFFER_NUM_MAX   45
+struct DecRefPicMarking_s {
+	int memory_management_control_operation;
+	int difference_of_pic_nums_minus1;
+	int long_term_pic_num;
+	int long_term_frame_idx;
+	int max_long_term_frame_idx_plus1;
+	struct DecRefPicMarking_s *Next;
+};
+
+#define REORDERING_COMMAND_MAX_SIZE    33
+struct Slice {
+	int first_mb_in_slice;
+	int mode_8x8_flags;
+	int picture_structure_mmco;
+
+	int frame_num;
+	int idr_flag;
+	int toppoc;
+	int bottompoc;
+	int framepoc;
+	int pic_order_cnt_lsb;
+	int PicOrderCntMsb;
+	unsigned char field_pic_flag;
+	unsigned char bottom_field_flag;
+	int ThisPOC;
+	int nal_reference_idc;
+	int AbsFrameNum;
+	int delta_pic_order_cnt_bottom;
+	int delta_pic_order_cnt[2];
+
+	/**/
+	char listXsize[6];
+	struct StorablePicture *listX[6][MAX_LIST_SIZE * 2];
+
+	/**/
+	enum PictureStructure structure;
+	int long_term_reference_flag;
+	int no_output_of_prior_pics_flag;
+	int adaptive_ref_pic_buffering_flag;
+
+	struct VideoParameters *p_Vid;
+	struct DecodedPictureBuffer *p_Dpb;
+	int num_ref_idx_active[2];    /* number of available list references */
+
+	/*modification*/
+	int slice_type;    /* slice type */
+	int ref_pic_list_reordering_flag[2];
+	int modification_of_pic_nums_idc[2][REORDERING_COMMAND_MAX_SIZE];
+	int abs_diff_pic_num_minus1[2][REORDERING_COMMAND_MAX_SIZE];
+	int long_term_pic_idx[2][REORDERING_COMMAND_MAX_SIZE];
+	/**/
+	unsigned char dec_ref_pic_marking_buffer_valid;
+	struct DecRefPicMarking_s
+		dec_ref_pic_marking_buffer[DEC_REF_PIC_MARKING_BUFFER_NUM_MAX];
+	int pic_struct;
+};
+
+struct OldSliceParams {
+	unsigned int field_pic_flag;
+	unsigned int frame_num;
+	int      nal_ref_idc;
+	unsigned int pic_oder_cnt_lsb;
+	int      delta_pic_oder_cnt_bottom;
+	int      delta_pic_order_cnt[2];
+	unsigned char     bottom_field_flag;
+	unsigned char     idr_flag;
+	int      idr_pic_id;
+	int      pps_id;
+#if (MVC_EXTENSION_ENABLE)
+	int      view_id;
+	int      inter_view_flag;
+	int      anchor_pic_flag;
+#endif
+	int      layer_id;
+};
+
+struct VideoParameters {
+	int PrevPicOrderCntMsb;
+	int PrevPicOrderCntLsb;
+	unsigned char last_has_mmco_5;
+	unsigned char last_pic_bottom_field;
+	int ThisPOC;
+	int PreviousFrameNum;
+	int FrameNumOffset;
+	int PreviousFrameNumOffset;
+	int max_frame_num;
+	unsigned int pre_frame_num;
+	int ExpectedDeltaPerPicOrderCntCycle;
+	int PicOrderCntCycleCnt;
+	int FrameNumInPicOrderCntCycle;
+	int ExpectedPicOrderCnt;
+
+	/**/
+	struct SPSParameters *active_sps;
+	struct Slice **ppSliceList;
+	int iSliceNumOfCurrPic;
+	int conceal_mode;
+	int earlier_missing_poc;
+	int pocs_in_dpb[100];
+
+	struct OldSliceParams old_slice;
+	/**/
+	struct StorablePicture *dec_picture;
+	struct StorablePicture *no_reference_picture;
+
+	/*modification*/
+	int non_conforming_stream;
+	int recovery_point;
+};
+
+static inline int imin(int a, int b)
+{
+	return ((a) < (b)) ? (a) : (b);
+}
+
+static inline int imax(int a, int b)
+{
+	return ((a) > (b)) ? (a) : (b);
+}
+
+#define MAX_PIC_BUF_NUM 128
+#define MAX_NUM_SLICES 50
+
+struct StorablePicture {
+/**/
+	int width;
+	int height;
+
+	int y_canvas_index;
+	int u_canvas_index;
+	int v_canvas_index;
+/**/
+	int index;
+	unsigned char is_used;
+
+	enum PictureStructure structure;
+
+	int         poc;
+	int         top_poc;
+	int         bottom_poc;
+	int         frame_poc;
+	unsigned int  frame_num;
+	unsigned int  recovery_frame;
+
+	int         pic_num;
+	int         buf_spec_num;
+	int         buf_spec_is_alloced;
+	int         colocated_buf_index;
+	int         long_term_pic_num;
+	int         long_term_frame_idx;
+
+	unsigned char  is_long_term;
+	int         used_for_reference;
+	int         is_output;
+#if 1
+	/* rain */
+	int         pre_output;
+#endif
+	int         non_existing;
+	int         separate_colour_plane_flag;
+
+	short       max_slice_id;
+
+	int         size_x, size_y, size_x_cr, size_y_cr;
+	int         size_x_m1, size_y_m1, size_x_cr_m1, size_y_cr_m1;
+	int         coded_frame;
+	int         mb_aff_frame_flag;
+	unsigned int PicWidthInMbs;
+	unsigned int PicSizeInMbs;
+	int         iLumaPadY, iLumaPadX;
+	int         iChromaPadY, iChromaPadX;
+
+	/* for mb aff, if frame for referencing the top field */
+	struct StorablePicture *top_field;
+	/* for mb aff, if frame for referencing the bottom field */
+	struct StorablePicture *bottom_field;
+	/* for mb aff, if field for referencing the combined frame */
+	struct StorablePicture *frame;
+
+	int         slice_type;
+	int         idr_flag;
+	int         no_output_of_prior_pics_flag;
+	int         long_term_reference_flag;
+	int         adaptive_ref_pic_buffering_flag;
+
+	int         chroma_format_idc;
+	int         frame_mbs_only_flag;
+	int         frame_cropping_flag;
+	int         frame_crop_left_offset;
+	int         frame_crop_right_offset;
+	int         frame_crop_top_offset;
+	int         frame_crop_bottom_offset;
+	int         qp;
+	int         chroma_qp_offset[2];
+	int         slice_qp_delta;
+	/* stores the memory management control operations */
+	struct DecRefPicMarking_s *dec_ref_pic_marking_buffer;
+
+	/* picture error concealment */
+	/*indicates if this is a concealed picture */
+	int         concealed_pic;
+
+	/* variables for tone mapping */
+	int         seiHasTone_mapping;
+	int         tone_mapping_model_id;
+	int         tonemapped_bit_depth;
+	/* imgpel*     tone_mapping_lut; tone mapping look up table */
+
+	int         proc_flag;
+#if (MVC_EXTENSION_ENABLE)
+	int         view_id;
+	int         inter_view_flag;
+	int         anchor_pic_flag;
+#endif
+	int         iLumaStride;
+	int         iChromaStride;
+	int         iLumaExpandedHeight;
+	int         iChromaExpandedHeight;
+	/* imgpel **cur_imgY; for more efficient get_block_luma */
+	int no_ref;
+	int iCodingType;
+
+	char listXsize[MAX_NUM_SLICES][2];
+	struct StorablePicture **listX[MAX_NUM_SLICES][2];
+	int         layer_id;
+	u32 	       offset_delimiter;
+	u32         pts;
+	u64         pts64;
+	u64         timestamp;
+	unsigned char data_flag;
+	int pic_struct;
+
+	/* picture qos infomation*/
+	int frame_size;
+	int max_qp;
+	int avg_qp;
+	int min_qp;
+	int max_skip;
+	int avg_skip;
+	int min_skip;
+	int max_mv;
+	int min_mv;
+	int avg_mv;
+	u32 pic_size;
+};
+
+struct FrameStore {
+	/* rain */
+	int      buf_spec_num;
+	/* rain */
+	int      colocated_buf_index;
+
+	/* 0=empty; 1=top; 2=bottom; 3=both fields (or frame) */
+	int       is_used;
+	/* 0=not used for ref; 1=top used; 2=bottom used;
+	 * 3=both fields (or frame) used
+	 */
+	int       is_reference;
+	/* 0=not used for ref; 1=top used; 2=bottom used;
+	 * 3=both fields (or frame) used
+	 */
+	int       is_long_term;
+	/* original marking by nal_ref_idc: 0=not used for ref; 1=top used;
+	 * 2=bottom used; 3=both fields (or frame) used
+	 */
+	int       is_orig_reference;
+
+	int       is_non_existent;
+
+	unsigned int frame_num;
+	unsigned int recovery_frame;
+
+	int       frame_num_wrap;
+	int       long_term_frame_idx;
+	int       is_output;
+#if 1
+	/* rain */
+	int         pre_output;
+	/* index in gFrameStore */
+	int       index;
+#define I_FLAG			0x01
+#define IDR_FLAG		0x02
+#define ERROR_FLAG		0x10
+#define NULL_FLAG		0x20
+#define NODISP_FLAG		0x80
+	unsigned char data_flag;
+#endif
+	int       poc;
+
+	/* picture error concealment */
+	int concealment_reference;
+
+	struct StorablePicture *frame;
+	struct StorablePicture *top_field;
+	struct StorablePicture *bottom_field;
+
+#if (MVC_EXTENSION_ENABLE)
+	int       view_id;
+	int       inter_view_flag[2];
+	int       anchor_pic_flag[2];
+#endif
+	int       layer_id;
+	u32 	  offset_delimiter;
+	u32       pts;
+	u64       pts64;
+	u64       timestamp;
+
+
+	/* picture qos infomation*/
+	int slice_type;
+	int frame_size;
+
+	int max_qp;
+	int avg_qp;
+	int min_qp;
+	int max_skip;
+	int avg_skip;
+	int min_skip;
+	int max_mv;
+	int min_mv;
+	int avg_mv;
+	int dpb_frame_count;
+	u32 hw_decode_time;
+	u32 frame_size2; // For recording the chunk->size in frame mode
+	bool show_frame;
+	struct dma_fence *fence;
+	u32 decoded_frame_size;
+};
+
+/* #define DPB_SIZE_MAX     16 */
+#define DPB_SIZE_MAX     32
+struct DecodedPictureBuffer {
+	struct VideoParameters *p_Vid;
+	/* InputParameters *p_Inp; ??? */
+	struct FrameStore  *fs[DPB_SIZE_MAX];
+	struct FrameStore  *fs_ref[DPB_SIZE_MAX];
+	struct FrameStore  *fs_ltref[DPB_SIZE_MAX];
+	/* inter-layer reference (for multi-layered codecs) */
+	struct FrameStore  *fs_ilref[DPB_SIZE_MAX];
+	/**/
+	struct FrameStore *fs_list0[DPB_SIZE_MAX];
+	struct FrameStore *fs_list1[DPB_SIZE_MAX];
+	struct FrameStore *fs_listlt[DPB_SIZE_MAX];
+
+	/**/
+	unsigned int size;
+	unsigned int used_size;
+	unsigned int ref_frames_in_buffer;
+	unsigned int ltref_frames_in_buffer;
+	int           last_output_poc;
+#if (MVC_EXTENSION_ENABLE)
+	int           last_output_view_id;
+#endif
+	int           max_long_term_pic_idx;
+
+
+	int           init_done;
+	int           first_pic_done; /*by rain*/
+	int           num_ref_frames;
+
+	struct FrameStore   *last_picture;
+	unsigned int used_size_il;
+	int          layer_id;
+
+	/* DPB related function; */
+};
+
+struct h264_dpb_stru {
+	struct vdec_s *vdec;
+	int decoder_index;
+
+	union param dpb_param;
+
+	int decode_idx;
+	int buf_num;
+	int curr_POC;
+	int reorder_pic_num;
+	unsigned int dec_dpb_size;
+	u8 fast_output_enable;
+		/*poc_even_flag:
+		 0, init; 1, odd; 2, even*/
+	u8 poc_even_odd_flag;
+	u32 decode_pic_count;
+	/**/
+	unsigned int max_reference_size;
+
+	unsigned int colocated_buf_map;
+	unsigned int colocated_buf_count;
+	unsigned int colocated_mv_addr_start;
+	unsigned int colocated_mv_addr_end;
+	unsigned int colocated_buf_size;
+
+	struct DecodedPictureBuffer mDPB;
+	struct Slice mSlice;
+	struct VideoParameters mVideo;
+	struct SPSParameters mSPS;
+
+	struct StorablePicture m_PIC[MAX_PIC_BUF_NUM];
+	struct FrameStore mFrameStore[DPB_SIZE_MAX];
+
+	/*vui*/
+	unsigned int vui_status;
+	unsigned int num_units_in_tick;
+	unsigned int time_scale;
+	unsigned int fixed_frame_rate_flag;
+	unsigned int aspect_ratio_idc;
+	unsigned int aspect_ratio_sar_width;
+	unsigned int aspect_ratio_sar_height;
+	u8 bitstream_restriction_flag;
+	u16 num_reorder_frames;
+	u16 max_dec_frame_buffering;
+
+	unsigned int frame_crop_left_offset;
+	unsigned int frame_crop_right_offset;
+	unsigned int frame_crop_top_offset;
+	unsigned int frame_crop_bottom_offset;
+	unsigned int chroma_format_idc;
+
+	unsigned int dec_dpb_status;
+	unsigned int last_dpb_status;
+	unsigned char buf_alloc_fail;
+	unsigned int dpb_error_flag;
+	unsigned int reorder_output;
+	unsigned int first_insert_frame;
+	int first_output_poc;
+	int dpb_frame_count;
+	u32 without_display_mode;
+	int long_term_reference_flag;
+};
+
+
+extern unsigned int h264_debug_flag;
+extern unsigned int h264_debug_mask;
+
+int dpb_print(int indext, int debug_flag, const char *fmt, ...);
+
+int dpb_print_cont(int index, int debug_flag, const char *fmt, ...);
+
+unsigned char dpb_is_debug(int index, int debug_flag);
+
+int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame);
+
+int release_buf_spec_num(struct vdec_s *vdec, int buf_spec_num);
+
+void set_frame_output_flag(struct h264_dpb_stru *p_H264_Dpb, int index);
+
+int is_there_unused_frame_from_dpb(struct DecodedPictureBuffer *p_Dpb);
+
+int h264_slice_header_process(struct h264_dpb_stru *p_H264_Dpb, int *frame_num_gap);
+
+void dpb_init_global(struct h264_dpb_stru *p_H264_Dpb,
+	int id, int actual_dpb_size, int max_reference_size);
+
+void init_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int count);
+
+int release_colocate_buf(struct h264_dpb_stru *p_H264_Dpb, int index);
+
+int get_free_buf_idx(struct vdec_s *vdec);
+
+int store_picture_in_dpb(struct h264_dpb_stru *p_H264_Dpb,
+			struct StorablePicture *p, unsigned char data_flag);
+
+int release_picture(struct h264_dpb_stru *p_H264_Dpb,
+			struct StorablePicture *pic);
+
+void remove_dpb_pictures(struct h264_dpb_stru *p_H264_Dpb);
+
+void bufmgr_post(struct h264_dpb_stru *p_H264_Dpb);
+
+void bufmgr_force_recover(struct h264_dpb_stru *p_H264_Dpb);
+
+int get_long_term_flag_by_buf_spec_num(struct h264_dpb_stru *p_H264_Dpb,
+	int buf_spec_num);
+
+void bufmgr_h264_remove_unused_frame(struct h264_dpb_stru *p_H264_Dpb,
+	u8 force_flag);
+
+void flush_dpb(struct h264_dpb_stru *p_H264_Dpb);
+
+void print_pic_info(int decindex, const char *info,
+			struct StorablePicture *pic,
+			int slice_type);
+void dump_dpb(struct DecodedPictureBuffer *p_Dpb, u8 force);
+
+void dump_pic(struct h264_dpb_stru *p_H264_Dpb);
+
+void * vh264_get_bufspec_lock(struct vdec_s *vdec);
+
+enum PictureStructure get_cur_slice_picture_struct(
+	struct h264_dpb_stru *p_H264_Dpb);
+
+int dpb_check_ref_list_error(
+	struct h264_dpb_stru *p_H264_Dpb);
+
+void unmark_for_reference(struct DecodedPictureBuffer *p_Dpb,
+	struct FrameStore *fs);
+
+void update_ref_list(struct DecodedPictureBuffer *p_Dpb);
+
+int post_picture_early(struct vdec_s *vdec, int index);
+
+int is_used_for_reference(struct FrameStore *fs);
+
+#endif
diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c
new file mode 100644
index 0000000..5932c91
--- /dev/null
+++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c
@@ -0,0 +1,11272 @@
+/*
+ * drivers/amlogic/amports/vh264.c
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+#define DEBUG
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/kfifo.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/media/frame_sync/tsync.h>
+#include <linux/workqueue.h>
+#include <linux/dma-mapping.h>
+#include <linux/atomic.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
+#include "../../../stream_input/amports/amports_priv.h"
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include "../utils/vdec_input.h"
+//#include <linux/amlogic/tee.h>
+#include <uapi/linux/tee.h>
+#include <linux/sched/clock.h>
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../utils/vdec.h"
+#include "../utils/amvdec.h"
+#include "../h264/vh264.h"
+#include "../../../stream_input/amports/streambuf.h"
+#include <linux/delay.h>
+#include <linux/amlogic/media/codec_mm/configs.h>
+#include "../utils/decoder_mmu_box.h"
+#include "../utils/decoder_bmmu_box.h"
+#include "../utils/firmware.h"
+#include <linux/uaccess.h>
+#include "../utils/config_parser.h"
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+#include "../utils/vdec_v4l2_buffer_ops.h"
+#include <linux/crc32.h>
+#include <media/v4l2-mem2mem.h>
+#include "../utils/vdec_feature.h"
+
+
+#define DETECT_WRONG_MULTI_SLICE
+
+/*
+to enable DV of frame mode
+#define DOLBY_META_SUPPORT in ucode
+*/
+
+#undef pr_info
+#define pr_info printk
+#define VDEC_DW
+#define DEBUG_UCODE
+#define MEM_NAME "codec_m264"
+#define MULTI_INSTANCE_FRAMEWORK
+/* #define ONE_COLOCATE_BUF_PER_DECODE_BUF */
+#include "h264_dpb.h"
+/* #define SEND_PARAM_WITH_REG */
+
+#define DRIVER_NAME "ammvdec_h264"
+#define DRIVER_HEADER_NAME "ammvdec_h264_header"
+
+#define CHECK_INTERVAL        (HZ/100)
+
+#define SEI_DATA_SIZE			(8*1024)
+#define SEI_ITU_DATA_SIZE		(4*1024)
+
+#define RATE_MEASURE_NUM 8
+#define RATE_CORRECTION_THRESHOLD 5
+#define RATE_2397_FPS  4004   /* 23.97 */
+#define RATE_25_FPS  3840   /* 25 */
+#define RATE_2997_FPS  3203   /* 29.97 */
+#define DUR2PTS(x) ((x)*90/96)
+#define PTS2DUR(x) ((x)*96/90)
+#define DUR2PTS_REM(x) (x*90 - DUR2PTS(x)*96)
+#define FIX_FRAME_RATE_CHECK_IFRAME_NUM 2
+
+#define FIX_FRAME_RATE_OFF                0
+#define FIX_FRAME_RATE_ON                 1
+#define FIX_FRAME_RATE_SMOOTH_CHECKING    2
+
+#define DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE 0x0001
+#define DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE  0x0002
+#define DEC_CONTROL_FLAG_FORCE_RATE_2397_FPS_FIX_FRAME_RATE  0x0010
+#define DEC_CONTROL_FLAG_FORCE_RATE_2997_FPS_FIX_FRAME_RATE  0x0020
+
+#define DECODE_ID(hw) (hw_to_vdec(hw)->id)
+
+#define RATE_MEASURE_NUM 8
+#define RATE_CORRECTION_THRESHOLD 5
+#define RATE_24_FPS  4004	/* 23.97 */
+#define RATE_25_FPS  3840	/* 25 */
+#define DUR2PTS(x) ((x)*90/96)
+#define PTS2DUR(x) ((x)*96/90)
+#define DUR2PTS_REM(x) (x*90 - DUR2PTS(x)*96)
+#define FIX_FRAME_RATE_CHECK_IDRFRAME_NUM 2
+
+#define ALIGN_WIDTH(x) (ALIGN((x), 64))
+#define ALIGN_HEIGHT(x) (ALIGN((x), 32))
+
+#define H264_DEV_NUM        9
+
+#define CONSTRAIN_MAX_BUF_NUM
+
+#define H264_MMU
+#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK	0x20000000
+#define INVALID_IDX -1  /* Invalid buffer index.*/
+
+static int mmu_enable;
+/*mmu do not support mbaff*/
+static int force_enable_mmu = 0;
+unsigned int h264_debug_flag; /* 0xa0000000; */
+unsigned int h264_debug_mask = 0xff;
+	/*
+	 *h264_debug_cmd:
+	 *	0x1xx, force decoder id of xx to be disconnected
+	 */
+unsigned int h264_debug_cmd;
+
+static int ref_b_frame_error_max_count = 50;
+
+static unsigned int dec_control =
+	DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE |
+	DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE;
+
+static unsigned int force_rate_streambase;
+static unsigned int force_rate_framebase;
+static unsigned int force_disp_bufspec_num;
+static unsigned int fixed_frame_rate_mode;
+static unsigned int error_recovery_mode_in;
+static int start_decode_buf_level = 0x4000;
+static int pre_decode_buf_level = 0x1000;
+static int stream_mode_start_num = 4;
+static int dirty_again_threshold = 100;
+static unsigned int colocate_old_cal;
+
+
+static int check_dirty_data(struct vdec_s *vdec);
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+/*to make reorder size difference of bl and el not too big*/
+static unsigned int reorder_dpb_size_margin_dv = 16;
+#endif
+static unsigned int reorder_dpb_size_margin = 6;
+static unsigned int reference_buf_margin = 4;
+
+#ifdef CONSTRAIN_MAX_BUF_NUM
+static u32 run_ready_max_vf_only_num;
+static u32 run_ready_display_q_num;
+	/*0: not check
+	  0xff: mDPB.size
+	  */
+static u32 run_ready_max_buf_num = 0xff;
+#endif
+
+static u32 run_ready_min_buf_num = 2;
+
+#define VDEC_ASSIST_CANVAS_BLK32		0x5
+
+
+static unsigned int max_alloc_buf_count;
+static unsigned int decode_timeout_val = 100;
+static unsigned int errordata_timeout_val = 50;
+static unsigned int get_data_timeout_val = 2000;
+#if 1
+/* H264_DATA_REQUEST does not work, disable it,
+decode has error for data in none continuous address
+*/
+static unsigned int frame_max_data_packet;
+#else
+static unsigned int frame_max_data_packet = 8;
+#endif
+static unsigned int radr;
+static unsigned int rval;
+static u32 endian = 0xff0;
+
+/*
+	udebug_flag:
+	bit 0, enable ucode print
+	bit 1, enable ucode detail print
+	bit 3, disable ucode watchdog
+	bit [31:16] not 0, pos to dump lmem
+		bit 2, pop bits to lmem
+		bit [11:8], pre-pop bits for alignment (when bit 2 is 1)
+*/
+static u32 udebug_flag;
+/*
+	when udebug_flag[1:0] is not 0
+	udebug_pause_pos not 0,
+		pause position
+*/
+static u32 udebug_pause_pos;
+/*
+	when udebug_flag[1:0] is not 0
+	and udebug_pause_pos is not 0,
+		pause only when DEBUG_REG2 is equal to this val
+*/
+static u32 udebug_pause_val;
+
+static u32 udebug_pause_decode_idx;
+
+static unsigned int disp_vframe_valve_level;
+
+static unsigned int max_decode_instance_num = H264_DEV_NUM;
+static unsigned int decode_frame_count[H264_DEV_NUM];
+static unsigned int display_frame_count[H264_DEV_NUM];
+static unsigned int max_process_time[H264_DEV_NUM];
+static unsigned int max_get_frame_interval[H264_DEV_NUM];
+static unsigned int run_count[H264_DEV_NUM];
+static unsigned int input_empty[H264_DEV_NUM];
+static unsigned int not_run_ready[H264_DEV_NUM];
+static unsigned int ref_frame_mark_flag[H264_DEV_NUM] =
+{1, 1, 1, 1, 1, 1, 1, 1, 1};
+
+#define VDEC_CLOCK_ADJUST_FRAME 30
+static unsigned int clk_adj_frame_count;
+
+/*
+ *bit[3:0]: 0, run ; 1, pause; 3, step
+ *bit[4]: 1, schedule run
+ */
+static unsigned int step[H264_DEV_NUM];
+
+#define AUX_BUF_ALIGN(adr) ((adr + 0xf) & (~0xf))
+static u32 prefix_aux_buf_size = (16 * 1024);
+static u32 suffix_aux_buf_size;
+
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+static u32 dv_toggle_prov_name;
+
+static u32 dolby_meta_with_el;
+#endif
+
+/*
+	bit[8]
+		0: use sys_info[bit 3]
+		not 0:use i_only_flag[7:0]
+			bit[7:0]:
+				bit 0, 1: only display I picture;
+				bit 1, 1: only decode I picture;
+*/
+static unsigned int i_only_flag;
+
+/*
+	error_proc_policy:
+	bit[0] send_error_frame_flag;
+		(valid when bit[31] is 1, otherwise use sysinfo)
+	bit[1] do not decode if config_decode_buf() fail
+	bit[2] force release buf if in deadlock
+	bit[3] force sliding window ref_frames_in_buffer > num_ref_frames
+	bit[4] check inactive of receiver
+	bit[5] reset buffmgr if in deadlock
+	bit[6] reset buffmgr if bufspec, collocate buf, pic alloc fail
+	bit[7] reset buffmgr if dpb error
+
+	bit[8] check total mbx/mby of decoded frame
+	bit[9] check ERROR_STATUS_REG
+	bit[10] check reference list
+	bit[11] mark error if dpb error
+	bit[12] i_only when error happen
+	bit[13] 0: mark error according to last pic, 1: ignore mark error
+	bit[14] 0: result done when timeout from ucode. 1: reset bufmgr when timeout.
+	bit[15] 1: dpb_frame_count If the dpb_frame_count difference is large, it moves out of the DPB buffer.
+	bit[16] 1: check slice header number.
+	bit[17] 1: If the decoded Mb count is insufficient but greater than the threshold, it is considered the correct frame.
+	bit[18] 1: time out status, store pic to dpb buffer.
+	bit[19] 1: If a lot b frames are wrong consecutively, the DPB queue reset.
+	bit[20] 1: fixed some error stream will lead to the diffusion of the error, resulting playback stuck.
+	bit[21] 1: fixed DVB loop playback cause jetter issue.
+	bit[22] 1: In streaming mode, support for discarding data.
+	bit[23] 0: set error flag on frame number gap error and drop it, 1: ignore error.
+*/
+static unsigned int error_proc_policy = 0x7fCfb6; /*0x1f14*/
+
+
+/*
+	error_skip_count:
+	bit[11:0] error skip frame count
+	bit[15:12] error skip i picture count
+*/
+static unsigned int error_skip_count = (0x2 << 12) | 0x40;
+
+static unsigned int force_sliding_margin;
+/*
+	bit[1:0]:
+	0, start playing from any frame
+	1, start playing from I frame
+		bit[15:8]: the count of skip frames after first I
+	2, start playing from second I frame (decode from the first I)
+		bit[15:8]: the max count of skip frames after first I
+	3, start playing from IDR
+*/
+static unsigned int first_i_policy = 1;
+
+/*
+	fast_output_enable:
+	bit [0], output frame if there is IDR in list
+	bit [1], output frame if the current poc is 1 big than the previous poc
+	bit [2], if even poc only, output frame ifthe cuurent poc
+			is 2 big than the previous poc
+	bit [3],  ip only
+*/
+static unsigned int fast_output_enable = H264_OUTPUT_MODE_NORMAL;
+
+static unsigned int enable_itu_t35 = 1;
+
+static unsigned int frmbase_cont_bitlevel = 0x40;
+
+static unsigned int frmbase_cont_bitlevel2 = 0x1;
+
+static unsigned int check_slice_num = 30;
+
+static unsigned int mb_count_threshold = 5; /*percentage*/
+
+#define MH264_USERDATA_ENABLE
+
+/* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */
+/* hevc->double_write_mode:
+	0, no double write
+	1, 1:1 ratio
+	2, (1/4):(1/4) ratio
+	3, (1/4):(1/4) ratio, with both compressed frame included
+	4, (1/2):(1/2) ratio
+	0x10, double write only
+	0x10000: vdec dw horizotal 1/2
+	0x20000: vdec dw horizotal/vertical  1/2
+*/
+static u32 double_write_mode;
+static u32 without_display_mode;
+
+static int loop_playback_poc_threshold = 400;
+static int poc_threshold = 50;
+
+static u32 lookup_check_conut = 30;
+
+
+/*
+ *[3:0] 0: default use config from omx.
+ *      1: force enable fence.
+ *      2: disable fence.
+ *[7:4] 0: fence use for driver.
+ *      1: fence fd use for app.
+ */
+static u32 force_config_fence;
+
+#define IS_VDEC_DW(hw)  (hw->double_write_mode >> 16 & 0xf)
+
+static void vmh264_dump_state(struct vdec_s *vdec);
+
+#define is_in_parsing_state(status) \
+		((status == H264_ACTION_SEARCH_HEAD) || \
+			((status & 0xf0) == 0x80))
+
+#define is_interlace(frame)	\
+			((frame->frame &&\
+			frame->top_field &&\
+			frame->bottom_field &&\
+			(!frame->frame->coded_frame)) || \
+			(frame->frame && \
+			 frame->frame->coded_frame && \
+			 (!frame->frame->frame_mbs_only_flag) && \
+			 frame->frame->structure == FRAME))
+
+static inline bool close_to(int a, int b, int m)
+{
+	return (abs(a - b) < m) ? true : false;
+}
+
+#if 0
+#define h264_alloc_hw_stru(dev, size, opt) devm_kzalloc(dev, size, opt)
+#define h264_free_hw_stru(dev, hw) devm_kfree(dev, hw)
+#else
+#define h264_alloc_hw_stru(dev, size, opt) vzalloc(size)
+#define h264_free_hw_stru(dev, hw) vfree(hw)
+#endif
+
+/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
+#define NV21
+/* #endif */
+
+/* 12M for L41 */
+#define MAX_DPB_BUFF_SIZE       (12*1024*1024)
+#define DEFAULT_MEM_SIZE        (32*1024*1024)
+#define AVIL_DPB_BUFF_SIZE      0x01ec2000
+
+#define DEF_BUF_START_ADDR			0x00000000
+#define mem_sps_base				0x01c3c00
+#define mem_pps_base				0x01cbc00
+/*#define V_BUF_ADDR_OFFSET             (0x13e000)*/
+u32 V_BUF_ADDR_OFFSET = 0x200000;
+#define DCAC_READ_MARGIN	(64 * 1024)
+
+
+#define EXTEND_SAR                      0xff
+#define BUFSPEC_POOL_SIZE		64
+#define VF_POOL_SIZE        64
+#define VF_POOL_NUM			2
+#define MAX_VF_BUF_NUM          27
+#define BMMU_MAX_BUFFERS	(BUFSPEC_POOL_SIZE + 3)
+#define BMMU_REF_IDX	(BUFSPEC_POOL_SIZE)
+#define BMMU_DPB_IDX	(BUFSPEC_POOL_SIZE + 1)
+#define BMMU_EXTIF_IDX	(BUFSPEC_POOL_SIZE + 2)
+#define EXTIF_BUF_SIZE   (0x10000 * 2)
+
+#define HEADER_BUFFER_IDX(n) (n)
+#define VF_BUFFER_IDX(n)	(n)
+
+
+#define PUT_INTERVAL        (HZ/100)
+#define NO_DISP_WD_COUNT    (3 * HZ / PUT_INTERVAL)
+
+#define MMU_MAX_BUFFERS	BUFSPEC_POOL_SIZE
+#define SWITCHING_STATE_OFF       0
+#define SWITCHING_STATE_ON_CMD3   1
+#define SWITCHING_STATE_ON_CMD1   2
+
+
+
+#define INCPTR(p) ptr_atomic_wrap_inc(&p)
+
+#define SLICE_TYPE_I 2
+#define SLICE_TYPE_P 5
+#define SLICE_TYPE_B 6
+
+struct buffer_spec_s {
+	/*
+	used:
+	-1, none allocated
+	0, allocated, free
+	1, used by dpb
+	2, in disp queue;
+	3, in disp queue, isolated,
+		do not use for dpb when vf_put;
+	4, to release
+	5, in disp queue, isolated (but not to release)
+		do not use for dpb when vf_put;
+	*/
+	unsigned int used;
+	unsigned int info0;
+	unsigned int info1;
+	unsigned int info2;
+	unsigned int y_addr;
+	unsigned int u_addr;
+	unsigned int v_addr;
+
+	int y_canvas_index;
+	int u_canvas_index;
+	int v_canvas_index;
+
+#ifdef VDEC_DW
+	unsigned int vdec_dw_y_addr;
+	unsigned int vdec_dw_u_addr;
+	unsigned int vdec_dw_v_addr;
+
+	int vdec_dw_y_canvas_index;
+	int vdec_dw_u_canvas_index;
+	int vdec_dw_v_canvas_index;
+#ifdef NV21
+	struct canvas_config_s vdec_dw_canvas_config[2];
+#else
+	struct canvas_config_s vdec_dw_canvas_config[3];
+#endif
+#endif
+
+#ifdef NV21
+	struct canvas_config_s canvas_config[2];
+#else
+	struct canvas_config_s canvas_config[3];
+#endif
+	unsigned long cma_alloc_addr;
+	unsigned int buf_adr;
+#ifdef	H264_MMU
+	unsigned long alloc_header_addr;
+#endif
+	char *aux_data_buf;
+	int aux_data_size;
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	unsigned char dv_enhance_exist;
+#endif
+	int canvas_pos;
+	int vf_ref;
+	/*unsigned int comp_body_size;*/
+	unsigned int dw_y_adr;
+	unsigned int dw_u_v_adr;
+	int fs_idx;
+};
+
+#define AUX_DATA_SIZE(pic) (hw->buffer_spec[pic->buf_spec_num].aux_data_size)
+#define AUX_DATA_BUF(pic) (hw->buffer_spec[pic->buf_spec_num].aux_data_buf)
+#define DEL_EXIST(h, p) (h->buffer_spec[p->buf_spec_num].dv_enhance_exist)
+
+
+#define vdec_dw_spec2canvas(x)  \
+	(((x)->vdec_dw_v_canvas_index << 16) | \
+	 ((x)->vdec_dw_u_canvas_index << 8)  | \
+	 ((x)->vdec_dw_y_canvas_index << 0))
+
+
+#define spec2canvas(x)  \
+	(((x)->v_canvas_index << 16) | \
+	 ((x)->u_canvas_index << 8)  | \
+	 ((x)->y_canvas_index << 0))
+
+#define FRAME_INDEX(vf_index) (vf_index & 0xff)
+#define BUFSPEC_INDEX(vf_index) ((vf_index >> 8) & 0xff)
+#define VF_INDEX(frm_idx, bufspec_idx) (frm_idx | (bufspec_idx << 8))
+
+static struct vframe_s *vh264_vf_peek(void *);
+static struct vframe_s *vh264_vf_get(void *);
+static void vh264_vf_put(struct vframe_s *, void *);
+static int vh264_vf_states(struct vframe_states *states, void *);
+static int vh264_event_cb(int type, void *data, void *private_data);
+static void vh264_work(struct work_struct *work);
+static void vh264_timeout_work(struct work_struct *work);
+static void vh264_notify_work(struct work_struct *work);
+#ifdef MH264_USERDATA_ENABLE
+static void user_data_ready_notify_work(struct work_struct *work);
+static void vmh264_wakeup_userdata_poll(struct vdec_s *vdec);
+#endif
+
+static const char vh264_dec_id[] = "vh264-dev";
+
+#define PROVIDER_NAME "vdec.h264"
+
+static const struct vframe_operations_s vf_provider_ops = {
+	.peek = vh264_vf_peek,
+	.get = vh264_vf_get,
+	.put = vh264_vf_put,
+	.event_cb = vh264_event_cb,
+	.vf_states = vh264_vf_states,
+};
+
+#define DEC_RESULT_NONE             0
+#define DEC_RESULT_DONE             1
+#define DEC_RESULT_AGAIN            2
+#define DEC_RESULT_CONFIG_PARAM     3
+#define DEC_RESULT_GET_DATA         4
+#define DEC_RESULT_GET_DATA_RETRY   5
+#define DEC_RESULT_ERROR            6
+#define DEC_RESULT_EOS              7
+#define DEC_RESULT_FORCE_EXIT       8
+#define DEC_RESULT_TIMEOUT			9
+
+
+/*
+ *static const char *dec_result_str[] = {
+ *    "DEC_RESULT_NONE        ",
+ *    "DEC_RESULT_DONE        ",
+ *    "DEC_RESULT_AGAIN       ",
+ *    "DEC_RESULT_CONFIG_PARAM",
+ *    "DEC_RESULT_GET_DATA    ",
+ *    "DEC_RESULT_GET_DA_RETRY",
+ *    "DEC_RESULT_ERROR       ",
+ *};
+ */
+
+#define UCODE_IP_ONLY 2
+#define UCODE_IP_ONLY_PARAM 1
+
+#define MC_OFFSET_HEADER    0x0000
+#define MC_OFFSET_DATA      0x1000
+#define MC_OFFSET_MMCO      0x2000
+#define MC_OFFSET_LIST      0x3000
+#define MC_OFFSET_SLICE     0x4000
+#define MC_OFFSET_MAIN      0x5000
+
+#define MC_TOTAL_SIZE       ((20+16)*SZ_1K)
+#define MC_SWAP_SIZE        (4*SZ_1K)
+#define MODE_ERROR 0
+#define MODE_FULL  1
+
+#define DFS_HIGH_THEASHOLD 3
+
+#define INIT_FLAG_REG       AV_SCRATCH_2
+#define HEAD_PADING_REG     AV_SCRATCH_3
+#define UCODE_WATCHDOG_REG   AV_SCRATCH_7
+#define LMEM_DUMP_ADR       AV_SCRATCH_L
+#define DEBUG_REG1          AV_SCRATCH_M
+#define DEBUG_REG2          AV_SCRATCH_N
+#define FRAME_COUNTER_REG       AV_SCRATCH_I
+#define RPM_CMD_REG          AV_SCRATCH_A
+#define H264_DECODE_SIZE	AV_SCRATCH_E
+#define H264_DECODE_MODE    AV_SCRATCH_4
+#define H264_DECODE_SEQINFO	AV_SCRATCH_5
+#define H264_AUX_ADR            AV_SCRATCH_C
+#define H264_AUX_DATA_SIZE      AV_SCRATCH_H
+
+#define H264_DECODE_INFO          M4_CONTROL_REG /* 0xc29 */
+#define DPB_STATUS_REG       AV_SCRATCH_J
+#define ERROR_STATUS_REG	AV_SCRATCH_9
+	/*
+	NAL_SEARCH_CTL: bit 0, enable itu_t35
+	NAL_SEARCH_CTL: bit 1, enable mmu
+	NAL_SEARCH_CTL: bit 2, detect frame_mbs_only_flag whether switch resolution
+	NAL_SEARCH_CTL: bit 15,bitstream_restriction_flag
+	*/
+#define NAL_SEARCH_CTL		AV_SCRATCH_9
+#define MBY_MBX                 MB_MOTION_MODE /*0xc07*/
+
+#define DECODE_MODE_SINGLE					0x0
+#define DECODE_MODE_MULTI_FRAMEBASE			0x1
+#define DECODE_MODE_MULTI_STREAMBASE		0x2
+#define DECODE_MODE_MULTI_DVBAL				0x3
+#define DECODE_MODE_MULTI_DVENL				0x4
+static DEFINE_MUTEX(vmh264_mutex);
+
+#ifdef MH264_USERDATA_ENABLE
+
+struct mh264_userdata_record_t {
+	struct userdata_meta_info_t meta_info;
+	u32 rec_start;
+	u32 rec_len;
+};
+
+struct mh264_ud_record_wait_node_t {
+	struct list_head list;
+	struct mh264_userdata_record_t ud_record;
+};
+#define USERDATA_FIFO_NUM    256
+#define MAX_FREE_USERDATA_NODES		5
+
+struct mh264_userdata_info_t {
+	struct mh264_userdata_record_t records[USERDATA_FIFO_NUM];
+	u8 *data_buf;
+	u8 *data_buf_end;
+	u32 buf_len;
+	u32 read_index;
+	u32 write_index;
+	u32 last_wp;
+};
+
+
+#endif
+
+struct mh264_fence_vf_t {
+	u32 used_size;
+	struct vframe_s *fence_vf[VF_POOL_SIZE];
+};
+
+struct vdec_h264_hw_s {
+	spinlock_t lock;
+	spinlock_t bufspec_lock;
+	int id;
+	struct platform_device *platform_dev;
+	unsigned long cma_alloc_addr;
+	/* struct page *collocate_cma_alloc_pages; */
+	unsigned long collocate_cma_alloc_addr;
+
+	u32 prefix_aux_size;
+	u32 suffix_aux_size;
+	void *aux_addr;
+	dma_addr_t aux_phy_addr;
+
+	/* buffer for store all sei data */
+	void *sei_data_buf;
+	u32	sei_data_len;
+
+	/* buffer for storing one itu35 recored */
+	void *sei_itu_data_buf;
+	u32 sei_itu_data_len;
+
+	/* recycle buffer for user data storing all itu35 records */
+	void *sei_user_data_buffer;
+	u32 sei_user_data_wp;
+#ifdef MH264_USERDATA_ENABLE
+	struct work_struct user_data_ready_work;
+#endif
+	struct StorablePicture *last_dec_picture;
+
+	ulong lmem_phy_addr;
+	dma_addr_t lmem_addr;
+
+	void *bmmu_box;
+#ifdef H264_MMU
+	void *mmu_box;
+	void *frame_mmu_map_addr;
+	dma_addr_t frame_mmu_map_phy_addr;
+	u32	 hevc_cur_buf_idx;
+	u32 losless_comp_body_size;
+	u32 losless_comp_body_size_sao;
+	u32 losless_comp_header_size;
+	u32 mc_buffer_size_u_v;
+	u32 mc_buffer_size_u_v_h;
+	u32  is_idr_frame;
+	u32  is_new_pic;
+	u32  frame_done;
+	u32  frame_busy;
+	unsigned long extif_addr;
+	int double_write_mode;
+	int mmu_enable;
+#endif
+
+	DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE);
+	DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE);
+
+	int cur_pool;
+	struct vframe_s vfpool[VF_POOL_NUM][VF_POOL_SIZE];
+	struct buffer_spec_s buffer_spec[BUFSPEC_POOL_SIZE];
+	struct vframe_s switching_fense_vf;
+	struct h264_dpb_stru dpb;
+	u8 init_flag;
+	u8 first_sc_checked;
+	u8 has_i_frame;
+	u8 config_bufmgr_done;
+	u32 max_reference_size;
+	u32 decode_pic_count;
+	u32 reflist_error_count;
+	int start_search_pos;
+	u32 reg_iqidct_control;
+	bool reg_iqidct_control_init_flag;
+	u32 reg_vcop_ctrl_reg;
+	u32 reg_rv_ai_mb_count;
+	u32 vld_dec_control;
+	struct vframe_s vframe_dummy;
+
+	unsigned char buffer_empty_flag;
+
+	u32 frame_width;
+	u32 frame_height;
+	u32 frame_dur;
+	u32 frame_prog;
+	u32 frame_packing_type;
+
+	struct vframe_chunk_s *chunk;
+
+	u32 stat;
+	unsigned long buf_start;
+	u32 buf_offset;
+	u32 buf_size;
+	/* u32 ucode_map_start; */
+	u32 pts_outside;
+	u32 sync_outside;
+	u32 vh264_ratio;
+	u32 vh264_rotation;
+	u32 use_idr_framerate;
+
+	u32 seq_info;
+	u32 seq_info2;
+	u32 video_signal_from_vui; /*to do .. */
+	u32 timing_info_present_flag;
+	u32 fixed_frame_rate_flag;
+	u32 bitstream_restriction_flag;
+	u32 num_reorder_frames;
+	u32 max_dec_frame_buffering;
+	u32 iframe_count;
+	u32 aspect_ratio_info;
+	u32 num_units_in_tick;
+	u32 time_scale;
+	u32 h264_ar;
+	bool h264_first_valid_pts_ready;
+	u32 h264pts1;
+	u32 h264pts2;
+	u32 pts_duration;
+	u32 h264_pts_count;
+	u32 duration_from_pts_done;
+	u32 pts_unstable;
+	u32 unstable_pts;
+	u32 last_checkout_pts;
+	u32 max_refer_buf;
+
+	s32 vh264_stream_switching_state;
+	struct vframe_s *p_last_vf;
+	u32 last_pts;
+	u32 last_pts_remainder;
+	u32 last_duration;
+	u32 last_mb_width, last_mb_height;
+	bool check_pts_discontinue;
+	bool pts_discontinue;
+	u32 wait_buffer_counter;
+	u32 first_offset;
+	u32 first_pts;
+	u64 first_pts64;
+	bool first_pts_cached;
+	u64 last_pts64;
+#if 0
+	void *sei_data_buffer;
+	dma_addr_t sei_data_buffer_phys;
+#endif
+
+	uint error_recovery_mode;
+	uint mb_total;
+	uint mb_width;
+	uint mb_height;
+
+	uint i_only;
+	int skip_frame_count;
+	bool no_poc_reorder_flag;
+	bool send_error_frame_flag;
+	dma_addr_t mc_dma_handle;
+	void *mc_cpu_addr;
+	int vh264_reset;
+
+	atomic_t vh264_active;
+
+	struct dec_sysinfo vh264_amstream_dec_info;
+
+	int dec_result;
+	u32 timeout_processing;
+	struct work_struct work;
+	struct work_struct notify_work;
+	struct work_struct timeout_work;
+	void (*vdec_cb)(struct vdec_s *, void *);
+	void *vdec_cb_arg;
+
+	struct timer_list check_timer;
+
+	/**/
+	unsigned int last_frame_time;
+	u32 vf_pre_count;
+	atomic_t vf_get_count;
+	atomic_t vf_put_count;
+
+	/* timeout handle */
+	unsigned long int start_process_time;
+	unsigned int last_mby_mbx;
+	unsigned int last_vld_level;
+	unsigned int decode_timeout_count;
+	unsigned int timeout_num;
+	unsigned int search_dataempty_num;
+	unsigned int decode_timeout_num;
+	unsigned int decode_dataempty_num;
+	unsigned int buffer_empty_recover_num;
+
+	unsigned get_data_count;
+	unsigned get_data_start_time;
+	/**/
+
+	/*log*/
+	unsigned int packet_write_success_count;
+	unsigned int packet_write_EAGAIN_count;
+	unsigned int packet_write_ENOMEM_count;
+	unsigned int packet_write_EFAULT_count;
+	unsigned int total_read_size_pre;
+	unsigned int total_read_size;
+	unsigned int frame_count_pre;
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	u8 switch_dvlayer_flag;
+	u8 got_valid_nal;
+#endif
+	u8 eos;
+	u8 data_flag;
+	u32 no_error_count;
+	u32 no_error_i_count;
+	/*
+	NODISP_FLAG
+	*/
+	u8 dec_flag;
+
+	u32 ucode_pause_pos;
+
+	u8 reset_bufmgr_flag;
+	u32 reset_bufmgr_count;
+	ulong timeout;
+	u32 timeout_flag;
+	u32 cfg_param1;
+	u32 cfg_param2;
+	u32 cfg_param3;
+	u32 cfg_param4;
+	int valve_count;
+	u8 next_again_flag;
+	u32 pre_parser_wr_ptr;
+	struct firmware_s *fw;
+	struct firmware_s *fw_mmu;
+#ifdef MH264_USERDATA_ENABLE
+	/*user data*/
+	struct mutex userdata_mutex;
+	struct mh264_userdata_info_t userdata_info;
+	struct mh264_userdata_record_t ud_record;
+	int wait_for_udr_send;
+#endif
+	u32 no_mem_count;
+	u32 canvas_mode;
+	bool is_used_v4l;
+	void *v4l2_ctx;
+	bool v4l_params_parsed;
+	wait_queue_head_t wait_q;
+	u32 reg_g_status;
+	struct mutex chunks_mutex;
+	int need_cache_size;
+	u64 sc_start_time;
+	u8 frmbase_cont_flag;
+	struct vframe_qos_s vframe_qos;
+	int frameinfo_enable;
+	bool first_head_check_flag;
+	unsigned int height_aspect_ratio;
+	unsigned int width_aspect_ratio;
+	unsigned int first_i_policy;
+	u32 reorder_dpb_size_margin;
+	bool wait_reset_done_flag;
+#ifdef DETECT_WRONG_MULTI_SLICE
+	unsigned int multi_slice_pic_check_count;
+			/* multi_slice_pic_flag:
+				0, unknown;
+				1, single slice;
+				2, multi slice
+			*/
+	unsigned int multi_slice_pic_flag;
+	unsigned int picture_slice_count;
+	unsigned int cur_picture_slice_count;
+	unsigned char force_slice_as_picture_flag;
+	unsigned int last_picture_slice_count;
+	unsigned int first_pre_frame_num;
+#endif
+	u32 res_ch_flag;
+	u32 b_frame_error_count;
+	struct vdec_info gvs;
+	u32 kpi_first_i_comming;
+	u32 kpi_first_i_decoded;
+	int sidebind_type;
+	int sidebind_channel_id;
+	u32 low_latency_mode;
+	int ip_field_error_count;
+	int buffer_wrap[BUFSPEC_POOL_SIZE];
+	int loop_flag;
+	int loop_last_poc;
+	bool enable_fence;
+	int fence_usage;
+	bool discard_dv_data;
+	u32 metadata_config_flag;
+	int vdec_pg_enable_flag;
+	u32 save_reg_f;
+	u32 start_bit_cnt;
+	u32 right_frame_count;
+	u32 wrong_frame_count;
+	u32 error_frame_width;
+	u32 error_frame_height;
+	ulong fb_token;
+	int dec_again_cnt;
+	struct mh264_fence_vf_t fence_vf_s;
+	struct mutex fence_mutex;
+	u32 no_decoder_buffer_flag;
+	u32 video_signal_type;
+	struct trace_decoder_name trace;
+	int csd_change_flag;
+};
+
+static u32 again_threshold;
+
+static void timeout_process(struct vdec_h264_hw_s *hw);
+static void dump_bufspec(struct vdec_h264_hw_s *hw,
+	const char *caller);
+static void h264_reconfig(struct vdec_h264_hw_s *hw);
+static void h264_reset_bufmgr(struct vdec_s *vdec);
+static void vh264_local_init(struct vdec_h264_hw_s *hw, bool is_reset);
+static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw);
+static int vh264_stop(struct vdec_h264_hw_s *hw);
+static s32 vh264_init(struct vdec_h264_hw_s *hw);
+static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf,
+			u32 index);
+static void release_aux_data(struct vdec_h264_hw_s *hw,
+	int buf_spec_num);
+#ifdef ERROR_HANDLE_TEST
+static void h264_clear_dpb(struct vdec_h264_hw_s *hw);
+#endif
+
+#define		H265_PUT_SAO_4K_SET			0x03
+#define		H265_ABORT_SAO_4K_SET			0x04
+#define		H265_ABORT_SAO_4K_SET_DONE		0x05
+
+#define		SYS_COMMAND			HEVC_ASSIST_SCRATCH_0
+#define		H265_CHECK_AXI_INFO_BASE	HEVC_ASSIST_SCRATCH_8
+#define		H265_SAO_4K_SET_BASE	HEVC_ASSIST_SCRATCH_9
+#define		H265_SAO_4K_SET_COUNT	HEVC_ASSIST_SCRATCH_A
+#define		HEVCD_MPP_ANC2AXI_TBL_DATA		0x3464
+
+
+#define		HEVC_CM_HEADER_START_ADDR		0x3628
+#define		HEVC_CM_BODY_START_ADDR			0x3626
+#define		HEVC_CM_BODY_LENGTH			0x3627
+#define		HEVC_CM_HEADER_LENGTH			0x3629
+#define		HEVC_CM_HEADER_OFFSET			0x362b
+#define		HEVC_SAO_CTRL9				0x362d
+#define		HEVCD_MPP_DECOMP_CTL3			0x34c4
+#define		HEVCD_MPP_VDEC_MCR_CTL			0x34c8
+#define           HEVC_DBLK_CFGB                             0x350b
+#define		HEVC_ASSIST_MMU_MAP_ADDR	0x3009
+
+#define H265_DW_NO_SCALE
+#define H265_MEM_MAP_MODE 0  /*0:linear 1:32x32 2:64x32*/
+#define H265_LOSLESS_COMPRESS_MODE
+#define MAX_FRAME_4K_NUM 0x1200
+#define FRAME_MMU_MAP_SIZE  (MAX_FRAME_4K_NUM * 4)
+
+/* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */
+static u32 mem_map_mode = H265_MEM_MAP_MODE;
+
+#define MAX_SIZE_4K (4096 * 2304)
+#define MAX_SIZE_2K (1920 * 1088)
+
+static int is_oversize(int w, int h)
+{
+	int max = MAX_SIZE_4K;
+
+	if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5D)
+		max = MAX_SIZE_2K;
+
+	if (w < 0 || h < 0)
+		return true;
+
+	if (h != 0 && (w > max / h))
+		return true;
+
+	return false;
+}
+
+static void vmh264_udc_fill_vpts(struct vdec_h264_hw_s *hw,
+						int frame_type,
+						u32 vpts,
+						u32 vpts_valid);
+static int  compute_losless_comp_body_size(int width,
+				int height, int bit_depth_10);
+static int  compute_losless_comp_header_size(int width, int height);
+
+static int hevc_alloc_mmu(struct vdec_h264_hw_s *hw, int pic_idx,
+		int pic_width, int pic_height, u16 bit_depth,
+		unsigned int *mmu_index_adr) {
+	int cur_buf_idx;
+	int bit_depth_10 = (bit_depth != 0x00);
+	int picture_size;
+	u32 cur_mmu_4k_number;
+
+	WRITE_VREG(CURR_CANVAS_CTRL, pic_idx<<24);
+	cur_buf_idx = READ_VREG(CURR_CANVAS_CTRL)&0xff;
+	picture_size = compute_losless_comp_body_size(pic_width,
+					pic_height, bit_depth_10);
+	cur_mmu_4k_number = ((picture_size+(1<<12)-1) >> 12);
+	dpb_print(DECODE_ID(hw),
+		PRINT_FLAG_MMU_DETAIL,
+		"alloc_mmu new_fb_idx %d picture_size %d cur_mmu_4k_number %d\n",
+		cur_buf_idx, picture_size, cur_mmu_4k_number);
+
+	if (cur_mmu_4k_number > MAX_FRAME_4K_NUM) {
+		pr_err("hevc_alloc_mmu cur_mmu_4k_number %d unsupport\n",
+		cur_mmu_4k_number);
+		return -1;
+	}
+
+	return decoder_mmu_box_alloc_idx(
+		hw->mmu_box,
+		cur_buf_idx,
+		cur_mmu_4k_number,
+		mmu_index_adr);
+}
+
+static int  compute_losless_comp_body_size(int width,
+					int height, int bit_depth_10)
+{
+	int    width_x64;
+	int    height_x32;
+	int    bsize;
+
+	width_x64 = width + 63;
+	width_x64 >>= 6;
+
+	height_x32 = height + 31;
+	height_x32 >>= 5;
+
+#ifdef H264_MMU
+	bsize = (bit_depth_10 ? 4096 : 3264) * width_x64*height_x32;
+#else
+	bsize = (bit_depth_10 ? 4096 : 3072) * width_x64*height_x32;
+#endif
+	return bsize;
+}
+
+static int  compute_losless_comp_header_size(int width, int height)
+{
+	int	width_x64;
+	int	width_x128;
+	int    height_x64;
+	int	hsize;
+
+	width_x64 = width + 63;
+	width_x64 >>= 6;
+
+	width_x128 = width + 127;
+	width_x128 >>= 7;
+
+	height_x64 = height + 63;
+	height_x64 >>= 6;
+
+#ifdef	H264_MMU
+	hsize = 128*width_x64*height_x64;
+#else
+	hsize = 32*width_x128*height_x64;
+#endif
+	return  hsize;
+}
+
+static int get_dw_size(struct vdec_h264_hw_s *hw, u32 *pdw_buffer_size_u_v_h)
+{
+	int pic_width, pic_height;
+	int lcu_size = 16;
+	int dw_buf_size;
+	u32 dw_buffer_size_u_v;
+	u32 dw_buffer_size_u_v_h;
+	int dw_mode =  hw->double_write_mode;
+
+	pic_width = hw->frame_width;
+	pic_height = hw->frame_height;
+
+	if (dw_mode) {
+		int pic_width_dw = pic_width /
+			get_double_write_ratio(hw->double_write_mode);
+		int pic_height_dw = pic_height /
+			get_double_write_ratio(hw->double_write_mode);
+
+		int pic_width_lcu_dw = (pic_width_dw % lcu_size) ?
+			pic_width_dw / lcu_size + 1 :
+			pic_width_dw / lcu_size;
+		int pic_height_lcu_dw = (pic_height_dw % lcu_size) ?
+			pic_height_dw / lcu_size + 1 :
+			pic_height_dw / lcu_size;
+		int lcu_total_dw = pic_width_lcu_dw * pic_height_lcu_dw;
+
+
+		dw_buffer_size_u_v = lcu_total_dw * lcu_size * lcu_size / 2;
+		dw_buffer_size_u_v_h = (dw_buffer_size_u_v + 0xffff) >> 16;
+			/*64k alignment*/
+		dw_buf_size = ((dw_buffer_size_u_v_h << 16) * 3);
+		*pdw_buffer_size_u_v_h = dw_buffer_size_u_v_h;
+	} else {
+		*pdw_buffer_size_u_v_h = 0;
+		dw_buf_size = 0;
+	}
+
+	return dw_buf_size;
+}
+
+
+static void hevc_mcr_config_canv2axitbl(struct vdec_h264_hw_s *hw, int restore)
+{
+	int i, size;
+	u32   canvas_addr;
+	unsigned long maddr;
+	int     num_buff = hw->dpb.mDPB.size;
+	int dw_size = 0;
+	u32 dw_buffer_size_u_v_h;
+	u32 blkmode = hw->canvas_mode;
+	int dw_mode =  hw->double_write_mode;
+	struct vdec_s *vdec = hw_to_vdec(hw);
+
+	canvas_addr = ANC0_CANVAS_ADDR;
+	for (i = 0; i < num_buff; i++)
+		WRITE_VREG((canvas_addr + i), i | (i << 8) | (i << 16));
+
+	WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, (0x1 << 1) | (0x1 << 2));
+	size = hw->losless_comp_body_size + hw->losless_comp_header_size;
+
+
+	dw_size = get_dw_size(hw, &dw_buffer_size_u_v_h);
+	size += dw_size;
+	if (size > 0)
+		size += 0x10000;
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_MMU_DETAIL,
+		"dw_buffer_size_u_v_h = %d, dw_size = 0x%x, size = 0x%x\n",
+		dw_buffer_size_u_v_h, dw_size, size);
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_MMU_DETAIL,
+		"body_size = %d, header_size = %d, body_size_sao = %d\n",
+				hw->losless_comp_body_size,
+				hw->losless_comp_header_size,
+				hw->losless_comp_body_size_sao);
+
+	for (i = 0; i < num_buff; i++) {
+		if (!restore) {
+			if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box,
+				HEADER_BUFFER_IDX(i), size,
+				DRIVER_HEADER_NAME, &maddr) < 0) {
+				dpb_print(DECODE_ID(hw), 0,
+					"%s malloc compress header failed %d\n",
+					DRIVER_HEADER_NAME, i);
+				return;
+			}
+			if (hw->enable_fence) {
+				vdec_fence_buffer_count_increase((ulong)vdec->sync);
+				INIT_LIST_HEAD(&vdec->sync->release_callback[HEADER_BUFFER_IDX(i)].node);
+				decoder_bmmu_box_add_callback_func(hw->bmmu_box, HEADER_BUFFER_IDX(i), (void *)&vdec->sync->release_callback[i]);
+			}
+		} else
+			maddr = hw->buffer_spec[i].alloc_header_addr;
+		WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA,  maddr >> 5);
+		hw->buffer_spec[i].alloc_header_addr = maddr;
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_MMU_DETAIL,
+			"%s : canvas: %d  axiaddr:%x size 0x%x\n",
+			__func__, i, (u32)maddr, size);
+
+		if (dw_mode) {
+			u32 addr;
+			int canvas_w;
+			int canvas_h;
+
+			canvas_w = hw->frame_width /
+				get_double_write_ratio(hw->double_write_mode);
+			canvas_h = hw->frame_height /
+				get_double_write_ratio(hw->double_write_mode);
+
+			if (hw->canvas_mode == 0)
+				canvas_w = ALIGN(canvas_w, 32);
+			else
+				canvas_w = ALIGN(canvas_w, 64);
+			canvas_h = ALIGN(canvas_h, 32);
+
+			hw->buffer_spec[i].dw_y_adr =
+				maddr + hw->losless_comp_header_size;
+
+			hw->buffer_spec[i].dw_y_adr =
+				((hw->buffer_spec[i].dw_y_adr + 0xffff) >> 16)
+					<< 16;
+			hw->buffer_spec[i].dw_u_v_adr =
+				hw->buffer_spec[i].dw_y_adr
+				+ (dw_buffer_size_u_v_h << 16) * 2;
+
+
+			hw->buffer_spec[i].buf_adr
+				= hw->buffer_spec[i].dw_y_adr;
+			addr = hw->buffer_spec[i].buf_adr;
+
+
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_MMU_DETAIL,
+				"dw_y_adr = 0x%x, dw_u_v_adr = 0x%x, y_addr = 0x%x, u_addr = 0x%x, v_addr = 0x%x, width = %d, height = %d\n",
+				hw->buffer_spec[i].dw_y_adr,
+				hw->buffer_spec[i].dw_u_v_adr,
+				hw->buffer_spec[i].y_addr,
+				hw->buffer_spec[i].u_addr,
+				hw->buffer_spec[i].v_addr,
+				canvas_w,
+				canvas_h);
+
+			hw->buffer_spec[i].canvas_config[0].phy_addr =
+					hw->buffer_spec[i].dw_y_adr;
+			hw->buffer_spec[i].canvas_config[0].width = canvas_w;
+			hw->buffer_spec[i].canvas_config[0].height = canvas_h;
+			hw->buffer_spec[i].canvas_config[0].block_mode =
+				blkmode;
+			hw->buffer_spec[i].canvas_config[0].endian = 7;
+
+			hw->buffer_spec[i].canvas_config[1].phy_addr =
+					hw->buffer_spec[i].dw_u_v_adr;
+			hw->buffer_spec[i].canvas_config[1].width = canvas_w;
+			hw->buffer_spec[i].canvas_config[1].height = canvas_h;
+			hw->buffer_spec[i].canvas_config[1].block_mode =
+				blkmode;
+			hw->buffer_spec[i].canvas_config[1].endian = 7;
+		}
+	}
+	WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1);
+
+	WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR, (0 << 8) | (0<<1) | 1);
+	for (i = 0; i < 32; i++)
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
+	return;
+}
+static void    hevc_mcr_config_mc_ref(struct vdec_h264_hw_s *hw)
+{
+	u32 i;
+	u32 ref_canv;
+	struct Slice *pSlice = &(hw->dpb.mSlice);
+	/*REFLIST[0]*/
+	for (i = 0; i < (unsigned int)(pSlice->listXsize[0]); i++) {
+		struct StorablePicture *ref = pSlice->listX[0][i];
+		if (ref == NULL)
+			return;
+		WRITE_VREG(CURR_CANVAS_CTRL, ref->buf_spec_num<<24);
+		ref_canv = READ_VREG(CURR_CANVAS_CTRL)&0xffffff;
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+					(ref->buf_spec_num & 0x3f) << 8);
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, ref_canv);
+	}
+	/*REFLIST[1]*/
+	for (i = 0; i < (unsigned int)(pSlice->listXsize[1]); i++) {
+		struct StorablePicture *ref = pSlice->listX[1][i];
+		if (ref == NULL)
+			return;
+		WRITE_VREG(CURR_CANVAS_CTRL, ref->buf_spec_num<<24);
+		ref_canv = READ_VREG(CURR_CANVAS_CTRL)&0xffffff;
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+					(ref->buf_spec_num & 0x3f) << 8);
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, ref_canv);
+	}
+	return;
+}
+
+static void   hevc_mcr_config_mcrcc(struct vdec_h264_hw_s *hw)
+{
+	u32 rdata32;
+	u32 rdata32_2;
+	u32 slice_type;
+	struct StorablePicture *ref;
+	struct Slice *pSlice;
+	slice_type = hw->dpb.mSlice.slice_type;
+	pSlice = &(hw->dpb.mSlice);
+	WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2);
+	if (slice_type == I_SLICE) {
+		WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0);
+		return;
+	}
+	if (slice_type == B_SLICE) {
+		ref = pSlice->listX[0][0];
+		if (ref == NULL)
+			return;
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+				((ref->buf_spec_num & 0x3f) << 8));
+		rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+		rdata32 = rdata32 & 0xffff;
+		rdata32 = rdata32 | (rdata32 << 16);
+		WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32);
+
+		ref = pSlice->listX[1][0];
+		if (ref == NULL)
+			return;
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+			((ref->buf_spec_num & 0x3f) << 8));
+		rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+		rdata32_2 = rdata32_2 & 0xffff;
+		rdata32_2 = rdata32_2 | (rdata32_2 << 16);
+		if (rdata32 == rdata32_2) {
+			ref = pSlice->listX[1][1];
+			if (ref == NULL)
+				return;
+			WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+				((ref->buf_spec_num & 0x3f) << 8));
+			rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+			rdata32_2 = rdata32_2 & 0xffff;
+			rdata32_2 = rdata32_2 | (rdata32_2 << 16);
+		}
+		WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32_2);
+	} else { /*P-PIC*/
+		ref = pSlice->listX[0][0];
+		if (ref == NULL)
+			return;
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+				((ref->buf_spec_num & 0x3f) << 8));
+		rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+		rdata32 = rdata32 & 0xffff;
+		rdata32 = rdata32 | (rdata32 << 16);
+		WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32);
+
+		ref = pSlice->listX[0][1];
+		if (ref == NULL)
+			return;
+		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+				((ref->buf_spec_num & 0x3f) << 8));
+		rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+		rdata32 = rdata32 & 0xffff;
+		rdata32 = rdata32 | (rdata32 << 16);
+		WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32);
+	}
+	WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0);
+	return;
+}
+
+
+static void  hevc_mcr_sao_global_hw_init(struct vdec_h264_hw_s *hw,
+		u32 width, u32 height) {
+	u32 data32;
+	u32 lcu_x_num, lcu_y_num;
+	u32 lcu_total;
+	u32 mc_buffer_size_u_v;
+	u32 mc_buffer_size_u_v_h;
+	int  dw_mode = hw->double_write_mode;
+
+	/*lcu_x_num = (width + 15) >> 4;*/
+	// width need to be round to 64 pixel -- case0260 1/10/2020
+	lcu_x_num = (((width + 63) >> 6) << 2);
+	lcu_y_num = (height + 15) >> 4;
+	lcu_total = lcu_x_num * lcu_y_num;
+
+	hw->mc_buffer_size_u_v = mc_buffer_size_u_v = lcu_total*16*16/2;
+	hw->mc_buffer_size_u_v_h =
+		mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff)>>16;
+
+	hw->losless_comp_body_size = 0;
+
+	hw->losless_comp_body_size_sao =
+			compute_losless_comp_body_size(width, height, 0);
+	hw->losless_comp_header_size =
+			compute_losless_comp_header_size(width, height);
+
+	WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x1); /*sw reset ipp10b_top*/
+	WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x0); /*sw reset ipp10b_top*/
+
+	/* setup lcu_size = 16*/
+	WRITE_VREG(HEVCD_IPP_TOP_LCUCONFIG, 16); /*set lcu size = 16*/
+	/*pic_width/pic_height*/
+	WRITE_VREG(HEVCD_IPP_TOP_FRMCONFIG,
+		(height & 0xffff) << 16 | (width & 0xffff));
+	/* bitdepth_luma = 8*/
+	/* bitdepth_chroma = 8*/
+	WRITE_VREG(HEVCD_IPP_BITDEPTH_CONFIG, 0x0);/*set bit-depth 8 */
+
+#ifdef	H265_LOSLESS_COMPRESS_MODE
+	WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4));
+	WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0x0);
+#else
+	WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
+#endif
+	data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
+	data32 &= (~0x30);
+	data32 |= (hw->canvas_mode << 4);
+	WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32);
+
+	WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,
+			(0x80 << 20) | (0x80 << 10) | (0xff));
+
+	WRITE_VREG(HEVCD_MPP_VDEC_MCR_CTL, 0x1 | (0x1 << 4));
+
+	/*comfig vdec:h264:mdec to use hevc mcr/mcrcc/decomp*/
+	WRITE_VREG(MDEC_PIC_DC_MUX_CTRL,
+			READ_VREG(MDEC_PIC_DC_MUX_CTRL) | 0x1 << 31);
+	/* ipp_enable*/
+	WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x1 << 1);
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
+		  WRITE_VREG(HEVC_DBLK_CFG1, 0x2); // set ctusize==16
+		  WRITE_VREG(HEVC_DBLK_CFG2, ((height & 0xffff)<<16) | (width & 0xffff));
+		  if (dw_mode & 0x10)
+			WRITE_VREG(HEVC_DBLK_CFGB, 0x40405603);
+		  else if (dw_mode)
+			WRITE_VREG(HEVC_DBLK_CFGB, 0x40405703);
+		  else
+			WRITE_VREG(HEVC_DBLK_CFGB, 0x40405503);
+	}
+
+	data32 = READ_VREG(HEVC_SAO_CTRL0);
+	data32 &= (~0xf);
+	data32 |= 0x4;
+	WRITE_VREG(HEVC_SAO_CTRL0, data32);
+	WRITE_VREG(HEVC_SAO_PIC_SIZE, (height & 0xffff) << 16 |
+			(width & 0xffff));
+	data32  = ((lcu_x_num-1) | (lcu_y_num-1) << 16);
+
+	WRITE_VREG(HEVC_SAO_PIC_SIZE_LCU, data32);
+	data32  =  (lcu_x_num  | lcu_y_num << 16);
+	WRITE_VREG(HEVC_SAO_TILE_SIZE_LCU, data32);
+	data32 = (mc_buffer_size_u_v_h << 16) << 1;
+	WRITE_VREG(HEVC_SAO_Y_LENGTH, data32);
+	data32 = (mc_buffer_size_u_v_h << 16);
+	WRITE_VREG(HEVC_SAO_C_LENGTH, data32);
+
+	data32 = READ_VREG(HEVC_SAO_CTRL1);
+	data32 &= (~0x3000);
+	data32 &= (~0xff0);
+	data32 |= endian;	/* Big-Endian per 64-bit */
+
+	if (hw->mmu_enable && (dw_mode & 0x10))
+		data32 |= ((hw->canvas_mode << 12) |1);
+	else if (hw->mmu_enable && dw_mode)
+		data32 |= ((hw->canvas_mode << 12));
+	else
+		data32 |= ((hw->canvas_mode << 12)|2);
+
+	WRITE_VREG(HEVC_SAO_CTRL1, data32);
+
+#ifdef	H265_DW_NO_SCALE
+	WRITE_VREG(HEVC_SAO_CTRL5, READ_VREG(HEVC_SAO_CTRL5) & ~(0xff << 16));
+	if (hw->mmu_enable && dw_mode) {
+		data32 =	READ_VREG(HEVC_SAO_CTRL5);
+		data32 &= (~(0xff << 16));
+		if (dw_mode == 2 ||
+			dw_mode == 3)
+			data32 |= (0xff<<16);
+		else if (dw_mode == 4)
+			data32 |= (0x33<<16);
+		WRITE_VREG(HEVC_SAO_CTRL5, data32);
+	}
+
+
+#endif
+
+
+#ifdef	H265_LOSLESS_COMPRESS_MODE
+	data32 = READ_VREG(HEVC_SAO_CTRL5);
+	data32 |= (1<<9); /*8-bit smem-mode*/
+	WRITE_VREG(HEVC_SAO_CTRL5, data32);
+
+	WRITE_VREG(HEVC_CM_BODY_LENGTH, hw->losless_comp_body_size_sao);
+	WRITE_VREG(HEVC_CM_HEADER_OFFSET, hw->losless_comp_body_size);
+	WRITE_VREG(HEVC_CM_HEADER_LENGTH, hw->losless_comp_header_size);
+#endif
+
+#ifdef	H265_LOSLESS_COMPRESS_MODE
+	WRITE_VREG(HEVC_SAO_CTRL9, READ_VREG(HEVC_SAO_CTRL9) | (0x1 << 1));
+	WRITE_VREG(HEVC_SAO_CTRL5, READ_VREG(HEVC_SAO_CTRL5) | (0x1 << 10));
+#endif
+
+	WRITE_VREG(HEVC_SAO_CTRL9, READ_VREG(HEVC_SAO_CTRL9) | 0x1 << 7);
+
+	memset(hw->frame_mmu_map_addr, 0, FRAME_MMU_MAP_SIZE);
+
+	WRITE_VREG(MDEC_EXTIF_CFG0, hw->extif_addr);
+	WRITE_VREG(MDEC_EXTIF_CFG1, 0x80000000);
+	return;
+}
+
+static void  hevc_sao_set_slice_type(struct vdec_h264_hw_s *hw,
+		u32 is_new_pic, u32 is_idr)
+{
+	hw->is_new_pic = is_new_pic;
+	hw->is_idr_frame = is_idr;
+	return;
+}
+
+static void  hevc_sao_set_pic_buffer(struct vdec_h264_hw_s *hw,
+			struct StorablePicture *pic) {
+	u32 mc_y_adr;
+	u32 mc_u_v_adr;
+	u32 dw_y_adr;
+	u32 dw_u_v_adr;
+	u32 canvas_addr;
+	int ret;
+	int  dw_mode = hw->double_write_mode;
+	if (hw->is_new_pic != 1)
+		return;
+
+	if (hw->is_idr_frame) {
+		/* William TBD */
+		memset(hw->frame_mmu_map_addr, 0, FRAME_MMU_MAP_SIZE);
+	}
+
+	WRITE_VREG(CURR_CANVAS_CTRL, pic->buf_spec_num << 24);
+	canvas_addr = READ_VREG(CURR_CANVAS_CTRL)&0xffffff;
+	WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, (0x0 << 1) |
+			(0x0 << 2) | ((canvas_addr & 0xff) << 8));
+	mc_y_adr = READ_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA) << 5;
+	WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, (0x0 << 1) |
+			(0x0 << 2) | (((canvas_addr >> 8) & 0xff) << 8));
+	mc_u_v_adr = READ_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA) << 5;
+	WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1);
+
+
+	if (dw_mode) {
+		dw_y_adr = hw->buffer_spec[pic->buf_spec_num].dw_y_adr;
+		dw_u_v_adr = hw->buffer_spec[pic->buf_spec_num].dw_u_v_adr;
+	} else {
+		dw_y_adr = 0;
+		dw_u_v_adr = 0;
+	}
+#ifdef	H265_LOSLESS_COMPRESS_MODE
+	if (dw_mode)
+		WRITE_VREG(HEVC_SAO_Y_START_ADDR, dw_y_adr);
+	WRITE_VREG(HEVC_CM_BODY_START_ADDR, mc_y_adr);
+#ifdef	H264_MMU
+	WRITE_VREG(HEVC_CM_HEADER_START_ADDR, mc_y_adr);
+#else
+	WRITE_VREG(HEVC_CM_HEADER_START_ADDR,
+			(mc_y_adr + hw->losless_comp_body_size));
+#endif
+#else
+	WRITE_VREG(HEVC_SAO_Y_START_ADDR, mc_y_adr);
+#endif
+
+#ifndef H265_LOSLESS_COMPRESS_MODE
+	WRITE_VREG(HEVC_SAO_C_START_ADDR, mc_u_v_adr);
+#else
+	if (dw_mode)
+		WRITE_VREG(HEVC_SAO_C_START_ADDR, dw_u_v_adr);
+#endif
+
+#ifndef LOSLESS_COMPRESS_MODE
+	if (dw_mode) {
+		WRITE_VREG(HEVC_SAO_Y_WPTR, mc_y_adr);
+		WRITE_VREG(HEVC_SAO_C_WPTR, mc_u_v_adr);
+	}
+#else
+	WRITE_VREG(HEVC_SAO_Y_WPTR, dw_y_adr);
+	WRITE_VREG(HEVC_SAO_C_WPTR, dw_u_v_adr);
+#endif
+
+	ret = hevc_alloc_mmu(hw, pic->buf_spec_num,
+			(hw->mb_width << 4), (hw->mb_height << 4), 0x0,
+			hw->frame_mmu_map_addr);
+	if (ret != 0) {
+		dpb_print(DECODE_ID(hw),
+		PRINT_FLAG_MMU_DETAIL, "can't alloc need mmu1,idx %d ret =%d\n",
+		pic->buf_spec_num,
+		ret);
+		return;
+	}
+
+	/*Reset SAO + Enable SAO slice_start*/
+	if (hw->mmu_enable  && get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
+		WRITE_VREG(HEVC_DBLK_CFG0, 0x1); // reset buffer32x4 in lpf for every picture
+	WRITE_VREG(HEVC_SAO_INT_STATUS,
+			READ_VREG(HEVC_SAO_INT_STATUS) | 0x1 << 28);
+	WRITE_VREG(HEVC_SAO_INT_STATUS,
+			READ_VREG(HEVC_SAO_INT_STATUS) | 0x1 << 31);
+	/*pr_info("hevc_sao_set_pic_buffer:mc_y_adr: %x\n", mc_y_adr);*/
+	/*Send coommand to hevc-code to supply 4k buffers to sao*/
+
+	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) {
+		WRITE_VREG(H265_SAO_4K_SET_BASE, (u32)hw->frame_mmu_map_phy_addr);
+		WRITE_VREG(H265_SAO_4K_SET_COUNT, MAX_FRAME_4K_NUM);
+	} else
+		WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, (u32)hw->frame_mmu_map_phy_addr);
+	WRITE_VREG(SYS_COMMAND, H265_PUT_SAO_4K_SET);
+	hw->frame_busy = 1;
+	return;
+}
+
+
+static void  hevc_set_unused_4k_buff_idx(struct vdec_h264_hw_s *hw,
+		u32 buf_spec_num) {
+	WRITE_VREG(CURR_CANVAS_CTRL, buf_spec_num<<24);
+	hw->hevc_cur_buf_idx = READ_VREG(CURR_CANVAS_CTRL)&0xff;
+	dpb_print(DECODE_ID(hw),
+		PRINT_FLAG_MMU_DETAIL, " %s  cur_buf_idx %d  buf_spec_num %d\n",
+		__func__, hw->hevc_cur_buf_idx, buf_spec_num);
+	return;
+}
+
+
+static void  hevc_set_frame_done(struct vdec_h264_hw_s *hw)
+{
+	ulong timeout = jiffies + HZ;
+	dpb_print(DECODE_ID(hw),
+		PRINT_FLAG_MMU_DETAIL, "hevc_frame_done...set\n");
+	while ((READ_VREG(HEVC_SAO_INT_STATUS) & 0x1) == 0) {
+		if (time_after(jiffies, timeout)) {
+			dpb_print(DECODE_ID(hw),
+			PRINT_FLAG_MMU_DETAIL, " %s..timeout!\n", __func__);
+			break;
+		}
+	}
+	timeout = jiffies + HZ;
+	while (READ_VREG(HEVC_CM_CORE_STATUS) & 0x1) {
+		if (time_after(jiffies, timeout)) {
+			dpb_print(DECODE_ID(hw),
+			PRINT_FLAG_MMU_DETAIL, " %s cm_core..timeout!\n", __func__);
+			break;
+		}
+	}
+	WRITE_VREG(HEVC_SAO_INT_STATUS, 0x1);
+	hw->frame_done = 1;
+	return;
+}
+
+static void release_cur_decoding_buf(struct vdec_h264_hw_s *hw)
+{
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	if (p_H264_Dpb->mVideo.dec_picture) {
+		release_picture(p_H264_Dpb,
+			p_H264_Dpb->mVideo.dec_picture);
+		p_H264_Dpb->mVideo.dec_picture->data_flag &= ~ERROR_FLAG;
+		p_H264_Dpb->mVideo.dec_picture = NULL;
+		if (hw->mmu_enable)
+			hevc_set_frame_done(hw);
+	}
+}
+
+static void  hevc_sao_wait_done(struct vdec_h264_hw_s *hw)
+{
+	ulong timeout = jiffies + HZ;
+	dpb_print(DECODE_ID(hw),
+		PRINT_FLAG_MMU_DETAIL, "hevc_sao_wait_done...start\n");
+	while ((READ_VREG(HEVC_SAO_INT_STATUS) >> 31)) {
+		if (time_after(jiffies, timeout)) {
+			dpb_print(DECODE_ID(hw),
+			PRINT_FLAG_MMU_DETAIL,
+			"hevc_sao_wait_done...wait timeout!\n");
+			break;
+		}
+	}
+	timeout = jiffies + HZ;
+	if ((hw->frame_busy == 1) && (hw->frame_done == 1) ) {
+		if (get_cpu_major_id() <  AM_MESON_CPU_MAJOR_ID_G12A) {
+		WRITE_VREG(SYS_COMMAND, H265_ABORT_SAO_4K_SET);
+			while ((READ_VREG(SYS_COMMAND) & 0xff) !=
+					H265_ABORT_SAO_4K_SET_DONE) {
+					if (time_after(jiffies, timeout)) {
+						dpb_print(DECODE_ID(hw),
+						PRINT_FLAG_MMU_DETAIL,
+						"wait h265_abort_sao_4k_set_done timeout!\n");
+						break;
+					}
+			}
+		}
+		amhevc_stop();
+		hw->frame_busy = 0;
+		hw->frame_done = 0;
+		dpb_print(DECODE_ID(hw),
+			PRINT_FLAG_MMU_DETAIL,
+			"sao wait done ,hevc stop!\n");
+	}
+	return;
+}
+static void buf_spec_init(struct vdec_h264_hw_s *hw, bool buffer_reset_flag)
+{
+	int i;
+	unsigned long flags;
+	spin_lock_irqsave(&hw->bufspec_lock, flags);
+
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		struct vframe_s *vf = &hw->vfpool[hw->cur_pool][i];
+		u32 ref_idx = BUFSPEC_INDEX(vf->index);
+		if ((vf->index != -1) &&
+			(hw->buffer_spec[ref_idx].vf_ref == 0) &&
+			(hw->buffer_spec[ref_idx].used != -1)) {
+			vf->index = -1;
+		}
+	}
+
+	hw->cur_pool++;
+	if (hw->cur_pool >= VF_POOL_NUM)
+		hw->cur_pool = 0;
+
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		struct vframe_s *vf = &hw->vfpool[hw->cur_pool][i];
+		u32 ref_idx = BUFSPEC_INDEX(vf->index);
+		if ((vf->index != -1) &&
+			(hw->buffer_spec[ref_idx].vf_ref == 0) &&
+			(hw->buffer_spec[ref_idx].used != -1)) {
+			vf->index = -1;
+		}
+	}
+	/* buffers are alloced when error reset, v4l must find buffer by buffer_wrap[] */
+	if (hw->reset_bufmgr_flag && buffer_reset_flag) {
+		for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+			if (hw->buffer_spec[i].used == 1 || hw->buffer_spec[i].used == 2)
+				hw->buffer_spec[i].used = 0;
+		}
+	} else {
+		for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+			hw->buffer_spec[i].used = -1;
+			hw->buffer_spec[i].canvas_pos = -1;
+			hw->buffer_wrap[i] = -1;
+		}
+	}
+
+	if (dpb_is_debug(DECODE_ID(hw),
+		PRINT_FLAG_DUMP_BUFSPEC))
+		dump_bufspec(hw, __func__);
+	spin_unlock_irqrestore(&hw->bufspec_lock, flags);
+}
+
+
+/*is active in buf management */
+static unsigned char is_buf_spec_in_use(struct vdec_h264_hw_s *hw,
+	int buf_spec_num)
+{
+	unsigned char ret = 0;
+	if (hw->buffer_spec[buf_spec_num].used == 1 ||
+		hw->buffer_spec[buf_spec_num].used == 2 ||
+		hw->buffer_spec[buf_spec_num].used == 3 ||
+		hw->buffer_spec[buf_spec_num].used == 5)
+		ret = 1;
+	return ret;
+}
+
+static unsigned char is_buf_spec_in_disp_q(struct vdec_h264_hw_s *hw,
+	int buf_spec_num)
+{
+	unsigned char ret = 0;
+	if (hw->buffer_spec[buf_spec_num].used == 2 ||
+		hw->buffer_spec[buf_spec_num].used == 3 ||
+		hw->buffer_spec[buf_spec_num].used == 5)
+		ret = 1;
+	return ret;
+}
+
+static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i)
+{
+	struct vdec_s *vdec = hw_to_vdec(hw);
+	if (hw->mmu_enable) {
+		if (hw->buffer_spec[i].alloc_header_addr)
+			return 0;
+		else
+			return -1;
+	} else {
+
+		int buf_size = (hw->mb_total << 8) + (hw->mb_total << 7);
+		int addr;
+#ifdef VDEC_DW
+		int orig_buf_size;
+		orig_buf_size = buf_size;
+		if (IS_VDEC_DW(hw) == 1)
+			buf_size += (hw->mb_total << 7) + (hw->mb_total << 6);
+		else if (IS_VDEC_DW(hw) == 2)
+			buf_size += (hw->mb_total << 6) + (hw->mb_total << 5);
+		else if (IS_VDEC_DW(hw) == 4)
+			buf_size += (hw->mb_total << 4) + (hw->mb_total << 3);
+		else if (IS_VDEC_DW(hw) == 8)
+			buf_size += (hw->mb_total << 2) + (hw->mb_total << 1);
+		if (IS_VDEC_DW(hw)) {
+			u32 align_size;
+			/* add align padding size for blk64x32: (mb_w<<4)*32, (mb_h<<4)*64 */
+			align_size = ((hw->mb_width << 9) + (hw->mb_height << 10)) / IS_VDEC_DW(hw);
+			/* double align padding size for uv*/
+			align_size <<= 1;
+			buf_size += align_size + PAGE_SIZE;
+		}
+#endif
+		if (hw->buffer_spec[i].cma_alloc_addr)
+			return 0;
+
+		if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, i,
+			PAGE_ALIGN(buf_size), DRIVER_NAME,
+			&hw->buffer_spec[i].cma_alloc_addr) < 0) {
+			hw->buffer_spec[i].cma_alloc_addr = 0;
+			if (hw->no_mem_count++ > 3) {
+				hw->stat |= DECODER_FATAL_ERROR_NO_MEM;
+				hw->reset_bufmgr_flag = 1;
+			}
+			dpb_print(DECODE_ID(hw), 0,
+			"%s, fail to alloc buf for bufspec%d, try later\n",
+					__func__, i
+			);
+			return -1;
+		} else {
+			if (hw->enable_fence) {
+				vdec_fence_buffer_count_increase((ulong)vdec->sync);
+				INIT_LIST_HEAD(&vdec->sync->release_callback[i].node);
+				decoder_bmmu_box_add_callback_func(hw->bmmu_box, i, (void *)&vdec->sync->release_callback[i]);
+			}
+			hw->no_mem_count = 0;
+			hw->stat &= ~DECODER_FATAL_ERROR_NO_MEM;
+		}
+		if (!vdec_secure(vdec)) {
+			/*init internal buf*/
+			char *tmpbuf = (char *)codec_mm_phys_to_virt(hw->buffer_spec[i].cma_alloc_addr);
+			if (tmpbuf) {
+				memset(tmpbuf, 0, PAGE_ALIGN(buf_size));
+				codec_mm_dma_flush(tmpbuf,
+					   PAGE_ALIGN(buf_size),
+					   DMA_TO_DEVICE);
+			} else {
+				tmpbuf = codec_mm_vmap(hw->buffer_spec[i].cma_alloc_addr, PAGE_ALIGN(buf_size));
+				if (tmpbuf) {
+					memset(tmpbuf, 0, PAGE_ALIGN(buf_size));
+					codec_mm_dma_flush(tmpbuf,
+						   PAGE_ALIGN(buf_size),
+						   DMA_TO_DEVICE);
+					codec_mm_unmap_phyaddr(tmpbuf);
+				}
+			}
+		}
+		hw->buffer_spec[i].buf_adr =
+		hw->buffer_spec[i].cma_alloc_addr;
+		addr = hw->buffer_spec[i].buf_adr;
+
+
+		hw->buffer_spec[i].y_addr = addr;
+		addr += hw->mb_total << 8;
+		hw->buffer_spec[i].u_addr = addr;
+		hw->buffer_spec[i].v_addr = addr;
+		addr += hw->mb_total << 7;
+
+		hw->buffer_spec[i].canvas_config[0].phy_addr =
+			hw->buffer_spec[i].y_addr;
+		hw->buffer_spec[i].canvas_config[0].width =
+			hw->mb_width << 4;
+		hw->buffer_spec[i].canvas_config[0].height =
+			hw->mb_height << 4;
+		hw->buffer_spec[i].canvas_config[0].block_mode =
+			hw->canvas_mode;
+
+		hw->buffer_spec[i].canvas_config[1].phy_addr =
+				hw->buffer_spec[i].u_addr;
+		hw->buffer_spec[i].canvas_config[1].width =
+				hw->mb_width << 4;
+		hw->buffer_spec[i].canvas_config[1].height =
+				hw->mb_height << 3;
+		hw->buffer_spec[i].canvas_config[1].block_mode =
+				hw->canvas_mode;
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+		"%s, alloc buf for bufspec%d\n",
+				__func__, i);
+#ifdef  VDEC_DW
+		if (!IS_VDEC_DW(hw))
+			return 0;
+		else {
+			int w_shift = 3, h_shift = 3;
+
+			if (IS_VDEC_DW(hw) == 1) {
+				w_shift = 3;
+				h_shift = 4;
+			} else if (IS_VDEC_DW(hw) == 2) {
+				w_shift = 3;
+				h_shift = 3;
+			} else if (IS_VDEC_DW(hw) == 4) {
+				w_shift = 2;
+				h_shift = 2;
+			} else if (IS_VDEC_DW(hw) == 8) {
+				w_shift = 1;
+				h_shift = 1;
+			}
+
+			addr = hw->buffer_spec[i].cma_alloc_addr + PAGE_ALIGN(orig_buf_size);
+			hw->buffer_spec[i].vdec_dw_y_addr = addr;
+			addr += ALIGN_WIDTH(hw->mb_width << w_shift) * ALIGN_HEIGHT(hw->mb_height << h_shift);
+			hw->buffer_spec[i].vdec_dw_u_addr = addr;
+			hw->buffer_spec[i].vdec_dw_v_addr = addr;
+			addr += hw->mb_total << (w_shift + h_shift - 1);
+
+			hw->buffer_spec[i].vdec_dw_canvas_config[0].phy_addr =
+				hw->buffer_spec[i].vdec_dw_y_addr;
+			hw->buffer_spec[i].vdec_dw_canvas_config[0].width =
+				ALIGN_WIDTH(hw->mb_width << w_shift);
+			hw->buffer_spec[i].vdec_dw_canvas_config[0].height =
+				ALIGN_HEIGHT(hw->mb_height << h_shift);
+			hw->buffer_spec[i].vdec_dw_canvas_config[0].block_mode =
+				hw->canvas_mode;
+
+			hw->buffer_spec[i].vdec_dw_canvas_config[1].phy_addr =
+				hw->buffer_spec[i].vdec_dw_u_addr;
+			hw->buffer_spec[i].vdec_dw_canvas_config[1].width =
+				ALIGN_WIDTH(hw->mb_width << w_shift);
+			hw->buffer_spec[i].vdec_dw_canvas_config[1].height =
+				ALIGN_HEIGHT(hw->mb_height << (h_shift - 1));
+			hw->buffer_spec[i].vdec_dw_canvas_config[1].block_mode =
+				hw->canvas_mode;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+			"%s, vdec_dw: alloc buf for bufspec%d blkmod %d\n",
+					__func__, i, hw->canvas_mode);
+		}
+#endif
+	}
+	return 0;
+}
+
+static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx)
+{
+	int ret = 0;
+	struct aml_vcodec_ctx *ctx = NULL;
+	struct buffer_spec_s *bs = &hw->buffer_spec[idx];
+	struct canvas_config_s *y_canvas_cfg = NULL;
+	struct canvas_config_s *c_canvas_cfg = NULL;
+	struct vdec_v4l2_buffer *fb = NULL;
+	unsigned int y_addr = 0, c_addr = 0;
+
+	if (IS_ERR_OR_NULL(hw->v4l2_ctx)) {
+		pr_err("the v4l context has err.\n");
+		return -1;
+	}
+
+	if (bs->cma_alloc_addr)
+		return 0;
+
+	ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
+		"[%d] %s(), try alloc from v4l queue buf size: %d\n",
+		ctx->id, __func__,
+		(hw->mb_total << 8) + (hw->mb_total << 7));
+
+	ret = ctx->fb_ops.alloc(&ctx->fb_ops, hw->fb_token, &fb, AML_FB_REQ_DEC);
+	if (ret < 0) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
+			"[%d] get fb fail.\n", ctx->id);
+		return ret;
+	}
+
+	bs->cma_alloc_addr = (unsigned long)fb;
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
+		"[%d] %s(), cma alloc addr: 0x%x, out %d dec %d\n",
+		ctx->id, __func__, bs->cma_alloc_addr,
+		ctx->cap_pool.out, ctx->cap_pool.dec);
+
+	if (fb->num_planes == 1) {
+		y_addr = fb->m.mem[0].addr;
+		c_addr = fb->m.mem[0].addr + fb->m.mem[0].offset;
+		fb->m.mem[0].bytes_used = fb->m.mem[0].size;
+	} else if (fb->num_planes == 2) {
+		y_addr = fb->m.mem[0].addr;
+		c_addr = fb->m.mem[1].addr;
+		fb->m.mem[0].bytes_used = fb->m.mem[0].size;
+		fb->m.mem[1].bytes_used = fb->m.mem[1].size;
+	}
+
+	fb->status	= FB_ST_DECODER;
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
+		"[%d] %s(), y_addr: %x, size: %u\n",
+		ctx->id, __func__, y_addr, fb->m.mem[0].size);
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
+		"[%d] %s(), c_addr: %x, size: %u\n",
+		ctx->id, __func__, c_addr, fb->m.mem[1].size);
+
+	bs->y_addr = y_addr;
+	bs->u_addr = c_addr;
+	bs->v_addr = c_addr;
+
+	y_canvas_cfg = &bs->canvas_config[0];
+	c_canvas_cfg = &bs->canvas_config[1];
+
+	y_canvas_cfg->phy_addr	= y_addr;
+	y_canvas_cfg->width	= hw->mb_width << 4;
+	y_canvas_cfg->height	= hw->mb_height << 4;
+	y_canvas_cfg->block_mode = hw->canvas_mode;
+	//fb->m.mem[0].bytes_used = y_canvas_cfg->width * y_canvas_cfg->height;
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
+		"[%d] %s(), y_w: %d, y_h: %d\n", ctx->id, __func__,
+		y_canvas_cfg->width,y_canvas_cfg->height);
+
+	c_canvas_cfg->phy_addr	= c_addr;
+	c_canvas_cfg->width	= hw->mb_width << 4;
+	c_canvas_cfg->height	= hw->mb_height << 3;
+	c_canvas_cfg->block_mode = hw->canvas_mode;
+	//fb->m.mem[1].bytes_used = c_canvas_cfg->width * c_canvas_cfg->height;
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
+		"[%d] %s(), c_w: %d, c_h: %d\n", ctx->id, __func__,
+		c_canvas_cfg->width, c_canvas_cfg->height);
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
+		"[%d] %s(), alloc buf for bufspec%d\n", ctx->id, __func__, idx);
+
+	return ret;
+}
+
+static void config_decode_canvas(struct vdec_h264_hw_s *hw, int i)
+{
+	int blkmode = hw->canvas_mode;
+	int endian = 0;
+
+	if (blkmode == CANVAS_BLKMODE_LINEAR) {
+		if ((h264_debug_flag & IGNORE_PARAM_FROM_CONFIG) == 0)
+			endian = 7;
+		else
+			endian = 0;
+	}
+
+	if (hw->is_used_v4l)
+		endian = 7;
+
+	config_cav_lut_ex(hw->buffer_spec[i].
+		y_canvas_index,
+		hw->buffer_spec[i].y_addr,
+		hw->mb_width << 4,
+		hw->mb_height << 4,
+		CANVAS_ADDR_NOWRAP,
+		blkmode,
+		endian,
+		VDEC_1);
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
+		WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32,
+				(1 << 11) | /* canvas_blk32_wr */
+				(blkmode << 10) | /* canvas_blk32*/
+				 (1 << 8) | /* canvas_index_wr*/
+				(hw->buffer_spec[i].y_canvas_index << 0) /* canvas index*/
+				);
+	}
+
+	config_cav_lut_ex(hw->buffer_spec[i].
+		u_canvas_index,
+		hw->buffer_spec[i].u_addr,
+		hw->mb_width << 4,
+		hw->mb_height << 3,
+		CANVAS_ADDR_NOWRAP,
+		blkmode,
+		endian,
+		VDEC_1);
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
+		WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32,
+				(1 << 11) |
+				(blkmode << 10) |
+				 (1 << 8) |
+				(hw->buffer_spec[i].u_canvas_index << 0));
+	}
+
+	WRITE_VREG(ANC0_CANVAS_ADDR + hw->buffer_spec[i].canvas_pos,
+		spec2canvas(&hw->buffer_spec[i]));
+
+
+#ifdef  VDEC_DW
+	if (!IS_VDEC_DW(hw))
+		return;
+	else {
+		config_cav_lut_ex(hw->buffer_spec[i].
+			vdec_dw_y_canvas_index,
+			hw->buffer_spec[i].vdec_dw_canvas_config[0].phy_addr,
+			hw->buffer_spec[i].vdec_dw_canvas_config[0].width,
+			hw->buffer_spec[i].vdec_dw_canvas_config[0].height,
+			CANVAS_ADDR_NOWRAP,
+			blkmode,
+			endian,
+			VDEC_1);
+		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
+			WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32,
+				(1 << 11) |
+				(blkmode << 10) |
+				(1 << 8) |
+				(hw->buffer_spec[i].vdec_dw_y_canvas_index << 0));
+		}
+
+		config_cav_lut_ex(hw->buffer_spec[i].
+			vdec_dw_u_canvas_index,
+			hw->buffer_spec[i].vdec_dw_canvas_config[1].phy_addr,
+			hw->buffer_spec[i].vdec_dw_canvas_config[1].width,
+			hw->buffer_spec[i].vdec_dw_canvas_config[1].height,
+			CANVAS_ADDR_NOWRAP,
+			blkmode,
+			endian,
+			VDEC_1);
+		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
+			WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32,
+				(1 << 11) |
+				(blkmode << 10) |
+				(1 << 8) |
+				(hw->buffer_spec[i].vdec_dw_u_canvas_index << 0));
+		}
+	}
+#endif
+}
+
+static void config_decode_canvas_ex(struct vdec_h264_hw_s *hw, int i)
+{
+	u32 blkmode = hw->canvas_mode;
+	int canvas_w;
+	int canvas_h;
+
+	canvas_w = hw->frame_width /
+		get_double_write_ratio(hw->double_write_mode);
+	canvas_h = hw->frame_height /
+		get_double_write_ratio(hw->double_write_mode);
+
+	if (hw->canvas_mode == 0)
+		canvas_w = ALIGN(canvas_w, 32);
+	else
+		canvas_w = ALIGN(canvas_w, 64);
+	canvas_h = ALIGN(canvas_h, 32);
+
+	config_cav_lut_ex(hw->buffer_spec[i].
+		y_canvas_index,
+		hw->buffer_spec[i].dw_y_adr,
+		canvas_w,
+		canvas_h,
+		CANVAS_ADDR_NOWRAP,
+		blkmode,
+		7,
+		VDEC_HEVC);
+
+	config_cav_lut_ex(hw->buffer_spec[i].
+		u_canvas_index,
+		hw->buffer_spec[i].dw_u_v_adr,
+		canvas_w,
+		canvas_h,
+		CANVAS_ADDR_NOWRAP,
+		blkmode,
+		7,
+		VDEC_HEVC);
+}
+
+static int v4l_get_free_buffer_spec(struct vdec_h264_hw_s *hw)
+{
+	int i;
+
+	for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+		if (hw->buffer_spec[i].cma_alloc_addr == 0)
+			return i;
+	}
+
+	return -1;
+}
+
+static int v4l_find_buffer_spec_idx(struct vdec_h264_hw_s *hw, unsigned int v4l_indx)
+{
+	int i;
+
+	for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+		if (hw->buffer_wrap[i] == v4l_indx)
+			return i;
+	}
+	return -1;
+}
+
+static int v4l_get_free_buf_idx(struct vdec_s *vdec)
+{
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	struct aml_vcodec_ctx * v4l = hw->v4l2_ctx;
+	struct v4l_buff_pool *pool = &v4l->cap_pool;
+	struct buffer_spec_s *pic = NULL;
+	int i, rt, idx = INVALID_IDX;
+	ulong flags;
+	u32 state = 0, index;
+
+	spin_lock_irqsave(&hw->bufspec_lock, flags);
+	for (i = 0; i < pool->in; ++i) {
+		state = (pool->seq[i] >> 16);
+		index = (pool->seq[i] & 0xffff);
+
+		switch (state) {
+		case V4L_CAP_BUFF_IN_DEC:
+			rt = v4l_find_buffer_spec_idx(hw, index);
+			if (rt >= 0) {
+				pic = &hw->buffer_spec[rt];
+				if ((pic->vf_ref == 0) &&
+					(pic->used == 0) &&
+					pic->cma_alloc_addr) {
+					idx = rt;
+				}
+			}
+			break;
+		case V4L_CAP_BUFF_IN_M2M:
+			rt = v4l_get_free_buffer_spec(hw);
+			if (rt >= 0) {
+				pic = &hw->buffer_spec[rt];
+				if (!alloc_one_buf_spec_from_queue(hw, rt)) {
+					struct vdec_v4l2_buffer *fb;
+					config_decode_canvas(hw, rt);
+					fb = (struct vdec_v4l2_buffer *)pic->cma_alloc_addr;
+					hw->buffer_wrap[rt] = fb->buf_idx;
+					idx = rt;
+				}
+			}
+			break;
+		default:
+			break;
+		}
+
+		if (idx != INVALID_IDX) {
+			pic->used = 1;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&hw->bufspec_lock, flags);
+
+	if (idx < 0) {
+		dpb_print(DECODE_ID(hw), 0, "%s fail, state %d\n", __func__, state);
+		for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+			dpb_print(DECODE_ID(hw), 0, "%s, %d\n",
+				__func__, hw->buffer_wrap[i]);
+		}
+		vmh264_dump_state(vdec);
+	} else {
+		struct vdec_v4l2_buffer *fb =
+			(struct vdec_v4l2_buffer *)pic->cma_alloc_addr;
+
+		fb->status = FB_ST_DECODER;
+	}
+
+	return idx;
+}
+
+int get_free_buf_idx(struct vdec_s *vdec)
+{
+	int i;
+	unsigned long addr, flags;
+	int index = -1;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	int buf_total = BUFSPEC_POOL_SIZE;
+
+	if (hw->is_used_v4l)
+		return v4l_get_free_buf_idx(vdec);
+
+	spin_lock_irqsave(&hw->bufspec_lock, flags);
+	/*hw->start_search_pos = 0;*/
+	for (i = hw->start_search_pos; i < buf_total; i++) {
+		if (hw->mmu_enable)
+			addr = hw->buffer_spec[i].alloc_header_addr;
+		else
+			addr = hw->buffer_spec[i].cma_alloc_addr;
+
+		if (hw->buffer_spec[i].vf_ref == 0 &&
+			hw->buffer_spec[i].used == 0 && addr) {
+			hw->buffer_spec[i].used = 1;
+			hw->start_search_pos = i+1;
+			index = i;
+			hw->buffer_wrap[i] = index;
+			break;
+		}
+	}
+	if (index < 0) {
+		for (i = 0; i < hw->start_search_pos; i++) {
+			if (hw->mmu_enable)
+				addr = hw->buffer_spec[i].alloc_header_addr;
+			else
+				addr = hw->buffer_spec[i].cma_alloc_addr;
+
+			if (hw->buffer_spec[i].vf_ref == 0 &&
+				hw->buffer_spec[i].used == 0 && addr) {
+				hw->buffer_spec[i].used = 1;
+				hw->start_search_pos = i+1;
+				index = i;
+				hw->buffer_wrap[i] = index;
+				break;
+			}
+		}
+	}
+
+	spin_unlock_irqrestore(&hw->bufspec_lock, flags);
+	if (hw->start_search_pos >= buf_total)
+		hw->start_search_pos = 0;
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL,
+			"%s, buf_spec_num %d\n", __func__, index);
+
+	if (index < 0) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
+			"%s fail\n", __func__);
+		vmh264_dump_state(vdec);
+	}
+
+	if (dpb_is_debug(DECODE_ID(hw),
+		PRINT_FLAG_DUMP_BUFSPEC))
+		dump_bufspec(hw, __func__);
+	return index;
+}
+
+int release_buf_spec_num(struct vdec_s *vdec, int buf_spec_num)
+{
+	/*u32 cur_buf_idx;*/
+	unsigned long flags;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_MMU_DETAIL,
+		"%s buf_spec_num %d used %d\n",
+		__func__, buf_spec_num,
+		buf_spec_num > 0 ? hw->buffer_spec[buf_spec_num].used : 0);
+	if (buf_spec_num >= 0 &&
+		buf_spec_num < BUFSPEC_POOL_SIZE
+		) {
+		spin_lock_irqsave(&hw->bufspec_lock, flags);
+		hw->buffer_spec[buf_spec_num].used = 0;
+		spin_unlock_irqrestore(&hw->bufspec_lock, flags);
+		if (hw->mmu_enable) {
+			/*WRITE_VREG(CURR_CANVAS_CTRL, buf_spec_num<<24);
+			cur_buf_idx = READ_VREG(CURR_CANVAS_CTRL);
+			cur_buf_idx = cur_buf_idx&0xff;*/
+			decoder_mmu_box_free_idx(hw->mmu_box, buf_spec_num);
+		}
+		release_aux_data(hw, buf_spec_num);
+	}
+	if (dpb_is_debug(DECODE_ID(hw),
+		PRINT_FLAG_DUMP_BUFSPEC))
+		dump_bufspec(hw, __func__);
+	return 0;
+}
+
+static void config_buf_specs(struct vdec_s *vdec)
+{
+	int i, j;
+	unsigned long flags;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	int mode = IS_VDEC_DW(hw) ? 2 : 1;
+
+	spin_lock_irqsave(&hw->bufspec_lock, flags);
+	for (i = 0, j = 0;
+		j < hw->dpb.mDPB.size
+		&& i < BUFSPEC_POOL_SIZE;
+		i++) {
+		int canvas;
+		if (hw->buffer_spec[i].used != -1)
+			continue;
+		if (vdec->parallel_dec == 1) {
+			if (hw->buffer_spec[i].y_canvas_index == -1)
+				hw->buffer_spec[i].y_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
+			if (hw->buffer_spec[i].u_canvas_index == -1) {
+				hw->buffer_spec[i].u_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
+				hw->buffer_spec[i].v_canvas_index = hw->buffer_spec[i].u_canvas_index;
+			}
+#ifdef VDEC_DW
+			if (IS_VDEC_DW(hw)) {
+				if (hw->buffer_spec[i].vdec_dw_y_canvas_index == -1)
+					hw->buffer_spec[i].vdec_dw_y_canvas_index =
+						vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
+				if (hw->buffer_spec[i].vdec_dw_u_canvas_index == -1) {
+					hw->buffer_spec[i].vdec_dw_u_canvas_index =
+						vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
+					hw->buffer_spec[i].vdec_dw_v_canvas_index =
+						hw->buffer_spec[i].vdec_dw_u_canvas_index;
+				}
+			}
+#endif
+		} else {
+			canvas = vdec->get_canvas(j * mode, 2);
+			hw->buffer_spec[i].y_canvas_index = canvas_y(canvas);
+			hw->buffer_spec[i].u_canvas_index = canvas_u(canvas);
+			hw->buffer_spec[i].v_canvas_index = canvas_v(canvas);
+			dpb_print(DECODE_ID(hw),
+					PRINT_FLAG_DPB_DETAIL,
+					"config canvas (%d) %x for bufspec %d\r\n",
+				j, canvas, i);
+#ifdef VDEC_DW
+		  if (IS_VDEC_DW(hw)) {
+			canvas = vdec->get_canvas(j * mode + 1, 2);
+			hw->buffer_spec[i].vdec_dw_y_canvas_index = canvas_y(canvas);
+			hw->buffer_spec[i].vdec_dw_u_canvas_index = canvas_u(canvas);
+			hw->buffer_spec[i].vdec_dw_v_canvas_index = canvas_v(canvas);
+			dpb_print(DECODE_ID(hw),
+				PRINT_FLAG_DPB_DETAIL,
+				"vdec_dw: config canvas (%d) %x for bufspec %d\r\n",
+				j, canvas, i);
+		  }
+#endif
+		}
+
+		hw->buffer_spec[i].used = 0;
+		hw->buffer_spec[i].canvas_pos = j;
+
+
+		j++;
+	}
+	spin_unlock_irqrestore(&hw->bufspec_lock, flags);
+}
+
+static void config_buf_specs_ex(struct vdec_s *vdec)
+{
+	int i, j;
+	unsigned long flags;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	int mode = IS_VDEC_DW(hw) ? 2 : 1;
+
+	spin_lock_irqsave(&hw->bufspec_lock, flags);
+	for (i = 0, j = 0;
+		j < hw->dpb.mDPB.size
+		&& i < BUFSPEC_POOL_SIZE;
+		i++) {
+		int canvas = 0;
+		if (hw->buffer_spec[i].used != -1)
+			continue;
+		if (vdec->parallel_dec == 1) {
+			if (hw->buffer_spec[i].y_canvas_index == -1)
+				hw->buffer_spec[i].y_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
+			if (hw->buffer_spec[i].u_canvas_index == -1) {
+				hw->buffer_spec[i].u_canvas_index = vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
+				hw->buffer_spec[i].v_canvas_index = hw->buffer_spec[i].u_canvas_index;
+			}
+#ifdef VDEC_DW
+			if (IS_VDEC_DW(hw)) {
+				if (hw->buffer_spec[i].vdec_dw_y_canvas_index == -1)
+					hw->buffer_spec[i].vdec_dw_y_canvas_index =
+						vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
+				if (hw->buffer_spec[i].vdec_dw_u_canvas_index == -1) {
+					hw->buffer_spec[i].vdec_dw_u_canvas_index =
+						vdec->get_canvas_ex(CORE_MASK_VDEC_1, vdec->id);
+					hw->buffer_spec[i].vdec_dw_v_canvas_index =
+						hw->buffer_spec[i].vdec_dw_u_canvas_index;
+				}
+			}
+#endif
+		} else {
+			canvas = vdec->get_canvas(j* mode, 2);
+			hw->buffer_spec[i].y_canvas_index = canvas_y(canvas);
+			hw->buffer_spec[i].u_canvas_index = canvas_u(canvas);
+			hw->buffer_spec[i].v_canvas_index = canvas_v(canvas);
+
+			dpb_print(DECODE_ID(hw),
+					PRINT_FLAG_DPB_DETAIL,
+					"config canvas (%d) %x for bufspec %d\r\n",
+				j, canvas, i);
+#ifdef VDEC_DW
+			if (IS_VDEC_DW(hw)) {
+				canvas = vdec->get_canvas(j*mode + 1, 2);
+				hw->buffer_spec[i].vdec_dw_y_canvas_index = canvas_y(canvas);
+				hw->buffer_spec[i].vdec_dw_u_canvas_index = canvas_u(canvas);
+				hw->buffer_spec[i].vdec_dw_v_canvas_index = canvas_v(canvas);
+				dpb_print(DECODE_ID(hw),
+					PRINT_FLAG_DPB_DETAIL,
+					"vdec_dw: config canvas (%d) %x for bufspec %d\r\n",
+					j, canvas, i);
+			}
+#endif
+		}
+
+		hw->buffer_spec[i].used = 0;
+		hw->buffer_spec[i].alloc_header_addr = 0;
+		hw->buffer_spec[i].canvas_pos = j;
+
+		j++;
+	}
+	spin_unlock_irqrestore(&hw->bufspec_lock, flags);
+}
+
+
+static void dealloc_buf_specs(struct vdec_h264_hw_s *hw,
+	unsigned char release_all)
+{
+	int i;
+	unsigned long flags;
+	unsigned char dealloc_flag = 0;
+	for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+		if (hw->buffer_spec[i].used == 4 ||
+			release_all) {
+			dealloc_flag = 1;
+			dpb_print(DECODE_ID(hw),
+				PRINT_FLAG_DPB_DETAIL,
+				"%s buf_spec_num %d\n",
+				__func__, i
+				);
+			spin_lock_irqsave
+				(&hw->bufspec_lock, flags);
+			hw->buffer_spec[i].used = -1;
+			spin_unlock_irqrestore
+				(&hw->bufspec_lock, flags);
+			release_aux_data(hw, i);
+
+			if (!hw->mmu_enable) {
+				if (hw->buffer_spec[i].cma_alloc_addr) {
+					if (!hw->is_used_v4l) {
+						decoder_bmmu_box_free_idx(
+							hw->bmmu_box,
+							i);
+					}
+					spin_lock_irqsave
+						(&hw->bufspec_lock, flags);
+					hw->buffer_spec[i].cma_alloc_addr = 0;
+					hw->buffer_spec[i].buf_adr = 0;
+					spin_unlock_irqrestore
+						(&hw->bufspec_lock, flags);
+				}
+			} else {
+				if (hw->buffer_spec[i].alloc_header_addr) {
+					decoder_mmu_box_free_idx(
+						hw->mmu_box,
+						i);
+					spin_lock_irqsave
+						(&hw->bufspec_lock, flags);
+					hw->buffer_spec[i].
+						alloc_header_addr = 0;
+					hw->buffer_spec[i].buf_adr = 0;
+					spin_unlock_irqrestore
+						(&hw->bufspec_lock, flags);
+				}
+			}
+		}
+	}
+	if (dealloc_flag &&
+		dpb_is_debug(DECODE_ID(hw),
+		PRINT_FLAG_DUMP_BUFSPEC))
+		dump_bufspec(hw, __func__);
+	return;
+}
+
+unsigned char have_free_buf_spec(struct vdec_s *vdec)
+{
+	int i;
+	unsigned long addr;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	struct aml_vcodec_ctx * ctx = hw->v4l2_ctx;
+	int canvas_pos_min = BUFSPEC_POOL_SIZE;
+	int index = -1;
+	int ret = 0;
+	int allocated_count = 0;
+
+	if (hw->is_used_v4l) {
+		struct h264_dpb_stru *dpb = &hw->dpb;
+
+		/* trigger to parse head data. */
+		if (!hw->v4l_params_parsed)
+			return 1;
+
+		if (dpb->mDPB.used_size >= dpb->mDPB.size - 1)
+			return 0;
+
+		for (i = 0; i < hw->dpb.mDPB.size; i++) {
+			if (hw->buffer_spec[i].used == 0 &&
+				hw->buffer_spec[i].vf_ref == 0 &&
+				hw->buffer_spec[i].cma_alloc_addr) {
+				return 1;
+			}
+		}
+
+		if (ctx->cap_pool.dec < hw->dpb.mDPB.size) {
+			if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) >=
+				run_ready_min_buf_num) {
+				if (ctx->fb_ops.query(&ctx->fb_ops, &hw->fb_token))
+					return 1;
+			}
+		}
+
+		return 0;
+	}
+
+	for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+		if (hw->mmu_enable)
+			addr = hw->buffer_spec[i].alloc_header_addr;
+		else
+			addr = hw->buffer_spec[i].cma_alloc_addr;
+		if (hw->buffer_spec[i].used == 0 &&
+			hw->buffer_spec[i].vf_ref == 0) {
+
+			if (addr)
+				return 1;
+			if (hw->buffer_spec[i].canvas_pos < canvas_pos_min) {
+				canvas_pos_min = hw->buffer_spec[i].canvas_pos;
+				index = i;
+			}
+		}
+		if (addr)
+			allocated_count++;
+	}
+	if (index >= 0) {
+		mutex_lock(&vmh264_mutex);
+		dealloc_buf_specs(hw, 0);
+		if (max_alloc_buf_count == 0 ||
+			allocated_count < max_alloc_buf_count) {
+			if (alloc_one_buf_spec(hw, index) >= 0)
+				ret = 1;
+		}
+		mutex_unlock(&vmh264_mutex);
+	}
+
+	return ret;
+}
+
+static int get_buf_spec_by_canvas_pos(struct vdec_h264_hw_s *hw,
+	int canvas_pos)
+{
+	int i;
+	int j = 0;
+	for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+		if (hw->buffer_spec[i].canvas_pos >= 0) {
+			if (j == canvas_pos)
+				return i;
+			j++;
+		}
+	}
+	return -1;
+}
+static void update_vf_memhandle(struct vdec_h264_hw_s *hw,
+	struct vframe_s *vf, int index)
+{
+	if (index < 0) {
+		vf->mem_handle = NULL;
+		vf->mem_head_handle = NULL;
+	} else if (vf->type & VIDTYPE_SCATTER) {
+		vf->mem_handle =
+			decoder_mmu_box_get_mem_handle(
+				hw->mmu_box, index);
+		vf->mem_head_handle =
+			decoder_bmmu_box_get_mem_handle(
+				hw->bmmu_box, HEADER_BUFFER_IDX(index));
+	} else {
+		vf->mem_handle =
+			decoder_bmmu_box_get_mem_handle(
+				hw->bmmu_box, VF_BUFFER_IDX(index));
+	/*	vf->mem_head_handle =
+			decoder_bmmu_box_get_mem_handle(
+				hw->bmmu_box, HEADER_BUFFER_IDX(index));*/
+	}
+	return;
+}
+static int check_force_interlace(struct vdec_h264_hw_s *hw,
+	struct FrameStore *frame)
+{
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	int bForceInterlace = 0;
+	/* no di in secure mode, disable force di */
+	if (vdec_secure(hw_to_vdec(hw)))
+		return 0;
+
+	if (hw->i_only)
+		return 0;
+
+	if ((dec_control & DEC_CONTROL_FLAG_FORCE_2997_1080P_INTERLACE)
+		&& hw->bitstream_restriction_flag
+		&& (hw->frame_width == 1920)
+		&& (hw->frame_height >= 1080) /* For being compatible with a fake progressive stream which is interlaced actually*/
+		&& (hw->frame_dur == 3203 || (hw->frame_dur == 3840 && p_H264_Dpb->mSPS.profile_idc == 100 &&
+		p_H264_Dpb->mSPS.level_idc == 40))) {
+		bForceInterlace = 1;
+	} else if ((dec_control & DEC_CONTROL_FLAG_FORCE_2500_576P_INTERLACE)
+			 && (hw->frame_width == 720)
+			 && (hw->frame_height == 576)
+			 && (hw->frame_dur == 3840)) {
+		bForceInterlace = 1;
+	}
+
+	return bForceInterlace;
+}
+
+static void fill_frame_info(struct vdec_h264_hw_s *hw, struct FrameStore *frame)
+{
+	struct vframe_qos_s *vframe_qos = &hw->vframe_qos;
+
+	if (frame->slice_type == I_SLICE)
+		vframe_qos->type = 1;
+	else if (frame->slice_type == P_SLICE)
+		vframe_qos->type = 2;
+	else if (frame->slice_type == B_SLICE)
+		vframe_qos->type = 3;
+
+	if (input_frame_based(hw_to_vdec(hw)))
+		vframe_qos->size = frame->frame_size2;
+	else
+		vframe_qos->size = frame->frame_size;
+	vframe_qos->pts = frame->pts64;
+
+	vframe_qos->max_mv = frame->max_mv;
+	vframe_qos->avg_mv = frame->avg_mv;
+	vframe_qos->min_mv = frame->min_mv;
+/*
+	pr_info("mv: max:%d,  avg:%d, min:%d\n",
+		vframe_qos->max_mv,
+		vframe_qos->avg_mv,
+		vframe_qos->min_mv);
+*/
+
+	vframe_qos->max_qp = frame->max_qp;
+	vframe_qos->avg_qp = frame->avg_qp;
+	vframe_qos->min_qp = frame->min_qp;
+/*
+	pr_info("qp: max:%d,  avg:%d, min:%d\n",
+		vframe_qos->max_qp,
+		vframe_qos->avg_qp,
+		vframe_qos->min_qp);
+*/
+
+	vframe_qos->max_skip = frame->max_skip;
+	vframe_qos->avg_skip = frame->avg_skip;
+	vframe_qos->min_skip = frame->min_skip;
+/*
+	pr_info("skip: max:%d,  avg:%d, min:%d\n",
+		vframe_qos->max_skip,
+		vframe_qos->avg_skip,
+		vframe_qos->min_skip);
+*/
+	vframe_qos->num++;
+}
+
+static int is_iframe(struct FrameStore *frame) {
+
+	if (frame->frame && frame->frame->slice_type == I_SLICE) {
+		return 1;
+	}
+	return 0;
+}
+
+static int post_prepare_process(struct vdec_s *vdec, struct FrameStore *frame)
+{
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	int buffer_index = frame->buf_spec_num;
+
+	if (buffer_index < 0 || buffer_index >= BUFSPEC_POOL_SIZE) {
+		dpb_print(DECODE_ID(hw), 0,
+			"%s, buffer_index 0x%x is beyond range\n",
+			__func__, buffer_index);
+		return -1;
+	}
+
+	if (force_disp_bufspec_num & 0x100) {
+		/*recycle directly*/
+		if (hw->buffer_spec[frame->buf_spec_num].used != 3 &&
+			hw->buffer_spec[frame->buf_spec_num].used != 5)
+			set_frame_output_flag(&hw->dpb, frame->index);
+
+		/*make pre_output not set*/
+		return -1;
+	}
+	if (error_proc_policy & 0x1000) {
+		int error_skip_i_count = (error_skip_count >> 12) & 0xf;
+		int error_skip_frame_count = error_skip_count & 0xfff;
+		if (((hw->no_error_count < error_skip_frame_count)
+			&& (error_skip_i_count == 0 ||
+			hw->no_error_i_count < error_skip_i_count))
+			&& (!(frame->data_flag & I_FLAG)))
+			frame->data_flag |= ERROR_FLAG;
+	}
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG,
+		"%s, buffer_index 0x%x  frame_error %x  poc %d hw error %x error_proc_policy %x\n",
+		__func__, buffer_index,
+		frame->data_flag & ERROR_FLAG,
+		frame->poc, hw->data_flag & ERROR_FLAG,
+		error_proc_policy);
+
+	if (frame->frame == NULL &&
+			((frame->is_used == 1 && frame->top_field)
+			|| (frame->is_used == 2 && frame->bottom_field))) {
+			if (hw->i_only) {
+				if (frame->is_used == 1)
+					dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+						"%s   No bottom_field !!  frame_num %d  used %d\n",
+						__func__, frame->frame_num, frame->is_used);
+				if (frame->is_used == 2)
+					dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+						"%s   No top_field !!  frame_num %d  used %d\n",
+						__func__, frame->frame_num, frame->is_used);
+			}
+			else {
+				frame->data_flag |= ERROR_FLAG;
+					dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG,
+					"%s Error  frame_num %d  used %d\n",
+					__func__, frame->frame_num, frame->is_used);
+			}
+	}
+	if (vdec_stream_based(vdec) && !(frame->data_flag & NODISP_FLAG)) {
+		if ((vdec->vbuf.no_parser == 0) || (vdec->vbuf.use_ptsserv)) {
+			if ((pts_lookup_offset_us64(PTS_TYPE_VIDEO,
+				frame->offset_delimiter, &frame->pts, &frame->frame_size,
+				0, &frame->pts64) == 0)) {
+				if ((lookup_check_conut && (hw->vf_pre_count > lookup_check_conut) &&
+					(hw->wrong_frame_count > hw->right_frame_count)) &&
+					((frame->decoded_frame_size * 2 < frame->frame_size))) {
+					/*resolve many frame only one check in pts, cause playback unsmooth issue*/
+					frame->pts64 = hw->last_pts64 +DUR2PTS(hw->frame_dur) ;
+					frame->pts = hw->last_pts + DUR2PTS(hw->frame_dur);
+				}
+				hw->right_frame_count++;
+			} else {
+				frame->pts64 = hw->last_pts64 +DUR2PTS(hw->frame_dur) ;
+				frame->pts = hw->last_pts + DUR2PTS(hw->frame_dur);
+				hw->wrong_frame_count++;
+			}
+		}
+
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+		"%s error= 0x%x poc = %d  offset= 0x%x pts= 0x%x last_pts =0x%x  pts64 = %lld  last_pts64= %lld  duration = %d\n",
+		__func__, (frame->data_flag & ERROR_FLAG), frame->poc,
+		frame->offset_delimiter, frame->pts,hw->last_pts,
+		frame->pts64, hw->last_pts64, hw->frame_dur);
+		hw->last_pts64 = frame->pts64;
+		hw->last_pts = frame->pts;
+	}
+
+	/* SWPL-18973 96000/15=6400, less than 15fps check */
+	if ((!hw->duration_from_pts_done) && (hw->frame_dur > 6400ULL)) {
+		if ((check_force_interlace(hw, frame)) &&
+			(frame->slice_type == I_SLICE) &&
+			(hw->pts_outside)) {
+			if ((!hw->h264_pts_count) || (!hw->h264pts1)) {
+				hw->h264pts1 = frame->pts;
+				hw->h264_pts_count = 0;
+			} else if (frame->pts > hw->h264pts1) {
+				u32 calc_dur =
+					PTS2DUR(frame->pts - hw->h264pts1);
+				calc_dur = ((calc_dur/hw->h264_pts_count) << 1);
+				if (hw->frame_dur < (calc_dur + 200) &&
+					hw->frame_dur > (calc_dur - 200)) {
+					hw->frame_dur >>= 1;
+					vdec_schedule_work(&hw->notify_work);
+					dpb_print(DECODE_ID(hw), 0,
+						"correct frame_dur %d, calc_dur %d, count %d\n",
+						hw->frame_dur, (calc_dur >> 1), hw->h264_pts_count);
+					hw->duration_from_pts_done = 1;
+					hw->h264_pts_count = 0;
+				}
+			}
+		}
+		hw->h264_pts_count++;
+	}
+
+	if (frame->data_flag & ERROR_FLAG) {
+		vdec_count_info(&hw->gvs, 1, 0);
+		if (frame->slice_type == I_SLICE) {
+			hw->gvs.i_concealed_frames++;
+		} else if (frame->slice_type == P_SLICE) {
+			hw->gvs.p_concealed_frames++;
+		} else if (frame->slice_type == B_SLICE) {
+			hw->gvs.b_concealed_frames++;
+		}
+		if (!hw->send_error_frame_flag) {
+			hw->gvs.drop_frame_count++;
+			if (frame->slice_type == I_SLICE) {
+				hw->gvs.i_lost_frames++;
+			} else if (frame->slice_type == P_SLICE) {
+				hw->gvs.p_lost_frames++;
+			} else if (frame->slice_type == B_SLICE) {
+				hw->gvs.b_lost_frames++;
+			}
+		}
+
+	}
+
+	if ((!hw->enable_fence) &&
+		((frame->data_flag & NODISP_FLAG) ||
+		(frame->data_flag & NULL_FLAG) ||
+		((!hw->send_error_frame_flag) &&
+		(frame->data_flag & ERROR_FLAG)) ||
+		((hw->i_only & 0x1) &&
+		(!(frame->data_flag & I_FLAG))))) {
+		frame->show_frame = false;
+		return 0;
+	}
+
+	if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL)) {
+		dpb_print(DECODE_ID(hw), 0,
+			"%s, fs[%d] poc %d, buf_spec_num %d\n",
+			__func__, frame->index, frame->poc,
+			frame->buf_spec_num);
+		print_pic_info(DECODE_ID(hw), "predis_frm",
+			frame->frame, -1);
+		print_pic_info(DECODE_ID(hw), "predis_top",
+			frame->top_field, -1);
+		print_pic_info(DECODE_ID(hw), "predis_bot",
+			frame->bottom_field, -1);
+	}
+
+	frame->show_frame = true;
+
+	return 0;
+}
+
+static int post_video_frame(struct vdec_s *vdec, struct FrameStore *frame)
+{
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	struct vframe_s *vf = NULL;
+	int buffer_index = frame->buf_spec_num;
+	struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+	struct vdec_v4l2_buffer *fb = NULL;
+	ulong nv_order = VIDTYPE_VIU_NV21;
+	int bForceInterlace = 0;
+	int vf_count = 1;
+	int i;
+
+	/* swap uv */
+	if (hw->is_used_v4l) {
+		if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) ||
+			(v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12M))
+			nv_order = VIDTYPE_VIU_NV12;
+	}
+
+	if (!is_interlace(frame))
+		vf_count = 1;
+	else
+		vf_count = 2;
+
+	bForceInterlace = check_force_interlace(hw, frame);
+	if (bForceInterlace)
+		vf_count = 2;
+
+	if (!hw->enable_fence)
+		hw->buffer_spec[buffer_index].vf_ref = 0;
+	fill_frame_info(hw, frame);
+
+	if ((hw->is_used_v4l) &&
+		(vdec->prog_only))
+		vf_count = 1;
+
+	for (i = 0; i < vf_count; i++) {
+		if (kfifo_get(&hw->newframe_q, &vf) == 0 ||
+			vf == NULL) {
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
+				"%s fatal error, no available buffer slot.\n",
+				__func__);
+			return -1;
+		}
+		vf->duration_pulldown = 0;
+		if (!(is_iframe(frame)) && hw->unstable_pts) {
+			vf->pts = 0;
+			vf->pts_us64 = 0;
+			vf->timestamp = 0;
+			vf->index = VF_INDEX(frame->index, buffer_index);
+		} else {
+			vf->pts = frame->pts;
+			vf->pts_us64 = frame->pts64;
+			vf->timestamp = frame->timestamp;
+			vf->index = VF_INDEX(frame->index, buffer_index);
+		}
+
+		if (hw->is_used_v4l) {
+			vf->v4l_mem_handle
+				= hw->buffer_spec[buffer_index].cma_alloc_addr;
+			fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
+		}
+
+		if (hw->enable_fence) {
+			/* fill fence information. */
+			if (hw->fence_usage == FENCE_USE_FOR_DRIVER)
+				vf->fence	= frame->fence;
+		}
+
+		if (hw->mmu_enable) {
+			if (hw->double_write_mode & 0x10) {
+				/* double write only */
+				vf->compBodyAddr = 0;
+				vf->compHeadAddr = 0;
+			} else {
+				/*head adr*/
+				vf->compHeadAddr =
+				hw->buffer_spec[buffer_index].alloc_header_addr;
+				/*body adr*/
+				vf->compBodyAddr = 0;
+				vf->canvas0Addr = vf->canvas1Addr = 0;
+			}
+
+			vf->type = VIDTYPE_SCATTER;
+
+			if (hw->double_write_mode) {
+				vf->type |= VIDTYPE_PROGRESSIVE
+					| VIDTYPE_VIU_FIELD;
+				vf->type |= nv_order;
+				if (hw->double_write_mode == 3)
+					vf->type |= VIDTYPE_COMPRESS;
+
+				vf->canvas0Addr = vf->canvas1Addr = -1;
+				vf->plane_num = 2;
+				vf->canvas0_config[0] =
+					hw->buffer_spec[buffer_index].
+						canvas_config[0];
+				vf->canvas0_config[1] =
+					hw->buffer_spec[buffer_index].
+						canvas_config[1];
+
+				vf->canvas1_config[0] =
+					hw->buffer_spec[buffer_index].
+						canvas_config[0];
+				vf->canvas1_config[1] =
+					hw->buffer_spec[buffer_index].
+						canvas_config[1];
+
+			} else {
+				vf->type |=
+					VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD;
+				vf->canvas0Addr = vf->canvas1Addr = 0;
+			}
+
+			vf->bitdepth =
+				BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8;
+
+			vf->compWidth = hw->frame_width;
+			vf->compHeight = hw->frame_height;
+		} else {
+			vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD |
+				nv_order;
+
+			vf->canvas0Addr = vf->canvas1Addr =
+			spec2canvas(&hw->buffer_spec[buffer_index]);
+#ifdef VDEC_DW
+			if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_T7) {
+				if (IS_VDEC_DW(hw))
+					vf->canvas0Addr = vf->canvas1Addr =
+						vdec_dw_spec2canvas(&hw->buffer_spec[buffer_index]);
+			} else {
+				if (IS_VDEC_DW(hw))
+					vf->canvas0Addr = vf->canvas1Addr = -1;
+			}
+#endif
+
+		}
+		set_frame_info(hw, vf, buffer_index);
+		if (hw->discard_dv_data) {
+			vf->discard_dv_data = true;
+		}
+
+		if (hw->mmu_enable && hw->double_write_mode) {
+			vf->width = hw->frame_width /
+				get_double_write_ratio(hw->double_write_mode);
+			vf->height = hw->frame_height /
+				get_double_write_ratio(hw->double_write_mode);
+		}
+
+		if (frame->slice_type == I_SLICE) {
+			vf->frame_type |= V4L2_BUF_FLAG_KEYFRAME;
+		} else if (frame->slice_type == P_SLICE) {
+			vf->frame_type |= V4L2_BUF_FLAG_PFRAME;
+		} else if (frame->slice_type == B_SLICE) {
+			vf->frame_type |= V4L2_BUF_FLAG_BFRAME;
+		}
+
+		vf->flag = 0;
+		if (frame->data_flag & I_FLAG)
+			vf->flag |= VFRAME_FLAG_SYNCFRAME;
+		if (frame->data_flag & ERROR_FLAG)
+			vf->flag |= VFRAME_FLAG_ERROR_RECOVERY;
+		update_vf_memhandle(hw, vf, buffer_index);
+
+		if (!hw->enable_fence) {
+			hw->buffer_spec[buffer_index].used = 2;
+			hw->buffer_spec[buffer_index].vf_ref++;
+		}
+
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL,
+			"%s %d frame = %p top_field = %p bottom_field = %p\n", __func__, __LINE__, frame->frame,
+			frame->top_field, frame->bottom_field);
+
+		if (frame->frame != NULL) {
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL,
+				"%s %d coded_frame = %d frame_mbs_only_flag = %d structure = %d\n", __func__, __LINE__,
+				frame->frame->coded_frame, frame->frame->frame_mbs_only_flag, frame->frame->structure);
+		}
+
+		if (bForceInterlace || is_interlace(frame)) {
+			vf->type =
+				VIDTYPE_INTERLACE_FIRST |
+				nv_order;
+
+			if (frame->frame != NULL &&
+				(frame->frame->pic_struct == PIC_TOP_BOT ||
+				frame->frame->pic_struct == PIC_BOT_TOP) &&
+				frame->frame->coded_frame) {
+				if (frame->frame != NULL && frame->frame->pic_struct == PIC_TOP_BOT) {
+				vf->type |= (i == 0 ?
+					VIDTYPE_INTERLACE_TOP :
+					VIDTYPE_INTERLACE_BOTTOM);
+				} else if (frame->frame != NULL && frame->frame->pic_struct == PIC_BOT_TOP) {
+					vf->type |= (i == 0 ?
+					VIDTYPE_INTERLACE_BOTTOM :
+					VIDTYPE_INTERLACE_TOP);
+				}
+			} else if (frame->top_field != NULL && frame->bottom_field != NULL) {/*top first*/
+				if (frame->top_field->poc <= frame->bottom_field->poc)
+					vf->type |= (i == 0 ?
+						VIDTYPE_INTERLACE_TOP :
+						VIDTYPE_INTERLACE_BOTTOM);
+				else
+					vf->type |= (i == 0 ?
+						VIDTYPE_INTERLACE_BOTTOM :
+						VIDTYPE_INTERLACE_TOP);
+			} else {
+				vf->type |= (i == 0 ?
+					VIDTYPE_INTERLACE_TOP :
+					VIDTYPE_INTERLACE_BOTTOM);
+			}
+			vf->duration = vf->duration/2;
+			if (i == 1) {
+				vf->pts = 0;
+				vf->pts_us64 = 0;
+			}
+
+			if (frame->frame) {
+				dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL,
+					"%s %d type = 0x%x pic_struct = %d pts = 0x%x pts_us64 = 0x%llx bForceInterlace = %d\n",
+					__func__, __LINE__, vf->type, frame->frame->pic_struct,
+					vf->pts, vf->pts_us64, bForceInterlace);
+			}
+		}
+
+		if (hw->i_only) {
+			if (vf_count == 1 && frame->is_used == 1 && frame->top_field
+				&& frame->bottom_field == NULL && frame->frame == NULL) {
+				vf->type =
+					VIDTYPE_INTERLACE_FIRST |
+					nv_order;
+				vf->type |= VIDTYPE_INTERLACE_TOP;
+				vf->duration = vf->duration/2;
+			}
+
+			if (vf_count == 1 && frame->is_used == 2 && frame->bottom_field
+				&& frame->top_field == NULL && frame->frame == NULL) {
+				vf->type =
+					VIDTYPE_INTERLACE_FIRST |
+					nv_order;
+				vf->type |= VIDTYPE_INTERLACE_BOTTOM;
+				vf->duration = vf->duration/2;
+			}
+		}
+
+		/*vf->ratio_control |= (0x3FF << DISP_RATIO_ASPECT_RATIO_BIT);*/
+		vf->sar_width = hw->width_aspect_ratio;
+		vf->sar_height = hw->height_aspect_ratio;
+		if (!vdec->vbuf.use_ptsserv && vdec_stream_based(vdec)) {
+			/* offset for tsplayer pts lookup */
+			if (i == 0) {
+				vf->pts_us64 =
+					(((u64)vf->duration << 32) &
+					0xffffffff00000000) | frame->offset_delimiter;
+				vf->pts = 0;
+			} else {
+				vf->pts_us64 = (u64)-1;
+				vf->pts = 0;
+			}
+		}
+
+		hw->vf_pre_count++;
+		vdec_vframe_ready(hw_to_vdec(hw), vf);
+		if (!frame->show_frame) {
+			vh264_vf_put(vf, vdec);
+			atomic_add(1, &hw->vf_get_count);
+			continue;
+		}
+
+		if (i == 0) {
+			struct vdec_s *pvdec;
+			struct vdec_info vs;
+
+			pvdec = hw_to_vdec(hw);
+			memset(&vs, 0, sizeof(struct vdec_info));
+			pvdec->dec_status(pvdec, &vs);
+			decoder_do_frame_check(pvdec, vf);
+			vdec_fill_vdec_frame(pvdec, &hw->vframe_qos, &vs, vf, frame->hw_decode_time);
+
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL,
+			"[%s:%d] i_decoded_frame = %d p_decoded_frame = %d b_decoded_frame = %d\n",
+			__func__, __LINE__,vs.i_decoded_frames,vs.p_decoded_frames,vs.b_decoded_frames);
+		}
+
+		kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
+		ATRACE_COUNTER(hw->trace.pts_name, vf->pts);
+		ATRACE_COUNTER(hw->trace.disp_q_name, kfifo_len(&hw->display_q));
+		ATRACE_COUNTER(hw->trace.new_q_name, kfifo_len(&hw->newframe_q));
+		hw->vf_pre_count++;
+		vdec->vdec_fps_detec(vdec->id);
+#ifdef AUX_DATA_CRC
+		decoder_do_aux_data_check(vdec, hw->buffer_spec[buffer_index].aux_data_buf,
+			hw->buffer_spec[buffer_index].aux_data_size);
+#endif
+
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_SEI_DETAIL, "aux_data_size: %d, signal_type: 0x%x\n",
+			hw->buffer_spec[buffer_index].aux_data_size, hw->video_signal_type);
+
+		if (dpb_is_debug(DECODE_ID(hw), PRINT_FLAG_SEI_DETAIL)) {
+			int i = 0;
+			PR_INIT(128);
+
+			for (i = 0; i < hw->buffer_spec[buffer_index].aux_data_size; i++) {
+				PR_FILL("%02x ", hw->buffer_spec[buffer_index].aux_data_buf[i]);
+				if (((i + 1) & 0xf) == 0)
+					PR_INFO(hw->id);
+			}
+			PR_INFO(hw->id);
+		}
+
+		if (hw->is_used_v4l) {
+			update_vframe_src_fmt(vf,
+				hw->buffer_spec[buffer_index].aux_data_buf,
+				hw->buffer_spec[buffer_index].aux_data_size,
+				false, vdec->vf_provider_name, NULL);
+		}
+
+		if (without_display_mode == 0) {
+			if (hw->is_used_v4l) {
+				if (v4l2_ctx->is_stream_off) {
+					vh264_vf_put(vh264_vf_get(vdec), vdec);
+				} else {
+					fb->task->submit(fb->task, TASK_TYPE_DEC);
+				}
+			} else
+				vf_notify_receiver(vdec->vf_provider_name,
+					VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+		} else
+			vh264_vf_put(vh264_vf_get(vdec), vdec);
+	}
+	if (dpb_is_debug(DECODE_ID(hw),
+		PRINT_FLAG_DUMP_BUFSPEC))
+		dump_bufspec(hw, __func__);
+
+	return 0;
+}
+
+int post_picture_early(struct vdec_s *vdec, int index)
+{
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	struct h264_dpb_stru *dpb_stru = &hw->dpb;
+	struct FrameStore fs;
+	u32 offset_lo, offset_hi;
+
+	if (!hw->enable_fence)
+		return 0;
+
+	/* create fence for each buffers. */
+	if (vdec_timeline_create_fence(vdec->sync))
+		return -1;
+
+	memset(&fs, 0, sizeof(fs));
+
+	fs.buf_spec_num		= index;
+	fs.fence		= vdec->sync->fence;
+	fs.slice_type		= dpb_stru->mSlice.slice_type;
+	fs.dpb_frame_count	= dpb_stru->dpb_frame_count;
+
+	offset_lo = dpb_stru->dpb_param.l.data[OFFSET_DELIMITER_LO];
+	offset_hi = dpb_stru->dpb_param.l.data[OFFSET_DELIMITER_HI];
+	fs.offset_delimiter	= (offset_lo | offset_hi << 16);
+
+	if (hw->chunk) {
+		fs.pts		= hw->chunk->pts;
+		fs.pts64	= hw->chunk->pts64;
+		fs.timestamp	= hw->chunk->timestamp;
+	}
+	fs.show_frame = true;
+	post_video_frame(vdec, &fs);
+
+	display_frame_count[DECODE_ID(hw)]++;
+	return 0;
+}
+
+int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame)
+{
+	struct vdec_h264_hw_s *hw =
+		(struct vdec_h264_hw_s *)vdec->private;
+
+	if (hw->enable_fence) {
+		int i, j, used_size, ret;
+		int signed_count = 0;
+		struct vframe_s *signed_fence[VF_POOL_SIZE];
+
+		post_prepare_process(vdec, frame);
+
+		if (!frame->show_frame)
+			pr_info("do not display.\n");
+
+		hw->buffer_spec[frame->buf_spec_num].used = 2;
+		hw->buffer_spec[frame->buf_spec_num].vf_ref = 1;
+		hw->buffer_spec[frame->buf_spec_num].fs_idx = frame->index;
+
+		/* notify signal to wake up wq of fence. */
+		vdec_timeline_increase(vdec->sync, 1);
+
+		mutex_lock(&hw->fence_mutex);
+		used_size = hw->fence_vf_s.used_size;
+		if (used_size) {
+			for (i = 0, j = 0; i < VF_POOL_SIZE && j < used_size; i++) {
+				if (hw->fence_vf_s.fence_vf[i] != NULL) {
+					ret = dma_fence_get_status(hw->fence_vf_s.fence_vf[i]->fence);
+					if (ret == 1) {
+						signed_fence[signed_count] = hw->fence_vf_s.fence_vf[i];
+						hw->fence_vf_s.fence_vf[i] = NULL;
+						hw->fence_vf_s.used_size--;
+						signed_count++;
+					}
+					j++;
+				}
+			}
+		}
+		mutex_unlock(&hw->fence_mutex);
+		if (signed_count != 0) {
+			for (i = 0; i < signed_count; i++)
+				vh264_vf_put(signed_fence[i], vdec);
+		}
+
+		return 0;
+	}
+
+	if (post_prepare_process(vdec, frame))
+		return -1;
+
+	if (post_video_frame(vdec, frame))
+		return -1;
+
+	display_frame_count[DECODE_ID(hw)]++;
+	return 0;
+}
+
+int notify_v4l_eos(struct vdec_s *vdec)
+{
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+	struct vframe_s *vf = &hw->vframe_dummy;
+	struct vdec_v4l2_buffer *fb = NULL;
+	int index = INVALID_IDX;
+	ulong expires;
+
+	if (hw->eos) {
+		if (hw->is_used_v4l) {
+			expires = jiffies + msecs_to_jiffies(2000);
+			while (INVALID_IDX == (index = v4l_get_free_buf_idx(vdec))) {
+				if (time_after(jiffies, expires) ||
+					v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx))
+					break;
+			}
+
+			if (index == INVALID_IDX) {
+				ctx->fb_ops.query(&ctx->fb_ops, &hw->fb_token);
+				if (ctx->fb_ops.alloc(&ctx->fb_ops, hw->fb_token, &fb, AML_FB_REQ_DEC) < 0) {
+					pr_err("[%d] EOS get free buff fail.\n", ctx->id);
+					return -1;
+				}
+			}
+		}
+
+		vf->type		|= VIDTYPE_V4L_EOS;
+		vf->timestamp		= ULONG_MAX;
+		vf->flag		= VFRAME_FLAG_EMPTY_FRAME_V4L;
+		vf->v4l_mem_handle	= (index == INVALID_IDX) ? (ulong)fb :
+					hw->buffer_spec[index].cma_alloc_addr;
+		fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
+
+		vdec_vframe_ready(vdec, vf);
+		kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
+
+		ATRACE_COUNTER(hw->trace.pts_name, vf->pts);
+
+		if (hw->is_used_v4l)
+			fb->task->submit(fb->task, TASK_TYPE_DEC);
+		else
+			vf_notify_receiver(vdec->vf_provider_name,
+				VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+
+		pr_info("[%d] H264 EOS notify.\n", (hw->is_used_v4l)?ctx->id:vdec->id);
+	}
+
+	return 0;
+}
+
+/******************
+ * Hardware config
+ */
+char *slice_type_name[] = {
+	"P_SLICE ",
+	"B_SLICE ",
+	"I_SLICE ",
+	"SP_SLICE",
+	"SI_SLICE",
+};
+
+char *picture_structure_name[] = {
+	"FRAME",
+	"TOP_FIELD",
+	"BOTTOM_FIELD"
+};
+
+void print_pic_info(int decindex, const char *info,
+			struct StorablePicture *pic,
+			int slice_type)
+{
+	if (pic)
+		dpb_print(decindex, PRINT_FLAG_DEC_DETAIL,
+		"%s: %s (original %s), %s, mb_aff_frame_flag %d  poc %d, pic_num %d, buf_spec_num %d data_flag 0x%x\n",
+		info,
+		picture_structure_name[pic->structure],
+		pic->coded_frame ? "Frame" : "Field",
+		(slice_type < 0 ||
+		slice_type >= (sizeof(slice_type_name) / sizeof(slice_type_name[0]))) ? "" : slice_type_name[slice_type],
+		pic->mb_aff_frame_flag,
+		pic->poc,
+		pic->pic_num,
+		pic->buf_spec_num,
+		pic->data_flag);
+}
+
+static void reset_process_time(struct vdec_h264_hw_s *hw)
+{
+	if (hw->start_process_time) {
+		unsigned process_time =
+			1000 * (jiffies - hw->start_process_time) / HZ;
+		hw->start_process_time = 0;
+		if (process_time > max_process_time[DECODE_ID(hw)])
+			max_process_time[DECODE_ID(hw)] = process_time;
+	}
+}
+
+static void start_process_time(struct vdec_h264_hw_s *hw)
+{
+	hw->decode_timeout_count = 10;
+	hw->start_process_time = jiffies;
+}
+
+static void config_aux_buf(struct vdec_h264_hw_s *hw)
+{
+	WRITE_VREG(H264_AUX_ADR, hw->aux_phy_addr);
+	WRITE_VREG(H264_AUX_DATA_SIZE,
+		((hw->prefix_aux_size >> 4) << 16) |
+		(hw->suffix_aux_size >> 4)
+		);
+}
+
+/*
+* dv_meta_flag: 1, dolby meta only; 2, not include dolby meta
+*/
+static void set_aux_data(struct vdec_h264_hw_s *hw,
+	struct StorablePicture *pic, unsigned char suffix_flag,
+	unsigned char dv_meta_flag, struct vdec_h264_hw_s *hw_b)
+{
+	int i;
+	unsigned short *aux_adr;
+	unsigned size_reg_val =
+		READ_VREG(H264_AUX_DATA_SIZE);
+	unsigned aux_count = 0;
+	int aux_size = 0;
+	struct vdec_h264_hw_s *hw_buf = hw_b ? hw_b : hw;
+	if (pic == NULL || pic->buf_spec_num < 0 || pic->buf_spec_num >= BUFSPEC_POOL_SIZE
+		|| (!is_buf_spec_in_use(hw, pic->buf_spec_num)))
+		return;
+
+	if (suffix_flag) {
+		aux_adr = (unsigned short *)
+			(hw_buf->aux_addr +
+			hw_buf->prefix_aux_size);
+		aux_count =
+		((size_reg_val & 0xffff) << 4)
+			>> 1;
+		aux_size =
+			hw_buf->suffix_aux_size;
+	} else {
+		aux_adr =
+		(unsigned short *)hw_buf->aux_addr;
+		aux_count =
+		((size_reg_val >> 16) << 4)
+			>> 1;
+		aux_size =
+			hw_buf->prefix_aux_size;
+	}
+	if (dpb_is_debug(DECODE_ID(hw),
+		 PRINT_FLAG_SEI_DETAIL)) {
+		dpb_print(DECODE_ID(hw), 0,
+			"%s:poc %d old size %d count %d,suf %d dv_flag %d\r\n",
+			__func__, pic->poc, AUX_DATA_SIZE(pic),
+			aux_count, suffix_flag, dv_meta_flag);
+	}
+	if (aux_size > 0 && aux_count > 0) {
+		int heads_size = 0;
+		int new_size;
+		char *new_buf;
+		for (i = 0; i < aux_count; i++) {
+			unsigned char tag = aux_adr[i] >> 8;
+			if (tag != 0 && tag != 0xff) {
+				if (dv_meta_flag == 0)
+					heads_size += 8;
+				else if (dv_meta_flag == 1 && tag == 0x1)
+					heads_size += 8;
+				else if (dv_meta_flag == 2 && tag != 0x1)
+					heads_size += 8;
+			}
+		}
+		new_size = AUX_DATA_SIZE(pic) + aux_count + heads_size;
+		new_buf = krealloc(AUX_DATA_BUF(pic),
+			new_size,
+			GFP_KERNEL);
+		if (new_buf) {
+			unsigned char valid_tag = 0;
+			unsigned char *h =
+				new_buf +
+				AUX_DATA_SIZE(pic);
+			unsigned char *p = h + 8;
+			int len = 0;
+			int padding_len = 0;
+			AUX_DATA_BUF(pic) = new_buf;
+			for (i = 0; i < aux_count; i += 4) {
+				int ii;
+				unsigned char tag = aux_adr[i + 3] >> 8;
+				if (tag != 0 && tag != 0xff) {
+					if (dv_meta_flag == 0)
+						valid_tag = 1;
+					else if (dv_meta_flag == 1
+						&& tag == 0x1)
+						valid_tag = 1;
+					else if (dv_meta_flag == 2
+						&& tag != 0x1)
+						valid_tag = 1;
+					else
+						valid_tag = 0;
+					if (valid_tag && len > 0) {
+						AUX_DATA_SIZE(pic) +=
+						(len + 8);
+						h[0] =
+						(len >> 24) & 0xff;
+						h[1] =
+						(len >> 16) & 0xff;
+						h[2] =
+						(len >> 8) & 0xff;
+						h[3] =
+						(len >> 0) & 0xff;
+						h[6] =
+						(padding_len >> 8)
+						& 0xff;
+						h[7] =
+						(padding_len) & 0xff;
+						h += (len + 8);
+						p += 8;
+						len = 0;
+						padding_len = 0;
+					}
+					if (valid_tag) {
+						h[4] = tag;
+						h[5] = 0;
+						h[6] = 0;
+						h[7] = 0;
+					}
+				}
+				if (valid_tag) {
+					for (ii = 0; ii < 4; ii++) {
+						unsigned short aa =
+							aux_adr[i + 3
+							- ii];
+						*p = aa & 0xff;
+						p++;
+						len++;
+						/*if ((aa >> 8) == 0xff)
+							padding_len++;*/
+					}
+				}
+			}
+			if (len > 0) {
+				AUX_DATA_SIZE(pic) += (len + 8);
+				h[0] = (len >> 24) & 0xff;
+				h[1] = (len >> 16) & 0xff;
+				h[2] = (len >> 8) & 0xff;
+				h[3] = (len >> 0) & 0xff;
+				h[6] = (padding_len >> 8) & 0xff;
+				h[7] = (padding_len) & 0xff;
+			}
+			if (dpb_is_debug(DECODE_ID(hw),
+				PRINT_FLAG_SEI_DETAIL)) {
+				dpb_print(DECODE_ID(hw), 0,
+					"aux: (size %d) suffix_flag %d\n",
+					AUX_DATA_SIZE(pic), suffix_flag);
+				for (i = 0; i < AUX_DATA_SIZE(pic); i++) {
+					dpb_print_cont(DECODE_ID(hw), 0,
+						"%02x ", AUX_DATA_BUF(pic)[i]);
+					if (((i + 1) & 0xf) == 0)
+						dpb_print_cont(
+						DECODE_ID(hw),
+							0, "\n");
+				}
+				dpb_print_cont(DECODE_ID(hw),
+					0, "\n");
+			}
+
+		}
+	}
+
+}
+
+static void release_aux_data(struct vdec_h264_hw_s *hw,
+	int buf_spec_num)
+{
+	kfree(hw->buffer_spec[buf_spec_num].aux_data_buf);
+	hw->buffer_spec[buf_spec_num].aux_data_buf = NULL;
+	hw->buffer_spec[buf_spec_num].aux_data_size = 0;
+}
+
+static void dump_aux_buf(struct vdec_h264_hw_s *hw)
+{
+	int i;
+	unsigned short *aux_adr =
+		(unsigned short *)
+		hw->aux_addr;
+	unsigned aux_size =
+		(READ_VREG(H264_AUX_DATA_SIZE)
+		>> 16) << 4;
+
+	if (hw->prefix_aux_size > 0) {
+		dpb_print(DECODE_ID(hw),
+			0,
+			"prefix aux: (size %d)\n",
+			aux_size);
+		for (i = 0; i <
+		(aux_size >> 1); i++) {
+			dpb_print_cont(DECODE_ID(hw),
+				0,
+				"%04x ",
+				*(aux_adr + i));
+			if (((i + 1) & 0xf)
+				== 0)
+				dpb_print_cont(
+				DECODE_ID(hw),
+				0, "\n");
+		}
+	}
+	if (hw->suffix_aux_size > 0) {
+		aux_adr = (unsigned short *)
+			(hw->aux_addr +
+			hw->prefix_aux_size);
+		aux_size =
+		(READ_VREG(H264_AUX_DATA_SIZE) & 0xffff)
+			<< 4;
+		dpb_print(DECODE_ID(hw),
+			0,
+			"suffix aux: (size %d)\n",
+			aux_size);
+		for (i = 0; i <
+		(aux_size >> 1); i++) {
+			dpb_print_cont(DECODE_ID(hw),
+				0,
+				"%04x ", *(aux_adr + i));
+			if (((i + 1) & 0xf) == 0)
+				dpb_print_cont(DECODE_ID(hw),
+				0, "\n");
+		}
+	}
+}
+
+#ifdef VDEC_DW
+
+struct vdec_dw_param_set{
+	char dw_x_shrink_1st;
+	char dw_x_shrink_2nd;
+	char dw_x_shrink_3rd;
+	char dw_y_shrink_1st;
+	char dw_y_shrink_2nd;
+	char dw_y_shrink_3rd;
+	char dw_merge_8to16;
+	char dw_merge_16to32;
+	char dw_dma_blk_mode;
+	char dw_bwsave_mode;
+};
+//#define FOR_LPDDR4_EFFICIENCY
+
+static void h264_vdec_dw_cfg(struct vdec_h264_hw_s *hw, int canvas_pos)
+{
+	u32 data32 = 0, stride = 0;
+	struct vdec_dw_param_set *p = NULL;
+	struct vdec_dw_param_set dw_param_set_pool[] = {
+		/*x1, x2, x3, y1, y2, y3, m8t6, m16to32 */
+		//{0, 0, 0, 0, 0, 0, 0, 0, 0, 1},	/* 1/1, 1/1 */
+		{1, 0, 0, 0, 0, 0, 0, 0, 0, 1},		/* 1/2, 1/1 */
+		{1, 0, 0, 1, 0, 0, 0, 0, 0, 1},		/* 1/2, 1/2 */
+		//{1, 0, 0, 1, 1, 0, 0, 0, 0, 1},	/* 1/4, 1/2 */
+		{2, 0, 1, 1, 3, 0, 0, 1, 0, 1},		/* 1/4, 1/4 */
+		//{1, 1, 1, 0, 1, 1, 1, 1, 0, 1},	/*> 1080p 1/8, 1/4 */
+		{1, 1, 1, 1, 1, 1, 1, 1, 0, 1},		/*> 1080p 1/8, 1/8 */
+	};
+
+	if (IS_VDEC_DW(hw))
+		p = &dw_param_set_pool[__ffs(IS_VDEC_DW(hw))];
+	else
+		return;
+
+	WRITE_VREG(MDEC_DOUBLEW_CFG3,
+		hw->buffer_spec[canvas_pos].vdec_dw_y_addr); // luma start address
+	WRITE_VREG(MDEC_DOUBLEW_CFG4,
+		hw->buffer_spec[canvas_pos].vdec_dw_u_addr); // chroma start address
+
+	stride = ALIGN_WIDTH((hw->mb_width << 4) / (IS_VDEC_DW(hw)));
+	if ((IS_VDEC_DW(hw)) == 1)	//width 1/2
+		stride >>= 1;
+	data32 = (stride << 16) | stride;
+	WRITE_VREG(MDEC_DOUBLEW_CFG5, data32); // chroma stride | luma stride
+
+	data32 = 0;
+	p->dw_dma_blk_mode = hw->canvas_mode;
+	data32 |= ((p->dw_x_shrink_1st << 0 ) |     // 1st down-scale horizontal, 00:no-scale 01:1/2avg 10:left 11:right
+		(p->dw_y_shrink_1st << 2 ) |     // 1st down-scale vertical,   00:no-scale 01:1/2avg 10:up   11:down
+		(p->dw_x_shrink_2nd << 4 ) |     // 2nd down-scale horizontal, 00:no-scale 01:1/2avg 10:left 11:right
+		(p->dw_y_shrink_2nd << 6 ) |     // 2nd down-scale vertical,   00:no-scale 01:1/2avg 10:up   11:down
+		(p->dw_x_shrink_3rd << 8 ) |     // 3rd down-scale horizontal, 00:no-scale 01:1/2avg 10:left 11:right
+		(p->dw_y_shrink_3rd << 10) |     // 3rd down-scale vertical,   00:no-scale 01:1/2avg 10:up   11:down
+		(p->dw_merge_8to16 << 12 ) |     //  8->16 horizontal block merge for better ddr efficiency
+		(p->dw_merge_16to32 << 13) |     // 16->32 horizontal block merge for better ddr efficiency
+		(p->dw_dma_blk_mode << 14) |     // DMA block mode, 0:linear 1:32x32 2:64x32
+#ifdef FOR_LPDDR4_EFFICIENCY
+		(1 << 19) |
+#endif
+		(p->dw_bwsave_mode << 22));      // Save line buffers to save band width
+	WRITE_VREG(MDEC_DOUBLEW_CFG1, data32); // add some special tests here
+
+	data32 = 0;
+	data32 |= (1 << 0) | (0 << 27);
+	WRITE_VREG(MDEC_DOUBLEW_CFG0, data32); // Double Write Enable | source from dblk
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+		"vdec_double_write mode %d\n",
+		IS_VDEC_DW(hw));
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+		"param {%d, %d, %d, %d, %d, %d, %d, %d, %d}\n",
+		p->dw_x_shrink_1st,
+		p->dw_y_shrink_1st,
+		p->dw_x_shrink_2nd,
+		p->dw_y_shrink_2nd,
+		p->dw_x_shrink_3rd,
+		p->dw_y_shrink_3rd,
+		p->dw_merge_8to16,
+		p->dw_merge_16to32,
+		p->dw_dma_blk_mode);
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+		"cfg0,1,3,4,5 = {%x, %x, %x, %x, %x}\n",
+		READ_VREG(MDEC_DOUBLEW_CFG0),
+		READ_VREG(MDEC_DOUBLEW_CFG1),
+		READ_VREG(MDEC_DOUBLEW_CFG3),
+		READ_VREG(MDEC_DOUBLEW_CFG4),
+		READ_VREG(MDEC_DOUBLEW_CFG5));
+}
+#endif
+
+static void config_decode_mode(struct vdec_h264_hw_s *hw)
+{
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	struct vdec_s *vdec = hw_to_vdec(hw);
+#endif
+	if (input_frame_based(hw_to_vdec(hw)))
+		WRITE_VREG(H264_DECODE_MODE,
+			DECODE_MODE_MULTI_FRAMEBASE);
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	else if (vdec->slave)
+		WRITE_VREG(H264_DECODE_MODE,
+			(hw->got_valid_nal << 8) |
+			DECODE_MODE_MULTI_DVBAL);
+	else if (vdec->master)
+		WRITE_VREG(H264_DECODE_MODE,
+			(hw->got_valid_nal << 8) |
+			DECODE_MODE_MULTI_DVENL);
+#endif
+	else
+		WRITE_VREG(H264_DECODE_MODE,
+			DECODE_MODE_MULTI_STREAMBASE);
+	WRITE_VREG(H264_DECODE_SEQINFO,
+		hw->seq_info2);
+	WRITE_VREG(HEAD_PADING_REG, 0);
+
+	if (hw->init_flag == 0)
+		WRITE_VREG(INIT_FLAG_REG, 0);
+	else
+		WRITE_VREG(INIT_FLAG_REG, 1);
+}
+
+int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic)
+{
+	/* static int count = 0; */
+	int ret = 0;
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	struct Slice *pSlice = &(p_H264_Dpb->mSlice);
+	unsigned int colocate_adr_offset;
+	unsigned int val;
+	struct StorablePicture *last_pic = hw->last_dec_picture;
+
+#ifdef ONE_COLOCATE_BUF_PER_DECODE_BUF
+	int colocate_buf_index;
+#endif
+#define H264_BUFFER_INFO_INDEX    PMV3_X /* 0xc24 */
+#define H264_BUFFER_INFO_DATA   PMV2_X  /* 0xc22 */
+#define H264_CURRENT_POC_IDX_RESET LAST_SLICE_MV_ADDR /* 0xc30 */
+#define H264_CURRENT_POC          LAST_MVY /* 0xc32 shared with conceal MV */
+
+#define H264_CO_MB_WR_ADDR        VLD_C38 /* 0xc38 */
+/* bit 31:30 -- L1[0] picture coding structure,
+ *	00 - top field,	01 - bottom field,
+ *	10 - frame, 11 - mbaff frame
+ *   bit 29 - L1[0] top/bot for B field pciture , 0 - top, 1 - bot
+ *   bit 28:0 h264_co_mb_mem_rd_addr[31:3]
+ *	-- only used for B Picture Direct mode [2:0] will set to 3'b000
+ */
+#define H264_CO_MB_RD_ADDR        VLD_C39 /* 0xc39 */
+
+/* bit 15 -- flush co_mb_data to DDR -- W-Only
+ *   bit 14 -- h264_co_mb_mem_wr_addr write Enable -- W-Only
+ *   bit 13 -- h264_co_mb_info_wr_ptr write Enable -- W-Only
+ *   bit 9 -- soft_reset -- W-Only
+ *   bit 8 -- upgent
+ *   bit 7:2 -- h264_co_mb_mem_wr_addr
+ *   bit 1:0 -- h264_co_mb_info_wr_ptr
+ */
+#define H264_CO_MB_RW_CTL         VLD_C3D /* 0xc3d */
+#define DCAC_DDR_BYTE64_CTL                   0x0e1d
+	unsigned long canvas_adr;
+	unsigned int ref_reg_val;
+	unsigned int one_ref_cfg = 0;
+	int h264_buffer_info_data_write_count;
+	int i, j;
+	unsigned int colocate_wr_adr;
+	unsigned int colocate_rd_adr;
+	unsigned char use_direct_8x8;
+	int canvas_pos;
+	canvas_pos = hw->buffer_spec[pic->buf_spec_num].canvas_pos;
+	WRITE_VREG(H264_CURRENT_POC_IDX_RESET, 0);
+	WRITE_VREG(H264_CURRENT_POC, pic->frame_poc);
+	WRITE_VREG(H264_CURRENT_POC, pic->top_poc);
+	WRITE_VREG(H264_CURRENT_POC, pic->bottom_poc);
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+		"%s: pic_num is %d, poc is %d (%d, %d, %d), buf_spec_num %d canvas_pos %d\n",
+		__func__, pic->pic_num, pic->poc, pic->frame_poc,
+		pic->top_poc, pic->bottom_poc, pic->buf_spec_num,
+		canvas_pos);
+	print_pic_info(DECODE_ID(hw), "cur", pic, pSlice->slice_type);
+
+#ifdef VDEC_DW
+	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_T7) {
+		if (IS_VDEC_DW(hw) && pic->mb_aff_frame_flag)
+			WRITE_VREG(MDEC_DOUBLEW_CFG0,
+				(READ_VREG(MDEC_DOUBLEW_CFG0) & (~(1 << 30))));
+	}
+#endif
+	WRITE_VREG(CURR_CANVAS_CTRL, canvas_pos << 24);
+	canvas_adr = READ_VREG(CURR_CANVAS_CTRL) & 0xffffff;
+
+	if (!hw->mmu_enable) {
+		WRITE_VREG(REC_CANVAS_ADDR, canvas_adr);
+		WRITE_VREG(DBKR_CANVAS_ADDR, canvas_adr);
+		WRITE_VREG(DBKW_CANVAS_ADDR, canvas_adr);
+#ifdef VDEC_DW
+		if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_T7) {
+			WRITE_VREG(MDEC_DOUBLEW_CFG1,
+				(hw->buffer_spec[canvas_pos].vdec_dw_y_canvas_index |
+				(hw->buffer_spec[canvas_pos].vdec_dw_u_canvas_index << 8)));
+		} else {
+				h264_vdec_dw_cfg(hw, canvas_pos);
+		}
+#endif
+	} else
+		hevc_sao_set_pic_buffer(hw, pic);
+
+	if (pic->mb_aff_frame_flag)
+		hw->buffer_spec[pic->buf_spec_num].info0 = 0xf4c0;
+	else if (pic->structure == TOP_FIELD)
+		hw->buffer_spec[pic->buf_spec_num].info0 = 0xf400;
+	else if (pic->structure == BOTTOM_FIELD)
+		hw->buffer_spec[pic->buf_spec_num].info0 = 0xf440;
+	else
+		hw->buffer_spec[pic->buf_spec_num].info0 = 0xf480;
+
+	if (pic->bottom_poc < pic->top_poc)
+		hw->buffer_spec[pic->buf_spec_num].info0 |= 0x100;
+
+	hw->buffer_spec[pic->buf_spec_num].info1 = pic->top_poc;
+	hw->buffer_spec[pic->buf_spec_num].info2 = pic->bottom_poc;
+	WRITE_VREG(H264_BUFFER_INFO_INDEX, 16);
+
+	for (j = 0; j < hw->dpb.mDPB.size; j++) {
+		int long_term_flag;
+		i = get_buf_spec_by_canvas_pos(hw, j);
+		if (i < 0)
+			break;
+		long_term_flag =
+			get_long_term_flag_by_buf_spec_num(p_H264_Dpb, i);
+		if (long_term_flag > 0) {
+			if (long_term_flag & 0x1)
+				hw->buffer_spec[i].info0 |= (1 << 4);
+			else
+				hw->buffer_spec[i].info0 &= ~(1 << 4);
+
+			if (long_term_flag & 0x2)
+				hw->buffer_spec[i].info0 |= (1 << 5);
+			else
+				hw->buffer_spec[i].info0 &= ~(1 << 5);
+		}
+
+		if (i == pic->buf_spec_num)
+			WRITE_VREG(H264_BUFFER_INFO_DATA,
+				hw->buffer_spec[i].info0 | 0xf);
+		else
+			WRITE_VREG(H264_BUFFER_INFO_DATA,
+				hw->buffer_spec[i].info0);
+		WRITE_VREG(H264_BUFFER_INFO_DATA, hw->buffer_spec[i].info1);
+		WRITE_VREG(H264_BUFFER_INFO_DATA, hw->buffer_spec[i].info2);
+	}
+
+	/* config reference buffer */
+	if (hw->mmu_enable) {
+		hevc_mcr_config_mc_ref(hw);
+		hevc_mcr_config_mcrcc(hw);
+	}
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+		"list0 size %d\n", pSlice->listXsize[0]);
+	WRITE_VREG(H264_BUFFER_INFO_INDEX, 0);
+	ref_reg_val = 0;
+	j = 0;
+	h264_buffer_info_data_write_count = 0;
+
+	//disable this read cache when frame width <= 64 (4MBs)
+	//IQIDCT_CONTROL, bit[16] dcac_dma_read_cache_disable
+	if (hw->frame_width <= 64) {
+		SET_VREG_MASK(IQIDCT_CONTROL,(1 << 16));
+		if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A))
+			// Disable DDR_BYTE64_CACHE
+			WRITE_VREG(DCAC_DDR_BYTE64_CTL,
+			(READ_VREG(DCAC_DDR_BYTE64_CTL) & (~0xf)) | 0xa);
+	}
+	else
+		CLEAR_VREG_MASK(IQIDCT_CONTROL,(1 << 16));
+
+	if (last_pic)
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG,
+				"last_pic->data_flag %x   slice_type %x last_pic->slice_type %x\n",
+				last_pic->data_flag, pSlice->slice_type, last_pic->slice_type);
+	if (!hw->i_only && !(error_proc_policy & 0x2000) &&
+		last_pic && (last_pic->data_flag & ERROR_FLAG)
+		&& (!(last_pic->slice_type == B_SLICE))
+		&& (!(pSlice->slice_type == I_SLICE))) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG,
+				  "no i/idr error mark\n");
+		hw->data_flag |= ERROR_FLAG;
+		pic->data_flag |= ERROR_FLAG;
+	}
+
+	for (i = 0; i < (unsigned int)(pSlice->listXsize[0]); i++) {
+		/*ref list 0 */
+		struct StorablePicture *ref = pSlice->listX[0][i];
+		unsigned int cfg;
+		/* bit[6:5] - frame/field info,
+		 * 01 - top, 10 - bottom, 11 - frame
+		 */
+	#ifdef ERROR_CHECK
+		if (ref == NULL) {
+			hw->data_flag |= ERROR_FLAG;
+			pic->data_flag  |= ERROR_FLAG;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref list0 NULL\n");
+			return -1;
+		}
+		if ((ref->data_flag & ERROR_FLAG) && ref_frame_mark_flag[DECODE_ID(hw)]) {
+			hw->data_flag |= ERROR_FLAG;
+			pic->data_flag |= ERROR_FLAG;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref error mark1 \n");
+		}
+
+		if (error_proc_policy & 0x80000) {
+			if (ref_b_frame_error_max_count &&
+				ref->slice_type == B_SLICE) {
+				if (ref->data_flag & ERROR_FLAG)
+					hw->b_frame_error_count++;
+				else
+					hw->b_frame_error_count = 0;
+				if (hw->b_frame_error_count > ref_b_frame_error_max_count) {
+					hw->b_frame_error_count = 0;
+					dpb_print(DECODE_ID(hw), 0,
+						"error %d B frame, reset dpb buffer\n",
+						ref_b_frame_error_max_count);
+					return -1;
+				}
+			}
+		}
+
+		if (ref->data_flag & NULL_FLAG)
+			hw->data_flag |= NULL_FLAG;
+#endif
+		canvas_pos = hw->buffer_spec[ref->buf_spec_num].canvas_pos;
+
+		if (ref->structure == TOP_FIELD)
+			cfg = 0x1;
+		else if (ref->structure == BOTTOM_FIELD)
+			cfg = 0x2;
+		else /* FRAME */
+			cfg = 0x3;
+
+		one_ref_cfg = (canvas_pos & 0x1f) | (cfg << 5);
+		ref_reg_val <<= 8;
+		ref_reg_val |= one_ref_cfg;
+		j++;
+
+		if (j == 4) {
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+				"H264_BUFFER_INFO_DATA: %x\n", ref_reg_val);
+			WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val);
+			h264_buffer_info_data_write_count++;
+			j = 0;
+		}
+		print_pic_info(DECODE_ID(hw), "list0",
+			pSlice->listX[0][i], -1);
+	}
+	if (j != 0) {
+		while (j != 4) {
+			ref_reg_val <<= 8;
+			ref_reg_val |= one_ref_cfg;
+			j++;
+		}
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+			"H264_BUFFER_INFO_DATA: %x\n",
+					ref_reg_val);
+		WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val);
+		h264_buffer_info_data_write_count++;
+	}
+	ref_reg_val = (one_ref_cfg << 24) | (one_ref_cfg<<16) |
+				(one_ref_cfg << 8) | one_ref_cfg;
+	for (i = h264_buffer_info_data_write_count; i < 8; i++)
+		WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val);
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+		"list1 size %d\n", pSlice->listXsize[1]);
+	WRITE_VREG(H264_BUFFER_INFO_INDEX, 8);
+	ref_reg_val = 0;
+	j = 0;
+
+	for (i = 0; i < (unsigned int)(pSlice->listXsize[1]); i++) {
+		/* ref list 0 */
+		struct StorablePicture *ref = pSlice->listX[1][i];
+		unsigned int cfg;
+		/* bit[6:5] - frame/field info,
+		 * 01 - top, 10 - bottom, 11 - frame
+		 */
+
+	#ifdef ERROR_CHECK
+		if (ref == NULL) {
+			hw->data_flag |= ERROR_FLAG;
+			pic->data_flag  |= ERROR_FLAG;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref error list1 NULL\n");
+			return -2;
+		}
+		if ((ref->data_flag & ERROR_FLAG) && (ref_frame_mark_flag[DECODE_ID(hw)])) {
+			pic->data_flag  |= ERROR_FLAG;
+			hw->data_flag |= ERROR_FLAG;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " ref error mark2\n");
+		}
+		if (ref->data_flag & NULL_FLAG)
+			hw->data_flag |= NULL_FLAG;
+#endif
+		canvas_pos = hw->buffer_spec[ref->buf_spec_num].canvas_pos;
+		if (ref->structure == TOP_FIELD)
+			cfg = 0x1;
+		else if (ref->structure == BOTTOM_FIELD)
+			cfg = 0x2;
+		else /* FRAME */
+			cfg = 0x3;
+		one_ref_cfg = (canvas_pos & 0x1f) | (cfg << 5);
+		ref_reg_val <<= 8;
+		ref_reg_val |= one_ref_cfg;
+		j++;
+
+		if (j == 4) {
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+				"H264_BUFFER_INFO_DATA: %x\n",
+				ref_reg_val);
+			WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val);
+			j = 0;
+		}
+		print_pic_info(DECODE_ID(hw), "list1",
+			pSlice->listX[1][i], -1);
+	}
+	if (j != 0) {
+		while (j != 4) {
+			ref_reg_val <<= 8;
+			ref_reg_val |= one_ref_cfg;
+			j++;
+		}
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+		"H264_BUFFER_INFO_DATA: %x\n", ref_reg_val);
+		WRITE_VREG(H264_BUFFER_INFO_DATA, ref_reg_val);
+	}
+
+	/* configure co-locate buffer */
+	while ((READ_VREG(H264_CO_MB_RW_CTL) >> 11) & 0x1)
+		;
+	if ((pSlice->mode_8x8_flags & 0x4) &&
+		(pSlice->mode_8x8_flags & 0x2))
+		use_direct_8x8 = 1;
+	else
+		use_direct_8x8 = 0;
+
+#ifndef ONE_COLOCATE_BUF_PER_DECODE_BUF
+	colocate_adr_offset =
+		((pic->structure == FRAME && pic->mb_aff_frame_flag == 0)
+		 ? 1 : 2) * 96;
+	if (use_direct_8x8)
+		colocate_adr_offset >>= 2;
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+		"colocate buf size of each mb 0x%x first_mb_in_slice 0x%x colocate_adr_offset 0x%x\r\n",
+		colocate_adr_offset, pSlice->first_mb_in_slice,
+		colocate_adr_offset * pSlice->first_mb_in_slice);
+
+	colocate_adr_offset *= pSlice->first_mb_in_slice;
+
+	if ((pic->colocated_buf_index >= 0) &&
+		(pic->colocated_buf_index < p_H264_Dpb->colocated_buf_count)) {
+		colocate_wr_adr = p_H264_Dpb->colocated_mv_addr_start +
+			((p_H264_Dpb->colocated_buf_size *
+			pic->colocated_buf_index)
+			>> (use_direct_8x8 ? 2 : 0));
+		if ((colocate_wr_adr + p_H264_Dpb->colocated_buf_size) >
+			p_H264_Dpb->colocated_mv_addr_end) {
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
+				"Error, colocate buf is not enough, index is %d\n",
+			pic->colocated_buf_index);
+			ret = -3;
+		}
+		val = colocate_wr_adr + colocate_adr_offset;
+		WRITE_VREG(H264_CO_MB_WR_ADDR, val);
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+			"WRITE_VREG(H264_CO_MB_WR_ADDR) = %x, first_mb_in_slice %x pic_structure %x  colocate_adr_offset %x mode_8x8_flags %x colocated_buf_size %x\n",
+			val, pSlice->first_mb_in_slice, pic->structure,
+			colocate_adr_offset, pSlice->mode_8x8_flags,
+			p_H264_Dpb->colocated_buf_size);
+	} else {
+		WRITE_VREG(H264_CO_MB_WR_ADDR, 0xffffffff);
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+			"WRITE_VREG(H264_CO_MB_WR_ADDR) = 0xffffffff\n");
+	}
+#else
+	colocate_buf_index = hw->buffer_spec[pic->buf_spec_num].canvas_pos;
+	colocate_adr_offset =
+	((pic->structure == FRAME && pic->mb_aff_frame_flag == 0) ? 1 : 2) * 96;
+	if (use_direct_8x8)
+		colocate_adr_offset >>= 2;
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+		"colocate buf size of each mb 0x%x first_mb_in_slice 0x%x colocate_adr_offset 0x%x\r\n",
+		colocate_adr_offset, pSlice->first_mb_in_slice,
+		colocate_adr_offset * pSlice->first_mb_in_slice);
+
+	colocate_adr_offset *= pSlice->first_mb_in_slice;
+
+	colocate_wr_adr = p_H264_Dpb->colocated_mv_addr_start +
+		((p_H264_Dpb->colocated_buf_size * colocate_buf_index) >>
+			(use_direct_8x8 ? 2 : 0));
+
+	if ((colocate_wr_adr + p_H264_Dpb->colocated_buf_size) >
+		p_H264_Dpb->colocated_mv_addr_end) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
+		"Error, colocate buf is not enough, col buf index is %d\n",
+				colocate_buf_index);
+		ret = -4;
+	}
+	val = colocate_wr_adr + colocate_adr_offset;
+	WRITE_VREG(H264_CO_MB_WR_ADDR, val);
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+		"WRITE_VREG(H264_CO_MB_WR_ADDR) = %x, first_mb_in_slice %x pic_structure %x colocate_adr_offset %x mode_8x8_flags %x colocated_buf_size %x\n",
+		val, pSlice->first_mb_in_slice, pic->structure,
+		colocate_adr_offset, pSlice->mode_8x8_flags,
+		p_H264_Dpb->colocated_buf_size);
+#endif
+	if (pSlice->listXsize[1] > 0) {
+		struct StorablePicture *colocate_pic = pSlice->listX[1][0];
+		/* H264_CO_MB_RD_ADDR[bit 31:30],
+		 * original picture structure of L1[0],
+		 * 00 - top field, 01 - bottom field,
+		 * 10 - frame, 11 - mbaff frame
+		 */
+		int l10_structure, cur_structure;
+		int cur_colocate_ref_type;
+		/* H264_CO_MB_RD_ADDR[bit 29], top/bot for B field pciture,
+		 * 0 - top, 1 - bot
+		 */
+		unsigned int val;
+		unsigned int colocate_rd_adr_offset;
+		unsigned int mby_mbx;
+		unsigned int mby, mbx;
+
+#ifdef ERROR_CHECK
+		if (colocate_pic == NULL) {
+			hw->data_flag |= ERROR_FLAG;
+			pic->data_flag |= ERROR_FLAG;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " colocate error pic NULL\n");
+			return -5;
+		}
+		if (colocate_pic->data_flag & ERROR_FLAG) {
+			pic->data_flag |= ERROR_FLAG;
+			hw->data_flag |= ERROR_FLAG;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG, " colocare ref error mark\n");
+			}
+		if (colocate_pic->data_flag & NULL_FLAG)
+			hw->data_flag |= NULL_FLAG;
+#endif
+
+		if (colocate_pic->mb_aff_frame_flag)
+			l10_structure = 3;
+		else {
+			if (colocate_pic->coded_frame)
+				l10_structure = 2;
+			else
+				l10_structure =	(colocate_pic->structure ==
+					BOTTOM_FIELD) ?	1 : 0;
+		}
+
+		//ALLEGRO_FIX, ported from single mode ucode
+		mby_mbx = READ_VREG(MBY_MBX);
+		mby = pSlice->first_mb_in_slice / hw->mb_width;
+		mbx = pSlice->first_mb_in_slice % hw->mb_width;
+		if (pic->mb_aff_frame_flag)
+			cur_structure = 3;
+		else {
+			if (pic->coded_frame)
+				cur_structure = 2;
+			else
+				cur_structure =	(pic->structure ==
+					BOTTOM_FIELD) ?	1 : 0;
+		}
+		if (cur_structure < 2) {
+			//current_field_structure
+			if (l10_structure != 2) {
+				colocate_rd_adr_offset = pSlice->first_mb_in_slice * 2;
+			} else {
+				// field_ref_from_frame co_mv_rd_addr :
+				// mby*2*mb_width + mbx
+				colocate_rd_adr_offset = mby * 2 * hw->mb_width + mbx;
+			}
+
+		} else {
+			//current_frame_structure
+			if (l10_structure < 2) {
+				//calculate_co_mv_offset_frame_ref_field:
+				// frame_ref_from_field co_mv_rd_addr :
+				// (mby/2*mb_width+mbx)*2
+				colocate_rd_adr_offset = ((mby / 2) * hw->mb_width + mbx) * 2;
+			} else if (cur_structure == 2) {
+				colocate_rd_adr_offset = pSlice->first_mb_in_slice;
+			} else {
+				//mbaff frame case1196
+				colocate_rd_adr_offset = pSlice->first_mb_in_slice * 2;
+			}
+
+		}
+
+		colocate_rd_adr_offset *= 96;
+		if (use_direct_8x8)
+			colocate_rd_adr_offset >>= 2;
+
+		if (colocate_old_cal)
+			colocate_rd_adr_offset = colocate_adr_offset;
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+			"first_mb_in_slice 0x%x 0x%x 0x%x (MBY_MBX reg 0x%x) use_direct_8x8 %d cur %d (mb_aff_frame_flag %d, coded_frame %d structure %d) col %d (mb_aff_frame_flag %d, coded_frame %d structure %d) offset 0x%x rdoffset 0x%x\n",
+				pSlice->first_mb_in_slice, mby, mbx, mby_mbx, use_direct_8x8,
+				cur_structure, pic->mb_aff_frame_flag, pic->coded_frame, pic->structure,
+				l10_structure, colocate_pic->mb_aff_frame_flag, colocate_pic->coded_frame, colocate_pic->structure,
+				colocate_adr_offset,
+				colocate_rd_adr_offset);
+
+#if 0
+		/*case0016, p16,
+		 *cur_colocate_ref_type should be configured base on current pic
+		 */
+		if (pic->structure == FRAME &&
+			pic->mb_aff_frame_flag)
+			cur_colocate_ref_type = 0;
+		else if (pic->structure == BOTTOM_FIELD)
+			cur_colocate_ref_type = 1;
+		else
+			cur_colocate_ref_type = 0;
+#else
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+			" CUR TMP DEBUG : mb_aff_frame_flag : %d, structure : %d coded_frame %d\n",
+			pic->mb_aff_frame_flag,
+			pic->structure,
+			pic->coded_frame);
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+			" COL TMP DEBUG : mb_aff_frame_flag : %d, structure : %d coded_frame %d\n",
+			colocate_pic->mb_aff_frame_flag,
+				colocate_pic->structure,
+				colocate_pic->coded_frame);
+		if (pic->structure == FRAME  || pic->mb_aff_frame_flag) {
+			cur_colocate_ref_type =
+				(abs(pic->poc - colocate_pic->top_poc)
+				< abs(pic->poc -
+				colocate_pic->bottom_poc)) ? 0 : 1;
+		} else
+			cur_colocate_ref_type =
+				(colocate_pic->structure
+					== BOTTOM_FIELD) ? 1 : 0;
+#endif
+
+#ifndef ONE_COLOCATE_BUF_PER_DECODE_BUF
+		if ((colocate_pic->colocated_buf_index >= 0) &&
+			(colocate_pic->colocated_buf_index <
+				p_H264_Dpb->colocated_buf_count)) {
+			colocate_rd_adr = p_H264_Dpb->colocated_mv_addr_start +
+				((p_H264_Dpb->colocated_buf_size *
+				colocate_pic->colocated_buf_index)
+				>> (use_direct_8x8 ? 2 : 0));
+			if ((colocate_rd_adr + p_H264_Dpb->colocated_buf_size) >
+				p_H264_Dpb->colocated_mv_addr_end) {
+				dpb_print(DECODE_ID(hw),
+					PRINT_FLAG_ERROR,
+				"Error, colocate buf is not enough, index is %d\n",
+					colocate_pic->colocated_buf_index);
+				ret = -6;
+			}
+			/* bit 31:30 -- L1[0] picture coding structure,
+			 * 00 - top field, 01 - bottom field,
+			 * 10 - frame, 11 - mbaff frame
+			 * bit 29 - L1[0] top/bot for B field pciture,
+			 * 0 - top, 1 - bot
+			 * bit 28:0 h264_co_mb_mem_rd_addr[31:3]
+			 * -- only used for B Picture Direct mode
+			 * [2:0] will set to 3'b000
+			 */
+			/* #define H264_CO_MB_RD_ADDR        VLD_C39 0xc39 */
+			val = ((colocate_rd_adr+colocate_rd_adr_offset) >> 3) |
+				(l10_structure << 30) |
+				(cur_colocate_ref_type << 29);
+			WRITE_VREG(H264_CO_MB_RD_ADDR, val);
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+				"co idx %d, WRITE_VREG(H264_CO_MB_RD_ADDR) = %x, addr %x L1(0) pic_structure %d mbaff %d\n",
+				colocate_pic->colocated_buf_index,
+				val, colocate_rd_adr + colocate_rd_adr_offset,
+				colocate_pic->structure,
+				colocate_pic->mb_aff_frame_flag);
+		} else {
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
+			"Error, reference pic has no colocated buf\n");
+			ret = -7;
+		}
+#else
+		colocate_buf_index =
+			hw->buffer_spec[colocate_pic->buf_spec_num].canvas_pos;
+		colocate_rd_adr = p_H264_Dpb->colocated_mv_addr_start +
+			((p_H264_Dpb->colocated_buf_size *
+				colocate_buf_index)
+				>> (use_direct_8x8 ? 2 : 0));
+		if ((colocate_rd_adr + p_H264_Dpb->colocated_buf_size) >
+			p_H264_Dpb->colocated_mv_addr_end) {
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
+				"Error, colocate buf is not enough, col buf index is %d\n",
+				colocate_buf_index);
+			ret = -8;
+		}
+		/* bit 31:30 -- L1[0] picture coding structure,
+		 * 00 - top field, 01 - bottom field,
+		 * 10 - frame, 11 - mbaff frame
+		 * bit 29 - L1[0] top/bot for B field pciture,
+		 * 0 - top, 1 - bot
+		 * bit 28:0 h264_co_mb_mem_rd_addr[31:3]
+		 * -- only used for B Picture Direct mode
+		 * [2:0] will set to 3'b000
+		 */
+		/* #define H264_CO_MB_RD_ADDR        VLD_C39 0xc39 */
+		val = ((colocate_rd_adr+colocate_rd_adr_offset)>>3) |
+			(l10_structure << 30) | (cur_colocate_ref_type << 29);
+		WRITE_VREG(H264_CO_MB_RD_ADDR, val);
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+			"WRITE_VREG(H264_CO_MB_RD_ADDR) = %x, L1(0) pic_structure %d mbaff %d\n",
+			val, colocate_pic->structure,
+			colocate_pic->mb_aff_frame_flag);
+#endif
+	}
+	return ret;
+}
+
+static int vh264_vf_states(struct vframe_states *states, void *op_arg)
+{
+	unsigned long flags;
+	struct vdec_s *vdec = op_arg;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+
+	spin_lock_irqsave(&hw->lock, flags);
+
+	states->vf_pool_size = VF_POOL_SIZE;
+	states->buf_free_num = kfifo_len(&hw->newframe_q);
+	states->buf_avail_num = kfifo_len(&hw->display_q);
+
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+	return 0;
+}
+
+static struct vframe_s *vh264_vf_peek(void *op_arg)
+{
+	struct vframe_s *vf[2] = {0, 0};
+	struct vdec_s *vdec = op_arg;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+
+	if (!hw)
+		return NULL;
+
+	if (force_disp_bufspec_num & 0x100) {
+		if (force_disp_bufspec_num & 0x200)
+			return NULL;
+		return &hw->vframe_dummy;
+	}
+
+	if (kfifo_len(&hw->display_q) > VF_POOL_SIZE) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+			"kfifo len:%d invaild, peek error\n",
+			kfifo_len(&hw->display_q));
+		return NULL;
+	}
+
+	if (kfifo_out_peek(&hw->display_q, (void *)&vf, 2)) {
+		if (vf[1]) {
+			vf[0]->next_vf_pts_valid = true;
+			vf[0]->next_vf_pts = vf[1]->pts;
+		} else
+			vf[0]->next_vf_pts_valid = false;
+		return vf[0];
+	}
+
+	return NULL;
+}
+
+static struct vframe_s *vh264_vf_get(void *op_arg)
+{
+	struct vframe_s *vf;
+	struct vdec_s *vdec = op_arg;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+	ulong nv_order = VIDTYPE_VIU_NV21;
+
+	if (!hw)
+		return NULL;
+
+	/* swap uv */
+	if (hw->is_used_v4l) {
+		if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) ||
+			(v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12M))
+			nv_order = VIDTYPE_VIU_NV12;
+	}
+
+	if (force_disp_bufspec_num & 0x100) {
+		int buffer_index = force_disp_bufspec_num & 0xff;
+		if (force_disp_bufspec_num & 0x200)
+			return NULL;
+
+		vf = &hw->vframe_dummy;
+		vf->duration_pulldown = 0;
+		vf->pts = 0;
+		vf->pts_us64 = 0;
+		set_frame_info(hw, vf, buffer_index);
+		vf->flag = 0;
+		if (hw->mmu_enable) {
+			if (hw->double_write_mode & 0x10) {
+				/* double write only */
+				vf->compBodyAddr = 0;
+				vf->compHeadAddr = 0;
+			} else {
+				/*head adr*/
+				vf->compHeadAddr =
+				hw->buffer_spec[buffer_index].alloc_header_addr;
+				/*body adr*/
+				vf->compBodyAddr = 0;
+				vf->canvas0Addr = vf->canvas1Addr = 0;
+			}
+
+			vf->type = VIDTYPE_SCATTER;
+
+			if (hw->double_write_mode) {
+				vf->type |= VIDTYPE_PROGRESSIVE
+					| VIDTYPE_VIU_FIELD;
+				vf->type |= nv_order;
+				if (hw->double_write_mode == 3)
+					vf->type |= VIDTYPE_COMPRESS;
+
+				vf->canvas0Addr = vf->canvas1Addr = -1;
+				vf->plane_num = 2;
+				vf->canvas0_config[0] =
+					hw->buffer_spec[buffer_index].
+						canvas_config[0];
+				vf->canvas0_config[1] =
+					hw->buffer_spec[buffer_index].
+						canvas_config[1];
+
+				vf->canvas1_config[0] =
+					hw->buffer_spec[buffer_index].
+						canvas_config[0];
+				vf->canvas1_config[1] =
+					hw->buffer_spec[buffer_index].
+						canvas_config[1];
+			} else {
+				vf->type |=
+					VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD;
+				vf->canvas0Addr = vf->canvas1Addr = 0;
+			}
+			vf->bitdepth =
+				BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8;
+
+			vf->compWidth = hw->frame_width;
+			vf->compHeight = hw->frame_height;
+
+			if (hw->double_write_mode) {
+				vf->width = hw->frame_width /
+					get_double_write_ratio(hw->double_write_mode);
+				vf->height = hw->frame_height /
+					get_double_write_ratio(hw->double_write_mode);
+			}
+		} else {
+			vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD |
+				nv_order;
+			vf->canvas0Addr = vf->canvas1Addr =
+			spec2canvas(&hw->buffer_spec[buffer_index]);
+		}
+
+		/*vf->mem_handle = decoder_bmmu_box_get_mem_handle(
+			hw->bmmu_box, buffer_index);*/
+		update_vf_memhandle(hw, vf, buffer_index);
+		force_disp_bufspec_num |= 0x200;
+		return vf;
+	}
+
+	if (kfifo_get(&hw->display_q, &vf)) {
+		int time = jiffies;
+		unsigned int frame_interval =
+			1000*(time - hw->last_frame_time)/HZ;
+		struct vframe_s *next_vf = NULL;
+		ATRACE_COUNTER(hw->trace.disp_q_name, kfifo_len(&hw->display_q));
+		if (dpb_is_debug(DECODE_ID(hw),
+			PRINT_FLAG_VDEC_DETAIL)) {
+			struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+			int frame_index = FRAME_INDEX(vf->index);
+			if (frame_index < 0 ||
+					frame_index >= DPB_SIZE_MAX) {
+				dpb_print(DECODE_ID(hw), 0,
+						"%s vf index 0x%x error\r\n",
+						__func__, vf->index);
+			} else {
+				dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL,
+				"%s buf_spec_num %d vf %p poc %d dur %d pts %d interval %dms, ts: %lld\n",
+				__func__, BUFSPEC_INDEX(vf->index), vf,
+				p_H264_Dpb->mFrameStore[frame_index].poc,
+				vf->duration, vf->pts, frame_interval, vf->timestamp);
+			}
+		}
+		if (hw->last_frame_time > 0) {
+			if (frame_interval >
+				max_get_frame_interval[DECODE_ID(hw)])
+				max_get_frame_interval[DECODE_ID(hw)]
+				= frame_interval;
+		}
+		hw->last_frame_time = time;
+		vf->index_disp = atomic_read(&hw->vf_get_count);
+		atomic_add(1, &hw->vf_get_count);
+		if (kfifo_peek(&hw->display_q, &next_vf) && next_vf) {
+			vf->next_vf_pts_valid = true;
+			vf->next_vf_pts = next_vf->pts;
+		} else
+			vf->next_vf_pts_valid = false;
+
+		return vf;
+	}
+
+	return NULL;
+}
+
+static bool vf_valid_check(struct vframe_s *vf, struct vdec_h264_hw_s *hw) {
+	int i,j;
+	if (hw->is_used_v4l)
+		return true;
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		for (j = 0; j < VF_POOL_NUM; j ++) {
+			if (vf == &(hw->vfpool[j][i]) || vf == &hw->vframe_dummy)
+				return true;
+		}
+	}
+	dpb_print(DECODE_ID(hw), 0, " invalid vf been put, vf = %p\n", vf);
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+		"dump vf [%d]= %p\n",  i, &(hw->vfpool[hw->cur_pool][i]));
+	}
+	return false;
+}
+
+static void vh264_vf_put(struct vframe_s *vf, void *op_arg)
+{
+	struct vdec_s *vdec = op_arg;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	unsigned long flags;
+	int buf_spec_num;
+	int frame_index;
+
+	if (vf == (&hw->vframe_dummy))
+		return;
+
+	if (!vf)
+		return;
+
+	if (vf->index == -1) {
+		dpb_print(DECODE_ID(hw), 0,
+			"Warning: %s vf %p invalid index\r\n",
+			__func__, vf);
+		return;
+	}
+
+	if (hw->enable_fence && vf->fence) {
+		int ret, i;
+
+		mutex_lock(&hw->fence_mutex);
+		ret = dma_fence_get_status(vf->fence);
+		if (ret == 0) {
+			for (i = 0; i < VF_POOL_SIZE; i++) {
+				if (hw->fence_vf_s.fence_vf[i] == NULL) {
+					hw->fence_vf_s.fence_vf[i] = vf;
+					hw->fence_vf_s.used_size++;
+					mutex_unlock(&hw->fence_mutex);
+					return;
+				}
+			}
+		}
+		mutex_unlock(&hw->fence_mutex);
+	}
+
+	buf_spec_num = BUFSPEC_INDEX(vf->index);
+	if (hw->enable_fence)
+		frame_index = hw->buffer_spec[buf_spec_num].fs_idx;
+	else
+		frame_index = FRAME_INDEX(vf->index);
+
+	if (frame_index < 0 ||
+		frame_index >= DPB_SIZE_MAX ||
+		buf_spec_num < 0 ||
+		buf_spec_num >= BUFSPEC_POOL_SIZE) {
+		dpb_print(DECODE_ID(hw), 0,
+			"%s vf index 0x%x error\r\n",
+			__func__, vf->index);
+		return;
+	}
+		/*get_buf_spec_idx_by_canvas_config(hw,
+			&vf->canvas0_config[0]);*/
+
+	if (hw->enable_fence && vf->fence) {
+		vdec_fence_put(vf->fence);
+		vf->fence = NULL;
+	}
+
+	spin_lock_irqsave(&hw->bufspec_lock, flags);
+	if (hw->buffer_spec[buf_spec_num].used == 2) {
+		struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+		"%s %p to fs[%d], poc %d buf_spec_num %d used %d vf_ref %d\n",
+		__func__, vf, frame_index,
+		p_H264_Dpb->mFrameStore[frame_index].poc,
+		buf_spec_num,
+		hw->buffer_spec[buf_spec_num].used,
+		hw->buffer_spec[buf_spec_num].vf_ref);
+		hw->buffer_spec[buf_spec_num].vf_ref--;
+		if (hw->buffer_spec[buf_spec_num].vf_ref <= 0)
+			set_frame_output_flag(&hw->dpb, frame_index);
+	} else {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+		"%s %p isolated vf, buf_spec_num %d used %d vf_ref %d\n",
+		__func__, vf, buf_spec_num,
+		hw->buffer_spec[buf_spec_num].used,
+		hw->buffer_spec[buf_spec_num].vf_ref);
+		hw->buffer_spec[buf_spec_num].vf_ref--;
+		if (hw->buffer_spec[buf_spec_num].vf_ref <= 0) {
+			if (hw->buffer_spec[buf_spec_num].used == 3)
+				hw->buffer_spec[buf_spec_num].used = 4;
+			else if (hw->buffer_spec[buf_spec_num].used == 5)
+				hw->buffer_spec[buf_spec_num].used = 0;
+		}
+		if (dpb_is_debug(DECODE_ID(hw),
+			PRINT_FLAG_DUMP_BUFSPEC))
+			dump_bufspec(hw, __func__);
+
+	}
+
+	if (hw->is_used_v4l) {
+		struct buffer_spec_s *pic = &hw->buffer_spec[buf_spec_num];
+
+		if (vf->v4l_mem_handle != pic->cma_alloc_addr)
+			pic->cma_alloc_addr = vf->v4l_mem_handle;
+	}
+
+	atomic_add(1, &hw->vf_put_count);
+	if (vf && (vf_valid_check(vf, hw) == true)) {
+		kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf);
+		ATRACE_COUNTER(hw->trace.new_q_name, kfifo_len(&hw->newframe_q));
+	}
+
+#define ASSIST_MBOX1_IRQ_REG    VDEC_ASSIST_MBOX1_IRQ_REG
+	if (hw->buffer_empty_flag)
+		WRITE_VREG(ASSIST_MBOX1_IRQ_REG, 0x1);
+	spin_unlock_irqrestore(&hw->bufspec_lock, flags);
+}
+
+void * vh264_get_bufspec_lock(struct vdec_s *vdec)
+{
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	if (hw)
+		return (&hw->bufspec_lock);
+	else
+		return NULL;
+}
+static int vh264_event_cb(int type, void *data, void *op_arg)
+{
+	unsigned long flags;
+	struct vdec_s *vdec = op_arg;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+
+	if (type & VFRAME_EVENT_RECEIVER_GET_AUX_DATA) {
+		struct provider_aux_req_s *req =
+			(struct provider_aux_req_s *)data;
+		int buf_spec_num;
+
+		if (!req->vf) {
+			req->aux_size = atomic_read(&hw->vf_put_count);
+			return 0;
+		}
+		buf_spec_num = BUFSPEC_INDEX(req->vf->index);
+		spin_lock_irqsave(&hw->lock, flags);
+		req->aux_buf = NULL;
+		req->aux_size = 0;
+		if (buf_spec_num >= 0 &&
+			buf_spec_num < BUFSPEC_POOL_SIZE &&
+			is_buf_spec_in_disp_q(hw, buf_spec_num)
+			) {
+			req->aux_buf =
+				hw->buffer_spec[buf_spec_num].aux_data_buf;
+			req->aux_size =
+				hw->buffer_spec[buf_spec_num].aux_data_size;
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+			req->dv_enhance_exist =
+				hw->buffer_spec[buf_spec_num].dv_enhance_exist;
+#else
+			req->dv_enhance_exist = 0;
+#endif
+		}
+		spin_unlock_irqrestore(&hw->lock, flags);
+
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+		"%s(type 0x%x vf buf_spec_num 0x%x)=>size 0x%x\n",
+		__func__, type, buf_spec_num, req->aux_size);
+	} else if (type & VFRAME_EVENT_RECEIVER_REQ_STATE) {
+		struct provider_state_req_s *req =
+			(struct provider_state_req_s *)data;
+		if (req->req_type == REQ_STATE_SECURE)
+			req->req_result[0] = vdec_secure(vdec);
+		else
+			req->req_result[0] = 0xffffffff;
+	}
+
+	return 0;
+}
+
+static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf,
+				u32 index)
+{
+	struct canvas_config_s *p_canvas_config;
+	int force_rate = input_frame_based(hw_to_vdec(hw)) ?
+		force_rate_framebase : force_rate_streambase;
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL,
+		"%s (%d,%d) dur %d, vf %p, index %d\n", __func__,
+		hw->frame_width, hw->frame_height, hw->frame_dur, vf, index);
+
+	/* signal_type */
+	if (hw->video_signal_from_vui & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) {
+		vf->signal_type = hw->video_signal_from_vui;
+		if (hw->is_used_v4l) {
+			struct aml_vdec_hdr_infos hdr;
+			struct aml_vcodec_ctx *ctx =
+				(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+
+			memset(&hdr, 0, sizeof(hdr));
+			hdr.signal_type = hw->video_signal_from_vui;
+			vdec_v4l_set_hdr_infos(ctx, &hdr);
+		}
+	} else
+		vf->signal_type = 0;
+	hw->video_signal_type = vf->signal_type;
+
+	vf->width = hw->frame_width;
+	vf->height = hw->frame_height;
+	if (force_rate) {
+		if (force_rate == -1)
+			vf->duration = 0;
+		else
+			vf->duration = 96000/force_rate;
+	} else
+		vf->duration = hw->frame_dur;
+	vf->ratio_control =
+		(min(hw->h264_ar, (u32) DISP_RATIO_ASPECT_RATIO_MAX)) <<
+		DISP_RATIO_ASPECT_RATIO_BIT;
+	vf->orientation = hw->vh264_rotation;
+
+	vf->sidebind_type = hw->sidebind_type;
+	vf->sidebind_channel_id = hw->sidebind_channel_id;
+
+	if (hw->mmu_enable)
+		return;
+
+	vf->canvas0Addr = vf->canvas1Addr = -1;
+#ifdef NV21
+	vf->plane_num = 2;
+#else
+	vf->plane_num = 3;
+#endif
+
+	if (IS_VDEC_DW(hw)) {
+		if (IS_VDEC_DW(hw) == 1)
+			vf->width = hw->frame_width / 2;
+		else
+			vf->width = (hw->frame_width / IS_VDEC_DW(hw));
+		vf->height = (hw->frame_height / IS_VDEC_DW(hw));
+		p_canvas_config = &hw->buffer_spec[index].vdec_dw_canvas_config[0];
+	} else
+		p_canvas_config = &hw->buffer_spec[index].canvas_config[0];
+
+	vf->canvas0_config[0] = p_canvas_config[0];
+	vf->canvas0_config[1] = p_canvas_config[1];
+#ifndef NV21
+	vf->canvas0_config[2] = p_canvas_config[2];
+#endif
+	vf->canvas1_config[0] = p_canvas_config[0];
+	vf->canvas1_config[1] = p_canvas_config[1];
+#ifndef NV21
+	vf->canvas1_config[2] = p_canvas_config[2];
+#endif
+}
+
+static void get_picture_qos_info(struct StorablePicture *picture)
+{
+	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) {
+		unsigned char a[3];
+		unsigned char i, j, t;
+		unsigned long  data;
+
+		get_random_bytes(&data, sizeof(unsigned long));
+		if (picture->slice_type == I_SLICE)
+			data = 0;
+		a[0] = data & 0xff;
+		a[1] = (data >> 8) & 0xff;
+		a[2] = (data >> 16) & 0xff;
+
+		for (i = 0; i < 3; i++)
+			for (j = i+1; j < 3; j++) {
+				if (a[j] < a[i]) {
+					t = a[j];
+					a[j] = a[i];
+					a[i] = t;
+				} else if (a[j] == a[i]) {
+					a[i]++;
+					t = a[j];
+					a[j] = a[i];
+					a[i] = t;
+				}
+			}
+		picture->max_mv = a[2];
+		picture->avg_mv = a[1];
+		picture->min_mv = a[0];
+		/*
+		pr_info("mv data %x  a[0]= %x a[1]= %x a[2]= %x\n",
+			data, a[0], a[1], a[2]);
+		*/
+
+		get_random_bytes(&data, sizeof(unsigned long));
+		a[0] = data & 0x1f;
+		a[1] = (data >> 8) & 0x3f;
+		a[2] = (data >> 16) & 0x7f;
+
+		for (i = 0; i < 3; i++)
+			for (j = i+1; j < 3; j++) {
+				if (a[j] < a[i]) {
+					t = a[j];
+					a[j] = a[i];
+					a[i] = t;
+				} else if (a[j] == a[i]) {
+					a[i]++;
+					t = a[j];
+					a[j] = a[i];
+					a[i] = t;
+				}
+			}
+		picture->max_qp = a[2];
+		picture->avg_qp = a[1];
+		picture->min_qp = a[0];
+		/*
+		pr_info("qp data %x  a[0]= %x a[1]= %x a[2]= %x\n",
+			data, a[0], a[1], a[2]);
+		*/
+
+		get_random_bytes(&data, sizeof(unsigned long));
+		a[0] = data & 0x1f;
+		a[1] = (data >> 8) & 0x3f;
+		a[2] = (data >> 16) & 0x7f;
+
+		for (i = 0; i < 3; i++)
+			for (j = i+1; j < 3; j++) {
+				if (a[j] < a[i]) {
+					t = a[j];
+					a[j] = a[i];
+					a[i] = t;
+				} else if (a[j] == a[i]) {
+					a[i]++;
+					t = a[j];
+					a[j] = a[i];
+					a[i] = t;
+				}
+			}
+		picture->max_skip = a[2];
+		picture->avg_skip = a[1];
+		picture->min_skip = a[0];
+
+
+		/*
+		pr_info("skip data %x  a[0]= %x a[1]= %x a[2]= %x\n",
+			data,a[0], a[1], a[2]);
+		*/
+	} else {
+		uint32_t blk88_y_count;
+		uint32_t blk88_c_count;
+		uint32_t blk22_mv_count;
+		uint32_t rdata32;
+		int32_t mv_hi;
+		int32_t mv_lo;
+		uint32_t rdata32_l;
+		uint32_t mvx_L0_hi;
+		uint32_t mvy_L0_hi;
+		uint32_t mvx_L1_hi;
+		uint32_t mvy_L1_hi;
+		int64_t value;
+		uint64_t temp_value;
+/*
+#define DEBUG_QOS
+*/
+#ifdef DEBUG_QOS
+		int pic_number = picture->poc;
+#endif
+
+		picture->max_mv = 0;
+		picture->avg_mv = 0;
+		picture->min_mv = 0;
+
+		picture->max_skip = 0;
+		picture->avg_skip = 0;
+		picture->min_skip = 0;
+
+		picture->max_qp = 0;
+		picture->avg_qp = 0;
+		picture->min_qp = 0;
+
+
+
+
+
+		/* set rd_idx to 0 */
+	    WRITE_VREG(VDEC_PIC_QUALITY_CTRL, 0);
+	    blk88_y_count = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	    if (blk88_y_count == 0) {
+#ifdef DEBUG_QOS
+			pr_info(" [Picture %d Quality] NO Data yet.\n",
+				pic_number);
+#endif
+			/* reset all counts */
+			WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8));
+			return;
+	    }
+		/* qp_y_sum */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] Y QP AVG : %d (%d/%d)\n",
+			pic_number, rdata32/blk88_y_count,
+			rdata32, blk88_y_count);
+#endif
+		picture->avg_qp = rdata32/blk88_y_count;
+		/* intra_y_count */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] Y intra rate : %d%c (%d)\n",
+			pic_number, rdata32*100/blk88_y_count,
+			'%', rdata32);
+#endif
+		/* skipped_y_count */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] Y skipped rate : %d%c (%d)\n",
+			pic_number, rdata32*100/blk88_y_count,
+			'%', rdata32);
+#endif
+		picture->avg_skip = rdata32*100/blk88_y_count;
+		/* coeff_non_zero_y_count */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] Y ZERO_Coeff rate : %d%c (%d)\n",
+			pic_number, (100 - rdata32*100/(blk88_y_count*1)),
+			'%', rdata32);
+#endif
+		/* blk66_c_count */
+	    blk88_c_count = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	    if (blk88_c_count == 0) {
+#ifdef DEBUG_QOS
+			pr_info(" [Picture %d Quality] NO Data yet.\n",
+				pic_number);
+#endif
+			/* reset all counts */
+			WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8));
+			return;
+	    }
+		/* qp_c_sum */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] C QP AVG : %d (%d/%d)\n",
+			pic_number, rdata32/blk88_c_count,
+			rdata32, blk88_c_count);
+#endif
+		/* intra_c_count */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] C intra rate : %d%c (%d)\n",
+			pic_number, rdata32*100/blk88_c_count,
+			'%', rdata32);
+#endif
+		/* skipped_cu_c_count */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] C skipped rate : %d%c (%d)\n",
+			pic_number, rdata32*100/blk88_c_count,
+			'%', rdata32);
+#endif
+		/* coeff_non_zero_c_count */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] C ZERO_Coeff rate : %d%c (%d)\n",
+			pic_number, (100 - rdata32*100/(blk88_c_count*1)),
+			'%', rdata32);
+#endif
+
+		/* 1'h0, qp_c_max[6:0], 1'h0, qp_c_min[6:0],
+		1'h0, qp_y_max[6:0], 1'h0, qp_y_min[6:0] */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] Y QP min : %d\n",
+			pic_number, (rdata32>>0)&0xff);
+#endif
+		picture->min_qp = (rdata32>>0)&0xff;
+
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] Y QP max : %d\n",
+			pic_number, (rdata32>>8)&0xff);
+#endif
+		picture->max_qp = (rdata32>>8)&0xff;
+
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] C QP min : %d\n",
+			pic_number, (rdata32>>16)&0xff);
+	    pr_info(" [Picture %d Quality] C QP max : %d\n",
+			pic_number, (rdata32>>24)&0xff);
+#endif
+
+		/* blk22_mv_count */
+	    blk22_mv_count = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	    if (blk22_mv_count == 0) {
+#ifdef DEBUG_QOS
+			pr_info(" [Picture %d Quality] NO MV Data yet.\n",
+				pic_number);
+#endif
+			/* reset all counts */
+			WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8));
+			return;
+	    }
+		/* mvy_L1_count[39:32], mvx_L1_count[39:32],
+		mvy_L0_count[39:32], mvx_L0_count[39:32] */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	    /* should all be 0x00 or 0xff */
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] MV AVG High Bits: 0x%X\n",
+			pic_number, rdata32);
+#endif
+	    mvx_L0_hi = ((rdata32>>0)&0xff);
+	    mvy_L0_hi = ((rdata32>>8)&0xff);
+	    mvx_L1_hi = ((rdata32>>16)&0xff);
+	    mvy_L1_hi = ((rdata32>>24)&0xff);
+
+		/* mvx_L0_count[31:0] */
+	    rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA);
+		temp_value = mvx_L0_hi;
+		temp_value = (temp_value << 32) | rdata32_l;
+
+		if (mvx_L0_hi & 0x80)
+			value = 0xFFFFFFF000000000 | temp_value;
+		else
+			value = temp_value;
+		value = div_s64(value, blk22_mv_count);
+#ifdef DEBUG_QOS
+		pr_info(" [Picture %d Quality] MVX_L0 AVG : %d (%lld/%d)\n",
+			pic_number, (int)(value),
+			value, blk22_mv_count);
+#endif
+		picture->avg_mv = value;
+
+		/* mvy_L0_count[31:0] */
+	    rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA);
+		temp_value = mvy_L0_hi;
+		temp_value = (temp_value << 32) | rdata32_l;
+
+		if (mvy_L0_hi & 0x80)
+			value = 0xFFFFFFF000000000 | temp_value;
+		else
+			value = temp_value;
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] MVY_L0 AVG : %d (%lld/%d)\n",
+			pic_number, rdata32_l/blk22_mv_count,
+			value, blk22_mv_count);
+#endif
+
+		/* mvx_L1_count[31:0] */
+	    rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA);
+		temp_value = mvx_L1_hi;
+		temp_value = (temp_value << 32) | rdata32_l;
+		if (mvx_L1_hi & 0x80)
+			value = 0xFFFFFFF000000000 | temp_value;
+		else
+			value = temp_value;
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] MVX_L1 AVG : %d (%lld/%d)\n",
+			pic_number, rdata32_l/blk22_mv_count,
+			value, blk22_mv_count);
+#endif
+
+		/* mvy_L1_count[31:0] */
+	    rdata32_l = READ_VREG(VDEC_PIC_QUALITY_DATA);
+		temp_value = mvy_L1_hi;
+		temp_value = (temp_value << 32) | rdata32_l;
+		if (mvy_L1_hi & 0x80)
+			value = 0xFFFFFFF000000000 | temp_value;
+		else
+			value = temp_value;
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] MVY_L1 AVG : %d (%lld/%d)\n",
+			pic_number, rdata32_l/blk22_mv_count,
+			value, blk22_mv_count);
+#endif
+
+		/* {mvx_L0_max, mvx_L0_min} // format : {sign, abs[14:0]}  */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	    mv_hi = (rdata32>>16)&0xffff;
+	    if (mv_hi & 0x8000)
+			mv_hi = 0x8000 - mv_hi;
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] MVX_L0 MAX : %d\n",
+			pic_number, mv_hi);
+#endif
+		picture->max_mv = mv_hi;
+
+	    mv_lo = (rdata32>>0)&0xffff;
+	    if (mv_lo & 0x8000)
+			mv_lo = 0x8000 - mv_lo;
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] MVX_L0 MIN : %d\n",
+			pic_number, mv_lo);
+#endif
+		picture->min_mv = mv_lo;
+
+#ifdef DEBUG_QOS
+		/* {mvy_L0_max, mvy_L0_min} */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	    mv_hi = (rdata32>>16)&0xffff;
+	    if (mv_hi & 0x8000)
+			mv_hi = 0x8000 - mv_hi;
+	    pr_info(" [Picture %d Quality] MVY_L0 MAX : %d\n",
+			pic_number, mv_hi);
+
+
+	    mv_lo = (rdata32>>0)&0xffff;
+	    if (mv_lo & 0x8000)
+			mv_lo = 0x8000 - mv_lo;
+
+	    pr_info(" [Picture %d Quality] MVY_L0 MIN : %d\n",
+			pic_number, mv_lo);
+
+
+		/* {mvx_L1_max, mvx_L1_min} */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	    mv_hi = (rdata32>>16)&0xffff;
+	    if (mv_hi & 0x8000)
+			mv_hi = 0x8000 - mv_hi;
+
+	    pr_info(" [Picture %d Quality] MVX_L1 MAX : %d\n",
+			pic_number, mv_hi);
+
+
+	    mv_lo = (rdata32>>0)&0xffff;
+	    if (mv_lo & 0x8000)
+			mv_lo = 0x8000 - mv_lo;
+
+	    pr_info(" [Picture %d Quality] MVX_L1 MIN : %d\n",
+			pic_number, mv_lo);
+
+
+		/* {mvy_L1_max, mvy_L1_min} */
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_DATA);
+	    mv_hi = (rdata32>>16)&0xffff;
+	    if (mv_hi & 0x8000)
+			mv_hi = 0x8000 - mv_hi;
+
+	    pr_info(" [Picture %d Quality] MVY_L1 MAX : %d\n",
+			pic_number, mv_hi);
+
+	    mv_lo = (rdata32>>0)&0xffff;
+	    if (mv_lo & 0x8000)
+			mv_lo = 0x8000 - mv_lo;
+
+	    pr_info(" [Picture %d Quality] MVY_L1 MIN : %d\n",
+			pic_number, mv_lo);
+#endif
+
+	    rdata32 = READ_VREG(VDEC_PIC_QUALITY_CTRL);
+#ifdef DEBUG_QOS
+	    pr_info(" [Picture %d Quality] After Read : VDEC_PIC_QUALITY_CTRL : 0x%x\n",
+			pic_number, rdata32);
+#endif
+		/* reset all counts */
+	    WRITE_VREG(VDEC_PIC_QUALITY_CTRL, (1<<8));
+	}
+}
+
+static int get_dec_dpb_size(struct vdec_h264_hw_s *hw, int mb_width,
+		int mb_height)
+{
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	int pic_size = mb_width * mb_height * 384;
+	int size = 0, size_vui;
+	int level_idc = p_H264_Dpb->mSPS.level_idc;
+
+	switch (level_idc) {
+	case 9:
+		size = 152064;
+		break;
+	case 10:
+		size = 152064;
+		break;
+	case 11:
+		size = 345600;
+		break;
+	case 12:
+		size = 912384;
+		break;
+	case 13:
+		size = 912384;
+		break;
+	case 20:
+		size = 912384;
+		break;
+	case 21:
+		size = 1824768;
+		break;
+	case 22:
+		size = 3110400;
+		break;
+	case 30:
+		size = 3110400;
+		break;
+	case 31:
+		size = 6912000;
+		break;
+	case 32:
+		size = 7864320;
+		break;
+	case 40:
+		size = 12582912;
+		break;
+	case 41:
+		size = 12582912;
+		break;
+	case 42:
+		size = 13369344;
+		break;
+	case 50:
+		size = 42393600;
+		break;
+	case 51:
+	case 52:
+	default:
+		size = 70778880;
+		break;
+	}
+
+	size /= pic_size;
+	size = imin(size, 16);
+	dpb_print(DECODE_ID(hw), 0,
+				"level_idc = %d pic_size = %d size = %d\n",
+				level_idc, pic_size, size);
+	if (p_H264_Dpb->bitstream_restriction_flag) {
+		if ((int)p_H264_Dpb->max_dec_frame_buffering > size) {
+			dpb_print(DECODE_ID(hw), 0,
+				"max_dec_frame_buffering larger than MaxDpbSize.\n");
+		}
+		size_vui = imax (1, p_H264_Dpb->max_dec_frame_buffering);
+		if (size_vui < size) {
+			dpb_print(DECODE_ID(hw), 0,
+				"Warning: max_dec_frame_buffering(%d) is less than DPB size(%d) calculated from Profile/Level.\n",
+				size_vui, size);
+		}
+		size = size_vui;
+	}
+
+	size += 2;	/* need two more buffer */
+
+	return size;
+}
+
+static int get_dec_dpb_size_active(struct vdec_h264_hw_s *hw, u32 param1)
+{
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	struct vdec_s *vdec = hw_to_vdec(hw);
+#endif
+	int mb_width, mb_total;
+	int mb_height = 0;
+	int active_buffer_spec_num, dec_dpb_size;
+	u32 used_reorder_dpb_size_margin
+			= hw->reorder_dpb_size_margin;
+
+	mb_width = param1 & 0xff;
+	mb_total = (param1 >> 8) & 0xffff;
+	if (!mb_width && mb_total) /*for 4k2k*/
+		mb_width = 256;
+	if (mb_width)
+		mb_height = mb_total/mb_width;
+	if (mb_width <= 0 || mb_height <= 0 ||
+		is_oversize(mb_width << 4, mb_height << 4)) {
+		dpb_print(DECODE_ID(hw), 0,
+			"!!!wrong param1 0x%x mb_width/mb_height (0x%x/0x%x) %x\r\n",
+			param1,
+			mb_width,
+			mb_height);
+		hw->error_frame_width = mb_width << 4;
+		hw->error_frame_height = mb_height << 4;
+		return -1;
+	}
+	hw->error_frame_width = 0;
+	hw->error_frame_height = 0;
+
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+		if (vdec->master || vdec->slave)
+			used_reorder_dpb_size_margin =
+				reorder_dpb_size_margin_dv;
+#endif
+
+	dec_dpb_size = get_dec_dpb_size(hw , mb_width, mb_height);
+
+	active_buffer_spec_num =
+		dec_dpb_size
+		+ used_reorder_dpb_size_margin;
+
+	if (active_buffer_spec_num > MAX_VF_BUF_NUM) {
+		active_buffer_spec_num = MAX_VF_BUF_NUM;
+		dec_dpb_size = active_buffer_spec_num
+			- used_reorder_dpb_size_margin;
+	}
+
+	hw->dpb.mDPB.size = active_buffer_spec_num;
+
+	if (hw->no_poc_reorder_flag)
+		dec_dpb_size = 1;
+
+	return dec_dpb_size;
+}
+
+static void vh264_config_canvs_for_mmu(struct vdec_h264_hw_s *hw)
+{
+	int i, j;
+
+	if (hw->double_write_mode) {
+		mutex_lock(&vmh264_mutex);
+		if (hw->decode_pic_count == 0) {
+			for (j = 0; j < hw->dpb.mDPB.size; j++) {
+				i = get_buf_spec_by_canvas_pos(hw, j);
+				if (i >= 0)
+					config_decode_canvas_ex(hw, i);
+			}
+		}
+		mutex_unlock(&vmh264_mutex);
+	}
+}
+
+static int vh264_set_params(struct vdec_h264_hw_s *hw,
+	u32 param1, u32 param2, u32 param3, u32 param4, bool buffer_reset_flag)
+{
+	int i, j;
+	int mb_width, mb_total;
+	int max_reference_size, level_idc;
+	int mb_height = 0;
+	unsigned long flags;
+	/*int mb_mv_byte;*/
+	struct vdec_s *vdec = hw_to_vdec(hw);
+	u32 seq_info2;
+	int ret = 0;
+	int active_buffer_spec_num;
+	unsigned int buf_size;
+	unsigned int frame_mbs_only_flag;
+	unsigned int chroma_format_idc;
+	unsigned int crop_bottom, crop_right;
+	unsigned int used_reorder_dpb_size_margin
+		= hw->reorder_dpb_size_margin;
+	u8 *colocate_vaddr = NULL;
+	int dec_dpb_size_change = 0;
+
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	if (vdec->master || vdec->slave)
+		used_reorder_dpb_size_margin =
+			reorder_dpb_size_margin_dv;
+#endif
+	seq_info2 = param1;
+	hw->seq_info = param2;
+
+	mb_width = seq_info2 & 0xff;
+	mb_total = (seq_info2 >> 8) & 0xffff;
+	if (!mb_width && mb_total) /*for 4k2k*/
+		mb_width = 256;
+	if (mb_width)
+		mb_height = mb_total/mb_width;
+	if (mb_width <= 0 || mb_height <= 0 ||
+		is_oversize(mb_width << 4, mb_height << 4)) {
+		dpb_print(DECODE_ID(hw), 0,
+			"!!!wrong seq_info2 0x%x mb_width/mb_height (0x%x/0x%x) %x\r\n",
+			seq_info2,
+			mb_width,
+			mb_height);
+			hw->error_frame_width = mb_width << 4;
+			hw->error_frame_height = mb_height << 4;
+		return -1;
+	}
+	hw->error_frame_width = 0;
+	hw->error_frame_height = 0;
+
+	dec_dpb_size_change = hw->csd_change_flag && (hw->dpb.dec_dpb_size != get_dec_dpb_size_active(hw, param1));
+
+	if (((seq_info2 != 0 &&
+		hw->seq_info2 != seq_info2) || hw->csd_change_flag) &&
+		hw->seq_info2 != 0
+		) {
+		if (hw->seq_info2 != seq_info2 || dec_dpb_size_change) { /*picture size changed*/
+			h264_reconfig(hw);
+		} else {
+			/*someting changes and not including dpb_size, width, height, ...*/
+			struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+			u32 reg_val = param4;
+			max_reference_size = (reg_val >> 8) & 0xff;
+			hw->dpb.reorder_output = max_reference_size;
+
+			if (p_H264_Dpb->bitstream_restriction_flag &&
+				p_H264_Dpb->num_reorder_frames <= p_H264_Dpb->max_dec_frame_buffering &&
+				p_H264_Dpb->num_reorder_frames >= 0) {
+				hw->dpb.reorder_output = hw->num_reorder_frames + 1;
+			}
+		}
+	}
+
+	if (hw->config_bufmgr_done == 0) {
+		struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+		u32 reg_val;
+		int sub_width_c = 0, sub_height_c = 0;
+
+		hw->cfg_param1 = param1;
+		hw->cfg_param2 = param2;
+		hw->cfg_param3 = param3;
+		hw->cfg_param4 = param4;
+
+		hw->seq_info2 = seq_info2;
+		dpb_print(DECODE_ID(hw), 0,
+			"AV_SCRATCH_1 = %x, AV_SCRATCH_2 %x\r\n",
+			seq_info2, hw->seq_info);
+
+		dpb_init_global(&hw->dpb,
+			DECODE_ID(hw), 0, 0);
+
+		p_H264_Dpb->fast_output_enable = fast_output_enable;
+		/*mb_mv_byte = (seq_info2 & 0x80000000) ? 24 : 96;*/
+		if (hw->enable_fence)
+			p_H264_Dpb->fast_output_enable = H264_OUTPUT_MODE_FAST;
+#if 1
+		/*crop*/
+		/* AV_SCRATCH_2
+		   bit 15: frame_mbs_only_flag
+		   bit 13-14: chroma_format_idc */
+		frame_mbs_only_flag = (hw->seq_info >> 15) & 0x01;
+		if (p_H264_Dpb->mSPS.profile_idc != 100 &&
+			p_H264_Dpb->mSPS.profile_idc != 110 &&
+			p_H264_Dpb->mSPS.profile_idc != 122 &&
+			p_H264_Dpb->mSPS.profile_idc != 144) {
+			p_H264_Dpb->chroma_format_idc = 1;
+		}
+		chroma_format_idc = p_H264_Dpb->chroma_format_idc;
+
+		/* @AV_SCRATCH_6.31-16 =  (left  << 8 | right ) << 1
+		   @AV_SCRATCH_6.15-0   =  (top << 8  | bottom ) <<
+		   (2 - frame_mbs_only_flag) */
+
+		switch (chroma_format_idc) {
+			case 1:
+				sub_width_c = 2;
+				sub_height_c = 2;
+				break;
+
+			case 2:
+				sub_width_c = 2;
+				sub_height_c = 1;
+				break;
+
+			case 3:
+				sub_width_c = 1;
+				sub_height_c = 1;
+				break;
+
+			default:
+				break;
+		}
+
+		if (chroma_format_idc == 0) {
+			crop_right = p_H264_Dpb->frame_crop_right_offset;
+			crop_bottom = p_H264_Dpb->frame_crop_bottom_offset *
+				(2 - frame_mbs_only_flag);
+		} else {
+			crop_right = sub_width_c * p_H264_Dpb->frame_crop_right_offset;
+			crop_bottom = sub_height_c * p_H264_Dpb->frame_crop_bottom_offset *
+				(2 - frame_mbs_only_flag);
+		}
+
+		p_H264_Dpb->mSPS.frame_mbs_only_flag = frame_mbs_only_flag;
+		hw->frame_width = mb_width << 4;
+		hw->frame_height = mb_height << 4;
+
+		hw->frame_width = hw->frame_width - crop_right;
+		hw->frame_height = hw->frame_height - crop_bottom;
+
+		dpb_print(DECODE_ID(hw), 0,
+			"chroma_format_idc = %d frame_mbs_only_flag %d, crop_bottom %d,  frame_height %d,\n",
+			chroma_format_idc, frame_mbs_only_flag, crop_bottom, hw->frame_height);
+		dpb_print(DECODE_ID(hw), 0,
+			"mb_height %d,crop_right %d, frame_width %d, mb_width %d\n",
+			mb_height, crop_right,
+			hw->frame_width, mb_width);
+
+		if (hw->frame_height == 1088 && (crop_right != 0 || crop_bottom != 0))
+			hw->frame_height = 1080;
+#endif
+		reg_val = param4;
+		level_idc = reg_val & 0xff;
+		p_H264_Dpb->mSPS.level_idc = level_idc;
+		max_reference_size = (reg_val >> 8) & 0xff;
+		hw->dpb.reorder_output = max_reference_size;
+		hw->dpb.dec_dpb_size =
+			get_dec_dpb_size(hw , mb_width, mb_height);
+		if (!hw->mmu_enable) {
+			mb_width = (mb_width+3) & 0xfffffffc;
+			mb_height = (mb_height+3) & 0xfffffffc;
+		}
+		mb_total = mb_width * mb_height;
+		hw->mb_width = mb_width;
+		hw->mb_height = mb_height;
+		hw->mb_total = mb_total;
+		if (hw->mmu_enable)
+			hevc_mcr_sao_global_hw_init(hw,
+				(hw->mb_width << 4), (hw->mb_height << 4));
+
+		dpb_print(DECODE_ID(hw), 0,
+			"mb height/widht/total: %x/%x/%x level_idc %x max_ref_num %x\n",
+			mb_height, mb_width, mb_total,
+			level_idc, max_reference_size);
+
+		p_H264_Dpb->colocated_buf_size = mb_total * 96;
+
+		dpb_print(DECODE_ID(hw), 0,
+			"restriction_flag=%d, max_dec_frame_buffering=%d, dec_dpb_size=%d num_reorder_frames %d used_reorder_dpb_size_margin %d\n",
+			hw->bitstream_restriction_flag,
+			hw->max_dec_frame_buffering,
+			hw->dpb.dec_dpb_size,
+			hw->num_reorder_frames,
+			used_reorder_dpb_size_margin);
+
+		if (p_H264_Dpb->bitstream_restriction_flag &&
+			p_H264_Dpb->num_reorder_frames <= p_H264_Dpb->max_dec_frame_buffering &&
+			p_H264_Dpb->num_reorder_frames >= 0) {
+			hw->dpb.reorder_output = hw->num_reorder_frames + 1;
+		}
+
+		active_buffer_spec_num =
+			hw->dpb.dec_dpb_size
+			+ used_reorder_dpb_size_margin;
+		hw->max_reference_size =
+			max_reference_size + reference_buf_margin;
+
+		if (active_buffer_spec_num > MAX_VF_BUF_NUM) {
+			active_buffer_spec_num = MAX_VF_BUF_NUM;
+			hw->dpb.dec_dpb_size = active_buffer_spec_num
+				- used_reorder_dpb_size_margin;
+			dpb_print(DECODE_ID(hw), 0,
+				"active_buffer_spec_num is larger than MAX %d, set dec_dpb_size to %d\n",
+				MAX_VF_BUF_NUM, hw->dpb.dec_dpb_size);
+		}
+		hw->dpb.mDPB.size = active_buffer_spec_num;
+		if (hw->max_reference_size > MAX_VF_BUF_NUM)
+			hw->max_reference_size = MAX_VF_BUF_NUM;
+		hw->dpb.max_reference_size = hw->max_reference_size;
+
+		if (hw->no_poc_reorder_flag)
+			hw->dpb.dec_dpb_size = 1;
+		dpb_print(DECODE_ID(hw), 0,
+			"%s active_buf_spec_num %d dec_dpb_size %d collocate_buf_num %d\r\n",
+			__func__, active_buffer_spec_num,
+			hw->dpb.dec_dpb_size,
+			hw->max_reference_size);
+
+		if (hw->kpi_first_i_comming == 0) {
+			hw->kpi_first_i_comming = 1;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL,
+				"[vdec_kpi][%s] First I frame comming.\n", __func__);
+		}
+
+		buf_size = (hw->mb_total << 8) + (hw->mb_total << 7);
+
+		mutex_lock(&vmh264_mutex);
+		if (!hw->mmu_enable) {
+			if (!buffer_reset_flag || hw->is_used_v4l)
+				config_buf_specs(vdec);
+			i = get_buf_spec_by_canvas_pos(hw, 0);
+
+			if (hw->is_used_v4l) {
+				if (i != -1) {
+					pr_info("v4l: delay alloc the buffer.\n");
+				}
+			} else {
+				if ((i != -1) && alloc_one_buf_spec(hw, i) >= 0)
+					config_decode_canvas(hw, i);
+				else
+					ret = -1;
+			}
+		} else {
+			if (hw->double_write_mode) {
+				config_buf_specs_ex(vdec);
+			} else {
+				spin_lock_irqsave(&hw->bufspec_lock, flags);
+				for (i = 0, j = 0;
+					j < active_buffer_spec_num
+					&& i < BUFSPEC_POOL_SIZE;
+					i++) {
+					if (hw->buffer_spec[i].used != -1)
+						continue;
+					hw->buffer_spec[i].used = 0;
+					hw->buffer_spec[i].
+						alloc_header_addr = 0;
+					hw->buffer_spec[i].canvas_pos = j;
+					j++;
+				}
+				spin_unlock_irqrestore(&hw->bufspec_lock,
+					flags);
+			}
+			hevc_mcr_config_canv2axitbl(hw, 0);
+		}
+		mutex_unlock(&vmh264_mutex);
+		if (dpb_is_debug(DECODE_ID(hw),
+			PRINT_FLAG_DUMP_BUFSPEC))
+			dump_bufspec(hw, __func__);
+
+#ifdef ONE_COLOCATE_BUF_PER_DECODE_BUF
+		buf_size = PAGE_ALIGN(
+			p_H264_Dpb->colocated_buf_size *
+					active_buffer_spec_num);
+#else
+		buf_size = PAGE_ALIGN(
+			p_H264_Dpb->colocated_buf_size *
+					hw->max_reference_size);
+#endif
+
+		if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, BMMU_REF_IDX,
+			buf_size, DRIVER_NAME,
+			&hw->collocate_cma_alloc_addr) < 0)
+			return -1;
+		if (!vdec_secure(vdec)) {
+			/* clear for some mosaic problem after reset bufmgr */
+			colocate_vaddr = codec_mm_vmap(hw->collocate_cma_alloc_addr, buf_size);
+			if (colocate_vaddr != NULL) {
+				memset(colocate_vaddr, 0, buf_size);
+				codec_mm_dma_flush(colocate_vaddr, buf_size, DMA_TO_DEVICE);
+				codec_mm_unmap_phyaddr(colocate_vaddr);
+			}
+		}
+
+		hw->dpb.colocated_mv_addr_start =
+			hw->collocate_cma_alloc_addr;
+#ifdef ONE_COLOCATE_BUF_PER_DECODE_BUF
+		hw->dpb.colocated_mv_addr_end  =
+			hw->dpb.colocated_mv_addr_start +
+			(p_H264_Dpb->colocated_buf_size *
+			active_buffer_spec_num);
+#else
+		hw->dpb.colocated_mv_addr_end  =
+			hw->dpb.colocated_mv_addr_start +
+			(p_H264_Dpb->colocated_buf_size *
+			hw->max_reference_size);
+#endif
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+			"callocate cma, %lx, %x\n",
+			hw->collocate_cma_alloc_addr,
+			hw->dpb.colocated_mv_addr_start);
+
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+			"colocated_mv_addr_start %x colocated_mv_addr_end %x\n",
+			hw->dpb.colocated_mv_addr_start,
+			hw->dpb.colocated_mv_addr_end);
+		if (!hw->mmu_enable) {
+			mutex_lock(&vmh264_mutex);
+			if (ret >= 0 && hw->decode_pic_count == 0) {
+				int buf_cnt;
+				/* h264_reconfig: alloc later*/
+				buf_cnt = hw->dpb.mDPB.size;
+
+				for (j = 1; j < buf_cnt; j++) {
+					i = get_buf_spec_by_canvas_pos(hw, j);
+
+					if (hw->is_used_v4l) {
+						pr_info("v4l: delay alloc the buffer.\n");
+						break;
+					} else if (alloc_one_buf_spec(hw, i) < 0)
+						break;
+
+					config_decode_canvas(hw, i);
+				}
+			}
+			mutex_unlock(&vmh264_mutex);
+		} else {
+			vh264_config_canvs_for_mmu(hw);
+		}
+
+		hw->config_bufmgr_done = 1;
+
+	/*end of  config_bufmgr_done */
+	}
+
+	return ret;
+}
+
+static void vui_config(struct vdec_h264_hw_s *hw)
+{
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	int aspect_ratio_info_present_flag, aspect_ratio_idc;
+	/*time*/
+	hw->num_units_in_tick = p_H264_Dpb->num_units_in_tick;
+	hw->time_scale = p_H264_Dpb->time_scale;
+	hw->timing_info_present_flag = p_H264_Dpb->vui_status & 0x2;
+
+	hw->bitstream_restriction_flag =
+		p_H264_Dpb->bitstream_restriction_flag;
+	hw->num_reorder_frames =
+		p_H264_Dpb->num_reorder_frames;
+	hw->max_dec_frame_buffering =
+		p_H264_Dpb->max_dec_frame_buffering;
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL,
+		"vui_config: pdb %d, %d, %d\n",
+		p_H264_Dpb->bitstream_restriction_flag,
+		p_H264_Dpb->num_reorder_frames,
+		p_H264_Dpb->max_dec_frame_buffering);
+
+	hw->fixed_frame_rate_flag = 0;
+	if (hw->timing_info_present_flag) {
+		hw->fixed_frame_rate_flag =
+			p_H264_Dpb->fixed_frame_rate_flag;
+
+		if (((hw->num_units_in_tick * 120) >= hw->time_scale &&
+			((!hw->sync_outside) ||
+				(!hw->frame_dur)))
+			&& hw->num_units_in_tick && hw->time_scale) {
+			if (hw->use_idr_framerate ||
+				hw->fixed_frame_rate_flag ||
+				!hw->frame_dur ||
+				!hw->duration_from_pts_done
+				/*|| vh264_running*/) {
+				u32 frame_dur_es =
+				div_u64(96000ULL * 2 * hw->num_units_in_tick,
+					hw->time_scale);
+				if (hw->frame_dur != frame_dur_es) {
+					hw->h264_first_valid_pts_ready = false;
+					hw->h264pts1 = 0;
+					hw->h264pts2 = 0;
+					hw->h264_pts_count = 0;
+					hw->duration_from_pts_done = 0;
+					fixed_frame_rate_mode =
+						FIX_FRAME_RATE_OFF;
+					hw->pts_duration = 0;
+					hw->frame_dur = frame_dur_es;
+					if (!hw->fixed_frame_rate_flag && (p_H264_Dpb->mSPS.profile_idc != BASELINE)) {
+						if (frame_dur_es == 7680)
+							hw->frame_dur = frame_dur_es /2;
+					}
+					vdec_schedule_work(&hw->notify_work);
+					dpb_print(DECODE_ID(hw),
+						PRINT_FLAG_DEC_DETAIL,
+						"frame_dur %d from timing_info\n",
+						hw->frame_dur);
+				}
+
+				/*hack to avoid use ES frame duration when
+				 *it's half of the rate from system info
+				 * sometimes the encoder is given a wrong
+				 * frame rate but the system side information
+				 * is more reliable
+				 *if ((frame_dur * 2) != frame_dur_es) {
+				 *    frame_dur = frame_dur_es;
+				 *}
+				 */
+			}
+		}
+	} else {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+			"H.264: timing_info not present\n");
+	}
+
+	/*aspect ratio*/
+	aspect_ratio_info_present_flag =
+		p_H264_Dpb->vui_status & 0x1;
+	aspect_ratio_idc = p_H264_Dpb->aspect_ratio_idc;
+
+	if (aspect_ratio_info_present_flag) {
+		if (aspect_ratio_idc == EXTEND_SAR) {
+			hw->h264_ar = 0x3ff;
+			hw->height_aspect_ratio =
+				p_H264_Dpb->aspect_ratio_sar_height;
+			hw->width_aspect_ratio =
+				p_H264_Dpb->aspect_ratio_sar_width;
+		} else {
+			/* pr_info("v264dec: aspect_ratio_idc = %d\n",
+			   aspect_ratio_idc); */
+
+			switch (aspect_ratio_idc) {
+			case 1:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 1;
+				hw->width_aspect_ratio = 1;
+				break;
+			case 2:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 11;
+				hw->width_aspect_ratio = 12;
+				break;
+			case 3:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 11;
+				hw->width_aspect_ratio = 10;
+				break;
+			case 4:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 11;
+				hw->width_aspect_ratio = 16;
+				break;
+			case 5:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 33;
+				hw->width_aspect_ratio = 40;
+				break;
+			case 6:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 11;
+				hw->width_aspect_ratio = 24;
+				break;
+			case 7:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 11;
+				hw->width_aspect_ratio = 20;
+				break;
+			case 8:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 11;
+				hw->width_aspect_ratio = 32;
+				break;
+			case 9:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 33;
+				hw->width_aspect_ratio = 80;
+				break;
+			case 10:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 11;
+				hw->width_aspect_ratio = 18;
+				break;
+			case 11:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 11;
+				hw->width_aspect_ratio = 15;
+				break;
+			case 12:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 33;
+				hw->width_aspect_ratio = 64;
+				break;
+			case 13:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 99;
+				hw->width_aspect_ratio = 160;
+				break;
+			case 14:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 3;
+				hw->width_aspect_ratio = 4;
+				break;
+			case 15:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 2;
+				hw->width_aspect_ratio = 3;
+				break;
+			case 16:
+				hw->h264_ar = 0x3ff;
+				hw->height_aspect_ratio = 1;
+				hw->width_aspect_ratio = 2;
+				break;
+			default:
+				if (hw->vh264_ratio >> 16) {
+					hw->h264_ar = (hw->frame_height *
+						(hw->vh264_ratio & 0xffff) *
+						0x100 +
+						((hw->vh264_ratio >> 16) *
+						 hw->frame_width / 2)) /
+						((hw->vh264_ratio >> 16) *
+						 hw->frame_width);
+					hw->height_aspect_ratio = 1;
+					hw->width_aspect_ratio = 1;
+				} else {
+					hw->h264_ar = 0x3ff;
+					hw->height_aspect_ratio = 1;
+					hw->width_aspect_ratio = 1;
+				}
+				break;
+			}
+		}
+	} else {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+			"v264dec: aspect_ratio not available from source\n");
+		if (hw->vh264_ratio >> 16) {
+			/* high 16 bit is width, low 16 bit is height */
+			hw->h264_ar =
+				((hw->vh264_ratio & 0xffff) *
+					hw->frame_height * 0x100 +
+				 (hw->vh264_ratio >> 16) *
+				 hw->frame_width / 2) /
+				((hw->vh264_ratio >> 16) *
+					hw->frame_width);
+			hw->height_aspect_ratio = 1;
+			hw->width_aspect_ratio = 1;
+		} else {
+			hw->h264_ar = 0x3ff;
+			hw->height_aspect_ratio = 1;
+			hw->width_aspect_ratio = 1;
+		}
+	}
+
+	if (hw->pts_unstable && (hw->fixed_frame_rate_flag == 0)) {
+		if (((hw->frame_dur == RATE_2397_FPS)
+		&& (dec_control
+		& DEC_CONTROL_FLAG_FORCE_RATE_2397_FPS_FIX_FRAME_RATE))
+			|| ((RATE_2997_FPS ==
+			hw->frame_dur) &&
+		(dec_control &
+			DEC_CONTROL_FLAG_FORCE_RATE_2997_FPS_FIX_FRAME_RATE))) {
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+				"force fix frame rate\n");
+			hw->fixed_frame_rate_flag = 0x40;
+		}
+	}
+
+	/*video_signal_from_vui: to do .. */
+}
+
+static void bufmgr_recover(struct vdec_h264_hw_s *hw)
+{
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+
+	bufmgr_h264_remove_unused_frame(p_H264_Dpb, 2);
+	if (error_proc_policy & 0x20) {
+		if (!hw->is_used_v4l)
+			hw->reset_bufmgr_flag = 1;
+	}
+}
+
+void bufmgr_force_recover(struct h264_dpb_stru *p_H264_Dpb)
+{
+	struct vdec_h264_hw_s *hw =
+		container_of(p_H264_Dpb, struct vdec_h264_hw_s, dpb);
+
+	dpb_print(DECODE_ID(hw), 0,	"call %s\n", __func__);
+
+	bufmgr_h264_remove_unused_frame(p_H264_Dpb, 2);
+	hw->reset_bufmgr_flag = 1;
+}
+
+#ifdef CONSTRAIN_MAX_BUF_NUM
+static int get_vf_ref_only_buf_count(struct vdec_h264_hw_s *hw)
+{
+	int i;
+	int count = 0;
+	for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+		if (is_buf_spec_in_disp_q(hw, i) &&
+			hw->buffer_spec[i].vf_ref > 0)
+			count++;
+	}
+	return count;
+}
+
+static int get_used_buf_count(struct vdec_h264_hw_s *hw)
+{
+	int i;
+	int count = 0;
+	for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+		if (is_buf_spec_in_use(hw, i))
+			count++;
+	}
+	return count;
+}
+#endif
+
+
+static bool is_buffer_available(struct vdec_s *vdec)
+{
+	bool buffer_available = 1;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)(vdec->private);
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+	int i, frame_outside_count = 0, inner_size = 0;
+	if ((kfifo_len(&hw->newframe_q) <= 0) ||
+	    ((hw->config_bufmgr_done) && (!have_free_buf_spec(vdec))) ||
+	    ((p_H264_Dpb->mDPB.init_done) &&
+	     (p_H264_Dpb->mDPB.used_size >= (p_H264_Dpb->mDPB.size - 1)) &&
+	     (is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB) == 0))) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL,
+		"%s, empty, newq(%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d)\n",
+		__func__,
+		kfifo_len(&hw->newframe_q),
+		have_free_buf_spec(vdec),
+		p_H264_Dpb->mDPB.init_done,
+		p_H264_Dpb->mDPB.used_size, p_H264_Dpb->mDPB.size,
+		is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB)
+		);
+		buffer_available = 0;
+		if (dpb_is_debug(DECODE_ID(hw),
+			DEBUG_DISABLE_RUNREADY_RMBUF))
+			return buffer_available;
+
+		if ((error_proc_policy & 0x4) &&
+			(error_proc_policy & 0x8)) {
+			if ((kfifo_len(&hw->display_q) <= 0) &&
+			(p_H264_Dpb->mDPB.used_size >=
+				(p_H264_Dpb->mDPB.size - 1)) &&
+				(p_Dpb->ref_frames_in_buffer >
+				(imax(
+				1, p_Dpb->num_ref_frames)
+				- p_Dpb->ltref_frames_in_buffer +
+				force_sliding_margin))){
+				bufmgr_recover(hw);
+			} else {
+				bufmgr_h264_remove_unused_frame(p_H264_Dpb, 1);
+			}
+		} else if ((error_proc_policy & 0x4) &&
+			(kfifo_len(&hw->display_q) <= 0) &&
+			((p_H264_Dpb->mDPB.used_size >=
+				(p_H264_Dpb->mDPB.size - 1)) ||
+			(!have_free_buf_spec(vdec)))) {
+			unsigned long flags;
+			spin_lock_irqsave(&hw->bufspec_lock, flags);
+
+			for (i = 0; i < p_Dpb->used_size; i++) {
+				if (p_Dpb->fs[i]->pre_output)
+					frame_outside_count++;
+				else if (p_Dpb->fs[i]->is_output && !is_used_for_reference(p_Dpb->fs[i])) {
+					spin_unlock_irqrestore(&hw->bufspec_lock, flags);
+					bufmgr_h264_remove_unused_frame(p_H264_Dpb, 0);
+					return 0;
+				}
+			}
+			spin_unlock_irqrestore(&hw->bufspec_lock, flags);
+			inner_size = p_Dpb->size - frame_outside_count;
+
+			if (inner_size >= p_H264_Dpb->dec_dpb_size) {
+				if (p_H264_Dpb->mDPB.used_size >=
+					p_H264_Dpb->mDPB.size) {
+					bufmgr_recover(hw);
+				} else if (p_H264_Dpb->mDPB.used_size >=
+					(p_H264_Dpb->mDPB.size - 1)) {
+					if (inner_size > p_H264_Dpb->dec_dpb_size) {
+						bufmgr_recover(hw);
+					}
+				}
+			}
+			bufmgr_h264_remove_unused_frame(p_H264_Dpb, 0);
+		} else if ((error_proc_policy & 0x8) &&
+			(p_Dpb->ref_frames_in_buffer >
+			(imax(
+			1, p_Dpb->num_ref_frames)
+			- p_Dpb->ltref_frames_in_buffer +
+			force_sliding_margin)))
+			bufmgr_recover(hw);
+		else
+			bufmgr_h264_remove_unused_frame(p_H264_Dpb, 1);
+
+		if (hw->reset_bufmgr_flag == 1)
+			buffer_available = 1;
+	}
+
+	if (hw->is_used_v4l)
+		buffer_available = have_free_buf_spec(vdec);
+
+	return buffer_available;
+}
+
+#define AUX_TAG_SEI				0x2
+
+#define SEI_BUFFERING_PERIOD	0
+#define SEI_PicTiming			1
+#define SEI_USER_DATA			4
+#define SEI_RECOVERY_POINT		6
+
+/*
+ *************************************************************************
+ * Function:Reads bits from the bitstream buffer
+ * Input:
+	byte buffer[]
+		containing sei message data bits
+	int totbitoffset
+		bit offset from start of partition
+	int bytecount
+		total bytes in bitstream
+	int numbits
+		number of bits to read
+ * Output:
+	int *info
+ * Return:
+	-1: failed
+	> 0: the count of bit read
+ * Attention:
+ *************************************************************************
+ */
+
+static int get_bits(unsigned char buffer[],
+					int totbitoffset,
+					int *info,
+					int bytecount,
+					int numbits)
+{
+	register int inf;
+	long byteoffset;
+	int bitoffset;
+
+	int bitcounter = numbits;
+
+	byteoffset = totbitoffset / 8;
+	bitoffset = 7 - (totbitoffset % 8);
+
+	inf = 0;
+	while (numbits) {
+		inf <<= 1;
+		inf |= (buffer[byteoffset] & (0x01 << bitoffset)) >> bitoffset;
+		numbits--;
+		bitoffset--;
+		if (bitoffset < 0) {
+			byteoffset++;
+			bitoffset += 8;
+			if (byteoffset > bytecount)
+				return -1;
+		}
+	}
+
+	*info = inf;
+
+
+	return bitcounter;
+}
+
+static int parse_one_sei_record(struct vdec_h264_hw_s *hw,
+							u8 *sei_data_buf,
+							u8 *sei_data_buf_end)
+{
+	int payload_type;
+	int payload_size;
+	u8 *p_sei;
+	int temp = 0;
+	int bit_offset;
+	int read_size;
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+
+	p_sei = sei_data_buf;
+	read_size = 0;
+	payload_type = 0;
+	do {
+		if (p_sei >= sei_data_buf_end)
+			return read_size;
+
+		payload_type += *p_sei;
+		read_size++;
+	} while (*p_sei++ == 255);
+
+
+	payload_size = 0;
+	do {
+		if (p_sei >= sei_data_buf_end)
+			return read_size;
+
+		payload_size += *p_sei;
+		read_size++;
+	} while (*p_sei++ == 255);
+
+
+	if (p_sei + payload_size > sei_data_buf_end) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL,
+			"%s: payload_type = %d, payload_size = %d is over\n",
+			__func__, payload_type, payload_size);
+		return read_size;
+	}
+	bit_offset = 0;
+
+	if (payload_size <= 0) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL,
+			"%s warning: this is a null sei message for payload_type = %d\n",
+			__func__, payload_type);
+		return read_size;
+	}
+	p_H264_Dpb->vui_status = p_H264_Dpb->dpb_param.l.data[VUI_STATUS];
+	switch (payload_type) {
+	case SEI_BUFFERING_PERIOD:
+		break;
+	case SEI_PicTiming:
+		if (p_H264_Dpb->vui_status & 0xc) {
+			int cpb_removal_delay;
+			int dpb_output_delay;
+			u32 delay_len;
+
+			delay_len = p_H264_Dpb->dpb_param.l.data[DELAY_LENGTH];
+			cpb_removal_delay
+				= (delay_len & 0x1F) + 1;
+			dpb_output_delay
+				= ((delay_len >> 5) & 0x1F) + 1;
+
+			get_bits(p_sei, bit_offset,
+				&temp, payload_size,
+				dpb_output_delay+cpb_removal_delay);
+			bit_offset += dpb_output_delay+cpb_removal_delay;
+		}
+		if (p_H264_Dpb->vui_status & 0x10) {
+			get_bits(p_sei, bit_offset, &temp, payload_size, 4);
+			bit_offset += 4;
+			p_H264_Dpb->dpb_param.l.data[PICTURE_STRUCT] = temp;
+		}
+		break;
+	case SEI_USER_DATA:
+		if (enable_itu_t35) {
+			int i;
+			int j;
+			int data_len;
+			u8 *user_data_buf;
+
+			user_data_buf
+				= hw->sei_itu_data_buf + hw->sei_itu_data_len;
+			/* user data length should be align with 8 bytes,
+			if not, then padding with zero*/
+			for (i = 0; i < payload_size; i += 8) {
+				if (hw->sei_itu_data_len + i >= SEI_ITU_DATA_SIZE)
+					break; // Avoid out-of-bound writing
+				for (j = 0; j < 8; j++) {
+					int index;
+
+					index = i+7-j;
+					if (index >= payload_size)
+						user_data_buf[i+j] = 0;
+					else
+						user_data_buf[i+j]
+							= p_sei[i+7-j];
+				}
+			}
+
+			data_len = payload_size;
+			if (payload_size % 8)
+				data_len = ((payload_size + 8) >> 3) << 3;
+
+			hw->sei_itu_data_len += data_len;
+			if (hw->sei_itu_data_len >= SEI_ITU_DATA_SIZE)
+				hw->sei_itu_data_len = SEI_ITU_DATA_SIZE;
+			/*
+			dpb_print(DECODE_ID(hw), 0,
+				"%s: user data, and len = %d:\n",
+				__func__, hw->sei_itu_data_len);
+			*/
+		}
+		break;
+	case SEI_RECOVERY_POINT:
+		p_H264_Dpb->dpb_param.l.data[RECOVERY_POINT] = 1;
+		break;
+	}
+
+	return read_size + payload_size;
+}
+
+static void parse_sei_data(struct vdec_h264_hw_s *hw,
+							u8 *sei_data_buf,
+							int len)
+{
+	char *p_sei;
+	char *p_sei_end;
+	int parsed_size;
+	int read_size;
+
+
+	p_sei = sei_data_buf;
+	p_sei_end = p_sei + len;
+	parsed_size = 0;
+	while (parsed_size < len) {
+		read_size = parse_one_sei_record(hw, p_sei, p_sei_end);
+		p_sei += read_size;
+		parsed_size += read_size;
+		if (*p_sei == 0x80) {
+			p_sei++;
+			parsed_size++;
+		}
+	}
+}
+
+static void check_decoded_pic_error(struct vdec_h264_hw_s *hw)
+{
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	struct StorablePicture *p = p_H264_Dpb->mVideo.dec_picture;
+	unsigned mby_mbx = READ_VREG(MBY_MBX);
+	unsigned mb_total = (hw->seq_info2 >> 8) & 0xffff;
+	unsigned mb_width = hw->seq_info2 & 0xff;
+	unsigned decode_mb_count;
+	if (!mb_width && mb_total) /*for 4k2k*/
+		mb_width = 256;
+	decode_mb_count = ((mby_mbx & 0xff) * mb_width +
+		(((mby_mbx >> 8) & 0xff) + 1));
+	if ((mby_mbx == 0) && (p_H264_Dpb->dec_dpb_status != H264_SLICE_HEAD_DONE)) {
+		dpb_print(DECODE_ID(hw), 0,
+			"mby_mbx is zero\n");
+		return;
+	}
+	if (get_cur_slice_picture_struct(p_H264_Dpb) != FRAME)
+		mb_total /= 2;
+
+	if ((error_proc_policy & 0x200) &&
+		READ_VREG(ERROR_STATUS_REG) != 0) {
+		p->data_flag |= ERROR_FLAG;
+	}
+
+	if (error_proc_policy & 0x100 && !(p->data_flag & ERROR_FLAG)) {
+		if (decode_mb_count < mb_total) {
+			p->data_flag |= ERROR_FLAG;
+			if (((error_proc_policy & 0x20000) &&
+				decode_mb_count >= mb_total * (100 - mb_count_threshold) / 100)) {
+				p->data_flag &= ~ERROR_FLAG;
+			}
+		}
+	}
+
+	if ((error_proc_policy & 0x100000) &&
+			hw->last_dec_picture &&
+				(hw->last_dec_picture->slice_type == I_SLICE) &&
+				(hw->dpb.mSlice.slice_type == P_SLICE)) {
+		if ((p->data_flag & ERROR_FLAG) &&
+				(decode_mb_count >= mb_total)) {
+				hw->ip_field_error_count++;
+				if (hw->ip_field_error_count == 4) {
+					unsigned int i;
+					struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+					for (i = 0; i < p_Dpb->ref_frames_in_buffer; i++) {
+						if (p_Dpb->fs_ref[i]->top_field)
+							p_Dpb->fs_ref[i]->top_field->data_flag &= ~ERROR_FLAG;
+						if (p_Dpb->fs_ref[i]->bottom_field)
+							p_Dpb->fs_ref[i]->bottom_field->data_flag &= ~ERROR_FLAG;
+						if (p_Dpb->fs_ref[i]->frame)
+							p_Dpb->fs_ref[i]->frame->data_flag &= ~ERROR_FLAG;
+					}
+					hw->ip_field_error_count = 0;
+					p->data_flag &= ~ERROR_FLAG;
+					hw->data_flag &= ~ERROR_FLAG;
+					dpb_print(DECODE_ID(hw), 0,
+						"clear all ref frame error flag\n");
+				}
+		} else {
+			if (hw->ip_field_error_count > 0)
+				dpb_print(DECODE_ID(hw), 0,
+					"clear error count %d\n", hw->ip_field_error_count);
+			hw->ip_field_error_count = 0;
+		}
+	}
+
+	if (p->data_flag & ERROR_FLAG) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_ERRORFLAG_DBG,
+			"%s: decode error, seq_info2 0x%x, mby_mbx 0x%x, mb_total %d decoded mb_count %d ERROR_STATUS_REG 0x%x\n",
+			__func__,
+			hw->seq_info2,
+			mby_mbx,
+			mb_total,
+			decode_mb_count,
+			READ_VREG(ERROR_STATUS_REG)
+			);
+
+	}
+}
+
+static int vh264_pic_done_proc(struct vdec_s *vdec)
+{
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)(vdec->private);
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	int ret;
+	int i;
+	struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+
+	if (vdec->mvfrm)
+		vdec->mvfrm->hw_decode_time =
+		local_clock() - vdec->mvfrm->hw_decode_start;
+
+	if (input_frame_based(vdec) &&
+			(!(hw->i_only & 0x2)) &&
+			frmbase_cont_bitlevel != 0 &&
+			READ_VREG(VIFF_BIT_CNT) >
+			frmbase_cont_bitlevel) {
+			/*handle the case: multi pictures in one packet*/
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+			"%s H264_PIC_DATA_DONE decode slice count %d, continue (bitcnt 0x%x)\n",
+			__func__,
+			hw->decode_pic_count,
+			READ_VREG(VIFF_BIT_CNT));
+			hw->frmbase_cont_flag = 1;
+		} else
+			hw->frmbase_cont_flag = 0;
+
+		if (p_H264_Dpb->mVideo.dec_picture) {
+			get_picture_qos_info(p_H264_Dpb->mVideo.dec_picture);
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+			DEL_EXIST(hw,
+				p_H264_Dpb->mVideo.dec_picture) = 0;
+			if (vdec->master) {
+				struct vdec_h264_hw_s *hw_ba =
+				(struct vdec_h264_hw_s *)
+					vdec->master->private;
+				if (hw_ba->last_dec_picture)
+					DEL_EXIST(hw_ba,
+						hw_ba->last_dec_picture)
+						= 1;
+			}
+#endif
+			mutex_lock(&hw->chunks_mutex);
+			if (hw->chunk) {
+				p_H264_Dpb->mVideo.dec_picture->pts =
+					hw->chunk->pts;
+				p_H264_Dpb->mVideo.dec_picture->pts64 =
+					hw->chunk->pts64;
+				p_H264_Dpb->mVideo.dec_picture->timestamp =
+					hw->chunk->timestamp;
+#ifdef MH264_USERDATA_ENABLE
+				vmh264_udc_fill_vpts(hw,
+					p_H264_Dpb->mSlice.slice_type,
+					hw->chunk->pts, 1);
+#endif
+
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+			} else if (vdec->master) {
+				/*dv enhance layer,
+				do not checkout pts*/
+				struct StorablePicture *pic =
+					p_H264_Dpb->mVideo.dec_picture;
+				pic->pts = 0;
+				pic->pts64 = 0;
+#endif
+		} else {
+				struct StorablePicture *pic =
+					p_H264_Dpb->mVideo.dec_picture;
+				u32 offset = pic->offset_delimiter;
+				pic->pic_size = (hw->start_bit_cnt - READ_VREG(VIFF_BIT_CNT)) >> 3;
+				if (pts_pickout_offset_us64(PTS_TYPE_VIDEO,
+					offset, &pic->pts, 0, &pic->pts64)) {
+					pic->pts = 0;
+					pic->pts64 = 0;
+#ifdef MH264_USERDATA_ENABLE
+					vmh264_udc_fill_vpts(hw,
+						p_H264_Dpb->mSlice.slice_type,
+						pic->pts, 0);
+#endif
+				} else {
+#ifdef MH264_USERDATA_ENABLE
+					vmh264_udc_fill_vpts(hw,
+						p_H264_Dpb->mSlice.slice_type,
+						pic->pts, 1);
+#endif
+				}
+
+	}
+			mutex_unlock(&hw->chunks_mutex);
+
+			check_decoded_pic_error(hw);
+#ifdef ERROR_HANDLE_TEST
+			if ((hw->data_flag & ERROR_FLAG)
+				&& (error_proc_policy & 0x80)) {
+				release_cur_decoding_buf(hw);
+				h264_clear_dpb(hw);
+				hw->dec_flag = 0;
+				hw->data_flag = 0;
+				hw->skip_frame_count = 0;
+				hw->has_i_frame = 0;
+				hw->no_error_count = 0xfff;
+				hw->no_error_i_count = 0xf;
+			} else
+#endif
+			if (error_proc_policy & 0x200000) {
+				if (!hw->loop_flag) {
+					for (i = 0; i < p_Dpb->used_size; i++) {
+						if ((p_H264_Dpb->mVideo.dec_picture->poc + loop_playback_poc_threshold < p_Dpb->fs[i]->poc) &&
+								!p_Dpb->fs[i]->is_output &&
+								!p_Dpb->fs[i]->pre_output) {
+							hw->loop_flag = 1;
+							hw->loop_last_poc = p_H264_Dpb->mVideo.dec_picture->poc;
+							break;
+						}
+					}
+				} else {
+					if ((p_H264_Dpb->mVideo.dec_picture->poc >= hw->loop_last_poc - poc_threshold) &&
+						(p_H264_Dpb->mVideo.dec_picture->poc <= hw->loop_last_poc + poc_threshold)) {
+						if (hw->loop_flag >= 5) {
+							for (i = 0; i < p_Dpb->used_size; i++) {
+								if ((hw->loop_last_poc + loop_playback_poc_threshold < p_Dpb->fs[i]->poc) &&
+										!p_Dpb->fs[i]->is_output &&
+										!p_Dpb->fs[i]->pre_output) {
+									p_Dpb->fs[i]->is_output = 1;
+								}
+							}
+							hw->loop_flag = 0;
+						} else
+							hw->loop_flag++;
+					} else
+						hw->loop_flag = 0;
+				}
+			}
+				ret = store_picture_in_dpb(p_H264_Dpb,
+					p_H264_Dpb->mVideo.dec_picture,
+					hw->data_flag | hw->dec_flag |
+				p_H264_Dpb->mVideo.dec_picture->data_flag);
+
+
+
+			if (ret == -1) {
+				release_cur_decoding_buf(hw);
+				bufmgr_force_recover(p_H264_Dpb);
+			} else if (ret == -2) {
+				release_cur_decoding_buf(hw);
+			} else {
+			if (hw->data_flag & ERROR_FLAG) {
+				hw->no_error_count = 0;
+				hw->no_error_i_count = 0;
+			} else {
+				hw->no_error_count++;
+				if (hw->data_flag & I_FLAG)
+					hw->no_error_i_count++;
+			}
+			if (hw->mmu_enable)
+				hevc_set_unused_4k_buff_idx(hw,
+					p_H264_Dpb->mVideo.
+						dec_picture->buf_spec_num);
+			bufmgr_post(p_H264_Dpb);
+				hw->last_dec_picture =
+					p_H264_Dpb->mVideo.dec_picture;
+			p_H264_Dpb->mVideo.dec_picture = NULL;
+			/* dump_dpb(&p_H264_Dpb->mDPB); */
+			hw->has_i_frame = 1;
+			if (hw->mmu_enable)
+				hevc_set_frame_done(hw);
+			hw->decode_pic_count++;
+			p_H264_Dpb->decode_pic_count = hw->decode_pic_count;
+			if (hw->skip_frame_count > 0) {
+				/*skip n frame after first I */
+				hw->skip_frame_count--;
+				if (hw->skip_frame_count == 0)
+					hw->dec_flag &= (~NODISP_FLAG);
+			} else if (hw->skip_frame_count < -1) {
+				/*skip n frame after first I until second I */
+				hw->skip_frame_count++;
+				if (hw->skip_frame_count == -1)
+					hw->dec_flag &= (~NODISP_FLAG);
+				}
+			}
+		}
+		return 0;
+}
+
+static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
+{
+	int i;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)(vdec->private);
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	unsigned int dec_dpb_status = p_H264_Dpb->dec_dpb_status;
+	u32 debug_tag;
+
+	if (dec_dpb_status == H264_SLICE_HEAD_DONE ||
+		p_H264_Dpb->dec_dpb_status == H264_CONFIG_REQUEST) {
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_START);
+	}
+	else if (dec_dpb_status == H264_PIC_DATA_DONE) {
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_PIC_DONE_START);
+	}
+	else if (dec_dpb_status == H264_SEI_DATA_READY)
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_SEI_START);
+	else if (dec_dpb_status == H264_AUX_DATA_READY)
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_AUX_START);
+
+	if (dec_dpb_status == H264_CONFIG_REQUEST) {
+#if 1
+		unsigned short *p = (unsigned short *)hw->lmem_addr;
+		for (i = 0; i < (RPM_END-RPM_BEGIN); i += 4) {
+			int ii;
+			for (ii = 0; ii < 4; ii++) {
+				p_H264_Dpb->dpb_param.l.data[i+ii] =
+					p[i+3-ii];
+				if (dpb_is_debug(DECODE_ID(hw),
+					RRINT_FLAG_RPM)) {
+					if (((i + ii) & 0xf) == 0)
+						dpb_print(DECODE_ID(hw),
+							0, "%04x:",
+							i);
+					dpb_print_cont(DECODE_ID(hw),
+						0, "%04x ",
+						p[i+3-ii]);
+					if (((i + ii + 1) & 0xf) == 0)
+						dpb_print_cont(
+						DECODE_ID(hw),
+							0, "\r\n");
+				}
+			}
+		}
+		if (p_H264_Dpb->bitstream_restriction_flag !=
+			((p_H264_Dpb->dpb_param.l.data[SPS_FLAGS2] >> 3) & 0x1)) {
+			dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+				"p_H264_Dpb->bitstream_restriction_flag 0x%x, new 0x%x\n",
+				p_H264_Dpb->bitstream_restriction_flag, ((p_H264_Dpb->dpb_param.l.data[SPS_FLAGS2] >> 3) & 0x1));
+			hw->csd_change_flag = 1;
+		}
+		p_H264_Dpb->bitstream_restriction_flag =
+			(p_H264_Dpb->dpb_param.l.data[SPS_FLAGS2] >> 3) & 0x1;
+		p_H264_Dpb->num_reorder_frames =
+			p_H264_Dpb->dpb_param.l.data[NUM_REORDER_FRAMES];
+		p_H264_Dpb->max_dec_frame_buffering =
+			p_H264_Dpb->dpb_param.l.data[MAX_BUFFER_FRAME];
+
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL,
+			"H264_CONFIG_REQUEST: pdb %d, %d, %d\n",
+			p_H264_Dpb->bitstream_restriction_flag,
+			p_H264_Dpb->num_reorder_frames,
+			p_H264_Dpb->max_dec_frame_buffering);
+		hw->bitstream_restriction_flag =
+			p_H264_Dpb->bitstream_restriction_flag;
+		hw->num_reorder_frames =
+			p_H264_Dpb->num_reorder_frames;
+		hw->max_dec_frame_buffering =
+			p_H264_Dpb->max_dec_frame_buffering;
+
+		/*crop*/
+		p_H264_Dpb->chroma_format_idc = p_H264_Dpb->dpb_param.dpb.chroma_format_idc;
+		p_H264_Dpb->frame_crop_left_offset = p_H264_Dpb->dpb_param.dpb.frame_crop_left_offset;
+		p_H264_Dpb->frame_crop_right_offset = p_H264_Dpb->dpb_param.dpb.frame_crop_right_offset;
+		p_H264_Dpb->frame_crop_top_offset = p_H264_Dpb->dpb_param.dpb.frame_crop_top_offset;
+		p_H264_Dpb->frame_crop_bottom_offset = p_H264_Dpb->dpb_param.dpb.frame_crop_bottom_offset;
+
+		dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
+		"%s chroma_format_idc %d crop offset: left %d right %d top %d bottom %d\n",
+		__func__, p_H264_Dpb->chroma_format_idc,
+		p_H264_Dpb->frame_crop_left_offset,
+		p_H264_Dpb->frame_crop_right_offset,
+		p_H264_Dpb->frame_crop_top_offset,
+		p_H264_Dpb->frame_crop_bottom_offset);
+#endif
+
+		WRITE_VREG(DPB_STATUS_REG, H264_ACTION_CONFIG_DONE);
+		reset_process_time(hw);
+		hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL);
+		hw->reg_iqidct_control_init_flag = 1;
+		hw->dec_result = DEC_RESULT_CONFIG_PARAM;
+#ifdef DETECT_WRONG_MULTI_SLICE
+		/*restart check count and set 'unknown'*/
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_UCODE_EVT,
+		"%s MULTI_SLICE_DETECT (check_count %d slice_count %d cur_slice_count %d flag %d), H264_CONFIG_REQUEST => restart check\n",
+		__func__,
+		hw->multi_slice_pic_check_count,
+		hw->picture_slice_count,
+		hw->cur_picture_slice_count,
+		hw->multi_slice_pic_flag);
+
+		hw->multi_slice_pic_check_count = 0;
+		hw->multi_slice_pic_flag = 0;
+		hw->picture_slice_count = 0;
+#endif
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_END);
+		vdec_schedule_work(&hw->work);
+	} else if (dec_dpb_status == H264_SLICE_HEAD_DONE) {
+		u16 data_hight;
+		u16 data_low;
+		u32 video_signal;
+
+		int slice_header_process_status = 0;
+		int I_flag;
+		int frame_num_gap = 0;
+		union param dpb_param_bak;
+		/*unsigned char is_idr;*/
+		unsigned short *p = (unsigned short *)hw->lmem_addr;
+		unsigned mb_width = hw->seq_info2 & 0xff;
+		unsigned short first_mb_in_slice;
+		unsigned int decode_mb_count, mby_mbx;
+		struct StorablePicture *pic = p_H264_Dpb->mVideo.dec_picture;
+		reset_process_time(hw);
+		hw->frmbase_cont_flag = 0;
+
+		if ((pic != NULL) && (pic->mb_aff_frame_flag == 1))
+			first_mb_in_slice = p[FIRST_MB_IN_SLICE + 3] * 2;
+		else
+			first_mb_in_slice = p[FIRST_MB_IN_SLICE + 3];
+
+#ifdef DETECT_WRONG_MULTI_SLICE
+		hw->cur_picture_slice_count++;
+
+		if ((error_proc_policy & 0x10000) &&
+			(hw->cur_picture_slice_count > 1) &&
+			(first_mb_in_slice == 0) &&
+			(hw->multi_slice_pic_flag == 0))
+				hw->multi_slice_pic_check_count = 0;
+
+		if ((error_proc_policy & 0x10000) &&
+			(hw->cur_picture_slice_count > 1) &&
+			(hw->multi_slice_pic_flag == 1)) {
+			dpb_print(DECODE_ID(hw), 0,
+			"%s MULTI_SLICE_DETECT (check_count %d slice_count %d cur_slice_count %d flag %d), WRONG_MULTI_SLICE detected, insert picture\n",
+			__func__,
+			hw->multi_slice_pic_check_count,
+			hw->picture_slice_count,
+			hw->cur_picture_slice_count,
+			hw->multi_slice_pic_flag);
+
+			mby_mbx = READ_VREG(MBY_MBX);
+			decode_mb_count = ((mby_mbx & 0xff) * mb_width +
+					(((mby_mbx >> 8) & 0xff) + 1));
+
+			if (first_mb_in_slice == decode_mb_count &&
+				first_mb_in_slice != 0) {
+				dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+				"%s first_mb_in_slice = %d \n",
+				__func__, first_mb_in_slice);
+
+				hw->multi_slice_pic_flag = 0;
+				hw->multi_slice_pic_check_count = 0;
+			} else if (hw->cur_picture_slice_count > hw->last_picture_slice_count) {
+				vh264_pic_done_proc(vdec);
+				//if (p_H264_Dpb->mDPB.used_size == p_H264_Dpb->mDPB.size) {
+				if (!have_free_buf_spec(vdec)) {
+					dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS, "dpb full, wait buffer\n");
+					p_H264_Dpb->mVideo.pre_frame_num = hw->first_pre_frame_num;
+					hw->last_picture_slice_count = hw->cur_picture_slice_count;
+					hw->no_decoder_buffer_flag = 1;
+					hw->dec_result = DEC_RESULT_AGAIN;
+					vdec_schedule_work(&hw->work);
+					return IRQ_HANDLED;
+				}
+			}
+			else {
+				if (p_H264_Dpb->mVideo.dec_picture) {
+					if (p_H264_Dpb->mVideo.dec_picture->colocated_buf_index >= 0) {
+						release_colocate_buf(p_H264_Dpb,
+						p_H264_Dpb->mVideo.dec_picture->colocated_buf_index);
+						p_H264_Dpb->mVideo.dec_picture->colocated_buf_index = -1;
+					}
+				}
+				release_cur_decoding_buf(hw);
+			}
+		}
+#endif
+
+		hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL);
+		hw->reg_iqidct_control_init_flag = 1;
+		hw->reg_vcop_ctrl_reg = READ_VREG(VCOP_CTRL_REG);
+		hw->reg_rv_ai_mb_count = READ_VREG(RV_AI_MB_COUNT);
+		hw->vld_dec_control = READ_VREG(VLD_DECODE_CONTROL);
+		if (input_frame_based(vdec) &&
+			frmbase_cont_bitlevel2 != 0 &&
+			READ_VREG(VIFF_BIT_CNT) <
+			frmbase_cont_bitlevel2 &&
+			hw->get_data_count >= 0x70000000) {
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+			"%s H264_SLICE_HEAD_DONE with small bitcnt %d, goto empty_proc\n",
+			__func__,
+			READ_VREG(VIFF_BIT_CNT));
+
+			goto empty_proc;
+		}
+
+#if 0
+		if (p_H264_Dpb->mVideo.dec_picture == NULL) {
+			if (!is_buffer_available(vdec)) {
+				hw->buffer_empty_flag = 1;
+				dpb_print(DECODE_ID(hw),
+				PRINT_FLAG_UCODE_EVT,
+				"%s, buffer_empty, newframe_q(%d), have_free_buf_spec(%d), init_done(%d), used_size(%d/%d), is_there_unused_frame_from_dpb(%d)\n",
+					__func__,
+					kfifo_len(&hw->newframe_q),
+					have_free_buf_spec(vdec),
+					p_H264_Dpb->mDPB.init_done,
+					p_H264_Dpb->mDPB.used_size,
+					p_H264_Dpb->mDPB.size,
+					is_there_unused_frame_from_dpb(
+						&p_H264_Dpb->mDPB));
+				return IRQ_HANDLED;
+			}
+		}
+
+		hw->buffer_empty_flag = 0;
+#endif
+#ifdef SEND_PARAM_WITH_REG
+		for (i = 0; i < (RPM_END-RPM_BEGIN); i++) {
+			unsigned int data32;
+
+			do {
+				data32 = READ_VREG(RPM_CMD_REG);
+				/* printk("%x\n", data32); */
+			} while ((data32&0x10000) == 0);
+			p_H264_Dpb->dpb_param.l.data[i] = data32 & 0xffff;
+			WRITE_VREG(RPM_CMD_REG, 0);
+			/* printk("%x:%x\n", i,data32); */
+		}
+#else
+		dpb_param_bak = p_H264_Dpb->dpb_param;
+
+		ATRACE_COUNTER(hw->trace.decode_header_time_name, TRACE_HEADER_RPM_START);
+
+		for (i = 0; i < (RPM_END-RPM_BEGIN); i += 4) {
+			int ii;
+
+			for (ii = 0; ii < 4; ii++) {
+				p_H264_Dpb->dpb_param.l.data[i+ii] =
+					p[i+3-ii];
+				if (dpb_is_debug(DECODE_ID(hw),
+					RRINT_FLAG_RPM)) {
+					if (((i + ii) & 0xf) == 0)
+						dpb_print(DECODE_ID(hw),
+							0, "%04x:",
+							i);
+					dpb_print_cont(DECODE_ID(hw),
+						0, "%04x ",
+						p[i+3-ii]);
+					if (((i + ii + 1) & 0xf) == 0)
+						dpb_print_cont(
+						DECODE_ID(hw),
+							0, "\r\n");
+				}
+			}
+		}
+		ATRACE_COUNTER(hw->trace.decode_header_time_name, TRACE_HEADER_RPM_END);
+#endif
+#ifdef DETECT_WRONG_MULTI_SLICE
+
+		if (p_H264_Dpb->mVideo.dec_picture &&
+				hw->multi_slice_pic_flag == 2 &&
+				(p_H264_Dpb->dpb_param.l.data[SLICE_TYPE] != dpb_param_bak.l.data[SLICE_TYPE] ||
+				dpb_param_bak.l.data[FIRST_MB_IN_SLICE] > p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE])) {
+			dpb_print(DECODE_ID(hw), 0,
+				"decode next pic, save before, SLICE_TYPE BAK %d, SLICE_TYPE %d, FIRST_MB_IN_SLICE BAK %d, FIRST_MB_IN_SLICE %d\n",
+					dpb_param_bak.l.data[SLICE_TYPE], p_H264_Dpb->dpb_param.l.data[SLICE_TYPE],
+					dpb_param_bak.l.data[FIRST_MB_IN_SLICE], p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE]);
+			vh264_pic_done_proc(vdec);
+		}
+#endif
+		data_low = p_H264_Dpb->dpb_param.l.data[VIDEO_SIGNAL_LOW];
+		data_hight = p_H264_Dpb->dpb_param.l.data[VIDEO_SIGNAL_HIGHT];
+
+		video_signal = (data_hight << 16) | data_low;
+		hw->video_signal_from_vui =
+					((video_signal & 0xffff) << 8) |
+					((video_signal & 0xff0000) >> 16) |
+					((video_signal & 0x3f000000));
+
+
+		/*dpb_print(DECODE_ID(hw),
+				0,
+				"video_signal_from_vui:0x%x, "
+				"data_low:0x%x, data_hight:0x%x\n",
+				hw->video_signal_from_vui,
+				data_low,
+				data_hight);*/
+
+		parse_sei_data(hw, hw->sei_data_buf, hw->sei_data_len);
+
+		if (hw->config_bufmgr_done == 0) {
+			hw->dec_result = DEC_RESULT_DONE;
+			vdec_schedule_work(&hw->work);
+			dpb_print(DECODE_ID(hw),
+				PRINT_FLAG_UCODE_EVT,
+				"config_bufmgr not done, discard frame\n");
+			return IRQ_HANDLED;
+		} else if ((hw->first_i_policy & 0x3) != 0) {
+			unsigned char is_i_slice =
+				(p_H264_Dpb->dpb_param.l.data[SLICE_TYPE]
+					== I_Slice)
+				? 1 : 0;
+			unsigned char is_idr =
+			((p_H264_Dpb->dpb_param.dpb.NAL_info_mmco & 0x1f)
+				== 5);
+			if ((hw->first_i_policy & 0x3) == 0x3)
+				is_i_slice = is_idr;
+			if (!is_i_slice) {
+				if (hw->has_i_frame == 0) {
+					amvdec_stop();
+					vdec->mc_loaded = 0;
+					hw->dec_result = DEC_RESULT_DONE;
+					vdec_schedule_work(&hw->work);
+					dpb_print(DECODE_ID(hw),
+						PRINT_FLAG_UCODE_EVT,
+						"has_i_frame is 0, discard none I(DR) frame silce_type %d is_idr %d\n", p_H264_Dpb->dpb_param.l.data[SLICE_TYPE], is_idr);
+					return IRQ_HANDLED;
+				}
+			} else {
+				if (hw->skip_frame_count < 0 || is_idr) {
+					/* second I */
+					hw->dec_flag &= (~NODISP_FLAG);
+					hw->skip_frame_count = 0;
+				}
+				if (hw->has_i_frame == 0 &&
+					(!is_idr)) {
+					int skip_count =
+						(hw->first_i_policy >> 8) & 0xff;
+					/* first I (not IDR) */
+					if ((hw->first_i_policy & 0x3) == 2)
+						hw->skip_frame_count =
+							-1 - skip_count;
+					else
+						hw->skip_frame_count =
+							skip_count;
+					if (hw->skip_frame_count != 0)
+						hw->dec_flag |= NODISP_FLAG;
+				}
+			}
+		}
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_UCODE_EVT,
+			"current dpb index %d, poc %d, top/bot poc (%d,%d)\n",
+			p_H264_Dpb->dpb_param.dpb.current_dpb_index,
+			val(p_H264_Dpb->dpb_param.dpb.frame_pic_order_cnt),
+			val(p_H264_Dpb->dpb_param.dpb.top_field_pic_order_cnt),
+			val(p_H264_Dpb->dpb_param.dpb.top_field_pic_order_cnt));
+		I_flag = (p_H264_Dpb->dpb_param.l.data[SLICE_TYPE] == I_Slice)
+			? I_FLAG : 0;
+
+		if ((hw->i_only & 0x2) && (I_flag & I_FLAG))
+			flush_dpb(p_H264_Dpb);
+
+		if ((hw->i_only & 0x2) && (!(I_flag & I_FLAG)) &&
+			(p_H264_Dpb->mSlice.structure == FRAME)) {
+				hw->data_flag = NULL_FLAG;
+				goto pic_done_proc;
+		}
+
+		slice_header_process_status =
+			h264_slice_header_process(p_H264_Dpb, &frame_num_gap);
+		if (hw->mmu_enable)
+			hevc_sao_set_slice_type(hw,
+				slice_header_process_status,
+					hw->dpb.mSlice.idr_flag);
+		vui_config(hw);
+
+		if (p_H264_Dpb->mVideo.dec_picture) {
+			int cfg_ret = 0;
+			bool field_pic_flag = false;
+			unsigned mby_mbx = READ_VREG(MBY_MBX);
+			struct StorablePicture *p =
+				p_H264_Dpb->mVideo.dec_picture;
+
+			if (slice_header_process_status == 1) {
+				if (!p_H264_Dpb->mSPS.frame_mbs_only_flag) {
+					field_pic_flag =
+						(p_H264_Dpb->mSlice.structure == TOP_FIELD ||
+						p_H264_Dpb->mSlice.structure == BOTTOM_FIELD) ?
+						true : false;
+				}
+
+				vdec_set_profile_level(vdec, p_H264_Dpb->mSPS.profile_idc,
+					p_H264_Dpb->mSPS.level_idc);
+
+				if (!field_pic_flag && (((p_H264_Dpb->mSPS.profile_idc == BASELINE) &&
+					(p_H264_Dpb->dec_dpb_size < 2)) ||
+					(((unsigned long)(hw->vh264_amstream_dec_info
+						.param)) & 0x8) || hw->low_latency_mode & 0x8)) {
+					p_H264_Dpb->fast_output_enable =
+					H264_OUTPUT_MODE_FAST;
+				}
+				else
+					p_H264_Dpb->fast_output_enable
+							= fast_output_enable;
+				if (hw->enable_fence)
+					p_H264_Dpb->fast_output_enable = H264_OUTPUT_MODE_FAST;
+
+				hw->data_flag = I_flag;
+				if ((p_H264_Dpb->
+					dpb_param.dpb.NAL_info_mmco & 0x1f)
+					== 5)
+					hw->data_flag |= IDR_FLAG;
+				if ((p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE]) && !mby_mbx) {
+					p->data_flag |= ERROR_FLAG;
+					dpb_print(DECODE_ID(hw),
+						PRINT_FLAG_VDEC_STATUS,
+						"one slice error in muulti-slice  first_mb 0x%x mby_mbx 0x%x  slice_type %d\n",
+						p_H264_Dpb->dpb_param.l.
+						data[FIRST_MB_IN_SLICE],
+						READ_VREG(MBY_MBX),
+						 p->slice_type);
+				}
+				dpb_print(DECODE_ID(hw),
+				PRINT_FLAG_VDEC_STATUS,
+				"==================> frame count %d to skip %d\n",
+				hw->decode_pic_count+1,
+				hw->skip_frame_count);
+				} else if (error_proc_policy & 0x100){
+					unsigned decode_mb_count =
+						((mby_mbx & 0xff) * hw->mb_width +
+						(((mby_mbx >> 8) & 0xff) + 1));
+					if (decode_mb_count <
+						((p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE]) *
+						(1 + p->mb_aff_frame_flag)) && decode_mb_count) {
+						dpb_print(DECODE_ID(hw),
+						PRINT_FLAG_VDEC_STATUS,
+						"Error detect! first_mb 0x%x mby_mbx 0x%x decode_mb 0x%x\n",
+						p_H264_Dpb->dpb_param.l.
+						data[FIRST_MB_IN_SLICE],
+						READ_VREG(MBY_MBX),
+						decode_mb_count);
+						p->data_flag |= ERROR_FLAG;
+					}/* else if (!p_H264_Dpb->dpb_param.l.data[FIRST_MB_IN_SLICE] && decode_mb_count) {
+						p->data_flag |= ERROR_FLAG;
+						goto pic_done_proc;
+					}*/
+				}
+
+			if (!I_flag && frame_num_gap && !p_H264_Dpb->long_term_reference_flag) {
+				if (!(error_proc_policy & 0x800000)) {
+					hw->data_flag |= ERROR_FLAG;
+					p_H264_Dpb->mVideo.dec_picture->data_flag |= ERROR_FLAG;
+					dpb_print(DECODE_ID(hw), 0, "frame number gap error\n");
+				}
+			}
+
+			if ((error_proc_policy & 0x400) && !hw->enable_fence) {
+				int ret = dpb_check_ref_list_error(p_H264_Dpb);
+				if (ret != 0) {
+					hw->reflist_error_count ++;
+					dpb_print(DECODE_ID(hw), 0,
+						"reference list error %d frame count %d to skip %d reflist_error_count %d\n",
+						ret,
+						hw->decode_pic_count+1,
+						hw->skip_frame_count,
+						hw->reflist_error_count);
+
+					p_H264_Dpb->mVideo.dec_picture->data_flag = NODISP_FLAG;
+					if (((error_proc_policy & 0x80)
+						&& ((hw->dec_flag &
+							NODISP_FLAG) == 0)) ||(hw->reflist_error_count > 50)) {
+						hw->reset_bufmgr_flag = 1;
+						hw->reflist_error_count =0;
+						amvdec_stop();
+						vdec->mc_loaded = 0;
+						hw->dec_result = DEC_RESULT_DONE;
+						vdec_schedule_work(&hw->work);
+						return IRQ_HANDLED;
+					}
+				} else
+					hw->reflist_error_count = 0;
+			}
+			if ((error_proc_policy & 0x800) && (!(hw->i_only & 0x2))
+				&& p_H264_Dpb->dpb_error_flag != 0) {
+				dpb_print(DECODE_ID(hw), 0,
+					"dpb error %d\n",
+					p_H264_Dpb->dpb_error_flag);
+				hw->data_flag |= ERROR_FLAG;
+				p_H264_Dpb->mVideo.dec_picture->data_flag |= ERROR_FLAG;
+				if ((error_proc_policy & 0x80) &&
+					((hw->dec_flag & NODISP_FLAG) == 0)) {
+					hw->reset_bufmgr_flag = 1;
+					amvdec_stop();
+					vdec->mc_loaded = 0;
+					hw->dec_result = DEC_RESULT_DONE;
+					vdec_schedule_work(&hw->work);
+					return IRQ_HANDLED;
+				}
+			}
+			ATRACE_COUNTER(hw->trace.decode_header_time_name, TRACE_HEADER_REGISTER_START);
+			cfg_ret = config_decode_buf(hw,
+				p_H264_Dpb->mVideo.dec_picture);
+			ATRACE_COUNTER(hw->trace.decode_header_time_name, TRACE_HEADER_REGISTER_END);
+			if (cfg_ret < 0) {
+				dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
+					"config_decode_buf fail (%d)\n",
+					cfg_ret);
+				if (error_proc_policy & 0x2) {
+					release_cur_decoding_buf(hw);
+					/*hw->data_flag |= ERROR_FLAG;*/
+					hw->reset_bufmgr_flag = 1;
+					hw->dec_result = DEC_RESULT_DONE;
+					vdec_schedule_work(&hw->work);
+					return IRQ_HANDLED;
+				} else
+					hw->data_flag |= ERROR_FLAG;
+				p_H264_Dpb->mVideo.dec_picture->data_flag |= ERROR_FLAG;
+			}
+		}
+
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_END);
+
+		if (slice_header_process_status == 1)
+			WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_NEWPIC);
+		else
+			WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_SLICE);
+		hw->last_mby_mbx = 0;
+		hw->last_vld_level = 0;
+		start_process_time(hw);
+	} else if (dec_dpb_status == H264_PIC_DATA_DONE
+		||((dec_dpb_status == H264_DATA_REQUEST) && input_frame_based(vdec))) {
+#ifdef DETECT_WRONG_MULTI_SLICE
+				dpb_print(DECODE_ID(hw), PRINT_FLAG_UCODE_EVT,
+				"%s MULTI_SLICE_DETECT (check_count %d slice_count %d cur_slice_count %d flag %d), H264_PIC_DATA_DONE\n",
+				__func__,
+				hw->multi_slice_pic_check_count,
+				hw->picture_slice_count,
+				hw->cur_picture_slice_count,
+				hw->multi_slice_pic_flag);
+
+				if (hw->multi_slice_pic_check_count < check_slice_num) {
+					hw->multi_slice_pic_check_count++;
+					if (hw->cur_picture_slice_count !=
+						hw->picture_slice_count) {
+						/*restart check count and set 'unknown'*/
+						hw->multi_slice_pic_check_count = 0;
+						hw->multi_slice_pic_flag = 0;
+					}
+					hw->picture_slice_count =
+						hw->cur_picture_slice_count;
+				} else if (hw->multi_slice_pic_check_count >= check_slice_num) {
+					if (hw->picture_slice_count > 1)
+						hw->multi_slice_pic_flag = 2;
+					else
+						hw->multi_slice_pic_flag = 1;
+				}
+#endif
+
+pic_done_proc:
+		reset_process_time(hw);
+		if ((dec_dpb_status == H264_SEARCH_BUFEMPTY) ||
+			(dec_dpb_status == H264_DECODE_BUFEMPTY) ||
+			(dec_dpb_status == H264_DECODE_TIMEOUT) ||
+			((dec_dpb_status == H264_DATA_REQUEST) && input_frame_based(vdec))) {
+			hw->data_flag |= ERROR_FLAG;
+			if (hw->dpb.mVideo.dec_picture)
+				hw->dpb.mVideo.dec_picture->data_flag |= ERROR_FLAG;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL,
+				"%s, mark err_frame\n", __func__);
+		}
+		vh264_pic_done_proc(vdec);
+
+		if (hw->frmbase_cont_flag) {
+			/*do not DEC_RESULT_GET_DATA*/
+			hw->get_data_count = 0x7fffffff;
+			WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD);
+			decode_frame_count[DECODE_ID(hw)]++;
+			if (p_H264_Dpb->mSlice.slice_type == I_SLICE) {
+				hw->gvs.i_decoded_frames++;
+			} else if (p_H264_Dpb->mSlice.slice_type == P_SLICE) {
+				hw->gvs.p_decoded_frames++;
+			} else if (p_H264_Dpb->mSlice.slice_type == B_SLICE) {
+				hw->gvs.b_decoded_frames++;
+			}
+			start_process_time(hw);
+			return IRQ_HANDLED;
+		}
+		amvdec_stop();
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+			"%s %s decode slice count %d\n",
+			__func__,
+			(dec_dpb_status == H264_PIC_DATA_DONE) ?
+			"H264_PIC_DATA_DONE" :
+			(dec_dpb_status == H264_FIND_NEXT_PIC_NAL) ?
+			"H264_FIND_NEXT_PIC_NAL" : "H264_FIND_NEXT_DVEL_NAL",
+			hw->decode_pic_count);
+		if (hw->kpi_first_i_decoded == 0) {
+			hw->kpi_first_i_decoded = 1;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL,
+				"[vdec_kpi][%s] First I frame decoded.\n", __func__);
+		}
+		/* WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD); */
+		hw->dec_result = DEC_RESULT_DONE;
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+		if (vdec->slave &&
+			dec_dpb_status == H264_FIND_NEXT_DVEL_NAL) {
+			struct vdec_h264_hw_s *hw_el =
+			 (struct vdec_h264_hw_s *)(vdec->slave->private);
+			hw_el->got_valid_nal = 0;
+			hw->switch_dvlayer_flag = 1;
+		} else if (vdec->master &&
+			dec_dpb_status == H264_FIND_NEXT_PIC_NAL) {
+			struct vdec_h264_hw_s *hw_bl =
+			 (struct vdec_h264_hw_s *)(vdec->master->private);
+			hw_bl->got_valid_nal = 0;
+			hw->switch_dvlayer_flag = 1;
+		} else {
+			hw->switch_dvlayer_flag = 0;
+			hw->got_valid_nal = 1;
+		}
+#endif
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_EDN);
+
+		hw->dec_result = DEC_RESULT_DONE;
+		vdec_schedule_work(&hw->work);
+
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	} else if (
+			(dec_dpb_status == H264_FIND_NEXT_PIC_NAL) ||
+			(dec_dpb_status == H264_FIND_NEXT_DVEL_NAL)) {
+		goto pic_done_proc;
+#endif
+	} else if (dec_dpb_status == H264_AUX_DATA_READY) {
+		reset_process_time(hw);
+		if (READ_VREG(H264_AUX_DATA_SIZE) != 0) {
+			if (dpb_is_debug(DECODE_ID(hw),
+				PRINT_FLAG_SEI_DETAIL))
+				dump_aux_buf(hw);
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+			if (vdec_frame_based(vdec)) {
+				if (hw->last_dec_picture)
+					set_aux_data(hw,
+						hw->last_dec_picture, 0, 0, NULL);
+			} else if (vdec->dolby_meta_with_el || vdec->slave) {
+				if (hw->last_dec_picture)
+					set_aux_data(hw, hw->last_dec_picture,
+						0, 0, NULL);
+			} else {
+				if (vdec->master) {
+						struct vdec_h264_hw_s *hw_bl =
+						(struct vdec_h264_hw_s *)
+						(vdec->master->private);
+					if (hw_bl->last_dec_picture != NULL) {
+						set_aux_data(hw_bl,
+							hw_bl->last_dec_picture,
+							0, 1, hw);
+					}
+					set_aux_data(hw,
+						hw->last_dec_picture,
+						0, 2, NULL);
+				}
+			}
+#else
+			if (hw->last_dec_picture)
+				set_aux_data(hw,
+					hw->last_dec_picture, 0, 0, NULL);
+#endif
+		}
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+		hw->switch_dvlayer_flag = 0;
+		hw->got_valid_nal = 1;
+#endif
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+			"%s H264_AUX_DATA_READY\n", __func__);
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_EDN);
+		hw->dec_result = DEC_RESULT_DONE;
+		vdec_schedule_work(&hw->work);
+	} else if (/*(dec_dpb_status == H264_DATA_REQUEST) ||*/
+			(dec_dpb_status == H264_SEARCH_BUFEMPTY) ||
+			(dec_dpb_status == H264_DECODE_BUFEMPTY) ||
+			(dec_dpb_status == H264_DECODE_TIMEOUT)) {
+empty_proc:
+		reset_process_time(hw);
+		if ((error_proc_policy & 0x40000) &&
+			((dec_dpb_status == H264_DECODE_TIMEOUT) ||
+			(!hw->frmbase_cont_flag && (dec_dpb_status == H264_SEARCH_BUFEMPTY || dec_dpb_status == H264_DECODE_BUFEMPTY) && input_frame_based(vdec))))
+			goto pic_done_proc;
+		if (!hw->frmbase_cont_flag)
+			release_cur_decoding_buf(hw);
+
+		if (input_frame_based(vdec) ||
+			(READ_VREG(VLD_MEM_VIFIFO_LEVEL) > 0x200)) {
+			if (h264_debug_flag &
+				DISABLE_ERROR_HANDLE) {
+				dpb_print(DECODE_ID(hw),
+				PRINT_FLAG_ERROR,
+					"%s decoding error, level 0x%x\n",
+					__func__,
+					READ_VREG(VLD_MEM_VIFIFO_LEVEL));
+				goto send_again;
+			}
+			amvdec_stop();
+			vdec->mc_loaded = 0;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+				"%s %s\n", __func__,
+				(dec_dpb_status == H264_SEARCH_BUFEMPTY) ?
+				"H264_SEARCH_BUFEMPTY" :
+				(dec_dpb_status == H264_DECODE_BUFEMPTY) ?
+				"H264_DECODE_BUFEMPTY" :
+				(dec_dpb_status == H264_DECODE_TIMEOUT) ?
+				"H264_DECODE_TIMEOUT" :
+				"OTHER");
+			hw->dec_result = DEC_RESULT_DONE;
+
+			if (dec_dpb_status == H264_SEARCH_BUFEMPTY)
+				hw->search_dataempty_num++;
+			else if (dec_dpb_status == H264_DECODE_TIMEOUT) {
+				hw->decode_timeout_num++;
+				if (error_proc_policy & 0x4000) {
+					hw->data_flag |= ERROR_FLAG;
+					if ((p_H264_Dpb->last_dpb_status == H264_DECODE_TIMEOUT) ||
+						(p_H264_Dpb->last_dpb_status == H264_PIC_DATA_DONE) ||
+						((p_H264_Dpb->last_dpb_status == H264_SLICE_HEAD_DONE) &&
+						 (p_H264_Dpb->mSlice.slice_type != B_SLICE))) {
+						 dpb_print(DECODE_ID(hw),
+							PRINT_FLAG_ERROR, "%s last dpb status 0x%x need bugmgr reset \n",
+							p_H264_Dpb->last_dpb_status, __func__);
+							hw->reset_bufmgr_flag = 1;
+					}
+				}
+			} else if (dec_dpb_status == H264_DECODE_BUFEMPTY)
+				hw->decode_dataempty_num++;
+			if (!hw->frmbase_cont_flag)
+				hw->data_flag |= ERROR_FLAG;
+
+			vdec_schedule_work(&hw->work);
+		} else {
+			/* WRITE_VREG(DPB_STATUS_REG, H264_ACTION_INIT); */
+#ifdef DETECT_WRONG_MULTI_SLICE
+			if (error_proc_policy & 0x10000) {
+				p_H264_Dpb->mVideo.pre_frame_num = hw->first_pre_frame_num;
+			}
+			hw->last_picture_slice_count = hw->cur_picture_slice_count;
+#endif
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+				"%s DEC_RESULT_AGAIN\n", __func__);
+send_again:
+			hw->dec_result = DEC_RESULT_AGAIN;
+			vdec_schedule_work(&hw->work);
+		}
+	} else if (dec_dpb_status == H264_DATA_REQUEST) {
+		reset_process_time(hw);
+		if (input_frame_based(vdec)) {
+			dpb_print(DECODE_ID(hw),
+			PRINT_FLAG_VDEC_STATUS,
+			"%s H264_DATA_REQUEST (%d)\n",
+			__func__, hw->get_data_count);
+			hw->dec_result = DEC_RESULT_GET_DATA;
+			hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL);
+			hw->reg_iqidct_control_init_flag = 1;
+			hw->get_data_start_time = jiffies;
+			hw->get_data_count++;
+			if (hw->get_data_count >= frame_max_data_packet)
+				goto empty_proc;
+			vdec_schedule_work(&hw->work);
+		} else
+			goto empty_proc;
+	} else if (dec_dpb_status == H264_DECODE_OVER_SIZE) {
+		dpb_print(DECODE_ID(hw), 0,
+			"vmh264 decode oversize !!\n");
+		release_cur_decoding_buf(hw);
+		hw->data_flag |= ERROR_FLAG;
+		hw->stat |= DECODER_FATAL_ERROR_SIZE_OVERFLOW;
+		reset_process_time(hw);
+		hw->dec_result = DEC_RESULT_DONE;
+		vdec_schedule_work(&hw->work);
+		return IRQ_HANDLED;
+	} else if (dec_dpb_status == H264_SEI_DATA_READY) {
+		int aux_data_len;
+		aux_data_len =
+			(READ_VREG(H264_AUX_DATA_SIZE) >> 16) << 4;
+
+		if (aux_data_len > SEI_DATA_SIZE) {
+				dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
+					"sei data size more than 4K: %d, discarded it\n",
+					hw->sei_itu_data_len);
+				hw->sei_itu_data_len = 0;
+		}
+
+		if (aux_data_len != 0) {
+			u8 *trans_data_buf;
+			u8 *sei_data_buf;
+			u8 swap_byte;
+
+#if 0
+			dump_aux_buf(hw);
+#endif
+			trans_data_buf = (u8 *)hw->aux_addr;
+
+			if (trans_data_buf[7] == AUX_TAG_SEI) {
+				int left_len;
+
+				sei_data_buf = (u8 *)hw->sei_data_buf
+							+ hw->sei_data_len;
+				left_len = SEI_DATA_SIZE - hw->sei_data_len;
+				if (aux_data_len/2 <= left_len) {
+					for (i = 0; i < aux_data_len/2; i++)
+						sei_data_buf[i]
+							= trans_data_buf[i*2];
+
+					aux_data_len = aux_data_len / 2;
+					for (i = 0; i < aux_data_len; i = i+4) {
+						swap_byte = sei_data_buf[i];
+						sei_data_buf[i]
+							= sei_data_buf[i+3];
+						sei_data_buf[i+3] = swap_byte;
+
+						swap_byte = sei_data_buf[i+1];
+						sei_data_buf[i+1]
+							= sei_data_buf[i+2];
+						sei_data_buf[i+2] = swap_byte;
+					}
+
+					for (i = aux_data_len-1; i >= 0; i--)
+						if (sei_data_buf[i] != 0)
+							break;
+
+					hw->sei_data_len += i+1;
+				} else
+					dpb_print(DECODE_ID(hw),
+						PRINT_FLAG_ERROR,
+						"sei data size %d and more than left space: %d, discarded it\n",
+						hw->sei_itu_data_len,
+						left_len);
+			}
+		}
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_EDN);
+		WRITE_VREG(DPB_STATUS_REG, H264_SEI_DATA_DONE);
+
+		return IRQ_HANDLED;
+	}
+
+
+	/* ucode debug */
+	debug_tag = READ_VREG(DEBUG_REG1);
+	if (debug_tag & 0x10000) {
+		unsigned short *p = (unsigned short *)hw->lmem_addr;
+
+		dpb_print(DECODE_ID(hw), 0,
+			"LMEM<tag %x>:\n", debug_tag);
+		for (i = 0; i < 0x400; i += 4) {
+			int ii;
+			if ((i & 0xf) == 0)
+				dpb_print_cont(DECODE_ID(hw), 0,
+					"%03x: ", i);
+			for (ii = 0; ii < 4; ii++)
+				dpb_print_cont(DECODE_ID(hw), 0,
+					"%04x ", p[i+3-ii]);
+			if (((i+ii) & 0xf) == 0)
+				dpb_print_cont(DECODE_ID(hw), 0,
+					"\n");
+		}
+		if (((udebug_pause_pos & 0xffff)
+			== (debug_tag & 0xffff)) &&
+			(udebug_pause_decode_idx == 0 ||
+			udebug_pause_decode_idx ==
+			hw->decode_pic_count) &&
+			(udebug_pause_val == 0 ||
+			udebug_pause_val == READ_VREG(DEBUG_REG2))) {
+			udebug_pause_pos &= 0xffff;
+			hw->ucode_pause_pos = udebug_pause_pos;
+		}
+		else if (debug_tag & 0x20000)
+			hw->ucode_pause_pos = 0xffffffff;
+		if (hw->ucode_pause_pos)
+			reset_process_time(hw);
+		else
+			WRITE_VREG(DEBUG_REG1, 0);
+	} else if (debug_tag != 0) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_UCODE_EVT,
+			"dbg%x: %x\n", debug_tag,
+			READ_VREG(DEBUG_REG2));
+		if (((udebug_pause_pos & 0xffff)
+			== (debug_tag & 0xffff)) &&
+			(udebug_pause_decode_idx == 0 ||
+			udebug_pause_decode_idx ==
+			hw->decode_pic_count) &&
+			(udebug_pause_val == 0 ||
+			udebug_pause_val == READ_VREG(DEBUG_REG2))) {
+			udebug_pause_pos &= 0xffff;
+			hw->ucode_pause_pos = udebug_pause_pos;
+		}
+		if (hw->ucode_pause_pos)
+			reset_process_time(hw);
+		else
+			WRITE_VREG(DEBUG_REG1, 0);
+	}
+	/**/
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t vh264_isr(struct vdec_s *vdec, int irq)
+{
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)(vdec->private);
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+
+
+	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+	if (!hw)
+		return IRQ_HANDLED;
+
+	if (hw->eos)
+		return IRQ_HANDLED;
+
+	p_H264_Dpb->vdec = vdec;
+	p_H264_Dpb->dec_dpb_status = READ_VREG(DPB_STATUS_REG);
+	if (p_H264_Dpb->dec_dpb_status == H264_SLICE_HEAD_DONE ||
+		p_H264_Dpb->dec_dpb_status == H264_CONFIG_REQUEST) {
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_HEAD_DONE);
+	}
+	else if (p_H264_Dpb->dec_dpb_status == H264_PIC_DATA_DONE) {
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_PIC_DONE);
+	}
+	else if (p_H264_Dpb->dec_dpb_status == H264_SEI_DATA_READY)
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_SEI_DONE);
+	else if (p_H264_Dpb->dec_dpb_status == H264_AUX_DATA_READY)
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_AUX_DONE);
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_UCODE_EVT,
+			"%s DPB_STATUS_REG: 0x%x, run(%d) last_state (%x) ERROR_STATUS_REG 0x%x, sb (0x%x 0x%x 0x%x) bitcnt 0x%x mby_mbx 0x%x\n",
+			__func__,
+			p_H264_Dpb->dec_dpb_status,
+			run_count[DECODE_ID(hw)],
+			hw->dec_result,
+			READ_VREG(ERROR_STATUS_REG),
+			READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+			READ_VREG(VLD_MEM_VIFIFO_WP),
+			READ_VREG(VLD_MEM_VIFIFO_RP),
+			READ_VREG(VIFF_BIT_CNT),
+			READ_VREG(MBY_MBX));
+
+	if (p_H264_Dpb->dec_dpb_status == H264_WRRSP_REQUEST) {
+		if (hw->mmu_enable)
+			hevc_sao_wait_done(hw);
+		WRITE_VREG(DPB_STATUS_REG, H264_WRRSP_DONE);
+		return IRQ_HANDLED;
+	}
+	ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_END);
+	return IRQ_WAKE_THREAD;
+
+}
+
+static void timeout_process(struct vdec_h264_hw_s *hw)
+{
+	struct vdec_s *vdec = hw_to_vdec(hw);
+
+	/*
+	 * In this very timeout point,the vh264_work arrives,
+	 * or in some cases the system become slow,  then come
+	 * this second timeout. In both cases we return.
+	 */
+	if (work_pending(&hw->work) ||
+	    work_busy(&hw->work) ||
+	    work_busy(&hw->timeout_work) ||
+	    work_pending(&hw->timeout_work)) {
+		pr_err("%s h264[%d] work pending, do nothing.\n",__func__, vdec->id);
+		return;
+	}
+	hw->timeout_num++;
+	amvdec_stop();
+	vdec->mc_loaded = 0;
+	if (hw->mmu_enable) {
+		hevc_set_frame_done(hw);
+		hevc_sao_wait_done(hw);
+	}
+	dpb_print(DECODE_ID(hw),
+		PRINT_FLAG_ERROR, "%s decoder timeout, DPB_STATUS_REG 0x%x\n", __func__, READ_VREG(DPB_STATUS_REG));
+	release_cur_decoding_buf(hw);
+	hw->dec_result = DEC_RESULT_TIMEOUT;
+	hw->data_flag |= ERROR_FLAG;
+
+	if (work_pending(&hw->work))
+		return;
+	vdec_schedule_work(&hw->timeout_work);
+}
+
+static void dump_bufspec(struct vdec_h264_hw_s *hw,
+	const char *caller)
+{
+	int i;
+	dpb_print(DECODE_ID(hw), 0,
+		"%s in %s:\n", __func__, caller);
+	for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+		if (hw->buffer_spec[i].used == -1)
+			continue;
+		dpb_print(DECODE_ID(hw), 0,
+			"bufspec (%d): used %d adr 0x%x(%lx) canvas(%d) vf_ref(%d) ",
+			i, hw->buffer_spec[i].used,
+			hw->buffer_spec[i].buf_adr,
+			hw->buffer_spec[i].cma_alloc_addr,
+			hw->buffer_spec[i].canvas_pos,
+			hw->buffer_spec[i].vf_ref
+			);
+#ifdef CONFIG_AM_VDEC_DV
+		dpb_print_cont(DECODE_ID(hw), 0,
+			"dv_el_exist %d",
+			hw->buffer_spec[i].dv_enhance_exist
+		);
+#endif
+		dpb_print_cont(DECODE_ID(hw), 0, "\n");
+	}
+
+}
+
+static void vmh264_dump_state(struct vdec_s *vdec)
+{
+	struct vdec_h264_hw_s *hw =
+		(struct vdec_h264_hw_s *)(vdec->private);
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	dpb_print(DECODE_ID(hw), 0,
+		"====== %s\n", __func__);
+	dpb_print(DECODE_ID(hw), 0,
+		"width/height (%d/%d), num_reorder_frames %d dec_dpb_size %d dpb size(bufspec count) %d max_reference_size(collocate count) %d i_only %d video_signal_type 0x%x send_err %d \n",
+		hw->frame_width,
+		hw->frame_height,
+		hw->num_reorder_frames,
+		hw->dpb.dec_dpb_size,
+		hw->dpb.mDPB.size,
+		hw->max_reference_size,
+		hw->i_only,
+		hw->video_signal_type,
+		hw->send_error_frame_flag
+		);
+
+	dpb_print(DECODE_ID(hw), 0,
+		"is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d disp_frm %d run %d not_run_ready %d input_empty %d bufmgr_reset_cnt %d error_frame_count = %d, drop_frame_count = %d\n",
+		input_frame_based(vdec),
+		hw->eos,
+		hw->stat,
+		hw->dec_result,
+		decode_frame_count[DECODE_ID(hw)],
+		display_frame_count[DECODE_ID(hw)],
+		run_count[DECODE_ID(hw)],
+		not_run_ready[DECODE_ID(hw)],
+		input_empty[DECODE_ID(hw)],
+		hw->reset_bufmgr_count,
+		hw->gvs.error_frame_count,
+		hw->gvs.drop_frame_count
+		);
+
+#ifdef DETECT_WRONG_MULTI_SLICE
+		dpb_print(DECODE_ID(hw), 0,
+		"MULTI_SLICE_DETECT (check_count %d slice_count %d cur_slice_count %d flag %d)\n",
+		hw->multi_slice_pic_check_count,
+		hw->picture_slice_count,
+		hw->cur_picture_slice_count,
+		hw->multi_slice_pic_flag);
+#endif
+	if (!hw->is_used_v4l && vf_get_receiver(vdec->vf_provider_name)) {
+		enum receviver_start_e state =
+		vf_notify_receiver(vdec->vf_provider_name,
+			VFRAME_EVENT_PROVIDER_QUREY_STATE,
+			NULL);
+		dpb_print(DECODE_ID(hw), 0,
+			"\nreceiver(%s) state %d\n",
+			vdec->vf_provider_name,
+			state);
+	}
+
+	dpb_print(DECODE_ID(hw), 0,
+	"%s, newq(%d/%d), dispq(%d/%d) vf prepare/get/put (%d/%d/%d), free_spec(%d), initdon(%d), used_size(%d/%d), unused_fr_dpb(%d)  fast_output_enable %x \n",
+	__func__,
+	kfifo_len(&hw->newframe_q),
+	VF_POOL_SIZE,
+	kfifo_len(&hw->display_q),
+	VF_POOL_SIZE,
+	hw->vf_pre_count,
+	hw->vf_get_count,
+	hw->vf_put_count,
+	have_free_buf_spec(vdec),
+	p_H264_Dpb->mDPB.init_done,
+	p_H264_Dpb->mDPB.used_size, p_H264_Dpb->mDPB.size,
+	is_there_unused_frame_from_dpb(&p_H264_Dpb->mDPB),
+	p_H264_Dpb->fast_output_enable
+	);
+
+	dump_dpb(&p_H264_Dpb->mDPB, 1);
+	dump_pic(p_H264_Dpb);
+	dump_bufspec(hw, __func__);
+
+	dpb_print(DECODE_ID(hw), 0,
+		"DPB_STATUS_REG=0x%x\n",
+		READ_VREG(DPB_STATUS_REG));
+	dpb_print(DECODE_ID(hw), 0,
+		"MPC_E=0x%x\n",
+		READ_VREG(MPC_E));
+	dpb_print(DECODE_ID(hw), 0,
+		"H264_DECODE_MODE=0x%x\n",
+		READ_VREG(H264_DECODE_MODE));
+	dpb_print(DECODE_ID(hw), 0,
+		"MBY_MBX=0x%x\n",
+		READ_VREG(MBY_MBX));
+	dpb_print(DECODE_ID(hw), 0,
+		"H264_DECODE_SIZE=0x%x\n",
+		READ_VREG(H264_DECODE_SIZE));
+	dpb_print(DECODE_ID(hw), 0,
+		"VIFF_BIT_CNT=0x%x\n",
+		READ_VREG(VIFF_BIT_CNT));
+	dpb_print(DECODE_ID(hw), 0,
+		"VLD_MEM_VIFIFO_LEVEL=0x%x\n",
+		READ_VREG(VLD_MEM_VIFIFO_LEVEL));
+	dpb_print(DECODE_ID(hw), 0,
+		"VLD_MEM_VIFIFO_WP=0x%x\n",
+		READ_VREG(VLD_MEM_VIFIFO_WP));
+	dpb_print(DECODE_ID(hw), 0,
+		"VLD_MEM_VIFIFO_RP=0x%x\n",
+		READ_VREG(VLD_MEM_VIFIFO_RP));
+	dpb_print(DECODE_ID(hw), 0,
+		"PARSER_VIDEO_RP=0x%x\n",
+		STBUF_READ(&vdec->vbuf, get_rp));
+	dpb_print(DECODE_ID(hw), 0,
+		"PARSER_VIDEO_WP=0x%x\n",
+		STBUF_READ(&vdec->vbuf, get_wp));
+
+	if (input_frame_based(vdec) &&
+		dpb_is_debug(DECODE_ID(hw),
+		PRINT_FRAMEBASE_DATA)
+		) {
+		int jj;
+		if (hw->chunk && hw->chunk->block &&
+			hw->chunk->size > 0) {
+			u8 *data = NULL;
+
+			if (!hw->chunk->block->is_mapped)
+				data = codec_mm_vmap(hw->chunk->block->start +
+					hw->chunk->offset, hw->chunk->size);
+			else
+				data = ((u8 *)hw->chunk->block->start_virt)
+					+ hw->chunk->offset;
+
+			dpb_print(DECODE_ID(hw), 0,
+				"frame data size 0x%x\n",
+				hw->chunk->size);
+			for (jj = 0; jj < hw->chunk->size; jj++) {
+				if ((jj & 0xf) == 0)
+					dpb_print(DECODE_ID(hw),
+					PRINT_FRAMEBASE_DATA,
+						"%06x:", jj);
+				dpb_print_cont(DECODE_ID(hw),
+				PRINT_FRAMEBASE_DATA,
+					"%02x ", data[jj]);
+				if (((jj + 1) & 0xf) == 0)
+					dpb_print_cont(DECODE_ID(hw),
+					PRINT_FRAMEBASE_DATA,
+						"\n");
+			}
+
+			if (!hw->chunk->block->is_mapped)
+				codec_mm_unmap_phyaddr(data);
+		}
+	}
+}
+
+
+static void check_timer_func(struct timer_list *timer)
+{
+	struct vdec_h264_hw_s *hw = container_of(timer,
+		struct vdec_h264_hw_s, check_timer);
+	struct vdec_s *vdec = hw_to_vdec(hw);
+	int error_skip_frame_count = error_skip_count & 0xfff;
+	unsigned int timeout_val = decode_timeout_val;
+	if (timeout_val != 0 &&
+		hw->no_error_count < error_skip_frame_count)
+		timeout_val = errordata_timeout_val;
+	if ((h264_debug_cmd & 0x100) != 0 &&
+		DECODE_ID(hw) == (h264_debug_cmd & 0xff)) {
+		hw->dec_result = DEC_RESULT_DONE;
+		vdec_schedule_work(&hw->work);
+		pr_info("vdec %d is forced to be disconnected\n",
+			h264_debug_cmd & 0xff);
+		h264_debug_cmd = 0;
+		return;
+	}
+	if ((h264_debug_cmd & 0x200) != 0 &&
+		DECODE_ID(hw) == (h264_debug_cmd & 0xff)) {
+		pr_debug("vdec %d is forced to reset bufmgr\n",
+			h264_debug_cmd & 0xff);
+		hw->reset_bufmgr_flag = 1;
+		h264_debug_cmd = 0;
+		return;
+	}
+
+	if (vdec->next_status == VDEC_STATUS_DISCONNECTED &&
+			!hw->is_used_v4l) {
+		hw->dec_result = DEC_RESULT_FORCE_EXIT;
+		vdec_schedule_work(&hw->work);
+		pr_debug("vdec requested to be disconnected\n");
+		return;
+	}
+
+	if (radr != 0) {
+		if (rval != 0) {
+			WRITE_VREG(radr, rval);
+			pr_info("WRITE_VREG(%x,%x)\n", radr, rval);
+		} else
+			pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr));
+		rval = 0;
+		radr = 0;
+	}
+
+	if (((h264_debug_flag & DISABLE_ERROR_HANDLE) == 0) &&
+		(timeout_val > 0) &&
+		(hw->start_process_time > 0) &&
+		((1000 * (jiffies - hw->start_process_time) / HZ)
+			> timeout_val)
+	) {
+		u32 dpb_status = READ_VREG(DPB_STATUS_REG);
+		u32 mby_mbx = READ_VREG(MBY_MBX);
+		if ((dpb_status == H264_ACTION_DECODE_NEWPIC) ||
+			(dpb_status == H264_ACTION_DECODE_SLICE) ||
+			(dpb_status == H264_SEI_DATA_DONE) ||
+			(dpb_status == H264_STATE_SEARCH_HEAD) ||
+			(dpb_status == H264_SLICE_HEAD_DONE) ||
+			(dpb_status == H264_SEI_DATA_READY)) {
+			if (h264_debug_flag & DEBUG_TIMEOUT_DEC_STAT)
+				pr_debug("%s dpb_status = 0x%x last_mby_mbx = %u mby_mbx = %u\n",
+				__func__, dpb_status, hw->last_mby_mbx, mby_mbx);
+
+			if (hw->last_mby_mbx == mby_mbx) {
+				if (hw->decode_timeout_count > 0)
+					hw->decode_timeout_count--;
+				if (hw->decode_timeout_count == 0)
+				{
+					reset_process_time(hw);
+					timeout_process(hw);
+				}
+			} else
+				start_process_time(hw);
+		} else if (is_in_parsing_state(dpb_status)) {
+			if (hw->last_vld_level ==
+				READ_VREG(VLD_MEM_VIFIFO_LEVEL)) {
+				if (hw->decode_timeout_count > 0)
+					hw->decode_timeout_count--;
+				if (hw->decode_timeout_count == 0)
+				{
+					reset_process_time(hw);
+					timeout_process(hw);
+				}
+			}
+		}
+		hw->last_vld_level =
+			READ_VREG(VLD_MEM_VIFIFO_LEVEL);
+		hw->last_mby_mbx = mby_mbx;
+	}
+
+	if ((hw->ucode_pause_pos != 0) &&
+		(hw->ucode_pause_pos != 0xffffffff) &&
+		udebug_pause_pos != hw->ucode_pause_pos) {
+		hw->ucode_pause_pos = 0;
+		WRITE_VREG(DEBUG_REG1, 0);
+	}
+
+	mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL);
+}
+
+static int dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
+{
+	u32 ar, ar_tmp;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+
+	if (!hw)
+		return -1;
+
+	vstatus->frame_width = hw->frame_width;
+	vstatus->frame_height = hw->frame_height;
+	if (hw->error_frame_width &&
+		hw->error_frame_height) {
+		vstatus->frame_width = hw->error_frame_width;
+		vstatus->frame_height = hw->error_frame_height;
+	}
+	if (hw->frame_dur != 0) {
+		vstatus->frame_dur = hw->frame_dur;
+		vstatus->frame_rate = ((96000 * 10 / hw->frame_dur) % 10) < 5 ?
+		                    96000 / hw->frame_dur : (96000 / hw->frame_dur +1);
+	}
+	else
+		vstatus->frame_rate = -1;
+	vstatus->error_count = hw->gvs.error_frame_count;
+	vstatus->status = hw->stat;
+	if (hw->h264_ar == 0x3ff)
+		ar_tmp = (0x100 *
+			hw->frame_height * hw->height_aspect_ratio) /
+			(hw->frame_width * hw->width_aspect_ratio);
+	else
+		ar_tmp = hw->h264_ar;
+	ar = min_t(u32,
+			ar_tmp,
+			DISP_RATIO_ASPECT_RATIO_MAX);
+	vstatus->ratio_control =
+		ar << DISP_RATIO_ASPECT_RATIO_BIT;
+
+	vstatus->error_frame_count = hw->gvs.error_frame_count;
+	vstatus->drop_frame_count = hw->gvs.drop_frame_count;
+	vstatus->frame_count = decode_frame_count[DECODE_ID(hw)];
+	vstatus->i_decoded_frames = hw->gvs.i_decoded_frames;
+	vstatus->i_lost_frames = hw->gvs.i_lost_frames;
+	vstatus->i_concealed_frames = hw->gvs.i_concealed_frames;
+	vstatus->p_decoded_frames = hw->gvs.p_decoded_frames;
+	vstatus->p_lost_frames = hw->gvs.p_lost_frames;
+	vstatus->p_concealed_frames = hw->gvs.p_concealed_frames;
+	vstatus->b_decoded_frames = hw->gvs.b_decoded_frames;
+	vstatus->b_lost_frames = hw->gvs.b_lost_frames;
+	vstatus->b_concealed_frames = hw->gvs.b_concealed_frames;
+	snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
+		"%s-%02d", DRIVER_NAME, hw->id);
+
+	return 0;
+}
+
+static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw)
+{
+	int i, j;
+	struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+
+	hw->frmbase_cont_flag = 0;
+	/* if (hw->init_flag == 0) { */
+	if (h264_debug_flag & 0x40000000) {
+		/* if (1) */
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+		"%s, reset register\n", __func__);
+
+		while (READ_VREG(DCAC_DMA_CTRL) & 0x8000)
+			;
+		while (READ_VREG(LMEM_DMA_CTRL) & 0x8000)
+			;    /* reg address is 0x350 */
+
+#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
+		WRITE_VREG(DOS_SW_RESET0, (1<<7) | (1<<6) | (1<<4));
+		WRITE_VREG(DOS_SW_RESET0, 0);
+
+		READ_VREG(DOS_SW_RESET0);
+		READ_VREG(DOS_SW_RESET0);
+		READ_VREG(DOS_SW_RESET0);
+
+		WRITE_VREG(DOS_SW_RESET0, (1<<7) | (1<<6) | (1<<4));
+		WRITE_VREG(DOS_SW_RESET0, 0);
+
+		WRITE_VREG(DOS_SW_RESET0, (1<<9) | (1<<8));
+		WRITE_VREG(DOS_SW_RESET0, 0);
+
+		READ_VREG(DOS_SW_RESET0);
+		READ_VREG(DOS_SW_RESET0);
+		READ_VREG(DOS_SW_RESET0);
+
+#else
+		WRITE_RESET_REG(RESET0_REGISTER,
+			RESET_IQIDCT | RESET_MC | RESET_VLD_PART);
+		READ_RESET_REG(RESET0_REGISTER);
+			WRITE_RESET_REG(RESET0_REGISTER,
+			RESET_IQIDCT | RESET_MC | RESET_VLD_PART);
+
+		WRITE_RESET_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK);
+#endif
+		WRITE_VREG(POWER_CTL_VLD,
+			READ_VREG(POWER_CTL_VLD) | (0 << 10) |
+				(1 << 9) | (1 << 6));
+	} else {
+		/* WRITE_VREG(POWER_CTL_VLD,
+		 *	READ_VREG(POWER_CTL_VLD) | (0 << 10) | (1 << 9) );
+		 */
+		WRITE_VREG(POWER_CTL_VLD,
+			READ_VREG(POWER_CTL_VLD) |
+				(0 << 10) | (1 << 9) | (1 << 6));
+	}
+	/* disable PSCALE for hardware sharing */
+	WRITE_VREG(PSCALE_CTRL, 0);
+
+	/* clear mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
+
+	/* enable mailbox interrupt */
+	WRITE_VREG(ASSIST_MBOX1_MASK, 1);
+
+#ifdef NV21
+	SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1<<17);
+#endif
+
+	/* cbcr_merge_swap_en */
+	if (hw->is_used_v4l
+		&& (v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21
+		|| v4l2_ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M))
+		SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
+	else
+		CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
+
+	SET_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24);
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24);
+
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31);
+	if (hw->mmu_enable) {
+		SET_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1<<31);
+		/* sw reset to extif hardware */
+		SET_VREG_MASK(MDEC_EXTIF_CFG1, 1<<30);
+		CLEAR_VREG_MASK(MDEC_EXTIF_CFG1, 1<<30);
+	} else {
+		CLEAR_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1 << 31);
+		WRITE_VREG(MDEC_EXTIF_CFG1, 0);
+	}
+
+
+#if 1 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
+	/* pr_info("vh264 meson8 prot init\n"); */
+	WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa);
+#endif
+
+#ifdef VDEC_DW
+	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_T7) {
+		if (IS_VDEC_DW(hw)) {
+			u32 data = ((1   << 30) |(1   <<  0) |(1   <<  8));
+
+			if (IS_VDEC_DW(hw) == 2)
+				data |= (1   <<  9);
+			WRITE_VREG(MDEC_DOUBLEW_CFG0, data); /* Double Write Enable*/
+		}
+	}
+#endif
+	if (hw->dpb.mDPB.size > 0) {
+		WRITE_VREG(AV_SCRATCH_7, (hw->max_reference_size << 24) |
+			(hw->dpb.mDPB.size << 16) |
+			(hw->dpb.mDPB.size << 8));
+
+		for (j = 0; j < hw->dpb.mDPB.size; j++) {
+			i = get_buf_spec_by_canvas_pos(hw, j);
+			if (i < 0)
+				break;
+
+			if (!hw->mmu_enable &&
+				hw->buffer_spec[i].cma_alloc_addr)
+				config_decode_canvas(hw, i);
+			if (hw->mmu_enable && hw->double_write_mode)
+				config_decode_canvas_ex(hw, i);
+		}
+	} else {
+		WRITE_VREG(AV_SCRATCH_0, 0);
+		WRITE_VREG(AV_SCRATCH_9, 0);
+	}
+
+	if (hw->init_flag == 0)
+		WRITE_VREG(DPB_STATUS_REG, 0);
+	else
+		WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_START);
+
+	WRITE_VREG(FRAME_COUNTER_REG, hw->decode_pic_count);
+	WRITE_VREG(AV_SCRATCH_8, hw->buf_offset);
+	if (!tee_enabled())
+		WRITE_VREG(AV_SCRATCH_G, hw->mc_dma_handle);
+
+	/* hw->error_recovery_mode = (error_recovery_mode != 0) ?
+	 *	error_recovery_mode : error_recovery_mode_in;
+	 */
+	/* WRITE_VREG(AV_SCRATCH_F,
+	 *	(READ_VREG(AV_SCRATCH_F) & 0xffffffc3) );
+	 */
+	WRITE_VREG(AV_SCRATCH_F, (hw->save_reg_f & 0xffffffc3) |
+		((error_recovery_mode_in & 0x1) << 4));
+	/*if (hw->ucode_type == UCODE_IP_ONLY_PARAM)
+		SET_VREG_MASK(AV_SCRATCH_F, 1 << 6);
+	else*/
+		CLEAR_VREG_MASK(AV_SCRATCH_F, 1 << 6);
+
+	WRITE_VREG(LMEM_DUMP_ADR, (u32)hw->lmem_phy_addr);
+#if 1 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
+	WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa);
+#endif
+
+	WRITE_VREG(DEBUG_REG1, 0);
+	WRITE_VREG(DEBUG_REG2, 0);
+
+	/*Because CSD data is not found at playback start,
+	  the IQIDCT_CONTROL register is not saved,
+	  the initialized value 0x200 of IQIDCT_CONTROL is set*/
+	if (hw->init_flag && (hw->reg_iqidct_control_init_flag == 0))
+		WRITE_VREG(IQIDCT_CONTROL, 0x200);
+
+	if (hw->reg_iqidct_control)
+		WRITE_VREG(IQIDCT_CONTROL, hw->reg_iqidct_control);
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+		"IQIDCT_CONTROL = 0x%x\n", READ_VREG(IQIDCT_CONTROL));
+
+	if (hw->reg_vcop_ctrl_reg)
+		WRITE_VREG(VCOP_CTRL_REG, hw->reg_vcop_ctrl_reg);
+	if (hw->vld_dec_control)
+		WRITE_VREG(VLD_DECODE_CONTROL, hw->vld_dec_control);
+	return 0;
+}
+
+static int vmh264_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
+{
+	struct vdec_h264_hw_s *hw =
+		(struct vdec_h264_hw_s *)vdec->private;
+	if (i_only_flag & 0x100)
+		return 0;
+	if (trickmode == TRICKMODE_I)
+		hw->i_only = 0x3;
+	else if (trickmode == TRICKMODE_NONE)
+		hw->i_only = 0x0;
+	return 0;
+}
+
+static unsigned char amvdec_enable_flag;
+static void vh264_local_init(struct vdec_h264_hw_s *hw, bool is_reset)
+{
+	int i;
+	hw->init_flag = 0;
+	hw->first_sc_checked= 0;
+	hw->eos = 0;
+	hw->valve_count = 0;
+	hw->config_bufmgr_done = 0;
+	hw->start_process_time = 0;
+	hw->has_i_frame = 0;
+	hw->no_error_count = 0xfff;
+	hw->no_error_i_count = 0xf;
+
+	hw->dec_flag = 0;
+	hw->data_flag = 0;
+	hw->skip_frame_count = 0;
+	hw->reg_iqidct_control = 0;
+	hw->reg_iqidct_control_init_flag = 0;
+	hw->reg_vcop_ctrl_reg = 0;
+	hw->reg_rv_ai_mb_count = 0;
+	hw->vld_dec_control = 0;
+	hw->decode_timeout_count = 0;
+	hw->no_mem_count = 0;
+	hw->dec_again_cnt = 0;
+	hw->vh264_ratio = hw->vh264_amstream_dec_info.ratio;
+	/* vh264_ratio = 0x100; */
+
+	hw->vh264_rotation = (((unsigned long)
+			hw->vh264_amstream_dec_info.param) >> 16) & 0xffff;
+
+	hw->frame_prog = 0;
+	hw->frame_width = hw->vh264_amstream_dec_info.width;
+	hw->frame_height = hw->vh264_amstream_dec_info.height;
+	hw->frame_dur = hw->vh264_amstream_dec_info.rate;
+	hw->pts_outside = ((unsigned long)
+			hw->vh264_amstream_dec_info.param) & 0x01;
+	hw->sync_outside = ((unsigned long)
+			hw->vh264_amstream_dec_info.param & 0x02) >> 1;
+	hw->use_idr_framerate = ((unsigned long)
+			hw->vh264_amstream_dec_info.param & 0x04) >> 2;
+	hw->max_refer_buf = !(((unsigned long)
+			hw->vh264_amstream_dec_info.param & 0x10) >> 4);
+	if (hw->frame_dur < 96000/960) {
+		/*more than 960fps,it should not be a correct value,
+		 *give default 30fps
+		 */
+		hw->frame_dur = 96000/30;
+	}
+
+	hw->unstable_pts = (((unsigned long) hw->vh264_amstream_dec_info.param & 0x40) >> 6);
+
+	hw->first_i_policy = first_i_policy;
+
+	pr_info("H264 sysinfo: %dx%d duration=%d, pts_outside=%d\n",
+		hw->frame_width, hw->frame_height, hw->frame_dur, hw->pts_outside);
+	pr_debug("sync_outside=%d, use_idr_framerate=%d, is_used_v4l: %d\n",
+		hw->sync_outside, hw->use_idr_framerate, hw->is_used_v4l);
+
+	if (i_only_flag & 0x100)
+		hw->i_only = i_only_flag & 0xff;
+	if (hw->i_only)
+		hw->dpb.first_insert_frame = FirstInsertFrm_SKIPDONE;
+
+	if ((unsigned long) hw->vh264_amstream_dec_info.param
+		& 0x08)
+		hw->no_poc_reorder_flag = 1;
+
+	error_recovery_mode_in = 1; /*ucode control?*/
+	if (error_proc_policy & 0x80000000)
+		hw->send_error_frame_flag = error_proc_policy & 0x1;
+	else if ((unsigned long) hw->vh264_amstream_dec_info.param & 0x20)
+		hw->send_error_frame_flag = 0; /*Don't display mark err frames*/
+
+	if (!is_reset) {
+		INIT_KFIFO(hw->display_q);
+		INIT_KFIFO(hw->newframe_q);
+
+		for (i = 0; i < VF_POOL_SIZE; i++) {
+			const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]);
+			hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */
+			hw->vfpool[hw->cur_pool][i].bufWidth = 1920;
+			kfifo_put(&hw->newframe_q, vf);
+		}
+	}
+
+	hw->duration_from_pts_done = 0;
+
+	hw->p_last_vf = NULL;
+	hw->vh264_stream_switching_state = SWITCHING_STATE_OFF;
+	hw->hevc_cur_buf_idx = 0xffff;
+
+	init_waitqueue_head(&hw->wait_q);
+
+	return;
+}
+
+static s32 vh264_init(struct vdec_h264_hw_s *hw)
+{
+	int size = -1;
+	int fw_size = 0x1000 * 16;
+	int fw_mmu_size = 0x1000 * 16;
+	struct firmware_s *fw = NULL, *fw_mmu = NULL;
+
+	/* int trickmode_fffb = 0; */
+
+	/* pr_info("\nvh264_init\n"); */
+	/* init_timer(&hw->recycle_timer); */
+
+	/* timer init */
+	timer_setup(&hw->check_timer, check_timer_func, 0);
+	hw->check_timer.expires = jiffies + CHECK_INTERVAL;
+
+	/* add_timer(&hw->check_timer); */
+	hw->stat |= STAT_TIMER_ARM;
+	hw->stat |= STAT_ISR_REG;
+
+	mutex_init(&hw->chunks_mutex);
+	vh264_local_init(hw, false);
+	INIT_WORK(&hw->work, vh264_work);
+	INIT_WORK(&hw->notify_work, vh264_notify_work);
+	INIT_WORK(&hw->timeout_work, vh264_timeout_work);
+#ifdef MH264_USERDATA_ENABLE
+	INIT_WORK(&hw->user_data_ready_work, user_data_ready_notify_work);
+#endif
+
+	/*if (!amvdec_enable_flag) {
+		amvdec_enable_flag = true;
+		amvdec_enable();
+		if (hw->mmu_enable)
+			amhevc_enable();
+	}*/
+	if (hw->mmu_enable) {
+
+		hw->frame_mmu_map_addr =
+				dma_alloc_coherent(amports_get_dma_device(),
+				FRAME_MMU_MAP_SIZE,
+				&hw->frame_mmu_map_phy_addr, GFP_KERNEL);
+		if (hw->frame_mmu_map_addr == NULL) {
+			pr_err("%s: failed to alloc count_buffer\n", __func__);
+			return -ENOMEM;
+		}
+	}
+
+	fw = vmalloc(sizeof(struct firmware_s) + fw_size);
+	if (IS_ERR_OR_NULL(fw))
+		return -ENOMEM;
+
+	size = get_firmware_data(VIDEO_DEC_H264_MULTI, fw->data);
+	if (size < 0) {
+		pr_err("get firmware fail.\n");
+		vfree(fw);
+		return -1;
+	}
+
+	fw->len = size;
+	hw->fw = fw;
+
+	if (hw->mmu_enable) {
+		fw_mmu = vmalloc(sizeof(struct firmware_s) + fw_mmu_size);
+		if (IS_ERR_OR_NULL(fw_mmu))
+			return -ENOMEM;
+
+		size = get_firmware_data(VIDEO_DEC_H264_MULTI_MMU, fw_mmu->data);
+		if (size < 0) {
+			pr_err("get mmu fw fail.\n");
+			vfree(fw_mmu);
+			return -1;
+		}
+
+		fw_mmu->len = size;
+		hw->fw_mmu = fw_mmu;
+	}
+
+	if (!tee_enabled()) {
+		/* -- ucode loading (amrisc and swap code) */
+		hw->mc_cpu_addr =
+			dma_alloc_coherent(amports_get_dma_device(), MC_TOTAL_SIZE,
+					&hw->mc_dma_handle, GFP_KERNEL);
+		if (!hw->mc_cpu_addr) {
+			amvdec_enable_flag = false;
+			amvdec_disable();
+			hw->vdec_pg_enable_flag = 0;
+			if (hw->mmu_enable)
+				amhevc_disable();
+			pr_info("vh264_init: Can not allocate mc memory.\n");
+			return -ENOMEM;
+		}
+
+		/*pr_info("264 ucode swap area: phyaddr %p, cpu vaddr %p\n",
+			(void *)hw->mc_dma_handle, hw->mc_cpu_addr);
+		*/
+
+		/*ret = amvdec_loadmc_ex(VFORMAT_H264, NULL, buf);*/
+
+		/*header*/
+		memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_HEADER,
+			fw->data + 0x4000, MC_SWAP_SIZE);
+		/*data*/
+		memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_DATA,
+			fw->data + 0x2000, MC_SWAP_SIZE);
+		/*mmco*/
+		memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MMCO,
+			fw->data + 0x6000, MC_SWAP_SIZE);
+		/*list*/
+		memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_LIST,
+			fw->data + 0x3000, MC_SWAP_SIZE);
+		/*slice*/
+		memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_SLICE,
+			fw->data + 0x5000, MC_SWAP_SIZE);
+		/*main*/
+		memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MAIN,
+			fw->data, 0x2000);
+		/*data*/
+		memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MAIN + 0x2000,
+			fw->data + 0x2000, 0x1000);
+		/*slice*/
+		memcpy((u8 *) hw->mc_cpu_addr + MC_OFFSET_MAIN + 0x3000,
+			fw->data + 0x5000, 0x1000);
+	}
+
+#if 1 /* #ifdef  BUFFER_MGR_IN_C */
+	hw->lmem_addr = (dma_addr_t)dma_alloc_coherent(amports_get_dma_device(),
+			PAGE_SIZE, (dma_addr_t *)&hw->lmem_phy_addr, GFP_KERNEL);
+
+	if (hw->lmem_addr == 0) {
+		pr_err("%s: failed to alloc lmem buffer\n", __func__);
+		return -1;
+	}
+	pr_debug("%s, phy_addr=%lx vaddr=%p\n",
+		__func__, hw->lmem_phy_addr, (void *)hw->lmem_addr);
+
+	if (prefix_aux_buf_size > 0 ||
+		suffix_aux_buf_size > 0) {
+		u32 aux_buf_size;
+		hw->prefix_aux_size = AUX_BUF_ALIGN(prefix_aux_buf_size);
+		hw->suffix_aux_size = AUX_BUF_ALIGN(suffix_aux_buf_size);
+		aux_buf_size = hw->prefix_aux_size + hw->suffix_aux_size;
+		hw->aux_addr = dma_alloc_coherent(amports_get_dma_device(),
+						  aux_buf_size, &hw->aux_phy_addr,
+						  GFP_KERNEL);
+		if (hw->aux_addr == NULL) {
+			pr_err("%s: failed to alloc rpm buffer\n", __func__);
+			return -1;
+		}
+
+		hw->sei_data_buf = kmalloc(SEI_DATA_SIZE, GFP_KERNEL);
+		if (hw->sei_data_buf == NULL) {
+			pr_err("%s: failed to alloc sei itu data buffer\n",
+				__func__);
+			return -1;
+		}
+		hw->sei_itu_data_buf = kmalloc(SEI_ITU_DATA_SIZE, GFP_KERNEL);
+		if (hw->sei_itu_data_buf == NULL) {
+			pr_err("%s: failed to alloc sei itu data buffer\n",
+				__func__);
+			dma_free_coherent(amports_get_dma_device(),
+				hw->prefix_aux_size + hw->suffix_aux_size, hw->aux_addr,
+				hw->aux_phy_addr);
+			hw->aux_addr = NULL;
+			kfree(hw->sei_data_buf);
+			hw->sei_data_buf = NULL;
+
+			return -1;
+		}
+
+		if (NULL == hw->sei_user_data_buffer) {
+			hw->sei_user_data_buffer = kmalloc(USER_DATA_SIZE,
+								GFP_KERNEL);
+			if (!hw->sei_user_data_buffer) {
+				pr_info("%s: Can not allocate sei_data_buffer\n",
+					   __func__);
+				dma_free_coherent(amports_get_dma_device(),
+					hw->prefix_aux_size + hw->suffix_aux_size, hw->aux_addr,
+					hw->aux_phy_addr);
+				hw->aux_addr = NULL;
+				kfree(hw->sei_data_buf);
+				hw->sei_data_buf = NULL;
+				kfree(hw->sei_itu_data_buf);
+				hw->sei_itu_data_buf = NULL;
+
+				return -1;
+			}
+			hw->sei_user_data_wp = 0;
+		}
+	}
+/* BUFFER_MGR_IN_C */
+#endif
+	hw->stat |= STAT_MC_LOAD;
+
+	/* add memory barrier */
+	wmb();
+
+	return 0;
+}
+
+static int vh264_stop(struct vdec_h264_hw_s *hw)
+{
+	if (hw->stat & STAT_VDEC_RUN) {
+		amvdec_stop();
+		hw->stat &= ~STAT_VDEC_RUN;
+	}
+#ifdef VDEC_DW
+	WRITE_VREG(MDEC_DOUBLEW_CFG0, 0);
+	WRITE_VREG(MDEC_DOUBLEW_CFG1, 0);
+#endif
+#ifdef MH264_USERDATA_ENABLE
+	cancel_work_sync(&hw->user_data_ready_work);
+#endif
+	cancel_work_sync(&hw->notify_work);
+	cancel_work_sync(&hw->timeout_work);
+	cancel_work_sync(&hw->work);
+
+	if (hw->stat & STAT_MC_LOAD) {
+		if (hw->mc_cpu_addr != NULL) {
+			dma_free_coherent(amports_get_dma_device(),
+					MC_TOTAL_SIZE, hw->mc_cpu_addr,
+					hw->mc_dma_handle);
+			hw->mc_cpu_addr = NULL;
+		}
+		if (hw->frame_mmu_map_addr != NULL) {
+			dma_free_coherent(amports_get_dma_device(),
+				FRAME_MMU_MAP_SIZE, hw->frame_mmu_map_addr,
+					hw->frame_mmu_map_phy_addr);
+			hw->frame_mmu_map_addr = NULL;
+		}
+
+	}
+	if (hw->stat & STAT_ISR_REG) {
+		vdec_free_irq(VDEC_IRQ_1, (void *)hw);
+		hw->stat &= ~STAT_ISR_REG;
+	}
+	if (hw->lmem_addr) {
+		dma_free_coherent(amports_get_dma_device(),
+			PAGE_SIZE, (void *)hw->lmem_addr,
+			hw->lmem_phy_addr);
+		hw->lmem_addr = 0;
+	}
+
+	if (hw->aux_addr) {
+		dma_free_coherent(amports_get_dma_device(),
+			hw->prefix_aux_size + hw->suffix_aux_size, hw->aux_addr,
+			hw->aux_phy_addr);
+		hw->aux_addr = NULL;
+	}
+	if (hw->sei_data_buf != NULL) {
+		kfree(hw->sei_data_buf);
+		hw->sei_data_buf = NULL;
+	}
+	if (hw->sei_itu_data_buf != NULL) {
+		kfree(hw->sei_itu_data_buf);
+		hw->sei_itu_data_buf = NULL;
+	}
+	if (hw->sei_user_data_buffer != NULL) {
+		kfree(hw->sei_user_data_buffer);
+		hw->sei_user_data_buffer = NULL;
+	}
+	/* amvdec_disable(); */
+
+	vfree(hw->fw);
+	hw->fw = NULL;
+
+	if (hw->mmu_enable) {
+		vfree(hw->fw_mmu);
+		hw->fw_mmu = NULL;
+	}
+
+	dpb_print(DECODE_ID(hw), 0,
+		"%s\n",
+		__func__);
+	return 0;
+}
+
+static void wait_vmh264_search_done(struct vdec_h264_hw_s *hw)
+{
+	u32 vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP);
+	int count = 0;
+	do {
+		usleep_range(100, 500);
+		if (vld_rp == READ_VREG(VLD_MEM_VIFIFO_RP))
+			break;
+		if (count > 2000) {
+			dpb_print(DECODE_ID(hw),
+			PRINT_FLAG_ERROR, "%s timeout count %d vld_rp 0x%x VLD_MEM_VIFIFO_RP 0x%x\n",
+			 __func__, count, vld_rp, READ_VREG(VLD_MEM_VIFIFO_RP));
+			break;
+		} else
+			vld_rp = READ_VREG(VLD_MEM_VIFIFO_RP);
+		count++;
+	} while (1);
+}
+
+static void vh264_notify_work(struct work_struct *work)
+{
+	struct vdec_h264_hw_s *hw = container_of(work,
+					struct vdec_h264_hw_s, notify_work);
+	struct vdec_s *vdec = hw_to_vdec(hw);
+
+	if (hw->is_used_v4l)
+		return;
+
+	if (vdec->fr_hint_state == VDEC_NEED_HINT) {
+		vf_notify_receiver(vdec->vf_provider_name,
+				VFRAME_EVENT_PROVIDER_FR_HINT,
+				(void *)((unsigned long)hw->frame_dur));
+		vdec->fr_hint_state = VDEC_HINTED;
+	}
+
+	return;
+}
+
+#ifdef MH264_USERDATA_ENABLE
+static void vmh264_reset_udr_mgr(struct vdec_h264_hw_s *hw)
+{
+	hw->wait_for_udr_send = 0;
+	hw->sei_itu_data_len = 0;
+	memset(&hw->ud_record, 0, sizeof(hw->ud_record));
+}
+
+static void vmh264_crate_userdata_manager(
+						struct vdec_h264_hw_s *hw,
+						u8 *userdata_buf,
+						int buf_len)
+{
+	if (hw) {
+
+
+		mutex_init(&hw->userdata_mutex);
+
+		memset(&hw->userdata_info, 0,
+			sizeof(struct mh264_userdata_info_t));
+		hw->userdata_info.data_buf = userdata_buf;
+		hw->userdata_info.buf_len = buf_len;
+		hw->userdata_info.data_buf_end = userdata_buf + buf_len;
+
+		vmh264_reset_udr_mgr(hw);
+
+	}
+}
+
+static void vmh264_destroy_userdata_manager(struct vdec_h264_hw_s *hw)
+{
+	if (hw)
+		memset(&hw->userdata_info,
+				0,
+				sizeof(struct mh264_userdata_info_t));
+}
+
+/*
+#define DUMP_USERDATA_RECORD
+*/
+#ifdef DUMP_USERDATA_RECORD
+
+#define MAX_USER_DATA_SIZE		3145728
+static void *user_data_buf;
+static unsigned char *pbuf_start;
+static int total_len;
+static int bskip;
+static int n_userdata_id;
+
+static void print_data(unsigned char *pdata,
+						int len,
+						unsigned int poc_number,
+						unsigned int flag,
+						unsigned int duration,
+						unsigned int vpts,
+						unsigned int vpts_valid,
+						int rec_id)
+{
+	int nLeft;
+
+	nLeft = len;
+#if 0
+	pr_info("%d len:%d, flag:%d, dur:%d, vpts:0x%x, valid:%d, poc:%d\n",
+				rec_id,	len, flag,
+				duration, vpts, vpts_valid, poc_number);
+#endif
+	pr_info("%d len = %d, flag = %d, vpts = 0x%x\n",
+				rec_id,	len, flag, vpts);
+
+	if (len == 96) {
+		int i;
+		nLeft = 72;
+		while (nLeft >= 16) {
+			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+				pdata[0], pdata[1], pdata[2], pdata[3],
+				pdata[4], pdata[5], pdata[6], pdata[7],
+				pdata[8], pdata[9], pdata[10], pdata[11],
+				pdata[12], pdata[13], pdata[14], pdata[15]);
+			nLeft -= 16;
+			pdata += 16;
+		}
+
+
+		while (nLeft > 0) {
+			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+				pdata[0], pdata[1], pdata[2], pdata[3],
+				pdata[4], pdata[5], pdata[6], pdata[7]);
+			nLeft -= 8;
+			pdata += 8;
+		}
+
+		i = 0;
+		nLeft = 96-72;
+		while (i < nLeft) {
+			if (pdata[0] != 0) {
+				pr_info("some data error\n");
+				break;
+			}
+			pdata++;
+			i++;
+		}
+	} else {
+		while (nLeft >= 16) {
+			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+				pdata[0], pdata[1], pdata[2], pdata[3],
+				pdata[4], pdata[5], pdata[6], pdata[7],
+				pdata[8], pdata[9], pdata[10], pdata[11],
+				pdata[12], pdata[13], pdata[14], pdata[15]);
+			nLeft -= 16;
+			pdata += 16;
+		}
+
+
+		while (nLeft > 0) {
+			pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+				pdata[0], pdata[1], pdata[2], pdata[3],
+				pdata[4], pdata[5], pdata[6], pdata[7]);
+			nLeft -= 8;
+			pdata += 8;
+		}
+
+	}
+}
+
+static void push_to_buf(struct vdec_h264_hw_s *hw,
+					u8 *pdata,
+					int len,
+					struct userdata_meta_info_t *pmeta);
+
+static void dump_userdata_record(struct vdec_h264_hw_s *hw,
+					struct mh264_userdata_record_t *record)
+{
+	if (record && hw) {
+		u8 *pdata;
+
+		pdata = hw->userdata_info.data_buf + record->rec_start;
+/*
+		print_data(pdata,
+			record->rec_len,
+			record->meta_info.flags,
+			record->meta_info.duration,
+			record->meta_info.vpts,
+			record->meta_info.vpts_valid,
+			n_record_id);
+*/
+		push_to_buf(hw, pdata, record->rec_len,  &record->meta_info);
+		n_userdata_id++;
+	}
+}
+
+
+static void push_to_buf(struct vdec_h264_hw_s *hw,
+					u8 *pdata, int len,
+					struct userdata_meta_info_t *pmeta)
+{
+	u32 *pLen;
+	int info_cnt;
+	u8 *pbuf_end;
+
+	if (!user_data_buf)
+		return;
+
+	if (bskip) {
+		pr_info("over size, skip\n");
+		return;
+	}
+	info_cnt = 0;
+	pLen = (u32 *)pbuf_start;
+
+	*pLen = len;
+	pbuf_start += sizeof(u32);
+	info_cnt++;
+	pLen++;
+
+	*pLen = pmeta->poc_number;
+	pbuf_start += sizeof(u32);
+	info_cnt++;
+	pLen++;
+
+	*pLen = pmeta->duration;
+	pbuf_start += sizeof(u32);
+	info_cnt++;
+	pLen++;
+
+	*pLen = pmeta->flags;
+	pbuf_start += sizeof(u32);
+	info_cnt++;
+	pLen++;
+
+	*pLen = pmeta->vpts;
+	pbuf_start += sizeof(u32);
+	info_cnt++;
+	pLen++;
+
+	*pLen = pmeta->vpts_valid;
+	pbuf_start += sizeof(u32);
+	info_cnt++;
+	pLen++;
+
+
+	*pLen = n_userdata_id;
+	pbuf_start += sizeof(u32);
+	info_cnt++;
+	pLen++;
+
+
+
+	pbuf_end = (u8 *)hw->sei_user_data_buffer + USER_DATA_SIZE;
+	if (pdata + len > pbuf_end) {
+		int first_section_len;
+
+		first_section_len = pbuf_end - pdata;
+		memcpy(pbuf_start, pdata, first_section_len);
+		pdata = (u8 *)hw->sei_user_data_buffer;
+		pbuf_start += first_section_len;
+		memcpy(pbuf_start, pdata, len - first_section_len);
+		pbuf_start += len - first_section_len;
+	} else {
+		memcpy(pbuf_start, pdata, len);
+		pbuf_start += len;
+	}
+
+	total_len += len + info_cnt * sizeof(u32);
+	if (total_len >= MAX_USER_DATA_SIZE-4096)
+		bskip = 1;
+}
+
+static void show_user_data_buf(void)
+{
+	u8 *pbuf;
+	int len;
+	unsigned int flag;
+	unsigned int duration;
+	unsigned int vpts;
+	unsigned int vpts_valid;
+	unsigned int poc_number;
+	int rec_id;
+
+	pr_info("show user data buf\n");
+	pbuf = user_data_buf;
+
+	while (pbuf < pbuf_start) {
+		u32 *pLen;
+
+		pLen = (u32 *)pbuf;
+
+		len = *pLen;
+		pLen++;
+		pbuf += sizeof(u32);
+
+		poc_number = *pLen;
+		pLen++;
+		pbuf += sizeof(u32);
+
+		duration = *pLen;
+		pLen++;
+		pbuf += sizeof(u32);
+
+		flag = *pLen;
+		pLen++;
+		pbuf += sizeof(u32);
+
+		vpts = *pLen;
+		pLen++;
+		pbuf += sizeof(u32);
+
+		vpts_valid = *pLen;
+		pLen++;
+		pbuf += sizeof(u32);
+
+		rec_id = *pLen;
+		pLen++;
+		pbuf += sizeof(u32);
+
+		print_data(pbuf, len, poc_number, flag,
+			duration, vpts,
+			vpts_valid, rec_id);
+		pbuf += len;
+		msleep(30);
+	}
+}
+
+static int vmh264_init_userdata_dump(void)
+{
+	user_data_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL);
+	if (user_data_buf)
+		return 1;
+	else
+		return 0;
+}
+
+static void vmh264_dump_userdata(void)
+{
+	if (user_data_buf) {
+		show_user_data_buf();
+		kfree(user_data_buf);
+		user_data_buf = NULL;
+	}
+}
+
+static void vmh264_reset_user_data_buf(void)
+{
+	total_len = 0;
+	pbuf_start = user_data_buf;
+	bskip = 0;
+	n_userdata_id = 0;
+}
+#endif
+
+
+static void vmh264_udc_fill_vpts(struct vdec_h264_hw_s *hw,
+						int frame_type,
+						u32 vpts,
+						u32 vpts_valid)
+{
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+
+	unsigned char *pdata;
+	u8 *pmax_sei_data_buffer;
+	u8 *sei_data_buf;
+	int i;
+	int wp;
+	int data_length;
+	struct mh264_userdata_record_t *p_userdata_rec;
+
+
+#ifdef MH264_USERDATA_ENABLE
+	struct userdata_meta_info_t meta_info;
+	memset(&meta_info, 0, sizeof(meta_info));
+#endif
+
+	if (hw->sei_itu_data_len <= 0)
+		return;
+
+	pdata = (u8 *)hw->sei_user_data_buffer + hw->sei_user_data_wp;
+	pmax_sei_data_buffer = (u8 *)hw->sei_user_data_buffer + USER_DATA_SIZE;
+	sei_data_buf = (u8 *)hw->sei_itu_data_buf;
+	for (i = 0; i < hw->sei_itu_data_len; i++) {
+		*pdata++ = sei_data_buf[i];
+		if (pdata >= pmax_sei_data_buffer)
+			pdata = (u8 *)hw->sei_user_data_buffer;
+	}
+
+	hw->sei_user_data_wp = (hw->sei_user_data_wp
+		+ hw->sei_itu_data_len) % USER_DATA_SIZE;
+	hw->sei_itu_data_len = 0;
+
+#ifdef MH264_USERDATA_ENABLE
+	meta_info.duration = hw->frame_dur;
+	meta_info.flags |= (VFORMAT_H264 << 3);
+
+	meta_info.vpts = vpts;
+	meta_info.vpts_valid = vpts_valid;
+	meta_info.poc_number =
+		p_H264_Dpb->mVideo.dec_picture->poc;
+
+
+	wp = hw->sei_user_data_wp;
+
+	if (hw->sei_user_data_wp > hw->userdata_info.last_wp)
+		data_length = wp - hw->userdata_info.last_wp;
+	else
+		data_length = wp + hw->userdata_info.buf_len
+			- hw->userdata_info.last_wp;
+
+	if (data_length & 0x7)
+		data_length = (((data_length + 8) >> 3) << 3);
+
+	p_userdata_rec = &hw->ud_record;
+	p_userdata_rec->meta_info = meta_info;
+	p_userdata_rec->rec_start = hw->userdata_info.last_wp;
+	p_userdata_rec->rec_len = data_length;
+	hw->userdata_info.last_wp = wp;
+
+	p_userdata_rec->meta_info.flags |=
+		p_H264_Dpb->mVideo.dec_picture->pic_struct << 12;
+
+	hw->wait_for_udr_send = 1;
+	vdec_schedule_work(&hw->user_data_ready_work);
+#endif
+}
+
+
+static void user_data_ready_notify_work(struct work_struct *work)
+{
+	struct vdec_h264_hw_s *hw = container_of(work,
+		struct vdec_h264_hw_s, user_data_ready_work);
+
+
+	mutex_lock(&hw->userdata_mutex);
+
+	hw->userdata_info.records[hw->userdata_info.write_index]
+		= hw->ud_record;
+	hw->userdata_info.write_index++;
+	if (hw->userdata_info.write_index >= USERDATA_FIFO_NUM)
+		hw->userdata_info.write_index = 0;
+
+	mutex_unlock(&hw->userdata_mutex);
+
+#ifdef DUMP_USERDATA_RECORD
+	dump_userdata_record(hw, &hw->ud_record);
+#endif
+	vdec_wakeup_userdata_poll(hw_to_vdec(hw));
+
+	hw->wait_for_udr_send = 0;
+}
+
+static int vmh264_user_data_read(struct vdec_s *vdec,
+	struct userdata_param_t *puserdata_para)
+{
+	struct vdec_h264_hw_s *hw = NULL;
+	int rec_ri, rec_wi;
+	int rec_len;
+	u8 *rec_data_start;
+	u8 *pdest_buf;
+	struct mh264_userdata_record_t *p_userdata_rec;
+	u32 data_size;
+	u32 res;
+	int copy_ok = 1;
+
+	hw = (struct vdec_h264_hw_s *)vdec->private;
+
+	pdest_buf = puserdata_para->pbuf_addr;
+
+	mutex_lock(&hw->userdata_mutex);
+
+/*
+	pr_info("ri = %d, wi = %d\n",
+		lg_p_mpeg12_userdata_info->read_index,
+		lg_p_mpeg12_userdata_info->write_index);
+*/
+	rec_ri = hw->userdata_info.read_index;
+	rec_wi = hw->userdata_info.write_index;
+
+	if (rec_ri == rec_wi) {
+		mutex_unlock(&hw->userdata_mutex);
+		return 0;
+	}
+
+	p_userdata_rec = hw->userdata_info.records + rec_ri;
+
+	rec_len = p_userdata_rec->rec_len;
+	rec_data_start = p_userdata_rec->rec_start + hw->userdata_info.data_buf;
+/*
+	pr_info("rec_len:%d, rec_start:%d, buf_len:%d\n",
+		p_userdata_rec->rec_len,
+		p_userdata_rec->rec_start,
+		puserdata_para->buf_len);
+*/
+	if (rec_len <= puserdata_para->buf_len) {
+		/* dvb user data buffer is enought to
+		copy the whole recored. */
+		data_size = rec_len;
+		if (rec_data_start + data_size
+			> hw->userdata_info.data_buf_end) {
+			int first_section_len;
+
+			first_section_len = hw->userdata_info.buf_len -
+				p_userdata_rec->rec_start;
+			res = (u32)copy_to_user((void *)pdest_buf,
+							(void *)rec_data_start,
+							first_section_len);
+			if (res) {
+				pr_info("p1 read not end res=%d, request=%d\n",
+					res, first_section_len);
+				copy_ok = 0;
+
+				p_userdata_rec->rec_len -=
+					first_section_len - res;
+				p_userdata_rec->rec_start +=
+					first_section_len - res;
+				puserdata_para->data_size =
+					first_section_len - res;
+			} else {
+				res = (u32)copy_to_user(
+					(void *)(pdest_buf+first_section_len),
+					(void *)hw->userdata_info.data_buf,
+					data_size - first_section_len);
+				if (res) {
+					pr_info("p2 read not end res=%d, request=%d\n",
+						res, data_size);
+					copy_ok = 0;
+				}
+				p_userdata_rec->rec_len -=
+					data_size - res;
+				p_userdata_rec->rec_start =
+					data_size - first_section_len - res;
+				puserdata_para->data_size =
+					data_size - res;
+			}
+		} else {
+			res = (u32)copy_to_user((void *)pdest_buf,
+							(void *)rec_data_start,
+							data_size);
+			if (res) {
+				pr_info("p3 read not end res=%d, request=%d\n",
+					res, data_size);
+				copy_ok = 0;
+			}
+			p_userdata_rec->rec_len -= data_size - res;
+			p_userdata_rec->rec_start += data_size - res;
+			puserdata_para->data_size = data_size - res;
+		}
+
+		if (copy_ok) {
+			hw->userdata_info.read_index++;
+			if (hw->userdata_info.read_index >= USERDATA_FIFO_NUM)
+				hw->userdata_info.read_index = 0;
+		}
+	} else {
+		/* dvb user data buffer is not enought
+		to copy the whole recored. */
+		data_size = puserdata_para->buf_len;
+		if (rec_data_start + data_size
+			> hw->userdata_info.data_buf_end) {
+			int first_section_len;
+
+			first_section_len = hw->userdata_info.buf_len -
+				p_userdata_rec->rec_start;
+			res = (u32)copy_to_user((void *)pdest_buf,
+						(void *)rec_data_start,
+						first_section_len);
+			if (res) {
+				pr_info("p4 read not end res=%d, request=%d\n",
+					res, first_section_len);
+				copy_ok = 0;
+				p_userdata_rec->rec_len -=
+					first_section_len - res;
+				p_userdata_rec->rec_start +=
+					first_section_len - res;
+				puserdata_para->data_size =
+					first_section_len - res;
+			} else {
+				/* first secton copy is ok*/
+				res = (u32)copy_to_user(
+					(void *)(pdest_buf+first_section_len),
+					(void *)hw->userdata_info.data_buf,
+					data_size - first_section_len);
+				if (res) {
+					pr_info("p5 read not end res=%d, request=%d\n",
+						res,
+						data_size - first_section_len);
+					copy_ok = 0;
+				}
+
+				p_userdata_rec->rec_len -=
+					data_size - res;
+				p_userdata_rec->rec_start =
+					data_size - first_section_len - res;
+				puserdata_para->data_size =
+					data_size - res;
+			}
+		} else {
+			res = (u32)copy_to_user((void *)pdest_buf,
+							(void *)rec_data_start,
+							data_size);
+			if (res) {
+				pr_info("p6 read not end res=%d, request=%d\n",
+					res, data_size);
+				copy_ok = 0;
+			}
+
+			p_userdata_rec->rec_len -= data_size - res;
+			p_userdata_rec->rec_start += data_size - res;
+			puserdata_para->data_size = data_size - res;
+		}
+
+		if (copy_ok) {
+			hw->userdata_info.read_index++;
+			if (hw->userdata_info.read_index >= USERDATA_FIFO_NUM)
+				hw->userdata_info.read_index = 0;
+		}
+
+	}
+	puserdata_para->meta_info = p_userdata_rec->meta_info;
+
+	if (hw->userdata_info.read_index <= hw->userdata_info.write_index)
+		puserdata_para->meta_info.records_in_que =
+			hw->userdata_info.write_index -
+			hw->userdata_info.read_index;
+	else
+		puserdata_para->meta_info.records_in_que =
+			hw->userdata_info.write_index +
+			USERDATA_FIFO_NUM -
+			hw->userdata_info.read_index;
+
+	puserdata_para->version = (0<<24|0<<16|0<<8|1);
+
+	mutex_unlock(&hw->userdata_mutex);
+
+	return 1;
+}
+
+static void vmh264_reset_userdata_fifo(struct vdec_s *vdec, int bInit)
+{
+	struct vdec_h264_hw_s *hw = NULL;
+
+	hw = (struct vdec_h264_hw_s *)vdec->private;
+
+	if (hw) {
+		mutex_lock(&hw->userdata_mutex);
+		pr_info("vmh264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n",
+			bInit,
+			hw->userdata_info.read_index,
+			hw->userdata_info.write_index);
+		hw->userdata_info.read_index = 0;
+		hw->userdata_info.write_index = 0;
+
+		if (bInit)
+			hw->userdata_info.last_wp = 0;
+		mutex_unlock(&hw->userdata_mutex);
+	}
+}
+
+static void vmh264_wakeup_userdata_poll(struct vdec_s *vdec)
+{
+	amstream_wakeup_userdata_poll(vdec);
+}
+
+#endif
+
+static int vmh264_get_ps_info(struct vdec_h264_hw_s *hw,
+	u32 param1, u32 param2, u32 param3, u32 param4,
+	struct aml_vdec_ps_infos *ps)
+{
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	struct vdec_s *vdec = hw_to_vdec(hw);
+#endif
+	int mb_width, mb_total;
+	int mb_height = 0;
+	int active_buffer_spec_num, dec_dpb_size;
+	int max_reference_size ,level_idc;
+	u32 frame_mbs_only_flag;
+	u32 chroma_format_idc;
+	u32 crop_bottom, crop_right;
+	int sub_width_c = 0, sub_height_c = 0;
+	u32 frame_width, frame_height;
+	u32 used_reorder_dpb_size_margin
+		= hw->reorder_dpb_size_margin;
+
+	level_idc = param4 & 0xff;
+	max_reference_size = (param4 >> 8) & 0xff;
+
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	if (vdec->master || vdec->slave)
+		used_reorder_dpb_size_margin =
+			reorder_dpb_size_margin_dv;
+#endif
+	mb_width = param1 & 0xff;
+	mb_total = (param1 >> 8) & 0xffff;
+	if (!mb_width && mb_total) /*for 4k2k*/
+		mb_width = 256;
+	if (mb_width)
+		mb_height = mb_total/mb_width;
+	if (mb_width <= 0 || mb_height <= 0 ||
+		is_oversize(mb_width << 4, mb_height << 4)) {
+		dpb_print(DECODE_ID(hw), 0,
+			"!!!wrong param1 0x%x mb_width/mb_height (0x%x/0x%x) %x\r\n",
+			param1,
+			mb_width,
+			mb_height);
+		hw->error_frame_width = mb_width << 4;
+		hw->error_frame_height = mb_height << 4;
+		return -1;
+	}
+	hw->error_frame_width = 0;
+	hw->error_frame_height = 0;
+
+	dec_dpb_size = get_dec_dpb_size(hw , mb_width, mb_height);
+
+	dpb_print(DECODE_ID(hw), 0,
+		"restriction_flag=%d, max_dec_frame_buffering=%d, dec_dpb_size=%d num_reorder_frames %d used_reorder_dpb_size_margin %d\n",
+		hw->bitstream_restriction_flag,
+		hw->max_dec_frame_buffering,
+		dec_dpb_size,
+		hw->num_reorder_frames,
+		used_reorder_dpb_size_margin);
+
+	active_buffer_spec_num =
+		dec_dpb_size
+		+ used_reorder_dpb_size_margin;
+
+	if (active_buffer_spec_num > MAX_VF_BUF_NUM) {
+		active_buffer_spec_num = MAX_VF_BUF_NUM;
+		dec_dpb_size = active_buffer_spec_num
+			- used_reorder_dpb_size_margin;
+	}
+
+	hw->dpb.mDPB.size = active_buffer_spec_num;
+
+	if (hw->no_poc_reorder_flag)
+		dec_dpb_size = 1;
+
+	/*
+	 * crop
+	 * AV_SCRATCH_2
+	 * bit 15: frame_mbs_only_flag
+	 * bit 13-14: chroma_format_idc
+	 */
+	hw->seq_info = param2;
+	frame_mbs_only_flag = (hw->seq_info >> 15) & 0x01;
+	if (hw->dpb.mSPS.profile_idc != 100 &&
+		hw->dpb.mSPS.profile_idc != 110 &&
+		hw->dpb.mSPS.profile_idc != 122 &&
+		hw->dpb.mSPS.profile_idc != 144) {
+		hw->dpb.chroma_format_idc = 1;
+	}
+	chroma_format_idc = hw->dpb.chroma_format_idc;
+
+	/*
+	 * AV_SCRATCH_6 bit 31-16 =  (left  << 8 | right ) << 1
+	 * AV_SCRATCH_6 bit 15-0 =  (top << 8  | bottom ) <<
+	 *                          (2 - frame_mbs_only_flag)
+	 */
+	switch (chroma_format_idc) {
+		case 1:
+			sub_width_c = 2;
+			sub_height_c = 2;
+			break;
+
+		case 2:
+			sub_width_c = 2;
+			sub_height_c = 1;
+			break;
+
+		case 3:
+			sub_width_c = 1;
+			sub_height_c = 1;
+			break;
+
+		default:
+			break;
+	}
+
+	if (chroma_format_idc == 0) {
+		crop_right = hw->dpb.frame_crop_right_offset;
+		crop_bottom = hw->dpb.frame_crop_bottom_offset *
+			(2 - frame_mbs_only_flag);
+	} else {
+		crop_right = sub_width_c * hw->dpb.frame_crop_right_offset;
+		crop_bottom = sub_height_c * hw->dpb.frame_crop_bottom_offset *
+			(2 - frame_mbs_only_flag);
+	}
+
+	frame_width = mb_width << 4;
+	frame_height = mb_height << 4;
+
+	frame_width = frame_width - crop_right;
+	frame_height = frame_height - crop_bottom;
+
+	ps->profile 		= level_idc;
+	ps->ref_frames 		= max_reference_size;
+	ps->mb_width 		= mb_width;
+	ps->mb_height 		= mb_height;
+	ps->visible_width	= frame_width;
+	ps->visible_height	= frame_height;
+	ps->coded_width		= ALIGN(mb_width << 4, 64);
+	ps->coded_height	= ALIGN(mb_height << 4, 64);
+	ps->dpb_frames		= dec_dpb_size + 1; /* +1 for two frames in one packet */
+	ps->dpb_size		= active_buffer_spec_num;
+
+	return 0;
+}
+
+static int v4l_res_change(struct vdec_h264_hw_s *hw,
+			  u32 param1, u32 param2,
+			  u32 param3, u32 param4)
+{
+	struct aml_vcodec_ctx *ctx =
+		(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	int ret = 0;
+	int dec_dpb_size_change = hw->csd_change_flag && (hw->dpb.dec_dpb_size != get_dec_dpb_size_active(hw, param1));
+
+	if (ctx->param_sets_from_ucode &&
+			hw->res_ch_flag == 0) {
+		if (((param1 != 0 &&
+			hw->seq_info2 != param1) || hw->csd_change_flag) &&
+			hw->seq_info2 != 0) {
+			if (hw->seq_info2 != param1 || dec_dpb_size_change) { /*picture size changed*/
+				struct aml_vdec_ps_infos ps;
+				dpb_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
+					"h264 res_change\n");
+				if (vmh264_get_ps_info(hw, param1,
+					param2, param3, param4, &ps) < 0) {
+					dpb_print(DECODE_ID(hw), 0,
+						"set parameters error\n");
+				}
+				hw->v4l_params_parsed = false;
+				vdec_v4l_set_ps_infos(ctx, &ps);
+				vdec_v4l_res_ch_event(ctx);
+				hw->res_ch_flag = 1;
+				ctx->v4l_resolution_change = 1;
+				amvdec_stop();
+				if (hw->mmu_enable)
+					amhevc_stop();
+				hw->eos = 1;
+				flush_dpb(p_H264_Dpb);
+				//del_timer_sync(&hw->check_timer);
+				notify_v4l_eos(hw_to_vdec(hw));
+				ret = 1;
+			}
+		}
+	}
+
+	return ret;
+
+}
+
+static int check_dirty_data(struct vdec_s *vdec)
+{
+	struct vdec_h264_hw_s *hw =
+		(struct vdec_h264_hw_s *)(vdec->private);
+	u32 wp, rp, level;
+
+	rp = STBUF_READ(&vdec->vbuf, get_rp);
+	wp = STBUF_READ(&vdec->vbuf, get_wp);
+
+	if (wp > rp)
+		level = wp - rp;
+	else
+		level = wp + vdec->input.size - rp ;
+
+	if (level > (vdec->input.size / 2))
+		hw->dec_again_cnt++;
+
+	if (hw->dec_again_cnt > dirty_again_threshold) {
+		dpb_print(DECODE_ID(hw), 0, "h264 data skipped %x\n", level);
+		hw->dec_again_cnt = 0;
+		return 1;
+	}
+	return 0;
+}
+
+static void vh264_work_implement(struct vdec_h264_hw_s *hw,
+	struct vdec_s *vdec, int from)
+{
+	/* finished decoding one frame or error,
+	 * notify vdec core to switch context
+	 */
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+
+	if (hw->dec_result == DEC_RESULT_DONE) {
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_WORKER_START);
+	} else if (hw->dec_result == DEC_RESULT_AGAIN)
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_WORKER_AGAIN);
+
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL,
+		"%s dec_result %d %x %x %x\n",
+		__func__,
+		hw->dec_result,
+		READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+		READ_VREG(VLD_MEM_VIFIFO_WP),
+		READ_VREG(VLD_MEM_VIFIFO_RP));
+		if (!hw->mmu_enable) {
+			mutex_lock(&vmh264_mutex);
+			dealloc_buf_specs(hw, 0);
+			mutex_unlock(&vmh264_mutex);
+		}
+	hw->save_reg_f = READ_VREG(AV_SCRATCH_F);
+	hw->dpb.last_dpb_status = hw->dpb.dec_dpb_status;
+	if (hw->dec_result == DEC_RESULT_CONFIG_PARAM) {
+		u32 param1 = READ_VREG(AV_SCRATCH_1);
+		u32 param2 = READ_VREG(AV_SCRATCH_2);
+		u32 param3 = READ_VREG(AV_SCRATCH_6);
+		u32 param4 = READ_VREG(AV_SCRATCH_B);
+		struct aml_vcodec_ctx *ctx =
+				(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+
+		if (hw->is_used_v4l &&
+			ctx->param_sets_from_ucode) {
+			if (!v4l_res_change(hw, param1, param2, param3, param4)) {
+				if (!hw->v4l_params_parsed) {
+					struct aml_vdec_ps_infos ps;
+					dpb_print(DECODE_ID(hw),
+						PRINT_FLAG_DEC_DETAIL,
+						"h264 parsered csd data\n");
+					if (vmh264_get_ps_info(hw,
+						param1, param2,
+						param3, param4, &ps) < 0) {
+						dpb_print(DECODE_ID(hw), 0,
+							"set parameters error\n");
+					}
+					hw->v4l_params_parsed = true;
+					vdec_v4l_set_ps_infos(ctx, &ps);
+
+					amvdec_stop();
+					if (hw->mmu_enable)
+						amhevc_stop();
+				} else {
+					if (vh264_set_params(hw, param1,
+					param2, param3, param4, false) < 0) {
+						hw->init_flag = 0;
+						dpb_print(DECODE_ID(hw), 0, "set parameters error, init_flag: %u\n",
+							hw->init_flag);
+					}
+
+					WRITE_VREG(AV_SCRATCH_0, (hw->max_reference_size<<24) |
+						(hw->dpb.mDPB.size<<16) |
+						(hw->dpb.mDPB.size<<8));
+					hw->res_ch_flag = 0;
+					start_process_time(hw);
+					return;
+				}
+			}
+		} else {
+			if (vh264_set_params(hw, param1,
+				param2, param3, param4, false) < 0) {
+				hw->init_flag = 0;
+				dpb_print(DECODE_ID(hw), 0, "set parameters error, init_flag: %u\n",
+					hw->init_flag);
+			}
+
+			WRITE_VREG(AV_SCRATCH_0, (hw->max_reference_size<<24) |
+				(hw->dpb.mDPB.size<<16) |
+				(hw->dpb.mDPB.size<<8));
+			start_process_time(hw);
+			return;
+		}
+	} else
+	if (((hw->dec_result == DEC_RESULT_GET_DATA) ||
+		(hw->dec_result == DEC_RESULT_GET_DATA_RETRY))
+		&& (hw_to_vdec(hw)->next_status !=
+		VDEC_STATUS_DISCONNECTED)) {
+		if (!vdec_has_more_input(vdec)) {
+			hw->dec_result = DEC_RESULT_EOS;
+			vdec_schedule_work(&hw->work);
+			return;
+		}
+
+		if (hw->dec_result == DEC_RESULT_GET_DATA) {
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+				"%s DEC_RESULT_GET_DATA %x %x %x\n",
+				__func__,
+				READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+				READ_VREG(VLD_MEM_VIFIFO_WP),
+				READ_VREG(VLD_MEM_VIFIFO_RP));
+			mutex_lock(&hw->chunks_mutex);
+			vdec_vframe_dirty(vdec, hw->chunk);
+			hw->chunk = NULL;
+			mutex_unlock(&hw->chunks_mutex);
+			vdec_clean_input(vdec);
+		}
+		if ((hw->dec_result == DEC_RESULT_GET_DATA_RETRY) &&
+			((1000 * (jiffies - hw->get_data_start_time) / HZ)
+			> get_data_timeout_val)) {
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+				"%s DEC_RESULT_GET_DATA_RETRY timeout\n",
+				__func__);
+			goto result_done;
+		}
+		if (is_buffer_available(vdec)) {
+			int r;
+			int decode_size;
+			r = vdec_prepare_input(vdec, &hw->chunk);
+			if (r < 0 && (hw_to_vdec(hw)->next_status !=
+						VDEC_STATUS_DISCONNECTED)) {
+				hw->dec_result = DEC_RESULT_GET_DATA_RETRY;
+
+				dpb_print(DECODE_ID(hw),
+					PRINT_FLAG_VDEC_DETAIL,
+					"vdec_prepare_input: Insufficient data\n");
+				vdec_schedule_work(&hw->work);
+				return;
+			}
+			hw->dec_result = DEC_RESULT_NONE;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+				"%s: chunk size 0x%x\n",
+				__func__, hw->chunk->size);
+
+			if (dpb_is_debug(DECODE_ID(hw),
+				PRINT_FRAMEBASE_DATA)) {
+				int jj;
+				u8 *data = NULL;
+
+				if (!hw->chunk->block->is_mapped)
+					data = codec_mm_vmap(
+						hw->chunk->block->start +
+						hw->chunk->offset, r);
+				else
+					data = ((u8 *)
+						hw->chunk->block->start_virt)
+						+ hw->chunk->offset;
+
+				for (jj = 0; jj < r; jj++) {
+					if ((jj & 0xf) == 0)
+						dpb_print(DECODE_ID(hw),
+						PRINT_FRAMEBASE_DATA,
+							"%06x:", jj);
+					dpb_print_cont(DECODE_ID(hw),
+					PRINT_FRAMEBASE_DATA,
+						"%02x ", data[jj]);
+					if (((jj + 1) & 0xf) == 0)
+						dpb_print_cont(DECODE_ID(hw),
+						PRINT_FRAMEBASE_DATA,
+							"\n");
+				}
+
+				if (!hw->chunk->block->is_mapped)
+					codec_mm_unmap_phyaddr(data);
+			}
+			WRITE_VREG(POWER_CTL_VLD,
+				READ_VREG(POWER_CTL_VLD) |
+					(0 << 10) | (1 << 9) | (1 << 6));
+			WRITE_VREG(H264_DECODE_INFO, (1<<13));
+			decode_size = hw->chunk->size +
+				(hw->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+			WRITE_VREG(H264_DECODE_SIZE, decode_size);
+			WRITE_VREG(VIFF_BIT_CNT, decode_size * 8);
+			vdec_enable_input(vdec);
+
+			WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD);
+			start_process_time(hw);
+		} else{
+			if (hw_to_vdec(hw)->next_status
+				!=	VDEC_STATUS_DISCONNECTED) {
+				hw->dec_result = DEC_RESULT_GET_DATA_RETRY;
+				vdec_schedule_work(&hw->work);
+			}
+		}
+		return;
+	} else if (hw->dec_result == DEC_RESULT_DONE ||
+					hw->dec_result == DEC_RESULT_TIMEOUT) {
+		/* if (!hw->ctx_valid)
+			hw->ctx_valid = 1; */
+		hw->dec_again_cnt = 0;
+		if ((hw->dec_result == DEC_RESULT_TIMEOUT) &&
+				!hw->i_only && (error_proc_policy & 0x2)) {
+			struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+			dpb_print(DECODE_ID(hw), 0,
+				"%s, decode timeout flush dpb\n",
+				__func__);
+			flush_dpb(p_H264_Dpb);
+		}
+result_done:
+		{
+			if (error_proc_policy & 0x8000) {
+				struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+				int i;
+				struct DecodedPictureBuffer *p_Dpb = &p_H264_Dpb->mDPB;
+
+				for (i = 0; i < p_Dpb->used_size; i++) {
+					int i_flag = p_Dpb->fs[i]->bottom_field || p_Dpb->fs[i]->top_field;
+					int threshold = (i_flag || (hw->max_reference_size >= 12)) ? ((50 + p_Dpb->used_size) * 2)  : 50 + p_Dpb->used_size;
+					if ((p_Dpb->fs[i]->dpb_frame_count + threshold
+							< p_H264_Dpb->dpb_frame_count) &&
+						p_Dpb->fs[i]->is_reference &&
+						!p_Dpb->fs[i]->is_long_term &&
+						p_Dpb->fs[i]->is_output) {
+						dpb_print(DECODE_ID(hw),
+							0,
+							"unmark reference dpb_frame_count diffrence large in dpb\n");
+						unmark_for_reference(p_Dpb, p_Dpb->fs[i]);
+						update_ref_list(p_Dpb);
+					}
+				}
+			}
+		}
+			if (hw->mmu_enable
+				&& hw->frame_busy && hw->frame_done) {
+				long used_4k_num;
+				hevc_sao_wait_done(hw);
+				if (hw->hevc_cur_buf_idx != 0xffff) {
+					used_4k_num =
+					(READ_VREG(HEVC_SAO_MMU_STATUS) >> 16);
+				if (used_4k_num >= 0)
+					dpb_print(DECODE_ID(hw),
+					PRINT_FLAG_MMU_DETAIL,
+					"release unused buf , used_4k_num %ld index %d\n",
+					used_4k_num, hw->hevc_cur_buf_idx);
+				hevc_mmu_dma_check(hw_to_vdec(hw));
+				decoder_mmu_box_free_idx_tail(
+					hw->mmu_box,
+					hw->hevc_cur_buf_idx,
+					used_4k_num);
+					hw->hevc_cur_buf_idx = 0xffff;
+				}
+			}
+		decode_frame_count[DECODE_ID(hw)]++;
+		if (hw->dpb.mSlice.slice_type == I_SLICE) {
+			hw->gvs.i_decoded_frames++;
+		} else if (hw->dpb.mSlice.slice_type == P_SLICE) {
+			hw->gvs.p_decoded_frames++;
+		} else if (hw->dpb.mSlice.slice_type == B_SLICE) {
+			hw->gvs.b_decoded_frames++;
+		}
+		amvdec_stop();
+
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+			"%s dec_result %d %x %x %x\n",
+			__func__,
+			hw->dec_result,
+			READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+			READ_VREG(VLD_MEM_VIFIFO_WP),
+			READ_VREG(VLD_MEM_VIFIFO_RP));
+		mutex_lock(&hw->chunks_mutex);
+		vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk);
+		hw->chunk = NULL;
+		mutex_unlock(&hw->chunks_mutex);
+	} else if (hw->dec_result == DEC_RESULT_AGAIN) {
+		/*
+			stream base: stream buf empty or timeout
+			frame base: vdec_prepare_input fail
+		*/
+		if (!vdec_has_more_input(vdec) && (hw_to_vdec(hw)->next_status !=
+			VDEC_STATUS_DISCONNECTED) && (hw->no_decoder_buffer_flag == 0)) {
+			hw->dec_result = DEC_RESULT_EOS;
+			vdec_schedule_work(&hw->work);
+			return;
+		}
+
+		if ((vdec_stream_based(vdec)) &&
+			(error_proc_policy & 0x400000) &&
+			check_dirty_data(vdec)) {
+			hw->dec_result = DEC_RESULT_DONE;
+			vdec_schedule_work(&hw->work);
+			return;
+		}
+		hw->no_decoder_buffer_flag = 0;
+		hw->next_again_flag = 1;
+	} else if (hw->dec_result == DEC_RESULT_EOS) {
+		struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+			"%s: end of stream\n",
+			__func__);
+		amvdec_stop();
+		if (hw->mmu_enable)
+			amhevc_stop();
+		hw->eos = 1;
+		flush_dpb(p_H264_Dpb);
+		notify_v4l_eos(hw_to_vdec(hw));
+		mutex_lock(&hw->chunks_mutex);
+		vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk);
+		hw->chunk = NULL;
+		mutex_unlock(&hw->chunks_mutex);
+		vdec_clean_input(vdec);
+	} else if (hw->dec_result == DEC_RESULT_FORCE_EXIT) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+			"%s: force exit\n",
+			__func__);
+		amvdec_stop();
+		if (hw->mmu_enable)
+			amhevc_stop();
+		if (hw->stat & STAT_ISR_REG) {
+			vdec_free_irq(VDEC_IRQ_1, (void *)hw);
+			hw->stat &= ~STAT_ISR_REG;
+		}
+	}
+
+	if (p_H264_Dpb->mVideo.dec_picture) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+			"%s, release decoded picture\n", __func__);
+		release_cur_decoding_buf(hw);
+	}
+
+	WRITE_VREG(ASSIST_MBOX1_MASK, 0);
+	del_timer_sync(&hw->check_timer);
+	hw->stat &= ~STAT_TIMER_ARM;
+#ifdef DETECT_WRONG_MULTI_SLICE
+	if (hw->dec_result != DEC_RESULT_AGAIN)
+		hw->last_picture_slice_count = 0;
+#endif
+	ATRACE_COUNTER(hw->trace.decode_work_time_name, TRACE_WORK_WAIT_SEARCH_DONE_START);
+	wait_vmh264_search_done(hw);
+	ATRACE_COUNTER(hw->trace.decode_work_time_name, TRACE_WORK_WAIT_SEARCH_DONE_END);
+	/* mark itself has all HW resource released and input released */
+
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	if (hw->switch_dvlayer_flag) {
+		if (vdec->slave)
+			vdec_set_next_sched(vdec, vdec->slave);
+		else if (vdec->master)
+			vdec_set_next_sched(vdec, vdec->master);
+	} else if (vdec->slave || vdec->master)
+		vdec_set_next_sched(vdec, vdec);
+#endif
+
+	if (from == 1) {
+		/* This is a timeout work */
+		if (work_pending(&hw->work)) {
+			/*
+			 * The vh264_work arrives at the last second,
+			 * give it a chance to handle the scenario.
+			 */
+			return;
+		}
+	}
+	if (hw->dec_result == DEC_RESULT_DONE) {
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_WORKER_END);
+	}
+
+	/* mark itself has all HW resource released and input released */
+	if (vdec->parallel_dec == 1) {
+		if (hw->mmu_enable == 0)
+			vdec_core_finish_run(vdec, CORE_MASK_VDEC_1);
+		else
+			vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
+	} else
+		vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
+
+	wake_up_interruptible(&hw->wait_q);
+
+	if (hw->is_used_v4l) {
+		struct aml_vcodec_ctx *ctx =
+			(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+
+		if (ctx->param_sets_from_ucode &&
+			!hw->v4l_params_parsed)
+			vdec_v4l_write_frame_sync(ctx);
+	}
+
+	if (hw->vdec_cb)
+		hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg);
+}
+
+
+static void vh264_work(struct work_struct *work)
+{
+	struct vdec_h264_hw_s *hw = container_of(work,
+		struct vdec_h264_hw_s, work);
+	struct vdec_s *vdec = hw_to_vdec(hw);
+
+	vh264_work_implement(hw, vdec, 0);
+}
+
+
+static void vh264_timeout_work(struct work_struct *work)
+{
+	struct vdec_h264_hw_s *hw = container_of(work,
+		struct vdec_h264_hw_s, timeout_work);
+	struct vdec_s *vdec = hw_to_vdec(hw);
+
+	if (work_pending(&hw->work))
+		return;
+
+	hw->timeout_processing = 1;
+	vh264_work_implement(hw, vdec, 1);
+}
+
+static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
+{
+	bool ret = 0;
+	struct vdec_h264_hw_s *hw =
+		(struct vdec_h264_hw_s *)vdec->private;
+	int tvp = vdec_secure(hw_to_vdec(hw)) ?
+		CODEC_MM_FLAGS_TVP : 0;
+
+	if (hw->timeout_processing &&
+	    (work_pending(&hw->work) || work_busy(&hw->work) ||
+	    work_pending(&hw->timeout_work) || work_busy(&hw->timeout_work))) {
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL,
+			  "h264 work pending, not ready for run.\n");
+		return 0;
+	}
+	hw->timeout_processing = 0;
+	if (!hw->first_sc_checked && hw->mmu_enable) {
+		int size = decoder_mmu_box_sc_check(hw->mmu_box, tvp);
+		hw->first_sc_checked =1;
+		dpb_print(DECODE_ID(hw), 0,
+			"vmh264 cached=%d  need_size=%d speed= %d ms\n",
+			size, (hw->need_cache_size >> PAGE_SHIFT),
+			(int)(get_jiffies_64() - hw->sc_start_time) * 1000/HZ);
+	}
+
+	if (vdec_stream_based(vdec) && (hw->init_flag == 0)
+		&& pre_decode_buf_level != 0) {
+		u32 rp, wp, level;
+
+		rp = STBUF_READ(&vdec->vbuf, get_rp);
+		wp = STBUF_READ(&vdec->vbuf, get_wp);
+		if (wp < rp)
+			level = vdec->input.size + wp - rp;
+		else
+			level = wp - rp;
+
+		if (level < pre_decode_buf_level)
+			return 0;
+	}
+
+#ifndef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	if (vdec->master)
+		return 0;
+#endif
+	if (hw->eos)
+		return 0;
+
+	if (hw->stat & DECODER_FATAL_ERROR_NO_MEM)
+		return 0;
+
+	if (disp_vframe_valve_level &&
+		kfifo_len(&hw->display_q) >=
+		disp_vframe_valve_level) {
+		hw->valve_count--;
+		if (hw->valve_count <= 0)
+			hw->valve_count = 2;
+		else
+			return 0;
+	}
+	if (hw->next_again_flag &&
+		(!vdec_frame_based(vdec))) {
+		u32 parser_wr_ptr = STBUF_READ(&vdec->vbuf, get_wp);
+		if (parser_wr_ptr >= hw->pre_parser_wr_ptr &&
+			(parser_wr_ptr - hw->pre_parser_wr_ptr) <
+			again_threshold) {
+			int r = vdec_sync_input(vdec);
+				dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL,
+					"%s buf lelvel:%x\n",  __func__, r);
+			return 0;
+		}
+	}
+
+	if (h264_debug_flag & 0x20000000) {
+		/* pr_info("%s, a\n", __func__); */
+		ret = 1;
+	} else
+		ret = is_buffer_available(vdec);
+
+#ifdef CONSTRAIN_MAX_BUF_NUM
+	if (ret && (hw->dpb.mDPB.size > 0)) { /*make sure initilized*/
+		if (run_ready_max_vf_only_num > 0 &&
+			get_vf_ref_only_buf_count(hw) >=
+			run_ready_max_vf_only_num
+			)
+			ret = 0;
+		if (run_ready_display_q_num > 0 &&
+			kfifo_len(&hw->display_q) >=
+			run_ready_display_q_num)
+			ret = 0;
+		/*avoid more buffers consumed when
+		switching resolution*/
+		if (run_ready_max_buf_num == 0xff &&
+			get_used_buf_count(hw) >
+			hw->dpb.mDPB.size)
+			ret = 0;
+		else if (run_ready_max_buf_num &&
+			get_used_buf_count(hw) >=
+			run_ready_max_buf_num)
+			ret = 0;
+		if (ret == 0)
+			bufmgr_h264_remove_unused_frame(&hw->dpb, 0);
+	}
+#endif
+	if (hw->is_used_v4l) {
+		struct aml_vcodec_ctx *ctx =
+			(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+
+		if (ctx->param_sets_from_ucode) {
+			if (hw->v4l_params_parsed) {
+				if (ctx->cap_pool.dec < hw->dpb.mDPB.size) {
+					if (is_buffer_available(vdec))
+						ret = 1;
+					else
+						ret = 0;
+				}
+			} else {
+				if (ctx->v4l_resolution_change)
+					ret = 0;
+			}
+		} else if (!ctx->v4l_codec_dpb_ready) {
+			if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
+				run_ready_min_buf_num)
+				ret = 0;
+		}
+	}
+
+	if (ret)
+		not_run_ready[DECODE_ID(hw)] = 0;
+	else
+		not_run_ready[DECODE_ID(hw)]++;
+	if (vdec->parallel_dec == 1) {
+		if (hw->mmu_enable == 0)
+			return ret ? (CORE_MASK_VDEC_1) : 0;
+		else
+			return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0;
+	} else
+		return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0;
+}
+
+static unsigned char get_data_check_sum
+	(struct vdec_h264_hw_s *hw, int size)
+{
+	int jj;
+	int sum = 0;
+	u8 *data = NULL;
+
+	if (!hw->chunk->block->is_mapped)
+		data = codec_mm_vmap(hw->chunk->block->start +
+			hw->chunk->offset, size);
+	else
+		data = ((u8 *)hw->chunk->block->start_virt)
+			+ hw->chunk->offset;
+
+	for (jj = 0; jj < size; jj++)
+		sum += data[jj];
+
+	if (!hw->chunk->block->is_mapped)
+		codec_mm_unmap_phyaddr(data);
+	return sum;
+}
+
+static void run(struct vdec_s *vdec, unsigned long mask,
+	void (*callback)(struct vdec_s *, void *), void *arg)
+{
+	struct vdec_h264_hw_s *hw =
+		(struct vdec_h264_hw_s *)vdec->private;
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	int size, ret = -1;
+	if (!hw->vdec_pg_enable_flag) {
+		hw->vdec_pg_enable_flag = 1;
+		amvdec_enable();
+		if (hw->mmu_enable)
+			amhevc_enable();
+	}
+	ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_RUN_START);
+
+	run_count[DECODE_ID(hw)]++;
+	vdec_reset_core(vdec);
+	if (hw->mmu_enable)
+		hevc_reset_core(vdec);
+	hw->vdec_cb_arg = arg;
+	hw->vdec_cb = callback;
+
+#ifdef DETECT_WRONG_MULTI_SLICE
+	hw->cur_picture_slice_count = 0;
+#endif
+
+	if (kfifo_len(&hw->display_q) > VF_POOL_SIZE) {
+		hw->reset_bufmgr_flag = 1;
+		dpb_print(DECODE_ID(hw), 0,
+			"kfifo len:%d invaild, need bufmgr reset\n",
+			kfifo_len(&hw->display_q));
+	}
+
+	if (vdec_stream_based(vdec)) {
+		hw->pre_parser_wr_ptr =
+			STBUF_READ(&vdec->vbuf, get_wp);
+		hw->next_again_flag = 0;
+	}
+
+	if (hw->reset_bufmgr_flag ||
+		((error_proc_policy & 0x40) &&
+		p_H264_Dpb->buf_alloc_fail)) {
+		h264_reset_bufmgr(vdec);
+		//flag must clear after reset for v4l buf_spec_init use
+		hw->reset_bufmgr_flag = 0;
+	}
+
+	if (h264_debug_cmd & 0xf000) {
+		if (((h264_debug_cmd >> 12) & 0xf)
+			== (DECODE_ID(hw) + 1)) {
+			h264_reconfig(hw);
+			h264_debug_cmd &= (~0xf000);
+		}
+	}
+	/* hw->chunk = vdec_prepare_input(vdec); */
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	if (vdec->slave || vdec->master)
+		vdec_set_flag(vdec, VDEC_FLAG_SELF_INPUT_CONTEXT);
+#endif
+	size = vdec_prepare_input(vdec, &hw->chunk);
+	if ((size < 0) ||
+		(input_frame_based(vdec) && hw->chunk == NULL)) {
+		input_empty[DECODE_ID(hw)]++;
+		hw->dec_result = DEC_RESULT_AGAIN;
+
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_DETAIL,
+			"vdec_prepare_input: Insufficient data\n");
+
+		vdec_schedule_work(&hw->work);
+		return;
+	}
+	input_empty[DECODE_ID(hw)] = 0;
+
+	hw->dec_result = DEC_RESULT_NONE;
+	hw->get_data_count = 0;
+	hw->csd_change_flag = 0;
+#if 0
+	pr_info("VLD_MEM_VIFIFO_LEVEL = 0x%x, rp = 0x%x, wp = 0x%x\n",
+		READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+		READ_VREG(VLD_MEM_VIFIFO_RP),
+		READ_VREG(VLD_MEM_VIFIFO_WP));
+#endif
+
+	if (input_frame_based(vdec) && !vdec_secure(vdec)) {
+		u8 *data = NULL;
+
+		if (!hw->chunk->block->is_mapped)
+			data = codec_mm_vmap(hw->chunk->block->start +
+				hw->chunk->offset, size);
+		else
+			data = ((u8 *)hw->chunk->block->start_virt)
+				+ hw->chunk->offset;
+
+		if (dpb_is_debug(DECODE_ID(hw),
+			PRINT_FLAG_VDEC_STATUS)
+			) {
+			dpb_print(DECODE_ID(hw), 0,
+			"%s: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n",
+			__func__, size, get_data_check_sum(hw, size),
+			data[0], data[1], data[2], data[3],
+			data[4], data[5], data[size - 4],
+			data[size - 3],	data[size - 2],
+			data[size - 1]);
+		}
+		if (dpb_is_debug(DECODE_ID(hw),
+			PRINT_FRAMEBASE_DATA)
+			) {
+			int jj;
+
+			for (jj = 0; jj < size; jj++) {
+				if ((jj & 0xf) == 0)
+					dpb_print(DECODE_ID(hw),
+					PRINT_FRAMEBASE_DATA,
+						"%06x:", jj);
+				dpb_print_cont(DECODE_ID(hw),
+				PRINT_FRAMEBASE_DATA,
+					"%02x ", data[jj]);
+				if (((jj + 1) & 0xf) == 0)
+					dpb_print_cont(DECODE_ID(hw),
+					PRINT_FRAMEBASE_DATA,
+						"\n");
+			}
+		}
+
+		if (!hw->chunk->block->is_mapped)
+			codec_mm_unmap_phyaddr(data);
+	} else
+		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+			"%s: %x %x %x %x %x size 0x%x\n",
+			__func__,
+			READ_VREG(VLD_MEM_VIFIFO_LEVEL),
+			READ_VREG(VLD_MEM_VIFIFO_WP),
+			READ_VREG(VLD_MEM_VIFIFO_RP),
+			STBUF_READ(&vdec->vbuf, get_rp),
+			STBUF_READ(&vdec->vbuf, get_wp),
+			size);
+
+	start_process_time(hw);
+	if (vdec->mc_loaded) {
+			/*firmware have load before,
+			  and not changes to another.
+			  ignore reload.
+			*/
+		WRITE_VREG(AV_SCRATCH_G, hw->reg_g_status);
+	} else {
+		ATRACE_COUNTER(hw->trace.decode_run_time_name, TRACE_RUN_LOADING_FW_START);
+		ret = amvdec_vdec_loadmc_ex(VFORMAT_H264, "mh264", vdec, hw->fw->data);
+		if (ret < 0) {
+			amvdec_enable_flag = false;
+			amvdec_disable();
+			hw->vdec_pg_enable_flag = 0;
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
+				"MH264 the %s fw loading failed, err: %x\n",
+				tee_enabled() ? "TEE" : "local", ret);
+			hw->dec_result = DEC_RESULT_FORCE_EXIT;
+			vdec_schedule_work(&hw->work);
+			return;
+		}
+		vdec->mc_type  = VFORMAT_H264;
+		hw->reg_g_status = READ_VREG(AV_SCRATCH_G);
+		if (hw->mmu_enable) {
+			ret = amhevc_loadmc_ex(VFORMAT_H264, "mh264_mmu",
+				hw->fw_mmu->data);
+			if (ret < 0) {
+				amvdec_enable_flag = false;
+				amhevc_disable();
+				dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
+					"MH264_MMU the %s fw loading failed, err: %x\n",
+					tee_enabled() ? "TEE" : "local", ret);
+				hw->dec_result = DEC_RESULT_FORCE_EXIT;
+				vdec_schedule_work(&hw->work);
+				return;
+			}
+			vdec->mc_type = ((1 << 16) | VFORMAT_H264);
+		}
+		vdec->mc_loaded = 0;
+		ATRACE_COUNTER(hw->trace.decode_run_time_name, TRACE_RUN_LOADING_FW_END);
+	}
+	vmh264_reset_udr_mgr(hw);
+	ATRACE_COUNTER(hw->trace.decode_run_time_name, TRACE_RUN_LOADING_RESTORE_START);
+	if (vh264_hw_ctx_restore(hw) < 0) {
+		vdec_schedule_work(&hw->work);
+		return;
+	}
+	if (error_proc_policy & 0x10000) {
+		hw->first_pre_frame_num = p_H264_Dpb->mVideo.pre_frame_num;
+	}
+	ATRACE_COUNTER(hw->trace.decode_run_time_name, TRACE_RUN_LOADING_RESTORE_END);
+	if (input_frame_based(vdec)) {
+		int decode_size = 0;
+
+		decode_size = hw->chunk->size +
+			(hw->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+		WRITE_VREG(H264_DECODE_INFO, (1<<13));
+		WRITE_VREG(H264_DECODE_SIZE, decode_size);
+		WRITE_VREG(VIFF_BIT_CNT, decode_size * 8);
+		if (vdec->mvfrm)
+			vdec->mvfrm->frame_size = hw->chunk->size;
+	} else {
+		if (size <= 0)
+			size = 0x7fffffff; /*error happen*/
+		WRITE_VREG(H264_DECODE_INFO, (1<<13));
+		WRITE_VREG(H264_DECODE_SIZE, size);
+		WRITE_VREG(VIFF_BIT_CNT, size * 8);
+		hw->start_bit_cnt = size * 8;
+	}
+	config_aux_buf(hw);
+	config_decode_mode(hw);
+	vdec_enable_input(vdec);
+	WRITE_VREG(NAL_SEARCH_CTL, 0);
+	hw->sei_data_len = 0;
+	if (enable_itu_t35)
+		WRITE_VREG(NAL_SEARCH_CTL, READ_VREG(NAL_SEARCH_CTL) | 0x1);
+	if (!hw->init_flag) {
+		if (hw->mmu_enable)
+			WRITE_VREG(NAL_SEARCH_CTL,
+					READ_VREG(NAL_SEARCH_CTL) | 0x2);
+		else
+			WRITE_VREG(NAL_SEARCH_CTL,
+					READ_VREG(NAL_SEARCH_CTL) & (~0x2));
+	}
+	WRITE_VREG(NAL_SEARCH_CTL, READ_VREG(NAL_SEARCH_CTL) | (1 << 2) | (hw->bitstream_restriction_flag << 15));
+
+	if (udebug_flag)
+		WRITE_VREG(AV_SCRATCH_K, udebug_flag);
+	hw->stat |= STAT_TIMER_ARM;
+	mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL);
+
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
+
+		if (hw->mmu_enable)
+			SET_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3);
+		else
+			CLEAR_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3);
+	}
+	if (vdec->mvfrm)
+		vdec->mvfrm->hw_decode_start = local_clock();
+	amvdec_start();
+	if (hw->mmu_enable /*&& !hw->frame_busy && !hw->frame_done*/) {
+		WRITE_VREG(HEVC_ASSIST_SCRATCH_0, 0x0);
+		amhevc_start();
+		if (hw->config_bufmgr_done) {
+			hevc_mcr_sao_global_hw_init(hw,
+					(hw->mb_width << 4), (hw->mb_height << 4));
+			hevc_mcr_config_canv2axitbl(hw, 1);
+		}
+	}
+
+	/* if (hw->init_flag) { */
+		WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD);
+	/* } */
+
+	hw->init_flag = 1;
+	ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_RUN_END);
+}
+
+static void clear_refer_bufs(struct vdec_h264_hw_s *hw)
+{
+	int i;
+	ulong flags;
+
+	if (hw->is_used_v4l) {
+		spin_lock_irqsave(&hw->bufspec_lock, flags);
+		for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+			hw->buffer_spec[i].used = -1;
+			hw->buffer_spec[i].cma_alloc_addr = 0;
+			hw->buffer_spec[i].buf_adr = 0;
+		}
+		spin_unlock_irqrestore(&hw->bufspec_lock, flags);
+	}
+
+	INIT_KFIFO(hw->display_q);
+	INIT_KFIFO(hw->newframe_q);
+
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]);
+		hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */
+		hw->vfpool[hw->cur_pool][i].bufWidth = 1920;
+		kfifo_put(&hw->newframe_q, vf);
+	}
+}
+
+static void reset(struct vdec_s *vdec)
+{
+	struct vdec_h264_hw_s *hw =
+		(struct vdec_h264_hw_s *)vdec->private;
+
+	pr_info("vmh264 reset\n");
+
+	cancel_work_sync(&hw->work);
+	cancel_work_sync(&hw->notify_work);
+	if (hw->stat & STAT_VDEC_RUN) {
+		amvdec_stop();
+		if (hw->mmu_enable)
+			amhevc_stop();
+		hw->stat &= ~STAT_VDEC_RUN;
+	}
+
+	if (hw->stat & STAT_TIMER_ARM) {
+		del_timer_sync(&hw->check_timer);
+		hw->stat &= ~STAT_TIMER_ARM;
+	}
+	hw->eos = 0;
+	hw->decode_pic_count = 0;
+
+	reset_process_time(hw);
+	h264_reset_bufmgr(vdec);
+	clear_refer_bufs(hw);
+
+	dpb_print(DECODE_ID(hw), 0, "%s\n", __func__);
+}
+
+static void h264_reconfig(struct vdec_h264_hw_s *hw)
+{
+	int i;
+	unsigned long flags;
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	struct vdec_s *vdec = hw_to_vdec(hw);
+	dpb_print(DECODE_ID(hw), 0,
+	"%s\n", __func__);
+	/* after calling flush_dpb() and bufmgr_h264_remove_unused_frame(),
+		all buffers are in display queue (used == 2),
+			or free (used == 0)
+	*/
+	if (dpb_is_debug(DECODE_ID(hw),
+		PRINT_FLAG_DUMP_BUFSPEC))
+		dump_bufspec(hw, "pre h264_reconfig");
+
+	flush_dpb(p_H264_Dpb);
+	bufmgr_h264_remove_unused_frame(p_H264_Dpb, 0);
+
+	if (hw->collocate_cma_alloc_addr) {
+		decoder_bmmu_box_free_idx(
+			hw->bmmu_box,
+			BMMU_REF_IDX);
+		hw->collocate_cma_alloc_addr = 0;
+		hw->dpb.colocated_mv_addr_start = 0;
+		hw->dpb.colocated_mv_addr_end = 0;
+	}
+	spin_lock_irqsave(&hw->bufspec_lock, flags);
+	for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+		if (vdec->parallel_dec == 1) {
+			vdec->free_canvas_ex(hw->buffer_spec[i].y_canvas_index, vdec->id);
+			vdec->free_canvas_ex(hw->buffer_spec[i].u_canvas_index, vdec->id);
+			vdec->free_canvas_ex(hw->buffer_spec[i].v_canvas_index, vdec->id);
+			hw->buffer_spec[i].y_canvas_index = -1;
+			hw->buffer_spec[i].u_canvas_index = -1;
+			hw->buffer_spec[i].v_canvas_index = -1;
+#ifdef VDEC_DW
+			if (IS_VDEC_DW(hw)) {
+				vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_y_canvas_index, vdec->id);
+				vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_u_canvas_index, vdec->id);
+				vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_v_canvas_index, vdec->id);
+				hw->buffer_spec[i].vdec_dw_y_canvas_index = -1;
+				hw->buffer_spec[i].vdec_dw_u_canvas_index = -1;
+				hw->buffer_spec[i].vdec_dw_v_canvas_index = -1;
+#endif
+			}
+		}
+		/*make sure buffers not put back to bufmgr when
+			vf_put is called*/
+		if (hw->buffer_spec[i].used == 2)
+			hw->buffer_spec[i].used = 3;
+
+		/* ready to release "free buffers"
+		*/
+		if (hw->buffer_spec[i].used == 0)
+			hw->buffer_spec[i].used = 4;
+
+		hw->buffer_spec[i].canvas_pos = -1;
+
+		if (hw->buffer_spec[i].used == 4 &&
+			hw->buffer_spec[i].vf_ref != 0 &&
+			hw->buffer_spec[i].cma_alloc_addr) {
+			hw->buffer_spec[i].used = 3;
+		}
+	}
+	spin_unlock_irqrestore(&hw->bufspec_lock, flags);
+	hw->has_i_frame = 0;
+	hw->config_bufmgr_done = 0;
+
+	if (hw->is_used_v4l) {
+		mutex_lock(&vmh264_mutex);
+		dealloc_buf_specs(hw, 1);
+		mutex_unlock(&vmh264_mutex);
+	}
+
+	if (dpb_is_debug(DECODE_ID(hw),
+		PRINT_FLAG_DUMP_BUFSPEC))
+		dump_bufspec(hw, "after h264_reconfig");
+}
+
+#ifdef ERROR_HANDLE_TEST
+static void h264_clear_dpb(struct vdec_h264_hw_s *hw)
+{
+	int i;
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
+		"%s\n", __func__);
+	remove_dpb_pictures(p_H264_Dpb);
+	for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+		/*make sure buffers not put back to bufmgr when
+			vf_put is called*/
+		if (hw->buffer_spec[i].used == 2)
+			hw->buffer_spec[i].used = 5;
+	}
+
+}
+#endif
+
+static void h264_reset_bufmgr(struct vdec_s *vdec)
+{
+	ulong timeout;
+	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+#if 0
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	int actual_dpb_size, max_reference_size;
+	int reorder_pic_num;
+	unsigned int colocated_buf_size;
+	unsigned int colocated_mv_addr_start;
+	unsigned int colocated_mv_addr_end;
+	dpb_print(DECODE_ID(hw), 0,
+	"%s\n", __func__);
+
+	for (i = 0; i < VF_POOL_SIZE; i++)
+		hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */
+
+	actual_dpb_size = p_H264_Dpb->mDPB.size;
+	max_reference_size = p_H264_Dpb->max_reference_size;
+	reorder_pic_num = p_H264_Dpb->reorder_pic_num;
+
+	colocated_buf_size = p_H264_Dpb->colocated_buf_size;
+	colocated_mv_addr_start = p_H264_Dpb->colocated_mv_addr_start;
+	colocated_mv_addr_end  = p_H264_Dpb->colocated_mv_addr_end;
+
+	hw->cur_pool++;
+	if (hw->cur_pool >= VF_POOL_NUM)
+		hw->cur_pool = 0;
+
+	INIT_KFIFO(hw->display_q);
+	INIT_KFIFO(hw->newframe_q);
+
+	for (i = 0; i < VF_POOL_SIZE; i++) {
+		const struct vframe_s *vf = &(hw->vfpool[hw->cur_pool][i]);
+		hw->vfpool[hw->cur_pool][i].index = -1; /* VF_BUF_NUM; */
+		hw->vfpool[hw->cur_pool][i].bufWidth = 1920;
+		kfifo_put(&hw->newframe_q, vf);
+	}
+
+	for (i = 0; i < BUFSPEC_POOL_SIZE; i++)
+		hw->buffer_spec[i].used = 0;
+
+	dpb_init_global(&hw->dpb,
+		DECODE_ID(hw), 0, 0);
+	p_H264_Dpb->mDPB.size = actual_dpb_size;
+	p_H264_Dpb->max_reference_size = max_reference_size;
+	p_H264_Dpb->reorder_pic_num = reorder_pic_num;
+
+	p_H264_Dpb->colocated_buf_size = colocated_buf_size;
+	p_H264_Dpb->colocated_mv_addr_start = colocated_mv_addr_start;
+	p_H264_Dpb->colocated_mv_addr_end  = colocated_mv_addr_end;
+
+	p_H264_Dpb->fast_output_enable = fast_output_enable;
+	hw->has_i_frame = 0;
+#else
+	dpb_print(DECODE_ID(hw), 0,
+	"%s frame count %d to skip %d\n\n",
+	__func__, hw->decode_pic_count+1,
+	hw->skip_frame_count);
+
+	flush_dpb(&hw->dpb);
+
+	if (!hw->is_used_v4l) {
+		timeout = jiffies + HZ;
+		while (kfifo_len(&hw->display_q) > 0) {
+			if (time_after(jiffies, timeout))
+				break;
+			schedule();
+		}
+	}
+
+	buf_spec_init(hw, true);
+
+	vh264_local_init(hw, true);
+	/*hw->decode_pic_count = 0;
+	hw->seq_info2 = 0;*/
+
+	if (vh264_set_params(hw,
+		hw->cfg_param1,
+		hw->cfg_param2,
+		hw->cfg_param3,
+		hw->cfg_param4, true) < 0)
+		hw->stat |= DECODER_FATAL_ERROR_SIZE_OVERFLOW;
+	else
+		hw->stat &= (~DECODER_FATAL_ERROR_SIZE_OVERFLOW);
+
+	/*drop 3 frames after reset bufmgr if bit0 is set 1 */
+	if (first_i_policy & 0x01)
+		hw->first_i_policy = (3 << 8) | first_i_policy;
+
+	p_H264_Dpb->first_insert_frame = FirstInsertFrm_RESET;
+
+	if (hw->stat & DECODER_FATAL_ERROR_SIZE_OVERFLOW)
+		hw->init_flag = 0;
+	else
+		hw->init_flag = 1;
+
+	hw->reset_bufmgr_count++;
+#endif
+}
+
+int ammvdec_h264_mmu_init(struct vdec_h264_hw_s *hw)
+{
+	int ret = -1;
+	int tvp_flag = vdec_secure(hw_to_vdec(hw)) ?
+		CODEC_MM_FLAGS_TVP : 0;
+	int buf_size = 64;
+
+	pr_debug("ammvdec_h264_mmu_init tvp = 0x%x mmu_enable %d\n",
+			tvp_flag, hw->mmu_enable);
+	hw->need_cache_size = buf_size * SZ_1M;
+	hw->sc_start_time = get_jiffies_64();
+	if (hw->mmu_enable && !hw->mmu_box) {
+		hw->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME,
+				hw->id,
+				MMU_MAX_BUFFERS,
+				hw->need_cache_size,
+				tvp_flag);
+		if (!hw->mmu_box) {
+			pr_err("h264 4k alloc mmu box failed!!\n");
+			return -1;
+		}
+		ret = 0;
+	}
+	if (!hw->bmmu_box) {
+		hw->bmmu_box = decoder_bmmu_box_alloc_box(
+			DRIVER_NAME,
+			hw->id,
+			BMMU_MAX_BUFFERS,
+			4 + PAGE_SHIFT,
+			CODEC_MM_FLAGS_CMA_CLEAR |
+			CODEC_MM_FLAGS_FOR_VDECODER |
+			tvp_flag);
+		if (hw->bmmu_box)
+			ret = 0;
+	}
+	return ret;
+}
+int ammvdec_h264_mmu_release(struct vdec_h264_hw_s *hw)
+{
+	if (hw->mmu_box) {
+		decoder_mmu_box_free(hw->mmu_box);
+		hw->mmu_box = NULL;
+	}
+	if (hw->bmmu_box) {
+		decoder_bmmu_box_free(hw->bmmu_box);
+		hw->bmmu_box = NULL;
+	}
+	return 0;
+}
+
+static int ammvdec_h264_probe(struct platform_device *pdev)
+{
+	struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
+	struct vdec_h264_hw_s *hw = NULL;
+	char *tmpbuf;
+	int config_val;
+	if (pdata == NULL) {
+		pr_info("\nammvdec_h264 memory resource undefined.\n");
+		return -EFAULT;
+	}
+
+	hw = (struct vdec_h264_hw_s *)h264_alloc_hw_stru(&pdev->dev,
+		sizeof(struct vdec_h264_hw_s), GFP_KERNEL);
+	if (hw == NULL) {
+		pr_info("\nammvdec_h264 device data allocation failed\n");
+		return -ENOMEM;
+	}
+	hw->id = pdev->id;
+	hw->platform_dev = pdev;
+
+	snprintf(hw->trace.vdec_name, sizeof(hw->trace.vdec_name),
+		"h264-%d", hw->id);
+	snprintf(hw->trace.pts_name, sizeof(hw->trace.pts_name),
+		"%s-pts", hw->trace.vdec_name);
+	snprintf(hw->trace.new_q_name, sizeof(hw->trace.new_q_name),
+		"%s-newframe_q", hw->trace.vdec_name);
+	snprintf(hw->trace.disp_q_name, sizeof(hw->trace.disp_q_name),
+		"%s-dispframe_q", hw->trace.vdec_name);
+	snprintf(hw->trace.decode_time_name, sizeof(hw->trace.decode_time_name),
+		"decoder_time%d", pdev->id);
+	snprintf(hw->trace.decode_run_time_name, sizeof(hw->trace.decode_run_time_name),
+		"decoder_run_time%d", pdev->id);
+	snprintf(hw->trace.decode_header_time_name, sizeof(hw->trace.decode_header_time_name),
+		"decoder_header_time%d", pdev->id);
+	snprintf(hw->trace.decode_work_time_name, sizeof(hw->trace.decode_work_time_name),
+		"decoder_work_time%d", pdev->id);
+
+	/* the ctx from v4l2 driver. */
+	hw->v4l2_ctx = pdata->private;
+
+	platform_set_drvdata(pdev, pdata);
+
+	hw->mmu_enable = 0;
+	hw->first_head_check_flag = 0;
+
+	if (pdata->sys_info)
+		hw->vh264_amstream_dec_info = *pdata->sys_info;
+
+	if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5)
+		force_enable_mmu = 1;
+
+	if (force_enable_mmu && pdata->sys_info &&
+		    (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) &&
+		    (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXLX) &&
+			(pdata->sys_info->height * pdata->sys_info->width
+			> 1920 * 1088))
+			hw->mmu_enable = 1;
+
+	if (hw->mmu_enable &&
+		(pdata->frame_base_video_path == FRAME_BASE_PATH_IONVIDEO)) {
+		hw->mmu_enable = 0;
+		pr_info("ionvideo needs disable mmu, path= %d \n",
+				pdata->frame_base_video_path);
+	}
+
+	if (ammvdec_h264_mmu_init(hw)) {
+		h264_free_hw_stru(&pdev->dev, (void *)hw);
+		pr_info("\nammvdec_h264 mmu alloc failed!\n");
+		return -ENOMEM;
+	}
+
+	if (pdata->config_len) {
+		dpb_print(DECODE_ID(hw), 0, "pdata->config=%s\n", pdata->config);
+		/*use ptr config for doubel_write_mode, etc*/
+		if (get_config_int(pdata->config,
+			"mh264_double_write_mode", &config_val) == 0)
+			hw->double_write_mode = config_val;
+		else
+			hw->double_write_mode = double_write_mode;
+
+		if (get_config_int(pdata->config,
+			"parm_v4l_codec_enable",
+			&config_val) == 0)
+			hw->is_used_v4l = config_val;
+
+		if (get_config_int(pdata->config,
+			"parm_v4l_buffer_margin",
+			&config_val) == 0)
+			hw->reorder_dpb_size_margin = config_val;
+
+		if (get_config_int(pdata->config,
+			"parm_v4l_canvas_mem_mode",
+			&config_val) == 0)
+			hw->canvas_mode = config_val;
+		if (get_config_int(pdata->config,
+			"parm_v4l_low_latency_mode",
+			&config_val) == 0)
+			hw->low_latency_mode = config_val ? 0x8:0;
+		if (get_config_int(pdata->config, "sidebind_type",
+				&config_val) == 0)
+			hw->sidebind_type = config_val;
+
+		if (get_config_int(pdata->config, "sidebind_channel_id",
+				&config_val) == 0)
+			hw->sidebind_channel_id = config_val;
+
+		if (get_config_int(pdata->config,
+			"parm_enable_fence",
+			&config_val) == 0)
+			hw->enable_fence = config_val;
+
+		if (get_config_int(pdata->config,
+			"parm_fence_usage",
+			&config_val) == 0)
+			hw->fence_usage = config_val;
+
+		if (get_config_int(pdata->config,
+			"negative_dv",
+			&config_val) == 0) {
+			hw->discard_dv_data = config_val;
+			dpb_print(DECODE_ID(hw), 0, "discard dv data\n");
+		}
+
+		if (get_config_int(pdata->config,
+			"parm_v4l_metadata_config_flag",
+			&config_val) == 0) {
+			hw->metadata_config_flag = config_val;
+			hw->discard_dv_data = hw->metadata_config_flag & VDEC_CFG_FLAG_DV_NEGATIVE;
+			if (hw->discard_dv_data)
+				dpb_print(DECODE_ID(hw), 0, "discard dv data\n");
+		}
+
+	} else
+		hw->double_write_mode = double_write_mode;
+
+	if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5)
+		hw->double_write_mode = 3;
+
+	if (force_config_fence) {
+		hw->enable_fence = true;
+		hw->fence_usage = (force_config_fence >> 4) & 0xf;
+		if (force_config_fence & 0x2)
+			hw->enable_fence = false;
+		dpb_print(DECODE_ID(hw), 0,
+			"enable fence: %d, fence usage: %d\n",
+			hw->enable_fence, hw->fence_usage);
+	}
+
+	if (!hw->is_used_v4l) {
+		hw->reorder_dpb_size_margin = reorder_dpb_size_margin;
+		hw->canvas_mode = mem_map_mode;
+
+		if ((h264_debug_flag & IGNORE_PARAM_FROM_CONFIG) == 0)
+			hw->canvas_mode = pdata->canvas_mode;
+	}
+
+	if (hw->mmu_enable) {
+			hw->canvas_mode = CANVAS_BLKMODE_LINEAR;
+			hw->double_write_mode &= 0xffff;
+	}
+
+	if (pdata->parallel_dec == 1) {
+		int i;
+		for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+			hw->buffer_spec[i].y_canvas_index = -1;
+			hw->buffer_spec[i].u_canvas_index = -1;
+			hw->buffer_spec[i].v_canvas_index = -1;
+#ifdef VDEC_DW
+			if (IS_VDEC_DW(hw)) {
+				hw->buffer_spec[i].vdec_dw_y_canvas_index = -1;
+				hw->buffer_spec[i].vdec_dw_u_canvas_index = -1;
+				hw->buffer_spec[i].vdec_dw_v_canvas_index = -1;
+			}
+#endif
+		}
+	}
+
+	dpb_print(DECODE_ID(hw), 0,
+		"%s mmu_enable %d double_write_mode 0x%x\n",
+		__func__, hw->mmu_enable, hw->double_write_mode);
+
+	pdata->private = hw;
+	pdata->dec_status = dec_status;
+	pdata->set_trickmode = vmh264_set_trickmode;
+	pdata->run_ready = run_ready;
+	pdata->run = run;
+	pdata->reset = reset;
+	pdata->irq_handler = vh264_isr;
+	pdata->threaded_irq_handler = vh264_isr_thread_fn;
+	pdata->dump_state = vmh264_dump_state;
+
+#ifdef MH264_USERDATA_ENABLE
+	pdata->wakeup_userdata_poll = vmh264_wakeup_userdata_poll;
+	pdata->user_data_read = vmh264_user_data_read;
+	pdata->reset_userdata_fifo = vmh264_reset_userdata_fifo;
+#else
+	pdata->wakeup_userdata_poll = NULL;
+	pdata->user_data_read = NULL;
+	pdata->reset_userdata_fifo = NULL;
+#endif
+	if (pdata->use_vfm_path) {
+		snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
+			VFM_DEC_PROVIDER_NAME);
+		hw->frameinfo_enable = 1;
+	}
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	else if (vdec_dual(pdata)) {
+		if (!pdata->is_stream_mode_dv_multi) {
+			if (dv_toggle_prov_name) /*debug purpose*/
+				snprintf(pdata->vf_provider_name,
+				VDEC_PROVIDER_NAME_SIZE,
+					(pdata->master) ? VFM_DEC_DVBL_PROVIDER_NAME :
+					VFM_DEC_DVEL_PROVIDER_NAME);
+			else
+				snprintf(pdata->vf_provider_name,
+				VDEC_PROVIDER_NAME_SIZE,
+					(pdata->master) ? VFM_DEC_DVEL_PROVIDER_NAME :
+					VFM_DEC_DVBL_PROVIDER_NAME);
+		} else {
+			if (dv_toggle_prov_name) /*debug purpose*/
+				snprintf(pdata->vf_provider_name,
+				VDEC_PROVIDER_NAME_SIZE,
+					(pdata->master) ? VFM_DEC_DVBL_PROVIDER_NAME2 :
+					VFM_DEC_DVEL_PROVIDER_NAME2);
+			else
+				snprintf(pdata->vf_provider_name,
+				VDEC_PROVIDER_NAME_SIZE,
+					(pdata->master) ? VFM_DEC_DVEL_PROVIDER_NAME2 :
+					VFM_DEC_DVBL_PROVIDER_NAME2);
+		}
+	}
+#endif
+	else
+		snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
+			PROVIDER_NAME ".%02x", pdev->id & 0xff);
+
+	if (!hw->is_used_v4l)
+		vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
+			&vf_provider_ops, pdata);
+
+	platform_set_drvdata(pdev, pdata);
+
+	buf_spec_init(hw, false);
+
+	hw->platform_dev = pdev;
+
+#ifdef DUMP_USERDATA_RECORD
+	vmh264_init_userdata_dump();
+	vmh264_reset_user_data_buf();
+#endif
+	if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, BMMU_DPB_IDX,
+		V_BUF_ADDR_OFFSET, DRIVER_NAME, &hw->cma_alloc_addr) < 0) {
+		h264_free_hw_stru(&pdev->dev, (void *)hw);
+		pdata->dec_status = NULL;
+		return -ENOMEM;
+	}
+
+	hw->buf_offset = hw->cma_alloc_addr - DEF_BUF_START_ADDR +
+			DCAC_READ_MARGIN;
+	if (hw->mmu_enable) {
+		u32 extif_size = EXTIF_BUF_SIZE;
+		if (get_cpu_major_id() >=  AM_MESON_CPU_MAJOR_ID_G12A)
+			extif_size <<= 1;
+		if (decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box, BMMU_EXTIF_IDX,
+			extif_size, DRIVER_NAME, &hw->extif_addr) < 0) {
+			h264_free_hw_stru(&pdev->dev, (void *)hw);
+			pdata->dec_status = NULL;
+			return -ENOMEM;
+		}
+	}
+	if (!vdec_secure(pdata)) {
+#if 1
+		/*init internal buf*/
+		tmpbuf = (char *)codec_mm_phys_to_virt(hw->cma_alloc_addr);
+		if (tmpbuf) {
+			memset(tmpbuf, 0, V_BUF_ADDR_OFFSET);
+			codec_mm_dma_flush(tmpbuf,
+				V_BUF_ADDR_OFFSET,
+				DMA_TO_DEVICE);
+		} else {
+			tmpbuf = codec_mm_vmap(hw->cma_alloc_addr,
+				V_BUF_ADDR_OFFSET);
+			if (tmpbuf) {
+				memset(tmpbuf, 0, V_BUF_ADDR_OFFSET);
+				codec_mm_dma_flush(tmpbuf,
+					V_BUF_ADDR_OFFSET,
+					DMA_TO_DEVICE);
+				codec_mm_unmap_phyaddr(tmpbuf);
+			}
+		}
+#else
+		/*init sps/pps internal buf 64k*/
+		tmpbuf = (char *)codec_mm_phys_to_virt(hw->cma_alloc_addr
+			+ (mem_sps_base - DEF_BUF_START_ADDR));
+		memset(tmpbuf, 0, 0x10000);
+		dma_sync_single_for_device(amports_get_dma_device(),
+			hw->cma_alloc_addr +
+			(mem_sps_base - DEF_BUF_START_ADDR),
+			0x10000, DMA_TO_DEVICE);
+#endif
+	}
+	/**/
+
+#if 0
+	if (NULL == hw->sei_data_buffer) {
+		hw->sei_data_buffer =
+			dma_alloc_coherent(amports_get_dma_device(),
+				USER_DATA_SIZE,
+				&hw->sei_data_buffer_phys, GFP_KERNEL);
+		if (!hw->sei_data_buffer) {
+			pr_info("%s: Can not allocate sei_data_buffer\n",
+				   __func__);
+			ammvdec_h264_mmu_release(hw);
+			h264_free_hw_stru(&pdev->dev, (void *)hw);
+			return -ENOMEM;
+		}
+		/* pr_info("buffer 0x%x, phys 0x%x, remap 0x%x\n",
+		   sei_data_buffer, sei_data_buffer_phys,
+		   (u32)sei_data_buffer_remap); */
+	}
+#endif
+	dpb_print(DECODE_ID(hw), 0, "ammvdec_h264 mem-addr=%lx,buff_offset=%x,buf_start=%lx\n",
+		pdata->mem_start, hw->buf_offset, hw->cma_alloc_addr);
+
+	vdec_source_changed(VFORMAT_H264, 3840, 2160, 60);
+
+	if (hw->mmu_enable)
+		hevc_source_changed(VFORMAT_HEVC, 3840, 2160, 60);
+
+	if (vh264_init(hw) < 0) {
+		pr_info("\nammvdec_h264 init failed.\n");
+		ammvdec_h264_mmu_release(hw);
+		h264_free_hw_stru(&pdev->dev, (void *)hw);
+		pdata->dec_status = NULL;
+		return -ENODEV;
+	}
+#ifdef MH264_USERDATA_ENABLE
+	vmh264_crate_userdata_manager(hw,
+			hw->sei_user_data_buffer,
+			USER_DATA_SIZE);
+#endif
+
+#ifdef AUX_DATA_CRC
+	vdec_aux_data_check_init(pdata);
+#endif
+
+	vdec_set_prepare_level(pdata, start_decode_buf_level);
+	if (pdata->parallel_dec == 1) {
+		if (hw->mmu_enable == 0)
+			vdec_core_request(pdata, CORE_MASK_VDEC_1);
+		else {
+			vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+				| CORE_MASK_COMBINE);
+		}
+	} else
+		vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+				| CORE_MASK_COMBINE);
+
+	atomic_set(&hw->vh264_active, 1);
+	vdec_set_vframe_comm(pdata, DRIVER_NAME);
+	display_frame_count[DECODE_ID(hw)] = 0;
+	decode_frame_count[DECODE_ID(hw)] = 0;
+	hw->dpb.without_display_mode = without_display_mode;
+	mutex_init(&hw->fence_mutex);
+	if (hw->enable_fence) {
+		pdata->sync = vdec_sync_get();
+		if (!pdata->sync) {
+			dpb_print(DECODE_ID(hw), 0, "alloc fence timeline error\n");
+			ammvdec_h264_mmu_release(hw);
+			h264_free_hw_stru(&pdev->dev, (void *)hw);
+			pdata->dec_status = NULL;
+			return -ENODEV;
+		}
+		pdata->sync->usage = hw->fence_usage;
+		/* creat timeline. */
+		vdec_timeline_create(pdata->sync, DRIVER_NAME);
+	}
+
+	return 0;
+}
+
+static void vdec_fence_release(struct vdec_h264_hw_s *hw,
+			       struct vdec_sync *sync)
+{
+	ulong expires;
+
+	/* clear display pool. */
+	clear_refer_bufs(hw);
+
+	/* notify signal to wake up all fences. */
+	vdec_timeline_increase(sync, VF_POOL_SIZE);
+
+	expires = jiffies + msecs_to_jiffies(2000);
+	while (!check_objs_all_signaled(sync)) {
+		if (time_after(jiffies, expires)) {
+			pr_err("wait fence signaled timeout.\n");
+			break;
+		}
+	}
+
+	pr_info("fence start release\n");
+
+	/* decreases refcnt of timeline. */
+	vdec_timeline_put(sync);
+}
+
+static int ammvdec_h264_remove(struct platform_device *pdev)
+{
+	struct vdec_h264_hw_s *hw =
+		(struct vdec_h264_hw_s *)
+		(((struct vdec_s *)(platform_get_drvdata(pdev)))->private);
+	int i;
+
+	struct vdec_s *vdec = hw_to_vdec(hw);
+
+	if (vdec->next_status == VDEC_STATUS_DISCONNECTED
+				&& (vdec->status == VDEC_STATUS_ACTIVE)) {
+			dpb_print(DECODE_ID(hw), 0,
+				"%s  force exit %d\n", __func__, __LINE__);
+			hw->dec_result = DEC_RESULT_FORCE_EXIT;
+			vdec_schedule_work(&hw->work);
+			wait_event_interruptible_timeout(hw->wait_q,
+				(vdec->status == VDEC_STATUS_CONNECTED),
+				msecs_to_jiffies(1000));  /* wait for work done */
+	}
+
+	for (i = 0; i < BUFSPEC_POOL_SIZE; i++)
+		release_aux_data(hw, i);
+
+	atomic_set(&hw->vh264_active, 0);
+
+	if (hw->stat & STAT_TIMER_ARM) {
+		del_timer_sync(&hw->check_timer);
+		hw->stat &= ~STAT_TIMER_ARM;
+	}
+
+	vh264_stop(hw);
+#ifdef MH264_USERDATA_ENABLE
+#ifdef DUMP_USERDATA_RECORD
+	vmh264_dump_userdata();
+#endif
+	vmh264_destroy_userdata_manager(hw);
+#endif
+	/* vdec_source_changed(VFORMAT_H264, 0, 0, 0); */
+
+#ifdef AUX_DATA_CRC
+	vdec_aux_data_check_exit(vdec);
+#endif
+
+	atomic_set(&hw->vh264_active, 0);
+	if (vdec->parallel_dec == 1) {
+		if (hw->mmu_enable == 0)
+			vdec_core_release(vdec, CORE_MASK_VDEC_1);
+		else
+			vdec_core_release(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC |
+				CORE_MASK_COMBINE);
+	} else
+		vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
+
+	vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED);
+	if (vdec->parallel_dec == 1) {
+		for (i = 0; i < BUFSPEC_POOL_SIZE; i++) {
+			vdec->free_canvas_ex(hw->buffer_spec[i].y_canvas_index, vdec->id);
+			vdec->free_canvas_ex(hw->buffer_spec[i].u_canvas_index, vdec->id);
+			vdec->free_canvas_ex(hw->buffer_spec[i].v_canvas_index, vdec->id);
+			if (IS_VDEC_DW(hw)) {
+				vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_y_canvas_index, vdec->id);
+				vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_u_canvas_index, vdec->id);
+				vdec->free_canvas_ex(hw->buffer_spec[i].vdec_dw_v_canvas_index, vdec->id);
+			}
+		}
+	}
+
+	if (hw->enable_fence)
+		vdec_fence_release(hw, vdec->sync);
+
+	ammvdec_h264_mmu_release(hw);
+	h264_free_hw_stru(&pdev->dev, (void *)hw);
+	clk_adj_frame_count = 0;
+
+	return 0;
+}
+
+/****************************************/
+
+static struct platform_driver ammvdec_h264_driver = {
+	.probe = ammvdec_h264_probe,
+	.remove = ammvdec_h264_remove,
+#ifdef CONFIG_PM
+	.suspend = amvdec_suspend,
+	.resume = amvdec_resume,
+#endif
+	.driver = {
+		.name = DRIVER_NAME,
+	}
+};
+
+static struct codec_profile_t ammvdec_h264_profile = {
+	.name = "mh264",
+	.profile = ""
+};
+
+static struct mconfig hm264_configs[] = {
+	MC_PU32("h264_debug_flag", &h264_debug_flag),
+	MC_PI32("start_decode_buf_level", &start_decode_buf_level),
+	MC_PU32("fixed_frame_rate_mode", &fixed_frame_rate_mode),
+	MC_PU32("decode_timeout_val", &decode_timeout_val),
+	MC_PU32("reorder_dpb_size_margin", &reorder_dpb_size_margin),
+	MC_PU32("reference_buf_margin", &reference_buf_margin),
+	MC_PU32("radr", &radr),
+	MC_PU32("rval", &rval),
+	MC_PU32("h264_debug_mask", &h264_debug_mask),
+	MC_PU32("h264_debug_cmd", &h264_debug_cmd),
+	MC_PI32("force_rate_streambase", &force_rate_streambase),
+	MC_PI32("dec_control", &dec_control),
+	MC_PI32("force_rate_framebase", &force_rate_framebase),
+	MC_PI32("force_disp_bufspec_num", &force_disp_bufspec_num),
+	MC_PU32("prefix_aux_buf_size", &prefix_aux_buf_size),
+	MC_PU32("suffix_aux_buf_size", &suffix_aux_buf_size),
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+	MC_PU32("reorder_dpb_size_margin_dv", &reorder_dpb_size_margin_dv),
+	MC_PU32("dv_toggle_prov_name", &dv_toggle_prov_name),
+	MC_PU32("dolby_meta_with_el", &dolby_meta_with_el),
+#endif
+	MC_PU32("i_only_flag", &i_only_flag),
+	MC_PU32("force_rate_streambase", &force_rate_streambase),
+};
+static struct mconfig_node hm264_node;
+
+
+static int __init ammvdec_h264_driver_init_module(void)
+{
+
+	pr_info("ammvdec_h264 module init\n");
+	if (platform_driver_register(&ammvdec_h264_driver)) {
+		pr_info("failed to register ammvdec_h264 driver\n");
+		return -ENODEV;
+	}
+
+	if (vdec_is_support_4k()) {
+		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) {
+			ammvdec_h264_profile.profile =
+					"4k, dwrite, compressed, frame_dv, fence, v4l";
+		} else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB) {
+			ammvdec_h264_profile.profile = "4k, frame_dv, fence, v4l";
+		}
+	} else {
+		if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5D || is_cpu_s4_s805x2()) {
+			ammvdec_h264_profile.profile =
+						"dwrite, compressed, frame_dv, v4l";
+		} else {
+			ammvdec_h264_profile.profile =
+				        "dwrite, compressed, v4l";
+		}
+	}
+
+	vcodec_profile_register(&ammvdec_h264_profile);
+	INIT_REG_NODE_CONFIGS("media.decoder", &hm264_node,
+	"mh264", hm264_configs, CONFIG_FOR_RW);
+
+	vcodec_feature_register(VFORMAT_H264, 0);
+	return 0;
+}
+
+static void __exit ammvdec_h264_driver_remove_module(void)
+{
+	pr_info("ammvdec_h264 module remove.\n");
+
+	platform_driver_unregister(&ammvdec_h264_driver);
+}
+
+/****************************************/
+module_param(h264_debug_flag, uint, 0664);
+MODULE_PARM_DESC(h264_debug_flag, "\n ammvdec_h264 h264_debug_flag\n");
+
+module_param(start_decode_buf_level, int, 0664);
+MODULE_PARM_DESC(start_decode_buf_level,
+		"\n ammvdec_h264 start_decode_buf_level\n");
+
+module_param(pre_decode_buf_level, int, 0664);
+MODULE_PARM_DESC(pre_decode_buf_level, "\n ammvdec_h264 pre_decode_buf_level\n");
+
+module_param(fixed_frame_rate_mode, uint, 0664);
+MODULE_PARM_DESC(fixed_frame_rate_mode, "\namvdec_h264 fixed_frame_rate_mode\n");
+
+module_param(decode_timeout_val, uint, 0664);
+MODULE_PARM_DESC(decode_timeout_val, "\n amvdec_h264 decode_timeout_val\n");
+
+module_param(errordata_timeout_val, uint, 0664);
+MODULE_PARM_DESC(errordata_timeout_val, "\n amvdec_h264 errordata_timeout_val\n");
+
+module_param(get_data_timeout_val, uint, 0664);
+MODULE_PARM_DESC(get_data_timeout_val, "\n amvdec_h264 get_data_timeout_val\n");
+
+module_param(frame_max_data_packet, uint, 0664);
+MODULE_PARM_DESC(frame_max_data_packet, "\n amvdec_h264 frame_max_data_packet\n");
+
+module_param(reorder_dpb_size_margin, uint, 0664);
+MODULE_PARM_DESC(reorder_dpb_size_margin, "\n ammvdec_h264 reorder_dpb_size_margin\n");
+
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+module_param(reorder_dpb_size_margin_dv, uint, 0664);
+MODULE_PARM_DESC(reorder_dpb_size_margin_dv,
+	"\n ammvdec_h264 reorder_dpb_size_margin_dv\n");
+#endif
+
+module_param(reference_buf_margin, uint, 0664);
+MODULE_PARM_DESC(reference_buf_margin, "\n ammvdec_h264 reference_buf_margin\n");
+
+#ifdef CONSTRAIN_MAX_BUF_NUM
+module_param(run_ready_max_vf_only_num, uint, 0664);
+MODULE_PARM_DESC(run_ready_max_vf_only_num, "\n run_ready_max_vf_only_num\n");
+
+module_param(run_ready_display_q_num, uint, 0664);
+MODULE_PARM_DESC(run_ready_display_q_num, "\n run_ready_display_q_num\n");
+
+module_param(run_ready_max_buf_num, uint, 0664);
+MODULE_PARM_DESC(run_ready_max_buf_num, "\n run_ready_max_buf_num\n");
+#endif
+
+module_param(radr, uint, 0664);
+MODULE_PARM_DESC(radr, "\nradr\n");
+
+module_param(rval, uint, 0664);
+MODULE_PARM_DESC(rval, "\nrval\n");
+
+module_param(h264_debug_mask, uint, 0664);
+MODULE_PARM_DESC(h264_debug_mask, "\n amvdec_h264 h264_debug_mask\n");
+
+module_param(h264_debug_cmd, uint, 0664);
+MODULE_PARM_DESC(h264_debug_cmd, "\n amvdec_h264 h264_debug_cmd\n");
+
+module_param(force_rate_streambase, int, 0664);
+MODULE_PARM_DESC(force_rate_streambase, "\n amvdec_h264 force_rate_streambase\n");
+
+module_param(dec_control, int, 0664);
+MODULE_PARM_DESC(dec_control, "\n amvdec_h264 dec_control\n");
+
+module_param(force_rate_framebase, int, 0664);
+MODULE_PARM_DESC(force_rate_framebase, "\n amvdec_h264 force_rate_framebase\n");
+
+module_param(force_disp_bufspec_num, int, 0664);
+MODULE_PARM_DESC(force_disp_bufspec_num, "\n amvdec_h264 force_disp_bufspec_num\n");
+
+module_param(V_BUF_ADDR_OFFSET, int, 0664);
+MODULE_PARM_DESC(V_BUF_ADDR_OFFSET, "\n amvdec_h264 V_BUF_ADDR_OFFSET\n");
+
+module_param(prefix_aux_buf_size, uint, 0664);
+MODULE_PARM_DESC(prefix_aux_buf_size, "\n prefix_aux_buf_size\n");
+
+module_param(suffix_aux_buf_size, uint, 0664);
+MODULE_PARM_DESC(suffix_aux_buf_size, "\n suffix_aux_buf_size\n");
+
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+module_param(dv_toggle_prov_name, uint, 0664);
+MODULE_PARM_DESC(dv_toggle_prov_name, "\n dv_toggle_prov_name\n");
+
+module_param(dolby_meta_with_el, uint, 0664);
+MODULE_PARM_DESC(dolby_meta_with_el, "\n dolby_meta_with_el\n");
+
+#endif
+
+module_param(fast_output_enable, uint, 0664);
+MODULE_PARM_DESC(fast_output_enable, "\n amvdec_h264 fast_output_enable\n");
+
+module_param(error_proc_policy, uint, 0664);
+MODULE_PARM_DESC(error_proc_policy, "\n amvdec_h264 error_proc_policy\n");
+
+module_param(error_skip_count, uint, 0664);
+MODULE_PARM_DESC(error_skip_count, "\n amvdec_h264 error_skip_count\n");
+
+module_param(force_sliding_margin, uint, 0664);
+MODULE_PARM_DESC(force_sliding_margin, "\n amvdec_h264 force_sliding_margin\n");
+
+module_param(i_only_flag, uint, 0664);
+MODULE_PARM_DESC(i_only_flag, "\n amvdec_h264 i_only_flag\n");
+
+module_param(first_i_policy, uint, 0664);
+MODULE_PARM_DESC(first_i_policy, "\n amvdec_h264 first_i_policy\n");
+
+module_param(frmbase_cont_bitlevel, uint, 0664);
+MODULE_PARM_DESC(frmbase_cont_bitlevel,
+	"\n amvdec_h264 frmbase_cont_bitlevel\n");
+
+module_param(frmbase_cont_bitlevel2, uint, 0664);
+MODULE_PARM_DESC(frmbase_cont_bitlevel2,
+	"\n amvdec_h264 frmbase_cont_bitlevel\n");
+
+module_param(udebug_flag, uint, 0664);
+MODULE_PARM_DESC(udebug_flag, "\n amvdec_mh264 udebug_flag\n");
+
+module_param(udebug_pause_pos, uint, 0664);
+MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n");
+
+module_param(udebug_pause_val, uint, 0664);
+MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n");
+
+module_param(udebug_pause_decode_idx, uint, 0664);
+MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n");
+
+module_param(max_alloc_buf_count, uint, 0664);
+MODULE_PARM_DESC(max_alloc_buf_count, "\n amvdec_h264 max_alloc_buf_count\n");
+
+module_param(enable_itu_t35, uint, 0664);
+MODULE_PARM_DESC(enable_itu_t35, "\n amvdec_h264 enable_itu_t35\n");
+
+module_param(endian, uint, 0664);
+MODULE_PARM_DESC(endian, "\nrval\n");
+
+module_param(mmu_enable, uint, 0664);
+MODULE_PARM_DESC(mmu_enable, "\n mmu_enable\n");
+
+module_param(force_enable_mmu, uint, 0664);
+MODULE_PARM_DESC(force_enable_mmu, "\n force_enable_mmu\n");
+
+module_param(again_threshold, uint, 0664);
+MODULE_PARM_DESC(again_threshold, "\n again_threshold\n");
+
+module_param(stream_mode_start_num, uint, 0664);
+MODULE_PARM_DESC(stream_mode_start_num, "\n stream_mode_start_num\n");
+
+module_param(colocate_old_cal, uint, 0664);
+MODULE_PARM_DESC(colocate_old_cal, "\n amvdec_mh264 colocate_old_cal\n");
+
+/*
+module_param(trigger_task, uint, 0664);
+MODULE_PARM_DESC(trigger_task, "\n amvdec_h264 trigger_task\n");
+*/
+module_param_array(decode_frame_count, uint, &max_decode_instance_num, 0664);
+
+module_param_array(display_frame_count, uint, &max_decode_instance_num, 0664);
+
+module_param_array(max_process_time, uint, &max_decode_instance_num, 0664);
+
+module_param_array(run_count, uint,
+	&max_decode_instance_num, 0664);
+
+module_param_array(not_run_ready, uint,
+	&max_decode_instance_num, 0664);
+
+module_param_array(input_empty, uint,
+	&max_decode_instance_num, 0664);
+
+module_param_array(max_get_frame_interval, uint,
+	&max_decode_instance_num, 0664);
+
+module_param_array(step, uint, &max_decode_instance_num, 0664);
+
+module_param_array(ref_frame_mark_flag, uint, &max_decode_instance_num, 0664);
+
+module_param(disp_vframe_valve_level, uint, 0664);
+MODULE_PARM_DESC(disp_vframe_valve_level, "\n disp_vframe_valve_level\n");
+
+module_param(double_write_mode, uint, 0664);
+MODULE_PARM_DESC(double_write_mode, "\n double_write_mode\n");
+
+module_param(mem_map_mode, uint, 0664);
+MODULE_PARM_DESC(mem_map_mode, "\n mem_map_mode\n");
+
+module_param(without_display_mode, uint, 0664);
+MODULE_PARM_DESC(without_display_mode, "\n without_display_mode\n");
+
+module_param(check_slice_num, uint, 0664);
+MODULE_PARM_DESC(check_slice_num, "\n check_slice_num\n");
+
+module_param(mb_count_threshold, uint, 0664);
+MODULE_PARM_DESC(mb_count_threshold, "\n mb_count_threshold\n");
+
+module_param(loop_playback_poc_threshold, int, 0664);
+MODULE_PARM_DESC(loop_playback_poc_threshold, "\n loop_playback_poc_threshold\n");
+
+module_param(poc_threshold, int, 0664);
+MODULE_PARM_DESC(poc_threshold, "\n poc_threshold\n");
+
+module_param(force_config_fence, uint, 0664);
+MODULE_PARM_DESC(force_config_fence, "\n force enable fence\n");
+
+module_param(dirty_again_threshold, uint, 0664);
+MODULE_PARM_DESC(dirty_again_threshold, "\n amvdec_h264 dirty_again_threshold\n");
+
+module_init(ammvdec_h264_driver_init_module);
+module_exit(ammvdec_h264_driver_remove_module);
+
+MODULE_DESCRIPTION("AMLOGIC H264 Video Decoder Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/frame_provider/decoder/h265/Makefile b/drivers/frame_provider/decoder/h265/Makefile
new file mode 100644
index 0000000..86b8b88
--- /dev/null
+++ b/drivers/frame_provider/decoder/h265/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H265) += amvdec_h265.o
+amvdec_h265-objs += vh265.o
diff --git a/drivers/frame_provider/decoder/h265/vh265.c b/drivers/frame_provider/decoder/h265/vh265.c
new file mode 100644
index 0000000..d5945ce
--- /dev/null
+++ b/drivers/frame_provider/decoder/h265/vh265.c
@@ -0,0 +1,16227 @@
+/*
+ * drivers/amlogic/amports/vh265.c
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+#define DEBUG
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/semaphore.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/kfifo.h>
+#include <linux/kthread.h>
+#include <linux/platform_device.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/timer.h>
+//#include <linux/amlogic/tee.h>
+#include <uapi/linux/tee.h>
+#include <linux/sched/clock.h>
+#include "../../../stream_input/amports/amports_priv.h"
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include "../utils/decoder_mmu_box.h"
+#include "../utils/decoder_bmmu_box.h"
+#include "../utils/config_parser.h"
+#include "../utils/firmware.h"
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+#include "../utils/vdec_v4l2_buffer_ops.h"
+#include <media/v4l2-mem2mem.h>
+
+/*
+to enable DV of frame mode
+#define DOLBY_META_SUPPORT in ucode
+*/
+
+#define HEVC_8K_LFTOFFSET_FIX
+#define SUPPORT_LONG_TERM_RPS
+
+//#define CO_MV_COMPRESS
+
+#define CONSTRAIN_MAX_BUF_NUM
+
+#define SWAP_HEVC_UCODE
+#define DETREFILL_ENABLE
+
+#define AGAIN_HAS_THRESHOLD
+/*#define TEST_NO_BUF*/
+#define HEVC_PIC_STRUCT_SUPPORT
+#define MULTI_INSTANCE_SUPPORT
+#define USE_UNINIT_SEMA
+
+			/* .buf_size = 0x100000*16,
+			//4k2k , 0x100000 per buffer */
+			/* 4096x2304 , 0x120000 per buffer */
+#define MPRED_8K_MV_BUF_SIZE		(0x120000*4)
+#define MPRED_4K_MV_BUF_SIZE		(0x120000)
+#define MPRED_MV_BUF_SIZE		(0x3fc00)
+
+#define MMU_COMPRESS_HEADER_SIZE_1080P  0x10000
+#define MMU_COMPRESS_HEADER_SIZE_4K  0x48000
+#define MMU_COMPRESS_HEADER_SIZE_8K  0x120000
+#define DB_NUM 20
+
+#define MAX_FRAME_4K_NUM 0x1200
+#define MAX_FRAME_8K_NUM ((MAX_FRAME_4K_NUM) * 4)
+
+//#define FRAME_MMU_MAP_SIZE  (MAX_FRAME_4K_NUM * 4)
+#define H265_MMU_MAP_BUFFER       HEVC_ASSIST_SCRATCH_7
+
+#define HEVC_ASSIST_MMU_MAP_ADDR                   0x3009
+
+#define HEVC_CM_HEADER_START_ADDR                  0x3628
+#define HEVC_CM_HEADER_START_ADDR2                 0x364a
+#define HEVC_SAO_MMU_VH1_ADDR                      0x363b
+#define HEVC_SAO_MMU_VH0_ADDR                      0x363a
+#define HEVC_SAO_MMU_VH0_ADDR2                     0x364d
+#define HEVC_SAO_MMU_VH1_ADDR2                     0x364e
+
+#define HEVC_SAO_MMU_DMA_CTRL2                     0x364c
+#define HEVC_SAO_MMU_STATUS2                       0x3650
+#define HEVC_DW_VH0_ADDDR                          0x365e
+#define HEVC_DW_VH1_ADDDR                          0x365f
+
+#define HEVC_DBLK_CFGB                             0x350b
+#define HEVCD_MPP_DECOMP_AXIURG_CTL                0x34c7
+#define SWAP_HEVC_OFFSET (3 * 0x1000)
+
+#define MEM_NAME "codec_265"
+/* #include <mach/am_regs.h> */
+#include <linux/amlogic/media/utils/vdec_reg.h>
+
+#include "../utils/vdec.h"
+#include "../utils/amvdec.h"
+#include <linux/amlogic/media/video_sink/video.h>
+#include <linux/amlogic/media/codec_mm/configs.h>
+#include "../utils/vdec_feature.h"
+
+#define SEND_LMEM_WITH_RPM
+#define SUPPORT_10BIT
+#define H265_10B_MMU_DW
+/* #define ERROR_HANDLE_DEBUG */
+
+#ifndef STAT_KTHREAD
+#define STAT_KTHREAD 0x40
+#endif
+
+#ifdef MULTI_INSTANCE_SUPPORT
+#define MAX_DECODE_INSTANCE_NUM     9
+#define MULTI_DRIVER_NAME "ammvdec_h265"
+#endif
+#define DRIVER_NAME "amvdec_h265"
+#define DRIVER_HEADER_NAME "amvdec_h265_header"
+
+#define PUT_INTERVAL        (HZ/100)
+#define ERROR_SYSTEM_RESET_COUNT   200
+
+#define PTS_NORMAL                0
+#define PTS_NONE_REF_USE_DURATION 1
+
+#define PTS_MODE_SWITCHING_THRESHOLD           3
+#define PTS_MODE_SWITCHING_RECOVERY_THREASHOLD 3
+
+#define DUR2PTS(x) ((x)*90/96)
+
+#define MAX_SIZE_8K (8192 * 4608)
+#define MAX_SIZE_4K (4096 * 2304)
+#define MAX_SIZE_2K (1920 * 1088)
+
+#define IS_8K_SIZE(w, h)  (((w) * (h)) > MAX_SIZE_4K)
+#define IS_4K_SIZE(w, h)  (((w) * (h)) > (1920*1088))
+
+#define SEI_UserDataITU_T_T35	4
+#define INVALID_IDX -1  /* Invalid buffer index.*/
+
+static struct semaphore h265_sema;
+
+struct hevc_state_s;
+static int hevc_print(struct hevc_state_s *hevc,
+	int debug_flag, const char *fmt, ...);
+static int hevc_print_cont(struct hevc_state_s *hevc,
+	int debug_flag, const char *fmt, ...);
+static int vh265_vf_states(struct vframe_states *states, void *);
+static struct vframe_s *vh265_vf_peek(void *);
+static struct vframe_s *vh265_vf_get(void *);
+static void vh265_vf_put(struct vframe_s *, void *);
+static int vh265_event_cb(int type, void *data, void *private_data);
+
+static int vh265_stop(struct hevc_state_s *hevc);
+#ifdef MULTI_INSTANCE_SUPPORT
+static int vmh265_stop(struct hevc_state_s *hevc);
+static s32 vh265_init(struct vdec_s *vdec);
+static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask);
+static void reset_process_time(struct hevc_state_s *hevc);
+static void start_process_time(struct hevc_state_s *hevc);
+static void restart_process_time(struct hevc_state_s *hevc);
+static void timeout_process(struct hevc_state_s *hevc);
+#else
+static s32 vh265_init(struct hevc_state_s *hevc);
+#endif
+static void vh265_prot_init(struct hevc_state_s *hevc);
+static int vh265_local_init(struct hevc_state_s *hevc);
+static void vh265_check_timer_func(struct timer_list *timer);
+static void config_decode_mode(struct hevc_state_s *hevc);
+static int check_data_size(struct vdec_s *vdec);
+
+
+static const char vh265_dec_id[] = "vh265-dev";
+
+#define PROVIDER_NAME   "decoder.h265"
+#define MULTI_INSTANCE_PROVIDER_NAME    "vdec.h265"
+
+static const struct vframe_operations_s vh265_vf_provider = {
+	.peek = vh265_vf_peek,
+	.get = vh265_vf_get,
+	.put = vh265_vf_put,
+	.event_cb = vh265_event_cb,
+	.vf_states = vh265_vf_states,
+};
+
+static struct vframe_provider_s vh265_vf_prov;
+
+static u32 bit_depth_luma;
+static u32 bit_depth_chroma;
+static u32 video_signal_type;
+static int start_decode_buf_level = 0x8000;
+static unsigned int decode_timeout_val = 200;
+
+static u32 run_ready_min_buf_num = 2;
+static u32 disable_ip_mode;
+static u32 print_lcu_error = 1;
+/*data_resend_policy:
+	bit 0, stream base resend data when decoding buf empty
+*/
+static u32 data_resend_policy = 1;
+static int poc_num_margin = 1000;
+static int poc_error_limit = 30;
+
+static u32 dirty_again_threshold = 100;
+static u32 dirty_buffersize_threshold = 0x800000;
+
+
+#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK	0x20000000
+/*
+static const char * const video_format_names[] = {
+	"component", "PAL", "NTSC", "SECAM",
+	"MAC", "unspecified", "unspecified", "unspecified"
+};
+
+static const char * const color_primaries_names[] = {
+	"unknown", "bt709", "undef", "unknown",
+	"bt470m", "bt470bg", "smpte170m", "smpte240m",
+	"film", "bt2020"
+};
+
+static const char * const transfer_characteristics_names[] = {
+	"unknown", "bt709", "undef", "unknown",
+	"bt470m", "bt470bg", "smpte170m", "smpte240m",
+	"linear", "log100", "log316", "iec61966-2-4",
+	"bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12",
+	"smpte-st-2084", "smpte-st-428"
+};
+
+static const char * const matrix_coeffs_names[] = {
+	"GBR", "bt709", "undef", "unknown",
+	"fcc", "bt470bg", "smpte170m", "smpte240m",
+	"YCgCo", "bt2020nc", "bt2020c"
+};
+*/
+#ifdef SUPPORT_10BIT
+#define HEVC_CM_BODY_START_ADDR                    0x3626
+#define HEVC_CM_BODY_LENGTH                        0x3627
+#define HEVC_CM_HEADER_LENGTH                      0x3629
+#define HEVC_CM_HEADER_OFFSET                      0x362b
+#define HEVC_SAO_CTRL9                             0x362d
+
+#define HEVC_CM_BODY_LENGTH2                       0x3663
+#define HEVC_CM_HEADER_OFFSET2                     0x3664
+#define HEVC_CM_HEADER_LENGTH2                     0x3665
+
+#define LOSLESS_COMPRESS_MODE
+/* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */
+/* double_write_mode:
+ *	0, no double write;
+ *	1, 1:1 ratio;
+ *	2, (1/4):(1/4) ratio;
+ *	3, (1/4):(1/4) ratio, with both compressed frame included
+ *	4, (1/2):(1/2) ratio;
+ *	5, (1/2):(1/2) ratio, with both compressed frame included
+ *	8, (1/8):(1/8) ratio,  from t7
+ *	0x10, double write only
+ *	0x100, if > 1080p,use mode 4,else use mode 1;
+ *	0x200, if > 1080p,use mode 2,else use mode 1;
+ *	0x300, if > 720p, use mode 4, else use mode 1;
+ *	0x1000,if > 1080p,use mode 3, else if > 960*540, use mode 4, else use mode 1;
+ */
+static u32 double_write_mode;
+
+/*#define DECOMP_HEADR_SURGENT*/
+
+static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */
+static u32 enable_mem_saving = 1;
+static u32 workaround_enable;
+static u32 force_w_h;
+#endif
+static u32 force_fps;
+static u32 pts_unstable;
+#define H265_DEBUG_BUFMGR                   0x01
+#define H265_DEBUG_BUFMGR_MORE              0x02
+#define H265_DEBUG_DETAIL                   0x04
+#define H265_DEBUG_REG                      0x08
+#define H265_DEBUG_MAN_SEARCH_NAL           0x10
+#define H265_DEBUG_MAN_SKIP_NAL             0x20
+#define H265_DEBUG_DISPLAY_CUR_FRAME        0x40
+#define H265_DEBUG_FORCE_CLK                0x80
+#define H265_DEBUG_SEND_PARAM_WITH_REG      0x100
+#define H265_DEBUG_NO_DISPLAY               0x200
+#define H265_DEBUG_DISCARD_NAL              0x400
+#define H265_DEBUG_OUT_PTS                  0x800
+#define H265_DEBUG_DUMP_PIC_LIST            0x1000
+#define H265_DEBUG_PRINT_SEI		        0x2000
+#define H265_DEBUG_PIC_STRUCT				0x4000
+#define H265_DEBUG_HAS_AUX_IN_SLICE			0x8000
+#define H265_DEBUG_DIS_LOC_ERROR_PROC       0x10000
+#define H265_DEBUG_DIS_SYS_ERROR_PROC       0x20000
+#define H265_NO_CHANG_DEBUG_FLAG_IN_CODE    0x40000
+#define H265_DEBUG_TRIG_SLICE_SEGMENT_PROC  0x80000
+#define H265_DEBUG_HW_RESET                 0x100000
+#define H265_CFG_CANVAS_IN_DECODE           0x200000
+#define H265_DEBUG_DV                       0x400000
+#define H265_DEBUG_NO_EOS_SEARCH_DONE       0x800000
+#define H265_DEBUG_NOT_USE_LAST_DISPBUF     0x1000000
+#define H265_DEBUG_IGNORE_CONFORMANCE_WINDOW	0x2000000
+#define H265_DEBUG_WAIT_DECODE_DONE_WHEN_STOP   0x4000000
+#ifdef MULTI_INSTANCE_SUPPORT
+#define PRINT_FLAG_ERROR		0x0
+#define IGNORE_PARAM_FROM_CONFIG	0x08000000
+#define PRINT_FRAMEBASE_DATA		0x10000000
+#define PRINT_FLAG_VDEC_STATUS		0x20000000
+#define PRINT_FLAG_VDEC_DETAIL		0x40000000
+#define PRINT_FLAG_V4L_DETAIL		0x80000000
+#endif
+
+#define BUF_POOL_SIZE	32
+#define MAX_BUF_NUM 24
+#define MAX_REF_PIC_NUM 24
+#define MAX_REF_ACTIVE  16
+
+#ifdef MV_USE_FIXED_BUF
+#define BMMU_MAX_BUFFERS (BUF_POOL_SIZE + 1)
+#define VF_BUFFER_IDX(n)	(n)
+#define BMMU_WORKSPACE_ID	(BUF_POOL_SIZE)
+#else
+#define BMMU_MAX_BUFFERS (BUF_POOL_SIZE + 1 + MAX_REF_PIC_NUM)
+#define VF_BUFFER_IDX(n)	(n)
+#define BMMU_WORKSPACE_ID	(BUF_POOL_SIZE)
+#define MV_BUFFER_IDX(n) (BUF_POOL_SIZE + 1 + n)
+#endif
+
+#define HEVC_MV_INFO   0x310d
+#define HEVC_QP_INFO   0x3137
+#define HEVC_SKIP_INFO 0x3136
+
+const u32 h265_version = 201602101;
+static u32 debug_mask = 0xffffffff;
+static u32 log_mask;
+static u32 debug;
+static u32 radr;
+static u32 rval;
+static u32 dbg_cmd;
+static u32 dump_nal;
+static u32 dbg_skip_decode_index;
+/*
+ * bit 0~3, for HEVCD_IPP_AXIIF_CONFIG endian config
+ * bit 8~23, for HEVC_SAO_CTRL1 endian config
+ */
+static u32 endian;
+#define HEVC_CONFIG_BIG_ENDIAN     ((0x880 << 8) | 0x8)
+#define HEVC_CONFIG_LITTLE_ENDIAN  ((0xff0 << 8) | 0xf)
+
+#ifdef ERROR_HANDLE_DEBUG
+static u32 dbg_nal_skip_flag;
+		/* bit[0], skip vps; bit[1], skip sps; bit[2], skip pps */
+static u32 dbg_nal_skip_count;
+#endif
+/*for debug*/
+static u32 force_bufspec;
+
+/*
+	udebug_flag:
+	bit 0, enable ucode print
+	bit 1, enable ucode detail print
+	bit [31:16] not 0, pos to dump lmem
+		bit 2, pop bits to lmem
+		bit [11:8], pre-pop bits for alignment (when bit 2 is 1)
+*/
+static u32 udebug_flag;
+/*
+	when udebug_flag[1:0] is not 0
+	udebug_pause_pos not 0,
+		pause position
+*/
+static u32 udebug_pause_pos;
+/*
+	when udebug_flag[1:0] is not 0
+	and udebug_pause_pos is not 0,
+		pause only when DEBUG_REG2 is equal to this val
+*/
+static u32 udebug_pause_val;
+
+static u32 udebug_pause_decode_idx;
+
+static u32 decode_pic_begin;
+static uint slice_parse_begin;
+static u32 step;
+static bool is_reset;
+
+#ifdef CONSTRAIN_MAX_BUF_NUM
+static u32 run_ready_max_vf_only_num;
+static u32 run_ready_display_q_num;
+	/*0: not check
+	  0xff: work_pic_num
+	  */
+static u32 run_ready_max_buf_num = 0xff;
+#endif
+
+static u32 dynamic_buf_num_margin = 7;
+static u32 buf_alloc_width;
+static u32 buf_alloc_height;
+
+static u32 max_buf_num = 16;
+static u32 buf_alloc_size;
+/*static u32 re_config_pic_flag;*/
+/*
+ *bit[0]: 0,
+ *bit[1]: 0, always release cma buffer when stop
+ *bit[1]: 1, never release cma buffer when stop
+ *bit[0]: 1, when stop, release cma buffer if blackout is 1;
+ *do not release cma buffer is blackout is not 1
+ *
+ *bit[2]: 0, when start decoding, check current displayed buffer
+ *	 (only for buffer decoded by h265) if blackout is 0
+ *	 1, do not check current displayed buffer
+ *
+ *bit[3]: 1, if blackout is not 1, do not release current
+ *			displayed cma buffer always.
+ */
+/* set to 1 for fast play;
+ *	set to 8 for other case of "keep last frame"
+ */
+static u32 buffer_mode = 1;
+
+/* buffer_mode_dbg: debug only*/
+static u32 buffer_mode_dbg = 0xffff0000;
+/**/
+/*
+ *bit[1:0]PB_skip_mode: 0, start decoding at begin;
+ *1, start decoding after first I;
+ *2, only decode and display none error picture;
+ *3, start decoding and display after IDR,etc
+ *bit[31:16] PB_skip_count_after_decoding (decoding but not display),
+ *only for mode 0 and 1.
+ */
+static u32 nal_skip_policy = 2;
+
+/*
+ *bit 0, 1: only display I picture;
+ *bit 1, 1: only decode I picture;
+ */
+static u32 i_only_flag;
+static u32 skip_nal_count = 500;
+/*
+bit 0, fast output first I picture
+*/
+static u32 fast_output_enable = 1;
+
+static u32 frmbase_cont_bitlevel = 0x60;
+
+/*
+use_cma: 1, use both reserver memory and cma for buffers
+2, only use cma for buffers
+*/
+static u32 use_cma = 2;
+
+#define AUX_BUF_ALIGN(adr) ((adr + 0xf) & (~0xf))
+/*
+static u32 prefix_aux_buf_size = (16 * 1024);
+static u32 suffix_aux_buf_size;
+*/
+static u32 prefix_aux_buf_size = (12 * 1024);
+static u32 suffix_aux_buf_size = (12 * 1024);
+
+static u32 max_decoding_time;
+/*
+ *error handling
+ */
+/*error_handle_policy:
+ *bit 0: 0, auto skip error_skip_nal_count nals before error recovery;
+ *1, skip error_skip_nal_count nals before error recovery;
+ *bit 1 (valid only when bit0 == 1):
+ *1, wait vps/sps/pps after error recovery;
+ *bit 2 (valid only when bit0 == 0):
+ *0, auto search after error recovery (hevc_recover() called);
+ *1, manual search after error recovery
+ *(change to auto search after get IDR: WRITE_VREG(NAL_SEARCH_CTL, 0x2))
+ *
+ *bit 4: 0, set error_mark after reset/recover
+ *	1, do not set error_mark after reset/recover
+ *
+ *bit 5: 0, check total lcu for every picture
+ *	1, do not check total lcu
+ *
+ *bit 6: 0, do not check head error
+ *	1, check head error
+ *
+ *bit 7: 0, allow to print over decode
+ *       1, NOT allow to print over decode
+ *
+ *bit 8: 0, use interlace policy
+ *       1, NOT use interlace policy
+ *bit 9: 0, discard dirty data on playback start
+ *       1, do not discard dirty data on playback start
+ *bit 10:0, when ucode always returns again, it supports discarding data
+ *		 1, When ucode always returns again, it does not support discarding data
+ */
+
+static u32 error_handle_policy;
+static u32 error_skip_nal_count = 6;
+static u32 error_handle_threshold = 30;
+static u32 error_handle_nal_skip_threshold = 10;
+static u32 error_handle_system_threshold = 30;
+static u32 interlace_enable = 1;
+static u32 fr_hint_status;
+
+	/*
+	 *parser_sei_enable:
+	 *  bit 0, sei;
+	 *  bit 1, sei_suffix (fill aux buf)
+	 *  bit 2, fill sei to aux buf (when bit 0 is 1)
+	 *  bit 8, debug flag
+	 */
+static u32 parser_sei_enable;
+static u32 parser_dolby_vision_enable = 1;
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+static u32 dolby_meta_with_el;
+static u32 dolby_el_flush_th = 2;
+#endif
+/* this is only for h265 mmu enable */
+
+static u32 mmu_enable = 1;
+static u32 mmu_enable_force;
+static u32 work_buf_size;
+static unsigned int force_disp_pic_index;
+static unsigned int disp_vframe_valve_level;
+static int pre_decode_buf_level = 0x1000;
+static unsigned int pic_list_debug;
+#ifdef HEVC_8K_LFTOFFSET_FIX
+	/* performance_profile: bit 0, multi slice in ucode
+	*/
+static unsigned int performance_profile = 1;
+#endif
+#ifdef MULTI_INSTANCE_SUPPORT
+static unsigned int max_decode_instance_num
+				= MAX_DECODE_INSTANCE_NUM;
+static unsigned int decode_frame_count[MAX_DECODE_INSTANCE_NUM];
+static unsigned int display_frame_count[MAX_DECODE_INSTANCE_NUM];
+static unsigned int max_process_time[MAX_DECODE_INSTANCE_NUM];
+static unsigned int max_get_frame_interval[MAX_DECODE_INSTANCE_NUM];
+static unsigned int run_count[MAX_DECODE_INSTANCE_NUM];
+static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM];
+static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM];
+static unsigned int ref_frame_mark_flag[MAX_DECODE_INSTANCE_NUM] =
+{1, 1, 1, 1, 1, 1, 1, 1, 1};
+
+#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
+static unsigned char get_idx(struct hevc_state_s *hevc);
+#endif
+
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
+static u32 dv_toggle_prov_name;
+
+static u32 dv_debug;
+
+static u32 force_bypass_dvenl;
+#endif
+#endif
+
+/*
+ *[3:0] 0: default use config from omx.
+ *      1: force enable fence.
+ *      2: disable fence.
+ *[7:4] 0: fence use for driver.
+ *      1: fence fd use for app.
+ */
+static u32 force_config_fence;
+
+/*
+ *The parameter sps_max_dec_pic_buffering_minus1_0+1
+ *in SPS is the minimum DPB size required for stream
+ *(note: this parameter does not include the frame
+ *currently being decoded) +1 (decoding the current
+ *frame) +1 (decoding the current frame will only
+ *update refrence frame information, such as reference
+ *relation, when the next frame is decoded)
+ */
+static u32 detect_stuck_buffer_margin = 3;
+
+
+#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
+#define get_dbg_flag(hevc) ((debug_mask & (1 << hevc->index)) ? debug : 0)
+#define get_dbg_flag2(hevc) ((debug_mask & (1 << get_idx(hevc))) ? debug : 0)
+#define is_log_enable(hevc) ((log_mask & (1 << hevc->index)) ? 1 : 0)
+#else
+#define get_dbg_flag(hevc) debug
+#define get_dbg_flag2(hevc) debug
+#define is_log_enable(hevc) (log_mask ? 1 : 0)
+#define get_valid_double_write_mode(hevc) double_write_mode
+#define get_buf_alloc_width(hevc) buf_alloc_width
+#define get_buf_alloc_height(hevc) buf_alloc_height
+#define get_dynamic_buf_num_margin(hevc) dynamic_buf_num_margin
+#endif
+#define get_buffer_mode(hevc) buffer_mode
+
+
+static DEFINE_SPINLOCK(lock);
+struct task_struct *h265_task = NULL;
+#undef DEBUG_REG
+#ifdef DEBUG_REG
+void WRITE_VREG_DBG(unsigned adr, unsigned val)
+{
+	if (debug & H265_DEBUG_REG)
+		pr_info("%s(%x, %x)\n", __func__, adr, val);
+	WRITE_VREG(adr, val);
+}
+
+#undef WRITE_VREG
+#define WRITE_VREG WRITE_VREG_DBG
+#endif
+extern u32 trickmode_i;
+
+static DEFINE_MUTEX(vh265_mutex);
+
+static DEFINE_MUTEX(vh265_log_mutex);
+
+//static struct vdec_info *gvs;
+
+static u32 without_display_mode;
+
+static u32 mv_buf_dynamic_alloc;
+
+/**************************************************
+ *
+ *h265 buffer management include
+ *
+ ***************************************************
+ */
+enum NalUnitType {
+	NAL_UNIT_CODED_SLICE_TRAIL_N = 0,	/* 0 */
+	NAL_UNIT_CODED_SLICE_TRAIL_R,	/* 1 */
+
+	NAL_UNIT_CODED_SLICE_TSA_N,	/* 2 */
+	/* Current name in the spec: TSA_R */
+	NAL_UNIT_CODED_SLICE_TLA,	/* 3 */
+
+	NAL_UNIT_CODED_SLICE_STSA_N,	/* 4 */
+	NAL_UNIT_CODED_SLICE_STSA_R,	/* 5 */
+
+	NAL_UNIT_CODED_SLICE_RADL_N,	/* 6 */
+	/* Current name in the spec: RADL_R */
+	NAL_UNIT_CODED_SLICE_DLP,	/* 7 */
+
+	NAL_UNIT_CODED_SLICE_RASL_N,	/* 8 */
+	/* Current name in the spec: RASL_R */
+	NAL_UNIT_CODED_SLICE_TFD,	/* 9 */
+
+	NAL_UNIT_RESERVED_10,
+	NAL_UNIT_RESERVED_11,
+	NAL_UNIT_RESERVED_12,
+	NAL_UNIT_RESERVED_13,
+	NAL_UNIT_RESERVED_14,
+	NAL_UNIT_RESERVED_15,
+
+	/* Current name in the spec: BLA_W_LP */
+	NAL_UNIT_CODED_SLICE_BLA,	/* 16 */
+	/* Current name in the spec: BLA_W_DLP */
+	NAL_UNIT_CODED_SLICE_BLANT,	/* 17 */
+	NAL_UNIT_CODED_SLICE_BLA_N_LP,	/* 18 */
+	/* Current name in the spec: IDR_W_DLP */
+	NAL_UNIT_CODED_SLICE_IDR,	/* 19 */
+	NAL_UNIT_CODED_SLICE_IDR_N_LP,	/* 20 */
+	NAL_UNIT_CODED_SLICE_CRA,	/* 21 */
+	NAL_UNIT_RESERVED_22,
+	NAL_UNIT_RESERVED_23,
+
+	NAL_UNIT_RESERVED_24,
+	NAL_UNIT_RESERVED_25,
+	NAL_UNIT_RESERVED_26,
+	NAL_UNIT_RESERVED_27,
+	NAL_UNIT_RESERVED_28,
+	NAL_UNIT_RESERVED_29,
+	NAL_UNIT_RESERVED_30,
+	NAL_UNIT_RESERVED_31,
+
+	NAL_UNIT_VPS,		/* 32 */
+	NAL_UNIT_SPS,		/* 33 */
+	NAL_UNIT_PPS,		/* 34 */
+	NAL_UNIT_ACCESS_UNIT_DELIMITER,	/* 35 */
+	NAL_UNIT_EOS,		/* 36 */
+	NAL_UNIT_EOB,		/* 37 */
+	NAL_UNIT_FILLER_DATA,	/* 38 */
+	NAL_UNIT_SEI,		/* 39 Prefix SEI */
+	NAL_UNIT_SEI_SUFFIX,	/* 40 Suffix SEI */
+	NAL_UNIT_RESERVED_41,
+	NAL_UNIT_RESERVED_42,
+	NAL_UNIT_RESERVED_43,
+	NAL_UNIT_RESERVED_44,
+	NAL_UNIT_RESERVED_45,
+	NAL_UNIT_RESERVED_46,
+	NAL_UNIT_RESERVED_47,
+	NAL_UNIT_UNSPECIFIED_48,
+	NAL_UNIT_UNSPECIFIED_49,
+	NAL_UNIT_UNSPECIFIED_50,
+	NAL_UNIT_UNSPECIFIED_51,
+	NAL_UNIT_UNSPECIFIED_52,
+	NAL_UNIT_UNSPECIFIED_53,
+	NAL_UNIT_UNSPECIFIED_54,
+	NAL_UNIT_UNSPECIFIED_55,
+	NAL_UNIT_UNSPECIFIED_56,
+	NAL_UNIT_UNSPECIFIED_57,
+	NAL_UNIT_UNSPECIFIED_58,
+	NAL_UNIT_UNSPECIFIED_59,
+	NAL_UNIT_UNSPECIFIED_60,
+	NAL_UNIT_UNSPECIFIED_61,
+	NAL_UNIT_UNSPECIFIED_62,
+	NAL_UNIT_UNSPECIFIED_63,
+	NAL_UNIT_INVALID,
+};
+
+/* --------------------------------------------------- */
+/* Amrisc Software Interrupt */
+/* --------------------------------------------------- */
+#define AMRISC_STREAM_EMPTY_REQ 0x01
+#define AMRISC_PARSER_REQ       0x02
+#define AMRISC_MAIN_REQ         0x04
+
+/* --------------------------------------------------- */
+/* HEVC_DEC_STATUS define */
+/* --------------------------------------------------- */
+#define HEVC_DEC_IDLE                        0x0
+#define HEVC_NAL_UNIT_VPS                    0x1
+#define HEVC_NAL_UNIT_SPS                    0x2
+#define HEVC_NAL_UNIT_PPS                    0x3
+#define HEVC_NAL_UNIT_CODED_SLICE_SEGMENT    0x4
+#define HEVC_CODED_SLICE_SEGMENT_DAT         0x5
+#define HEVC_SLICE_DECODING                  0x6
+#define HEVC_NAL_UNIT_SEI                    0x7
+#define HEVC_SLICE_SEGMENT_DONE              0x8
+#define HEVC_NAL_SEARCH_DONE                 0x9
+#define HEVC_DECPIC_DATA_DONE                0xa
+#define HEVC_DECPIC_DATA_ERROR               0xb
+#define HEVC_SEI_DAT                         0xc
+#define HEVC_SEI_DAT_DONE                    0xd
+#define HEVC_NAL_DECODE_DONE				0xe
+#define HEVC_OVER_DECODE					0xf
+
+#define HEVC_DATA_REQUEST           0x12
+
+#define HEVC_DECODE_BUFEMPTY        0x20
+#define HEVC_DECODE_TIMEOUT         0x21
+#define HEVC_SEARCH_BUFEMPTY        0x22
+#define HEVC_DECODE_OVER_SIZE       0x23
+#define HEVC_DECODE_BUFEMPTY2       0x24
+#define HEVC_FIND_NEXT_PIC_NAL				0x50
+#define HEVC_FIND_NEXT_DVEL_NAL				0x51
+
+#define HEVC_DUMP_LMEM				0x30
+
+#define HEVC_4k2k_60HZ_NOT_SUPPORT	0x80
+#define HEVC_DISCARD_NAL         0xf0
+#define HEVC_ACTION_DEC_CONT     0xfd
+#define HEVC_ACTION_ERROR        0xfe
+#define HEVC_ACTION_DONE         0xff
+
+/* --------------------------------------------------- */
+/* Include "parser_cmd.h" */
+/* --------------------------------------------------- */
+#define PARSER_CMD_SKIP_CFG_0 0x0000090b
+
+#define PARSER_CMD_SKIP_CFG_1 0x1b14140f
+
+#define PARSER_CMD_SKIP_CFG_2 0x001b1910
+
+#define PARSER_CMD_NUMBER 37
+
+/**************************************************
+ *
+ *h265 buffer management
+ *
+ ***************************************************
+ */
+/* #define BUFFER_MGR_ONLY */
+/* #define CONFIG_HEVC_CLK_FORCED_ON */
+/* #define ENABLE_SWAP_TEST */
+#define   MCRCC_ENABLE
+#define INVALID_POC 0x80000000
+
+#define HEVC_DEC_STATUS_REG       HEVC_ASSIST_SCRATCH_0
+#define HEVC_RPM_BUFFER           HEVC_ASSIST_SCRATCH_1
+#define HEVC_SHORT_TERM_RPS       HEVC_ASSIST_SCRATCH_2
+#define HEVC_VPS_BUFFER           HEVC_ASSIST_SCRATCH_3
+#define HEVC_SPS_BUFFER           HEVC_ASSIST_SCRATCH_4
+#define HEVC_PPS_BUFFER           HEVC_ASSIST_SCRATCH_5
+#define HEVC_SAO_UP               HEVC_ASSIST_SCRATCH_6
+#define HEVC_STREAM_SWAP_BUFFER   HEVC_ASSIST_SCRATCH_7
+#define HEVC_STREAM_SWAP_BUFFER2  HEVC_ASSIST_SCRATCH_8
+#define HEVC_sao_mem_unit         HEVC_ASSIST_SCRATCH_9
+#define HEVC_SAO_ABV              HEVC_ASSIST_SCRATCH_A
+#define HEVC_sao_vb_size          HEVC_ASSIST_SCRATCH_B
+#define HEVC_SAO_VB               HEVC_ASSIST_SCRATCH_C
+#define HEVC_SCALELUT             HEVC_ASSIST_SCRATCH_D
+#define HEVC_WAIT_FLAG            HEVC_ASSIST_SCRATCH_E
+#define RPM_CMD_REG               HEVC_ASSIST_SCRATCH_F
+#define LMEM_DUMP_ADR                 HEVC_ASSIST_SCRATCH_F
+#ifdef ENABLE_SWAP_TEST
+#define HEVC_STREAM_SWAP_TEST     HEVC_ASSIST_SCRATCH_L
+#endif
+
+/*#define HEVC_DECODE_PIC_BEGIN_REG HEVC_ASSIST_SCRATCH_M*/
+/*#define HEVC_DECODE_PIC_NUM_REG   HEVC_ASSIST_SCRATCH_N*/
+#define HEVC_DECODE_SIZE		HEVC_ASSIST_SCRATCH_N
+	/*do not define ENABLE_SWAP_TEST*/
+#define HEVC_AUX_ADR			HEVC_ASSIST_SCRATCH_L
+#define HEVC_AUX_DATA_SIZE		HEVC_ASSIST_SCRATCH_M
+
+#define DEBUG_REG1              HEVC_ASSIST_SCRATCH_G
+#define DEBUG_REG2              HEVC_ASSIST_SCRATCH_H
+/*
+ *ucode parser/search control
+ *bit 0:  0, header auto parse; 1, header manual parse
+ *bit 1:  0, auto skip for noneseamless stream; 1, no skip
+ *bit [3:2]: valid when bit1==0;
+ *0, auto skip nal before first vps/sps/pps/idr;
+ *1, auto skip nal before first vps/sps/pps
+ *2, auto skip nal before first  vps/sps/pps,
+ *	and not decode until the first I slice (with slice address of 0)
+ *
+ *3, auto skip before first I slice (nal_type >=16 && nal_type<=21)
+ *bit [15:4] nal skip count (valid when bit0 == 1 (manual mode) )
+ *bit [16]: for NAL_UNIT_EOS when bit0 is 0:
+ *	0, send SEARCH_DONE to arm ;  1, do not send SEARCH_DONE to arm
+ *bit [17]: for NAL_SEI when bit0 is 0:
+ *	0, do not parse/fetch SEI in ucode;
+ *	1, parse/fetch SEI in ucode
+ *bit [18]: for NAL_SEI_SUFFIX when bit0 is 0:
+ *	0, do not fetch NAL_SEI_SUFFIX to aux buf;
+ *	1, fetch NAL_SEL_SUFFIX data to aux buf
+ *bit [19]:
+ *	0, parse NAL_SEI in ucode
+ *	1, fetch NAL_SEI to aux buf
+ *bit [20]: for DOLBY_VISION_META
+ *	0, do not fetch DOLBY_VISION_META to aux buf
+ *	1, fetch DOLBY_VISION_META to aux buf
+ */
+#define NAL_SEARCH_CTL            HEVC_ASSIST_SCRATCH_I
+	/*read only*/
+#define CUR_NAL_UNIT_TYPE       HEVC_ASSIST_SCRATCH_J
+	/*
+	[15 : 8] rps_set_id
+	[7 : 0] start_decoding_flag
+	*/
+#define HEVC_DECODE_INFO       HEVC_ASSIST_SCRATCH_1
+	/*set before start decoder*/
+#define HEVC_DECODE_MODE		HEVC_ASSIST_SCRATCH_J
+#define HEVC_DECODE_MODE2		HEVC_ASSIST_SCRATCH_H
+#define DECODE_STOP_POS         HEVC_ASSIST_SCRATCH_K
+
+#define DECODE_MODE_SINGLE					0x0
+#define DECODE_MODE_MULTI_FRAMEBASE			0x1
+#define DECODE_MODE_MULTI_STREAMBASE		0x2
+#define DECODE_MODE_MULTI_DVBAL				0x3
+#define DECODE_MODE_MULTI_DVENL				0x4
+
+#define MAX_INT 0x7FFFFFFF
+
+#define RPM_BEGIN                                              0x100
+#define modification_list_cur                                  0x148
+#define RPM_END                                                0x180
+#ifdef SUPPORT_LONG_TERM_RPS
+/*
+  */
+#define RPS_END  0x8000
+#define RPS_LT_BIT 		14
+#define RPS_USED_BIT        13
+#define RPS_SIGN_BIT        12
+#else
+#define RPS_END		0x8000
+#define RPS_USED_BIT        14
+#define RPS_SIGN_BIT        13
+#endif
+/* MISC_FLAG0 */
+#define PCM_LOOP_FILTER_DISABLED_FLAG_BIT       0
+#define PCM_ENABLE_FLAG_BIT             1
+#define LOOP_FILER_ACROSS_TILES_ENABLED_FLAG_BIT    2
+#define PPS_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT  3
+#define DEBLOCKING_FILTER_OVERRIDE_ENABLED_FLAG_BIT 4
+#define PPS_DEBLOCKING_FILTER_DISABLED_FLAG_BIT     5
+#define DEBLOCKING_FILTER_OVERRIDE_FLAG_BIT     6
+#define SLICE_DEBLOCKING_FILTER_DISABLED_FLAG_BIT   7
+#define SLICE_SAO_LUMA_FLAG_BIT             8
+#define SLICE_SAO_CHROMA_FLAG_BIT           9
+#define SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED_FLAG_BIT 10
+
+union param_u {
+	struct {
+		unsigned short data[RPM_END - RPM_BEGIN];
+	} l;
+	struct {
+		/* from ucode lmem, do not change this struct */
+		unsigned short CUR_RPS[0x10];
+		unsigned short num_ref_idx_l0_active;
+		unsigned short num_ref_idx_l1_active;
+		unsigned short slice_type;
+		unsigned short slice_temporal_mvp_enable_flag;
+		unsigned short dependent_slice_segment_flag;
+		unsigned short slice_segment_address;
+		unsigned short num_title_rows_minus1;
+		unsigned short pic_width_in_luma_samples;
+		unsigned short pic_height_in_luma_samples;
+		unsigned short log2_min_coding_block_size_minus3;
+		unsigned short log2_diff_max_min_coding_block_size;
+		unsigned short log2_max_pic_order_cnt_lsb_minus4;
+		unsigned short POClsb;
+		unsigned short collocated_from_l0_flag;
+		unsigned short collocated_ref_idx;
+		unsigned short log2_parallel_merge_level;
+		unsigned short five_minus_max_num_merge_cand;
+		unsigned short sps_num_reorder_pics_0;
+		unsigned short modification_flag;
+		unsigned short tiles_enabled_flag;
+		unsigned short num_tile_columns_minus1;
+		unsigned short num_tile_rows_minus1;
+		unsigned short tile_width[12];
+		unsigned short tile_height[8];
+		unsigned short misc_flag0;
+		unsigned short pps_beta_offset_div2;
+		unsigned short pps_tc_offset_div2;
+		unsigned short slice_beta_offset_div2;
+		unsigned short slice_tc_offset_div2;
+		unsigned short pps_cb_qp_offset;
+		unsigned short pps_cr_qp_offset;
+		unsigned short first_slice_segment_in_pic_flag;
+		unsigned short m_temporalId;
+		unsigned short m_nalUnitType;
+
+		unsigned short vui_num_units_in_tick_hi;
+		unsigned short vui_num_units_in_tick_lo;
+		unsigned short vui_time_scale_hi;
+		unsigned short vui_time_scale_lo;
+		unsigned short bit_depth;
+		unsigned short profile_etc;
+		unsigned short sei_frame_field_info;
+		unsigned short video_signal_type;
+		unsigned short modification_list[0x20];
+		unsigned short conformance_window_flag;
+		unsigned short conf_win_left_offset;
+		unsigned short conf_win_right_offset;
+		unsigned short conf_win_top_offset;
+		unsigned short conf_win_bottom_offset;
+		unsigned short chroma_format_idc;
+		unsigned short color_description;
+		unsigned short aspect_ratio_idc;
+		unsigned short sar_width;
+		unsigned short sar_height;
+		unsigned short sps_max_dec_pic_buffering_minus1_0;
+	} p;
+};
+
+#define RPM_BUF_SIZE (0x80*2)
+/* non mmu mode lmem size : 0x400, mmu mode : 0x500*/
+#define LMEM_BUF_SIZE (0x500 * 2)
+
+struct buff_s {
+	u32 buf_start;
+	u32 buf_size;
+	u32 buf_end;
+};
+
+struct BuffInfo_s {
+	u32 max_width;
+	u32 max_height;
+	unsigned int start_adr;
+	unsigned int end_adr;
+	struct buff_s ipp;
+	struct buff_s sao_abv;
+	struct buff_s sao_vb;
+	struct buff_s short_term_rps;
+	struct buff_s vps;
+	struct buff_s sps;
+	struct buff_s pps;
+	struct buff_s sao_up;
+	struct buff_s swap_buf;
+	struct buff_s swap_buf2;
+	struct buff_s scalelut;
+	struct buff_s dblk_para;
+	struct buff_s dblk_data;
+	struct buff_s dblk_data2;
+	struct buff_s mmu_vbh;
+	struct buff_s cm_header;
+#ifdef H265_10B_MMU_DW
+	struct buff_s mmu_vbh_dw;
+	struct buff_s cm_header_dw;
+#endif
+	struct buff_s mpred_above;
+#ifdef MV_USE_FIXED_BUF
+	struct buff_s mpred_mv;
+#endif
+	struct buff_s rpm;
+	struct buff_s lmem;
+};
+
+//#define VBH_BUF_SIZE (2 * 16 * 2304)
+//#define VBH_BUF_COUNT 4
+
+/*mmu_vbh buf is used by HEVC_SAO_MMU_VH0_ADDR, HEVC_SAO_MMU_VH1_ADDR*/
+#define VBH_BUF_SIZE_1080P 0x3000
+#define VBH_BUF_SIZE_4K 0x5000
+#define VBH_BUF_SIZE_8K 0xa000
+#define VBH_BUF_SIZE(bufspec) (bufspec->mmu_vbh.buf_size / 2)
+	/*mmu_vbh_dw buf is used by HEVC_SAO_MMU_VH0_ADDR2,HEVC_SAO_MMU_VH1_ADDR2,
+		HEVC_DW_VH0_ADDDR, HEVC_DW_VH1_ADDDR*/
+#define DW_VBH_BUF_SIZE_1080P (VBH_BUF_SIZE_1080P * 2)
+#define DW_VBH_BUF_SIZE_4K (VBH_BUF_SIZE_4K * 2)
+#define DW_VBH_BUF_SIZE_8K (VBH_BUF_SIZE_8K * 2)
+#define DW_VBH_BUF_SIZE(bufspec) (bufspec->mmu_vbh_dw.buf_size / 4)
+
+/* necessary 4K page size align for t7/t3 decoder and after */
+#define WORKBUF_ALIGN(addr) (ALIGN(addr, PAGE_SIZE))
+
+#define WORK_BUF_SPEC_NUM 6
+static struct BuffInfo_s amvh265_workbuff_spec[WORK_BUF_SPEC_NUM] = {
+	{
+		/* 8M bytes */
+		.max_width = 1920,
+		.max_height = 1088,
+		.ipp = {
+			/* IPP work space calculation :
+			 *   4096 * (Y+CbCr+Flags) = 12k, round to 16k
+			 */
+			.buf_size = 0x4000,
+		},
+		.sao_abv = {
+			.buf_size = 0x30000,
+		},
+		.sao_vb = {
+			.buf_size = 0x30000,
+		},
+		.short_term_rps = {
+			/* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
+			 *   total 64x16x2 = 2048 bytes (0x800)
+			 */
+			.buf_size = 0x800,
+		},
+		.vps = {
+			/* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes,
+			 *   total 0x0800 bytes
+			 */
+			.buf_size = 0x800,
+		},
+		.sps = {
+			/* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
+			 *   total 0x0800 bytes
+			 */
+			.buf_size = 0x800,
+		},
+		.pps = {
+			/* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes,
+			 *   total 0x2000 bytes
+			 */
+			.buf_size = 0x2000,
+		},
+		.sao_up = {
+			/* SAO UP STORE AREA - Max 640(10240/16) LCU,
+			 *   each has 16 bytes total 0x2800 bytes
+			 */
+			.buf_size = 0x2800,
+		},
+		.swap_buf = {
+			/* 256cyclex64bit = 2K bytes 0x800
+			 *   (only 144 cycles valid)
+			 */
+			.buf_size = 0x800,
+		},
+		.swap_buf2 = {
+			.buf_size = 0x800,
+		},
+		.scalelut = {
+			/* support up to 32 SCALELUT 1024x32 =
+			 *   32Kbytes (0x8000)
+			 */
+			.buf_size = 0x8000,
+		},
+		.dblk_para = {
+#ifdef SUPPORT_10BIT
+			.buf_size = 0x40000,
+#else
+			/* DBLK -> Max 256(4096/16) LCU, each para
+			 *512bytes(total:0x20000), data 1024bytes(total:0x40000)
+			 */
+			.buf_size = 0x20000,
+#endif
+		},
+		.dblk_data = {
+			.buf_size = 0x40000,
+		},
+		.dblk_data2 = {
+			.buf_size = 0x80000 * 2,
+		}, /*dblk data for adapter*/
+		.mmu_vbh = {
+			.buf_size = 0x5000, /*2*16*2304/4, 4K*/
+		},
+#if 0
+		.cm_header = {/* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/
+			.buf_size = MMU_COMPRESS_HEADER_SIZE *
+			(MAX_REF_PIC_NUM + 1),
+		},
+#endif
+		.mpred_above = {
+			.buf_size = 0x8000,
+		},
+#ifdef MV_USE_FIXED_BUF
+		.mpred_mv = {/* 1080p, 0x40000 per buffer */
+			.buf_size = 0x40000 * MAX_REF_PIC_NUM,
+		},
+#endif
+		.rpm = {
+			.buf_size = RPM_BUF_SIZE,
+		},
+		.lmem = {
+			.buf_size = 0x500 * 2,
+		}
+	},
+	{
+		.max_width = 4096,
+		.max_height = 2048,
+		.ipp = {
+			/* IPP work space calculation :
+			 *   4096 * (Y+CbCr+Flags) = 12k, round to 16k
+			 */
+			.buf_size = 0x1e00,
+		},
+		.sao_abv = {
+			.buf_size = 0, //0x30000,
+		},
+		.sao_vb = {
+			.buf_size = 0, //0x30000,
+		},
+		.short_term_rps = {
+			/* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
+			 *   total 64x16x2 = 2048 bytes (0x800)
+			 */
+			.buf_size = 0x800,
+		},
+		.vps = {
+			/* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes,
+			 *   total 0x0800 bytes
+			 */
+			.buf_size = 0x800,
+		},
+		.sps = {
+			/* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
+			 *   total 0x0800 bytes
+			 */
+			.buf_size = 0x800,
+		},
+		.pps = {
+			/* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes,
+			 *   total 0x2000 bytes
+			 */
+			.buf_size = 0x2000,
+		},
+		.sao_up = {
+			/* SAO UP STORE AREA - Max 640(10240/16) LCU,
+			 *   each has 16 bytes total 0x2800 bytes
+			 */
+			.buf_size = 0x2800,
+		},
+		.swap_buf = {
+			/* 256cyclex64bit = 2K bytes 0x800
+			 *   (only 144 cycles valid)
+			 */
+			.buf_size = 0x800,
+		},
+		.swap_buf2 = {
+			.buf_size = 0x800,
+		},
+		.scalelut = {
+			/* support up to 32 SCALELUT 1024x32 = 32Kbytes
+			 *   (0x8000)
+			 */
+			.buf_size = 0x8000,
+		},
+		.dblk_para = {
+			/* DBLK -> Max 256(4096/16) LCU, each para
+			 *   512bytes(total:0x20000),
+			 *   data 1024bytes(total:0x40000)
+			 */
+			.buf_size = 0x20000,
+		},
+		.dblk_data = {
+			.buf_size = 0x80000,
+		},
+		.dblk_data2 = {
+			.buf_size = 0x80000,
+		}, /*dblk data for adapter*/
+		.mmu_vbh = {
+			.buf_size = 0x5000, /*2*16*2304/4, 4K*/
+		},
+#if 0
+		.cm_header = {/*0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/
+			.buf_size = MMU_COMPRESS_HEADER_SIZE *
+			(MAX_REF_PIC_NUM + 1),
+		},
+#endif
+		.mpred_above = {
+			.buf_size = 0x8000,
+		},
+#ifdef MV_USE_FIXED_BUF
+		.mpred_mv = {
+			/* .buf_size = 0x100000*16,
+			//4k2k , 0x100000 per buffer */
+			/* 4096x2304 , 0x120000 per buffer */
+			.buf_size = MPRED_4K_MV_BUF_SIZE * MAX_REF_PIC_NUM,
+		},
+#endif
+		.rpm = {
+			.buf_size = RPM_BUF_SIZE,
+		},
+		.lmem = {
+			.buf_size = 0x500 * 2,
+		}
+	},
+
+	{
+		.max_width = 4096*2,
+		.max_height = 2048*2,
+		.ipp = {
+			// IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k
+			.buf_size = 0x4000*2,
+		},
+		.sao_abv = {
+			.buf_size = 0x30000*2,
+		},
+		.sao_vb = {
+			.buf_size = 0x30000*2,
+		},
+		.short_term_rps = {
+			// SHORT_TERM_RPS - Max 64 set, 16 entry every set, total 64x16x2 = 2048 bytes (0x800)
+			.buf_size = 0x800,
+		},
+		.vps = {
+			// VPS STORE AREA - Max 16 VPS, each has 0x80 bytes, total 0x0800 bytes
+			.buf_size = 0x800,
+		},
+		.sps = {
+			// SPS STORE AREA - Max 16 SPS, each has 0x80 bytes, total 0x0800 bytes
+			.buf_size = 0x800,
+		},
+		.pps = {
+			// PPS STORE AREA - Max 64 PPS, each has 0x80 bytes, total 0x2000 bytes
+			.buf_size = 0x2000,
+		},
+		.sao_up = {
+			// SAO UP STORE AREA - Max 640(10240/16) LCU, each has 16 bytes total 0x2800 bytes
+			.buf_size = 0x2800*2,
+		},
+		.swap_buf = {
+			// 256cyclex64bit = 2K bytes 0x800 (only 144 cycles valid)
+			.buf_size = 0x800,
+		},
+		.swap_buf2 = {
+			.buf_size = 0x800,
+		},
+		.scalelut = {
+			// support up to 32 SCALELUT 1024x32 = 32Kbytes (0x8000)
+			.buf_size = 0x8000*2,
+		},
+		.dblk_para  = {.buf_size = 0x40000*2, }, // dblk parameter
+		.dblk_data  = {.buf_size = 0x80000*2, }, // dblk data for left/top
+		.dblk_data2 = {.buf_size = 0x80000*2, }, // dblk data for adapter
+		.mmu_vbh = {
+			.buf_size = 0x5000*2, //2*16*2304/4, 4K
+		},
+#if 0
+		.cm_header = {
+			.buf_size = MMU_COMPRESS_8K_HEADER_SIZE *
+				MAX_REF_PIC_NUM, 	// 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
+		},
+#endif
+		.mpred_above = {
+			.buf_size = 0x8000*2,
+		},
+#ifdef MV_USE_FIXED_BUF
+		.mpred_mv = {
+			.buf_size = MPRED_8K_MV_BUF_SIZE * MAX_REF_PIC_NUM, //4k2k , 0x120000 per buffer
+		},
+#endif
+		.rpm = {
+			.buf_size = RPM_BUF_SIZE,
+		},
+		.lmem = {
+			.buf_size = 0x500 * 2,
+		},
+	},
+	{
+		/* 8M bytes */
+		.max_width = 1920,
+		.max_height = 1088,
+		.ipp = {/*checked*/
+			/* IPP work space calculation :
+			 *   4096 * (Y+CbCr+Flags) = 12k, round to 16k
+			 */
+			.buf_size = 0x1e00,
+		},
+		.sao_abv = {
+			.buf_size = 0, //0x30000,
+		},
+		.sao_vb = {
+			.buf_size = 0, //0x30000,
+		},
+		.short_term_rps = {/*checked*/
+			/* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
+			 *   total 64x16x2 = 2048 bytes (0x800)
+			 */
+			.buf_size = 0x800,
+		},
+		.vps = {/*checked*/
+			/* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes,
+			 *   total 0x0800 bytes
+			 */
+			.buf_size = 0x800,
+		},
+		.sps = {/*checked*/
+			/* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
+			 *   total 0x0800 bytes
+			 */
+			.buf_size = 0x800,
+		},
+		.pps = {/*checked*/
+			/* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes,
+			 *   total 0x2000 bytes
+			 */
+			.buf_size = 0x2000,
+		},
+		.sao_up = {
+			/* SAO UP STORE AREA - Max 640(10240/16) LCU,
+			 *   each has 16 bytes total 0x2800 bytes
+			 */
+			.buf_size = 0, //0x2800,
+		},
+		.swap_buf = {/*checked*/
+			/* 256cyclex64bit = 2K bytes 0x800
+			 *   (only 144 cycles valid)
+			 */
+			.buf_size = 0x800,
+		},
+		.swap_buf2 = {/*checked*/
+			.buf_size = 0x800,
+		},
+		.scalelut = {/*checked*/
+			/* support up to 32 SCALELUT 1024x32 =
+			 *   32Kbytes (0x8000)
+			 */
+			.buf_size = 0x8000,
+		},
+		.dblk_para  = {.buf_size = 0x14500, }, // dblk parameter
+		.dblk_data  = {.buf_size = 0x62800, }, // dblk data for left/top
+		.dblk_data2 = {.buf_size = 0x22800, }, // dblk data for adapter
+		.mmu_vbh = {/*checked*/
+			.buf_size = VBH_BUF_SIZE_1080P, /*2*16*2304/4, 4K*/
+		},
+#if 0
+		.cm_header = {/*checked*//* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/
+			.buf_size = MMU_COMPRESS_HEADER_SIZE_1080P *
+			(MAX_REF_PIC_NUM + 1),
+		},
+#endif
+#ifdef H265_10B_MMU_DW
+		.mmu_vbh_dw = {/*checked*/
+			.buf_size = DW_VBH_BUF_SIZE_1080P, //VBH_BUF_SIZE * VBH_BUF_COUNT, //2*16*2304/4, 4K
+		},
+#ifdef USE_FIXED_MMU_DW_HEADER
+		.cm_header_dw = {/*checked*/
+			.buf_size = MMU_COMPRESS_HEADER_SIZE_1080P * DB_NUM, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
+		},
+#endif
+#endif
+		.mpred_above = {/*checked*/
+			.buf_size = 0x1e00,
+		},
+#ifdef MV_USE_FIXED_BUF
+		.mpred_mv = {/*checked*//* 1080p, 0x40000 per buffer */
+			.buf_size = MPRED_MV_BUF_SIZE * MAX_REF_PIC_NUM,
+		},
+#endif
+		.rpm = {/*checked*/
+			.buf_size = RPM_BUF_SIZE,
+		},
+		.lmem = {/*checked*/
+			.buf_size = 0x500 * 2,
+		}
+	},
+	{
+		.max_width = 4096,
+		.max_height = 2048,
+		.ipp = {
+			/* IPP work space calculation :
+			 *   4096 * (Y+CbCr+Flags) = 12k, round to 16k
+			 */
+			.buf_size = 0x4000,
+		},
+		.sao_abv = {
+			.buf_size = 0, //0x30000,
+		},
+		.sao_vb = {
+			.buf_size = 0, //0x30000,
+		},
+		.short_term_rps = {
+			/* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
+			 *   total 64x16x2 = 2048 bytes (0x800)
+			 */
+			.buf_size = 0x800,
+		},
+		.vps = {
+			/* VPS STORE AREA - Max 16 VPS, each has 0x80 bytes,
+			 *   total 0x0800 bytes
+			 */
+			.buf_size = 0x800,
+		},
+		.sps = {
+			/* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
+			 *   total 0x0800 bytes
+			 */
+			.buf_size = 0x800,
+		},
+		.pps = {
+			/* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes,
+			 *   total 0x2000 bytes
+			 */
+			.buf_size = 0x2000,
+		},
+		.sao_up = {
+			/* SAO UP STORE AREA - Max 640(10240/16) LCU,
+			 *   each has 16 bytes total 0x2800 bytes
+			 */
+			.buf_size = 0, //0x2800,
+		},
+		.swap_buf = {
+			/* 256cyclex64bit = 2K bytes 0x800
+			 *   (only 144 cycles valid)
+			 */
+			.buf_size = 0x800,
+		},
+		.swap_buf2 = {
+			.buf_size = 0x800,
+		},
+		.scalelut = {
+			/* support up to 32 SCALELUT 1024x32 = 32Kbytes
+			 *   (0x8000)
+			 */
+			.buf_size = 0x8000,
+		},
+		.dblk_para  = {.buf_size = 0x19100, }, // dblk parameter
+		.dblk_data  = {.buf_size = 0x88800, }, // dblk data for left/top
+		.dblk_data2 = {.buf_size = 0x48800, }, // dblk data for adapter
+		.mmu_vbh = {
+			.buf_size = VBH_BUF_SIZE_4K, /*2*16*2304/4, 4K*/
+		},
+#if 0
+		.cm_header = {/*0x44000 = ((1088*2*1024*4)/32/4)*(32/8)*/
+			.buf_size = MMU_COMPRESS_HEADER_SIZE_4K *
+			(MAX_REF_PIC_NUM + 1),
+		},
+#endif
+#ifdef H265_10B_MMU_DW
+		.mmu_vbh_dw = {
+			.buf_size = DW_VBH_BUF_SIZE_4K, //VBH_BUF_SIZE * VBH_BUF_COUNT, //2*16*(more than 2304)/4, 4K
+		},
+#ifdef USE_FIXED_MMU_DW_HEADER
+		.cm_header_dw = {
+			.buf_size = MMU_COMPRESS_HEADER_SIZE_4K * DB_NUM, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
+		},
+#endif
+#endif
+		.mpred_above = {
+			.buf_size = 0x4000,
+		},
+#ifdef MV_USE_FIXED_BUF
+		.mpred_mv = {
+			/* .buf_size = 0x100000*16,
+			//4k2k , 0x100000 per buffer */
+			/* 4096x2304 , 0x120000 per buffer */
+			.buf_size = MPRED_4K_MV_BUF_SIZE * MAX_REF_PIC_NUM,
+		},
+#endif
+		.rpm = {
+			.buf_size = RPM_BUF_SIZE,
+		},
+		.lmem = {
+			.buf_size = 0x500 * 2,
+		}
+	},
+
+	{
+		.max_width = 4096*2,
+		.max_height = 2048*2,
+		.ipp = {
+			// IPP work space calculation : 4096 * (Y+CbCr+Flags) = 12k, round to 16k
+			.buf_size = 0x4000*2,
+		},
+		.sao_abv = {
+			.buf_size = 0, //0x30000*2,
+		},
+		.sao_vb = {
+			.buf_size = 0, //0x30000*2,
+		},
+		.short_term_rps = {
+			// SHORT_TERM_RPS - Max 64 set, 16 entry every set, total 64x16x2 = 2048 bytes (0x800)
+			.buf_size = 0x800,
+		},