Project import generated by Copybara.

GitOrigin-RevId: 05dc909ff03281f027f18caebd767cfbe166299b
diff --git a/Makefile b/Makefile
old mode 100644
new mode 100755
index 6640ff9..7481eee
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,6 @@
+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 \
@@ -15,21 +18,25 @@
 	CONFIG_AMLOGIC_MEDIA_VDEC_AVS=m \
 	CONFIG_AMLOGIC_MEDIA_VDEC_AVS_MULTI=m \
 	CONFIG_AMLOGIC_MEDIA_VDEC_AVS2=m \
-	CONFIG_AMLOGIC_MEDIA_VDEC_AV1=m \
 	CONFIG_AMLOGIC_MEDIA_VENC_H264=m \
-	CONFIG_AMLOGIC_MEDIA_VENC_JPEG=m \
-	CONFIG_AMLOGIC_MEDIA_VENC_H265=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-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)" $(CONFIGS)
+	$(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
 
diff --git a/Media.mk b/Media.mk
index 68b0778..58db63b 100644
--- a/Media.mk
+++ b/Media.mk
@@ -18,13 +18,13 @@
 	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_VDEC_AV1=m \
 	CONFIG_AMLOGIC_MEDIA_VENC_H264=m \
-	CONFIG_AMLOGIC_MEDIA_VENC_JPEG=m \
 	CONFIG_AMLOGIC_MEDIA_VENC_H265=m \
-	CONFIG_FRAME_WARN=4096
+	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"),\
@@ -63,11 +63,10 @@
 $(shell cp $(MEDIA_DRIVERS)/* $(MEDIA_MODULES) -rfa)
 
 define media-modules
-	PATH=$$(cd ./$(TARGET_HOST_TOOL_PATH); pwd):$$PATH \
-		$(MAKE) -C $(KDIR) M=$(MEDIA_MODULES) ARCH=$(KERNEL_ARCH) \
-		CROSS_COMPILE=$(PREFIX_CROSS_COMPILE) $(CONFIGS) \
-		EXTRA_CFLAGS+=-I$(INCLUDE) modules;
-		sh $(TOP)/device/amlogic/common/copy_modules.sh $(MEDIA_MODULES) $(MODS_OUT)
+	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
@@ -91,18 +90,10 @@
 $(shell mkdir $(MODS_OUT) -p)
 endif
 
-ifeq ($(KERNEL_A32_SUPPORT), true)
-TOOLS := /opt/gcc-linaro-6.3.1-2017.02-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
-else
-TOOLS := /opt/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
-endif
-
-
 modules:
-	CCACHE_NODIRECT="true" PATH=$$(cd ./$(TARGET_HOST_TOOL_PATH); pwd):$$PATH \
-		$(MAKE) -C $(KDIR) M=$(MEDIA_DRIVERS) ARCH=$(KERNEL_ARCH) \
-		CROSS_COMPILE=$(TOOLS) $(CONFIGS) \
-		EXTRA_CFLAGS+=-I$(INCLUDE) -j64
+	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."
@@ -111,8 +102,9 @@
 
 all: modules copy-modules
 
+
 clean:
-	PATH=$$(cd ./$(TARGET_HOST_TOOL_PATH); pwd):$$PATH \
-		$(MAKE) -C $(KDIR) M=$(MEDIA_DRIVERS) ARCH=$(KERNEL_ARCH) 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/build_media.sh b/build_media.sh
deleted file mode 100755
index 63eaf1a..0000000
--- a/build_media.sh
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/bin/bash
-# Builds the media driver and updates the workspace path with output files
-
-exec_name=$0
-
-cpu_num=$(grep -c processor /proc/cpuinfo)
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
-CROSS_COMPILE=$DIR/../prebuilt/toolchain/aarch64/bin/aarch64-cros-linux-gnu-
-KERNEL_ARCH=arm64
-KDIR=$DIR/../kernel
-INCLUDE=$DIR/drivers/include
-MEDIA_MODULES=$DIR/drivers
-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_FRAME_WARN=4096"
-
-set -o errtrace
-trap 'echo Fatal error: script ${exec_name} aborting at line $LINENO, command \"$BASH_COMMAND\" returned $?; exit 1' ERR
-
-function usage(){
-  echo "Usage: ${exec_name} <product> [workspace path]"
-  echo "supported products: sabrina"
-  echo "Note: if [workspace path] is not set, it still builds"
-}
-
-if (( $# < 1 ))
-then
-  usage
-  exit 2
-fi
-
-readonly product=$1
-readonly workspace_path=$2
-
-pushd $DIR
-
-
-make -C $KDIR M=$MEDIA_MODULES ARCH=$KERNEL_ARCH \
-CROSS_COMPILE=$CROSS_COMPILE $CONFIGS \
-EXTRA_CFLAGS+=-I$INCLUDE modules -j64
-
-case $product in
-  sabrina*)
-    ;;
-  *)
-    echo "unknown product: $product"
-    exit 1
-esac
-
-popd
-
-if [ ! -z $workspace_path ]; then
-  media_out_dir=${workspace_path}/device/google/${product}-kernel/lib/modules
-  mkdir -p ${media_out_dir}
-
-  for ko in aml_hardware_dmx.ko \
-            amvdec_avs2.ko \
-            amvdec_avs.ko \
-            amvdec_h264.ko \
-            amvdec_h264mvc.ko \
-            amvdec_h265.ko \
-            amvdec_mh264.ko \
-            amvdec_mjpeg.ko \
-            amvdec_mmjpeg.ko \
-            amvdec_mmpeg12.ko \
-            amvdec_mmpeg4.ko \
-            amvdec_mpeg12.ko \
-            amvdec_mpeg4.ko \
-            amvdec_real.ko \
-            amvdec_vc1.ko \
-            amvdec_vp9.ko \
-            decoder_common.ko \
-            encoder.ko \
-            firmware.ko \
-            media_clock.ko \
-            stream_input.ko \
-            vpu.ko \
-            amvdec_ports.ko \
-            video_framerate_adapter.ko \
-            media_sync.ko
-  do
-    find $MEDIA_MODULES -name $ko | xargs -i cp {} $media_out_dir
-  done
-  media_fw_out_dir=${workspace_path}/device/google/${product}-kernel/lib/firmware/video/
-  mkdir -p $media_fw_out_dir
-  cp -r firmware/* $media_fw_out_dir
-fi
diff --git a/drivers/Makefile b/drivers/Makefile
index 3e487db..e96ba44 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -3,6 +3,6 @@
 obj-y	+=	frame_sink/
 obj-y	+=	stream_input/
 obj-y	+=	amvdec_ports/
-obj-y	+=	fake_video_out/
 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
index 6395adf..2e7cff4 100644
--- a/drivers/amvdec_ports/Makefile
+++ b/drivers/amvdec_ports/Makefile
@@ -3,8 +3,10 @@
 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_vfm.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
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
index 95ee48a..7e08371 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.c
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.c
@@ -56,17 +56,11 @@
 //#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 def_4k_vstreambuf_sizeM =
-	(DEFAULT_VIDEO_BUFFER_SIZE_4K >> 20);
-static int def_vstreambuf_sizeM =
-	(DEFAULT_VIDEO_BUFFER_SIZE >> 20);
 
 static int slow_input = 0;
 
-static int use_bufferlevelx10000 = 10000;
-static unsigned int amstream_buf_num = BUF_MAX_NUM;
-
 static struct stream_buf_s bufs[BUF_MAX_NUM] = {
 	{
 		.reg_base = VLD_MEM_VIFIFO_REG_BASE,
@@ -173,60 +167,6 @@
 	return 0;
 }
 
-static int reset_canuse_buferlevel(int levelx10000)
-{
-	int i;
-	struct stream_buf_s *p = NULL;
-
-	if (levelx10000 >= 0 && levelx10000 <= 10000)
-		use_bufferlevelx10000 = levelx10000;
-	else
-		use_bufferlevelx10000 = 10000;
-	for (i = 0; i < amstream_buf_num; i++) {
-		p = &bufs[i];
-		p->canusebuf_size = ((p->buf_size / 1024) *
-			use_bufferlevelx10000 / 10000) * 1024;
-		p->canusebuf_size += 1023;
-		p->canusebuf_size &= ~1023;
-
-		if (p->canusebuf_size > p->buf_size)
-			p->canusebuf_size = p->buf_size;
-	}
-
-	return 0;
-}
-
-static void change_vbufsize(struct vdec_s *vdec,
-	struct stream_buf_s *pvbuf)
-{
-	if (pvbuf->buf_start != 0) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "streambuf is alloced before\n");
-		return;
-	}
-
-	if (vdec->port->is_4k) {
-		pvbuf->buf_size = def_4k_vstreambuf_sizeM * SZ_1M;
-
-		if (vdec->port_flag & PORT_FLAG_DRM)
-			pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP;
-
-		if ((pvbuf->buf_size > 30 * SZ_1M)
-			&& (codec_mm_get_total_size() < 220 * SZ_1M)) {
-			/*if less than 250M, used 20M for 4K & 265*/
-			pvbuf->buf_size = pvbuf->buf_size >> 1;
-		}
-	} else if (pvbuf->buf_size > def_vstreambuf_sizeM * SZ_1M) {
-		if (vdec->port_flag & PORT_FLAG_DRM)
-			pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP;
-	} else {
-		pvbuf->buf_size = def_vstreambuf_sizeM * SZ_1M;
-		if (vdec->port_flag & PORT_FLAG_DRM)
-			pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP;
-	}
-
-	reset_canuse_buferlevel(10000);
-}
-
 static void user_buffer_init(void)
 {
 	struct stream_buf_s *pubuf = &bufs[BUF_TYPE_USERDATA];
@@ -237,41 +177,14 @@
 	pubuf->buf_rp = 0;
 }
 
-static void video_component_release(struct stream_port_s *port,
-struct stream_buf_s *pbuf, int release_num)
+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;
 
-	struct vdec_s *slave = NULL;
+	vdec_release(vdec);
 
-	switch (release_num) {
-	default:
-	case 0:
-	case 4: {
-		if ((port->type & PORT_TYPE_FRAME) == 0)
-			esparser_release(pbuf);
-	}
-
-	case 3: {
-		if (vdec->slave)
-			slave = vdec->slave;
-		vdec_release(vdec);
-
-		if (slave)
-			vdec_release(slave);
-		vdec = NULL;
-	}
-
-	case 2: {
-		if ((port->type & PORT_TYPE_FRAME) == 0)
-			stbuf_release(pbuf);
-	}
-
-	case 1:
-		;
-	}
 }
 
 static int video_component_init(struct stream_port_s *port,
@@ -291,69 +204,21 @@
 		|| port->vformat == VFORMAT_H264_4K2K) {
 		port->is_4k = true;
 		if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX
-				&& port->vformat == VFORMAT_H264)
+				&& (port->vformat == VFORMAT_H264))
 			vdec_poweron(VDEC_HEVC);
 	} else
 		port->is_4k = false;
 
-	if (port->type & PORT_TYPE_FRAME) {
-		ret = vdec_init(vdec, port->is_4k);
+	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, pbuf, 2);
-			return ret;
-		}
-
-		return 0;
-	}
-
-	change_vbufsize(vdec, pbuf);
-
-	if (has_hevc_vdec()) {
-		if (port->type & PORT_TYPE_MPTS) {
-			if (pbuf->type == BUF_TYPE_HEVC)
-				vdec_poweroff(VDEC_1);
-			else
-				vdec_poweroff(VDEC_HEVC);
-		}
-	}
-
-	ret = stbuf_init(pbuf, vdec);
-	if (ret < 0) {
-		v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "stbuf_init failed\n");
-		return ret;
-	}
-
-	/* todo: set path based on port flag */
-	ret = vdec_init(vdec, port->is_4k);
-	if (ret < 0) {
-		v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "vdec_init failed\n");
-		video_component_release(port, pbuf, 2);
-		return ret;
-	}
-
-	if (vdec_dual(vdec)) {
-		ret = vdec_init(vdec->slave, port->is_4k);
-		if (ret < 0) {
-			v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "vdec_init failed\n");
-			video_component_release(port, pbuf, 2);
+			video_component_release(port);
 			return ret;
 		}
 	}
 
-	if (port->type & PORT_TYPE_ES) {
-		ret = esparser_init(pbuf, vdec);
-		if (ret < 0) {
-			video_component_release(port, pbuf, 3);
-			v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "esparser_init() failed\n");
-			return ret;
-		}
-	}
-
-	pbuf->flag |= BUF_FLAG_IN_USE;
-
-	vdec_connect(vdec);
-
 	return 0;
 }
 
@@ -362,8 +227,8 @@
 	struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO];
 
 	if (has_hevc_vdec()) {
-		if (port->vformat == VFORMAT_HEVC
-			|| port->vformat == VFORMAT_VP9)
+		if (port->vformat == VFORMAT_HEVC ||
+			port->vformat == VFORMAT_VP9)
 			pvbuf = &bufs[BUF_TYPE_HEVC];
 	}
 
@@ -376,7 +241,7 @@
 		psparser_release();
 
 	if (port->type & PORT_TYPE_VIDEO)
-		video_component_release(port, pvbuf, 0);
+		video_component_release(port);
 
 	port->pcr_inited = 0;
 	port->flag = 0;
@@ -391,7 +256,6 @@
 	vdec->port	= &ada_ctx->port;
 	vdec->format	= ada_ctx->video_type;
 	vdec->sys_info_store = ada_ctx->dec_prop;
-	vdec->vf_receiver_name = ada_ctx->recv_name;
 
 	/* binding v4l2 ctx to vdec. */
 	vdec->private = ada_ctx->ctx;
@@ -425,7 +289,6 @@
 		vdec->frame_base_video_path = aml_set_vfm_path;
 
 	vdec->port->flag = vdec->port_flag;
-	ada_ctx->vfm_path = vdec->frame_base_video_path;
 
 	vdec->config_len = ada_ctx->config.length >
 		PAGE_SIZE ? PAGE_SIZE : ada_ctx->config.length;
@@ -445,6 +308,7 @@
 	if (IS_ERR_OR_NULL(vdec))
 		return -1;
 
+	vdec->disable_vfm = true;
 	set_vdec_properity(vdec, ada_ctx);
 
 	/* init hw and gate*/
@@ -461,8 +325,8 @@
 		&& (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)
+			if (vdec->port->vformat == VFORMAT_HEVC ||
+				vdec->port->vformat == VFORMAT_VP9)
 				pvbuf = &bufs[BUF_TYPE_HEVC];
 		}
 
@@ -526,9 +390,11 @@
 	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)
 {
@@ -579,11 +445,11 @@
 {
 	struct vdec_s *vdec = ada_ctx->vdec;
 
-	return (vdec->input.have_frame_num > 600) ? true : false;
+	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)
+	const char *buf, unsigned int count, u64 timestamp, ulong meta_ptr)
 {
 	int ret = -1;
 	struct vdec_s *vdec = ada_ctx->vdec;
@@ -591,6 +457,9 @@
 	/* 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) {
@@ -599,9 +468,12 @@
 		msleep(30);
 	}
 
-	if (dump_output_frame > 0) {
+	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,
@@ -658,23 +530,14 @@
 	int ret = 0;
 
 	if (vdec) {
-		if (!ada_ctx->ctx->q_data[AML_Q_DATA_SRC].resolution_changed)
+		if (ada_ctx->ctx->v4l_resolution_change)
+			*mode = V4L_RESET_MODE_LIGHT;
+		else
 			vdec_set_eos(vdec, false);
-		if (*mode == V4L_RESET_MODE_NORMAL &&
-			vdec->input.have_frame_num == 0) {
-			v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO,
-			"no input reset mode: %d\n", *mode);
-			*mode = V4L_RESET_MODE_LIGHT;
-		}
-		if (ada_ctx->ctx->param_sets_from_ucode &&
-			*mode == V4L_RESET_MODE_NORMAL &&
-			ada_ctx->ctx->q_data[AML_Q_DATA_SRC].resolution_changed == true) {
-			v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO,
-			"resolution_changed reset mode: %d\n", *mode);
-			*mode = V4L_RESET_MODE_LIGHT;
-		}
+
 		v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO,
-			"reset mode: %d\n", *mode);
+			"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;
@@ -709,6 +572,11 @@
 		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;
@@ -716,3 +584,8 @@
 	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
index b86cbff..c8641ce 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.h
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.h
@@ -27,13 +27,12 @@
 #include "aml_vcodec_drv.h"
 
 struct aml_vdec_adapt {
-	enum vformat_e format;
+	int format;
 	void *vsi;
 	int32_t failure;
 	uint32_t inst_addr;
 	unsigned int signaled;
 	struct aml_vcodec_ctx *ctx;
-	struct platform_device *dev;
 	wait_queue_head_t wq;
 	struct file *filp;
 	struct vdec_s *vdec;
@@ -41,8 +40,7 @@
 	struct dec_sysinfo dec_prop;
 	struct v4l2_config_parm config;
 	int video_type;
-	char *recv_name;
-	int vfm_path;
+	char *frm_name;
 };
 
 int video_decoder_init(struct aml_vdec_adapt *ada_ctx);
@@ -53,7 +51,7 @@
 	const char *buf, unsigned int count);
 
 int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx,
-	const char *buf, unsigned int count, u64 timestamp);
+	const char *buf, unsigned int count, u64 timestamp, ulong meta_ptr);
 
 void vdec_vframe_input_free(void *priv, u32 handle);
 
@@ -73,5 +71,9 @@
 
 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
index afebb7a..2bbfb6e 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec.c
@@ -20,27 +20,41 @@
 #include <media/v4l2-event.h>
 #include <media/v4l2-mem2mem.h>
 #include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-dma-sg.h>
 
-#include "aml_vcodec_drv.h"
-#include "aml_vcodec_dec.h"
-//#include "aml_vcodec_intr.h"
-#include "aml_vcodec_util.h"
-#include "vdec_drv_if.h"
 #include <linux/delay.h>
 #include <linux/atomic.h>
 #include <linux/crc32.h>
-#include "aml_vcodec_adapt.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_vfm.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	8 //capture nv21
+
+#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
@@ -49,8 +63,12 @@
 
 #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
 
@@ -62,70 +80,89 @@
 
 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[] = {
@@ -165,6 +202,11 @@
 				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},
@@ -184,16 +226,44 @@
 		.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 bool dump_capture_frame;
+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)
 {
@@ -209,6 +279,23 @@
 	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;
@@ -236,16 +323,6 @@
 {
 	struct v4l2_event event = {0};
 
-	if (ctx->receive_cmd_stop &&
-			changes != V4L2_EVENT_SRC_CH_RESOLUTION &&
-			changes != V4L2_EVENT_SEND_EOS) {
-		ctx->state = AML_STATE_ABORT;
-		ATRACE_COUNTER("v4l2_state", ctx->state);
-		changes = V4L2_EVENT_REQUEST_EXIT;
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
-			"vcodec state (AML_STATE_ABORT)\n");
-	}
-
 	switch (changes) {
 	case V4L2_EVENT_SRC_CH_RESOLUTION:
 	case V4L2_EVENT_SRC_CH_HDRINFO:
@@ -277,11 +354,176 @@
 	aml_decoder_flush(ctx->ada_ctx);
 }
 
-static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *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)
 {
-	unsigned int dpbsize = 0;
-	int ret;
+	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");
@@ -309,287 +551,277 @@
 			ctx->last_decoded_picinfo.coded_width,
 			ctx->last_decoded_picinfo.coded_width);
 
-	ret = vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize);
-	if (dpbsize == 0)
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
-			"Incorrect dpb size, ret=%d\n", ret);
-
-	/* update picture information */
-	ctx->dpb_size = dpbsize;
 	ctx->picinfo = ctx->last_decoded_picinfo;
-}
 
-static bool aml_check_inst_quit(struct aml_vcodec_dev *dev,
-	struct aml_vcodec_ctx * inst, u32 id)
-{
-	struct aml_vcodec_ctx *ctx = NULL;
-	bool ret = true;
+	if (ctx->vpp_is_need)
+		ctx->vpp_cfg.is_vpp_reset = true;
 
-	if (dev == NULL)
-		return false;
+	v4l_buf_size_decision(ctx);
 
-	mutex_lock(&dev->dev_mutex);
-
-	if (list_empty(&dev->ctx_list)) {
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
-			"v4l inst list is empty.\n");
-		ret = true;
-		goto out;
-	}
-
-	list_for_each_entry(ctx, &dev->ctx_list, list) {
-		if ((ctx == inst) && (ctx->id == id)) {
-			ret = ctx->receive_cmd_stop ? true : false;
-			goto out;
-		}
-	}
-out:
-	mutex_unlock(&dev->dev_mutex);
-
-	return ret;
+	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_dev *dev = (struct aml_vcodec_dev *)
-		priv_data->vb_handle;
-	struct aml_vcodec_ctx *inst = (struct aml_vcodec_ctx *)
+	struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)
 		priv_data->v4l_dec_ctx;
-	u32 id = priv_data->v4l_inst_id;
+	struct aml_video_dec_buf *vb = (struct aml_video_dec_buf *)
+		priv_data->vb_handle;
+	struct uvm_hook_mod_info *uvm = NULL;
 
-	if (aml_check_inst_quit(dev, inst, id)) {
-		struct vframe_s *vf = &priv_data->vf;
-
-		v4l_dbg(0, V4L_DEBUG_CODEC_BUFMGR,
-			"[%d]: vf idx: %d, bmmu idx: %d, bmmu_box: %lx\n",
-			id, vf->index, vf->mm_box.bmmu_idx,
-			(ulong) vf->mm_box.bmmu_box);
-
-		v4l_dbg(0, V4L_DEBUG_CODEC_BUFMGR,
-			"[%d]: vf idx: %d, mmu_idx: %d, mmu_box: %lx\n",
-			id, vf->index, vf->mm_box.mmu_idx,
-			(ulong) vf->mm_box.mmu_box);
-
-		if (decoder_bmmu_box_valide_check(vf->mm_box.bmmu_box)) {
-			decoder_bmmu_box_free_idx(vf->mm_box.bmmu_box,
-				vf->mm_box.bmmu_idx);
-			decoder_bmmu_try_to_release_box(vf->mm_box.bmmu_box);
-		}
-
-		if (decoder_mmu_box_valide_check(vf->mm_box.mmu_box)) {
-			decoder_mmu_box_free_idx(vf->mm_box.mmu_box,
-				vf->mm_box.mmu_idx);
-			decoder_mmu_try_to_release_box(vf->mm_box.mmu_box);
-		}
-
+	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);
 }
 
-int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_fb)
+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;
-	struct vb2_buffer *dst_buf = NULL;
-	struct vdec_v4l2_buffer *pfb;
-	struct aml_video_dec_buf *dst_buf_info, *info;
-	struct vb2_v4l2_buffer *dst_vb2_v4l2;
 
 	flags = aml_vcodec_ctx_lock(ctx);
 
-	if (ctx->state == AML_STATE_ABORT) {
-		aml_vcodec_ctx_unlock(ctx, flags);
-		return -1;
+	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;
 	}
 
-	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
-	if (!dst_buf) {
-		aml_vcodec_ctx_unlock(ctx, flags);
-		return -1;
-	}
-
-	v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
-		"vbuf idx: %d, state: %d, ready: %d\n",
-		dst_buf->index, dst_buf->state,
-		v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx));
-
-	dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf);
-	dst_buf_info = container_of(dst_vb2_v4l2, struct aml_video_dec_buf, vb);
-
-	pfb	= &dst_buf_info->frame_buffer;
-	pfb->buf_idx	= dst_buf->index;
-	pfb->num_planes	= dst_buf->num_planes;
-	pfb->status		= FB_ST_NORMAL;
-	if (dst_buf->num_planes == 1) {
-		pfb->m.mem[0].dma_addr	= vb2_dma_contig_plane_dma_addr(dst_buf, 0);
-		pfb->m.mem[0].addr	= dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[0].dma_addr);
-		pfb->m.mem[0].size	= ctx->picinfo.y_len_sz + ctx->picinfo.c_len_sz;
-		pfb->m.mem[0].offset	= ctx->picinfo.y_len_sz;
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
-			"idx: %u, 1 plane, y:(0x%lx, %d)\n", dst_buf->index,
-			pfb->m.mem[0].addr, pfb->m.mem[0].size);
-	} else if (dst_buf->num_planes == 2) {
-		pfb->m.mem[0].dma_addr	= vb2_dma_contig_plane_dma_addr(dst_buf, 0);
-		pfb->m.mem[0].addr	= dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[0].dma_addr);
-		pfb->m.mem[0].size	= ctx->picinfo.y_len_sz;
-		pfb->m.mem[0].offset	= 0;
-
-		pfb->m.mem[1].dma_addr	= vb2_dma_contig_plane_dma_addr(dst_buf, 1);
-		pfb->m.mem[1].addr	= dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[1].dma_addr);
-		pfb->m.mem[1].size	= ctx->picinfo.c_len_sz;
-		pfb->m.mem[1].offset	= ctx->picinfo.c_len_sz >> 1;
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
-			"idx: %u, 2 planes, y:(0x%lx, %d), c:(0x%lx, %d)\n", dst_buf->index,
-			pfb->m.mem[0].addr, pfb->m.mem[0].size,
-			pfb->m.mem[1].addr, pfb->m.mem[1].size);
-	} else {
-		pfb->m.mem[0].dma_addr	= vb2_dma_contig_plane_dma_addr(dst_buf, 0);
-		pfb->m.mem[0].addr	= dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[0].dma_addr);
-		pfb->m.mem[0].size	= ctx->picinfo.y_len_sz;
-		pfb->m.mem[0].offset	= 0;
-
-		pfb->m.mem[1].dma_addr	= vb2_dma_contig_plane_dma_addr(dst_buf, 1);
-		pfb->m.mem[1].addr	= dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[2].dma_addr);
-		pfb->m.mem[1].size	= ctx->picinfo.c_len_sz >> 1;
-		pfb->m.mem[1].offset	= 0;
-
-		pfb->m.mem[2].dma_addr	= vb2_dma_contig_plane_dma_addr(dst_buf, 2);
-		pfb->m.mem[2].addr	= dma_to_phys(v4l_get_dev_from_codec_mm(), pfb->m.mem[3].dma_addr);
-		pfb->m.mem[2].size	= ctx->picinfo.c_len_sz >> 1;
-		pfb->m.mem[2].offset	= 0;
-
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
-			"idx: %u, 3 planes, y:(0x%lx, %d), u:(0x%lx, %d), v:(0x%lx, %d)\n",
-			dst_buf->index,
-			pfb->m.mem[0].addr, pfb->m.mem[0].size,
-			pfb->m.mem[1].addr, pfb->m.mem[1].size,
-			pfb->m.mem[2].addr, pfb->m.mem[2].size);
-	}
-
-	dst_buf_info->used = true;
-	ctx->buf_used_count++;
-
-	*out_fb = pfb;
-
-	info = container_of(pfb, struct aml_video_dec_buf, frame_buffer);
-
-	ctx->cap_pool.dec++;
-	ctx->cap_pool.seq[ctx->cap_pool.out++] =
-		(V4L_CAP_BUFF_IN_DEC << 16 | dst_buf->index);
-	v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
-
 	aml_vcodec_ctx_unlock(ctx, flags);
 
-	return 0;
+	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "%s done\n", __func__);
 }
-EXPORT_SYMBOL(get_fb_from_queue);
 
-int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *in_fb)
+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)
 {
-	struct aml_video_dec_buf *dstbuf;
+	int i;
+	ulong addr, flags;
 
-	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO, "%s\n", __func__);
+	flags = aml_vcodec_ctx_lock(ctx);
 
-	if (in_fb == NULL) {
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "No free frame buffer\n");
-		return -1;
+	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;
+		}
 	}
 
-	dstbuf = container_of(in_fb, struct aml_video_dec_buf, frame_buffer);
+	aml_vcodec_ctx_unlock(ctx, flags);
 
-	mutex_lock(&ctx->lock);
-
-	if (!dstbuf->used)
-		goto out;
-
-	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
-		"status=%x queue id=%d to rdy_queue\n",
-		in_fb->status, dstbuf->vb.vb2_buf.index);
-
-	v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb);
-
-	dstbuf->used = false;
-out:
-	mutex_unlock(&ctx->lock);
-
-	return 0;
-
+	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);
+	}
 }
-EXPORT_SYMBOL(put_fb_to_queue);
 
-void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *fb)
+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)
 {
-	struct aml_video_dec_buf *dstbuf = NULL;
-	struct vb2_buffer *vb2_buf = NULL;
-	struct vframe_s *vf = (struct vframe_s *)fb->vf_handle;
+	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,
-		"FROM (%s %s) vf: %lx, ts: %llu, idx: %d, "
+		"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",
-		vf_get_provider(ctx->ada_ctx->recv_name)->name,
-		ctx->ada_ctx->vfm_path != FRAME_BASE_PATH_V4L_VIDEO ? "OSD" : "VIDEO",
-		(ulong) vf, vf->timestamp, vf->index,
+		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);
 
-	dstbuf = container_of(fb, struct aml_video_dec_buf, frame_buffer);
-	vb2_buf = &dstbuf->vb.vb2_buf;
+	vb2_v4l2 = container_of(vb2_buf, struct vb2_v4l2_buffer, vb2_buf);
 
 	if (dstbuf->frame_buffer.num_planes == 1) {
-		vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, fb->m.mem[0].bytes_used);
+		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(&dstbuf->vb.vb2_buf, 0, fb->m.mem[0].bytes_used);
-		vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, fb->m.mem[1].bytes_used);
+		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);
 	}
-	dstbuf->vb.vb2_buf.timestamp = vf->timestamp;
-	dstbuf->ready_to_display = true;
+	vb2_buf->timestamp = vf->timestamp;
+	dstbuf->vb.flags |= vf->frame_type;
 
-	if (dump_capture_frame) {
+	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;
-		fp = filp_open("/data/dec_dump.raw",
+		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 = &dstbuf->vb.vb2_buf;
-			kernel_write(fp,vb2_plane_vaddr(vb, 0),vb->planes[0].bytesused, 0);
+			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].bytesused, 0);
+						vb->planes[1].length, 0);
 			pr_info("dump idx: %d %dx%d\n", dump_capture_frame, vf->width, vf->height);
-			dump_capture_frame = false;
+			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(&dstbuf->vb.vb2_buf, 0, 0);
+			vb2_set_plane_payload(vb2_buf, 0, 0);
 		} else if (dstbuf->frame_buffer.num_planes == 2) {
-			vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, 0);
-			vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, 0);
+			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",
-			dstbuf->vb.vb2_buf.index,
-			dstbuf->vb.vb2_buf.state);
-		ATRACE_COUNTER("v4l2_eos", 0);
+			vb2_buf->index, vb2_buf->state);
 	}
 
 	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
 		"receive vbuf idx: %d, state: %d\n",
-		dstbuf->vb.vb2_buf.index,
-		dstbuf->vb.vb2_buf.state);
+		vb2_buf->index, vb2_buf->state);
 
 	if (vf->flag & VFRAME_FLAG_EMPTY_FRAME_V4L) {
-		if (ctx->q_data[AML_Q_DATA_SRC].resolution_changed) {
+		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
@@ -606,50 +838,449 @@
 
 	if (dstbuf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE) {
 		/* binding vframe handle. */
-		vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
-		ATRACE_COUNTER("v4l2_from", vf->index_disp);
-		dstbuf->privdata.vf = *vf;
-		dstbuf->privdata.vf.omx_index =
-			dstbuf->vb.vb2_buf.index;
+		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;
+		}
 
-		v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE);
+		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("v4l2_state", ctx->state);
+		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 int get_display_buffer(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out)
+static void fill_capture_done_cb(void *v4l_ctx, void *fb_ctx)
 {
-	int ret = -1;
+	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;
 
-	v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO, "%s\n", __func__);
-
-	ret = vdec_if_get_param(ctx, GET_PARAM_DISP_FRAME_BUFFER, out);
-	if (ret) {
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
-			"Cannot get param : GET_PARAM_DISP_FRAME_BUFFER\n");
-		return -1;
+	if (ctx->is_stream_off) {
+		v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT,
+			"ignore buff idx: %d streamoff\n", fb->buf_idx);
+		return;
 	}
 
-	if (!*out) {
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
-			"No display frame buffer\n");
-		return -1;
+	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) {
@@ -660,12 +1291,26 @@
 			ctx->v4l_codec_dpb_ready = true;
 
 		v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
-			"dpb: %d, ready: %d, used: %d, dpb is ready: %s\n",
-			ctx->dpb_size, v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx),
+			"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;
@@ -681,7 +1326,7 @@
 		mutex_lock(&ctx->state_lock);
 		if (ctx->state == AML_STATE_PROBE) {
 			ctx->state = AML_STATE_READY;
-			ATRACE_COUNTER("v4l2_state", ctx->state);
+			ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
 			v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
 				"vcodec state (AML_STATE_READY)\n");
 		}
@@ -693,7 +1338,7 @@
 		if (ctx->m2m_ctx->out_q_ctx.q.streaming &&
 			ctx->m2m_ctx->cap_q_ctx.q.streaming) {
 			ctx->state = AML_STATE_ACTIVE;
-			ATRACE_COUNTER("v4l2_state", ctx->state);
+			ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
 			v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
 				"vcodec state (AML_STATE_ACTIVE)\n");
 		}
@@ -718,7 +1363,7 @@
 	return true;
 }
 
-static void aml_wait_dpb_ready(struct aml_vcodec_ctx *ctx)
+static void aml_wait_buf_ready(struct aml_vcodec_ctx *ctx)
 {
 	ulong expires;
 
@@ -733,34 +1378,75 @@
 		}
 
 		ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx);
-		if ((ready_num + ctx->buf_used_count) >= ctx->dpb_size)
+		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 vb2_v4l2_buffer *vb;
-	struct aml_video_dec_buf *buf;
-	struct vb2_queue *q;
+	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]);
-	buf = container_of(vb, struct aml_video_dec_buf, vb);
-	v4l2_m2m_buf_done(vb, buf->error ? VB2_BUF_STATE_ERROR :
-		VB2_BUF_STATE_DONE);
 
-	v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT,
-		"recycle buff idx: %d, vbuf: %lx\n", index,
-		(ulong)vb2_dma_contig_plane_dma_addr(q->bufs[index], 0));
+	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)
@@ -768,12 +1454,12 @@
 	struct aml_vcodec_ctx *ctx =
 		container_of(work, struct aml_vcodec_ctx, decode_work);
 	struct aml_vcodec_dev *dev = ctx->dev;
-	struct vb2_buffer *src_buf;
+	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;
-	struct aml_video_dec_buf *src_buf_info;
-	struct vb2_v4l2_buffer *src_vb2_v4l2;
 
 	if (ctx->state < AML_STATE_INIT ||
 		ctx->state > AML_STATE_FLUSHED) {
@@ -787,21 +1473,23 @@
 		goto out;
 	}
 
-	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
-	if (src_buf == NULL) {
+	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;
 
-	src_vb2_v4l2 = container_of(src_buf, struct vb2_v4l2_buffer, vb2_buf);
-	src_buf_info = container_of(src_vb2_v4l2, struct aml_video_dec_buf, vb);
+	aml_buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
+	if (aml_buf->lastframe) {
+		ulong expires;
 
-	if (src_buf_info->lastframe) {
 		/*the empty data use to flushed the decoder.*/
 		v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
 			"Got empty flush input buffer.\n");
@@ -809,22 +1497,34 @@
 		/*
 		 * 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.
 		 */
-		if (!ctx->v4l_codec_dpb_ready) {
-			v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
-			goto out;
+		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("v4l2_state", ctx->state);
+			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);
 
-		src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		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. */
@@ -833,21 +1533,22 @@
 		goto out;
 	}
 
-	buf.index	= src_buf->index;
-	buf.vaddr	= vb2_plane_vaddr(src_buf, 0);
-	buf.addr	= vb2_dma_contig_plane_dma_addr(src_buf, 0);
-	buf.size	= src_buf->planes[0].bytesused;
-	buf.model	= src_buf->memory;
-	buf.timestamp	= src_buf->timestamp;
+	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", src_buf->index);
+			"id=%d src_addr is NULL.\n", vb->index);
 		goto out;
 	}
 
-	src_buf_info->used = true;
+	aml_buf->used = true;
 
 	/* v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
 		"size: 0x%zx, crc: 0x%x\n",
@@ -857,29 +1558,52 @@
 	/*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.
 		 */
-		v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
-		if (!(ctx->is_drm_mode && buf.model == VB2_MEMORY_DMABUF))
-			v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE);
-	} else if (ret && ret != -EAGAIN) {
-		src_buf_info->error = (ret == -EIO ? true : false);
+		aml_buf->used = false;
 		v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
 
-		if (!(ctx->is_drm_mode && buf.model == VB2_MEMORY_DMABUF))
-			v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR);
+		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_dpb_ready(ctx);
+		aml_wait_buf_ready(ctx);
 
-		src_buf_info->used = false;
+		aml_buf->used = false;
 		aml_vdec_pic_info_update(ctx);
 		/*
 		 * On encountering a resolution change in the stream.
@@ -890,13 +1614,13 @@
 		mutex_lock(&ctx->state_lock);
 		if (ctx->state == AML_STATE_ACTIVE) {
 			ctx->state = AML_STATE_FLUSHING;// prepare flushing
-			ATRACE_COUNTER("v4l2_state", ctx->state);
+			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->q_data[AML_Q_DATA_SRC].resolution_changed = true;
+		ctx->v4l_resolution_change = true;
 		while (ctx->m2m_ctx->job_flags & TRANS_RUNNING) {
 			v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
 		}
@@ -905,8 +1629,10 @@
 
 		goto out;
 	} else {
+		ATRACE_COUNTER("VO_OUT_VSINK-1.write_again", buf.size);
 		/* decoder is lack of resource, retry after short delay */
-		usleep_range(50000, 55000);
+		if (vdec_get_instance_num() < 2)
+			usleep_range(2000, 4000);
 	}
 
 	v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
@@ -924,28 +1650,10 @@
 
 	if (aml_codec_reset(ctx->ada_ctx, &ctx->reset_flag)) {
 		ctx->state = AML_STATE_ABORT;
-		ATRACE_COUNTER("v4l2_state", ctx->state);
+		ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
 		v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
 			"vcodec state (AML_STATE_ABORT).\n");
-		goto out;
 	}
-
-	if (ctx->state ==  AML_STATE_RESET) {
-		ctx->state = AML_STATE_PROBE;
-		ATRACE_COUNTER("v4l2_state", ctx->state);
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
-			"vcodec state (AML_STATE_PROBE)\n");
-
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
-			"dpb: %d, ready: %d, used: %d\n", ctx->dpb_size,
-			v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx),
-			ctx->buf_used_count);
-
-		/* vdec has ready to decode subsequence data of new resolution. */
-		ctx->q_data[AML_Q_DATA_SRC].resolution_changed = false;
-		v4l2_m2m_job_resume(ctx->dev->m2m_dev_dec, ctx->m2m_ctx);
-	}
-
 out:
 	complete(&ctx->comp);
 	return;
@@ -953,13 +1661,13 @@
 
 void wait_vcodec_ending(struct aml_vcodec_ctx *ctx)
 {
-	struct aml_vcodec_dev *dev = ctx->dev;
-
 	/* disable queue output item to worker. */
 	ctx->output_thread_ready = false;
+	ctx->is_stream_off = true;
 
 	/* flush output buffer worker. */
-	flush_workqueue(dev->decode_workqueue);
+	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)
@@ -973,33 +1681,38 @@
 	ctx->v4l_codec_dpb_ready = false;
 }
 
-void try_to_capture(struct aml_vcodec_ctx *ctx)
+void aml_thread_capture_worker(struct aml_vcodec_ctx *ctx)
 {
-	int ret = 0;
+	struct vb2_v4l2_buffer *vb = NULL;
+	struct aml_video_dec_buf *aml_buff = NULL;
 	struct vdec_v4l2_buffer *fb = NULL;
 
-	ret = get_display_buffer(ctx, &fb);
-	if (ret) {
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
-			"the que have no disp buf,ret: %d\n", ret);
-		return;
+	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);
 	}
-
-	trans_vframe_to_user(ctx, fb);
 }
-EXPORT_SYMBOL_GPL(try_to_capture);
+EXPORT_SYMBOL_GPL(aml_thread_capture_worker);
 
-static int vdec_thread(void *data)
+static int vdec_capture_thread(void *data)
 {
-	struct sched_param param =
-		{.sched_priority = MAX_RT_PRIO / 2};
 	struct aml_vdec_thread *thread =
 		(struct aml_vdec_thread *) data;
 	struct aml_vcodec_ctx *ctx =
 		(struct aml_vcodec_ctx *) thread->priv;
 
-	sched_setscheduler(current, SCHED_FIFO, &param);
-
 	for (;;) {
 		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
 			"%s, state: %d\n", __func__, ctx->state);
@@ -1015,19 +1728,19 @@
 	}
 
 	while (!kthread_should_stop()) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule();
+		usleep_range(1000, 2000);
 	}
 
 	return 0;
 }
 
-void aml_thread_notify(struct aml_vcodec_ctx *ctx,
+void aml_thread_post_task(struct aml_vcodec_ctx *ctx,
 	enum aml_thread_type type)
 {
 	struct aml_vdec_thread *thread = NULL;
+	ulong flags;
 
-	mutex_lock(&ctx->lock);
+	spin_lock_irqsave(&ctx->tsplock, flags);
 	list_for_each_entry(thread, &ctx->vdec_thread_list, node) {
 		if (thread->task == NULL)
 			continue;
@@ -1035,9 +1748,9 @@
 		if (thread->type == type)
 			up(&thread->sem);
 	}
-	mutex_unlock(&ctx->lock);
+	spin_unlock_irqrestore(&ctx->tsplock, flags);
 }
-EXPORT_SYMBOL_GPL(aml_thread_notify);
+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)
@@ -1055,7 +1768,7 @@
 	thread->priv = ctx;
 	sema_init(&thread->sem, 0);
 
-	thread->task = kthread_run(vdec_thread, thread, "aml-%s", thread_name);
+	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;
@@ -1063,6 +1776,10 @@
 	}
 	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;
@@ -1077,13 +1794,14 @@
 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);
-		mutex_lock(&ctx->lock);
+		spin_lock_irqsave(&ctx->tsplock, flags);
 		list_del(&thread->node);
-		mutex_unlock(&ctx->lock);
+		spin_unlock_irqrestore(&ctx->tsplock, flags);
 
 		thread->stop = true;
 		up(&thread->sem);
@@ -1105,7 +1823,17 @@
 	switch (cmd->cmd) {
 	case V4L2_DEC_CMD_STOP:
 	case V4L2_DEC_CMD_START:
-		if (cmd->flags != 0) {
+		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;
@@ -1134,19 +1862,6 @@
 
 	switch (cmd->cmd) {
 	case V4L2_DEC_CMD_STOP:
-		ATRACE_COUNTER("v4l2_stop", 0);
-		if (ctx->state != AML_STATE_ACTIVE) {
-			if (ctx->state >= AML_STATE_IDLE &&
-				ctx->state < AML_STATE_PROBE) {
-				ctx->state = AML_STATE_ABORT;
-				ATRACE_COUNTER("v4l2_state", ctx->state);
-				aml_vdec_dispatch_event(ctx, V4L2_EVENT_REQUEST_EXIT);
-				v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
-					"vcodec state (AML_STATE_ABORT)\n");
-				return 0;
-			}
-		}
-
 		src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
 				V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
 		if (!vb2_is_streaming(src_vq)) {
@@ -1155,18 +1870,32 @@
 			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:
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO, "CMD V4L2_DEC_CMD_START\n");
 		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:
@@ -1176,6 +1905,20 @@
 	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)
 {
@@ -1184,26 +1927,80 @@
 	struct vb2_queue *q;
 
 	q = v4l2_m2m_get_vq(fh->m2m_ctx, i);
-	if (!V4L2_TYPE_IS_OUTPUT(q->type)) {
-		if (ctx->is_stream_off) {
-			mutex_lock(&ctx->state_lock);
-			if ((ctx->state == AML_STATE_ACTIVE ||
-				ctx->state == AML_STATE_FLUSHING ||
-				ctx->state == AML_STATE_FLUSHED) ||
-				(ctx->reset_flag == V4L_RESET_MODE_LIGHT)) {
-				ctx->state = AML_STATE_RESET;
-				ATRACE_COUNTER("v4l2_state", ctx->state);
-				ctx->v4l_codec_dpb_ready = false;
+	if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
+		ctx->is_stream_off) {
+		if (ctx->vpp_is_need) {
+			int ret;
 
-				v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
-					"vcodec state (AML_STATE_RESET)\n");
-				aml_vdec_reset(ctx);
+			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;
 			}
-			mutex_unlock(&ctx->state_lock);
-
-			ctx->is_stream_off = false;
-			ctx->v4l_resolution_change = 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;
 
@@ -1219,12 +2016,26 @@
 	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);
-	if (!V4L2_TYPE_IS_OUTPUT(q->type))
-		ctx->is_stream_off = true;
-	else
+
+	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);
@@ -1241,19 +2052,38 @@
 
 	q = v4l2_m2m_get_vq(fh->m2m_ctx, rb->type);
 
-	if (!rb->count)
+	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 dpb_size */
-		if (rb->count > ctx->dpb_size) {
+		/* 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->dpb_size);
+					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 {
@@ -1293,9 +2123,12 @@
 {
 	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("v4l2_state", ctx->state);
+	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);
@@ -1321,6 +2154,8 @@
 	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;
 
@@ -1334,6 +2169,9 @@
 	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,
@@ -1349,8 +2187,11 @@
 	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("v4l2_state", ctx->state);
+	ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
 	v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
 		"vcodec state (AML_STATE_IDLE)\n");
 }
@@ -1374,11 +2215,24 @@
 	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("v4l2_qbuf_eagain", 0);
+			ATRACE_COUNTER("VC_IN_VSINK-1.que_again", buf->index);
 		else
-			ATRACE_COUNTER("v4l2_qbuf_ok", 0);
+			ATRACE_COUNTER("VC_IN_VSINK-0.que", buf->index);
 	}
+
 	return ret;
 }
 
@@ -1400,39 +2254,47 @@
 	}
 
 	ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
-	if (V4L2_TYPE_IS_OUTPUT(buf->type)) {
-		if (ret == -EAGAIN)
-			ATRACE_COUNTER("v4l2_dqin_eagain", 0);
-		else
-			ATRACE_COUNTER("v4l2_dqin_ok", 0);
-	} else {
-		if (ret == -EAGAIN)
-			ATRACE_COUNTER("v4l2_dqout_eagain", 0);
-	}
-
 	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) ctx->dev;
+		aml_buf->privdata.vb_handle	= (ulong) aml_buf;
 		aml_buf->privdata.v4l_dec_ctx	= (ulong) ctx;
-		aml_buf->privdata.v4l_inst_id		= ctx->id;
 
 		file = fget(vb2_v4l2->private);
-		if (is_v4l2_buf_file(file)) {
+		if (file && is_v4l2_buf_file(file)) {
 			dmabuf_fd_install_data(vb2_v4l2->private,
 				(void*)&aml_buf->privdata,
 				sizeof(struct file_private_data));
-			ATRACE_COUNTER("v4l2_dqout_ok", aml_buf->privdata.vf.index_disp);
 			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);
 		}
-		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;
@@ -1442,10 +2304,12 @@
 	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);
 
@@ -1483,115 +2347,154 @@
 
 static int vidioc_try_fmt(struct v4l2_format *f, struct aml_video_fmt *fmt)
 {
-	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
 	int i;
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
 
-	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		pix_fmt_mp->num_planes = 1;
-		pix_fmt_mp->plane_fmt[0].bytesperline = 0;
-		if (pix_fmt_mp->pixelformat != V4L2_PIX_FMT_MPEG2  &&
-		    pix_fmt_mp->pixelformat != V4L2_PIX_FMT_H264)
-			pix_fmt_mp->field = V4L2_FIELD_NONE;
-		else if (pix_fmt_mp->field != V4L2_FIELD_NONE)
-			pr_info("%s, field: %u, fmt: %u\n",
-				__func__, pix_fmt_mp->field,
-				pix_fmt_mp->pixelformat);
-	} else if (!V4L2_TYPE_IS_OUTPUT(f->type)) {
-		int tmp_w, tmp_h;
+	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;
 
-		pix_fmt_mp->field = V4L2_FIELD_NONE;
-		pix_fmt_mp->height = clamp(pix_fmt_mp->height,
-					AML_VDEC_MIN_H,
-					AML_VDEC_MAX_H);
-		pix_fmt_mp->width = clamp(pix_fmt_mp->width,
-					AML_VDEC_MIN_W,
-					AML_VDEC_MAX_W);
+			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;
 
-		/*
-		 * Find next closer width align 64, heign align 64, size align
-		 * 64 rectangle
-		 * Note: This only get default value, the real HW needed value
-		 *       only available when ctx in AML_STATE_PROBE state
-		 */
-		tmp_w = pix_fmt_mp->width;
-		tmp_h = pix_fmt_mp->height;
-		v4l_bound_align_image(&pix_fmt_mp->width,
-					AML_VDEC_MIN_W,
-					AML_VDEC_MAX_W, 6,
-					&pix_fmt_mp->height,
-					AML_VDEC_MIN_H,
-					AML_VDEC_MAX_H, 6, 9);
+				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);
 
-		if (pix_fmt_mp->width < tmp_w &&
-			(pix_fmt_mp->width + 64) <= AML_VDEC_MAX_W)
-			pix_fmt_mp->width += 64;
-		if (pix_fmt_mp->height < tmp_h &&
-			(pix_fmt_mp->height + 64) <= AML_VDEC_MAX_H)
-			pix_fmt_mp->height += 64;
+			pix_mp->num_planes = fmt->num_planes;
 
-		pix_fmt_mp->num_planes = fmt->num_planes;
-		pix_fmt_mp->plane_fmt[0].sizeimage =
-				pix_fmt_mp->width * pix_fmt_mp->height;
-		pix_fmt_mp->plane_fmt[0].bytesperline = pix_fmt_mp->width;
+			pix_mp->plane_fmt[0].bytesperline = pix_mp->width;
+			pix_mp->plane_fmt[0].sizeimage =
+				pix_mp->width * pix_mp->height;
 
-		if (pix_fmt_mp->num_planes == 2) {
-			pix_fmt_mp->plane_fmt[1].sizeimage =
-				(pix_fmt_mp->width * pix_fmt_mp->height) / 2;
-			pix_fmt_mp->plane_fmt[1].bytesperline =
-				pix_fmt_mp->width;
+			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;
 	}
 
-	for (i = 0; i < pix_fmt_mp->num_planes; i++)
-		memset(&(pix_fmt_mp->plane_fmt[i].reserved[0]), 0x0,
-			   sizeof(pix_fmt_mp->plane_fmt[0].reserved));
-
-	pix_fmt_mp->flags = 0;
-	memset(&pix_fmt_mp->reserved, 0x0, sizeof(pix_fmt_mp->reserved));
 	return 0;
 }
 
-static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv,
+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: %u\n",
-		__func__, f->type, f->fmt.pix_mp.num_planes,
+		"%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);
 
-	fmt = aml_vdec_find_format(f);
-	if (!fmt)
-		return -EINVAL;
-
-	return vidioc_try_fmt(f, fmt);
-}
-
-static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv,
-				struct v4l2_format *f)
-{
-	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-	struct aml_video_fmt *fmt = NULL;
-	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
-
-	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
-		"%s, type: %u, planes: %u, fmt: %u\n",
-		__func__, f->type, f->fmt.pix_mp.num_planes,
-		f->fmt.pix_mp.pixelformat);
-
-	fmt = aml_vdec_find_format(f);
-	if (!fmt)
-		return -EINVAL;
-
-	if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
-			"sizeimage of output format must be given\n");
+	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;
 	}
 
-	return vidioc_try_fmt(f, fmt);
+	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,
@@ -1599,29 +2502,36 @@
 {
 	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:
-		if (vdec_if_get_param(ctx, GET_PARAM_CROP_INFO, &(s->r))) {
-			/* 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;
-		}
+		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;
-		s->r.height = ctx->picinfo.coded_height;
+		s->r.width = ctx->picinfo.coded_width / ratio;
+		s->r.height = ctx->picinfo.coded_height / ratio;
 		break;
 	default:
 		return -EINVAL;
@@ -1645,6 +2555,7 @@
 	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);
@@ -1652,12 +2563,21 @@
 	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;
-		s->r.height = ctx->picinfo.visible_height;
+		s->r.width = ctx->picinfo.visible_width / ratio;
+		s->r.height = ctx->picinfo.visible_height / ratio;
 		break;
 	default:
 		return -EINVAL;
@@ -1666,89 +2586,127 @@
 	return 0;
 }
 
-static void copy_v4l2_format_dimention(struct v4l2_pix_format_mplane *pix_mp,
-		struct aml_q_data *q_data, u32 type)
+/* called when it is beyong AML_STATE_PROBE */
+static void update_ctx_dimension(struct aml_vcodec_ctx *ctx, u32 type)
 {
-	if (!pix_mp || !q_data)
-		return;
+	struct aml_q_data *q_data;
+	unsigned int dw_mode = VDEC_DW_NO_AFBC;
+	int ratio = 1;
 
-	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		pix_mp->width = q_data->visible_width;
-		pix_mp->height = q_data->visible_height;
-	} else {
-		/*
-		 * Width and height are set to the dimensions
-		 * of the movie, the buffer is bigger and
-		 * further processing stages should crop to this
-		 * rectangle.
-		 */
-		pix_mp->width = q_data->coded_width;
-		pix_mp->height = q_data->coded_height;
+	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);
 	}
 
-	/*
-	 * Set pixelformat to the format in which mt vcodec
-	 * outputs the decoded frame
-	 */
-	pix_mp->num_planes = q_data->fmt->num_planes;
-	pix_mp->pixelformat = q_data->fmt->fourcc;
-	pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
-	pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
-	if (type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1];
-		pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1];
+	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)
 {
-	struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
-	struct v4l2_pix_format_mplane *pix_mp;
-	struct aml_q_data *q_data;
 	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: %u\n",
-		__func__, f->type, f->fmt.pix_mp.num_planes,
+		"%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;
 
-	pix_mp = &f->fmt.pix_mp;
 	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 (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-			f->fmt.pix.pixelformat =
-				aml_video_formats[OUT_FMT_IDX].fourcc;
-			fmt = aml_vdec_find_format(f);
-		} else if (!V4L2_TYPE_IS_OUTPUT(f->type)) {
-			f->fmt.pix.pixelformat =
-				aml_video_formats[CAP_FMT_IDX].fourcc;
-			fmt = aml_vdec_find_format(f);
-		}
+		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) {
-		if (ctx->is_drm_mode)
-			pix_mp->plane_fmt[0].sizeimage = 1;
 		q_data->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage;
 		q_data->coded_width = pix_mp->width;
 		q_data->coded_height = pix_mp->height;
@@ -1758,6 +2716,7 @@
 			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;
@@ -1773,7 +2732,38 @@
 				return -EINVAL;
 			}
 			ctx->state = AML_STATE_INIT;
-			ATRACE_COUNTER("v4l2_state", ctx->state);
+			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");
 		}
@@ -1781,9 +2771,13 @@
 	}
 
 	if (!V4L2_TYPE_IS_OUTPUT(f->type)) {
-		ctx->cap_pix_fmt = pix_mp->pixelformat;
-		if (ctx->state >= AML_STATE_PROBE)
-			copy_v4l2_format_dimention(pix_mp, q_data, 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;
@@ -1833,16 +2827,31 @@
 static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue)
 {
 	struct aml_video_fmt *fmt;
-	int i, j = 0;
+	int i = 0, j = 0;
 
-	for (i = 0; i < NUM_FORMATS; i++) {
-		if (output_queue && (aml_video_formats[i].type != AML_FMT_DEC))
+	/* 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 && (aml_video_formats[i].type != AML_FMT_FRAME))
+		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) {
-			fmt = &aml_video_formats[i];
 			f->pixelformat = fmt->fourcc;
 			return 0;
 		}
@@ -1879,6 +2888,7 @@
 	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;
 
@@ -1889,12 +2899,29 @@
 		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)) {
@@ -1913,24 +2940,8 @@
 
 	if ((!V4L2_TYPE_IS_OUTPUT(f->type)) &&
 	    (ctx->state >= AML_STATE_PROBE)) {
-		/* Until STREAMOFF is called on the CAPTURE queue
-		 * (acknowledging the event), the driver operates as if
-		 * the resolution hasn't changed yet.
-		 * So we just return picinfo yet, and update picinfo in
-		 * stop_streaming hook function
-		 */
-		/* it is used for alloc the decode buffer size. */
-		q_data->sizeimage[0] = ctx->picinfo.y_len_sz;
-		q_data->sizeimage[1] = ctx->picinfo.c_len_sz;
-
-		/* it is used for alloc the EGL image buffer size. */
-		q_data->coded_width = ctx->picinfo.coded_width;
-		q_data->coded_height = ctx->picinfo.coded_height;
-
-		q_data->bytesperline[0] = ctx->picinfo.coded_width;
-		q_data->bytesperline[1] = ctx->picinfo.coded_width;
-
-		copy_v4l2_format_dimention(pix_mp, q_data, f->type);
+		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
@@ -1938,20 +2949,21 @@
 		 * so width and height have no meaning.
 		 * Assign value here to pass v4l2-compliance test
 		 */
-		copy_v4l2_format_dimention(pix_mp, q_data, f->type);
+		copy_v4l2_format_dimention(pix_mp, pix, q_data, f->type);
 	} else {
-		copy_v4l2_format_dimention(pix_mp, q_data, f->type);
+		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);
-		return -EINVAL;
 	}
 
 	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
-		"%s, type: %u, planes: %u, fmt: %u\n",
-		__func__, f->type, f->fmt.pix_mp.num_planes,
-		f->fmt.pix_mp.pixelformat);
+		"%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;
 }
@@ -2007,21 +3019,32 @@
 		for (i = 0; i < *nplanes; i++) {
 			if (sizes[i] < q_data->sizeimage[i])
 				return -EINVAL;
-			//alloc_devs[i] = &ctx->dev->plat_dev->dev;
-			alloc_devs[i] = v4l_get_dev_from_codec_mm();//alloc mm from the codec mm
+			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] = 0;
-			//alloc_devs[i] = &ctx->dev->plat_dev->dev;
-			alloc_devs[i] = v4l_get_dev_from_codec_mm();//alloc mm from the codec mm
+				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();
 		}
 	}
 
@@ -2036,6 +3059,8 @@
 {
 	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,
@@ -2057,65 +3082,710 @@
 		}
 	}
 
+	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 = NULL;
-	struct aml_video_dec_buf *buf = NULL;
+	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;
-	unsigned int dpb = 0;
-
-	vb2_v4l2 = to_vb2_v4l2_buffer(vb);
-	buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
 
 	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)) {
-		if (vb->index >= ctx->dpb_size) {
-			v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
-				"enque capture buf idx %d/%d is invalid.\n",
-				vb->index, ctx->dpb_size);
-			return;
-		}
+		u32 dw_mode = VDEC_DW_NO_AFBC;
 
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
-			"y_addr: %lx, vf_h: %lx, state: %d",
-			buf->frame_buffer.m.mem[0].addr,
-			buf->frame_buffer.vf_handle,
-			buf->frame_buffer.status);
+		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));
 
-			v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2);
-			buf->que_in_m2m = true;
-			buf->queued_in_vb2 = true;
-			buf->queued_in_v4l2 = true;
-			buf->ready_to_display = false;
+			/* 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 if (buf->frame_buffer.status == FB_ST_DISPLAY) {
-			buf->queued_in_vb2 = false;
-			buf->queued_in_v4l2 = true;
-			buf->ready_to_display = false;
+		} else {
+			struct vframe_s *vf = fb->vframe;
+			struct task_chain_s *task = fb->task;
 
-			/* recycle vf */
-			video_vf_put(ctx->ada_ctx->recv_name,
-				&buf->frame_buffer, ctx->id);
+			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;
 	}
 
@@ -2125,28 +3795,41 @@
 		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	= vb2_dma_contig_plane_dma_addr(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))
-			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(vb), VB2_BUF_STATE_DONE);
+		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;
 	}
 
@@ -2154,11 +3837,14 @@
 	 * If on model dmabuf must remove the buffer
 	 * because this data has been consumed by hw.
 	 */
-	if (ctx->is_drm_mode && src_mem.model == VB2_MEMORY_DMABUF) {
-		v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+	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_m2m_src_buf_remove(ctx->m2m_ctx);
-		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(vb),
+		v4l2_buff_done(to_vb2_v4l2_buffer(vb),
 			VB2_BUF_STATE_DONE);
 	}
 
@@ -2168,23 +3854,24 @@
 		return;
 	}
 
-	if (vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpb)) {
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
-			"GET_PARAM_DPB_SIZE err\n");
-		return;
-	}
-
-	if (!dpb)
+	if (!ctx->picinfo.dpb_frames)
 		return;
 
-	ctx->dpb_size = dpb;
+	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("v4l2_state", ctx->state);
+		ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
 		v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
 			"vcodec state (AML_STATE_PROBE)\n");
 	}
@@ -2196,26 +3883,19 @@
 	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;
-	bool buf_error;
 
 	v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
 		"%s, type: %d, idx: %d\n",
 		__func__, vb->vb2_queue->type, vb->index);
 
-	vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
+	vb2_v4l2 = to_vb2_v4l2_buffer(vb);
 	buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
 
-	if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
-		buf->queued_in_v4l2 = false;
-		buf->queued_in_vb2 = false;
-	}
-	buf_error = buf->error;
-
-	if (buf_error) {
+	if (buf->error) {
 		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
 			"Unrecoverable error on buffer.\n");
 		ctx->state = AML_STATE_ABORT;
-		ATRACE_COUNTER("v4l2_state", ctx->state);
+		ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
 		v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
 			"vcodec state (AML_STATE_ABORT)\n");
 	}
@@ -2228,108 +3908,145 @@
 					struct vb2_v4l2_buffer, vb2_buf);
 	struct aml_video_dec_buf *buf = container_of(vb2_v4l2,
 					struct aml_video_dec_buf, vb);
-	unsigned int size, phy_addr = 0;
-	char *owner = __getname();
+	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->used = false;
-		buf->ready_to_display = false;
-		buf->queued_in_v4l2 = false;
-		buf->frame_buffer.status = FB_ST_NORMAL;
-	} else {
+	if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
 		buf->lastframe = false;
 	}
 
 	/* codec_mm buffers count */
-	if (V4L2_TYPE_IS_OUTPUT(vb->type)) {
+	if (!V4L2_TYPE_IS_OUTPUT(vb->type)) {
 		if (vb->memory == VB2_MEMORY_MMAP) {
-			size = vb->planes[0].length;
-			phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
-			snprintf(owner, PATH_MAX, "%s-%d", "v4l-input", ctx->id);
+			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);
 
-			buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer,
-					phy_addr, size, vb->index);
-			v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
-				"IN alloc, addr: %x, size: %u, idx: %u\n",
-				phy_addr, size, vb->index);
-		}
-	} else {
-		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';
+			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;
 
-		if ((vb->memory == VB2_MEMORY_MMAP) && (vb->num_planes == 1)) {
-			size = vb->planes[0].length;
-			phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
-			buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer,
-				phy_addr, size, vb->index);
-			v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
-				"OUT Y alloc, addr: %x, size: %u, idx: %u\n",
-				phy_addr, size, vb->index);
-		} else if ((vb->memory == VB2_MEMORY_MMAP) && (vb->num_planes == 2)) {
-			size = vb->planes[0].length;
-			phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
-			buf->mem[0] = v4l_reqbufs_from_codec_mm(buf->mem_onwer,
-				phy_addr, size, vb->index);
-			v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
-				"OUT Y alloc, addr: %x, size: %u, idx: %u\n",
-				phy_addr, size, vb->index);
+			for (i = 0; i < vb->num_planes; i++) {
+				struct dma_buf * dma;
 
-			size = vb->planes[1].length;
-			phy_addr = vb2_dma_contig_plane_dma_addr(vb, 1);
-			buf->mem[1] = 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",
-				phy_addr, size, vb->index);
+				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");
+			}
 		}
 	}
 
-	__putname(owner);
+	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 codec_mm_bufs_cnt_clean(struct vb2_queue *q)
+static void vb2ops_vdec_buf_cleanup(struct vb2_buffer *vb)
 {
-	struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(q);
-	struct vb2_v4l2_buffer *vb2_v4l2 = NULL;
-	struct aml_video_dec_buf *buf = NULL;
-	int i;
+	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;;
 
-	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);
-		if (IS_ERR_OR_NULL(buf->mem[0]))
-			return;
+	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(q->bufs[i]->type)) {
-			v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]);
+	if (!V4L2_TYPE_IS_OUTPUT(vb->type)) {
+		if (vb->memory == VB2_MEMORY_MMAP) {
+			int i;
 
-			v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
-				"IN clean, addr: %lx, size: %u, idx: %u\n",
-				buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i);
-			buf->mem[0] = NULL;
-			continue;
+			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 (q->memory == VB2_MEMORY_MMAP) {
-			v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]);
-			v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[1]);
-
-			v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
-				"OUT Y clean, addr: %lx, size: %u, idx: %u\n",
-				buf->mem[0]->phy_addr, buf->mem[0]->buffer_size, i);
-			v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
-				"OUT C clean, addr: %lx, size: %u, idx: %u\n",
-				buf->mem[1]->phy_addr, buf->mem[1]->buffer_size, i);
-			buf->mem[0] = NULL;
-			buf->mem[1] = 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);
+			}
 		}
 	}
 }
@@ -2339,6 +4056,10 @@
 	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);
 
@@ -2359,40 +4080,81 @@
 		"%s, type: %d, state: %x, frame_cnt: %d\n",
 		__func__, q->type, ctx->state, ctx->decoded_frame_cnt);
 
-	codec_mm_bufs_cnt_clean(q);
+	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_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
+			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_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
+				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)
+		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_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
+			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_NORMAL;
-			buf->que_in_m2m = false;
-			buf->vb.flags = 0;
-			ctx->cap_pool.seq[i] = 0;
+			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_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
+				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;
@@ -2410,15 +4172,6 @@
 		queue_work(dev->decode_workqueue, &ctx->decode_work);
 }
 
-void vdec_device_vf_run(struct aml_vcodec_ctx *ctx)
-{
-	if (ctx->state < AML_STATE_INIT ||
-		ctx->state > AML_STATE_FLUSHED)
-		return;
-
-	aml_thread_notify(ctx, AML_THREAD_CAPTURE);
-}
-
 static int m2mops_vdec_job_ready(void *m2m_priv)
 {
 	struct aml_vcodec_ctx *ctx = m2m_priv;
@@ -2448,17 +4201,23 @@
 	switch (ctrl->id) {
 	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
 		if (ctx->state >= AML_STATE_PROBE) {
-			ctrl->val = ctx->dpb_size;
+			ctrl->val = CTX_BUF_TOTAL(ctx);
 		} else {
 			v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
 				"Seqinfo not ready.\n");
 			ctrl->val = 0;
-			ret = -EINVAL;
 		}
 		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;
 	}
@@ -2476,6 +4235,10 @@
 		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;
@@ -2498,6 +4261,42 @@
 	.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;
@@ -2508,24 +4307,42 @@
 				&aml_vcodec_dec_ctrl_ops,
 				V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
 				0, 32, 1, 2);
-	ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
-	if (ctx->ctrl_hdl.error) {
+	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;
-	if (ctx->ctrl_hdl.error) {
+
+	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_st_mode, NULL);
-	if (ctx->ctrl_hdl.error) {
+	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;
 	}
@@ -2545,16 +4362,25 @@
 	struct v4l2_streamparm *a)
 {
 	struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+	struct vb2_queue *dst_vq;
 
-	if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-		if (vdec_if_get_param(ctx, GET_PARAM_CONFIG_INFO,
-			&ctx->config.parm.dec)) {
+	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");
-			return -1;
-		}
-		memcpy(a->parm.raw_data, ctx->config.parm.data,
-			sizeof(a->parm.raw_data));
+		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__);
@@ -2562,22 +4388,65 @@
 	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__);
 
-	if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+	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 (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)
@@ -2586,31 +4455,37 @@
 			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;
 }
 
-static void m2mops_vdec_lock(void *m2m_priv)
-{
-	struct aml_vcodec_ctx *ctx = m2m_priv;
-
-	mutex_lock(&ctx->dev->dev_mutex);
-}
-
-static void m2mops_vdec_unlock(void *m2m_priv)
-{
-	struct aml_vcodec_ctx *ctx = m2m_priv;
-
-	mutex_unlock(&ctx->dev->dev_mutex);
-}
 
 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,
-	.lock		= m2mops_vdec_lock,
-	.unlock		= m2mops_vdec_unlock,
 };
 
 static const struct vb2_ops aml_vdec_vb2_ops = {
@@ -2620,6 +4495,7 @@
 	.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,
@@ -2636,10 +4512,10 @@
 	.vidioc_qbuf			= vidioc_vdec_qbuf,
 	.vidioc_dqbuf			= vidioc_vdec_dqbuf,
 
-	.vidioc_try_fmt_vid_cap_mplane	= vidioc_try_fmt_vid_cap_mplane,
-	.vidioc_try_fmt_vid_cap		= vidioc_try_fmt_vid_cap_mplane,
-	.vidioc_try_fmt_vid_out_mplane	= vidioc_try_fmt_vid_out_mplane,
-	.vidioc_try_fmt_vid_out		= vidioc_try_fmt_vid_out_mplane,
+	.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,
@@ -2652,17 +4528,18 @@
 
 	.vidioc_create_bufs		= vidioc_vdec_create_bufs,
 
-	.vidioc_enum_fmt_vid_cap_mplane	= vidioc_vdec_enum_fmt_vid_cap_mplane,
+	//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_mplane	= vidioc_vdec_enum_fmt_vid_out_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_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,
@@ -2680,11 +4557,11 @@
 	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;
+	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_contig_memops;
+	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);
@@ -2703,6 +4580,7 @@
 	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);
diff --git a/drivers/amvdec_ports/aml_vcodec_dec.h b/drivers/amvdec_ports/aml_vcodec_dec.h
index 3653ff0..a23522c 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.h
+++ b/drivers/amvdec_ports/aml_vcodec_dec.h
@@ -20,11 +20,14 @@
 #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
@@ -38,15 +41,25 @@
 #define VDEC_GATHER_MEMORY_TYPE		0
 #define VDEC_SCATTER_MEMORY_TYPE	1
 
-/**
- * struct vdec_fb  - decoder frame buffer
+#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
- * @vf_handle	: video frame handle
  * @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 {
@@ -56,11 +69,12 @@
 		struct	aml_vcodec_mem mem[4];
 		u32	vf_fd;
 	} m;
-	ulong	vf_handle;
 	u32	status;
 	u32	buf_idx;
-};
+	void	*vframe;
 
+	struct task_chain_s *task;
+};
 
 /**
  * struct aml_video_dec_buf - Private data related to each VB2 buffer.
@@ -68,10 +82,6 @@
  * @list:	link list
  * @used:	Capture buffer contain decoded frame data and keep in
  *			codec data structure
- * @ready_to_display:	Capture buffer not display yet
- * @queued_in_vb2:	Capture buffer is queue in vb2
- * @queued_in_v4l2:	Capture buffer is in v4l2 driver, but not in vb2
- *			queue yet
  * @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
@@ -87,12 +97,21 @@
 	struct codec_mm_s *mem[2];
 	char mem_onwer[32];
 	bool used;
-	bool ready_to_display;
 	bool que_in_m2m;
-	bool queued_in_vb2;
-	bool queued_in_v4l2;
 	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;
@@ -111,16 +130,19 @@
 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 vdec_device_vf_run(struct aml_vcodec_ctx *ctx);
-void try_to_capture(struct aml_vcodec_ctx *ctx);
-void aml_thread_notify(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);
 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
index 1ed0b97..18f0254 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec_drv.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec_drv.c
@@ -29,11 +29,11 @@
 #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_vfm.h"
+#include "aml_vcodec_vpp.h"
 #include <linux/file.h>
 #include <linux/anon_inodes.h>
 
@@ -50,6 +50,7 @@
 
 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)
 {
@@ -62,12 +63,21 @@
 	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++;
@@ -76,14 +86,26 @@
 	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->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) {
@@ -111,9 +133,19 @@
 	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;
 
-	ret = aml_thread_start(ctx, try_to_capture, AML_THREAD_CAPTURE, "cap");
+	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");
@@ -126,7 +158,7 @@
 	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "%s decoder %lx\n",
 		dev_name(&dev->plat_dev->dev), (ulong)ctx);
 
-	return ret;
+	return 0;
 
 	/* Deinit when failure occurred */
 err_creat_thread:
@@ -136,6 +168,7 @@
 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);
@@ -151,24 +184,20 @@
 	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "release decoder %lx\n", (ulong) ctx);
 	mutex_lock(&dev->dev_mutex);
 
-	/*
-	 * Call v4l2_m2m_ctx_release before aml_vcodec_dec_release. First, it
-	 * makes sure the worker thread is not running after vdec_if_deinit.
-	 * Second, the decoder will be flushed and all the buffers will be
-	 * returned in stop_streaming.
-	 */
 	aml_thread_stop(ctx);
 	wait_vcodec_ending(ctx);
-	v4l2_m2m_ctx_release(ctx->m2m_ctx);
-	aml_vcodec_dec_release(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);
-	kfree(ctx);
+	kref_put(&ctx->ctx_ref, aml_v4l_ctx_release);
 	mutex_unlock(&dev->dev_mutex);
 	return 0;
 }
@@ -302,8 +331,10 @@
 
 	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;
 	}
 
@@ -415,6 +446,43 @@
 	.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;
@@ -427,6 +495,7 @@
 
 	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);
@@ -437,8 +506,7 @@
 
 	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
 	if (ret) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
-			"v4l2_device_register err=%d\n", ret);
+		dev_err(&pdev->dev, "v4l2_device_register err=%d\n", ret);
 		goto err_res;
 	}
 
@@ -446,8 +514,7 @@
 
 	vfd_dec = video_device_alloc();
 	if (!vfd_dec) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
-			"Failed to allocate video device\n");
+		dev_err(&pdev->dev, "Failed to allocate video device\n");
 		ret = -ENOMEM;
 		goto err_dec_alloc;
 	}
@@ -459,7 +526,7 @@
 	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;
+					V4L2_CAP_STREAMING;
 
 	snprintf(vfd_dec->name, sizeof(vfd_dec->name), "%s",
 		AML_VCODEC_DEC_NAME);
@@ -469,18 +536,16 @@
 
 	dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops);
 	if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
-			"Failed to init mem2mem dec device\n");
+		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(AML_VCODEC_DEC_NAME,
-			WQ_MEM_RECLAIM | WQ_FREEZABLE);
+		alloc_ordered_workqueue("output-worker",
+			__WQ_LEGACY | WQ_MEM_RECLAIM | WQ_HIGHPRI);
 	if (!dev->decode_workqueue) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
-			"Failed to create decode workqueue\n");
+		dev_err(&pdev->dev, "Failed to create decode workqueue\n");
 		ret = -EINVAL;
 		goto err_event_workq;
 	}
@@ -489,16 +554,26 @@
 
 	ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, 26);
 	if (ret) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
-			"Failed to register video device\n");
+		dev_err(&pdev->dev, "Failed to register video device\n");
 		goto err_dec_reg;
 	}
 
-	v4l_dbg(0, V4L_DEBUG_CODEC_PRINFO,
-		"decoder registered as /dev/video%d\n", vfd_dec->num);
+	/*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:
@@ -512,13 +587,6 @@
 	return ret;
 }
 
-static const struct of_device_id aml_vcodec_match[] = {
-	{.compatible = "amlogic, vcodec-dec",},
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, aml_vcodec_match);
-
 static int aml_vcodec_dec_remove(struct platform_device *pdev)
 {
 	struct aml_vcodec_dev *dev = platform_get_drvdata(pdev);
@@ -526,6 +594,8 @@
 	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);
 
@@ -534,12 +604,17 @@
 
 	v4l2_device_unregister(&dev->v4l2_dev);
 
+	dev_info(&pdev->dev, "v4ldec removed.\n");
+
 	return 0;
 }
 
-/*static void aml_vcodec_dev_release(struct device *dev)
-{
-}*/
+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,
@@ -550,44 +625,36 @@
 	},
 };
 
-/*
-static struct platform_device aml_vcodec_dec_device = {
-	.name		= AML_VCODEC_DEC_NAME,
-	.dev.release	= aml_vcodec_dev_release,
-};*/
-
-module_platform_driver(aml_vcodec_dec_driver);
-
-/*
 static int __init amvdec_ports_init(void)
 {
-	int ret;
+	pr_info("v4l dec module init\n");
 
-	ret = platform_device_register(&aml_vcodec_dec_device);
-	if (ret)
-		return ret;
+	if (platform_driver_register(&aml_vcodec_dec_driver)) {
+		pr_err("failed to register v4l dec driver\n");
+		return -ENODEV;
+	}
 
-	ret = platform_driver_register(&aml_vcodec_dec_driver);
-	if (ret)
-		platform_device_unregister(&aml_vcodec_dec_device);
-
-	return ret;
+	return 0;
 }
 
 static void __exit amvdec_ports_exit(void)
 {
+	pr_info("v4l dec module exit\n");
+
 	platform_driver_unregister(&aml_vcodec_dec_driver);
-	platform_device_unregister(&aml_vcodec_dec_device);
 }
 
 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);
@@ -616,20 +683,72 @@
 EXPORT_SYMBOL(multiplanar);
 module_param(multiplanar, bool, 0644);
 
-bool dump_capture_frame;
+int dump_capture_frame;
 EXPORT_SYMBOL(dump_capture_frame);
-module_param(dump_capture_frame, bool, 0644);
+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
index 2e9e576..522fe67 100644
--- a/drivers/amvdec_ports/aml_vcodec_drv.h
+++ b/drivers/amvdec_ports/aml_vcodec_drv.h
@@ -20,14 +20,19 @@
 #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"
@@ -66,6 +71,8 @@
 #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. */
@@ -79,6 +86,7 @@
 /* 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
  */
@@ -119,7 +127,6 @@
  * @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_RESET	- decoder has be reset after flush.
  * @AML_STATE_ABORT	- vcodec should be aborted
  */
 enum aml_instance_state {
@@ -130,7 +137,6 @@
 	AML_STATE_ACTIVE,
 	AML_STATE_FLUSHING,
 	AML_STATE_FLUSHED,
-	AML_STATE_RESET,
 	AML_STATE_ABORT,
 };
 
@@ -156,9 +162,10 @@
  * struct aml_video_fmt - Structure used to store information about pixelformats
  */
 struct aml_video_fmt {
-	u32	fourcc;
+	u32			fourcc;
 	enum aml_fmt_type	type;
-	u32	num_planes;
+	u32			num_planes;
+	const u8		*name;
 };
 
 /**
@@ -183,13 +190,13 @@
  * struct aml_q_data - Structure used to store information about queue
  */
 struct aml_q_data {
-	unsigned int	visible_width;
-	unsigned int	visible_height;
-	unsigned int	coded_width;
-	unsigned int	coded_height;
+	u32	visible_width;
+	u32	visible_height;
+	u32	coded_width;
+	u32	coded_height;
 	enum v4l2_field	field;
-	unsigned int	bytesperline[AML_VCODEC_MAX_PLANES];
-	unsigned int	sizeimage[AML_VCODEC_MAX_PLANES];
+	u32	bytesperline[AML_VCODEC_MAX_PLANES];
+	u32	sizeimage[AML_VCODEC_MAX_PLANES];
 	struct aml_video_fmt	*fmt;
 	bool resolution_changed;
 };
@@ -214,42 +221,19 @@
  * @force_intra: force/insert intra frame
  */
 struct aml_enc_params {
-	unsigned int	bitrate;
-	unsigned int	num_b_frame;
-	unsigned int	rc_frame;
-	unsigned int	rc_mb;
-	unsigned int	seq_hdr_mode;
-	unsigned int	intra_period;
-	unsigned int	gop_size;
-	unsigned int	framerate_num;
-	unsigned int	framerate_denom;
-	unsigned int	h264_max_qp;
-	unsigned int	h264_profile;
-	unsigned int	h264_level;
-	unsigned int	force_intra;
-};
-
-/**
- * struct aml_vcodec_pm - Power management data structure
- */
-struct aml_vcodec_pm {
-	struct clk	*vdec_bus_clk_src;
-	struct clk	*vencpll;
-
-	struct clk	*vcodecpll;
-	struct clk	*univpll_d2;
-	struct clk	*clk_cci400_sel;
-	struct clk	*vdecpll;
-	struct clk	*vdec_sel;
-	struct clk	*vencpll_d2;
-	struct clk	*venc_sel;
-	struct clk	*univpll1_d2;
-	struct clk	*venc_lt_sel;
-	struct device	*larbvdec;
-	struct device	*larbvenc;
-	struct device	*larbvenclt;
-	struct device	*dev;
-	struct aml_vcodec_dev	*amldev;
+	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;
 };
 
 /**
@@ -266,20 +250,38 @@
  *		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 {
-	unsigned int visible_width;
-	unsigned int visible_height;
-	unsigned int coded_width;
-	unsigned int coded_height;
-	unsigned int y_bs_sz;
-	unsigned int c_bs_sz;
-	unsigned int y_len_sz;
-	unsigned int c_len_sz;
+	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;
-	int ref_frame_count;
 	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 {
@@ -290,6 +292,20 @@
 	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 {
@@ -323,8 +339,10 @@
 	u32 mb_height;
 	u32 dpb_size;
 	u32 ref_frames;
-	u32 reorder_frames;
+	u32 dpb_frames;
+	u32 dpb_margin;
 	u32 field;
+	u32 data[3];
 };
 
 struct aml_vdec_cnt_infos {
@@ -361,7 +379,7 @@
 	 */
 	u32 seq[V4L_CAP_BUFF_MAX];
 	u32 in, out;
-	u32 dec, vpp;
+	u32 dec, vpp, ge2d;
 };
 
 enum aml_thread_type {
@@ -372,35 +390,203 @@
 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;
+	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;
+	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.
- * @lock: protect the vdec thread.
  * @state_lock: protect the codec status.
  * @state: state of the context.
  * @decode_work: decoder work be used to output buffer.
@@ -408,6 +594,7 @@
  * @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.
@@ -430,24 +617,46 @@
  * @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			lock, state_lock;
+	struct mutex			state_lock;
 	enum aml_instance_state		state;
 	struct work_struct		decode_work;
 	bool				output_thread_ready;
@@ -455,6 +664,8 @@
 	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;
@@ -467,6 +678,7 @@
 	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;
@@ -477,81 +689,84 @@
 	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
- * @vfd_enc: Video device for encoder.
- *
- * @m2m_dev_dec: m2m device for decoder
- * @m2m_dev_enc: m2m device for encoder.
- * @plat_dev: platform device
- * @vpu_plat_dev: aml vpu platform device
- * @alloc_ctx: VB2 allocator context
- *	       (for allocations without kernel mapping).
- * @ctx_list: list of struct aml_vcodec_ctx
- * @irqlock: protect data access by irq handler and work thread
- * @curr_ctx: The context that is waiting for codec hardware
- *
- * @reg_base: Mapped address of AML Vcodec registers.
- *
- * @id_counter: used to identify current opened instance
- *
- * @encode_workqueue: encode work queue
- *
- * @int_cond: used to identify interrupt condition happen
- * @int_type: used to identify what kind of interrupt condition happen
- * @dev_mutex: video_device lock
- * @queue: waitqueue for waiting for completion of device commands
- *
- * @dec_irq: decoder irq resource
- * @enc_irq: h264 encoder irq resource
- * @enc_lt_irq: vp8 encoder irq resource
- *
- * @dec_mutex: decoder hardware lock
- * @enc_mutex: encoder hardware lock.
- *
- * @pm: power management control
- * @dec_capability: used to identify decode capability, ex: 4k
- * @enc_capability: used to identify encode capability
+ * 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 video_device *vfd_enc;
-	struct file *filp;
-
-	struct v4l2_m2m_dev *m2m_dev_dec;
-	struct v4l2_m2m_dev *m2m_dev_enc;
-	struct platform_device *plat_dev;
-	struct platform_device *vpu_plat_dev;//??
-	struct vb2_alloc_ctx *alloc_ctx;//??
-	struct list_head ctx_list;
-	spinlock_t irqlock;
-	struct aml_vcodec_ctx *curr_ctx;
-	void __iomem *reg_base[NUM_MAX_VCODEC_REG_BASE];
-
-	unsigned long id_counter;
-
-	struct workqueue_struct *decode_workqueue;
-	struct workqueue_struct *encode_workqueue;
-	int int_cond;
-	int int_type;
-	struct mutex dev_mutex;
-	wait_queue_head_t queue;
-
-	int dec_irq;
-	int enc_irq;
-	int enc_lt_irq;
-
-	struct mutex dec_mutex;
-	struct mutex enc_mutex;
-
-	struct aml_vcodec_pm pm;
-	unsigned int dec_capability;
-	unsigned int enc_capability;
+	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)
@@ -564,4 +779,10 @@
 	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
index 509a42a..54b0d06 100644
--- a/drivers/amvdec_ports/aml_vcodec_util.c
+++ b/drivers/amvdec_ports/aml_vcodec_util.c
@@ -22,72 +22,6 @@
 #include "aml_vcodec_drv.h"
 #include "aml_vcodec_util.h"
 
-void __iomem *aml_vcodec_get_reg_addr(struct aml_vcodec_ctx *data,
-					unsigned int reg_idx)
-{
-	struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data;
-
-	if (!data || reg_idx >= NUM_MAX_VCODEC_REG_BASE) {
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
-			"Invalid arguments, reg_idx=%d\n", reg_idx);
-		return NULL;
-	}
-	return ctx->dev->reg_base[reg_idx];
-}
-EXPORT_SYMBOL(aml_vcodec_get_reg_addr);
-
-int aml_vcodec_mem_alloc(struct aml_vcodec_ctx *data,
-			struct aml_vcodec_mem *mem)
-{
-	unsigned long size = mem->size;
-	struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data;
-	struct device *dev = &ctx->dev->plat_dev->dev;
-
-	mem->vaddr = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL);
-	//mem->vaddr = codec_mm_dma_alloc_coherent(dev_name(dev), size,
-	//		&mem->dma_addr, GFP_KERNEL, 0);
-	if (!mem->vaddr) {
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
-			"%s dma_alloc size=%ld failed!\n", dev_name(dev),
-			     size);
-		return -ENOMEM;
-	}
-
-	memset(mem->vaddr, 0, size);
-
-	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "va: %p\n", mem->vaddr);
-	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "dma: 0x%lx\n", (ulong) mem->dma_addr);
-	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "size: 0x%lx\n", size);
-
-	return 0;
-}
-EXPORT_SYMBOL(aml_vcodec_mem_alloc);
-
-void aml_vcodec_mem_free(struct aml_vcodec_ctx *data,
-			struct aml_vcodec_mem *mem)
-{
-	unsigned long size = mem->size;
-	struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)data;
-	struct device *dev = &ctx->dev->plat_dev->dev;
-
-	if (!mem->vaddr) {
-		v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
-			"%s dma_free size=%ld failed!\n", dev_name(dev),
-			     size);
-		return;
-	}
-
-	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "va: %p\n", mem->vaddr);
-	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "dma: 0x%lx\n", (ulong) mem->dma_addr);
-	v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "size: 0x%lx\n", size);
-
-	dma_free_coherent(dev, size, mem->vaddr, mem->dma_addr);
-	mem->vaddr = NULL;
-	mem->dma_addr = 0;
-	mem->size = 0;
-}
-EXPORT_SYMBOL(aml_vcodec_mem_free);
-
 void aml_vcodec_set_curr_ctx(struct aml_vcodec_dev *dev,
 	struct aml_vcodec_ctx *ctx)
 {
diff --git a/drivers/amvdec_ports/aml_vcodec_util.h b/drivers/amvdec_ports/aml_vcodec_util.h
index 312ee40..96c5453 100644
--- a/drivers/amvdec_ports/aml_vcodec_util.h
+++ b/drivers/amvdec_ports/aml_vcodec_util.h
@@ -23,14 +23,14 @@
 #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))
 
@@ -45,14 +45,16 @@
 	u32	bytes_used;
 	u32	offset;
 	u64	timestamp;
-	dma_addr_t dma_addr;
 	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
@@ -69,6 +71,11 @@
 #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 {								\
@@ -92,12 +99,6 @@
 		}								\
 	} while (0)
 
-void __iomem *aml_vcodec_get_reg_addr(struct aml_vcodec_ctx *data,
-				unsigned int reg_idx);
-int aml_vcodec_mem_alloc(struct aml_vcodec_ctx *data,
-				struct aml_vcodec_mem *mem);
-void aml_vcodec_mem_free(struct aml_vcodec_ctx *data,
-				struct aml_vcodec_mem *mem);
 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);
diff --git a/drivers/amvdec_ports/aml_vcodec_vfm.c b/drivers/amvdec_ports/aml_vcodec_vfm.c
deleted file mode 100644
index 62896ea..0000000
--- a/drivers/amvdec_ports/aml_vcodec_vfm.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
-* 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 "aml_vcodec_vfm.h"
-#include "aml_vcodec_vfq.h"
-#include "aml_vcodec_util.h"
-#include "aml_vcodec_adapt.h"
-#include <media/v4l2-mem2mem.h>
-
-#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_VIDEO_COMPOSER
-#include <trace/events/meson_atrace.h>
-
-#define RECEIVER_NAME	"v4l2-video"
-#define PROVIDER_NAME	"v4l2-video"
-
-static struct vframe_s *vdec_vf_peek(void *op_arg)
-{
-	struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg;
-
-	return vfq_peek(&vfm->vf_que);
-}
-
-static struct vframe_s *vdec_vf_get(void *op_arg)
-{
-	struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg;
-
-	return vfq_pop(&vfm->vf_que);
-}
-
-static void vdec_vf_put(struct vframe_s *vf, void *op_arg)
-{
-	struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg;
-
-	/* If the video frame from amvide that means */
-	/* the data has been processed and finished, */
-	/* then push back to VDA. thus we don't put the */
-	/* buffer to the decoder directly.*/
-
-	//vf_put(vf, vfm->recv_name);
-	//vf_notify_provider(vfm->recv_name, VFRAME_EVENT_RECEIVER_PUT, NULL);
-
-	if (vfq_level(&vfm->vf_que_recycle) > POOL_SIZE - 1) {
-		v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_ERROR, "vfq full.\n");
-		return;
-	}
-
-	atomic_set(&vf->use_cnt, 1);
-
-	vfq_push(&vfm->vf_que_recycle, vf);
-
-	/* schedule capture work. */
-	vdec_device_vf_run(vfm->ctx);
-}
-
-static int vdec_event_cb(int type, void *data, void *private_data)
-{
-
-	if (type & VFRAME_EVENT_RECEIVER_PUT) {
-	} else if (type & VFRAME_EVENT_RECEIVER_GET) {
-	} else if (type & VFRAME_EVENT_RECEIVER_FRAME_WAIT) {
-	}
-	return 0;
-}
-
-static int vdec_vf_states(struct vframe_states *states, void *op_arg)
-{
-	struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg;
-
-	states->vf_pool_size	= POOL_SIZE;
-	states->buf_recycle_num	= 0;
-	states->buf_free_num	= POOL_SIZE - vfq_level(&vfm->vf_que);
-	states->buf_avail_num	= vfq_level(&vfm->vf_que);
-
-	return 0;
-}
-
-void video_vf_put(char *receiver, struct vdec_v4l2_buffer *fb, int id)
-{
-	struct vframe_provider_s *vfp = vf_get_provider(receiver);
-	struct vframe_s *vf = (struct vframe_s *)fb->vf_handle;
-
-	ATRACE_COUNTER("v4l2_to", vf->index_disp);
-
-	v4l_dbg(0, V4L_DEBUG_CODEC_OUTPUT,
-		"[%d]: TO   (%s) vf: %p, idx: %d, "
-		"Y:(%lx, %u) C/U:(%lx, %u) V:(%lx, %u)\n",
-		id, vfp->name, vf, vf->index,
-		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);
-
-	if (vfp && vf && atomic_dec_and_test(&vf->use_cnt))
-		vf_put(vf, receiver);
-}
-
-static const struct vframe_operations_s vf_provider = {
-	.peek		= vdec_vf_peek,
-	.get		= vdec_vf_get,
-	.put		= vdec_vf_put,
-	.event_cb	= vdec_event_cb,
-	.vf_states	= vdec_vf_states,
-};
-
-static int video_receiver_event_fun(int type, void *data, void *private_data)
-{
-	int ret = 0;
-	struct vframe_states states;
-	struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)private_data;
-
-	switch (type) {
-	case VFRAME_EVENT_PROVIDER_UNREG: {
-		if (vf_get_receiver(vfm->prov_name)) {
-			v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_EXINFO,
-				"unreg %s provider.\n",
-				vfm->prov_name);
-			vf_unreg_provider(&vfm->vf_prov);
-		}
-
-		break;
-	}
-
-	case VFRAME_EVENT_PROVIDER_START: {
-		if (vf_get_receiver(vfm->prov_name)) {
-			v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_EXINFO,
-				"reg %s provider.\n",
-				vfm->prov_name);
-			vf_provider_init(&vfm->vf_prov, vfm->prov_name,
-				&vf_provider, vfm);
-			vf_reg_provider(&vfm->vf_prov);
-			vf_notify_receiver(vfm->prov_name,
-				VFRAME_EVENT_PROVIDER_START, NULL);
-		}
-
-		vfq_init(&vfm->vf_que, POOL_SIZE + 1, &vfm->pool[0]);
-		vfq_init(&vfm->vf_que_recycle, POOL_SIZE + 1, &vfm->pool_recycle[0]);
-
-		break;
-	}
-
-	case VFRAME_EVENT_PROVIDER_QUREY_STATE: {
-		vdec_vf_states(&states, vfm);
-		if (states.buf_avail_num > 0)
-			ret = RECEIVER_ACTIVE;
-		break;
-	}
-
-	case VFRAME_EVENT_PROVIDER_VFRAME_READY: {
-		if (vfq_level(&vfm->vf_que) > POOL_SIZE - 1)
-			ret = -1;
-
-		if (!vf_peek(vfm->recv_name))
-			ret = -1;
-
-		vfm->vf = vf_get(vfm->recv_name);
-		if (!vfm->vf)
-			ret = -1;
-
-		if (ret < 0) {
-			v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_ERROR, "receiver vf err.\n");
-			break;
-		}
-
-		vfq_push(&vfm->vf_que, vfm->vf);
-
-		if (vfm->ada_ctx->vfm_path == FRAME_BASE_PATH_V4L_VIDEO) {
-			vf_notify_receiver(vfm->prov_name,
-				VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
-			break;
-		}
-
-		/* schedule capture work. */
-		vdec_device_vf_run(vfm->ctx);
-
-		break;
-	}
-
-	default:
-		v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_EXINFO,
-			"the vf event is %d", type);
-	}
-
-	return ret;
-}
-
-static const struct vframe_receiver_op_s vf_receiver = {
-	.event_cb	= video_receiver_event_fun
-};
-
-struct vframe_s *peek_video_frame(struct vcodec_vfm_s *vfm)
-{
-	if (vfm->ada_ctx->vfm_path == FRAME_BASE_PATH_V4L_VIDEO)
-		return vfq_peek(&vfm->vf_que_recycle);
-	else
-		return vfq_peek(&vfm->vf_que);
-}
-
-struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm)
-{
-	if (vfm->ada_ctx->vfm_path == FRAME_BASE_PATH_V4L_VIDEO)
-		return vfq_pop(&vfm->vf_que_recycle);
-	else
-		return vfq_pop(&vfm->vf_que);
-}
-
-int vcodec_vfm_init(struct vcodec_vfm_s *vfm)
-{
-	int ret;
-
-	snprintf(vfm->recv_name, VF_NAME_SIZE, "%s-%d",
-		RECEIVER_NAME, vfm->ctx->id);
-	snprintf(vfm->prov_name, VF_NAME_SIZE, "%s-%d",
-		PROVIDER_NAME, vfm->ctx->id);
-
-	vfm->ada_ctx->recv_name = vfm->recv_name;
-
-	vf_receiver_init(&vfm->vf_recv, vfm->recv_name, &vf_receiver, vfm);
-	ret = vf_reg_receiver(&vfm->vf_recv);
-
-	vfm->vfm_initialized = ret ? false : true;
-
-	return ret;
-}
-
-void vcodec_vfm_release(struct vcodec_vfm_s *vfm)
-{
-	if (vfm->vfm_initialized)
-		vf_unreg_receiver(&vfm->vf_recv);
-}
-
diff --git a/drivers/amvdec_ports/aml_vcodec_vfm.h b/drivers/amvdec_ports/aml_vcodec_vfm.h
deleted file mode 100644
index 141e9a7..0000000
--- a/drivers/amvdec_ports/aml_vcodec_vfm.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-* 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_VFM_H_
-#define __AML_VCODEC_VFM_H_
-
-#include "aml_vcodec_vfq.h"
-#include "aml_vcodec_drv.h"
-#include "aml_vcodec_dec.h"
-#include <linux/amlogic/media/vfm/vframe_provider.h>
-#include <linux/amlogic/media/vfm/vframe_receiver.h>
-
-#define VF_NAME_SIZE	(32)
-#define POOL_SIZE	(32)
-
-struct vcodec_vfm_s {
-	struct aml_vcodec_ctx *ctx;
-	struct aml_vdec_adapt *ada_ctx;
-	struct vfq_s vf_que;
-	struct vfq_s vf_que_recycle;
-	struct vframe_s *vf;
-	struct vframe_s *pool[POOL_SIZE + 1];
-	struct vframe_s *pool_recycle[POOL_SIZE + 1];
-	char recv_name[VF_NAME_SIZE];
-	char prov_name[VF_NAME_SIZE];
-	struct vframe_provider_s vf_prov;
-	struct vframe_receiver_s vf_recv;
-	bool vfm_initialized;
-};
-
-int vcodec_vfm_init(struct vcodec_vfm_s *vfm);
-
-void vcodec_vfm_release(struct vcodec_vfm_s *vfm);
-
-struct vframe_s *peek_video_frame(struct vcodec_vfm_s *vfm);
-
-struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm);
-
-int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_fb);
-int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *in_fb);
-
-void video_vf_put(char *receiver, struct vdec_v4l2_buffer *fb, int id);
-
-#endif /* __AML_VCODEC_VFM_H_ */
diff --git a/drivers/amvdec_ports/aml_vcodec_vfq.h b/drivers/amvdec_ports/aml_vcodec_vfq.h
deleted file mode 100644
index e19c53c..0000000
--- a/drivers/amvdec_ports/aml_vcodec_vfq.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
-* 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_VFQ_H_
-#define __AML_VCODEC_VFQ_H_
-
-#include <linux/types.h>
-#include <asm/barrier.h>
-
-struct vfq_s {
-	int rp;
-	int wp;
-	int size;
-	int pre_rp;
-	int pre_wp;
-	struct vframe_s **pool;
-};
-
-static inline void vfq_lookup_start(struct vfq_s *q)
-{
-	q->pre_rp = q->rp;
-	q->pre_wp = q->wp;
-}
-static inline void vfq_lookup_end(struct vfq_s *q)
-{
-	q->rp = q->pre_rp;
-	q->wp = q->pre_wp;
-}
-
-static inline void vfq_init(struct vfq_s *q, u32 size, struct vframe_s **pool)
-{
-	q->rp = q->wp = 0;
-	q->size = size;
-	q->pool = pool;
-}
-
-static inline bool vfq_empty(struct vfq_s *q)
-{
-	return q->rp == q->wp;
-}
-
-static inline void vfq_push(struct vfq_s *q, struct vframe_s *vf)
-{
-	int wp = q->wp;
-
-	/*ToDo*/
-	smp_mb();
-
-	q->pool[wp] = vf;
-
-	/*ToDo*/
-	smp_wmb();
-
-	q->wp = (wp == (q->size - 1)) ? 0 : (wp + 1);
-}
-
-static inline struct vframe_s *vfq_pop(struct vfq_s *q)
-{
-	struct vframe_s *vf;
-	int rp;
-
-	if (vfq_empty(q))
-		return NULL;
-
-	rp = q->rp;
-
-	/*ToDo*/
-	smp_rmb();
-
-	vf = q->pool[rp];
-
-	/*ToDo*/
-	smp_mb();
-
-	q->rp = (rp == (q->size - 1)) ? 0 : (rp + 1);
-
-	return vf;
-}
-
-static inline struct vframe_s *vfq_peek(struct vfq_s *q)
-{
-	return (vfq_empty(q)) ? NULL : q->pool[q->rp];
-}
-
-static inline int vfq_level(struct vfq_s *q)
-{
-	int level = q->wp - q->rp;
-
-	if (level < 0)
-		level += q->size;
-
-	return level;
-}
-
-#endif /* __AML_VCODEC_VFQ_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
index c9da299..d0d0198 100644
--- a/drivers/amvdec_ports/decoder/aml_h264_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_h264_parser.c
@@ -1,22 +1,3 @@
-/*
-* 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/vmalloc.h>
diff --git a/drivers/amvdec_ports/decoder/aml_hevc_parser.c b/drivers/amvdec_ports/decoder/aml_hevc_parser.c
index 4ea76b9..24977a8 100644
--- a/drivers/amvdec_ports/decoder/aml_hevc_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_hevc_parser.c
@@ -1,22 +1,3 @@
-/*
-* 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/vmalloc.h>
diff --git a/drivers/amvdec_ports/decoder/aml_hevc_parser.h b/drivers/amvdec_ports/decoder/aml_hevc_parser.h
index 0c81cb5..9223639 100644
--- a/drivers/amvdec_ports/decoder/aml_hevc_parser.h
+++ b/drivers/amvdec_ports/decoder/aml_hevc_parser.h
@@ -22,7 +22,6 @@
 #include "../aml_vcodec_drv.h"
 #include "../utils/common.h"
 
-
 #define MAX_DPB_SIZE				16 // A.4.1
 #define MAX_REFS				16
 
diff --git a/drivers/amvdec_ports/decoder/aml_mjpeg_parser.c b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.c
index fd56755..c582ab0 100644
--- a/drivers/amvdec_ports/decoder/aml_mjpeg_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.c
@@ -1,22 +1,3 @@
-/*
-* 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/vmalloc.h>
diff --git a/drivers/amvdec_ports/decoder/aml_mjpeg_parser.h b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.h
index bbc9282..4704ba0 100644
--- a/drivers/amvdec_ports/decoder/aml_mjpeg_parser.h
+++ b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.h
@@ -1,19 +1,3 @@
-/*
- * drivers/amvdec_ports/decoder/aml_mjpeg_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_MJPEG_PARSER_H
 #define AML_MJPEG_PARSER_H
 
diff --git a/drivers/amvdec_ports/decoder/aml_mpeg12_parser.c b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.c
index 2720446..748a83f 100644
--- a/drivers/amvdec_ports/decoder/aml_mpeg12_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.c
@@ -1,22 +1,3 @@
-/*
-* 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/vmalloc.h>
diff --git a/drivers/amvdec_ports/decoder/aml_mpeg12_parser.h b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.h
index 8abbc78..c06d632 100644
--- a/drivers/amvdec_ports/decoder/aml_mpeg12_parser.h
+++ b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.h
@@ -1,19 +1,3 @@
-/*
- * drivers/amvdec_ports/decoder/aml_mpeg12_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_MPEG12_PARSER_H
 #define AML_MPEG12_PARSER_H
 
@@ -23,7 +7,6 @@
 #include "../utils/pixfmt.h"
 #endif
 
-
 /* Start codes. */
 #define SEQ_END_CODE            0x000001b7
 #define SEQ_START_CODE          0x000001b3
diff --git a/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c
index f680b12..9c47c08 100644
--- a/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c
@@ -1,22 +1,3 @@
-/*
-* 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/vmalloc.h>
diff --git a/drivers/amvdec_ports/decoder/aml_mpeg4_parser.h b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.h
index 3e5bf62..f9b71cf 100644
--- a/drivers/amvdec_ports/decoder/aml_mpeg4_parser.h
+++ b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.h
@@ -1,19 +1,3 @@
-/*
- * drivers/amvdec_ports/decoder/aml_mpeg4_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 AVCODEC_MPEG4VIDEO_H
 #define AVCODEC_MPEG4VIDEO_H
 
diff --git a/drivers/amvdec_ports/decoder/aml_vp9_parser.c b/drivers/amvdec_ports/decoder/aml_vp9_parser.c
index b027b8a..21d5283 100644
--- a/drivers/amvdec_ports/decoder/aml_vp9_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_vp9_parser.c
@@ -1,22 +1,3 @@
-/*
-* 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/vmalloc.h>
diff --git a/drivers/amvdec_ports/decoder/vdec_av1_if.c b/drivers/amvdec_ports/decoder/vdec_av1_if.c
index e8693d4..c28ca10 100644
--- a/drivers/amvdec_ports/decoder/vdec_av1_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_av1_if.c
@@ -29,7 +29,6 @@
 #include "../aml_vcodec_drv.h"
 #include "../aml_vcodec_adapt.h"
 #include "../vdec_drv_base.h"
-#include "../aml_vcodec_vfm.h"
 #include "../utils/common.h"
 
 #define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2
@@ -118,9 +117,9 @@
 	struct aml_vcodec_ctx *ctx;
 	struct aml_vdec_adapt vdec;
 	struct vdec_av1_vsi *vsi;
-	struct vcodec_vfm_s vfm;
 	struct aml_dec_params parms;
 	struct completion comp;
+	struct vdec_comp_buf_info comp_info;
 };
 
 /*!\brief OBU types. */
@@ -207,6 +206,7 @@
 
 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)
@@ -246,12 +246,12 @@
 	u8 *pbuf = parm;
 
 	pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
-	pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:11;");
-	pbuf += sprintf(pbuf, "av1_double_write_mode:3;");
+	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:8192;");
-	pbuf += sprintf(pbuf, "av1_max_pic_h:4608;");
+	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;");
@@ -264,6 +264,10 @@
 {
 	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;
@@ -273,10 +277,8 @@
 			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:%d;",
-			ctx->config.parm.dec.cfg.init_width);
-		pbuf += sprintf(pbuf, "av1_buf_height:%d;",
-			ctx->config.parm.dec.cfg.init_height);
+		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;",
@@ -285,19 +287,23 @@
 			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 = 16;
+		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) &&
-		inst->parms.hdr.color_parms.present_flag) {
+		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;",
@@ -326,6 +332,8 @@
 		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;
@@ -341,6 +349,7 @@
 	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;
@@ -355,16 +364,6 @@
 	/* to eable av1 hw.*/
 	inst->vdec.port.type	= PORT_TYPE_HEVC;
 
-	/* init vfm */
-	inst->vfm.ctx		= ctx;
-	inst->vfm.ada_ctx	= &inst->vdec;
-	ret = vcodec_vfm_init(&inst->vfm);
-	if (ret) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"init vfm failed.\n");
-		goto err;
-	}
-
 	/* probe info from the stream */
 	inst->vsi = kzalloc(sizeof(struct vdec_av1_vsi), GFP_KERNEL);
 	if (!inst->vsi) {
@@ -373,7 +372,7 @@
 	}
 
 	/* alloc the header buffer to be used cache sps or spp etc.*/
-	inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
+	inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
 	if (!inst->vsi->header_buf) {
 		ret = -ENOMEM;
 		goto err;
@@ -381,9 +380,6 @@
 
 	init_completion(&inst->comp);
 
-	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
-		"av1 Instance >> %lx\n", (ulong) inst);
-
 	ctx->ada_ctx	= &inst->vdec;
 	*h_vdec		= (unsigned long)inst;
 
@@ -395,14 +391,13 @@
 		goto err;
 	}
 
-	//dump_init();
+	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+		"av1 Instance >> %lx\n", (ulong) inst);
 
 	return 0;
 err:
-	if (inst)
-		vcodec_vfm_release(&inst->vfm);
 	if (inst && inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 	if (inst && inst->vsi)
 		kfree(inst->vsi);
 	if (inst)
@@ -428,7 +423,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_ucode_dma(struct vdec_av1_inst *inst,
@@ -449,7 +444,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_cpu(struct vdec_av1_inst *inst, u8 *buf, u32 size)
@@ -504,19 +499,13 @@
 
 static void vdec_av1_deinit(unsigned long h_vdec)
 {
-	ulong flags;
 	struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec;
 	struct aml_vcodec_ctx *ctx = inst->ctx;
 
 	video_decoder_release(&inst->vdec);
 
-	vcodec_vfm_release(&inst->vfm);
-
-	//dump_deinit();
-
-	spin_lock_irqsave(&ctx->slock, flags);
 	if (inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 
 	if (inst->vsi)
 		kfree(inst->vsi);
@@ -524,42 +513,6 @@
 	kfree(inst);
 
 	ctx->drv_handle = 0;
-	spin_unlock_irqrestore(&ctx->slock, flags);
-}
-
-static int vdec_av1_get_fb(struct vdec_av1_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	return get_fb_from_queue(inst->ctx, out);
-}
-
-static void vdec_av1_get_vf(struct vdec_av1_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	struct vframe_s *vf = NULL;
-	struct vdec_v4l2_buffer *fb = NULL;
-
-	vf = peek_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"there is no vframe.\n");
-		*out = NULL;
-		return;
-	}
-
-	vf = get_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"the vframe is avalid.\n");
-		*out = NULL;
-		return;
-	}
-
-	atomic_set(&vf->use_cnt, 1);
-
-	fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
-	fb->vf_handle = (unsigned long)vf;
-	fb->status = FB_ST_DISPLAY;
-
-	*out = fb;
 }
 
 // Returns 1 when OBU type is valid, and 0 otherwise.
@@ -636,7 +589,7 @@
 	int i;
 	const size_t leb_size = uleb_size_in_bytes(value);
 
-	if (leb_size > kMaximumLeb128Size ||
+	if (value > kMaximumLeb128Value || leb_size > kMaximumLeb128Size ||
 		leb_size > available || !coded_value || !coded_size) {
 		return -1;
 	}
@@ -704,13 +657,12 @@
 static int read_obu_header(struct read_bit_buffer *rb,
 	int is_annexb, struct ObuHeader *header)
 {
-	int bit_buffer_byte_length;
+	const int bit_buffer_byte_length =
+		rb->bit_buffer_end - rb->bit_buffer;
 
 	if (!rb || !header)
 		return -1;
 
-	bit_buffer_byte_length = rb->bit_buffer_end - rb->bit_buffer;
-
 	if (bit_buffer_byte_length < 1)
 		return -1;
 
@@ -1048,13 +1000,13 @@
 		parser_frame(0, src, src + size, data, &length, meta_buffer, &meta_size);
 
 		if (length)
-			ret = vdec_vframe_write(vdec, data, length, ts);
+			ret = vdec_vframe_write(vdec, data, length, ts, 0);
 		else
 			ret = -1;
 
 		vfree(data);
 	} else {
-		ret = vdec_vframe_write(vdec, buf, size, ts);
+		ret = vdec_vframe_write(vdec, buf, size, ts, 0);
 	}
 
 	return ret;
@@ -1088,18 +1040,14 @@
 {
 	struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec;
 	struct aml_vdec_adapt *vdec = &inst->vdec;
-	u8 *buf;
-	u32 size;
+	u8 *buf = (u8 *) bs->vaddr;
+	u32 size = bs->size;
 	int ret = -1;
 
 	if (bs == NULL)
 		return -1;
 
-	buf = (u8 *) bs->vaddr;
-	size = bs->size;
-
 	if (vdec_input_full(vdec)) {
-		ATRACE_COUNTER("vdec_input_full", 0);
 		return -EAGAIN;
 	}
 
@@ -1121,7 +1069,8 @@
 			ret = vdec_vframe_write(vdec,
 				s->data,
 				s->len,
-				bs->timestamp);
+				bs->timestamp,
+				0);
 		} else if (bs->model == VB2_MEMORY_DMABUF ||
 			bs->model == VB2_MEMORY_USERPTR) {
 			ret = vdec_vframe_write_with_dma(vdec,
@@ -1137,7 +1086,6 @@
 
 		ret = vdec_write_nalu(inst, buf, size, bs->timestamp);
 	}
-	ATRACE_COUNTER("v4l2_decode_write", ret);
 
 	return ret;
 }
@@ -1145,8 +1093,12 @@
  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)
-		 parms->cfg = inst->parms.cfg;
+	 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)
@@ -1156,10 +1108,16 @@
 
 	 parms->parms_status |= inst->parms.parms_status;
 
-	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
+	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)
 {
@@ -1167,20 +1125,12 @@
 	struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the av1 inst of dec is invalid.\n");
 		return -1;
 	}
 
 	switch (type) {
-	case GET_PARAM_DISP_FRAME_BUFFER:
-		vdec_av1_get_vf(inst, out);
-		break;
-
-	case GET_PARAM_FREE_FRAME_BUFFER:
-		ret = vdec_av1_get_fb(inst, out);
-		break;
-
 	case GET_PARAM_PIC_INFO:
 		get_pic_info(inst, out);
 		break;
@@ -1197,6 +1147,20 @@
 		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);
@@ -1211,12 +1175,69 @@
 	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;
@@ -1232,11 +1253,16 @@
 	pic->coded_width	= ps->coded_width;
 	pic->coded_height	= ps->coded_height;
 
-	pic->y_len_sz		= pic->coded_width * pic->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 |=
@@ -1246,23 +1272,27 @@
 	complete(&inst->comp);
 
 	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
-		"Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n",
+		"Parse from ucode, visible(%d x %d), coded(%d x %d)\n",
 		ps->visible_width, ps->visible_height,
-		ps->coded_width, ps->coded_height,
-		ps->dpb_size);
+		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 ((inst->parms.parms_status &
-		V4L2_CONFIG_PARM_DECODE_HDRINFO)) {
+	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_PRINFO,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
 			"av1 set HDR infos\n");
 	}
 }
@@ -1274,6 +1304,12 @@
 			"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)
 {
@@ -1281,7 +1317,7 @@
 	struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the av1 inst of dec is invalid.\n");
 		return -1;
 	}
@@ -1295,6 +1331,10 @@
 		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;
@@ -1302,6 +1342,11 @@
 	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);
diff --git a/drivers/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amvdec_ports/decoder/vdec_h264_if.c
index d13fc34..911c91d 100644
--- a/drivers/amvdec_ports/decoder/vdec_h264_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_h264_if.c
@@ -30,7 +30,6 @@
 #include "../aml_vcodec_drv.h"
 #include "../aml_vcodec_adapt.h"
 #include "../vdec_drv_base.h"
-#include "../aml_vcodec_vfm.h"
 #include "aml_h264_parser.h"
 #include "../utils/common.h"
 
@@ -150,7 +149,6 @@
 	struct aml_vcodec_mem mv_buf[H264_MAX_FB_NUM];
 	struct aml_vdec_adapt vdec;
 	struct vdec_h264_vsi *vsi;
-	struct vcodec_vfm_s vfm;
 	struct aml_dec_params parms;
 	struct completion comp;
 };
@@ -281,6 +279,10 @@
 			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;
@@ -297,14 +299,13 @@
 {
 	struct vdec_h264_inst *inst = NULL;
 	int ret = -1;
-	bool dec_init = false;
 
-	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	inst = vzalloc(sizeof(*inst));
 	if (!inst)
 		return -ENOMEM;
 
+	inst->vdec.frm_name	= "H.264";
 	inst->vdec.video_type	= VFORMAT_H264;
-	inst->vdec.dev		= ctx->dev->vpu_plat_dev;
 	inst->vdec.filp		= ctx->dev->filp;
 	inst->vdec.ctx		= ctx;
 	inst->ctx		= ctx;
@@ -315,33 +316,15 @@
 	if (ctx->is_drm_mode)
 		inst->vdec.port.flag |= PORT_FLAG_DRM;
 
-	/* init vfm */
-	inst->vfm.ctx		= ctx;
-	inst->vfm.ada_ctx	= &inst->vdec;
-	ret = vcodec_vfm_init(&inst->vfm);
-	if (ret) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"init vfm failed.\n");
-		goto err;
-	}
-
-	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;
-	}
-	dec_init = true;
-
 	/* probe info from the stream */
-	inst->vsi = kzalloc(sizeof(struct vdec_h264_vsi), GFP_KERNEL);
+	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 = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
+	inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
 	if (!inst->vsi->header_buf) {
 		ret = -ENOMEM;
 		goto err;
@@ -349,26 +332,27 @@
 
 	init_completion(&inst->comp);
 
-	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
-		"H264 Instance >> %lx", (ulong) inst);
-
 	ctx->ada_ctx	= &inst->vdec;
 	*h_vdec		= (unsigned long)inst;
 
-	//dump_init();
+	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 (dec_init)
-		video_decoder_release(&inst->vdec);
-	if (inst)
-		vcodec_vfm_release(&inst->vfm);
 	if (inst && inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 	if (inst && inst->vsi)
-		kfree(inst->vsi);
+		vfree(inst->vsi);
 	if (inst)
-		kfree(inst);
+		vfree(inst);
 	*h_vdec = 0;
 
 	return ret;
@@ -497,7 +481,6 @@
 	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;
-	pic->ref_frame_count= sps->ref_frame_count;
 	/* calc DPB size */
 	dec->dpb_sz		= sps->num_reorder_frames + margin;
 
@@ -509,7 +492,7 @@
 	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.reorder_frames	= sps->num_reorder_frames;
+	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;
 
@@ -571,7 +554,7 @@
 	int ret = 0;
 	struct aml_vdec_adapt *vdec = &inst->vdec;
 
-	ret = vdec_vframe_write(vdec, buf, size, timestamp);
+	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);
@@ -582,7 +565,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_ucode_dma(struct vdec_h264_inst *inst,
@@ -603,7 +586,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_cpu(struct vdec_h264_inst *inst, u8 *buf, u32 size)
@@ -688,71 +671,20 @@
 
 static void vdec_h264_deinit(unsigned long h_vdec)
 {
-	ulong flags;
 	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
 	struct aml_vcodec_ctx *ctx = inst->ctx;
 
 	video_decoder_release(&inst->vdec);
 
-	vcodec_vfm_release(&inst->vfm);
-
-	//dump_deinit();
-
-	spin_lock_irqsave(&ctx->slock, flags);
 	if (inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 
 	if (inst->vsi)
-		kfree(inst->vsi);
+		vfree(inst->vsi);
 
-	kfree(inst);
+	vfree(inst);
 
 	ctx->drv_handle = 0;
-	spin_unlock_irqrestore(&ctx->slock, flags);
-}
-
-static int vdec_h264_get_fb(struct vdec_h264_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	return get_fb_from_queue(inst->ctx, out);
-}
-
-static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	struct vframe_s *vf = NULL;
-	struct vdec_v4l2_buffer *fb = NULL;
-
-	vf = peek_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"there is no vframe.\n");
-		*out = NULL;
-		return;
-	}
-
-	vf = get_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"the vframe is avalid.\n");
-		*out = NULL;
-		return;
-	}
-
-	atomic_set(&vf->use_cnt, 1);
-
-	fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
-	if (fb) {
-		fb->vf_handle = (unsigned long)vf;
-		fb->status = FB_ST_DISPLAY;
-	}
-
-	*out = fb;
-
-	//pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
-	//dump_write(fb->base_y.vaddr, fb->base_y.bytes_used);
-	//dump_write(fb->base_c.vaddr, fb->base_c.bytes_used);
-
-	/* convert yuv format. */
-	//swap_uv(fb->base_c.vaddr, fb->base_c.size);
 }
 
 static int vdec_write_nalu(struct vdec_h264_inst *inst,
@@ -802,7 +734,7 @@
 		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);
+		ret = vdec_vframe_write(vdec, buf, size, ts, 0);
 	} else {
 		char *write_buf = vmalloc(inst->vsi->head_offset + size);
 		if (!write_buf) {
@@ -814,7 +746,7 @@
 		memcpy(write_buf + inst->vsi->head_offset, buf, size);
 
 		ret = vdec_vframe_write(vdec, write_buf,
-			inst->vsi->head_offset + size, ts);
+			inst->vsi->head_offset + size, ts, 0);
 
 		memset(inst->vsi->header_buf, 0, HEADER_BUFFER_SIZE);
 		inst->vsi->head_offset = 0;
@@ -862,9 +794,7 @@
 		inst->vsi->cur_pic.coded_height !=
 		inst->vsi->pic.coded_height) ||
 		(inst->vsi->pic.profile_idc !=
-		inst->vsi->cur_pic.profile_idc) ||
-		(inst->vsi->pic.ref_frame_count !=
-		inst->vsi->cur_pic.ref_frame_count))) {
+		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;
@@ -878,16 +808,13 @@
 {
 	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
 	struct aml_vdec_adapt *vdec = &inst->vdec;
-	u8 *buf;
-	u32 size;
+	u8 *buf = (u8 *) bs->vaddr;
+	u32 size = bs->size;
 	int ret = -1;
 
 	if (bs == NULL)
 		return -1;
 
-	buf = (u8 *) bs->vaddr;
-	size = bs->size;
-
 	if (vdec_input_full(vdec))
 		return -EAGAIN;
 
@@ -909,7 +836,8 @@
 			ret = vdec_vframe_write(vdec,
 				s->data,
 				s->len,
-				bs->timestamp);
+				bs->timestamp,
+				0);
 		} else if (bs->model == VB2_MEMORY_DMABUF ||
 			bs->model == VB2_MEMORY_USERPTR) {
 			ret = vdec_vframe_write_with_dma(vdec,
@@ -961,20 +889,12 @@
 	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the h264 inst of dec is invalid.\n");
 		return -1;
 	}
 
 	switch (type) {
-	case GET_PARAM_DISP_FRAME_BUFFER:
-		vdec_h264_get_vf(inst, out);
-		break;
-
-	case GET_PARAM_FREE_FRAME_BUFFER:
-		ret = vdec_h264_get_fb(inst, out);
-		break;
-
 	case GET_PARAM_PIC_INFO:
 		get_pic_info(inst, out);
 		break;
@@ -990,6 +910,14 @@
 	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);
@@ -1028,8 +956,10 @@
 	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->ref_frame_count	= ps->ref_frames;
 	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;
@@ -1042,10 +972,9 @@
 	complete(&inst->comp);
 
 	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
-		"Parse from ucode, visible(%d x %d), coded(%d x %d) dpb: %d, scan: %s\n",
+		"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,
-		dec->dpb_sz,
 		ps->field == V4L2_FIELD_NONE ? "P" : "I");
 }
 
@@ -1065,6 +994,12 @@
 	}
 }
 
+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);
@@ -1079,7 +1014,7 @@
 	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the h264 inst of dec is invalid.\n");
 		return -1;
 	}
@@ -1100,6 +1035,11 @@
 	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);
diff --git a/drivers/amvdec_ports/decoder/vdec_hevc_if.c b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
index 2a41276..56d492a 100644
--- a/drivers/amvdec_ports/decoder/vdec_hevc_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
@@ -29,7 +29,6 @@
 #include "../aml_vcodec_drv.h"
 #include "../aml_vcodec_adapt.h"
 #include "../vdec_drv_base.h"
-#include "../aml_vcodec_vfm.h"
 #include "aml_hevc_parser.h"
 
 #define HEVC_NAL_TYPE(value)				((value >> 1) & 0x3F)
@@ -112,9 +111,9 @@
 	struct aml_vcodec_ctx *ctx;
 	struct aml_vdec_adapt vdec;
 	struct vdec_hevc_vsi *vsi;
-	struct vcodec_vfm_s vfm;
 	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,
@@ -155,7 +154,7 @@
 
 	pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
 	pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
-	pbuf += sprintf(pbuf, "hevc_double_write_mode:16;");
+	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;");
@@ -187,9 +186,13 @@
 			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.double_write_mode = 1;
 		ctx->config.parm.dec.cfg.ref_buf_margin = 7;
 		ctx->config.length = vdec_config_default_parms(ctx->config.buf);
 	}
@@ -203,14 +206,13 @@
 {
 	struct vdec_hevc_inst *inst = NULL;
 	int ret = -1;
-	bool dec_init = false;
 
 	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
 	if (!inst)
 		return -ENOMEM;
 
+	inst->vdec.frm_name	= "H.265";
 	inst->vdec.video_type	= VFORMAT_HEVC;
-	inst->vdec.dev		= ctx->dev->vpu_plat_dev;
 	inst->vdec.filp		= ctx->dev->filp;
 	inst->vdec.ctx		= ctx;
 	inst->ctx		= ctx;
@@ -224,24 +226,6 @@
 	/* to eable hevc hw.*/
 	inst->vdec.port.type = PORT_TYPE_HEVC;
 
-	/* init vfm */
-	inst->vfm.ctx		= ctx;
-	inst->vfm.ada_ctx	= &inst->vdec;
-	ret = vcodec_vfm_init(&inst->vfm);
-	if (ret) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"init vfm failed.\n");
-		goto err;
-	}
-
-	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;
-	}
-	dec_init = true;
-
 	/* probe info from the stream */
 	inst->vsi = kzalloc(sizeof(struct vdec_hevc_vsi), GFP_KERNEL);
 	if (!inst->vsi) {
@@ -250,7 +234,7 @@
 	}
 
 	/* alloc the header buffer to be used cache sps or spp etc.*/
-	inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
+	inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
 	if (!inst->vsi->header_buf) {
 		ret = -ENOMEM;
 		goto err;
@@ -258,22 +242,23 @@
 
 	init_completion(&inst->comp);
 
-	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
-		"hevc Instance >> %lx\n", (ulong) inst);
-
 	ctx->ada_ctx	= &inst->vdec;
 	*h_vdec		= (unsigned long)inst;
 
-	//dump_init();
+	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 (dec_init)
-		video_decoder_release(&inst->vdec);
-	if (inst)
-		vcodec_vfm_release(&inst->vfm);
 	if (inst && inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 	if (inst && inst->vsi)
 		kfree(inst->vsi);
 	if (inst)
@@ -317,8 +302,8 @@
 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->parms.cfg.init_width;
-	int h = inst->parms.cfg.init_height;
+	int w = inst->vsi->pic.coded_width;
+	int h = inst->vsi->pic.coded_height;
 	u32 dw = 0x1; /*1:1*/
 
 	switch (valid_dw_mode) {
@@ -421,7 +406,7 @@
 	int ret = 0;
 	struct aml_vdec_adapt *vdec = &inst->vdec;
 
-	ret = vdec_vframe_write(vdec, buf, size, timestamp);
+	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);
@@ -432,7 +417,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_ucode_dma(struct vdec_hevc_inst *inst,
@@ -453,7 +438,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_cpu(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
@@ -526,19 +511,13 @@
 
 static void vdec_hevc_deinit(unsigned long h_vdec)
 {
-	ulong flags;
 	struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
 	struct aml_vcodec_ctx *ctx = inst->ctx;
 
 	video_decoder_release(&inst->vdec);
 
-	vcodec_vfm_release(&inst->vfm);
-
-	//dump_deinit();
-
-	spin_lock_irqsave(&ctx->slock, flags);
 	if (inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 
 	if (inst->vsi)
 		kfree(inst->vsi);
@@ -546,49 +525,6 @@
 	kfree(inst);
 
 	ctx->drv_handle = 0;
-	spin_unlock_irqrestore(&ctx->slock, flags);
-}
-
-static int vdec_hevc_get_fb(struct vdec_hevc_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	return get_fb_from_queue(inst->ctx, out);
-}
-
-static void vdec_hevc_get_vf(struct vdec_hevc_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	struct vframe_s *vf = NULL;
-	struct vdec_v4l2_buffer *fb = NULL;
-
-	vf = peek_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"there is no vframe.\n");
-		*out = NULL;
-		return;
-	}
-
-	vf = get_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"the vframe is avalid.\n");
-		*out = NULL;
-		return;
-	}
-
-	atomic_set(&vf->use_cnt, 1);
-
-	fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
-	fb->vf_handle = (unsigned long)vf;
-	fb->status = FB_ST_DISPLAY;
-
-	*out = fb;
-
-	//pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
-	//dump_write(fb->base_y.vaddr, fb->base_y.bytes_used);
-	//dump_write(fb->base_c.vaddr, fb->base_c.bytes_used);
-
-	/* convert yuv format. */
-	//swap_uv(fb->base_c.vaddr, fb->base_c.size);
 }
 
 static int vdec_write_nalu(struct vdec_hevc_inst *inst,
@@ -597,7 +533,7 @@
 	int ret = 0;
 	struct aml_vdec_adapt *vdec = &inst->vdec;
 
-	ret = vdec_vframe_write(vdec, buf, size, ts);
+	ret = vdec_vframe_write(vdec, buf, size, ts, 0);
 
 	return ret;
 }
@@ -644,16 +580,13 @@
 {
 	struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
 	struct aml_vdec_adapt *vdec = &inst->vdec;
-	u8 *buf;
-	u32 size;
+	u8 *buf = (u8 *) bs->vaddr;
+	u32 size = bs->size;
 	int ret = -1;
 
 	if (bs == NULL)
 		return -1;
 
-	buf = (u8 *) bs->vaddr;
-	size = bs->size;
-
 	if (vdec_input_full(vdec))
 		return -EAGAIN;
 
@@ -675,7 +608,8 @@
 			ret = vdec_vframe_write(vdec,
 				s->data,
 				s->len,
-				bs->timestamp);
+				bs->timestamp,
+				0);
 		} else if (bs->model == VB2_MEMORY_DMABUF ||
 			bs->model == VB2_MEMORY_USERPTR) {
 			ret = vdec_vframe_write_with_dma(vdec,
@@ -713,6 +647,12 @@
 		"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)
 {
@@ -720,20 +660,12 @@
 	struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the hevc inst of dec is invalid.\n");
 		return -1;
 	}
 
 	switch (type) {
-	case GET_PARAM_DISP_FRAME_BUFFER:
-		vdec_hevc_get_vf(inst, out);
-		break;
-
-	case GET_PARAM_FREE_FRAME_BUFFER:
-		ret = vdec_hevc_get_fb(inst, out);
-		break;
-
 	case GET_PARAM_PIC_INFO:
 		get_pic_info(inst, out);
 		break;
@@ -749,6 +681,21 @@
 	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);
@@ -769,6 +716,7 @@
 	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;
@@ -784,9 +732,14 @@
 
 	pic->coded_width 	= ps->coded_width;
 	pic->coded_height 	= ps->coded_height;
-	pic->y_len_sz		= pic->coded_width * pic->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;
 
@@ -798,13 +751,27 @@
 	complete(&inst->comp);
 
 	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
-		"Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d, scan: %s\n",
+		"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,
-		dec->dpb_sz,
 		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)
 {
@@ -827,6 +794,12 @@
 		"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)
 {
@@ -834,7 +807,7 @@
 	struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the hevc inst of dec is invalid.\n");
 		return -1;
 	}
@@ -844,10 +817,18 @@
 		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;
@@ -855,6 +836,10 @@
 	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);
diff --git a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
index f9816cc..8332956 100644
--- a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
@@ -28,7 +28,6 @@
 #include "../aml_vcodec_dec.h"
 #include "../aml_vcodec_adapt.h"
 #include "../vdec_drv_base.h"
-#include "../aml_vcodec_vfm.h"
 #include "aml_mjpeg_parser.h"
 #include <media/v4l2-mem2mem.h>
 
@@ -112,7 +111,6 @@
 	struct aml_vcodec_ctx *ctx;
 	struct aml_vdec_adapt vdec;
 	struct vdec_mjpeg_vsi *vsi;
-	struct vcodec_vfm_s vfm;
 	struct aml_dec_params parms;
 	struct completion comp;
 };
@@ -158,6 +156,7 @@
 	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;
 }
@@ -177,6 +176,8 @@
 			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);
@@ -192,14 +193,13 @@
 {
 	struct vdec_mjpeg_inst *inst = NULL;
 	int ret = -1;
-	bool dec_init = false;
 
 	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
 	if (!inst)
 		return -ENOMEM;
 
+	inst->vdec.frm_name	= "MJPEG";
 	inst->vdec.video_type	= VFORMAT_MJPEG;
-	inst->vdec.dev		= ctx->dev->vpu_plat_dev;
 	inst->vdec.filp		= ctx->dev->filp;
 	inst->vdec.config	= ctx->config;
 	inst->vdec.ctx		= ctx;
@@ -213,24 +213,6 @@
 	/* to eable mjpeg hw.*/
 	inst->vdec.port.type = PORT_TYPE_VIDEO;
 
-	/* init vfm */
-	inst->vfm.ctx	= ctx;
-	inst->vfm.ada_ctx = &inst->vdec;
-	ret = vcodec_vfm_init(&inst->vfm);
-	if (ret) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"init vfm failed.\n");
-		goto err;
-	}
-
-	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;
-	}
-	dec_init = true;
-
 	/* probe info from the stream */
 	inst->vsi = kzalloc(sizeof(struct vdec_mjpeg_vsi), GFP_KERNEL);
 	if (!inst->vsi) {
@@ -239,30 +221,31 @@
 	}
 
 	/* alloc the header buffer to be used cache sps or spp etc.*/
-	inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
+	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);
 
-	init_completion(&inst->comp);
-	ctx->ada_ctx	= &inst->vdec;
-	*h_vdec		= (unsigned long)inst;
-
-	//dump_init();
-
 	return 0;
 
 err:
-	if (dec_init)
-		video_decoder_release(&inst->vdec);
-	if (inst)
-		vcodec_vfm_release(&inst->vfm);
 	if (inst && inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 	if (inst && inst->vsi)
 		kfree(inst->vsi);
 	if (inst)
@@ -308,9 +291,9 @@
 	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",
+		"The stream infos, coded:(%d x %d), visible:(%d x %d)\n",
 		pic->coded_width, pic->coded_height,
-		pic->visible_width, pic->visible_height, dec->dpb_sz);
+		pic->visible_width, pic->visible_height);
 }
 
 static int parse_stream_ucode(struct vdec_mjpeg_inst *inst,
@@ -319,7 +302,7 @@
 	int ret = 0;
 	struct aml_vdec_adapt *vdec = &inst->vdec;
 
-	ret = vdec_vframe_write(vdec, buf, size, timestamp);
+	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);
@@ -330,7 +313,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_ucode_dma(struct vdec_mjpeg_inst *inst,
@@ -351,7 +334,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_cpu(struct vdec_mjpeg_inst *inst, u8 *buf, u32 size)
@@ -431,12 +414,8 @@
 
 	video_decoder_release(&inst->vdec);
 
-	vcodec_vfm_release(&inst->vfm);
-
-	//dump_deinit();
-
 	if (inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 
 	if (inst->vsi)
 		kfree(inst->vsi);
@@ -444,55 +423,13 @@
 	kfree(inst);
 }
 
-static int vdec_mjpeg_get_fb(struct vdec_mjpeg_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	return get_fb_from_queue(inst->ctx, out);
-}
-
-static void vdec_mjpeg_get_vf(struct vdec_mjpeg_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	struct vframe_s *vf = NULL;
-	struct vdec_v4l2_buffer *fb = NULL;
-
-	vf = peek_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"there is no vframe.\n");
-		*out = NULL;
-		return;
-	}
-
-	vf = get_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"the vframe is avalid.\n");
-		*out = NULL;
-		return;
-	}
-
-	atomic_set(&vf->use_cnt, 1);
-
-	fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
-	fb->vf_handle = (unsigned long)vf;
-	fb->status = FB_ST_DISPLAY;
-
-	*out = fb;
-
-	//pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
-	//dump_write(fb->base_y.va, fb->base_y.bytes_used);
-	//dump_write(fb->base_c.va, fb->base_c.bytes_used);
-
-	/* convert yuv format. */
-	//swap_uv(fb->base_c.va, fb->base_c.size);
-}
-
 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);
+	ret = vdec_vframe_write(vdec, buf, size, ts, 0);
 
 	return ret;
 }
@@ -520,7 +457,8 @@
 			ret = vdec_vframe_write(vdec,
 				s->data,
 				s->len,
-				bs->timestamp);
+				bs->timestamp,
+				0);
 		} else if (bs->model == VB2_MEMORY_DMABUF ||
 			bs->model == VB2_MEMORY_USERPTR) {
 			ret = vdec_vframe_write_with_dma(vdec,
@@ -542,20 +480,12 @@
 	struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the mjpeg inst of dec is invalid.\n");
 		return -1;
 	}
 
 	switch (type) {
-	case GET_PARAM_DISP_FRAME_BUFFER:
-		vdec_mjpeg_get_vf(inst, out);
-		break;
-
-	case GET_PARAM_FREE_FRAME_BUFFER:
-		ret = vdec_mjpeg_get_fb(inst, out);
-		break;
-
 	case GET_PARAM_PIC_INFO:
 		get_pic_info(inst, out);
 		break;
@@ -568,6 +498,13 @@
 		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);
@@ -599,9 +536,13 @@
 	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;
+	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 |=
@@ -611,10 +552,10 @@
 	complete(&inst->comp);
 
 	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
-		"Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n",
+		"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,
-		dec->dpb_sz);
+		pic->field == V4L2_FIELD_NONE ? "P" : "I");
 }
 
 static void set_param_write_sync(struct vdec_mjpeg_inst *inst)
@@ -622,6 +563,12 @@
 	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)
 {
@@ -629,7 +576,7 @@
 	struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the mjpeg inst of dec is invalid.\n");
 		return -1;
 	}
@@ -638,10 +585,15 @@
 	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);
diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
index 9a38e71..2472ac1 100644
--- a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
@@ -28,7 +28,6 @@
 #include "../aml_vcodec_dec.h"
 #include "../aml_vcodec_adapt.h"
 #include "../vdec_drv_base.h"
-#include "../aml_vcodec_vfm.h"
 #include "aml_mpeg12_parser.h"
 
 #define NAL_TYPE(value)				((value) & 0x1F)
@@ -111,7 +110,6 @@
 	struct aml_vcodec_ctx *ctx;
 	struct aml_vdec_adapt vdec;
 	struct vdec_mpeg12_vsi *vsi;
-	struct vcodec_vfm_s vfm;
 	struct aml_dec_params parms;
 	struct completion comp;
 };
@@ -173,6 +171,10 @@
 			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);
@@ -187,14 +189,13 @@
 {
 	struct vdec_mpeg12_inst *inst = NULL;
 	int ret = -1;
-	bool dec_init = false;
 
 	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
 	if (!inst)
 		return -ENOMEM;
 
+	inst->vdec.frm_name	= "MPEG2";
 	inst->vdec.video_type	= VFORMAT_MPEG12;
-	inst->vdec.dev		= ctx->dev->vpu_plat_dev;
 	inst->vdec.filp		= ctx->dev->filp;
 	inst->vdec.config	= ctx->config;
 	inst->vdec.ctx		= ctx;
@@ -209,24 +210,6 @@
 	/* to eable mpeg12 hw.*/
 	inst->vdec.port.type = PORT_TYPE_VIDEO;
 
-	/* init vfm */
-	inst->vfm.ctx		= ctx;
-	inst->vfm.ada_ctx	= &inst->vdec;
-	ret = vcodec_vfm_init(&inst->vfm);
-	if (ret) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"init vfm failed.\n");
-		goto err;
-	}
-
-	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;
-	}
-	dec_init = true;
-
 	/* probe info from the stream */
 	inst->vsi = kzalloc(sizeof(struct vdec_mpeg12_vsi), GFP_KERNEL);
 	if (!inst->vsi) {
@@ -235,29 +218,31 @@
 	}
 
 	/* alloc the header buffer to be used cache sps or spp etc.*/
-	inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
+	inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
 	if (!inst->vsi->header_buf) {
 		ret = -ENOMEM;
 		goto err;
 	}
 
-	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
-		"mpeg12 Instance >> %lx\n", (ulong) inst);
 	init_completion(&inst->comp);
 	ctx->ada_ctx	= &inst->vdec;
 	*h_vdec		= (unsigned long)inst;
 
-	//dump_init();
+	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 (dec_init)
-		video_decoder_release(&inst->vdec);
-	if (inst)
-		vcodec_vfm_release(&inst->vfm);
 	if (inst && inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 	if (inst && inst->vsi)
 		kfree(inst->vsi);
 	if (inst)
@@ -306,7 +291,7 @@
 	int ret = 0;
 	struct aml_vdec_adapt *vdec = &inst->vdec;
 
-	ret = vdec_vframe_write(vdec, buf, size, timestamp);
+	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);
@@ -317,7 +302,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_ucode_dma(struct vdec_mpeg12_inst *inst,
@@ -338,7 +323,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_cpu(struct vdec_mpeg12_inst *inst, u8 *buf, u32 size)
@@ -418,12 +403,8 @@
 
 	video_decoder_release(&inst->vdec);
 
-	vcodec_vfm_release(&inst->vfm);
-
-	//dump_deinit();
-
 	if (inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 
 	if (inst->vsi)
 		kfree(inst->vsi);
@@ -431,55 +412,13 @@
 	kfree(inst);
 }
 
-static int vdec_mpeg12_get_fb(struct vdec_mpeg12_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	return get_fb_from_queue(inst->ctx, out);
-}
-
-static void vdec_mpeg12_get_vf(struct vdec_mpeg12_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	struct vframe_s *vf = NULL;
-	struct vdec_v4l2_buffer *fb = NULL;
-
-	vf = peek_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"there is no vframe.\n");
-		*out = NULL;
-		return;
-	}
-
-	vf = get_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"the vframe is avalid.\n");
-		*out = NULL;
-		return;
-	}
-
-	atomic_set(&vf->use_cnt, 1);
-
-	fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
-	fb->vf_handle = (unsigned long)vf;
-	fb->status = FB_ST_DISPLAY;
-
-	*out = fb;
-
-	//pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
-	//dump_write(fb->base_y.va, fb->base_y.bytes_used);
-	//dump_write(fb->base_c.va, fb->base_c.bytes_used);
-
-	/* convert yuv format. */
-	//swap_uv(fb->base_c.va, fb->base_c.size);
-}
-
 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);
+	ret = vdec_vframe_write(vdec, buf, size, ts, 0);
 
 	return ret;
 }
@@ -507,7 +446,8 @@
 			ret = vdec_vframe_write(vdec,
 				s->data,
 				s->len,
-				bs->timestamp);
+				bs->timestamp,
+				0);
 		} else if (bs->model == VB2_MEMORY_DMABUF ||
 			bs->model == VB2_MEMORY_USERPTR) {
 			ret = vdec_vframe_write_with_dma(vdec,
@@ -522,6 +462,19 @@
 	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)
 {
@@ -529,20 +482,12 @@
 	struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the mpeg12 inst of dec is invalid.\n");
 		return -1;
 	}
 
 	switch (type) {
-	case GET_PARAM_DISP_FRAME_BUFFER:
-		vdec_mpeg12_get_vf(inst, out);
-		break;
-
-	case GET_PARAM_FREE_FRAME_BUFFER:
-		ret = vdec_mpeg12_get_fb(inst, out);
-		break;
-
 	case GET_PARAM_PIC_INFO:
 		get_pic_info(inst, out);
 		break;
@@ -555,6 +500,17 @@
 		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);
@@ -569,6 +525,12 @@
 	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)
 {
@@ -592,6 +554,9 @@
 	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;
 
@@ -603,13 +568,28 @@
 	complete(&inst->comp);
 
 	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
-		"Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d scan: %s\n",
+		"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,
-		dec->dpb_sz,
 		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)
 {
@@ -617,7 +597,7 @@
 	struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the mpeg12 inst of dec is invalid.\n");
 		return -1;
 	}
@@ -626,10 +606,19 @@
 	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);
diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
index c47bafc..bc0af24 100644
--- a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
@@ -28,7 +28,6 @@
 #include "../aml_vcodec_dec.h"
 #include "../aml_vcodec_adapt.h"
 #include "../vdec_drv_base.h"
-#include "../aml_vcodec_vfm.h"
 #include "aml_mpeg4_parser.h"
 
 #define NAL_TYPE(value)				((value) & 0x1F)
@@ -111,7 +110,6 @@
 	struct aml_vcodec_ctx *ctx;
 	struct aml_vdec_adapt vdec;
 	struct vdec_mpeg4_vsi *vsi;
-	struct vcodec_vfm_s vfm;
 	struct aml_dec_params parms;
 	struct completion comp;
 };
@@ -173,6 +171,8 @@
 			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);
@@ -188,15 +188,14 @@
 {
 	struct vdec_mpeg4_inst *inst = NULL;
 	int ret = -1;
-	bool dec_init = false;
 
 	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.dev		= ctx->dev->vpu_plat_dev;
 	inst->vdec.filp		= ctx->dev->filp;
 	inst->vdec.config	= ctx->config;
 	inst->vdec.ctx		= ctx;
@@ -210,24 +209,6 @@
 	/* to eable mpeg4 hw.*/
 	inst->vdec.port.type	= PORT_TYPE_VIDEO;
 
-	/* init vfm */
-	inst->vfm.ctx		= ctx;
-	inst->vfm.ada_ctx	= &inst->vdec;
-	ret = vcodec_vfm_init(&inst->vfm);
-	if (ret) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"init vfm failed.\n");
-		goto err;
-	}
-	dec_init = true;
-
-	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;
-	}
-
 	/* probe info from the stream */
 	inst->vsi = kzalloc(sizeof(struct vdec_mpeg4_vsi), GFP_KERNEL);
 	if (!inst->vsi) {
@@ -236,30 +217,31 @@
 	}
 
 	/* alloc the header buffer to be used cache sps or spp etc.*/
-	inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
+	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);
 
-	init_completion(&inst->comp);
-	ctx->ada_ctx	= &inst->vdec;
-	*h_vdec		= (unsigned long)inst;
-
-	//dump_init();
-
 	return 0;
 
 err:
-	if (dec_init)
-		video_decoder_release(&inst->vdec);
-	if (inst)
-		vcodec_vfm_release(&inst->vfm);
 	if (inst && inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 	if (inst && inst->vsi)
 		kfree(inst->vsi);
 	if (inst)
@@ -316,7 +298,7 @@
 	int ret = 0;
 	struct aml_vdec_adapt *vdec = &inst->vdec;
 
-	ret = vdec_vframe_write(vdec, buf, size, timestamp);
+	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);
@@ -327,7 +309,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_ucode_dma(struct vdec_mpeg4_inst *inst,
@@ -348,7 +330,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_cpu(struct vdec_mpeg4_inst *inst, u8 *buf, u32 size)
@@ -428,12 +410,8 @@
 
 	video_decoder_release(&inst->vdec);
 
-	vcodec_vfm_release(&inst->vfm);
-
-	//dump_deinit();
-
 	if (inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 
 	if (inst->vsi)
 		kfree(inst->vsi);
@@ -441,55 +419,13 @@
 	kfree(inst);
 }
 
-static int vdec_mpeg4_get_fb(struct vdec_mpeg4_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	return get_fb_from_queue(inst->ctx, out);
-}
-
-static void vdec_mpeg4_get_vf(struct vdec_mpeg4_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	struct vframe_s *vf = NULL;
-	struct vdec_v4l2_buffer *fb = NULL;
-
-	vf = peek_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"there is no vframe.\n");
-		*out = NULL;
-		return;
-	}
-
-	vf = get_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"the vframe is avalid.\n");
-		*out = NULL;
-		return;
-	}
-
-	atomic_set(&vf->use_cnt, 1);
-
-	fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
-	fb->vf_handle = (unsigned long)vf;
-	fb->status = FB_ST_DISPLAY;
-
-	*out = fb;
-
-	//pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
-	//dump_write(fb->base_y.va, fb->base_y.bytes_used);
-	//dump_write(fb->base_c.va, fb->base_c.bytes_used);
-
-	/* convert yuv format. */
-	//swap_uv(fb->base_c.va, fb->base_c.size);
-}
-
 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);
+	ret = vdec_vframe_write(vdec, buf, size, ts, 0);
 
 	return ret;
 }
@@ -517,7 +453,8 @@
 			ret = vdec_vframe_write(vdec,
 				s->data,
 				s->len,
-				bs->timestamp);
+				bs->timestamp,
+				0);
 		} else if (bs->model == VB2_MEMORY_DMABUF ||
 			bs->model == VB2_MEMORY_USERPTR) {
 			ret = vdec_vframe_write_with_dma(vdec,
@@ -539,20 +476,12 @@
 	struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the mpeg4 inst of dec is invalid.\n");
 		return -1;
 	}
 
 	switch (type) {
-	case GET_PARAM_DISP_FRAME_BUFFER:
-		vdec_mpeg4_get_vf(inst, out);
-		break;
-
-	case GET_PARAM_FREE_FRAME_BUFFER:
-		ret = vdec_mpeg4_get_fb(inst, out);
-		break;
-
 	case GET_PARAM_PIC_INFO:
 		get_pic_info(inst, out);
 		break;
@@ -564,6 +493,12 @@
 	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,
@@ -598,6 +533,9 @@
 	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;
 
@@ -609,10 +547,9 @@
 	complete(&inst->comp);
 
 	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
-		"Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d, scan:%s\n",
+		"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,
-		dec->dpb_sz,
 		pic->field == V4L2_FIELD_NONE ? "P" : "I");
 }
 
@@ -621,6 +558,12 @@
 	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)
 {
@@ -628,7 +571,7 @@
 	struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the mpeg4 inst of dec is invalid.\n");
 		return -1;
 	}
@@ -637,10 +580,15 @@
 	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);
diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_if.c b/drivers/amvdec_ports/decoder/vdec_vp9_if.c
index 6704350..fe81ddd 100644
--- a/drivers/amvdec_ports/decoder/vdec_vp9_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_vp9_if.c
@@ -29,7 +29,6 @@
 #include "../aml_vcodec_drv.h"
 #include "../aml_vcodec_adapt.h"
 #include "../vdec_drv_base.h"
-#include "../aml_vcodec_vfm.h"
 #include "aml_vp9_parser.h"
 #include "vdec_vp9_trigger.h"
 
@@ -123,13 +122,13 @@
 	struct aml_vcodec_ctx *ctx;
 	struct aml_vdec_adapt vdec;
 	struct vdec_vp9_vsi *vsi;
-	struct vcodec_vfm_s vfm;
 	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);
+	u8 *buf, u32 size, u64 ts, ulong meta_ptr);
 
 static void get_pic_info(struct vdec_vp9_inst *inst,
 			 struct vdec_pic_info *pic)
@@ -170,7 +169,7 @@
 
 	pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
 	pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
-	pbuf += sprintf(pbuf, "vp9_double_write_mode:16;");
+	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;");
@@ -187,6 +186,10 @@
 {
 	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;
@@ -208,9 +211,11 @@
 			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 = 16;
+		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);
 	}
@@ -221,6 +226,8 @@
 		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;",
@@ -249,6 +256,8 @@
 		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;
@@ -264,8 +273,8 @@
 	if (!inst)
 		return -ENOMEM;
 
+	inst->vdec.frm_name	= "VP9";
 	inst->vdec.video_type	= VFORMAT_VP9;
-	inst->vdec.dev		= ctx->dev->vpu_plat_dev;
 	inst->vdec.filp		= ctx->dev->filp;
 	inst->vdec.ctx		= ctx;
 	inst->ctx		= ctx;
@@ -279,16 +288,6 @@
 	/* to eable vp9 hw.*/
 	inst->vdec.port.type	= PORT_TYPE_HEVC;
 
-	/* init vfm */
-	inst->vfm.ctx		= ctx;
-	inst->vfm.ada_ctx	= &inst->vdec;
-	ret = vcodec_vfm_init(&inst->vfm);
-	if (ret) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"init vfm failed.\n");
-		goto err;
-	}
-
 	/* probe info from the stream */
 	inst->vsi = kzalloc(sizeof(struct vdec_vp9_vsi), GFP_KERNEL);
 	if (!inst->vsi) {
@@ -297,7 +296,7 @@
 	}
 
 	/* alloc the header buffer to be used cache sps or spp etc.*/
-	inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
+	inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
 	if (!inst->vsi->header_buf) {
 		ret = -ENOMEM;
 		goto err;
@@ -319,14 +318,10 @@
 		goto err;
 	}
 
-	//dump_init();
-
 	return 0;
 err:
-	if (inst)
-		vcodec_vfm_release(&inst->vfm);
 	if (inst && inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 	if (inst && inst->vsi)
 		kfree(inst->vsi);
 	if (inst)
@@ -347,8 +342,8 @@
 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->parms.cfg.init_width;
-	int h = inst->parms.cfg.init_height;
+	int w = inst->vsi->pic.coded_width;
+	int h = inst->vsi->pic.coded_height;
 	u32 dw = 0x1; /*1:1*/
 
 	switch (valid_dw_mode) {
@@ -443,11 +438,11 @@
 }
 
 static int parse_stream_ucode(struct vdec_vp9_inst *inst,
-			      u8 *buf, u32 size, u64 timestamp)
+			      u8 *buf, u32 size, u64 timestamp, ulong meta_ptr)
 {
 	int ret = 0;
 
-	ret = vdec_write_nalu(inst, buf, size, timestamp);
+	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);
@@ -458,7 +453,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_ucode_dma(struct vdec_vp9_inst *inst,
@@ -479,7 +474,7 @@
 	wait_for_completion_timeout(&inst->comp,
 		msecs_to_jiffies(1000));
 
-	return inst->vsi->dec.dpb_sz ? 0 : -1;
+	return inst->vsi->pic.dpb_frames ? 0 : -1;
 }
 
 static int parse_stream_cpu(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
@@ -528,7 +523,7 @@
 
 			if (inst->ctx->param_sets_from_ucode) {
 				ret = parse_stream_ucode(inst, s->data,
-					s->len, bs->timestamp);
+					s->len, bs->timestamp, 0);
 			} else {
 				ret = parse_stream_cpu(inst, s->data, s->len);
 			}
@@ -539,7 +534,7 @@
 		}
 	} else {
 		if (inst->ctx->param_sets_from_ucode) {
-			ret = parse_stream_ucode(inst, buf, size, bs->timestamp);
+			ret = parse_stream_ucode(inst, buf, size, bs->timestamp, bs->meta_ptr);
 		} else {
 			ret = parse_stream_cpu(inst, buf, size);
 		}
@@ -552,19 +547,13 @@
 
 static void vdec_vp9_deinit(unsigned long h_vdec)
 {
-	ulong flags;
 	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
 	struct aml_vcodec_ctx *ctx = inst->ctx;
 
 	video_decoder_release(&inst->vdec);
 
-	vcodec_vfm_release(&inst->vfm);
-
-	//dump_deinit();
-
-	spin_lock_irqsave(&ctx->slock, flags);
 	if (inst->vsi && inst->vsi->header_buf)
-		kfree(inst->vsi->header_buf);
+		vfree(inst->vsi->header_buf);
 
 	if (inst->vsi)
 		kfree(inst->vsi);
@@ -572,54 +561,11 @@
 	kfree(inst);
 
 	ctx->drv_handle = 0;
-	spin_unlock_irqrestore(&ctx->slock, flags);
 
 	need_trigger = false;
 	dump_cnt = 0;
 }
 
-static int vdec_vp9_get_fb(struct vdec_vp9_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	return get_fb_from_queue(inst->ctx, out);
-}
-
-static void vdec_vp9_get_vf(struct vdec_vp9_inst *inst, struct vdec_v4l2_buffer **out)
-{
-	struct vframe_s *vf = NULL;
-	struct vdec_v4l2_buffer *fb = NULL;
-
-	vf = peek_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"there is no vframe.\n");
-		*out = NULL;
-		return;
-	}
-
-	vf = get_video_frame(&inst->vfm);
-	if (!vf) {
-		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
-			"the vframe is avalid.\n");
-		*out = NULL;
-		return;
-	}
-
-	atomic_set(&vf->use_cnt, 1);
-
-	fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
-	fb->vf_handle = (unsigned long)vf;
-	fb->status = FB_ST_DISPLAY;
-
-	*out = fb;
-
-	//pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
-	//dump_write(fb->base_y.vaddr, fb->base_y.bytes_used);
-	//dump_write(fb->base_c.vaddr, fb->base_c.bytes_used);
-
-	/* convert yuv format. */
-	//swap_uv(fb->base_c.vaddr, fb->base_c.size);
-}
-
 static void add_prefix_data(struct vp9_superframe_split *s,
 	u8 **out, u32 *out_size)
 {
@@ -770,7 +716,7 @@
 	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);
+			frame_size, 0, 0);
 		v4l_dbg(vdec->ctx, V4L_DEBUG_CODEC_ERROR,
 			"write trigger frame %d\n", ret);
 		p += frame_size;
@@ -778,7 +724,7 @@
 }
 
 static int vdec_write_nalu(struct vdec_vp9_inst *inst,
-	u8 *buf, u32 size, u64 ts)
+	u8 *buf, u32 size, u64 ts, ulong meta_ptr)
 {
 	int ret = 0;
 	struct aml_vdec_adapt *vdec = &inst->vdec;
@@ -808,10 +754,10 @@
 
 		/*add headers.*/
 		add_prefix_data(&s, &data, &length);
-		ret = vdec_vframe_write(vdec, data, length, ts);
+		ret = vdec_vframe_write(vdec, data, length, ts, 0);
 		vfree(data);
 	} else {
-		ret = vdec_vframe_write(vdec, buf, size, ts);
+		ret = vdec_vframe_write(vdec, buf, size, ts, meta_ptr);
 	}
 
 	return ret;
@@ -845,18 +791,14 @@
 {
 	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
 	struct aml_vdec_adapt *vdec = &inst->vdec;
-	u8 *buf;
-	u32 size;
+	u8 *buf = (u8 *) bs->vaddr;
+	u32 size = bs->size;
 	int ret = -1;
 
 	if (bs == NULL)
 		return -1;
 
-	buf = (u8 *) bs->vaddr;
-	size = bs->size;
-
 	if (vdec_input_full(vdec)) {
-		ATRACE_COUNTER("vdec_input_full", 0);
 		return -EAGAIN;
 	}
 
@@ -878,7 +820,8 @@
 			ret = vdec_vframe_write(vdec,
 				s->data,
 				s->len,
-				bs->timestamp);
+				bs->timestamp,
+				0);
 		} else if (bs->model == VB2_MEMORY_DMABUF ||
 			bs->model == VB2_MEMORY_USERPTR) {
 			ret = vdec_vframe_write_with_dma(vdec,
@@ -891,10 +834,8 @@
 		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);
+		ret = vdec_write_nalu(inst, buf, size, bs->timestamp, bs->meta_ptr);
 	}
-	ATRACE_COUNTER("v4l2_decode_write", ret);
 
 	return ret;
 }
@@ -917,6 +858,12 @@
 		"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)
 {
@@ -924,20 +871,12 @@
 	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the vp9 inst of dec is invalid.\n");
 		return -1;
 	}
 
 	switch (type) {
-	case GET_PARAM_DISP_FRAME_BUFFER:
-		vdec_vp9_get_vf(inst, out);
-		break;
-
-	case GET_PARAM_FREE_FRAME_BUFFER:
-		ret = vdec_vp9_get_fb(inst, out);
-		break;
-
 	case GET_PARAM_PIC_INFO:
 		get_pic_info(inst, out);
 		break;
@@ -953,6 +892,21 @@
 	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);
@@ -973,6 +927,7 @@
 	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;
@@ -988,11 +943,16 @@
 	pic->coded_width	= ps->coded_width;
 	pic->coded_height	= ps->coded_height;
 
-	pic->y_len_sz		= pic->coded_width * pic->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 |=
@@ -1002,10 +962,15 @@
 	complete(&inst->comp);
 
 	v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
-		"Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n",
-		ps->visible_width, ps->visible_height,
-		ps->coded_width, ps->coded_height,
-		ps->dpb_size);
+		"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,
@@ -1030,6 +995,12 @@
 			"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)
 {
@@ -1037,7 +1008,7 @@
 	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
 
 	if (!inst) {
-		v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+		v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
 			"the vp9 inst of dec is invalid.\n");
 		return -1;
 	}
@@ -1051,6 +1022,10 @@
 		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;
@@ -1058,6 +1033,11 @@
 	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);
diff --git a/drivers/amvdec_ports/utils/common.c b/drivers/amvdec_ports/utils/common.c
index 1d621da..67cf93b 100644
--- a/drivers/amvdec_ports/utils/common.c
+++ b/drivers/amvdec_ports/utils/common.c
@@ -1,22 +1,3 @@
-/*
-* 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/vmalloc.h>
@@ -240,3 +221,12 @@
 	_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
index dd4c51f..89ae50b 100644
--- a/drivers/amvdec_ports/utils/common.h
+++ b/drivers/amvdec_ports/utils/common.h
@@ -1,22 +1,3 @@
-/*
-* 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 UTILS_COMMON_H
 #define UTILS_COMMON_H
 
@@ -77,7 +58,7 @@
 #ifndef CONFIG_AMLOGIC_MEDIA_V4L_SOFTWARE_PARSER
 /**
  * YUV colorspace type.
- * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.3.
+ * 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)
@@ -101,7 +82,7 @@
 
 /**
   * Chromaticity coordinates of the source primaries.
-  * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.1.
+  * These values match the ones defined by ISO/IEC 23001-8_2013 ¡ì 7.1.
   */
 enum AVColorPrimaries {
 	AVCOL_PRI_RESERVED0   = 0,
@@ -125,7 +106,7 @@
 
 /**
  * Color Transfer Characteristic.
- * These values match the ones defined by ISO/IEC 23001-8_2013 § 7.2.
+ * These values match the ones defined by ISO/IEC 23001-8_2013 ¡ì 7.2.
  */
 enum AVColorTransferCharacteristic {
 	AVCOL_TRC_RESERVED0    = 0,
@@ -151,8 +132,8 @@
 	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);
@@ -169,4 +150,6 @@
 //debug
 void print_hex_debug(u8 *data, u32 len, int max);
 
-#endif
+bool is_over_size(int w, int h, int size);
+
+#endif
\ No newline at end of file
diff --git a/drivers/amvdec_ports/vdec_drv_if.c b/drivers/amvdec_ports/vdec_drv_if.c
index ed9f053..01510c5 100644
--- a/drivers/amvdec_ports/vdec_drv_if.c
+++ b/drivers/amvdec_ports/vdec_drv_if.c
@@ -116,6 +116,19 @@
 	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)
diff --git a/drivers/amvdec_ports/vdec_drv_if.h b/drivers/amvdec_ports/vdec_drv_if.h
index a04d832..29911f8 100644
--- a/drivers/amvdec_ports/vdec_drv_if.h
+++ b/drivers/amvdec_ports/vdec_drv_if.h
@@ -50,33 +50,48 @@
 
 /**
  * struct vdec_fb_status  - decoder frame buffer status
- * @FB_ST_NORMAL	: initial state
- * @FB_ST_DISPLAY	: frmae buffer is ready to be displayed
+ * @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_NORMAL,
+	FB_ST_INIT,
+	FB_ST_DECODER,
+	FB_ST_VPP,
+	FB_ST_GE2D,
 	FB_ST_DISPLAY,
 	FB_ST_FREE
 };
 
-/* For GET_PARAM_DISP_FRAME_BUFFER and GET_PARAM_FREE_FRAME_BUFFER,
+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_DISP_FRAME_BUFFER	: get next displayable frame buffer,
- *				struct vdec_fb**
- * GET_PARAM_FREE_FRAME_BUFFER	: get non-referenced framebuffer, vdec_fb**
  * 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_DISP_FRAME_BUFFER,
-	GET_PARAM_FREE_FRAME_BUFFER,
 	GET_PARAM_PIC_INFO,
 	GET_PARAM_CROP_INFO,
 	GET_PARAM_DPB_SIZE,
-	GET_PARAM_CONFIG_INFO
+	GET_PARAM_CONFIG_INFO,
+	GET_PARAM_DW_MODE,
+	GET_PARAM_COMP_BUF_INFO
 };
 
 /*
@@ -85,8 +100,11 @@
 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_POST_EVENT,
+	SET_PARAM_PIC_INFO,
+	SET_PARAM_CFG_INFO
 };
 
 /**
@@ -138,7 +156,10 @@
  * @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_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/chips/chips.c b/drivers/common/chips/chips.c
index d692ca8..158e32c 100644
--- a/drivers/common/chips/chips.c
+++ b/drivers/common/chips/chips.c
@@ -25,7 +25,7 @@
 #include <linux/mm.h>
 
 #include <linux/amlogic/media/utils/vformat.h>
-#include <linux/amlogic/cpu_version.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"
@@ -78,6 +78,14 @@
 	{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},
 };
 
diff --git a/drivers/common/chips/decoder_cpu_ver_info.c b/drivers/common/chips/decoder_cpu_ver_info.c
index d74728c..af162b8 100644
--- a/drivers/common/chips/decoder_cpu_ver_info.c
+++ b/drivers/common/chips/decoder_cpu_ver_info.c
@@ -24,7 +24,7 @@
 #include <linux/errno.h>
 #include <linux/platform_device.h>
 #include <linux/of_device.h>
-#include <linux/amlogic/cpu_version.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"
@@ -32,6 +32,7 @@
 #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]=
 {
@@ -57,13 +58,22 @@
 	AM_MESON_CPU_MAJOR_ID_G12B,
 	AM_MESON_CPU_MAJOR_ID_GXLX2,
 	AM_MESON_CPU_MAJOR_ID_SM1,
-	AM_MESON_CPU_MAJOR_ID_RES_0x2c,
+	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_RES_0x30,
+	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[] = {
@@ -114,32 +124,90 @@
 		.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 bool get_cpu_id_from_dtb(enum AM_MESON_CPU_MAJOR_ID *pidType)
-{
-	struct device_node *pNode = NULL;
-	struct platform_device* pDev = NULL;
-	const struct of_device_id *pMatch = NULL;
+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,
+};
 
-	pNode = of_find_node_by_name(NULL, DECODE_CPU_VER_ID_NODE_NAME);
-	if (NULL == pNode) {
+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)
+	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) {
-		pr_err("No find of_match_device\n");
-		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;
+		}
 	}
 
-	*pidType = *(enum AM_MESON_CPU_MAJOR_ID *)pMatch->data;
+	*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;
 }
@@ -147,15 +215,20 @@
 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))
+	if (AM_SUCESS == get_cpu_id_from_dtb(&id_type, &sub_id)) {
 		cpu_ver_id = id_type;
-	else
+		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)
-		if (is_meson_rev_b())
-			cpu_ver_id = AM_MESON_CPU_MAJOR_ID_TL1;
+	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)
@@ -167,10 +240,32 @@
 }
 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_meson_rev_b()));
+	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
index 673b001..6129244 100644
--- a/drivers/common/chips/decoder_cpu_ver_info.h
+++ b/drivers/common/chips/decoder_cpu_ver_info.h
@@ -19,9 +19,11 @@
 */
 #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
-{
+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,
@@ -44,18 +46,50 @@
 	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_RES_0x2c,
+	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_RES_0x30,
+	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_RES_0x33,
-	AM_MESON_CPU_MAJOR_ID_T5,
+	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/firmware_drv.c b/drivers/common/firmware/firmware_drv.c
index 85a81e6..9422198 100644
--- a/drivers/common/firmware/firmware_drv.c
+++ b/drivers/common/firmware/firmware_drv.c
@@ -25,7 +25,7 @@
 #include <linux/slab.h>
 
 #include <linux/amlogic/media/utils/vformat.h>
-#include <linux/amlogic/cpu_version.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"
@@ -34,13 +34,14 @@
 #include <linux/amlogic/media/utils/log.h>
 #include <linux/firmware.h>
 #include <linux/amlogic/tee.h>
-#include <linux/amlogic/major.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.2"
+#define PACK_VERS "v0.3"
 
 #define CLASS_NAME	"firmware_codec"
 #define DEV_NAME	"firmware_vdec"
@@ -75,6 +76,7 @@
 
 struct fw_mgr_s *g_mgr;
 struct fw_dev_s *g_dev;
+struct package_head_s package_head;
 
 static u32 debug;
 static u32 detail;
@@ -85,7 +87,7 @@
 	struct fw_mgr_s *mgr = g_mgr;
 	struct fw_info_s *info;
 
-	pr_info("[%s], the fw (%s) will be loaded.\n",
+	pr_info("[%s], the fw (%s) will be loaded...\n",
 		tee_enabled() ? "TEE" : "LOCAL",
 		get_fw_format_name(format));
 
@@ -109,6 +111,7 @@
 
 		break;
 	}
+
 out:
 	mutex_unlock(&mutex);
 
@@ -341,6 +344,8 @@
 	struct fw_info_s *info;
 	unsigned int secs = 0;
 	struct tm tm;
+	char history_change_id[7] = {0};
+	int i;
 
 	mutex_lock(&mutex);
 
@@ -350,7 +355,21 @@
 	}
 
 	/* shows version of driver. */
-	pr_info("The driver version is %s\n", PACK_VERS);
+	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))
@@ -375,7 +394,8 @@
 
 		secs = info->data->head.time
 			- sys_tz.tz_minuteswest * 60;
-		time_to_tm(secs, 0, &tm);
+		//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,
@@ -577,6 +597,7 @@
 	if (ret != 2)
 		return -1;
 
+	package_head = pack->head;
 	major_fw = (pack->head.version >> 16) & 0xff;
 	minor_fw = pack->head.version & 0xff;
 
@@ -595,7 +616,7 @@
 	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\n", major_fw, minor_fw);
+		pr_info("The firmware ver is v%d.%d.%d\n", major_fw, minor_fw, pack->head.submit_count);
 	}
 
 	return 0;
@@ -910,6 +931,7 @@
 	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),
@@ -921,7 +943,26 @@
 	.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;
diff --git a/drivers/common/firmware/firmware_priv.h b/drivers/common/firmware/firmware_priv.h
index 410745b..d901f9d 100644
--- a/drivers/common/firmware/firmware_priv.h
+++ b/drivers/common/firmware/firmware_priv.h
@@ -85,7 +85,11 @@
 	int checksum;
 	int total;
 	int version;
-	char reserved[128];
+	int submit_count;
+	char change_id[16];
+	char commit[16];
+	char history_change_id[30];
+	char reserved[62];
 };
 
 struct package_s {
diff --git a/drivers/common/firmware/firmware_type.c b/drivers/common/firmware/firmware_type.c
index c232020..8d95c12 100644
--- a/drivers/common/firmware/firmware_type.c
+++ b/drivers/common/firmware/firmware_type.c
@@ -76,6 +76,13 @@
 	{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)
diff --git a/drivers/common/firmware/firmware_type.h b/drivers/common/firmware/firmware_type.h
index e997057..4615baf 100644
--- a/drivers/common/firmware/firmware_type.h
+++ b/drivers/common/firmware/firmware_type.h
@@ -80,6 +80,7 @@
 #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;
diff --git a/drivers/common/media_clock/clk/clk.c b/drivers/common/media_clock/clk/clk.c
index 972bcc1..6340c1a 100644
--- a/drivers/common/media_clock/clk/clk.c
+++ b/drivers/common/media_clock/clk/clk.c
@@ -27,7 +27,7 @@
 #include <linux/slab.h>
 
 #include <linux/amlogic/media/utils/vformat.h>
-#include <linux/amlogic/cpu_version.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"
@@ -165,7 +165,7 @@
 
 void hcodec_clock_enable(void)
 {
-	hcodec_clock_set(1);
+	hcodec_clock_set(667);
 }
 EXPORT_SYMBOL(hcodec_clock_enable);
 
@@ -311,6 +311,21 @@
 }
 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);
@@ -338,7 +353,8 @@
 		|| 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) {
+		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;
 		}
@@ -372,7 +388,7 @@
 		 */
 		return 0;	/* ignore don't needed firmare. */
 	}
-	mgr = vzalloc(sizeof(struct chip_vdec_clk_s));
+	mgr = kmalloc(sizeof(struct chip_vdec_clk_s), GFP_KERNEL);
 	if (!mgr)
 		return -ENOMEM;
 	*mgr = *t_mgr;
@@ -381,7 +397,7 @@
 	 */
 	if (mgr->clock_init) {
 		if (mgr->clock_init()) {
-			vfree(mgr);
+			kfree(mgr);
 			return -ENOMEM;
 		}
 	}
@@ -404,7 +420,7 @@
 
 int unregister_vdec_clk_mgr(enum vdec_type_e vdec_type)
 {
-	vfree(get_current_vdec_chip()->clk_mgr[vdec_type]);
+	kfree(get_current_vdec_chip()->clk_mgr[vdec_type]);
 
 	return 0;
 }
@@ -423,7 +439,7 @@
 		 */
 		return 0;	/* ignore don't needed this setting . */
 	}
-	p_setting = vzalloc(size);
+	p_setting = kmalloc(size, GFP_KERNEL);
 	if (!p_setting)
 		return -ENOMEM;
 	memcpy(p_setting, setting, size);
@@ -449,7 +465,7 @@
 
 int unregister_vdec_clk_setting(void)
 {
-	vfree(get_current_vdec_chip()->clk_setting_array);
+	kfree(get_current_vdec_chip()->clk_setting_array);
 
 	return 0;
 }
diff --git a/drivers/common/media_clock/clk/clk.h b/drivers/common/media_clock/clk/clk.h
index 82eec1d..bbc3bee 100644
--- a/drivers/common/media_clock/clk/clk.h
+++ b/drivers/common/media_clock/clk/clk.h
@@ -52,6 +52,8 @@
 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);
 
@@ -130,7 +132,7 @@
 #endif
 #ifdef VDEC_HAS_HEVC
 	register_vdec_clk_mgr(cpus, VDEC_HEVC, &vdec_hevc_clk_mgr);
-	if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A)
+	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
diff --git a/drivers/common/media_clock/clk/clkg12.c b/drivers/common/media_clock/clk/clkg12.c
index be2401c..c49d150 100644
--- a/drivers/common/media_clock/clk/clkg12.c
+++ b/drivers/common/media_clock/clk/clkg12.c
@@ -114,11 +114,6 @@
 	WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 8, 1);\
 }while(0)
 
-#define CHECK_RET(_ret) if (ret) {debug_print(\
-		"%s:%d:function call failed with result: %d\n",\
-		__FUNCTION__, __LINE__, _ret);}
-
-
 static int clock_real_clk[VDEC_MAX + 1];
 
 static unsigned int set_frq_enable, vdec_frq, hevc_frq, hevcb_frq;
@@ -130,19 +125,14 @@
 static int gp_pll_user_cb_vdec(struct gp_pll_user_handle_s *user,
 			int event)
 {
-	int ret;
-
 	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) {
-				ret = clk_set_rate(clk, 1296000000UL);
-				CHECK_RET(ret);
-			} else {
-				ret = clk_set_rate(clk, 648000000UL);
-				CHECK_RET(ret);
-			}
+			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)
@@ -426,7 +416,9 @@
 	struct gate_switch_node *node = NULL;
 	char *hevc_mux_str = NULL;
 
-	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SC2)
+	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";
@@ -466,7 +458,6 @@
 static int vdec_set_clk(int dec, int rate)
 {
 	struct clk *clk = NULL;
-	int ret;
 
 	switch (dec) {
 	case VDEC_1:
@@ -506,8 +497,7 @@
 		return -1;
 	}
 
-	ret = clk_set_rate(clk, rate);
-	CHECK_RET(ret);
+	clk_set_rate(clk, rate);
 
 	return 0;
 }
@@ -523,12 +513,12 @@
 {
 	gp_pll_user_vdec = gp_pll_user_register("vdec", 0,
 		gp_pll_user_cb_vdec);
-	if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_GXL)
+	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() >= MESON_CPU_MAJOR_ID_GXL) {
+	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);
 	}
@@ -743,9 +733,14 @@
 	}
 
 	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_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;
@@ -841,10 +836,15 @@
 	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)
+		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) {
@@ -1042,6 +1042,14 @@
 	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"
 
diff --git a/drivers/common/media_clock/switch/amports_gate.c b/drivers/common/media_clock/switch/amports_gate.c
index 9d5f7b4..58a0289 100644
--- a/drivers/common/media_clock/switch/amports_gate.c
+++ b/drivers/common/media_clock/switch/amports_gate.c
@@ -99,11 +99,11 @@
 		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 %p\n",
+			pr_info("get gate %s control failed %px\n",
 				gates[i].name,
 				gates[i].clk);
 		} else {
-			pr_info("get gate %s control ok %p\n",
+			pr_info("get gate %s control ok %px\n",
 				gates[i].name,
 				gates[i].clk);
 		}
diff --git a/drivers/fake_video_out/Makefile b/drivers/fake_video_out/Makefile
deleted file mode 100644
index 1dd937c..0000000
--- a/drivers/fake_video_out/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-m   += fake_video.o
diff --git a/drivers/fake_video_out/fake_video.c b/drivers/fake_video_out/fake_video.c
deleted file mode 100644
index e0e9b16..0000000
--- a/drivers/fake_video_out/fake_video.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
-* 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/version.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/mutex.h>
-#include <linux/ctype.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/clk.h>
-#include <linux/debugfs.h>
-#include <linux/dma-mapping.h>
-#include <linux/dma-contiguous.h>
-#include <linux/sched.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/major.h>
-#include "../frame_provider/decoder/utils/vdec.h"
-#include <linux/delay.h>
-#include <linux/kthread.h>
-
-#define RECEIVER_NAME "fake-amvideo"
-#define DEVICE_NAME "fake-amvideo"
-
-#define TUNNEL_MODE	(0)
-#define NON_TUNNEL_MODE	(1)
-
-static u32 display_mode = TUNNEL_MODE;
-module_param(display_mode, uint, 0664);
-MODULE_PARM_DESC(display_mode, "\n display_mode\n");
-
-static struct device *amvideo_dev = NULL;
-struct timer_list timer;
-struct task_struct *task;
-bool thread_stop = false;
-atomic_t frame_count;
-
-static struct vframe_receiver_s fake_video_vf_recv;
-static int video_receiver_event_fun(int type, void *data, void *);
-static const struct vframe_receiver_op_s fake_video_vf_receiver = {
-	.event_cb = video_receiver_event_fun
-};
-
-static struct vframe_s *video_vf_peek(void)
-{
-	return vf_peek(RECEIVER_NAME);
-}
-
-static struct vframe_s *video_vf_get(void)
-{
-	struct vframe_s *vf = NULL;
-
-	vf = vf_get(RECEIVER_NAME);
-
-	if (vf) {
-		atomic_set(&vf->use_cnt, 1);
-		/*pr_err("Get vframe  w: %d, h: %d, fence: %lx, idx: %d\n",
-			vf->width, vf->height, (ulong)vf->fence, vf->index & 0xff);*/
-	}
-
-	return vf;
-}
-
-static void video_vf_put(struct vframe_s *vf)
-{
-	struct vframe_provider_s *vfp = vf_get_provider(RECEIVER_NAME);
-
-	if (vfp && vf && atomic_dec_and_test(&vf->use_cnt)) {
-		vf_put(vf, RECEIVER_NAME);
-	}
-}
-
-static int video_receiver_event_fun(int type, void *data, void *private_data)
-{
-	switch (type) {
-	case VFRAME_EVENT_PROVIDER_UNREG: {
-		atomic_set(&frame_count, 0);
-		pr_info("VFRAME_EVENT_PROVIDER_UNREG\n");
-		break;
-	}
-	case VFRAME_EVENT_PROVIDER_START: {
-		pr_info("VFRAME_EVENT_PROVIDER_START\n");
-		break;
-	}
-	case VFRAME_EVENT_PROVIDER_QUREY_STATE: {
-		break;
-	}
-	case VFRAME_EVENT_PROVIDER_VFRAME_READY: {
-		pr_info("VFRAME_EVENT_PROVIDER_VFRAME_READY\n");
-		atomic_inc(&frame_count);
-		break;
-	}
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static void display_timer_func(unsigned long arg)
-{
-	struct vframe_s *vf = NULL;
-
-	if (display_mode != TUNNEL_MODE)
-		goto out;
-
-	vf = video_vf_peek();
-	if (!vf) {
-		goto out;
-	}
-
-	if (vf->fence) {
-		if (vdec_fence_status_get(vf->fence) == 1) {
-			pr_info("[VDEC-FENCE]: Display, idx: %d\n",
-				vf->index & 0xff);
-			vf = video_vf_get();
-			video_vf_put(vf);
-		} else {
-			pr_err("[VDEC-FENCE]: Display invalid, fence status err.\n");
-		}
-	}
-
-out:
-	mod_timer(&timer, jiffies + msecs_to_jiffies(16));
-}
-
-static int display_thread(void *data)
-{
-	struct vframe_s *vf = NULL;
-
-	for (;;) {
-		if (thread_stop)
-			break;
-
-		if ((atomic_read(&frame_count) == 0) ||
-			display_mode != NON_TUNNEL_MODE)
-			continue;
-
-		if (video_vf_peek()) {
-			vf = video_vf_get();
-			if (!vf) {
-				pr_err("receiver vf err.\n");
-				break;
-			}
-
-			atomic_dec(&frame_count);
-
-			if (vf->fence) {
-				u64 timestamp = local_clock();
-				/* fence waiting until frame ready. */
-				vdec_fence_wait(vf->fence, msecs_to_jiffies(2000));
-
-				if (vdec_fence_status_get(vf->fence) == 1) {
-					pr_info("[VDEC-FENCE]: Display, idx: %d, dec cost: %lld\n",
-						vf->index & 0xff, local_clock() - timestamp);
-				} else {
-					pr_err("[VDEC-FENCE]: Display invalid, fence status err.\n");
-				}
-			}
-
-			video_vf_put(vf);
-		}
-		msleep(16);
-	}
-	return 0;
-}
-
-static int amvideo_open(struct inode *inode, struct file *file)
-{
-	file->private_data = NULL;
-	return 0;
-}
-
-static int amvideo_release(struct inode *inode, struct file *file)
-{
-	file->private_data = NULL;
-	return 0;
-}
-
-static long amvideo_ioctl(struct file *file, unsigned int cmd, ulong arg)
-{
-	file->private_data = NULL;
-	return 0;
-}
-
-#ifdef CONFIG_COMPAT
-static long amvideo_compat_ioctl(struct file *file, unsigned int cmd, ulong arg)
-{
-	file->private_data = NULL;
-	return 0;
-}
-#endif
-
-static const struct file_operations amvideo_fops = {
-	.owner = THIS_MODULE,
-	.open = amvideo_open,
-	.release = amvideo_release,
-	.unlocked_ioctl = amvideo_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl = amvideo_compat_ioctl,
-#endif
-	//.poll = amvideo_poll,
-};
-
-static struct class amvideo_class = {
-	.name = "fake_video",
-};
-
-#define FAKEVIDEO_MAJOR		(23 + (AML_BASE))
-
-static int __init fake_video_init(void)
-{
-	int ret = 0;
-
-	ret = class_register(&amvideo_class);
-	if (ret) {
-		pr_err("create video class fail.\n");
-		return 0;
-	}
-
-
-	/* create video device */
-	ret = register_chrdev(FAKEVIDEO_MAJOR, DEVICE_NAME, &amvideo_fops);
-	if (ret < 0) {
-		pr_err("Can't register major for amvideo device\n");
-		goto err1;
-	}
-
-	amvideo_dev = device_create(&amvideo_class, NULL,
-		MKDEV(FAKEVIDEO_MAJOR, 0), NULL, DEVICE_NAME);
-	if (IS_ERR(amvideo_dev)) {
-		pr_err("Can't create amvideo device\n");
-		goto err;
-	}
-
-	vf_receiver_init(&fake_video_vf_recv, RECEIVER_NAME,
-		&fake_video_vf_receiver, NULL);
-	vf_reg_receiver(&fake_video_vf_recv);
-
-	atomic_set(&frame_count, 0);
-
-	init_timer(&timer);
-	//timer.data = 0;
-	timer.function = display_timer_func;
-	timer.expires = jiffies + HZ;
-	add_timer(&timer);
-
-	thread_stop = false;
-	task = kthread_run(display_thread, NULL, "aml-%s", "fake-video-thread");
-	if (IS_ERR(task)) {
-		ret = PTR_ERR(task);
-		pr_err("Failed to creat display thread, ret: %d.\n", ret);
-		goto err;
-	}
-
-	return 0;
-
-err:
-	unregister_chrdev(FAKEVIDEO_MAJOR, DEVICE_NAME);
-err1:
-	class_unregister(&amvideo_class);
-
-	return ret;
-}
-
-static void __exit fake_video_exit(void)
-{
-	thread_stop = true;
-	kthread_stop(task);
-
-	del_timer_sync(&timer);
-
-	vf_unreg_receiver(&fake_video_vf_recv);
-
-	device_destroy(&amvideo_class, MKDEV(FAKEVIDEO_MAJOR, 0));
-	unregister_chrdev(FAKEVIDEO_MAJOR, DEVICE_NAME);
-	class_unregister(&amvideo_class);
-
-}
-
-
-module_init(fake_video_init);
-module_exit(fake_video_exit);
-
-
-MODULE_DESCRIPTION("AMLOGIC fake video output driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Nanxin Qin <nanxin.qin@amlogic.com>");
-
diff --git a/drivers/frame_provider/Makefile b/drivers/frame_provider/Makefile
index 371e088..f30c4f1 100644
--- a/drivers/frame_provider/Makefile
+++ b/drivers/frame_provider/Makefile
@@ -1 +1,2 @@
 obj-y	+=	decoder/
+obj-y	+=	decoder_v4l/
diff --git a/drivers/frame_provider/decoder/Makefile b/drivers/frame_provider/decoder/Makefile
index 349d381..bb0079e 100644
--- a/drivers/frame_provider/decoder/Makefile
+++ b/drivers/frame_provider/decoder/Makefile
@@ -7,7 +7,6 @@
 obj-y	+=	h265/
 obj-y	+=	vp9/
 obj-y	+=	mjpeg/
-obj-y	+=	real/
 obj-y	+=	avs/
 obj-y	+=	avs2/
 obj-y	+=	avs_multi/
diff --git a/drivers/frame_provider/decoder/avs/avs.c b/drivers/frame_provider/decoder/avs/avs.c
index 6314f9d..5869eac 100644
--- a/drivers/frame_provider/decoder/avs/avs.c
+++ b/drivers/frame_provider/decoder/avs/avs.c
@@ -43,8 +43,8 @@
 #include "../utils/decoder_bmmu_box.h"
 #include "../utils/firmware.h"
 #include "../../../common/chips/decoder_cpu_ver_info.h"
-#include <linux/amlogic/tee.h>
-
+//#include <linux/amlogic/tee.h>
+#include <uapi/linux/tee.h>
 
 #define DRIVER_NAME "amvdec_avs"
 #define MODULE_NAME "amvdec_avs"
@@ -162,7 +162,6 @@
 	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;
@@ -413,6 +412,7 @@
 	}
 }
 
+
 #ifdef HANDLE_AVS_IRQ
 static irqreturn_t vavs_isr(int irq, void *dev_id)
 #else
@@ -654,6 +654,7 @@
 				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);
@@ -740,7 +741,6 @@
 				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);
@@ -945,35 +945,35 @@
 		else
 			endian = 0;
 #ifdef NV21
-			canvas_config_ex(canvas_base + canvas_num * i + 0,
+			config_cav_lut_ex(canvas_base + canvas_num * i + 0,
 					buf_start,
 					canvas_width, canvas_height,
 					CANVAS_ADDR_NOWRAP,
-					vdec->canvas_mode, endian);
-			canvas_config_ex(canvas_base + canvas_num * i + 1,
+					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->canvas_mode, endian, VDEC_1);
 #else
-			canvas_config_ex(canvas_num * i + 0,
+			config_cav_lut_ex(canvas_num * i + 0,
 					buf_start,
 					canvas_width, canvas_height,
 					CANVAS_ADDR_NOWRAP,
-					vdec->canvas_mode, endian);
-			canvas_config_ex(canvas_num * i + 1,
+					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);
-			canvas_config_ex(canvas_num * i + 2,
+					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->canvas_mode, endian, VDEC_1);
 #endif
 			if (debug_flag & AVS_DEBUG_PRINT) {
 				pr_info("canvas config %d, addr %p\n", i,
@@ -1353,10 +1353,8 @@
 		}
 }
 
-static void vavs_put_timer_func(unsigned long arg)
+static void vavs_put_timer_func(struct timer_list *timer)
 {
-	struct timer_list *timer = (struct timer_list *)arg;
-
 #ifndef HANDLE_AVS_IRQ
 	vavs_isr();
 #endif
@@ -1573,7 +1571,6 @@
 		return -ENOMEM;
 
 	pr_info("vavs_init\n");
-	init_timer(&recycle_timer);
 
 	stat |= STAT_TIMER_INIT;
 
@@ -1657,10 +1654,8 @@
 
 	stat |= STAT_VF_HOOK;
 
-	recycle_timer.data = (ulong)(&recycle_timer);
-	recycle_timer.function = vavs_put_timer_func;
+	timer_setup(&recycle_timer, vavs_put_timer_func, 0);
 	recycle_timer.expires = jiffies + PUT_INTERVAL;
-
 	add_timer(&recycle_timer);
 
 	stat |= STAT_TIMER_ARM;
diff --git a/drivers/frame_provider/decoder/avs2/avs2_bufmgr.c b/drivers/frame_provider/decoder/avs2/avs2_bufmgr.c
index 3da87e4..de9a3d2 100644
--- a/drivers/frame_provider/decoder/avs2/avs2_bufmgr.c
+++ b/drivers/frame_provider/decoder/avs2/avs2_bufmgr.c
@@ -39,7 +39,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/dma-contiguous.h>
 #include <linux/slab.h>
-#include <linux/amlogic/tee.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"
diff --git a/drivers/frame_provider/decoder/avs2/avs2_global.h b/drivers/frame_provider/decoder/avs2/avs2_global.h
index 3e7fcb8..be35a5e 100644
--- a/drivers/frame_provider/decoder/avs2/avs2_global.h
+++ b/drivers/frame_provider/decoder/avs2/avs2_global.h
@@ -772,6 +772,9 @@
 	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;
@@ -814,6 +817,9 @@
 
 	u32 hw_decode_time;
 	u32 frame_size; // For frame base mode
+
+	char *cuva_data_buf;
+	int  cuva_data_size;
 };
 
 
diff --git a/drivers/frame_provider/decoder/avs2/vavs2.c b/drivers/frame_provider/decoder/avs2/vavs2.c
index a5d550f..e21dc55 100644
--- a/drivers/frame_provider/decoder/avs2/vavs2.c
+++ b/drivers/frame_provider/decoder/avs2/vavs2.c
@@ -37,7 +37,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/dma-contiguous.h>
 #include <linux/slab.h>
-#include <linux/amlogic/tee.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"
@@ -55,26 +57,46 @@
 #include "../utils/config_parser.h"
 #include "../utils/firmware.h"
 #include "../../../common/chips/decoder_cpu_ver_info.h"
-#include <linux/amlogic/tee.h>
-
+#include "../utils/vdec_feature.h"
 
 #define I_ONLY_SUPPORT
 #define MIX_STREAM_SUPPORT
-#define G12A_BRINGUP_DEBUG
 #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
@@ -227,6 +249,9 @@
 #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];
@@ -236,17 +261,11 @@
 static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM];
 static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM];
 
-#ifdef G12A_BRINGUP_DEBUG
 static u32 decode_timeout_val = 200;
-#else
-static u32 decode_timeout_val = 200;
-#endif
+
 static int start_decode_buf_level = 0x8000;
-#ifdef AVS2_10B_MMU
-static u32 work_buf_size; /* = 24 * 1024 * 1024*/;
-#else
-static u32 work_buf_size = 32 * 1024 * 1024;
-#endif
+
+static u32 work_buf_size;
 
 static u32 mv_buf_margin;
 static int pre_decode_buf_level = 0x1000;
@@ -260,6 +279,7 @@
  *	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;
@@ -298,7 +318,7 @@
 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(unsigned long arg);
+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);
@@ -330,6 +350,8 @@
 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",
@@ -405,11 +427,6 @@
 #define DOUBLE_WRITE_YSTART_TEMP 0x02000000
 #define DOUBLE_WRITE_CSTART_TEMP 0x02900000
 
-
-
-typedef unsigned int u32;
-typedef unsigned short u16;
-
 #define AVS2_DBG_BUFMGR                   0x01
 #define AVS2_DBG_BUFMGR_MORE              0x02
 #define AVS2_DBG_BUFMGR_DETAIL            0x04
@@ -425,6 +442,7 @@
 #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
@@ -497,6 +515,9 @@
 
 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)
@@ -511,11 +532,6 @@
 #define WRITE_VREG WRITE_VREG_DBG2
 #endif
 
-
-//#ifdef AVS2_10B_MMU
-//#define MMU_COMPRESS_HEADER_SIZE  0x48000
-//#define MMU_COMPRESS_8K_HEADER_SIZE  0x48000*4
-//#endif
 #define MMU_COMPRESS_HEADER_SIZE_1080P  0x10000
 #define MMU_COMPRESS_HEADER_SIZE_4K  0x48000
 #define MMU_COMPRESS_HEADER_SIZE_8K  0x120000
@@ -530,7 +546,7 @@
 #define FRAME_CONTEXTS_LOG2 2
 #define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2)
 /*buffer + header buffer + workspace*/
-#undef MV_USE_FIXED_BUF
+
 #ifdef MV_USE_FIXED_BUF
 #define MAX_BMMU_BUFFER_NUM ((FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1)+1)
 #define VF_BUFFER_IDX(n) (n)
@@ -542,6 +558,7 @@
 #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
@@ -584,6 +601,10 @@
 	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;
@@ -668,11 +689,22 @@
 	unsigned short *lmem_ptr;
 	unsigned short *debug_ptr;
 
-#if 1
-	/*AVS2_10B_MMU*/
+#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];
@@ -775,10 +807,14 @@
 	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(
@@ -888,10 +924,19 @@
 
 static u32 get_valid_double_write_mode(struct AVS2Decoder_s *dec)
 {
-	return (dec->m_ins_flag &&
+	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)
@@ -949,18 +994,6 @@
 	return dw;
 }
 
-static int get_double_write_ratio(struct AVS2Decoder_s *dec,
-	int dw_mode)
-{
-	int ratio = 1;
-	if ((dw_mode == 2) ||
-			(dw_mode == 3))
-		ratio = 4;
-	else if (dw_mode == 4)
-		ratio = 2;
-	return ratio;
-}
-
 //#define	MAX_4K_NUM		0x1200
 #ifdef AVS2_10B_MMU
 int avs2_alloc_mmu(
@@ -974,25 +1007,6 @@
 	int bit_depth_10 = (bit_depth == AVS2_BITS_10);
 	int picture_size;
 	int cur_mmu_4k_number, max_frame_num;
-#ifdef DYNAMIC_ALLOC_HEAD
-	unsigned long buf_addr;
-	struct avs2_frame_s *pic = dec->avs2_dec.hc.cur_pic;
-	if (pic->header_adr == 0) {
-		if (decoder_bmmu_box_alloc_buf_phy
-				(dec->bmmu_box,
-				HEADER_BUFFER_IDX(cur_buf_idx),
-				get_compress_header_size(dec),
-				DRIVER_HEADER_NAME,
-				&buf_addr) < 0){
-			avs2_print(dec, 0,
-				"%s malloc compress header failed %d\n",
-				DRIVER_HEADER_NAME, cur_buf_idx);
-			dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM;
-			return -1;
-		} else
-			pic->header_adr = buf_addr;
-	}
-#endif
 
 	picture_size = compute_losless_comp_body_size(
 		dec, pic_width, pic_height,
@@ -1015,157 +1029,38 @@
 }
 #endif
 
-#if 0
-/*ndef MV_USE_FIXED_BUF*/
-static void dealloc_mv_bufs(struct AVS2Decoder_s *dec)
+#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 i;
-	for (i = 0; i < FRAME_BUFFERS; i++) {
-		if (dec->m_mv_BUF[i].start_adr) {
-			if (debug)
-				pr_info(
-				"dealloc mv buf(%d) adr %ld size 0x%x used_flag %d\n",
-				i, dec->m_mv_BUF[i].start_adr,
-				dec->m_mv_BUF[i].size,
-				dec->m_mv_BUF[i].used_flag);
-			decoder_bmmu_box_free_idx(
-				dec->bmmu_box,
-				MV_BUFFER_IDX(i));
-			dec->m_mv_BUF[i].start_adr = 0;
-			dec->m_mv_BUF[i].size = 0;
-			dec->m_mv_BUF[i].used_flag = 0;
-		}
+	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);
 }
-
-static int alloc_mv_buf(struct AVS2Decoder_s *dec,
-	int i, int size)
-{
-	int ret = 0;
-	if (decoder_bmmu_box_alloc_buf_phy
-		(dec->bmmu_box,
-		MV_BUFFER_IDX(i), size,
-		DRIVER_NAME,
-		&dec->m_mv_BUF[i].start_adr) < 0) {
-		dec->m_mv_BUF[i].start_adr = 0;
-		ret = -1;
-	} else {
-		dec->m_mv_BUF[i].size = size;
-		dec->m_mv_BUF[i].used_flag = 0;
-		ret = 0;
-		if (debug) {
-			pr_info(
-			"MV Buffer %d: start_adr %p size %x\n",
-			i,
-			(void *)dec->m_mv_BUF[i].start_adr,
-			dec->m_mv_BUF[i].size);
-		}
-	}
-	return ret;
-}
-
-static int init_mv_buf_list(struct AVS2Decoder_s *dec)
-{
-	int i;
-	int ret = 0;
-	int count = FRAME_BUFFERS;
-	int pic_width = dec->init_pic_w;
-	int pic_height = dec->init_pic_h;
-	int lcu_size = 64; /*fixed 64*/
-	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;
-	int size = ((lcu_total * MV_MEM_UNIT) + 0xffff) &
-		(~0xffff);
-	if (mv_buf_margin > 0)
-		count = dec->avs2_dec.ref_maxbuffer + mv_buf_margin;
-	for (i = 0; i < count; i++) {
-		if (alloc_mv_buf(dec, i, size) < 0) {
-			ret = -1;
-			break;
-		}
-	}
-	return ret;
-}
-#if 0
-
-static int get_mv_buf(struct AVS2Decoder_s *dec,
-				struct avs2_frame_s *pic)
-{
-	int i;
-	int ret = -1;
-	for (i = 0; i < FRAME_BUFFERS; i++) {
-		if (dec->m_mv_BUF[i].start_adr &&
-			dec->m_mv_BUF[i].used_flag == 0) {
-			dec->m_mv_BUF[i].used_flag = 1;
-			ret = i;
-			break;
-		}
-	}
-
-	if (ret >= 0) {
-		pic->mv_buf_index = ret;
-		pic->mpred_mv_wr_start_addr =
-			(dec->m_mv_BUF[ret].start_adr + 0xffff) &
-			(~0xffff);
-		if (debug & AVS2_DBG_BUFMGR_MORE)
-			pr_info(
-			"%s => %d (%d) size 0x%x\n",
-			__func__, ret,
-			pic->mpred_mv_wr_start_addr,
-			dec->m_mv_BUF[ret].size);
-	} else {
-		pr_info(
-		"%s: Error, mv buf is not enough\n",
-		__func__);
-	}
-	return ret;
-}
-
-static void put_mv_buf(struct AVS2Decoder_s *dec,
-				struct avs2_frame_s *pic)
-{
-	int i = pic->mv_buf_index;
-	if (i >= FRAME_BUFFERS) {
-		if (debug & AVS2_DBG_BUFMGR_MORE)
-			pr_info(
-			"%s: index %d beyond range\n",
-			__func__, i);
-		return;
-	}
-	if (debug & AVS2_DBG_BUFMGR_MORE)
-		pr_info(
-		"%s(%d): used_flag(%d)\n",
-		__func__, i,
-		dec->m_mv_BUF[i].used_flag);
-
-	pic->mv_buf_index = -1;
-	if (dec->m_mv_BUF[i].start_adr &&
-		dec->m_mv_BUF[i].used_flag)
-		dec->m_mv_BUF[i].used_flag = 0;
-}
-
-static void	put_un_used_mv_bufs(struct AVS2Decoder_s *dec)
-{
-	struct VP9_Common_s *const cm = &dec->common;
-	struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
-	int i;
-	for (i = 0; i < dec->used_buf_num; ++i) {
-		if ((frame_bufs[i].ref_count == 0) &&
-			(frame_bufs[i].buf.index != -1) &&
-			(frame_bufs[i].buf.mv_buf_index >= 0)
-			)
-			put_mv_buf(dec, &frame_bufs[i].buf);
-	}
-}
-#endif
-
 #endif
 
 static int get_free_buf_count(struct AVS2Decoder_s *dec)
@@ -1308,13 +1203,19 @@
 
 
 const u32 avs2_version = 201602101;
-static u32 debug;
 static u32 radr;
 static u32 rval;
 static u32 pop_shorts;
 static u32 dbg_cmd;
 static u32 dbg_skip_decode_index;
-static u32 endian = 0xff0;
+/*
+ * 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 */
@@ -1418,6 +1319,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
@@ -1476,7 +1380,10 @@
 #define DW_VBH_BUF_SIZE_8K (VBH_BUF_SIZE_8K * 2)
 #define DW_VBH_BUF_SIZE(bufspec) (bufspec->mmu_vbh_dw.buf_size / 4)
 
-#define WORK_BUF_SPEC_NUM 3
+/* 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 */
@@ -1485,6 +1392,283 @@
 		.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 = {
@@ -1556,6 +1740,16 @@
 		},
 #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*/
 		},
@@ -1651,6 +1845,16 @@
 		},
 #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*/
 		},
@@ -1739,6 +1943,16 @@
 		},
 #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,
 		},
@@ -1840,64 +2054,70 @@
 	struct BuffInfo_s *buf_spec)
 {
 	void *mem_start_virt;
-	buf_spec->ipp.buf_start = buf_spec->start_adr;
+	buf_spec->ipp.buf_start =
+		WORKBUF_ALIGN(buf_spec->start_adr);
 	buf_spec->sao_abv.buf_start =
-		buf_spec->ipp.buf_start + buf_spec->ipp.buf_size;
-
+		WORKBUF_ALIGN(buf_spec->ipp.buf_start + buf_spec->ipp.buf_size);
 	buf_spec->sao_vb.buf_start =
-		buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size;
+		WORKBUF_ALIGN(buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size);
 	buf_spec->short_term_rps.buf_start =
-		buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size;
+		WORKBUF_ALIGN(buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size);
 	buf_spec->rcs.buf_start =
-		buf_spec->short_term_rps.buf_start +
-		buf_spec->short_term_rps.buf_size;
+		WORKBUF_ALIGN(buf_spec->short_term_rps.buf_start + buf_spec->short_term_rps.buf_size);
 	buf_spec->sps.buf_start =
-		buf_spec->rcs.buf_start + buf_spec->rcs.buf_size;
+		WORKBUF_ALIGN(buf_spec->rcs.buf_start + buf_spec->rcs.buf_size);
 	buf_spec->pps.buf_start =
-		buf_spec->sps.buf_start + buf_spec->sps.buf_size;
+		WORKBUF_ALIGN(buf_spec->sps.buf_start + buf_spec->sps.buf_size);
 	buf_spec->sao_up.buf_start =
-		buf_spec->pps.buf_start + buf_spec->pps.buf_size;
+		WORKBUF_ALIGN(buf_spec->pps.buf_start + buf_spec->pps.buf_size);
 	buf_spec->swap_buf.buf_start =
-		buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size;
+		WORKBUF_ALIGN(buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size);
 	buf_spec->swap_buf2.buf_start =
-		buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size;
+		WORKBUF_ALIGN(buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size);
 	buf_spec->scalelut.buf_start =
-		buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size;
+		WORKBUF_ALIGN(buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size);
 	buf_spec->dblk_para.buf_start =
-		buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size;
+		WORKBUF_ALIGN(buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size);
 	buf_spec->dblk_data.buf_start =
-		buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size;
+		WORKBUF_ALIGN(buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size);
 	buf_spec->dblk_data2.buf_start =
-		buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size;
+		WORKBUF_ALIGN(buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size);
 #ifdef AVS2_10B_MMU
 	buf_spec->mmu_vbh.buf_start  =
-		buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size;
+		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 =
-		buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size;
-#else
+		WORKBUF_ALIGN(buf_spec->mmu_vbh_dw.buf_start + buf_spec->mmu_vbh_dw.buf_size);
+	#else
 	buf_spec->mpred_above.buf_start =
-		buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size;
-#endif
+		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 =
-		buf_spec->mpred_above.buf_start +
-		buf_spec->mpred_above.buf_size;
-
+		WORKBUF_ALIGN(buf_spec->mpred_above.buf_start + buf_spec->mpred_above.buf_size);
 	buf_spec->rpm.buf_start =
-		buf_spec->mpred_mv.buf_start +
-		buf_spec->mpred_mv.buf_size;
+		WORKBUF_ALIGN(buf_spec->mpred_mv.buf_start + buf_spec->mpred_mv.buf_size);
 #else
 	buf_spec->rpm.buf_start =
-		buf_spec->mpred_above.buf_start +
-		buf_spec->mpred_above.buf_size;
-
+		WORKBUF_ALIGN(buf_spec->mpred_above.buf_start + buf_spec->mpred_above.buf_size);
 #endif
 	buf_spec->lmem.buf_start =
-		buf_spec->rpm.buf_start +
-		buf_spec->rpm.buf_size;
+		WORKBUF_ALIGN(buf_spec->rpm.buf_start + buf_spec->rpm.buf_size);
 	buf_spec->end_adr =
-		buf_spec->lmem.buf_start +
-		buf_spec->lmem.buf_size;
+		WORKBUF_ALIGN(buf_spec->lmem.buf_start + buf_spec->lmem.buf_size);
 
 	if (dec) {
 		mem_start_virt =
@@ -1950,6 +2170,10 @@
 			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
@@ -1967,9 +2191,11 @@
 
 static void uninit_mmu_buffers(struct AVS2Decoder_s *dec)
 {
-#if 0
-/*ndef MV_USE_FIXED_BUF*/
-	dealloc_mv_bufs(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;
@@ -2010,9 +2236,9 @@
 
 	if (dw_mode) {
 		int pic_width_dw = pic_width /
-			get_double_write_ratio(dec, dw_mode);
+			get_double_write_ratio(dw_mode);
 		int pic_height_dw = pic_height /
-			get_double_write_ratio(dec, dw_mode);
+			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);
@@ -2043,7 +2269,7 @@
 	for (i = 0; i < dec->used_buf_num; i++) {
 		if (((i + 1) * buf_size) > dec->mc_buf->buf_size)
 			dec->use_cma_flag = 1;
-#ifndef AVS2_10B_MMU
+
 		dec->m_BUF[i].alloc_flag = 0;
 		dec->m_BUF[i].index = i;
 
@@ -2084,7 +2310,6 @@
 			"Buffer %d: start_adr %p size %x\n", i,
 			   (void *)dec->m_BUF[i].start_adr,
 			   dec->m_BUF[i].size);
-#endif
 	}
 	dec->buf_num = i;
 }
@@ -2109,15 +2334,7 @@
 				pic_height_32 / lcu_size + 1
 				: pic_height_32 / lcu_size;
 	int lcu_total       = pic_width_lcu * pic_height_lcu;
-#if 0
-	int32_t MV_MEM_UNIT =
-		(lcu_size_log2 == 6) ? 0x200 :
-		((lcu_size_log2 == 5) ? 0x80 : 0x20);
-#endif
-#ifdef MV_USE_FIXED_BUF
-	u32 mpred_mv_end = dec->work_space_buf->mpred_mv.buf_start +
-			dec->work_space_buf->mpred_mv.buf_size;
-#endif
+
 	u32 y_adr = 0;
 	int buf_size = 0;
 
@@ -2133,11 +2350,11 @@
 	int mc_buffer_size_u_v_h = 0;
 	int dw_mode = get_double_write_mode_init(dec);
 
-	if (dw_mode) {
+	if (dw_mode && ((dw_mode & 0x20) == 0)) {
 		int pic_width_dw = pic_width /
-			get_double_write_ratio(dec, dw_mode);
+			get_double_write_ratio(dw_mode);
 		int pic_height_dw = pic_height /
-			get_double_write_ratio(dec, dw_mode);
+			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) ?
@@ -2156,171 +2373,150 @@
 	}
 	if (mc_buffer_size & 0xffff) /*64k alignment*/
 		mc_buffer_size_h += 1;
-#ifndef AVS2_10B_MMU
+
+
+#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
 
-#ifdef AVS2_10B_MMU
-#ifndef DYNAMIC_ALLOC_HEAD
-	pic->header_adr = decoder_bmmu_box_get_phy_addr(
-			dec->bmmu_box, HEADER_BUFFER_IDX(pic->index));
-
-	avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
-		"buf_size %d, MMU header_adr %d: %ld\n",
-		buf_size, pic->index, pic->header_adr);
-#endif
-#endif
-
 	i = pic->index;
-#ifdef MV_USE_FIXED_BUF
-#ifdef G12A_BRINGUP_DEBUG
-	if (1) {
+
+#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->work_space_buf->mpred_mv.buf_start +
-		(((i + 1) * lcu_total) * MV_MEM_UNIT))
-		<= mpred_mv_end
-	) {
-#endif
-#endif
-#ifndef AVS2_10B_MMU
-		if (debug) {
-			pr_err("start %x  .size=%d\n",
-				dec->mc_buf_spec.buf_start + i * buf_size,
-				buf_size);
+	/*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;
 		}
-#endif
-#ifndef AVS2_10B_MMU
-		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 (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;
 		}
-		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;
-#ifndef AVS2_10B_MMU
-			pic->mc_y_adr = y_adr;
-#endif
-			pic->mc_canvas_y = pic->index;
-			pic->mc_canvas_u_v = pic->index;
-#ifndef AVS2_10B_MMU
-			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) {
-				pic->dw_y_adr = y_adr
-#ifndef AVS2_10B_MMU
-				+ (mc_buffer_size_h << 16)
-#endif
-				;
-				pic->dw_u_v_adr = pic->dw_y_adr +
-					((mc_buffer_size_u_v_h << 16) << 1);
-#ifdef AVS2_10B_MMU
-				pic->mc_y_adr = pic->dw_y_adr;
-				pic->mc_u_v_adr = pic->dw_u_v_adr;
-#endif
-			}
-#ifdef MV_USE_FIXED_BUF
-#ifdef G12A_BRINGUP_DEBUG
-			if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
-				pic->mpred_mv_wr_start_addr =
-				dec->work_space_buf->mpred_mv.buf_start +
-					(pic->index * 0x120000 * 4);
-			} else {
-				pic->mpred_mv_wr_start_addr =
-				dec->work_space_buf->mpred_mv.buf_start +
-					(pic->index * 0x120000);
-			}
-#else
-			pic->mpred_mv_wr_start_addr =
-			dec->work_space_buf->mpred_mv.buf_start +
-					((pic->index * lcu_total)
-					* MV_MEM_UNIT);
-#endif
-#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;
-		}
-#ifdef MV_USE_FIXED_BUF
-	} else {
-		avs2_print(dec, 0,
-			"mv buffer alloc fail %x > %x\n",
-		dec->work_space_buf->mpred_mv.buf_start +
-		(((i + 1) * lcu_total) * MV_MEM_UNIT),
-		mpred_mv_end);
 	}
 #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;
 }
 
@@ -2331,36 +2527,28 @@
 	struct avs2_decoder *avs2_dec = &dec->avs2_dec;
 	struct avs2_frame_s *pic;
 #ifdef AVS2_10B_MMU
-	unsigned long buf_addr1;
-	/*alloc AVS2 compress header first*/
-		if (decoder_bmmu_box_alloc_buf_phy
-				(dec->bmmu_box,
-				HEADER_BUFFER_IDX(-1), get_compress_header_size(dec),
-				DRIVER_HEADER_NAME,
-				&buf_addr1) < 0){
-			avs2_print(dec, 0,
-				"%s malloc compress header failed %d\n",
-				DRIVER_HEADER_NAME, -1);
-			dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM;
-			return;
-		}
-#ifndef DYNAMIC_ALLOC_HEAD
-	for (i = 0; i < dec->used_buf_num; i++) {
-		unsigned long buf_addr;
-		if (decoder_bmmu_box_alloc_buf_phy
-				(dec->bmmu_box,
-				HEADER_BUFFER_IDX(i), get_compress_header_size(dec),
-				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;
+	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
-#endif
 	dec->frame_height = avs2_dec->img.height;
 	dec->frame_width = avs2_dec->img.width;
 
@@ -3073,7 +3261,7 @@
 	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)) {
+	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);
@@ -3085,6 +3273,14 @@
 #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);*/
@@ -3101,6 +3297,22 @@
 	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*/
@@ -3132,23 +3344,41 @@
 	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,
+	data32 |= (MEM_MAP_MODE << 12);	/* [13:12] axi_aformat, 0-Linear,
 				   1-32x32, 2-64x32 */
 	data32 &= (~0xff0);
-	/* data32 |= 0x670;  // Big-Endian per 64-bit */
-	data32 |= endian;	/* Big-Endian per 64-bit */
+#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) {
@@ -3166,6 +3396,18 @@
 	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) {
@@ -3179,26 +3421,55 @@
 		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) == 2 ||
-			get_double_write_mode(dec) == 3)
+		if ((get_double_write_mode(dec) & 0xf) == 8 ||
+			(get_double_write_mode(dec) & 0xf) == 9) {
 			data32 |= (0xff<<16);
-		else if (get_double_write_mode(dec) == 4)
+			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 |= (mem_map_mode << 4);
 	data32 &= (~0xF);
-	data32 |= 0xf;  /* valid only when double write only */
-		/*data32 |= 0x8;*/		/* Big-Endian per 64-bit */
+	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,
@@ -3465,6 +3736,110 @@
 #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;
@@ -3511,6 +3886,12 @@
 #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);
 
@@ -3580,11 +3961,38 @@
 
 #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);
-#if 1
-/*MULTI_INSTANCE_SUPPORT*/
-	/*new added in simulation???*/
+
 	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
 }
 
@@ -3611,7 +4019,6 @@
 	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);
@@ -3666,11 +4073,13 @@
 	WRITE_VREG(HEVC_DEC_STATUS_REG, 0);
 
 	/*Initial IQIT_SCALELUT memory -- just to avoid X in simulation*/
-
-	WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);/*cfg_p_addr*/
-	for (i = 0; i < 1024; i++)
-		WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0);
-
+	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);
@@ -3852,10 +4261,6 @@
 }
 #endif
 
-
-
-
-
 static struct AVS2Decoder_s gAVS2Decoder;
 
 static void avs2_local_uninit(struct AVS2Decoder_s *dec)
@@ -3868,6 +4273,14 @@
 						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(),
@@ -3885,6 +4298,17 @@
 		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;
@@ -3902,16 +4326,27 @@
 		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 (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 {
+		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
@@ -3937,14 +4372,15 @@
 	}
 	avs2_bufmgr_init(dec, cur_buf_info, &dec->mc_buf_spec);
 #endif
-
-	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 = 8192;
-		buf_alloc_height = 4608;
+	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 ?
@@ -3954,13 +4390,6 @@
 		(dec->vavs2_amstream_dec_info.height ?
 		dec->vavs2_amstream_dec_info.height :
 		dec->work_space_buf->max_height);
-#if 0
-/*ndef MV_USE_FIXED_BUF*/
-	if (init_mv_buf_list(dec) < 0) {
-		pr_err("%s: init_mv_buf_list fail\n", __func__);
-		return -1;
-	}
-#endif
 
 #ifndef AVS2_10B_MMU
 	init_buf_list(dec);
@@ -3990,6 +4419,20 @@
 		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);
@@ -4000,21 +4443,33 @@
 		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
-	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;
+	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));
 	}
-	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;
 }
@@ -4050,16 +4505,11 @@
 	/*CANVAS_BLKMODE_64X32*/
 	if	(pic->double_write_mode) {
 		canvas_w = pic->pic_w	/
-				get_double_write_ratio(dec,
-					pic->double_write_mode);
+			get_double_write_ratio(pic->double_write_mode);
 		canvas_h = pic->pic_h /
-				get_double_write_ratio(dec,
-					pic->double_write_mode);
-
-		if (mem_map_mode == 0)
-			canvas_w = ALIGN(canvas_w, 32);
-		else
-			canvas_w = ALIGN(canvas_w, 64);
+			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) {
@@ -4072,31 +4522,23 @@
 			pic->uv_canvas_index = 128 + pic->index * 2 + 1;
 		}
 
-		canvas_config_ex(pic->y_canvas_index,
+		config_cav_lut_ex(pic->y_canvas_index,
 			pic->dw_y_adr, canvas_w, canvas_h,
-			CANVAS_ADDR_NOWRAP, blkmode, 0x7);
-		canvas_config_ex(pic->uv_canvas_index,
+			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);
+			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].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].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 {
@@ -4111,12 +4553,12 @@
 			pic->uv_canvas_index = 128 + pic->index;
 		}
 
-		canvas_config_ex(pic->y_canvas_index,
+		config_cav_lut_ex(pic->y_canvas_index,
 			pic->mc_y_adr, canvas_w, canvas_h,
-			CANVAS_ADDR_NOWRAP, blkmode, 0x7);
-		canvas_config_ex(pic->uv_canvas_index,
-		pic->mc_u_v_adr,	canvas_w, canvas_h,
-			CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+			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
 	}
 }
@@ -4130,8 +4572,14 @@
 	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) {
@@ -4361,6 +4809,32 @@
 			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;
@@ -4462,7 +4936,7 @@
 		__func__, pic->index,
 		pic->imgtr_fwRefDistance);
 
-	if (pic->double_write_mode)
+	if (pic->double_write_mode && (pic->double_write_mode & 0x20) == 0)
 		set_canvas(dec, pic);
 
 	display_frame_count[dec->index]++;
@@ -4475,7 +4949,7 @@
 		} else {
 #endif
 			if ((vdec->vbuf.no_parser == 0) || (vdec->vbuf.use_ptsserv)) {
-				/* if (pts_lookup_offset(PTS_TYPE_VIDEO,
+			/* if (pts_lookup_offset(PTS_TYPE_VIDEO,
 			   stream_offset, &vf->pts, 0) != 0) { */
 				if (pts_lookup_offset_us64
 					(PTS_TYPE_VIDEO, stream_offset,
@@ -4530,18 +5004,16 @@
 
 		if (vf->pts != 0)
 			dec->last_lookup_pts = vf->pts;
-#if 1
+
 		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);
-#endif
 		dec->last_pts = vf->pts;
 
 		if (vf->pts_us64 != 0)
 			dec->last_lookup_pts_us64 = vf->pts_us64;
 
-#if 1
 		if ((dec->pts_mode == PTS_NONE_REF_USE_DURATION)
 			&& ((pic->slice_type != I_IMG) || (!pts_discontinue &&
 			!first_pts_checkin_complete(PTS_TYPE_AUDIO)))) {
@@ -4549,7 +5021,7 @@
 				dec->last_pts_us64 +
 				(DUR2PTS(dec->frame_dur) * 100 / 9);
 		}
-#endif
+
 		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",
@@ -4564,16 +5036,30 @@
 			vf->compHeadAddr = 0;
 		} else {
 #ifdef AVS2_10B_MMU
-		vf->compBodyAddr = 0;
-		vf->compHeadAddr = pic->header_adr;
+			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;
-		/*head adr*/
+			vf->compBodyAddr = pic->mc_y_adr; /*body adr*/
+			vf->compHeadAddr = pic->mc_y_adr + pic->comp_body_size;
 #endif
 		}
-		if (pic->double_write_mode) {
+		if (pic->double_write_mode &&
+			((pic->double_write_mode & 0x20) == 0)) {
 			vf->type = VIDTYPE_PROGRESSIVE |
 				VIDTYPE_VIU_FIELD;
 			vf->type |= VIDTYPE_VIU_NV21;
@@ -4637,17 +5123,26 @@
 		   vf->width,vf->height, pic->width,
 			pic->height); */
 		vf->width = pic->pic_w /
-			get_double_write_ratio(dec,
-				pic->double_write_mode);
+			get_double_write_ratio(pic->double_write_mode);
 		vf->height = pic->pic_h /
-			get_double_write_ratio(dec,
-				pic->double_write_mode);
+			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;
 		}
-		vf->compWidth = pic->pic_w;
-		vf->compHeight = pic->pic_h;
+		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)
@@ -4657,12 +5152,26 @@
 		}
 #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,
@@ -4705,7 +5214,6 @@
 	dec->gvs->status = dec->stat | dec->fatal_error;
 }
 
-
 static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec)
 {
 #ifndef NO_DISPLAY
@@ -4725,7 +5233,8 @@
 
 		if (pic->error_mark) {
 			avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
-				"!!!error pic, skip\n");
+				"!!!error pic, skip\n",
+				0);
 			continue;
 		}
 
@@ -4734,7 +5243,7 @@
 				pic->slice_type != I_IMG) {
 				avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
 					"!!!slice type %d (not I) skip\n",
-					pic->slice_type);
+					0, pic->slice_type);
 				continue;
 			}
 			dec->skip_PB_before_I = 0;
@@ -4771,7 +5280,7 @@
 			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 = get_double_write_mode(dec);
+			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) {
@@ -4965,7 +5474,7 @@
 	struct vdec_s *vdec = hw_to_vdec(dec);
 	if (!picture) {
 		avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
-			"decode picture is none exist\n");
+			"%s decode picture is none exist\n");
 
 		return;
 	}
@@ -5432,6 +5941,7 @@
 		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);
@@ -5561,31 +6071,19 @@
 			dec->avs2_dec.hc.cur_pic = NULL;
 			for (ii = 0; ii < dec->avs2_dec.ref_maxbuffer;
 					ii++) {
-				if (dec->avs2_dec.fref[ii]->
-					bg_flag == 0 &&
-					dec->avs2_dec.fref[ii]->
-					is_output == -1 &&
-					dec->avs2_dec.fref[ii]->
-					mmu_alloc_flag &&
-					dec->avs2_dec.fref[ii]->
-					vf_ref == 0) {
-					struct avs2_frame_s *pic =
-						dec->avs2_dec.fref[ii];
-					if (dec->avs2_dec.fref[ii]->
-						refered_by_others == 0) {
+				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
-						dec->avs2_dec.fref[ii]->
-						mmu_alloc_flag = 0;
+						pic->mmu_alloc_flag = 0;
 						/*release_buffer_4k(
 						dec->avs2_dec.fref[ii]->index);*/
 						decoder_mmu_box_free_idx(dec->mmu_box,
-							dec->avs2_dec.fref[ii]->index);
-#ifdef DYNAMIC_ALLOC_HEAD
-						decoder_bmmu_box_free_idx(
-							dec->bmmu_box,
-							HEADER_BUFFER_IDX(pic->index));
-						pic->header_adr = 0;
-#endif
+							pic->index);
 #endif
 #ifndef MV_USE_FIXED_BUF
 						decoder_bmmu_box_free_idx(
@@ -5594,10 +6092,6 @@
 						pic->mpred_mv_wr_start_addr = 0;
 #endif
 					}
-					decoder_bmmu_box_free_idx(
-						dec->bmmu_box,
-						VF_BUFFER_IDX(pic->index));
-					dec->cma_alloc_addr = 0;
 				}
 			}
 		}
@@ -5634,7 +6128,7 @@
 		debug_buffer_mgr_more(dec);
 		get_frame_rate(&dec->avs2_dec.param, dec);
 
-#if 0 // The video_signal_type is type of uint16_t and result false, so comment it out.
+#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;
@@ -5718,9 +6212,9 @@
 			u32 convert_c = c;
 
 			if (v & 0x2000) {
-				avs2_print(dec, 0,
+				avs2_print(dec, AVS2_DBG_HDR_INFO,
 					"video_signal_type present:\n");
-				avs2_print(dec, 0,
+				avs2_print(dec, AVS2_DBG_HDR_INFO,
 					" %s %s\n",
 					video_format_names[(v >> 10) & 7],
 					((v >> 9) & 1) ?
@@ -5729,21 +6223,21 @@
 					u32 transfer;
 					u32 maxtrix;
 
-					avs2_print(dec, 0,
+					avs2_print(dec, AVS2_DBG_HDR_INFO,
 						"color_description present:\n");
-					avs2_print(dec, 0,
+					avs2_print(dec, AVS2_DBG_HDR_INFO,
 						"color_primarie = %d\n",
 						v & 0xff);
-					avs2_print(dec, 0,
+					avs2_print(dec, AVS2_DBG_HDR_INFO,
 						"transfer_characteristic = %d\n",
 						(c >> 8) & 0xff);
-					avs2_print(dec, 0,
+					avs2_print(dec, AVS2_DBG_HDR_INFO,
 						"  matrix_coefficient = %d\n",
 						c & 0xff);
 
 					transfer = (c >> 8) & 0xFF;
 					if (transfer >= 15)
-						avs2_print(dec, 0,
+						avs2_print(dec, AVS2_DBG_HDR_INFO,
 							"unsupport transfer_characteristic\n");
 					else if (transfer  == 14)
 						transfer = 18; /* HLG */
@@ -5756,7 +6250,7 @@
 
 					maxtrix = c & 0xFF;
 					if (maxtrix >= 10)
-						avs2_print(dec, 0,
+						avs2_print(dec, AVS2_DBG_HDR_INFO,
 							"unsupport matrix_coefficient\n");
 					else if (maxtrix == 9)
 						maxtrix = 10;
@@ -5765,7 +6259,7 @@
 
 					convert_c = (transfer << 8) | (maxtrix);
 
-					avs2_print(dec, 0,
+					avs2_print(dec, AVS2_DBG_HDR_INFO,
 						" convered c:0x%x\n",
 						convert_c);
 				}
@@ -5824,34 +6318,58 @@
 		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
-#ifdef AVS2_10B_MMU
+
 		if (ret >= 0) {
-			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",
+#ifdef AVS2_10B_MMU
+			if (dec->mmu_enable) {
+				ret = avs2_alloc_mmu(dec,
 					dec->avs2_dec.hc.cur_pic->index,
-					ret);
-		}
+					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->
+		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(
@@ -5880,7 +6398,8 @@
 			 ret);
 			WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_10B_DISCARD_NAL);
 	#ifdef AVS2_10B_MMU
-			avs2_recycle_mmu_buf(dec);
+			if (dec->mmu_enable)
+				avs2_recycle_mmu_buf(dec);
 	#endif
 			if (dec->m_ins_flag) {
 				dec->dec_result = DEC_RESULT_DONE;
@@ -6075,10 +6594,10 @@
 	return IRQ_WAKE_THREAD;
 }
 
-static void vavs2_put_timer_func(unsigned long arg)
+static void vavs2_put_timer_func(struct timer_list *timer)
 {
-	struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)arg;
-	struct timer_list *timer = &dec->timer;
+	struct AVS2Decoder_s *dec = container_of(timer,
+		struct AVS2Decoder_s, timer);
 	uint8_t empty_flag;
 	unsigned int buf_level;
 
@@ -6196,6 +6715,7 @@
 	}
 	if (debug & AVS2_DBG_DUMP_RPM_BUF) {
 		int i;
+
 		pr_info("RPM:\n");
 		for (i = 0; i < RPM_BUF_SIZE; i += 4) {
 			int ii;
@@ -6212,6 +6732,7 @@
 	}
 	if (debug & AVS2_DBG_DUMP_LMEM_BUF) {
 		int i;
+
 		pr_info("LMEM:\n");
 		for (i = 0; i < LMEM_BUF_SIZE; i += 4) {
 			int ii;
@@ -6407,6 +6928,7 @@
 
 	WRITE_VREG(DECODE_STOP_POS, udebug_flag);
 
+	config_cuva_buf(dec);
 }
 
 #ifdef I_ONLY_SUPPORT
@@ -6495,7 +7017,8 @@
 	int fw_size = 0x1000 * 16;
 	struct firmware_s *fw = NULL;
 	struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)vdec->private;
-	init_timer(&dec->timer);
+
+	timer_setup(&dec->timer, vavs2_put_timer_func, 0);
 
 	dec->stat |= STAT_TIMER_INIT;
 	if (vavs2_local_init(dec) < 0)
@@ -6517,8 +7040,6 @@
 	fw->len = fw_size;
 
 	if (dec->m_ins_flag) {
-		dec->timer.data = (ulong) dec;
-		dec->timer.function = vavs2_put_timer_func;
 		dec->timer.expires = jiffies + PUT_INTERVAL;
 
 		/*add_timer(&dec->timer);
@@ -6531,7 +7052,9 @@
 
 		return 0;
 	}
+
 	amhevc_enable();
+
 	ret = amhevc_loadmc_ex(VFORMAT_AVS2, NULL, fw->data);
 	if (ret < 0) {
 		amhevc_disable();
@@ -6574,11 +7097,7 @@
 	}
 	dec->stat |= STAT_VF_HOOK;
 
-	dec->timer.data = (ulong)dec;
-	dec->timer.function = vavs2_put_timer_func;
 	dec->timer.expires = jiffies + PUT_INTERVAL;
-
-
 	add_timer(&dec->timer);
 
 	dec->stat |= STAT_TIMER_ARM;
@@ -6670,17 +7189,32 @@
 		CODEC_MM_FLAGS_TVP : 0;
 	int buf_size = 48;
 
-#ifdef AVS2_10B_MMU
 	dec->need_cache_size = buf_size * SZ_1M;
 	dec->sc_start_time = get_jiffies_64();
-	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;
+#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(
@@ -6701,15 +7235,19 @@
 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 BUF_s BUF[MAX_BUF_NUM];*/
 	struct AVS2Decoder_s *dec = &gAVS2Decoder;
 	int ret;
 	pr_info("%s\n", __func__);
-	mutex_lock(&vavs2_mutex);
 
-	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 = 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;
@@ -6728,6 +7266,14 @@
 	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");
@@ -6763,6 +7309,12 @@
 	}
 	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;*/
@@ -6808,32 +7360,16 @@
 }
 
 /****************************************/
-#ifdef CONFIG_PM
-static int avs2_suspend(struct device *dev)
-{
-	amhevc_suspend(to_platform_device(dev), dev->power.power_state);
-	return 0;
-}
-
-static int avs2_resume(struct device *dev)
-{
-	amhevc_resume(to_platform_device(dev));
-	return 0;
-}
-
-static const struct dev_pm_ops avs2_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(avs2_suspend, avs2_resume)
-};
-#endif
 
 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,
-#ifdef CONFIG_PM
-		.pm = &avs2_pm_ops,
-#endif
 	}
 };
 
@@ -7001,8 +7537,8 @@
 		decode_frame_count[dec->index] = dec->frame_count;
 
 #ifdef AVS2_10B_MMU
-		dec->used_4k_num =
-			(READ_VREG(HEVC_SAO_MMU_STATUS) >> 16);
+		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",
@@ -7376,7 +7912,7 @@
 
 	for (i = 0; i < MAX_BUF_NUM; i++) {
 		avs2_print(dec, 0,
-			"mv_Buf(%d) start_adr 0x%lx size 0x%x used %d\n",
+			"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,
@@ -7465,12 +8001,18 @@
 	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 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;
@@ -7478,8 +8020,7 @@
 	/*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 = vmalloc(sizeof(struct AVS2Decoder_s));
-	memset(dec, 0, sizeof(struct AVS2Decoder_s));
+	dec = vzalloc(sizeof(struct AVS2Decoder_s));
 	if (dec == NULL) {
 		pr_info("\nammvdec_avs2 device data allocation failed\n");
 		return -ENOMEM;
@@ -7503,12 +8044,26 @@
 	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);
+	/*
+	 * 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);
@@ -7538,9 +8093,8 @@
 	dec->video_ori_signal_type = 0;
 	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TXLX)
 		dec->stat |= VP9_TRIGGER_FRAME_ENABLE;
-#if 1
-	if ((debug & IGNORE_PARAM_FROM_CONFIG) == 0 &&
-			pdata->config_len) {
+
+	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",
@@ -7601,9 +8155,7 @@
 					| (9 << 0);	/* 2020 */
 		}
 		dec->vf_dp = vf_dp;
-	} else
-#endif
-	{
+	} else {
 		/*dec->vavs2_amstream_dec_info.width = 0;
 		dec->vavs2_amstream_dec_info.height = 0;
 		dec->vavs2_amstream_dec_info.rate = 30;*/
@@ -7612,10 +8164,21 @@
 	}
 	video_signal_type = dec->video_signal_type;
 
-#if 0
-	dec->buf_start = pdata->mem_start;
-	dec->buf_size = pdata->mem_end - pdata->mem_start + 1;
-#else
+	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); */
@@ -7634,7 +8197,7 @@
 	}
 	dec->buf_start = dec->cma_alloc_addr;
 	dec->buf_size = work_buf_size;
-#endif
+
 	dec->init_flag = 0;
 	dec->first_sc_checked = 0;
 	dec->fatal_error = 0;
@@ -7656,6 +8219,12 @@
 		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");
@@ -7684,6 +8253,8 @@
 	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)
@@ -7704,11 +8275,21 @@
 		}
 	}
 
+	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;
@@ -7717,11 +8298,12 @@
 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,
-#ifdef CONFIG_PM
-		.pm = &avs2_pm_ops,
-#endif
 	}
 };
 #endif
@@ -7767,16 +8349,22 @@
 {
 
 #ifdef AVS2_10B_MMU
-
 	struct BuffInfo_s *p_buf_info;
 
-	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];
+	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 =
@@ -7803,10 +8391,10 @@
 		return -ENODEV;
 	}
 
-	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
-		amvdec_avs2_profile.profile =
-				"8k, 10bit, dwrite, compressed";
-	} else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
+	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";
@@ -7814,7 +8402,9 @@
 			amvdec_avs2_profile.profile =
 				"10bit, dwrite, compressed";
 	} else {
-		amvdec_avs2_profile.name = "avs2_unsupport";
+		/* cpu id larger than sm1 support 8k */
+		amvdec_avs2_profile.profile =
+				"8k, 10bit, dwrite, compressed";
 	}
 
 	vcodec_profile_register(&amvdec_avs2_profile);
@@ -7824,6 +8414,7 @@
 
 	INIT_REG_NODE_CONFIGS("media.decoder", &avs2_node,
 		"avs2", avs2_configs, CONFIG_FOR_RW);
+	vcodec_feature_register(VFORMAT_AVS2, 0);
 
 	return 0;
 }
diff --git a/drivers/frame_provider/decoder/avs2/vavs2.h b/drivers/frame_provider/decoder/avs2/vavs2.h
index 6b51f61..071bfb3 100644
--- a/drivers/frame_provider/decoder/avs2/vavs2.h
+++ b/drivers/frame_provider/decoder/avs2/vavs2.h
@@ -19,7 +19,7 @@
 #define VAVS2_H
 
 #define AVS2_10B_MMU
-#define MV_USE_FIXED_BUF
+#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);
diff --git a/drivers/frame_provider/decoder/avs_multi/avs_multi.c b/drivers/frame_provider/decoder/avs_multi/avs_multi.c
index 38e39d0..7dd20bb 100644
--- a/drivers/frame_provider/decoder/avs_multi/avs_multi.c
+++ b/drivers/frame_provider/decoder/avs_multi/avs_multi.c
@@ -44,6 +44,7 @@
 #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
 /*
@@ -123,9 +124,6 @@
 
 #define DECODE_CFG            AV_SCRATCH_K
 
-
-
-
 #define VF_POOL_SIZE        64
 #define PUT_INTERVAL        (HZ/100)
 
@@ -153,7 +151,7 @@
 #define DEBUG_REG2	AV_SCRATCH_D
 
 
-static void check_timer_func(unsigned long arg);
+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
@@ -1272,35 +1270,35 @@
 
 		} else {
 #ifdef NV21
-			canvas_config(canvas_base + canvas_num * i + 0,
+			config_cav_lut_ex(canvas_base + canvas_num * i + 0,
 					buf_start,
 					canvas_width, canvas_height,
 					CANVAS_ADDR_NOWRAP,
-					CANVAS_BLKMODE_32X32);
-			canvas_config(canvas_base + canvas_num * i + 1,
+					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);
+					CANVAS_BLKMODE_32X32, 0, VDEC_1);
 #else
-			canvas_config(canvas_num * i + 0,
+			config_cav_lut_ex(canvas_num * i + 0,
 					buf_start,
 					canvas_width, canvas_height,
 					CANVAS_ADDR_NOWRAP,
-					CANVAS_BLKMODE_32X32);
-			canvas_config(canvas_num * i + 1,
+					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);
-			canvas_config(canvas_num * i + 2,
+					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);
+					CANVAS_BLKMODE_32X32, 0, VDEC_1);
 #endif
 			debug_print(hw, PRINT_FLAG_VFRAME_DETAIL,
 				"canvas config %d, addr %p\n", i,
@@ -1392,6 +1390,7 @@
 #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);
@@ -1601,21 +1600,21 @@
 			vavs_restore_regs(hw);
 
 		for (i = 0; i < hw->vf_buf_num_used; i++) {
-			canvas_config_ex(canvas_y(hw->canvas_spec[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);
+				0, VDEC_1);
 
-			canvas_config_ex(canvas_u(hw->canvas_spec[i]),
+			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);
+				0, VDEC_1);
 		}
 	} else {
 		r = vavs_canvas_init(hw);
@@ -1695,6 +1694,7 @@
 #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);
@@ -1938,9 +1938,10 @@
 #ifdef DEBUG_MULTI_WITH_AUTOMODE
 int delay_count = 0;
 #endif
-static void vavs_put_timer_func(unsigned long arg)
+static void vavs_put_timer_func(struct timer_list *arg)
 {
-	struct vdec_avs_hw_s *hw = (struct vdec_avs_hw_s *)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
@@ -2215,9 +2216,10 @@
 	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;
+		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;
 
 
@@ -2287,8 +2289,9 @@
 
 	hw->stat |= STAT_VF_HOOK;
 
-	hw->recycle_timer.data = (ulong)(hw);
-	hw->recycle_timer.function = vavs_put_timer_func;
+	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);
@@ -2510,7 +2513,7 @@
 }
 
 /****************************************/
-#ifdef DEBUG_WITH_SINGLE_MODE
+#if 0
 static struct platform_driver amvdec_avs_driver = {
 	.probe = amvdec_avs_probe,
 	.remove = amvdec_avs_remove,
@@ -2519,6 +2522,7 @@
 	}
 };
 #endif
+
 static void recycle_frames(struct vdec_avs_hw_s *hw);
 
 static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
@@ -2527,7 +2531,6 @@
 	(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])
@@ -2849,9 +2852,10 @@
 }
 
 
-static void check_timer_func(unsigned long arg)
+static void check_timer_func(struct timer_list *timer)
 {
-	struct vdec_avs_hw_s *hw = (struct vdec_avs_hw_s *)arg;
+	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;
@@ -3191,8 +3195,8 @@
 		"%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);
 
+	WRITE_VREG(VIFF_BIT_CNT, size * 8);
 	if (hw->reset_decode_flag)
 		WRITE_VREG(DECODE_STATUS, 0);
 	else {
@@ -3835,7 +3839,6 @@
 #endif
 }
 
-
 static irqreturn_t vmavs_isr(struct vdec_s *vdec, int irq)
 {
 
@@ -4375,21 +4378,21 @@
 			vavs_restore_regs(hw);
 
 		for (i = 0; i < hw->vf_buf_num_used; i++) {
-			canvas_config_ex(canvas_y(hw->canvas_spec[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);
+				0, VDEC_1);
 
-			canvas_config_ex(canvas_u(hw->canvas_spec[i]),
+			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);
+				0, VDEC_1);
 		}
 	}
 }
@@ -4449,6 +4452,8 @@
 #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);
 
@@ -4862,6 +4867,8 @@
 		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+";
@@ -4869,6 +4876,7 @@
 	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;
 }
 
@@ -4981,7 +4989,6 @@
 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");
 
diff --git a/drivers/frame_provider/decoder/h264/vh264.c b/drivers/frame_provider/decoder/h264/vh264.c
index 03a1dba..55f0581 100644
--- a/drivers/frame_provider/decoder/h264/vh264.c
+++ b/drivers/frame_provider/decoder/h264/vh264.c
@@ -23,7 +23,6 @@
 #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>
@@ -38,7 +37,6 @@
 #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"
@@ -46,19 +44,17 @@
 #include "../../../stream_input/amports/streambuf.h"
 #include <linux/delay.h>
 #include <linux/amlogic/media/video_sink/video.h>
-#include <linux/amlogic/tee.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 <linux/amlogic/tee.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"
@@ -160,7 +156,7 @@
 
 static void vh264_prot_init(void);
 static int vh264_local_init(void);
-static void vh264_put_timer_func(unsigned long arg);
+static void vh264_put_timer_func(struct timer_list *timer);
 static void stream_switching_done(void);
 
 static const char vh264_dec_id[] = "vh264-dev";
@@ -253,14 +249,6 @@
 #endif
 static u32 enable_userdata_debug;
 
-/* if not define, must clear AV_SCRATCH_J in isr when
- * ITU_T35 code enabled in ucode, otherwise may fatal
- * error repeatly.
- */
-//#define ENABLE_SEI_ITU_T35
-
-
-
 static unsigned int enable_switch_fense = 1;
 #define EN_SWITCH_FENCE() (enable_switch_fense && !is_4k)
 static struct vframe_qos_s s_vframe_qos;
@@ -472,15 +460,15 @@
 	int endian;
 
 	endian = (canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0;
-	canvas_config_ex(spec->y_canvas_index,
+	config_cav_lut_ex(spec->y_canvas_index,
 			spec->y_addr,
 			width, height,
-			CANVAS_ADDR_NOWRAP, canvas_mode, endian);
+			CANVAS_ADDR_NOWRAP, canvas_mode, endian, VDEC_1);
 
-	canvas_config_ex(spec->u_canvas_index,
+	config_cav_lut_ex(spec->u_canvas_index,
 			spec->u_addr,
 			width, height / 2,
-			CANVAS_ADDR_NOWRAP, canvas_mode, endian);
+			CANVAS_ADDR_NOWRAP, canvas_mode, endian, VDEC_1);
 
 }
 
@@ -2208,16 +2196,16 @@
 				buffer_spec[i].v_canvas_height = mb_height << 4;
 
 				endian = (canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0;
-				canvas_config_ex(128 + i * 2,
+				config_cav_lut_ex(128 + i * 2,
 						buffer_spec[i].y_addr,
 						mb_width << 4, mb_height << 4,
 						CANVAS_ADDR_NOWRAP,
-						canvas_mode, endian);
-				canvas_config_ex(128 + i * 2 + 1,
+						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);
+						canvas_mode, endian, VDEC_1);
 				WRITE_VREG(ANC0_CANVAS_ADDR + i,
 						spec2canvas(&buffer_spec[i]));
 				} else {
@@ -2599,7 +2587,6 @@
 	gvs->ratio_control = ratio_control;
 }
 
-
 #ifdef HANDLE_H264_IRQ
 static irqreturn_t vh264_isr(int irq, void *dev_id)
 #else
@@ -3348,9 +3335,8 @@
 			frame_width, frame_height, fps);
 }
 
-static void vh264_put_timer_func(unsigned long arg)
+static void vh264_put_timer_func(struct timer_list *timer)
 {
-	struct timer_list *timer = (struct timer_list *)arg;
 	unsigned int wait_buffer_status;
 	unsigned int wait_i_pass_frames;
 	unsigned int reg_val;
@@ -3800,7 +3786,7 @@
 	int firmwareloaded = 0;
 
 	/* pr_info("\nvh264_init\n"); */
-	init_timer(&recycle_timer);
+	timer_setup(&recycle_timer, vh264_put_timer_func, 0);
 
 	stat |= STAT_TIMER_INIT;
 
@@ -3992,10 +3978,7 @@
 
 	stat |= STAT_VF_HOOK;
 
-	recycle_timer.data = (ulong) &recycle_timer;
-	recycle_timer.function = vh264_put_timer_func;
 	recycle_timer.expires = jiffies + PUT_INTERVAL;
-
 	add_timer(&recycle_timer);
 
 	stat |= STAT_TIMER_ARM;
@@ -4224,17 +4207,17 @@
 			canvas_read(y_index, &csy);
 			canvas_read(u_index, &csu);
 
-			canvas_config(fense_buffer_spec[i].y_canvas_index,
+			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);
-			canvas_config(fense_buffer_spec[i].u_canvas_index,
+				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);
+				CANVAS_BLKMODE_LINEAR, 0, VDEC_1);
 
 			y_desindex = fense_buffer_spec[i].y_canvas_index;
 			u_desindex = fense_buffer_spec[i].u_canvas_index;
@@ -4351,8 +4334,6 @@
 	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);
@@ -4395,32 +4376,16 @@
 }
 
 /****************************************/
-#ifdef CONFIG_PM
-static int h264_suspend(struct device *dev)
-{
-	amvdec_suspend(to_platform_device(dev), dev->power.power_state);
-	return 0;
-}
-
-static int h264_resume(struct device *dev)
-{
-	amvdec_resume(to_platform_device(dev));
-	return 0;
-}
-
-static const struct dev_pm_ops h264_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(h264_suspend, h264_resume)
-};
-#endif
 
 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,
-#ifdef CONFIG_PM
-		.pm = &h264_pm_ops,
-#endif
 	}
 };
 
@@ -4460,7 +4425,8 @@
 		return -ENODEV;
 	}
 	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXTVBB
-		&& (codec_mm_get_total_size() > 80 * SZ_1M)) {
+		&& (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);
@@ -4490,7 +4456,7 @@
 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");
+		"\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");
diff --git a/drivers/frame_provider/decoder/h264/vh264_4k2k.c b/drivers/frame_provider/decoder/h264/vh264_4k2k.c
deleted file mode 100644
index 44465ad..0000000
--- a/drivers/frame_provider/decoder/h264/vh264_4k2k.c
+++ /dev/null
@@ -1,1808 +0,0 @@
-/*
- * drivers/amlogic/amports/vh264_4k2k.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/timer.h>
-#include <linux/kfifo.h>
-#include <linux/platform_device.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/delay.h>
-
-#include <linux/amlogic/media/codec_mm/codec_mm.h>
-#include <linux/amlogic/media/video_sink/video_keeper.h>
-#include "../utils/firmware.h"
-#include <linux/amlogic/tee.h>
-#include "../../../common/chips/decoder_cpu_ver_info.h"
-
-
-
-#define MEM_NAME "codec_264_4k"
-
-/* #include <mach/am_regs.h> */
-#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
-
-#include <linux/amlogic/media/vpu/vpu.h>
-#endif
-
-#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>
-
-
-
-#if  0 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6TVD */
-#define DOUBLE_WRITE
-#endif
-
-#define DRIVER_NAME "amvdec_h264_4k2k"
-#define MODULE_NAME "amvdec_h264_4k2k"
-
-#define PUT_INTERVAL        (HZ/100)
-#define ERROR_RESET_COUNT   500
-#define DECODE_BUFFER_NUM_MAX    32
-#define DISPLAY_BUFFER_NUM       6
-#define MAX_BMMU_BUFFER_NUM	(DECODE_BUFFER_NUM_MAX + DISPLAY_BUFFER_NUM)
-#define VF_BUFFER_IDX(n) (2  + n)
-#define DECODER_WORK_SPACE_SIZE 0x800000
-
-#if  1 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV */
-#define H264_4K2K_SINGLE_CORE 1
-#else
-#define H264_4K2K_SINGLE_CORE   IS_MESON_M8M2_CPU
-#endif
-
-#define SLICE_TYPE_I 2
-
-static int vh264_4k2k_vf_states(struct vframe_states *states, void *);
-static struct vframe_s *vh264_4k2k_vf_peek(void *);
-static struct vframe_s *vh264_4k2k_vf_get(void *);
-static void vh264_4k2k_vf_put(struct vframe_s *, void *);
-static int vh264_4k2k_event_cb(int type, void *data, void *private_data);
-
-static void vh264_4k2k_prot_init(void);
-static int vh264_4k2k_local_init(void);
-static void vh264_4k2k_put_timer_func(unsigned long arg);
-
-static const char vh264_4k2k_dec_id[] = "vh264_4k2k-dev";
-static const char vh264_4k2k_dec_id2[] = "vh264_4k2k-vdec2-dev";
-
-#define PROVIDER_NAME   "decoder.h264_4k2k"
-
-static const struct vframe_operations_s vh264_4k2k_vf_provider = {
-	.peek = vh264_4k2k_vf_peek,
-	.get = vh264_4k2k_vf_get,
-	.put = vh264_4k2k_vf_put,
-	.event_cb = vh264_4k2k_event_cb,
-	.vf_states = vh264_4k2k_vf_states,
-};
-static void *mm_blk_handle;
-static struct vframe_provider_s vh264_4k2k_vf_prov;
-
-static u32 mb_width_old, mb_height_old;
-static u32 frame_width, frame_height, frame_dur, frame_ar;
-static u32 saved_resolution;
-static struct timer_list recycle_timer;
-static u32 stat;
-static u32 error_watchdog_count;
-static uint error_recovery_mode;
-static u32 sync_outside;
-static u32 vh264_4k2k_rotation;
-static u32 first_i_received;
-static struct vframe_s *p_last_vf;
-static struct work_struct set_clk_work;
-
-#ifdef DEBUG_PTS
-static unsigned long pts_missed, pts_hit;
-#endif
-
-static struct dec_sysinfo vh264_4k2k_amstream_dec_info;
-static dma_addr_t mc_dma_handle;
-static void *mc_cpu_addr;
-
-#define AMVDEC_H264_4K2K_CANVAS_INDEX 0x80
-#define AMVDEC_H264_4K2K_CANVAS_MAX 0xc6
-static DEFINE_SPINLOCK(lock);
-static int fatal_error;
-
-static atomic_t vh264_4k2k_active = ATOMIC_INIT(0);
-
-static DEFINE_MUTEX(vh264_4k2k_mutex);
-
-static void (*probe_callback)(void);
-static void (*remove_callback)(void);
-static struct device *cma_dev;
-
-/* 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 MAILBOX_DATA_3          AV_SCRATCH_4
-#define MAILBOX_DATA_4          AV_SCRATCH_5
-#define CANVAS_START            AV_SCRATCH_6
-#define BUFFER_RECYCLE          AV_SCRATCH_7
-#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 MS_ID                   AV_SCRATCH_D
-#define WORKSPACE_START         AV_SCRATCH_E
-#define DECODED_PIC_NUM         AV_SCRATCH_F
-#define DECODE_ERROR_CNT        AV_SCRATCH_G
-#define CURRENT_UCODE           AV_SCRATCH_H
-/* bit[15:9]-SPS, bit[8:0]-PPS */
-#define CURRENT_SPS_PPS         AV_SCRATCH_I
-#define DECODE_SKIP_PICTURE     AV_SCRATCH_J
-#define DECODE_MODE             AV_SCRATCH_K
-#define RESERVED_REG_L          AV_SCRATCH_L
-#define REF_START_VIEW_0        AV_SCRATCH_M
-#define REF_START_VIEW_1        AV_SCRATCH_N
-
-#define VDEC2_MAILBOX_COMMAND         VDEC2_AV_SCRATCH_0
-#define VDEC2_MAILBOX_DATA_0          VDEC2_AV_SCRATCH_1
-#define VDEC2_MAILBOX_DATA_1          VDEC2_AV_SCRATCH_2
-#define VDEC2_MAILBOX_DATA_2          VDEC2_AV_SCRATCH_3
-#define VDEC2_MAILBOX_DATA_3          VDEC2_AV_SCRATCH_4
-#define VDEC2_MAILBOX_DATA_4          VDEC2_AV_SCRATCH_5
-#define VDEC2_CANVAS_START            VDEC2_AV_SCRATCH_6
-#define VDEC2_BUFFER_RECYCLE          VDEC2_AV_SCRATCH_7
-#define VDEC2_PICTURE_COUNT           VDEC2_AV_SCRATCH_9
-#define VDEC2_DECODE_STATUS           VDEC2_AV_SCRATCH_A
-#define VDEC2_SPS_STATUS              VDEC2_AV_SCRATCH_B
-#define VDEC2_PPS_STATUS              VDEC2_AV_SCRATCH_C
-#define VDEC2_MS_ID                   VDEC2_AV_SCRATCH_D
-#define VDEC2_WORKSPACE_START         VDEC2_AV_SCRATCH_E
-#define VDEC2_DECODED_PIC_NUM         VDEC2_AV_SCRATCH_F
-#define VDEC2_DECODE_ERROR_CNT        VDEC2_AV_SCRATCH_G
-#define VDEC2_CURRENT_UCODE           VDEC2_AV_SCRATCH_H
-/* bit[15:9]-SPS, bit[8:0]-PPS */
-#define VDEC2_CURRENT_SPS_PPS         VDEC2_AV_SCRATCH_I
-#define VDEC2_DECODE_SKIP_PICTURE     VDEC2_AV_SCRATCH_J
-#define VDEC2_RESERVED_REG_K          VDEC2_AV_SCRATCH_K
-#define VDEC2_RESERVED_REG_L          VDEC2_AV_SCRATCH_L
-#define VDEC2_REF_START_VIEW_0        VDEC2_AV_SCRATCH_M
-#define VDEC2_REF_START_VIEW_1        VDEC2_AV_SCRATCH_N
-
-/********************************************
- *  DECODE_STATUS Define
- *******************************************
- */
-#define DECODE_IDLE             0
-#define DECODE_START_HEADER     1
-#define DECODE_HEADER           2
-#define DECODE_START_MMCO       3
-#define DECODE_MMCO             4
-#define DECODE_START_SLICE      5
-#define DECODE_SLICE            6
-#define DECODE_WAIT_BUFFER      7
-
-/********************************************
- *  Dual Core Communication
- ********************************************
- */
-#define FATAL_ERROR             DOS_SCRATCH16
-#define PRE_MASTER_UPDATE_TIMES DOS_SCRATCH20
-/* bit[31] - REQUEST */
-/* bit[30:0] - MASTER_UPDATE_TIMES */
-#define SLAVE_WAIT_DPB_UPDATE   DOS_SCRATCH21
-/* [15:8] - current_ref, [7:0] current_dpb (0x80 means no buffer found) */
-#define SLAVE_REF_DPB           DOS_SCRATCH22
-#define SAVE_MVC_ENTENSION_0    DOS_SCRATCH23
-#define SAVE_I_POC              DOS_SCRATCH24
-/* bit[31:30] - core_status 0-idle, 1-mmco, 2-decoding, 3-finished */
-/* bit[29:0] - core_pic_count */
-#define CORE_STATUS_M           DOS_SCRATCH25
-#define CORE_STATUS_S           DOS_SCRATCH26
-#define SAVE_ref_status_view_0  DOS_SCRATCH27
-#define SAVE_ref_status_view_1  DOS_SCRATCH28
-#define ALLOC_INFO_0            DOS_SCRATCH29
-#define ALLOC_INFO_1            DOS_SCRATCH30
-
-/********************************************
- *  Mailbox command
- ********************************************/
-#define CMD_FINISHED               0
-#define CMD_ALLOC_VIEW             1
-#define CMD_FRAME_DISPLAY          3
-#define CMD_DEBUG                  10
-
-#define MC_TOTAL_SIZE           (28*SZ_1K)
-#define MC_SWAP_SIZE            (4*SZ_1K)
-
-static unsigned long work_space_adr, ref_start_addr;
-static unsigned long reserved_buffer;
-
-
-#define video_domain_addr(adr) (adr&0x7fffffff)
-
-
-struct buffer_spec_s {
-	unsigned int y_addr;
-	unsigned int uv_addr;
-#ifdef DOUBLE_WRITE
-	unsigned int y_dw_addr;
-	unsigned int uv_dw_addr;
-#endif
-
-	int y_canvas_index;
-	int uv_canvas_index;
-#ifdef DOUBLE_WRITE
-	int y_dw_canvas_index;
-	int uv_dw_canvas_index;
-#endif
-
-	struct page *alloc_pages;
-	unsigned long phy_addr;
-	int alloc_count;
-};
-
-static struct buffer_spec_s buffer_spec[MAX_BMMU_BUFFER_NUM];
-
-#ifdef DOUBLE_WRITE
-#define spec2canvas(x)  \
-	(((x)->uv_dw_canvas_index << 16) | \
-	 ((x)->uv_dw_canvas_index << 8)  | \
-	 ((x)->y_dw_canvas_index << 0))
-#else
-#define spec2canvas(x)  \
-	(((x)->uv_canvas_index << 16) | \
-	 ((x)->uv_canvas_index << 8)  | \
-	 ((x)->y_canvas_index << 0))
-#endif
-
-#define VF_POOL_SIZE        32
-
-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 s32 vfbuf_use[DECODE_BUFFER_NUM_MAX];
-static struct vframe_s vfpool[VF_POOL_SIZE];
-
-static struct work_struct alloc_work;
-static struct vdec_info *gvs;
-
-static void set_frame_info(struct vframe_s *vf)
-{
-	unsigned int ar;
-
-#ifdef DOUBLE_WRITE
-	vf->width = frame_width / 2;
-	vf->height = frame_height / 2;
-#else
-	vf->width = frame_width;
-	vf->height = frame_height;
-#endif
-	vf->duration = frame_dur;
-	vf->duration_pulldown = 0;
-	vf->flag = 0;
-
-	ar = min_t(u32, frame_ar, DISP_RATIO_ASPECT_RATIO_MAX);
-	vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT);
-	vf->orientation = vh264_4k2k_rotation;
-
-}
-
-static int vh264_4k2k_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;
-}
-
-static struct vframe_s *vh264_4k2k_vf_peek(void *op_arg)
-{
-	struct vframe_s *vf;
-
-	if (kfifo_peek(&display_q, &vf))
-		return vf;
-
-	return NULL;
-}
-
-static struct vframe_s *vh264_4k2k_vf_get(void *op_arg)
-{
-	struct vframe_s *vf;
-
-	if (kfifo_get(&display_q, &vf))
-		return vf;
-
-	return NULL;
-}
-
-static void vh264_4k2k_vf_put(struct vframe_s *vf, void *op_arg)
-{
-	kfifo_put(&recycle_q, (const struct vframe_s *)vf);
-}
-
-static int vh264_4k2k_event_cb(int type, void *data, void *private_data)
-{
-	if (type & VFRAME_EVENT_RECEIVER_RESET) {
-		unsigned long flags;
-
-		amvdec_stop();
-
-		if (!H264_4K2K_SINGLE_CORE)
-			amvdec2_stop();
-#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
-		vf_light_unreg_provider(&vh264_4k2k_vf_prov);
-#endif
-		spin_lock_irqsave(&lock, flags);
-		vh264_4k2k_local_init();
-		vh264_4k2k_prot_init();
-		spin_unlock_irqrestore(&lock, flags);
-#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
-		vf_reg_provider(&vh264_4k2k_vf_prov);
-#endif
-		amvdec_start();
-
-		if (!H264_4K2K_SINGLE_CORE)
-			amvdec2_start();
-	}
-
-	return 0;
-}
-
-static int init_canvas(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, ret = -1;
-	int mb_total;
-	int canvas_addr = ANC0_CANVAS_ADDR;
-	int vdec2_canvas_addr = VDEC2_ANC0_CANVAS_ADDR;
-	int index = AMVDEC_H264_4K2K_CANVAS_INDEX;
-
-	mb_total = mb_width * mb_height;
-	mutex_lock(&vh264_4k2k_mutex);
-
-	for (j = 0; j < (dpb_number + 1); j++) {
-		int page_count;
-		if (j == 0) {
-			ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, 1,
-				refbuf_size, DRIVER_NAME, &ref_start_addr);
-			if (ret < 0) {
-				mutex_unlock(&vh264_4k2k_mutex);
-				return ret;
-			}
-		continue;
-	}
-
-	WRITE_VREG(canvas_addr++, index | ((index + 1) << 8) |
-			((index + 1) << 16));
-	if (!H264_4K2K_SINGLE_CORE) {
-		WRITE_VREG(vdec2_canvas_addr++,
-			index | ((index + 1) << 8) |
-			((index + 1) << 16));
-	}
-
-	i = j - 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,
-			VF_BUFFER_IDX(i), page_count << PAGE_SHIFT,
-				DRIVER_NAME, &buffer_spec[i].phy_addr);
-
-			if (ret < 0) {
-				buffer_spec[i].alloc_count = 0;
-				mutex_unlock(&vh264_4k2k_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;
-		canvas_config(index,
-				addr,
-				mb_width << 4,
-				mb_height << 4,
-				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
-
-		addr += mb_total << 8;
-		index++;
-
-		buffer_spec[i].uv_addr = addr;
-		buffer_spec[i].uv_canvas_index = index;
-		canvas_config(index,
-				addr,
-				mb_width << 4,
-				mb_height << 3,
-				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
-
-		addr += mb_total << 7;
-		index++;
-
-#ifdef DOUBLE_WRITE
-		buffer_spec[i].y_dw_addr = addr;
-		buffer_spec[i].y_dw_canvas_index = index;
-		canvas_config(index,
-				addr,
-				mb_width << 3,
-				mb_height << 3,
-				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
-
-		addr += mb_total << 6;
-		index++;
-
-		buffer_spec[i].uv_dw_addr = addr;
-		buffer_spec[i].uv_dw_canvas_index = index;
-		canvas_config(index,
-				addr,
-				mb_width << 3,
-				mb_height << 2,
-				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
-
-		index++;
-#endif
-	}
-
-	mutex_unlock(&vh264_4k2k_mutex);
-
-	pr_info
-	("H264 4k2k decoder canvas allocation successful, ");
-
-	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:
-	case 52:
-	default:
-		size = 70778880;
-		break;
-	}
-
-	size /= pic_size;
-	size = size + 1;	/* need one 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;
-}
-
-static void do_alloc_work(struct work_struct *work)
-{
-	int level_idc, max_reference_frame_num, mb_width, mb_height,
-		frame_mbs_only_flag;
-	int dpb_size, ref_size, refbuf_size;
-	int max_dec_frame_buffering,
-		total_dec_frame_buffering;
-	unsigned int chroma444;
-	unsigned int crop_infor, crop_bottom, crop_right;
-	int ret = READ_VREG(MAILBOX_COMMAND);
-
-
-	ret = READ_VREG(MAILBOX_DATA_0);
-	/*  MAILBOX_DATA_1 :
-	 *	bit15    : frame_mbs_only_flag
-	 *	bit 0-7 : chroma_format_idc
-	 *    MAILBOX_DATA_2:
-	 *	bit31-16: (left << 8 | right ) << 1
-	 *	bit15-0 : (top << 8  | bottom ) <<  (2 - frame_mbs_only_flag)
-	 */
-	frame_mbs_only_flag = READ_VREG(MAILBOX_DATA_1);
-	crop_infor = READ_VREG(MAILBOX_DATA_2);
-	level_idc = (ret >> 24) & 0xff;
-	max_reference_frame_num = (ret >> 16) & 0xff;
-	mb_width = (ret >> 8) & 0xff;
-	if (mb_width == 0)
-		mb_width = 256;
-	mb_height = (ret >> 0) & 0xff;
-	max_dec_frame_buffering =
-		get_max_dec_frame_buf_size(level_idc, max_reference_frame_num,
-				mb_width, mb_height);
-	total_dec_frame_buffering =
-		max_dec_frame_buffering + DISPLAY_BUFFER_NUM;
-
-	chroma444 = ((frame_mbs_only_flag&0xffff) == 3) ? 1 : 0;
-	frame_mbs_only_flag = (frame_mbs_only_flag >> 16) & 0x01;
-	crop_bottom = (crop_infor & 0xff) >> (2 - frame_mbs_only_flag);
-	crop_right = ((crop_infor >> 16) & 0xff) >> 1;
-	pr_info("crop_right = 0x%x crop_bottom = 0x%x chroma_format_idc = 0x%x\n",
-		crop_right, crop_bottom, chroma444);
-
-	if ((frame_width == 0) || (frame_height == 0) || crop_infor ||
-		mb_width != mb_width_old ||
-		mb_height != mb_height_old) {
-		frame_width = mb_width << 4;
-		frame_height = mb_height << 4;
-		mb_width_old = mb_width;
-		mb_height_old = mb_height;
-		if (frame_mbs_only_flag) {
-			frame_height -= (2 >> chroma444) *
-				min(crop_bottom,
-				    (unsigned int)((8 << chroma444) - 1));
-			frame_width -= (2 >> chroma444) *
-				min(crop_right,
-				    (unsigned int)((8 << chroma444) - 1));
-		} else {
-			frame_height -= (4 >> chroma444) *
-				min(crop_bottom,
-				    (unsigned int)((8 << chroma444) - 1));
-			frame_width -= (4 >> chroma444) *
-				min(crop_right,
-				    (unsigned int)((8 << chroma444) - 1));
-		}
-		pr_info("frame_mbs_only_flag %d, crop_bottom %d frame_height %d, mb_height %d crop_right %d, frame_width %d, mb_width %d\n",
-			frame_mbs_only_flag, crop_bottom, frame_height,
-			mb_height, crop_right, frame_width, mb_height);
-	}
-
-	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;
-
-
-	pr_info("mb_width=%d, mb_height=%d\n",
-	 mb_width, mb_height);
-
-	ret = init_canvas(refbuf_size,  dpb_size,
-			total_dec_frame_buffering, mb_width, mb_height,
-			buffer_spec);
-
-	if (ret == -1) {
-		pr_info(" Un-expected memory alloc problem\n");
-		return;
-	}
-
-	if (frame_width == 0)
-		frame_width = mb_width << 4;
-	if (frame_height == 0)
-		frame_height = mb_height << 4;
-
-	WRITE_VREG(REF_START_VIEW_0, video_domain_addr(ref_start_addr));
-	if (!H264_4K2K_SINGLE_CORE) {
-		WRITE_VREG(VDEC2_REF_START_VIEW_0,
-				   video_domain_addr(ref_start_addr));
-	}
-
-	WRITE_VREG(MAILBOX_DATA_0,
-			(max_dec_frame_buffering << 8) |
-			(total_dec_frame_buffering << 0));
-	WRITE_VREG(MAILBOX_DATA_1, ref_size);
-	WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED);
-
-	/* ///////////// FAKE FIRST PIC */
-
-}
-
-static irqreturn_t vh264_4k2k_isr(int irq, void *dev_id)
-{
-	int drop_status, display_buff_id, display_POC, slice_type, error;
-	unsigned int stream_offset;
-	struct vframe_s *vf = NULL;
-	int ret = READ_VREG(MAILBOX_COMMAND);
-	u32 frame_size;
-
-	switch (ret & 0xff) {
-	case CMD_ALLOC_VIEW:
-		schedule_work(&alloc_work);
-		break;
-
-	case CMD_FRAME_DISPLAY:
-		ret >>= 8;
-		display_buff_id = (ret >> 0) & 0x3f;
-		drop_status = (ret >> 8) & 0x1;
-		slice_type = (ret >> 9) & 0x7;
-		error = (ret >> 12) & 0x1;
-		display_POC = READ_VREG(MAILBOX_DATA_0);
-		stream_offset = READ_VREG(MAILBOX_DATA_1);
-
-		smp_rmb();/* rmb smp */
-
-		WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED);
-
-		if (kfifo_get(&newframe_q, &vf) == 0) {
-			pr_info("fatal error, no available buffer slot.");
-			return IRQ_HANDLED;
-		}
-
-		if (vf) {
-			vfbuf_use[display_buff_id]++;
-
-			vf->pts = 0;
-			vf->pts_us64 = 0;
-
-			if ((!sync_outside)
-				|| (sync_outside &&
-					(slice_type == SLICE_TYPE_I))) {
-				ret = pts_lookup_offset_us64(PTS_TYPE_VIDEO,
-							stream_offset,
-							&vf->pts,
-							&frame_size,
-							0,
-							&vf->pts_us64);
-				if (ret != 0)
-					pr_debug(" vpts lookup failed\n");
-			}
-#ifdef H264_4K2K_SINGLE_CORE
-			if (READ_VREG(DECODE_MODE) & 1) {
-				/* for I only mode, ignore the PTS information
-				 *   and only uses 10fps for each
-				 *   I frame decoded
-				 */
-				if (p_last_vf) {
-					vf->pts = 0;
-					vf->pts_us64 = 0;
-				}
-				frame_dur = 96000 / 10;
-			}
-#endif
-			vf->signal_type = 0;
-			vf->index = display_buff_id;
-			vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
-			vf->type |= VIDTYPE_VIU_NV21;
-			vf->canvas0Addr = vf->canvas1Addr =
-				spec2canvas(&buffer_spec[display_buff_id]);
-			set_frame_info(vf);
-
-			if (error)
-				gvs->drop_frame_count++;
-
-			gvs->frame_dur = frame_dur;
-			vdec_count_info(gvs, error, stream_offset);
-
-			if (((error_recovery_mode & 2) && error)
-				|| (!first_i_received
-					&& (slice_type != SLICE_TYPE_I))) {
-				kfifo_put(&recycle_q,
-						  (const struct vframe_s *)vf);
-			} else {
-				p_last_vf = vf;
-				first_i_received = 1;
-				vf->mem_handle =
-				decoder_bmmu_box_get_mem_handle(
-					mm_blk_handle,
-					VF_BUFFER_IDX(display_buff_id));
-				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);
-			}
-		}
-		break;
-
-	case CMD_DEBUG:
-		pr_info("M: core_status 0x%08x 0x%08x; ",
-			   READ_VREG(CORE_STATUS_M), READ_VREG(CORE_STATUS_S));
-		switch (READ_VREG(MAILBOX_DATA_0)) {
-		case 1:
-			pr_info("H264_BUFFER_INFO_INDEX = 0x%x\n",
-				   READ_VREG(MAILBOX_DATA_1));
-			WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 2:
-			pr_info("H264_BUFFER_INFO_DATA = 0x%x\n",
-				   READ_VREG(MAILBOX_DATA_1));
-			WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 3:
-			pr_info("REC_CANVAS_ADDR = 0x%x\n",
-				   READ_VREG(MAILBOX_DATA_1));
-			WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 4:
-			pr_info("after DPB_MMCO\n");
-			WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 5:
-			pr_info("MBY = 0x%x, S_MBXY = 0x%x\n",
-					READ_VREG(MAILBOX_DATA_1),
-					READ_VREG(0x2c07));
-			WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 6:
-			pr_info("after FIFO_OUT_FRAME\n");
-			WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 7:
-			pr_info("after RELEASE_EXCEED_REF_BUFF\n");
-			WRITE_VREG(MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 0x5a:
-			pr_info("\n");
-			break;
-		default:
-			pr_info("\n");
-			break;
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	return IRQ_HANDLED;
-}
-
-#if 1 /*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8*/
-static irqreturn_t vh264_4k2k_vdec2_isr(int irq, void *dev_id)
-{
-	int ret = READ_VREG(VDEC2_MAILBOX_COMMAND);
-
-	switch (ret & 0xff) {
-	case CMD_DEBUG:
-		pr_info("S: core_status 0x%08x 0x%08x; ",
-			   READ_VREG(CORE_STATUS_M), READ_VREG(CORE_STATUS_S));
-		switch (READ_VREG(VDEC2_MAILBOX_DATA_0)) {
-		case 1:
-			pr_info("H264_BUFFER_INFO_INDEX = 0x%x\n",
-				   READ_VREG(VDEC2_MAILBOX_DATA_1));
-			WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 2:
-			pr_info("H264_BUFFER_INFO_DATA = 0x%x\n",
-				   READ_VREG(VDEC2_MAILBOX_DATA_1));
-			WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 3:
-			pr_info("REC_CANVAS_ADDR = 0x%x\n",
-				   READ_VREG(VDEC2_MAILBOX_DATA_1));
-			WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 4:
-			pr_info("after DPB_MMCO\n");
-			WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 5:
-			pr_info("MBY = 0x%x, M/S_MBXY = 0x%x-0x%x\n",
-				   READ_VREG(VDEC2_MAILBOX_DATA_1),
-				   READ_VREG(0xc07), READ_VREG(0x2c07));
-			WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 6:
-			pr_info("after FIFO_OUT_FRAME\n");
-			WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 7:
-			pr_info("after RELEASE_EXCEED_REF_BUFF\n");
-			WRITE_VREG(VDEC2_MAILBOX_COMMAND, CMD_FINISHED);
-			break;
-		case 0x5a:
-			pr_info("\n");
-			break;
-		default:
-			pr_info("\n");
-			break;
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	return IRQ_HANDLED;
-}
-#endif
-
-static void vh264_4k2k_set_clk(struct work_struct *work)
-{
-	if (first_i_received &&/*do switch after first i frame ready.*/
-		frame_dur > 0 && saved_resolution !=
-		frame_width * frame_height * (96000 / frame_dur)) {
-		int fps = 96000 / frame_dur;
-
-		pr_info("H264 4k2k resolution changed!!\n");
-		if (vdec_source_changed(VFORMAT_H264_4K2K,
-			frame_width, frame_height, fps) > 0)/*changed clk ok*/
-			saved_resolution = frame_width * frame_height * fps;
-	}
-}
-
-static void vh264_4k2k_put_timer_func(unsigned long arg)
-{
-	struct timer_list *timer = (struct timer_list *)arg;
-	enum receviver_start_e state = RECEIVER_INACTIVE;
-
-	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))
-			state = RECEIVER_INACTIVE;
-	} else
-		state = RECEIVER_INACTIVE;
-
-	/* error watchdog */
-	if (((READ_VREG(VLD_MEM_VIFIFO_CONTROL) & 0x100) == 0) &&/* dec has in*/
-		(state == RECEIVER_INACTIVE) &&	/* rec has no buf to recycle */
-		(kfifo_is_empty(&display_q)) &&	/* no buf in display queue */
-		(kfifo_is_empty(&recycle_q)) &&	/* no buf to recycle */
-		(READ_VREG(MS_ID) & 0x100)
-#ifdef CONFIG_H264_2K4K_SINGLE_CORE
-		&& (READ_VREG(VDEC2_MS_ID) & 0x100)
-
-/*  with both decoder
- *						      have started decoding
- */
-#endif
-		&& first_i_received) {
-		if (++error_watchdog_count == ERROR_RESET_COUNT) {
-			/* and it lasts for a while */
-			pr_info("H264 4k2k decoder fatal error watchdog.\n");
-			fatal_error = DECODER_FATAL_ERROR_UNKNOWN;
-		}
-	} else
-		error_watchdog_count = 0;
-
-	if (READ_VREG(FATAL_ERROR) != 0) {
-		pr_info("H264 4k2k decoder ucode fatal error.\n");
-		fatal_error = DECODER_FATAL_ERROR_UNKNOWN;
-		WRITE_VREG(FATAL_ERROR, 0);
-	}
-
-	while (!kfifo_is_empty(&recycle_q) &&
-			(READ_VREG(BUFFER_RECYCLE) == 0)) {
-		struct vframe_s *vf;
-
-		if (kfifo_get(&recycle_q, &vf)) {
-			if ((vf->index < DECODE_BUFFER_NUM_MAX)
-					&& (--vfbuf_use[vf->index] == 0)) {
-				WRITE_VREG(BUFFER_RECYCLE, vf->index + 1);
-				vf->index = DECODE_BUFFER_NUM_MAX;
-			}
-
-			kfifo_put(&newframe_q, (const struct vframe_s *)vf);
-		}
-	}
-
-	schedule_work(&set_clk_work);
-
-	timer->expires = jiffies + PUT_INTERVAL;
-
-	add_timer(timer);
-}
-
-int vh264_4k2k_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 = 0;
-	vstatus->status = stat | fatal_error;
-	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 vh264_4k2k_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_4k2k_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
-{
-	if (trickmode == TRICKMODE_I) {
-		WRITE_VREG(DECODE_MODE, 1);
-		trickmode_i = 1;
-	} else if (trickmode == TRICKMODE_NONE) {
-		WRITE_VREG(DECODE_MODE, 0);
-		trickmode_i = 0;
-	}
-
-	return 0;
-}
-
-static void H264_DECODE_INIT(void)
-{
-	int i;
-
-	WRITE_VREG(GCLK_EN, 0x3ff);
-
-	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);
-
-	/* 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);
-	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 */
-	WRITE_VREG(ASSIST_AMR1_INT8, 0x15);	/* vififo_empty */
-
-	/* 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));
-	WRITE_VREG(POWER_CTL_VLD, (1 << 10) |	/* disable cabac_step_2 */
-			   (1 << 9) |	/* viff_drop_flag_en */
-			   (1 << 6));	/* h264_000003_en */
-	WRITE_VREG(M4_CONTROL_REG, (1 << 13));	/* H264_DECODE_INFO - h264_en */
-
-	WRITE_VREG(CANVAS_START, AMVDEC_H264_4K2K_CANVAS_INDEX);
-	/* Start Address of Workspace (UCODE, temp_data...) */
-	WRITE_VREG(WORKSPACE_START,
-			   video_domain_addr(work_space_adr));
-	/* 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 H264_DECODE2_INIT(void)
-{
-	int i;
-
-	WRITE_VREG(VDEC2_GCLK_EN, 0x3ff);
-
-	WRITE_VREG(DOS_SW_RESET2, (1 << 7) | (1 << 6) | (1 << 4));
-	WRITE_VREG(DOS_SW_RESET2, 0);
-
-	READ_VREG(DOS_SW_RESET2);
-	READ_VREG(DOS_SW_RESET2);
-	READ_VREG(DOS_SW_RESET2);
-
-	WRITE_VREG(DOS_SW_RESET2, (1 << 7) | (1 << 6) | (1 << 4));
-	WRITE_VREG(DOS_SW_RESET2, 0);
-
-	WRITE_VREG(DOS_SW_RESET2, (1 << 9) | (1 << 8));
-	WRITE_VREG(DOS_SW_RESET2, 0);
-
-	READ_VREG(DOS_SW_RESET2);
-	READ_VREG(DOS_SW_RESET2);
-	READ_VREG(DOS_SW_RESET2);
-
-	/* fill_weight_pred */
-	WRITE_VREG(VDEC2_MC_MPORT_CTRL, 0x0300);
-	for (i = 0; i < 192; i++)
-		WRITE_VREG(VDEC2_MC_MPORT_DAT, 0x100);
-	WRITE_VREG(VDEC2_MC_MPORT_CTRL, 0);
-
-	WRITE_VREG(VDEC2_MB_WIDTH, 0xff);	/* invalid mb_width */
-
-	/* set slice start to 0x000000 or 0x000001 for check more_rbsp_data */
-	WRITE_VREG(VDEC2_SLICE_START_BYTE_01, 0x00000000);
-	WRITE_VREG(VDEC2_SLICE_START_BYTE_23, 0x01010000);
-	/* set to mpeg2 to enable mismatch logic */
-	WRITE_VREG(VDEC2_MPEG1_2_REG, 1);
-	/* disable COEF_GT_64 , error_m4_table and voff_rw_err */
-	WRITE_VREG(VDEC2_VLD_ERROR_MASK,
-			   0x1011);
-
-	/* Config MCPU Amrisc interrupt */
-	WRITE_VREG(VDEC2_ASSIST_AMR1_INT0, 0x1);/* viu_vsync_int */
-	WRITE_VREG(VDEC2_ASSIST_AMR1_INT1, 0x5);/* mbox_isr */
-	WRITE_VREG(VDEC2_ASSIST_AMR1_INT2, 0x8);/* vld_isr */
-	/* WRITE_VREG(VDEC2_ASSIST_AMR1_INT3, 0x15); // vififo_empty */
-	WRITE_VREG(VDEC2_ASSIST_AMR1_INT4, 0xd);/* rv_ai_mb_finished_int */
-	WRITE_VREG(VDEC2_ASSIST_AMR1_INT7, 0x14);/* dcac_dma_done */
-	WRITE_VREG(VDEC2_ASSIST_AMR1_INT8, 0x15);/* vififo_empty */
-
-	/* Config MCPU Amrisc interrupt */
-	WRITE_VREG(VDEC2_ASSIST_AMR1_INT5, 0x9);/* MCPU interrupt */
-	WRITE_VREG(VDEC2_ASSIST_AMR1_INT6, 0x17);/* CCPU interrupt */
-
-	WRITE_VREG(VDEC2_CPC_P, 0xc00);	/* CCPU Code will start from 0xc00 */
-	WRITE_VREG(VDEC2_CINT_VEC_BASE, (0xc20 >> 5));
-	WRITE_VREG(VDEC2_POWER_CTL_VLD, (1 << 10) |/* disable cabac_step_2 */
-			   (1 << 9) |	/* viff_drop_flag_en */
-			   (1 << 6));	/* h264_000003_en */
-	/* H264_DECODE_INFO - h264_en */
-	WRITE_VREG(VDEC2_M4_CONTROL_REG, (1 << 13));
-
-	WRITE_VREG(VDEC2_CANVAS_START, AMVDEC_H264_4K2K_CANVAS_INDEX);
-	/* Start Address of Workspace (UCODE, temp_data...) */
-	WRITE_VREG(VDEC2_WORKSPACE_START,
-			video_domain_addr(work_space_adr));
-	/* Clear all sequence parameter set available */
-	WRITE_VREG(VDEC2_SPS_STATUS, 0);
-	/* Clear all picture parameter set available */
-	WRITE_VREG(VDEC2_PPS_STATUS, 0);
-	/* Set current microcode to NULL */
-	WRITE_VREG(VDEC2_CURRENT_UCODE, 0xff);
-	/* Set current SPS/PPS to NULL */
-	WRITE_VREG(VDEC2_CURRENT_SPS_PPS, 0xffff);
-	/* Set decode status to DECODE_START_HEADER */
-	WRITE_VREG(VDEC2_DECODE_STATUS, 1);
-}
-
-static void vh264_4k2k_prot_init(void)
-{
-	/* clear mailbox interrupt */
-#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
-	if (!H264_4K2K_SINGLE_CORE)
-		WRITE_VREG(VDEC2_ASSIST_MBOX0_CLR_REG, 1);
-#endif
-	WRITE_VREG(VDEC_ASSIST_MBOX1_CLR_REG, 1);
-
-	/* enable mailbox interrupt */
-#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
-	if (!H264_4K2K_SINGLE_CORE)
-		WRITE_VREG(VDEC2_ASSIST_MBOX0_MASK, 1);
-#endif
-	WRITE_VREG(VDEC_ASSIST_MBOX1_MASK, 1);
-
-	/* disable PSCALE for hardware sharing */
-	WRITE_VREG(PSCALE_CTRL, 0);
-
-	H264_DECODE_INIT();
-	if (!H264_4K2K_SINGLE_CORE)
-		H264_DECODE2_INIT();
-
-	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);
-
-	if (!H264_4K2K_SINGLE_CORE) {
-		WRITE_VREG(DOS_SW_RESET2, (1 << 11));
-		WRITE_VREG(DOS_SW_RESET2, 0);
-
-		READ_VREG(DOS_SW_RESET2);
-		READ_VREG(DOS_SW_RESET2);
-		READ_VREG(DOS_SW_RESET2);
-	}
-
-	WRITE_VREG(MAILBOX_COMMAND, 0);
-	WRITE_VREG(BUFFER_RECYCLE, 0);
-
-	if (!H264_4K2K_SINGLE_CORE) {
-		WRITE_VREG(VDEC2_MAILBOX_COMMAND, 0);
-		WRITE_VREG(VDEC2_BUFFER_RECYCLE, 0);
-	}
-
-	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17);
-	if (!H264_4K2K_SINGLE_CORE)
-		CLEAR_VREG_MASK(VDEC2_MDEC_PIC_DC_CTRL, 1 << 17);
-
-	/* set VDEC Master/ID 0 */
-	WRITE_VREG(MS_ID, (1 << 7) | (0 << 0));
-	if (!H264_4K2K_SINGLE_CORE) {
-		/* set VDEC2 Slave/ID 0 */
-		WRITE_VREG(VDEC2_MS_ID, (0 << 7) | (1 << 0));
-	}
-	WRITE_VREG(DECODE_SKIP_PICTURE, 0);
-	if (!H264_4K2K_SINGLE_CORE)
-		WRITE_VREG(VDEC2_DECODE_SKIP_PICTURE, 0);
-
-	WRITE_VREG(PRE_MASTER_UPDATE_TIMES, 0);
-	WRITE_VREG(SLAVE_WAIT_DPB_UPDATE, 0);
-	WRITE_VREG(SLAVE_REF_DPB, 0);
-	WRITE_VREG(SAVE_MVC_ENTENSION_0, 0);
-	WRITE_VREG(SAVE_I_POC, 0);
-	WRITE_VREG(CORE_STATUS_M, 0);
-	WRITE_VREG(CORE_STATUS_S, 0);
-	WRITE_VREG(SAVE_ref_status_view_0, 0);
-	WRITE_VREG(SAVE_ref_status_view_1, 0);
-	WRITE_VREG(ALLOC_INFO_0, 0);
-	WRITE_VREG(ALLOC_INFO_1, 0);
-	WRITE_VREG(FATAL_ERROR, 0);
-
-	SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17);
-	if (!H264_4K2K_SINGLE_CORE)
-		SET_VREG_MASK(VDEC2_MDEC_PIC_DC_CTRL, 1 << 17);
-
-	WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa);
-	if (!H264_4K2K_SINGLE_CORE) {
-		WRITE_VREG(VDEC2_MDEC_PIC_DC_THRESH, 0x404038aa);
-	}
-#ifdef DOUBLE_WRITE
-	WRITE_VREG(MDEC_DOUBLEW_CFG0, (0 << 31) |	/* half y address */
-			   (1 << 30) |	/* 0:No Merge 1:Automatic Merge */
-			   (0 << 28) |
-
-/*  Field Picture, 0x:no skip
- *					   10:top only
- *					   11:bottom only
- */
-			   (0 << 27) |	/* Source from, 1:MCW 0:DBLK */
-			   (0 << 24) |	/* Endian Control for Chroma */
-			   (0 << 18) |	/* DMA ID */
-			   (0 << 12) |	/* DMA Burst Number */
-			   (0 << 11) |	/* DMA Urgent */
-			   (0 << 10) |	/* 1:Round 0:Truncation */
-			   (1 << 9) |
-
-/*  Size by vertical,   0:original size
- *					   1: 1/2 shrunken size
- */
-			   (1 << 8) |
-
-/*  Size by horizontal, 0:original size
- *					   1: 1/2 shrunken size
- */
-			   (0 << 6) |
-
-/*  Pixel sel by vertical,   0x:1/2
- *					   10:up
- *					   11:down
- */
-			   (0 << 4) |
-
-/*  Pixel sel by horizontal, 0x:1/2
- *					   10:left
- *					   11:right
- */
-			   (0 << 1) |	/* Endian Control for Luma */
-			   (1 << 0));	/* Double Write Enable */
-	if (!H264_4K2K_SINGLE_CORE) {
-		WRITE_VREG(VDEC2_MDEC_DOUBLEW_CFG0,
-				(0 << 31) |	/* half y address */
-				   (1 << 30) |
-
-/*  0:No Merge
- *						   1:Automatic Merge
- */
-				   (0 << 28) |
-
-/*  Field Picture, 0x:no skip
- *						   10:top only
- *						   11:bottom only
- */
-				   (0 << 27) |	/* Source from, 1:MCW 0:DBLK */
-				   (0 << 24) |	/* Endian Control for Chroma */
-				   (0 << 18) |	/* DMA ID */
-				   (0 << 12) |	/* DMA Burst Number */
-				   (0 << 11) |	/* DMA Urgent */
-				   (0 << 10) |	/* 1:Round 0:Truncation */
-				   (1 << 9) |
-
-/*  Size by vertical,
- *						   0:original size
- *						   1: 1/2 shrunken size
- */
-				   (1 << 8) |
-
-/*  Size by horizontal,
- *						   0:original size
- *						   1: 1/2 shrunken size
- */
-				   (0 << 6) |
-
-/*  Pixel sel by vertical,
- *						   0x:1/2
- *						   10:up
- *						   11:down
- */
-				   (0 << 4) |
-
-/*  Pixel sel by horizontal,
- *						   0x:1/2
- *						   10:left
- *						   11:right
- */
-				   (0 << 1) |	/* Endian Control for Luma */
-				   (1 << 0));	/* Double Write Enable */
-	}
-#endif
-}
-
-static int vh264_4k2k_local_init(void)
-{
-	int i, size, ret;
-
-#ifdef DEBUG_PTS
-	pts_missed = 0;
-	pts_hit = 0;
-#endif
-	mb_width_old = 0;
-	mb_height_old = 0;
-	saved_resolution = 0;
-	vh264_4k2k_rotation =
-		(((unsigned long) vh264_4k2k_amstream_dec_info.param) >> 16)
-			& 0xffff;
-	frame_width = vh264_4k2k_amstream_dec_info.width;
-	frame_height = vh264_4k2k_amstream_dec_info.height;
-	frame_dur =
-		(vh264_4k2k_amstream_dec_info.rate ==
-		 0) ? 3600 : vh264_4k2k_amstream_dec_info.rate;
-	if (frame_width && frame_height)
-		frame_ar = frame_height * 0x100 / frame_width;
-	sync_outside = ((unsigned long) vh264_4k2k_amstream_dec_info.param
-			& 0x02) >> 1;
-	error_watchdog_count = 0;
-
-	pr_info("H264_4K2K: decinfo: %dx%d rate=%d\n",
-			frame_width, frame_height,
-			frame_dur);
-
-	if (frame_dur == 0)
-		frame_dur = 96000 / 24;
-
-	INIT_KFIFO(display_q);
-	INIT_KFIFO(recycle_q);
-	INIT_KFIFO(newframe_q);
-
-	for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++)
-		vfbuf_use[i] = 0;
-
-	for (i = 0; i < VF_POOL_SIZE; i++) {
-		const struct vframe_s *vf = &vfpool[i];
-
-		vfpool[i].index = DECODE_BUFFER_NUM_MAX;
-		kfifo_put(&newframe_q, vf);
-	}
-
-	reserved_buffer = 0;
-	p_last_vf = NULL;
-	first_i_received = 0;
-	INIT_WORK(&alloc_work, do_alloc_work);
-
-	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);
-
-	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 vh264_4k2k_init(void)
-{
-	int ret = -1, size = -1;
-	char *buf = vmalloc(0x1000 * 16);
-
-	if (buf == NULL)
-		return -ENOMEM;
-
-	pr_info("\nvh264_4k2k_init\n");
-
-	init_timer(&recycle_timer);
-
-	stat |= STAT_TIMER_INIT;
-
-	ret = vh264_4k2k_local_init();
-	if (ret < 0) {
-		vfree(buf);
-		return ret;
-	}
-	amvdec_enable();
-
-	/* -- 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_4k2k init: Can not allocate mc memory.\n");
-		return -ENOMEM;
-	}
-
-	WRITE_VREG(AV_SCRATCH_L, mc_dma_handle);
-	if (!H264_4K2K_SINGLE_CORE)
-		WRITE_VREG(VDEC2_AV_SCRATCH_L, mc_dma_handle);
-
-	if (H264_4K2K_SINGLE_CORE)
-		size = get_firmware_data(VIDEO_DEC_H264_4k2K_SINGLE, buf);
-	else
-		size = get_firmware_data(VIDEO_DEC_H264_4k2K, buf);
-
-	if (size < 0) {
-		pr_err("get firmware fail.");
-		vfree(buf);
-		return -1;
-	}
-
-	if (H264_4K2K_SINGLE_CORE)
-		ret = amvdec_loadmc_ex(VFORMAT_H264_4K2K, "single_core", buf);
-	else
-		ret = amvdec_loadmc_ex(VFORMAT_H264_4K2K, NULL, buf);
-
-	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;
-		pr_err("H264_4K2K: the %s fw loading failed, err: %x\n",
-			tee_enabled() ? "TEE" : "local", ret);
-		return -EBUSY;
-	}
-
-	if (!H264_4K2K_SINGLE_CORE) {
-		amvdec2_enable();
-
-		if (amvdec2_loadmc_ex(VFORMAT_H264_4K2K, NULL, buf) < 0) {
-			amvdec_disable();
-			amvdec2_disable();
-			dma_free_coherent(amports_get_dma_device(),
-				MC_TOTAL_SIZE, mc_cpu_addr, mc_dma_handle);
-			mc_cpu_addr = NULL;
-			return -EBUSY;
-		}
-	}
-
-	/*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);
-
-	stat |= STAT_MC_LOAD;
-
-	/* enable AMRISC side protocol */
-	vh264_4k2k_prot_init();
-
-	if (vdec_request_irq(VDEC_IRQ_1, vh264_4k2k_isr,
-			"vh264_4k2k-irq", (void *)vh264_4k2k_dec_id)) {
-		pr_info("vh264_4k2k irq register error.\n");
-		amvdec_disable();
-		if (!H264_4K2K_SINGLE_CORE)
-			amvdec2_disable();
-
-		return -ENOENT;
-	}
-#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
-	if (!H264_4K2K_SINGLE_CORE) {
-		if (vdec_request_irq(VDEC_IRQ_0, vh264_4k2k_vdec2_isr,
-				"vh264_4k2k-vdec2-irq",
-				(void *)vh264_4k2k_dec_id2)) {
-			pr_info("vh264_4k2k irq register error.\n");
-			vdec_free_irq(VDEC_IRQ_1, (void *)vh264_4k2k_dec_id);
-			amvdec_disable();
-			amvdec2_disable();
-			return -ENOENT;
-		}
-	}
-#endif
-
-	stat |= STAT_ISR_REG;
-
-	vf_provider_init(&vh264_4k2k_vf_prov, PROVIDER_NAME,
-					 &vh264_4k2k_vf_provider, NULL);
-	vf_reg_provider(&vh264_4k2k_vf_prov);
-	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL);
-
-	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT,
-			(void *)((unsigned long)
-			vh264_4k2k_amstream_dec_info.rate));
-
-	stat |= STAT_VF_HOOK;
-
-	recycle_timer.data = (ulong) (&recycle_timer);
-	recycle_timer.function = vh264_4k2k_put_timer_func;
-	recycle_timer.expires = jiffies + PUT_INTERVAL;
-
-	add_timer(&recycle_timer);
-
-	stat |= STAT_TIMER_ARM;
-
-	amvdec_start();
-	if (!H264_4K2K_SINGLE_CORE)
-		amvdec2_start();
-
-	stat |= STAT_VDEC_RUN;
-
-	ret = vh264_4k2k_vdec_info_init();
-	if (0 != ret)
-		return -ret;
-
-	return 0;
-}
-
-static int vh264_4k2k_stop(void)
-{
-
-	if (stat & STAT_VDEC_RUN) {
-		amvdec_stop();
-		if (!H264_4K2K_SINGLE_CORE)
-			amvdec2_stop();
-		stat &= ~STAT_VDEC_RUN;
-	}
-
-	if (stat & STAT_ISR_REG) {
-		WRITE_VREG(VDEC_ASSIST_MBOX1_MASK, 0);
-		if (!H264_4K2K_SINGLE_CORE)
-			WRITE_VREG(VDEC2_ASSIST_MBOX0_MASK, 0);
-
-		vdec_free_irq(VDEC_IRQ_1, (void *)vh264_4k2k_dec_id);
-#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
-		if (!H264_4K2K_SINGLE_CORE)
-			vdec_free_irq(VDEC_IRQ_0, (void *)vh264_4k2k_dec_id2);
-#endif
-		stat &= ~STAT_ISR_REG;
-	}
-
-	if (stat & STAT_TIMER_ARM) {
-		del_timer_sync(&recycle_timer);
-		stat &= ~STAT_TIMER_ARM;
-	}
-
-	if (stat & STAT_VF_HOOK) {
-		vf_notify_receiver(PROVIDER_NAME,
-				VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL);
-
-		vf_unreg_provider(&vh264_4k2k_vf_prov);
-		stat &= ~STAT_VF_HOOK;
-	}
-#ifdef DOUBLE_WRITE
-	WRITE_VREG(MDEC_DOUBLEW_CFG0, 0);
-	if (!H264_4K2K_SINGLE_CORE)
-		WRITE_VREG(VDEC2_MDEC_DOUBLEW_CFG0, 0);
-#endif
-
-	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 (!H264_4K2K_SINGLE_CORE)
-		amvdec2_disable();
-#ifdef CONFIG_AMLOGIC_MEDIA_VSYNC_RDMA
-	msleep(100);
-#endif
-	if (mm_blk_handle) {
-		decoder_bmmu_box_free(mm_blk_handle);
-		mm_blk_handle = NULL;
-	}
-
-	return 0;
-}
-
-void vh264_4k_free_cmabuf(void)
-{
-	int i;
-
-	if (atomic_read(&vh264_4k2k_active))
-		return;
-	mutex_lock(&vh264_4k2k_mutex);
-	for (i = 0; i < ARRAY_SIZE(buffer_spec); i++) {
-		if (buffer_spec[i].phy_addr) {
-			codec_mm_free_for_dma(MEM_NAME,
-				buffer_spec[i].phy_addr);
-			buffer_spec[i].phy_addr = 0;
-			buffer_spec[i].alloc_pages = NULL;
-			buffer_spec[i].alloc_count = 0;
-			pr_info("force free CMA buffer %d\n", i);
-		}
-	}
-	mutex_unlock(&vh264_4k2k_mutex);
-}
-
-static int amvdec_h264_4k2k_probe(struct platform_device *pdev)
-{
-	struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
-
-	pr_info("amvdec_h264_4k2k probe start.\n");
-
-	mutex_lock(&vh264_4k2k_mutex);
-
-	fatal_error = 0;
-
-	if (pdata == NULL) {
-		pr_info("\namvdec_h264_4k2k memory resource undefined.\n");
-		mutex_unlock(&vh264_4k2k_mutex);
-		return -EFAULT;
-	}
-
-	if (pdata->sys_info)
-		vh264_4k2k_amstream_dec_info = *pdata->sys_info;
-	cma_dev = pdata->cma_dev;
-
-	pr_info("                   sysinfo: %dx%d, rate = %d, param = 0x%lx\n",
-		   vh264_4k2k_amstream_dec_info.width,
-		   vh264_4k2k_amstream_dec_info.height,
-		   vh264_4k2k_amstream_dec_info.rate,
-		   (unsigned long) vh264_4k2k_amstream_dec_info.param);
-
-	if (!H264_4K2K_SINGLE_CORE) {
-		if (vdec_on(VDEC_2)) {	/* ++++ */
-			vdec_poweroff(VDEC_2);	/* ++++ */
-			mdelay(10);
-		}
-		vdec_poweron(VDEC_2);
-	}
-
-
-	if (!H264_4K2K_SINGLE_CORE)
-		vdec2_power_mode(1);
-
-	pdata->dec_status = vh264_4k2k_dec_status;
-	if (H264_4K2K_SINGLE_CORE)
-		pdata->set_trickmode = vh264_4k2k_set_trickmode;
-
-	if (vh264_4k2k_init() < 0) {
-		pr_info("\namvdec_h264_4k2k init failed.\n");
-		mutex_unlock(&vh264_4k2k_mutex);
-		kfree(gvs);
-		gvs = NULL;
-
-		return -ENODEV;
-	}
-#if 1/*MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8*/
-	request_vpu_clk_vmod(360000000, VPU_VIU_VD1);
-#endif
-
-	if (probe_callback)
-		probe_callback();
-	/*set the max clk for smooth playing...*/
-		vdec_source_changed(VFORMAT_H264_4K2K,
-				4096, 2048, 30);
-	INIT_WORK(&set_clk_work, vh264_4k2k_set_clk);
-
-	atomic_set(&vh264_4k2k_active, 1);
-	mutex_unlock(&vh264_4k2k_mutex);
-
-	return 0;
-}
-
-static int amvdec_h264_4k2k_remove(struct platform_device *pdev)
-{
-	cancel_work_sync(&alloc_work);
-	cancel_work_sync(&set_clk_work);
-	mutex_lock(&vh264_4k2k_mutex);
-	atomic_set(&vh264_4k2k_active, 0);
-
-	vh264_4k2k_stop();
-
-	vdec_source_changed(VFORMAT_H264_4K2K, 0, 0, 0);
-
-	if (!H264_4K2K_SINGLE_CORE) {
-		vdec_poweroff(VDEC_2);
-	}
-#ifdef DEBUG_PTS
-	pr_info("pts missed %ld, pts hit %ld, duration %d\n",
-		   pts_missed, pts_hit, frame_dur);
-#endif
-
-	if (remove_callback)
-		remove_callback();
-
-	mutex_unlock(&vh264_4k2k_mutex);
-
-	kfree(gvs);
-	gvs = NULL;
-
-	pr_info("amvdec_h264_4k2k_remove\n");
-	return 0;
-}
-
-void vh264_4k2k_register_module_callback(void (*enter_func)(void),
-		void (*remove_func)(void))
-{
-	probe_callback = enter_func;
-	remove_callback = remove_func;
-}
-EXPORT_SYMBOL(vh264_4k2k_register_module_callback);
-
-/****************************************/
-
-static struct platform_driver amvdec_h264_4k2k_driver = {
-	.probe = amvdec_h264_4k2k_probe,
-	.remove = amvdec_h264_4k2k_remove,
-#ifdef CONFIG_PM
-	.suspend = amvdec_suspend,
-	.resume = amvdec_resume,
-#endif
-	.driver = {
-		.name = DRIVER_NAME,
-	}
-};
-
-static struct codec_profile_t amvdec_h264_4k2k_profile = {
-	.name = "h264_4k2k",
-	.profile = ""
-};
-static struct mconfig h264_4k2k_configs[] = {
-	MC_PU32("stat", &stat),
-	MC_PU32("error_recovery_mode", &error_recovery_mode),
-};
-static struct mconfig_node h264_4k2k_node;
-
-static int __init amvdec_h264_4k2k_driver_init_module(void)
-{
-	pr_debug("amvdec_h264_4k2k module init\n");
-
-	if (platform_driver_register(&amvdec_h264_4k2k_driver)) {
-		pr_err("failed to register amvdec_h264_4k2k driver\n");
-		return -ENODEV;
-	}
-	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXTVBB)
-		vcodec_profile_register(&amvdec_h264_4k2k_profile);
-	INIT_REG_NODE_CONFIGS("media.decoder", &h264_4k2k_node,
-		"h264_4k2k", h264_4k2k_configs, CONFIG_FOR_RW);
-	return 0;
-}
-
-static void __exit amvdec_h264_4k2k_driver_remove_module(void)
-{
-	pr_debug("amvdec_h264_4k2k module remove.\n");
-
-	platform_driver_unregister(&amvdec_h264_4k2k_driver);
-}
-
-/****************************************/
-
-module_param(stat, uint, 0664);
-MODULE_PARM_DESC(stat, "\n amvdec_h264_4k2k stat\n");
-
-module_param(error_recovery_mode, uint, 0664);
-MODULE_PARM_DESC(error_recovery_mode, "\n amvdec_h264 error_recovery_mode\n");
-
-module_init(amvdec_h264_4k2k_driver_init_module);
-module_exit(amvdec_h264_4k2k_driver_remove_module);
-
-MODULE_DESCRIPTION("AMLOGIC h264_4k2k Video Decoder Driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Tim Yao <tim.yao@amlogic.com>");
diff --git a/drivers/frame_provider/decoder/h264/vh264_mvc.c b/drivers/frame_provider/decoder/h264/vh264_mvc.c
index 0efd1a0..4827e38 100644
--- a/drivers/frame_provider/decoder/h264/vh264_mvc.c
+++ b/drivers/frame_provider/decoder/h264/vh264_mvc.c
@@ -31,11 +31,8 @@
 #include <linux/workqueue.h>
 #include <linux/dma-mapping.h>
 #include <linux/atomic.h>
-#include <linux/amlogic/tee.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"
@@ -45,8 +42,8 @@
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
 #include <linux/amlogic/media/codec_mm/configs.h>
 #include "../utils/firmware.h"
-#include <linux/amlogic/tee.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
@@ -82,7 +79,7 @@
 
 static void vh264mvc_prot_init(void);
 static int vh264mvc_local_init(void);
-static void vh264mvc_put_timer_func(unsigned long arg);
+static void vh264mvc_put_timer_func(struct timer_list *timer);
 
 static const char vh264mvc_dec_id[] = "vh264mvc-dev";
 
@@ -515,10 +512,10 @@
 
 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;
@@ -530,10 +527,27 @@
 	if ((view0_buf_id >= 0) && (view1_buf_id >= 0)) {
 		if (view_mode == 0 || view_mode == 1) {
 			vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
-			vf->canvas0Addr = vf->canvas1Addr =
-				(view_mode ==
-				 0) ? spec2canvas(&buffer_spec0[view0_buf_id]) :
-				spec2canvas(&buffer_spec1[view1_buf_id]);
+
+			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;
 
@@ -545,25 +559,50 @@
 			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;
+			//vf->trans_fmt = TVIN_TFMT_3D_TB;
 
 			if (view_mode == 2) {
-				vf->canvas0Addr =
-					spec2canvas(&buffer_spec1[
-							view1_buf_id]);
-				vf->canvas1Addr =
-					spec2canvas(&buffer_spec0[
-							view0_buf_id]);
+				buf_spec_0 = &buffer_spec1[view1_buf_id];
+				buf_spec_1 = &buffer_spec0[view0_buf_id];
 			} else {
-				vf->canvas0Addr =
-					spec2canvas(&buffer_spec0[
-							view0_buf_id]);
-				vf->canvas1Addr =
-					spec2canvas(&buffer_spec1[
-							view1_buf_id]);
+				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))
@@ -704,23 +743,23 @@
 		buffer_spec[i].alloc_count = page_count;
 		buffer_spec[i].y_addr = addr;
 		buffer_spec[i].y_canvas_index = index;
-		canvas_config(index, addr,
+		config_cav_lut_ex(index, addr,
 			mb_width << 4, mb_height << 4,
-			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
+			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;
-		canvas_config(index, addr, mb_width << 3, mb_height << 3,
-				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
+		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;
-		canvas_config(index, addr, mb_width << 3, mb_height << 3,
-				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
+		config_cav_lut_ex(index, addr, mb_width << 3, mb_height << 3,
+				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32, 0, VDEC_1);
 
 		index++;
 	}
@@ -858,7 +897,10 @@
 		refbuf_size
 			= ref_size * (max_reference_frame_num + 1) * 2;
 
-		index = CANVAS_INDEX_START;
+		if (is_support_vdec_canvas())
+			index = 0;
+		else
+			index = CANVAS_INDEX_START;
 		ANC_CANVAS_ADDR = ANC0_CANVAS_ADDR;
 
 		ret =
@@ -937,7 +979,10 @@
 				   max_reference_frame_num);
 		}
 
-		index = CANVAS_INDEX_START + total_dec_frame_buffering[0] * 3;
+		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];
 
@@ -1188,10 +1233,8 @@
 	}
 }
 
-static void vh264mvc_put_timer_func(unsigned long arg)
+static void vh264mvc_put_timer_func(struct timer_list *timer)
 {
-	struct timer_list *timer = (struct timer_list *)arg;
-
 	int valid_frame = 0;
 
 	mvc_set_rp();
@@ -1380,7 +1423,10 @@
 #endif
 	WRITE_VREG(M4_CONTROL_REG, (1 << 13));	/* H264_DECODE_INFO - h264_en */
 
-	WRITE_VREG(CANVAS_START, CANVAS_INDEX_START);
+	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,
@@ -1435,6 +1481,9 @@
 	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
@@ -1480,7 +1529,6 @@
 	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;
@@ -1524,11 +1572,12 @@
 {
 	int ret = -1;
 	char *buf = vmalloc(0x1000 * 16);
+
 	if (buf == NULL)
 		return -ENOMEM;
 
 	pr_info("\nvh264mvc_init\n");
-	init_timer(&recycle_timer);
+	timer_setup(&recycle_timer, vh264mvc_put_timer_func, 0);
 
 	stat |= STAT_TIMER_INIT;
 
@@ -1618,10 +1667,7 @@
 
 	stat |= STAT_VF_HOOK;
 
-	recycle_timer.data = (ulong) (&recycle_timer);
-	recycle_timer.function = vh264mvc_put_timer_func;
 	recycle_timer.expires = jiffies + PUT_INTERVAL;
-
 	add_timer(&recycle_timer);
 
 	stat |= STAT_TIMER_ARM;
@@ -1788,32 +1834,16 @@
 }
 
 /****************************************/
-#ifdef CONFIG_PM
-static int h264mvc_suspend(struct device *dev)
-{
-	amvdec_suspend(to_platform_device(dev), dev->power.power_state);
-	return 0;
-}
-
-static int h264mvc_resume(struct device *dev)
-{
-	amvdec_resume(to_platform_device(dev));
-	return 0;
-}
-
-static const struct dev_pm_ops h264mvc_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(h264mvc_suspend, h264mvc_resume)
-};
-#endif
 
 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,
-#ifdef CONFIG_PM
-		.pm = &h264mvc_pm_ops,
-#endif
 	}
 };
 
diff --git a/drivers/frame_provider/decoder/h264_multi/h264_dpb.c b/drivers/frame_provider/decoder/h264_multi/h264_dpb.c
old mode 100755
new mode 100644
index 7b0980a..52d9611
--- a/drivers/frame_provider/decoder/h264_multi/h264_dpb.c
+++ b/drivers/frame_provider/decoder/h264_multi/h264_dpb.c
@@ -37,15 +37,19 @@
 	if (((h264_debug_flag & debug_flag) &&
 		((1 << index) & h264_debug_mask))
 		|| (debug_flag == PRINT_FLAG_ERROR)) {
-		unsigned char buf[512];
+		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;
 }
@@ -55,13 +59,18 @@
 	if (((h264_debug_flag & debug_flag) &&
 		((1 << index) & h264_debug_mask))
 		|| (debug_flag == PRINT_FLAG_ERROR)) {
-		unsigned char buf[512];
+		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;
 }
@@ -412,6 +421,8 @@
 		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",
@@ -652,7 +663,7 @@
 				(pSlice->toppoc < pSlice->bottompoc) ?
 				 pSlice->toppoc : pSlice->bottompoc;
 					/* POC200301 */
-		} else if (pSlice->bottom_field_flag == FALSE) {
+		} else if (pSlice->bottom_field_flag == 0) {
 			/* top field */
 			pSlice->ThisPOC = pSlice->toppoc =
 				pSlice->PicOrderCntMsb +
@@ -770,7 +781,7 @@
 				(pSlice->toppoc < pSlice->bottompoc) ?
 				pSlice->toppoc : pSlice->bottompoc;
 				/* POC200301 */
-		} else if (pSlice->bottom_field_flag == FALSE) {
+		} else if (pSlice->bottom_field_flag == 0) {
 			/* top field */
 			pSlice->ThisPOC = pSlice->toppoc =
 				p_Vid->ExpectedPicOrderCnt +
@@ -824,7 +835,7 @@
 			if (pSlice->field_pic_flag == 0)
 				pSlice->toppoc = pSlice->bottompoc =
 					pSlice->framepoc = pSlice->ThisPOC;
-			else if (pSlice->bottom_field_flag == FALSE)
+			else if (pSlice->bottom_field_flag == 0)
 				pSlice->toppoc = pSlice->framepoc =
 				pSlice->ThisPOC;
 			else
@@ -1839,6 +1850,35 @@
 
 }
 
+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)
 {
@@ -2164,7 +2204,6 @@
 	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)
@@ -2331,7 +2370,8 @@
 			"%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)
+		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) {
@@ -2555,6 +2595,14 @@
 
 
 	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 */
@@ -2653,108 +2701,90 @@
 
 void dump_dpb(struct DecodedPictureBuffer *p_Dpb, u8 force)
 {
-	unsigned i;
+	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++) {
-		dpb_print(p_H264_Dpb->decoder_index,
-			0,
-			"(");
-		dpb_print_cont(p_H264_Dpb->decoder_index,
-			0,
-			"fn=%d  is_used %d ",
+		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_print_cont(p_H264_Dpb->decoder_index,
-				0,
-				"T: poc=%d  pic_num=%d ",
+				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_print_cont(p_H264_Dpb->decoder_index,
-				0,
-				"T: poc=%d  ",
+				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_print_cont(p_H264_Dpb->decoder_index,
-				0,
-				"B: poc=%d  pic_num=%d ",
+				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_print_cont(p_H264_Dpb->decoder_index,
-				0,
-				"B: poc=%d  ",
+				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_print_cont(p_H264_Dpb->decoder_index,
-				0,
-				"F: poc=%d pic_num=%d ",
+				DPB_STRCAT("F: poc=%d pic_num=%d ",
 				p_Dpb->fs[i]->frame->poc,
 				p_Dpb->fs[i]->frame->pic_num);
 			else
-				dpb_print_cont(p_H264_Dpb->decoder_index,
-				0, "fs[%d] frame is null ", i);
+				DPB_STRCAT("fs[%d] frame is null ", i);
 		}
-		dpb_print_cont(p_H264_Dpb->decoder_index,
-			0,
-			"G: poc=%d)  ", p_Dpb->fs[i]->poc);
+		DPB_STRCAT("G: poc=%d)  ", p_Dpb->fs[i]->poc);
 		if (p_Dpb->fs[i]->is_reference)
-			dpb_print_cont(p_H264_Dpb->decoder_index,
-			0,
-			"ref (%d) ", 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_print_cont(p_H264_Dpb->decoder_index,
-			0,
-			"lt_ref (%d) ", p_Dpb->fs[i]->is_reference);
+			DPB_STRCAT("lt_ref (%d) ", p_Dpb->fs[i]->is_reference);
 		if (p_Dpb->fs[i]->is_output)
-			dpb_print_cont(p_H264_Dpb->decoder_index,
-			0,
-			"out(displayed)  ");
+			DPB_STRCAT("out(displayed)  ");
 		if (p_Dpb->fs[i]->pre_output)
-			dpb_print_cont(p_H264_Dpb->decoder_index,
-			0,
-			"pre_output(in dispq or displaying)  ");
+			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_print_cont(p_H264_Dpb->decoder_index,
-				0,
-				"non_existing  ");
+				DPB_STRCAT("non_existing  ");
 			else
-				dpb_print_cont(p_H264_Dpb->decoder_index,
-				0, "fs[%d] frame is null ", i);
+				DPB_STRCAT("fs[%d] frame is null ", i);
 		}
-		dpb_print_cont(p_H264_Dpb->decoder_index,
-			0,
-			"dpb_frame_count %d  ",
+		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_print_cont(p_H264_Dpb->decoder_index,
-			0,
-			"view_id (%d) ", p_Dpb->fs[i]->view_id);
+			DPB_STRCAT("view_id (%d) ", p_Dpb->fs[i]->view_id);
 #endif
 		if (p_Dpb->fs[i]->data_flag) {
-			dpb_print_cont(p_H264_Dpb->decoder_index,
-			0,
-			"data_flag(0x%x)",
+			DPB_STRCAT("data_flag(0x%x)",
 			p_Dpb->fs[i]->data_flag);
 		}
-		dpb_print_cont(p_H264_Dpb->decoder_index,
-			0,
-			" bufspec %d\n",
+		DPB_STRCAT(" bufspec %d\n",
 			p_Dpb->fs[i]->buf_spec_num);
+		dpb_print(p_H264_Dpb->decoder_index, 0, "%s", buf);
 	}
+
+	kfree(buf);
 }
 
 /*!
@@ -2872,35 +2902,6 @@
 	}
 }
 
-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;
-}
-
 /*!
  ************************************************************************
  * \brief
@@ -3687,8 +3688,7 @@
 	else
 		i = 0;
 
-	if (i || (p_H264_Dpb->first_insert_frame < FirstInsertFrm_SKIPDONE) ||
-		((p_Dpb->size - frame_outside_count) == p_H264_Dpb->dec_dpb_size)) {
+	if (i || (p_H264_Dpb->first_insert_frame < FirstInsertFrm_SKIPDONE)) {
 		while (output_frames(p_H264_Dpb, i))
 			;
 	}
@@ -5066,7 +5066,7 @@
 	}
 
 	dpb_print(p_H264_Dpb->decoder_index, PRINT_FLAG_DPB_DETAIL,
-		"%s: RefPicListX[ %d ] = pic %px (%d)\n", __func__,
+		"%s: RefPicListX[ %d ] = pic %x (%d)\n", __func__,
 		*refIdxLX, picLX, picNumLX);
 
 	RefPicListX[(*refIdxLX)++] = picLX;
@@ -5501,7 +5501,7 @@
 	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       = FALSE;
+	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;
@@ -5836,11 +5836,7 @@
 						 *  p_Vid->height_cr,
 						 */
 						 1);
-		if (!p_H264_Dpb->mVideo.dec_picture) {
-			dpb_print(p_H264_Dpb->decoder_index,
-				PRINT_FLAG_DPB_DETAIL, "p_H264_Dpb->decoder_index is null\n");
-			return -1;
-		} else {
+		if (p_H264_Dpb->mVideo.dec_picture) {
 			u32 offset_lo, offset_hi;
 			struct DecodedPictureBuffer *p_Dpb =
 				&p_H264_Dpb->mDPB;
@@ -5892,12 +5888,13 @@
 				}
 			}
 #endif
+			if (post_picture_early(p_H264_Dpb->vdec,
+				p_H264_Dpb->mVideo.dec_picture->buf_spec_num))
+				return -1;
 		}
 	}
 
-	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);
@@ -5949,8 +5946,15 @@
 	/*int j;*/
 	struct Slice *currSlice = &p_H264_Dpb->mSlice;
 	/* in first output, ignore ref check */
-	if (p_H264_Dpb->first_insert_frame < FirstInsertFrm_SKIPDONE)
+	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++) {
diff --git a/drivers/frame_provider/decoder/h264_multi/h264_dpb.h b/drivers/frame_provider/decoder/h264_multi/h264_dpb.h
old mode 100755
new mode 100644
index 10b2dba..8b3e8bb
--- a/drivers/frame_provider/decoder/h264_multi/h264_dpb.h
+++ b/drivers/frame_provider/decoder/h264_multi/h264_dpb.h
@@ -39,6 +39,7 @@
 #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
@@ -64,7 +65,7 @@
 #define H264_OUTPUT_MODE_NORMAL 0x4
 #define H264_OUTPUT_MODE_FAST   0x8
 
-#define FALSE 0
+//#define FALSE 0
 
 #define H264_SLICE_HEAD_DONE         0x01
 #define H264_PIC_DATA_DONE          0x02
@@ -823,7 +824,7 @@
 	u32 hw_decode_time;
 	u32 frame_size2; // For recording the chunk->size in frame mode
 	bool show_frame;
-	struct fence *fence;
+	struct dma_fence *fence;
 	u32 decoded_frame_size;
 };
 
@@ -925,6 +926,7 @@
 	int first_output_poc;
 	int dpb_frame_count;
 	u32 without_display_mode;
+	int long_term_reference_flag;
 };
 
 
diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c
old mode 100755
new mode 100644
index 3274134..7a1762a
--- a/drivers/frame_provider/decoder/h264_multi/vmh264.c
+++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c
@@ -23,7 +23,6 @@
 #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>
@@ -41,10 +40,10 @@
 #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 <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"
@@ -55,13 +54,14 @@
 #include "../utils/decoder_mmu_box.h"
 #include "../utils/decoder_bmmu_box.h"
 #include "../utils/firmware.h"
-#include <linux/amlogic/tee.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
 
@@ -119,6 +119,9 @@
 #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
@@ -127,7 +130,6 @@
 #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;
@@ -152,6 +154,8 @@
 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
@@ -285,6 +289,7 @@
 	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*/
 
@@ -556,7 +561,6 @@
 #define DEC_RESULT_EOS              7
 #define DEC_RESULT_FORCE_EXIT       8
 #define DEC_RESULT_TIMEOUT			9
-#define DEC_RESULT_DISCARD_DATA      10
 
 
 /*
@@ -609,6 +613,7 @@
 	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*/
@@ -620,8 +625,6 @@
 #define DECODE_MODE_MULTI_DVENL				0x4
 static DEFINE_MUTEX(vmh264_mutex);
 
-
-
 #ifdef MH264_USERDATA_ENABLE
 
 struct mh264_userdata_record_t {
@@ -650,6 +653,11 @@
 
 #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;
@@ -820,8 +828,8 @@
 	/**/
 	unsigned int last_frame_time;
 	u32 vf_pre_count;
-	u32 vf_get_count;
-	u32 vf_put_count;
+	atomic_t vf_get_count;
+	atomic_t vf_put_count;
 
 	/* timeout handle */
 	unsigned long int start_process_time;
@@ -929,6 +937,7 @@
 	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;
@@ -936,11 +945,14 @@
 	u32 wrong_frame_count;
 	u32 error_frame_width;
 	u32 error_frame_height;
-	char vdec_name[32];
-	char pts_name[32];
-	char new_q_name[32];
-	char disp_q_name[32];
+	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;
@@ -994,11 +1006,15 @@
 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;
 
@@ -1092,19 +1108,6 @@
 	return  hsize;
 }
 
-static int get_double_write_ratio(struct vdec_h264_hw_s *hw)
-{
-	int ratio = 1;
-	int dw_mode = hw->double_write_mode;
-	if ((dw_mode == 2) ||
-			(dw_mode == 3))
-		ratio = 4;
-	else if (dw_mode == 4)
-		ratio = 2;
-	return ratio;
-}
-
-
 static int get_dw_size(struct vdec_h264_hw_s *hw, u32 *pdw_buffer_size_u_v_h)
 {
 	int pic_width, pic_height;
@@ -1119,9 +1122,9 @@
 
 	if (dw_mode) {
 		int pic_width_dw = pic_width /
-			get_double_write_ratio(hw);
+			get_double_write_ratio(hw->double_write_mode);
 		int pic_height_dw = pic_height /
-			get_double_write_ratio(hw);
+			get_double_write_ratio(hw->double_write_mode);
 
 		int pic_width_lcu_dw = (pic_width_dw % lcu_size) ?
 			pic_width_dw / lcu_size + 1 :
@@ -1156,6 +1159,7 @@
 	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++)
@@ -1190,6 +1194,11 @@
 					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);
@@ -1204,9 +1213,9 @@
 			int canvas_h;
 
 			canvas_w = hw->frame_width /
-				get_double_write_ratio(hw);
+				get_double_write_ratio(hw->double_write_mode);
 			canvas_h = hw->frame_height /
-				get_double_write_ratio(hw);
+				get_double_write_ratio(hw->double_write_mode);
 
 			if (hw->canvas_mode == 0)
 				canvas_w = ALIGN(canvas_w, 32);
@@ -1373,7 +1382,9 @@
 	u32 mc_buffer_size_u_v_h;
 	int  dw_mode = hw->double_write_mode;
 
-	lcu_x_num = (width + 15) >> 4;
+	/*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;
 
@@ -1422,7 +1433,7 @@
 	/* ipp_enable*/
 	WRITE_VREG(HEVCD_IPP_TOP_CNTL, 0x1 << 1);
 
-	if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A) {
+	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)
@@ -1590,7 +1601,7 @@
 	}
 
 	/*Reset SAO + Enable SAO slice_start*/
-	if (hw->mmu_enable  && get_cpu_major_id() >= MESON_CPU_MAJOR_ID_G12A)
+	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);
@@ -1599,7 +1610,7 @@
 	/*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() < MESON_CPU_MAJOR_ID_G12A) {
+	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
@@ -1674,7 +1685,7 @@
 	}
 	timeout = jiffies + HZ;
 	if ((hw->frame_busy == 1) && (hw->frame_done == 1) ) {
-		if (get_cpu_major_id() <  MESON_CPU_MAJOR_ID_G12A) {
+		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) {
@@ -1724,7 +1735,8 @@
 			vf->index = -1;
 		}
 	}
-	if (buffer_reset_flag) {
+	/* 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;
@@ -1743,6 +1755,7 @@
 	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)
@@ -1786,137 +1799,142 @@
 			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 {
-		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);
+		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 {
-			tmpbuf = codec_mm_vmap(hw->buffer_spec[i].cma_alloc_addr, PAGE_ALIGN(buf_size));
+			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);
-				codec_mm_unmap_phyaddr(tmpbuf);
+			} 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].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 if (IS_VDEC_DW(hw) == 1) {
-		addr = hw->buffer_spec[i].cma_alloc_addr + orig_buf_size;
-		hw->buffer_spec[i].vdec_dw_y_addr = addr;
+		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].vdec_dw_u_addr = addr;
-		hw->buffer_spec[i].vdec_dw_v_addr = addr;
-		addr += hw->mb_total << 6;
 
-		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 =
-			hw->mb_width << 3;
-		hw->buffer_spec[i].vdec_dw_canvas_config[0].height =
+		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].vdec_dw_canvas_config[0].block_mode =
-			CANVAS_BLKMODE_32X32;
+		hw->buffer_spec[i].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 =
-				hw->mb_width << 3;
-		hw->buffer_spec[i].vdec_dw_canvas_config[1].height =
+		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].vdec_dw_canvas_config[1].block_mode =
-				CANVAS_BLKMODE_32X32;
-	}else {
-		addr = hw->buffer_spec[i].cma_alloc_addr + orig_buf_size;
-		hw->buffer_spec[i].vdec_dw_y_addr = addr;
-		addr += hw->mb_total << 6;
-		hw->buffer_spec[i].vdec_dw_u_addr = addr;
-		hw->buffer_spec[i].vdec_dw_v_addr = addr;
-		addr += hw->mb_total << 5;
+		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;
 
-		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 =
-			hw->mb_width << 3;
-		hw->buffer_spec[i].vdec_dw_canvas_config[0].height =
-			hw->mb_height << 3;
-		hw->buffer_spec[i].vdec_dw_canvas_config[0].block_mode =
-			CANVAS_BLKMODE_32X32;
+			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;
+			}
 
-		hw->buffer_spec[i].vdec_dw_canvas_config[1].phy_addr =
+			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 =
-				hw->mb_width << 3;
-		hw->buffer_spec[i].vdec_dw_canvas_config[1].height =
-				hw->mb_height << 2;
-		hw->buffer_spec[i].vdec_dw_canvas_config[1].block_mode =
-				CANVAS_BLKMODE_32X32;
-	}
-	dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
-	"%s, vdec_dw: alloc buf for bufspec%d\n",
-			__func__, i
-	);
+			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;
@@ -1946,7 +1964,7 @@
 		ctx->id, __func__,
 		(hw->mb_total << 8) + (hw->mb_total << 7));
 
-	ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
+	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);
@@ -1955,7 +1973,7 @@
 
 	bs->cma_alloc_addr = (unsigned long)fb;
 	dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
-		"[%d] %s(), cma alloc addr: 0x%lx, out %d dec %d\n",
+		"[%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);
 
@@ -1970,6 +1988,8 @@
 		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);
@@ -2023,14 +2043,15 @@
 	if (hw->is_used_v4l)
 		endian = 7;
 
-	canvas_config_ex(hw->buffer_spec[i].
+	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);
+		endian,
+		VDEC_1);
 
 	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
 		WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32,
@@ -2041,14 +2062,15 @@
 				);
 	}
 
-	canvas_config_ex(hw->buffer_spec[i].
+	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);
+		endian,
+		VDEC_1);
 
 	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
 		WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32,
@@ -2065,46 +2087,16 @@
 #ifdef  VDEC_DW
 	if (!IS_VDEC_DW(hw))
 		return;
-	else if (IS_VDEC_DW(hw) == 1) {
-		canvas_config_ex(hw->buffer_spec[i].
+	else {
+		config_cav_lut_ex(hw->buffer_spec[i].
 			vdec_dw_y_canvas_index,
-			hw->buffer_spec[i].vdec_dw_y_addr,
-			hw->mb_width << 3,
-			hw->mb_height << 4,
+			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);
-		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));
-		}
-		canvas_config_ex(hw->buffer_spec[i].
-			vdec_dw_u_canvas_index,
-			hw->buffer_spec[i].vdec_dw_u_addr,
-			hw->mb_width << 3,
-			hw->mb_height << 3,
-			CANVAS_ADDR_NOWRAP,
-			blkmode,
-			endian);
-		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));
-		}
-	} else {
-		canvas_config_ex(hw->buffer_spec[i].
-			vdec_dw_y_canvas_index,
-			hw->buffer_spec[i].vdec_dw_y_addr,
-			hw->mb_width << 3,
-			hw->mb_height << 3,
-			CANVAS_ADDR_NOWRAP,
-			blkmode,
-			endian);
+			endian,
+			VDEC_1);
 		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
 			WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32,
 				(1 << 11) |
@@ -2113,14 +2105,15 @@
 				(hw->buffer_spec[i].vdec_dw_y_canvas_index << 0));
 		}
 
-		canvas_config_ex(hw->buffer_spec[i].
+		config_cav_lut_ex(hw->buffer_spec[i].
 			vdec_dw_u_canvas_index,
-			hw->buffer_spec[i].vdec_dw_u_addr,
-			hw->mb_width << 3,
-			hw->mb_height << 2,
+			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);
+			endian,
+			VDEC_1);
 		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
 			WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32,
 				(1 << 11) |
@@ -2139,9 +2132,9 @@
 	int canvas_h;
 
 	canvas_w = hw->frame_width /
-		get_double_write_ratio(hw);
+		get_double_write_ratio(hw->double_write_mode);
 	canvas_h = hw->frame_height /
-		get_double_write_ratio(hw);
+		get_double_write_ratio(hw->double_write_mode);
 
 	if (hw->canvas_mode == 0)
 		canvas_w = ALIGN(canvas_w, 32);
@@ -2149,26 +2142,27 @@
 		canvas_w = ALIGN(canvas_w, 64);
 	canvas_h = ALIGN(canvas_h, 32);
 
-	canvas_config_ex(hw->buffer_spec[i].
+	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);
+		7,
+		VDEC_HEVC);
 
-	canvas_config_ex(hw->buffer_spec[i].
+	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);
+		7,
+		VDEC_HEVC);
 }
 
-
 static int v4l_get_free_buffer_spec(struct vdec_h264_hw_s *hw)
 {
 	int i;
@@ -2200,7 +2194,7 @@
 	struct buffer_spec_s *pic = NULL;
 	int i, rt, idx = INVALID_IDX;
 	ulong flags;
-	u32 state, index;
+	u32 state = 0, index;
 
 	spin_lock_irqsave(&hw->bufspec_lock, flags);
 	for (i = 0; i < pool->in; ++i) {
@@ -2233,7 +2227,6 @@
 			}
 			break;
 		default:
-			pr_err("v4l buffer state err %d.\n", state);
 			break;
 		}
 
@@ -2245,12 +2238,17 @@
 	spin_unlock_irqrestore(&hw->bufspec_lock, flags);
 
 	if (idx < 0) {
-		dpb_print(DECODE_ID(hw), 0, "%s fail\n", __func__);
+		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;
@@ -2301,6 +2299,7 @@
 			}
 		}
 	}
+
 	spin_unlock_irqrestore(&hw->bufspec_lock, flags);
 	if (hw->start_search_pos >= buf_total)
 		hw->start_search_pos = 0;
@@ -2548,7 +2547,7 @@
 	int i;
 	unsigned long addr;
 	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
-	struct aml_vcodec_ctx * v4l = hw->v4l2_ctx;
+	struct aml_vcodec_ctx * ctx = hw->v4l2_ctx;
 	int canvas_pos_min = BUFSPEC_POOL_SIZE;
 	int index = -1;
 	int ret = 0;
@@ -2557,6 +2556,10 @@
 	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;
 
@@ -2568,10 +2571,13 @@
 			}
 		}
 
-		if (v4l->cap_pool.dec < hw->dpb.mDPB.size &&
-			v4l2_m2m_num_dst_bufs_ready(v4l->m2m_ctx)
-			>= run_ready_min_buf_num)
-			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;
 	}
@@ -2654,6 +2660,9 @@
 	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)
@@ -2667,9 +2676,7 @@
 			 && (hw->frame_dur == 3840)) {
 		bForceInterlace = 1;
 	}
-	if ((frame->frame) && (hw->is_used_v4l) && (bForceInterlace == 0)) {
-		bForceInterlace = (frame->frame->mb_aff_frame_flag)?1:0;
-	}
+
 	return bForceInterlace;
 }
 
@@ -2771,23 +2778,22 @@
 	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",
+			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 (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)) {
@@ -2808,6 +2814,7 @@
 				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,
@@ -2866,13 +2873,13 @@
 
 	}
 
-	if ((frame->data_flag & NODISP_FLAG) ||
+	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)))) {
-		set_frame_output_flag(&hw->dpb, frame->index);
+		(!(frame->data_flag & I_FLAG))))) {
 		frame->show_frame = false;
 		return 0;
 	}
@@ -2901,6 +2908,7 @@
 	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;
@@ -2921,12 +2929,15 @@
 	bForceInterlace = check_force_interlace(hw, frame);
 	if (bForceInterlace)
 		vf_count = 2;
-	if (hw->is_used_v4l)
-		vf_count = 1;
+
 	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) {
@@ -2951,6 +2962,7 @@
 		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) {
@@ -3016,9 +3028,14 @@
 			vf->canvas0Addr = vf->canvas1Addr =
 			spec2canvas(&hw->buffer_spec[buffer_index]);
 #ifdef VDEC_DW
-			if (IS_VDEC_DW(hw))
-				vf->canvas0Addr = vf->canvas1Addr =
-					vdec_dw_spec2canvas(&hw->buffer_spec[buffer_index]);
+			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
 
 		}
@@ -3029,9 +3046,17 @@
 
 		if (hw->mmu_enable && hw->double_write_mode) {
 			vf->width = hw->frame_width /
-				get_double_write_ratio(hw);
+				get_double_write_ratio(hw->double_write_mode);
 			vf->height = hw->frame_height /
-				get_double_write_ratio(hw);
+				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;
@@ -3122,21 +3147,6 @@
 			}
 		}
 
-		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);
-		}
-
 		/*vf->ratio_control |= (0x3FF << DISP_RATIO_ASPECT_RATIO_BIT);*/
 		vf->sar_width = hw->width_aspect_ratio;
 		vf->sar_height = hw->height_aspect_ratio;
@@ -3152,26 +3162,73 @@
 				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->pts_name, vf->pts);
-		ATRACE_COUNTER(hw->disp_q_name, kfifo_len(&hw->display_q));
-		ATRACE_COUNTER(hw->new_q_name, kfifo_len(&hw->newframe_q));
+		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
-		if (hw->is_used_v4l)
+
+		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) {
-			vf_notify_receiver(vdec->vf_provider_name,
-				VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+			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);
 	}
@@ -3193,13 +3250,13 @@
 		return 0;
 
 	/* create fence for each buffers. */
-	if (vdec_timeline_create_fence(&vdec->sync))
+	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.fence		= vdec->sync->fence;
 	fs.slice_type		= dpb_stru->mSlice.slice_type;
 	fs.dpb_frame_count	= dpb_stru->dpb_frame_count;
 
@@ -3212,7 +3269,7 @@
 		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)]++;
@@ -3225,6 +3282,10 @@
 		(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)
@@ -3235,16 +3296,36 @@
 		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);
+		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 (!frame->show_frame)
-		return 0;
-
 	if (post_video_frame(vdec, frame))
 		return -1;
 
@@ -3271,7 +3352,8 @@
 			}
 
 			if (index == INVALID_IDX) {
-				if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) {
+				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;
 				}
@@ -3283,12 +3365,18 @@
 		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->pts_name, vf->pts);
-		vf_notify_receiver(vdec->vf_provider_name,
-			VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+
+		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);
 	}
@@ -3395,7 +3483,7 @@
 			hw_buf->prefix_aux_size;
 	}
 	if (dpb_is_debug(DECODE_ID(hw),
-		 PRINT_FLAG_DEC_DETAIL)) {
+		 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),
@@ -3494,7 +3582,7 @@
 				h[7] = (padding_len) & 0xff;
 			}
 			if (dpb_is_debug(DECODE_ID(hw),
-				PRINT_FLAG_DEC_DETAIL)) {
+				PRINT_FLAG_SEI_DETAIL)) {
 				dpb_print(DECODE_ID(hw), 0,
 					"aux: (size %d) suffix_flag %d\n",
 					AUX_DATA_SIZE(pic), suffix_flag);
@@ -3574,6 +3662,98 @@
 	}
 }
 
+#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
@@ -3604,6 +3784,7 @@
 	else
 		WRITE_VREG(INIT_FLAG_REG, 1);
 }
+
 int config_decode_buf(struct vdec_h264_hw_s *hw, struct StorablePicture *pic)
 {
 	/* static int count = 0; */
@@ -3665,9 +3846,11 @@
 	print_pic_info(DECODE_ID(hw), "cur", pic, pSlice->slice_type);
 
 #ifdef VDEC_DW
-	if (IS_VDEC_DW(hw) && pic->mb_aff_frame_flag)
-		WRITE_VREG(MDEC_DOUBLEW_CFG0,
-			( READ_VREG(MDEC_DOUBLEW_CFG0) & (~(1 << 30))));
+	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;
@@ -3677,9 +3860,13 @@
 		WRITE_VREG(DBKR_CANVAS_ADDR, canvas_adr);
 		WRITE_VREG(DBKW_CANVAS_ADDR, canvas_adr);
 #ifdef VDEC_DW
-		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)));
+		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);
@@ -3999,12 +4186,16 @@
 		 * 00 - top field, 01 - bottom field,
 		 * 10 - frame, 11 - mbaff frame
 		 */
-		int l10_structure;
+		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;
@@ -4030,6 +4221,60 @@
 				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
@@ -4089,14 +4334,14 @@
 			 * [2:0] will set to 3'b000
 			 */
 			/* #define H264_CO_MB_RD_ADDR        VLD_C39 0xc39 */
-			val = ((colocate_rd_adr+colocate_adr_offset) >> 3) |
+			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_adr_offset,
+				val, colocate_rd_adr + colocate_rd_adr_offset,
 				colocate_pic->structure,
 				colocate_pic->mb_aff_frame_flag);
 		} else {
@@ -4128,7 +4373,7 @@
 		 * [2:0] will set to 3'b000
 		 */
 		/* #define H264_CO_MB_RD_ADDR        VLD_C39 0xc39 */
-		val = ((colocate_rd_adr+colocate_adr_offset)>>3) |
+		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,
@@ -4196,14 +4441,12 @@
 	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;
+	struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
 	ulong nv_order = VIDTYPE_VIU_NV21;
 
 	if (!hw)
 		return NULL;
 
-	v4l2_ctx = hw->v4l2_ctx;
-
 	/* swap uv */
 	if (hw->is_used_v4l) {
 		if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) ||
@@ -4273,9 +4516,9 @@
 
 			if (hw->double_write_mode) {
 				vf->width = hw->frame_width /
-					get_double_write_ratio(hw);
+					get_double_write_ratio(hw->double_write_mode);
 				vf->height = hw->frame_height /
-					get_double_write_ratio(hw);
+					get_double_write_ratio(hw->double_write_mode);
 			}
 		} else {
 			vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD |
@@ -4296,7 +4539,7 @@
 		unsigned int frame_interval =
 			1000*(time - hw->last_frame_time)/HZ;
 		struct vframe_s *next_vf = NULL;
-		ATRACE_COUNTER(hw->disp_q_name, kfifo_len(&hw->display_q));
+		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;
@@ -4308,10 +4551,10 @@
 						__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\n",
+				"%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->duration, vf->pts, frame_interval, vf->timestamp);
 			}
 		}
 		if (hw->last_frame_time > 0) {
@@ -4321,13 +4564,14 @@
 				= frame_interval;
 		}
 		hw->last_frame_time = time;
-		vf->index_disp = hw->vf_get_count;
-		hw->vf_get_count++;
+		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;
 	}
 
@@ -4373,6 +4617,24 @@
 		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;
@@ -4428,10 +4690,17 @@
 
 	}
 
-	hw->vf_put_count++;
-	if (vf_valid_check(vf, hw) == true) {
+	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->new_q_name, kfifo_len(&hw->newframe_q));
+		ATRACE_COUNTER(hw->trace.new_q_name, kfifo_len(&hw->newframe_q));
 	}
 
 #define ASSIST_MBOX1_IRQ_REG    VDEC_ASSIST_MBOX1_IRQ_REG
@@ -4439,6 +4708,7 @@
 		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;
@@ -4459,7 +4729,7 @@
 		int buf_spec_num;
 
 		if (!req->vf) {
-			req->aux_size = hw->vf_put_count;
+			req->aux_size = atomic_read(&hw->vf_put_count);
 			return 0;
 		}
 		buf_spec_num = BUFSPEC_INDEX(req->vf->index);
@@ -4522,6 +4792,7 @@
 		}
 	} else
 		vf->signal_type = 0;
+	hw->video_signal_type = vf->signal_type;
 
 	vf->width = hw->frame_width;
 	vf->height = hw->frame_height;
@@ -4551,9 +4822,11 @@
 #endif
 
 	if (IS_VDEC_DW(hw)) {
-		vf->width = (hw->frame_width /2);
-		 if (IS_VDEC_DW(hw) == 2)
-			vf->height = (hw->frame_height /2);
+		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];
@@ -5046,11 +5319,68 @@
 		size = size_vui;
 	}
 
-	size += 1;	/* need one more buffer */
+	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;
@@ -5088,6 +5418,7 @@
 	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)
@@ -5106,7 +5437,7 @@
 	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)\r\n",
+			"!!!wrong seq_info2 0x%x mb_width/mb_height (0x%x/0x%x) %x\r\n",
 			seq_info2,
 			mb_width,
 			mb_height);
@@ -5117,11 +5448,28 @@
 	hw->error_frame_width = 0;
 	hw->error_frame_height = 0;
 
-	if (seq_info2 != 0 &&
-		hw->seq_info2 != seq_info2 &&
+	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
-		) /*picture size changed*/
-		h264_reconfig(hw);
+		) {
+		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;
@@ -5143,7 +5491,8 @@
 
 		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
@@ -5229,10 +5578,6 @@
 			hevc_mcr_sao_global_hw_init(hw,
 				(hw->mb_width << 4), (hw->mb_height << 4));
 
-		reg_val = param4;
-		level_idc = reg_val & 0xff;
-		max_reference_size = (reg_val >> 8) & 0xff;
-		hw->dpb.reorder_output = max_reference_size;
 		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,
@@ -5249,11 +5594,6 @@
 			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) {
-			hw->dpb.reorder_output = hw->num_reorder_frames + 1;
-		}
-
-		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;
@@ -5650,6 +5990,10 @@
 	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)
@@ -5747,10 +6091,18 @@
 				}
 			}
 			spin_unlock_irqrestore(&hw->bufspec_lock, flags);
-			inner_size = p_Dpb->used_size - frame_outside_count;
+			inner_size = p_Dpb->size - frame_outside_count;
 
 			if (inner_size >= p_H264_Dpb->dec_dpb_size) {
-				bufmgr_recover(hw);
+				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) &&
@@ -5766,6 +6118,7 @@
 		if (hw->reset_bufmgr_flag == 1)
 			buffer_available = 1;
 	}
+
 	if (hw->is_used_v4l)
 		buffer_available = have_free_buf_spec(vdec);
 
@@ -5994,8 +6347,11 @@
 		mb_width = 256;
 	decode_mb_count = ((mby_mbx & 0xff) * mb_width +
 		(((mby_mbx >> 8) & 0xff) + 1));
-	if (mby_mbx == 0)
+	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;
 
@@ -6004,11 +6360,11 @@
 		p->data_flag |= ERROR_FLAG;
 	}
 
-	if (error_proc_policy & 0x100) {
+	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) {
+			if (((error_proc_policy & 0x20000) &&
+				decode_mb_count >= mb_total * (100 - mb_count_threshold) / 100)) {
 				p->data_flag &= ~ERROR_FLAG;
 			}
 		}
@@ -6199,6 +6555,7 @@
 				p_H264_Dpb->mVideo.dec_picture->data_flag);
 
 
+
 			if (ret == -1) {
 				release_cur_decoding_buf(hw);
 				bufmgr_force_recover(p_H264_Dpb);
@@ -6243,61 +6600,6 @@
 		return 0;
 }
 
-#ifdef VDEC_FCC_SUPPORT
-static void fcc_discard_mode_process(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;
-
-	if (vdec->fcc_status == AGAIN_STATUS) {
-		vdec->stream_offset = (p_H264_Dpb->dpb_param.l.data[OFFSET_DELIMITER_LO] |
-			p_H264_Dpb->dpb_param.l.data[OFFSET_DELIMITER_HI] << 16);
-		dpb_print(DECODE_ID(hw), PRINT_FLAG_FCC_STATUS,
-			"[%d][FCC]: Notify stream_offset: %d\n",
-			vdec->id, vdec->stream_offset);
-		vdec_wakeup_fcc_poll(vdec);
-		amvdec_stop();
-		vdec->mc_loaded = 0;
-		hw->init_flag = 0;
-		vdec->fcc_status = WAIT_MSG_STATUS;
-		hw->dec_result = DEC_RESULT_AGAIN;
-		vdec_schedule_work(&hw->work);
-	} else if (vdec->fcc_status == DISCARD_STATUS) {
-		dpb_print(DECODE_ID(hw), PRINT_FLAG_FCC_STATUS,
-			"[%d][FCC]: Discard current gop and to find next gop!\n",
-			vdec->id);
-		amvdec_stop();
-		vdec->mc_loaded = 0;
-		hw->init_flag = 0;
-		vdec->fcc_status = AGAIN_STATUS;
-		hw->dec_result = DEC_RESULT_DISCARD_DATA;
-		vdec_schedule_work(&hw->work);
-	}
-}
-
-static int vh264_fcc_process(struct vdec_s *vdec)
-{
-	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)(vdec->private);
-
-	if (input_stream_based(vdec)) {
-		switch (vdec->fcc_mode) {
-		case FCC_DISCARD_MODE:
-			fcc_discard_mode_process(vdec);
-			return 1;
-		case FCC_DEC_MODE:
-			dpb_print(DECODE_ID(hw), PRINT_FLAG_FCC_STATUS,
-					"[%d][FCC]: Current is Dec mode.\n", vdec->id);
-			break;
-		case FCC_BUTT:
-		default:
-			break;
-		}
-	}
-
-	return 0;
-}
-#endif
-
 static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
 {
 	int i;
@@ -6306,6 +6608,18 @@
 	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;
@@ -6330,7 +6644,13 @@
 				}
 			}
 		}
-
+		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 =
@@ -6357,7 +6677,7 @@
 		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(DECODE_ID(hw), PRINT_FLAG_DPB_DETAIL,
+		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,
@@ -6366,11 +6686,6 @@
 		p_H264_Dpb->frame_crop_bottom_offset);
 #endif
 
-#ifdef VDEC_FCC_SUPPORT
-		if (vh264_fcc_process(vdec) > 0)
-			return IRQ_HANDLED;
-#endif
-
 		WRITE_VREG(DPB_STATUS_REG, H264_ACTION_CONFIG_DONE);
 		reset_process_time(hw);
 		hw->reg_iqidct_control = READ_VREG(IQIDCT_CONTROL);
@@ -6390,6 +6705,7 @@
 		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;
@@ -6405,18 +6721,27 @@
 		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 (hw->multi_slice_pic_flag == 1 &&
-			hw->cur_picture_slice_count == 1 &&
-			(error_proc_policy & 0x10000)) {
-			hw->first_pre_frame_num = p_H264_Dpb->mVideo.pre_frame_num;
-		}
-		if (hw->multi_slice_pic_flag == 1 &&
-			hw->cur_picture_slice_count > 1 &&
-			(error_proc_policy & 0x10000)) {
+
+		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__,
@@ -6425,7 +6750,6 @@
 			hw->cur_picture_slice_count,
 			hw->multi_slice_pic_flag);
 
-			first_mb_in_slice = p[FIRST_MB_IN_SLICE + 3];
 			mby_mbx = READ_VREG(MBY_MBX);
 			decode_mb_count = ((mby_mbx & 0xff) * mb_width +
 					(((mby_mbx >> 8) & 0xff) + 1));
@@ -6438,8 +6762,19 @@
 
 				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)
+			} 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) {
@@ -6506,6 +6841,9 @@
 		}
 #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;
 
@@ -6528,6 +6866,7 @@
 				}
 			}
 		}
+		ATRACE_COUNTER(hw->trace.decode_header_time_name, TRACE_HEADER_RPM_END);
 #endif
 #ifdef DETECT_WRONG_MULTI_SLICE
 
@@ -6666,6 +7005,9 @@
 				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)
@@ -6707,13 +7049,15 @@
 					}*/
 				}
 
-			if (!I_flag && frame_num_gap) {
-				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 (!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) {
+			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 ++;
@@ -6756,9 +7100,10 @@
 					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",
@@ -6776,11 +7121,12 @@
 			}
 		}
 
-		if (slice_header_process_status == 1) {
+		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 {
+		else
 			WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_SLICE);
-		}
 		hw->last_mby_mbx = 0;
 		hw->last_vld_level = 0;
 		start_process_time(hw);
@@ -6815,6 +7161,16 @@
 
 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) {
@@ -6866,6 +7222,7 @@
 			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);
@@ -6880,7 +7237,7 @@
 		reset_process_time(hw);
 		if (READ_VREG(H264_AUX_DATA_SIZE) != 0) {
 			if (dpb_is_debug(DECODE_ID(hw),
-				PRINT_FLAG_DPB_DETAIL))
+				PRINT_FLAG_SEI_DETAIL))
 				dump_aux_buf(hw);
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
 			if (vdec_frame_based(vdec)) {
@@ -6918,6 +7275,7 @@
 #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) ||*/
@@ -6927,7 +7285,8 @@
 empty_proc:
 		reset_process_time(hw);
 		if ((error_proc_policy & 0x40000) &&
-			dec_dpb_status == H264_DECODE_TIMEOUT)
+			((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);
@@ -6968,7 +7327,7 @@
 						 (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",
-							__func__, p_H264_Dpb->last_dpb_status);
+							p_H264_Dpb->last_dpb_status, __func__);
 							hw->reset_bufmgr_flag = 1;
 					}
 				}
@@ -6981,9 +7340,7 @@
 		} else {
 			/* WRITE_VREG(DPB_STATUS_REG, H264_ACTION_INIT); */
 #ifdef DETECT_WRONG_MULTI_SLICE
-			if (hw->multi_slice_pic_flag == 1 &&
-				hw->cur_picture_slice_count > 1 &&
-				(error_proc_policy & 0x10000)) {
+			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;
@@ -7080,6 +7437,7 @@
 						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;
@@ -7160,6 +7518,17 @@
 
 	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",
@@ -7180,6 +7549,7 @@
 		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;
 
 }
@@ -7200,7 +7570,6 @@
 		pr_err("%s h264[%d] work pending, do nothing.\n",__func__, vdec->id);
 		return;
 	}
-
 	hw->timeout_num++;
 	amvdec_stop();
 	vdec->mc_loaded = 0;
@@ -7209,7 +7578,7 @@
 		hevc_sao_wait_done(hw);
 	}
 	dpb_print(DECODE_ID(hw),
-		PRINT_FLAG_ERROR, "%s decoder timeout\n", __func__);
+		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;
@@ -7255,7 +7624,7 @@
 	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  send_err %d\n",
+		"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,
@@ -7263,6 +7632,7 @@
 		hw->dpb.mDPB.size,
 		hw->max_reference_size,
 		hw->i_only,
+		hw->video_signal_type,
 		hw->send_error_frame_flag
 		);
 
@@ -7290,9 +7660,7 @@
 		hw->cur_picture_slice_count,
 		hw->multi_slice_pic_flag);
 #endif
-
-
-	if (vf_get_receiver(vdec->vf_provider_name)) {
+	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,
@@ -7398,9 +7766,10 @@
 }
 
 
-static void check_timer_func(unsigned long arg)
+static void check_timer_func(struct timer_list *timer)
 {
-	struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)arg;
+	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;
@@ -7454,7 +7823,9 @@
 		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_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);
@@ -7555,6 +7926,7 @@
 	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) */
@@ -7646,12 +8018,14 @@
 #endif
 
 #ifdef VDEC_DW
-	if (IS_VDEC_DW(hw)) {
-		u32 data = ((1   << 30) |(1   <<  0) |(1   <<  8));
+	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*/
+			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) {
@@ -7677,9 +8051,8 @@
 
 	if (hw->init_flag == 0)
 		WRITE_VREG(DPB_STATUS_REG, 0);
-	else {
+	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);
@@ -7848,10 +8221,7 @@
 	/* init_timer(&hw->recycle_timer); */
 
 	/* timer init */
-	init_timer(&hw->check_timer);
-
-	hw->check_timer.data = (unsigned long)hw;
-	hw->check_timer.function = check_timer_func;
+	timer_setup(&hw->check_timer, check_timer_func, 0);
 	hw->check_timer.expires = jiffies + CHECK_INTERVAL;
 
 	/* add_timer(&hw->check_timer); */
@@ -7987,13 +8357,13 @@
 			return -1;
 		}
 
-		hw->sei_data_buf = vzalloc(SEI_DATA_SIZE);
+		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 = vzalloc(SEI_ITU_DATA_SIZE);
+		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__);
@@ -8001,14 +8371,15 @@
 				hw->prefix_aux_size + hw->suffix_aux_size, hw->aux_addr,
 				hw->aux_phy_addr);
 			hw->aux_addr = NULL;
-			vfree(hw->sei_data_buf);
+			kfree(hw->sei_data_buf);
 			hw->sei_data_buf = NULL;
 
 			return -1;
 		}
 
 		if (NULL == hw->sei_user_data_buffer) {
-			hw->sei_user_data_buffer = vzalloc(USER_DATA_SIZE);
+			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__);
@@ -8016,9 +8387,9 @@
 					hw->prefix_aux_size + hw->suffix_aux_size, hw->aux_addr,
 					hw->aux_phy_addr);
 				hw->aux_addr = NULL;
-				vfree(hw->sei_data_buf);
+				kfree(hw->sei_data_buf);
 				hw->sei_data_buf = NULL;
-				vfree(hw->sei_itu_data_buf);
+				kfree(hw->sei_itu_data_buf);
 				hw->sei_itu_data_buf = NULL;
 
 				return -1;
@@ -8044,6 +8415,7 @@
 	}
 #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);
@@ -8052,7 +8424,6 @@
 	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(),
@@ -8086,15 +8457,15 @@
 		hw->aux_addr = NULL;
 	}
 	if (hw->sei_data_buf != NULL) {
-		vfree(hw->sei_data_buf);
+		kfree(hw->sei_data_buf);
 		hw->sei_data_buf = NULL;
 	}
 	if (hw->sei_itu_data_buf != NULL) {
-		vfree(hw->sei_itu_data_buf);
+		kfree(hw->sei_itu_data_buf);
 		hw->sei_itu_data_buf = NULL;
 	}
 	if (hw->sei_user_data_buffer != NULL) {
-		vfree(hw->sei_user_data_buffer);
+		kfree(hw->sei_user_data_buffer);
 		hw->sei_user_data_buffer = NULL;
 	}
 	/* amvdec_disable(); */
@@ -8137,6 +8508,10 @@
 	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,
@@ -8431,7 +8806,7 @@
 
 static int vmh264_init_userdata_dump(void)
 {
-	user_data_buf = vzalloc(MAX_USER_DATA_SIZE);
+	user_data_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL);
 	if (user_data_buf)
 		return 1;
 	else
@@ -8442,7 +8817,7 @@
 {
 	if (user_data_buf) {
 		show_user_data_buf();
-		vfree(user_data_buf);
+		kfree(user_data_buf);
 		user_data_buf = NULL;
 	}
 }
@@ -8804,7 +9179,7 @@
 	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)\r\n",
+			"!!!wrong param1 0x%x mb_width/mb_height (0x%x/0x%x) %x\r\n",
 			param1,
 			mb_width,
 			mb_height);
@@ -8835,6 +9210,8 @@
 			- used_reorder_dpb_size_margin;
 	}
 
+	hw->dpb.mDPB.size = active_buffer_spec_num;
+
 	if (hw->no_poc_reorder_flag)
 		dec_dpb_size = 1;
 
@@ -8844,6 +9221,7 @@
 	 * 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 &&
@@ -8902,9 +9280,8 @@
 	ps->visible_height	= frame_height;
 	ps->coded_width		= ALIGN(mb_width << 4, 64);
 	ps->coded_height	= ALIGN(mb_height << 4, 64);
-	ps->reorder_frames	= dec_dpb_size + 1; /* +1 for two frames in one packet */
+	ps->dpb_frames		= dec_dpb_size + 1; /* +1 for two frames in one packet */
 	ps->dpb_size		= active_buffer_spec_num;
-	ps->field		= frame_mbs_only_flag ? V4L2_FIELD_NONE : V4L2_FIELD_INTERLACED;
 
 	return 0;
 }
@@ -8917,34 +9294,36 @@
 		(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->seq_info2 != 0) /*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);
-			if (hw->is_used_v4l)
+		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;
+				ret = 1;
+			}
 		}
 	}
 
@@ -8983,6 +9362,13 @@
 	/* 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__,
@@ -9010,7 +9396,6 @@
 			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");
@@ -9160,7 +9545,6 @@
 		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;
@@ -9181,7 +9565,7 @@
 
 				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 ? ((50 + p_Dpb->used_size) * 2)  : 50 + p_Dpb->used_size;
+					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 &&
@@ -9225,17 +9609,7 @@
 			hw->gvs.b_decoded_frames++;
 		}
 		amvdec_stop();
-		if (!vdec_is_support_4k()) {
-			if (clk_adj_frame_count < VDEC_CLOCK_ADJUST_FRAME) {
-				clk_adj_frame_count++;
-				if (clk_adj_frame_count == VDEC_CLOCK_ADJUST_FRAME) {
-					if (hw->frame_height <= 144)
-						vdec_source_changed(VFORMAT_H264, 1920, 1080, 29);
-					else
-						vdec_source_changed(VFORMAT_H264, 3840, 2160, 60);
-				}
-			}
-		}
+
 		dpb_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
 			"%s dec_result %d %x %x %x\n",
 			__func__,
@@ -9253,11 +9627,12 @@
 			frame base: vdec_prepare_input fail
 		*/
 		if (!vdec_has_more_input(vdec) && (hw_to_vdec(hw)->next_status !=
-			VDEC_STATUS_DISCONNECTED)) {
+			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)) {
@@ -9265,6 +9640,7 @@
 			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;
@@ -9293,12 +9669,14 @@
 			vdec_free_irq(VDEC_IRQ_1, (void *)hw);
 			hw->stat &= ~STAT_ISR_REG;
 		}
-	} else if (hw->dec_result == DEC_RESULT_DISCARD_DATA) {
-		mutex_lock(&hw->chunks_mutex);
-		vdec_vframe_dirty(hw_to_vdec(hw), hw->chunk);
-		hw->chunk = NULL;
-		mutex_unlock(&hw->chunks_mutex);
 	}
+
+	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;
@@ -9306,7 +9684,9 @@
 	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
@@ -9329,6 +9709,9 @@
 			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) {
@@ -9376,16 +9759,8 @@
 
 	hw->timeout_processing = 1;
 	vh264_work_implement(hw, vdec, 1);
-
 }
 
-#ifdef VDEC_FCC_SUPPORT
-static void vmh264_wakeup_fcc_poll(struct vdec_s *vdec)
-{
-	amstream_wakeup_fcc_poll(vdec);
-}
-#endif
-
 static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
 {
 	bool ret = 0;
@@ -9393,9 +9768,6 @@
 		(struct vdec_h264_hw_s *)vdec->private;
 	int tvp = vdec_secure(hw_to_vdec(hw)) ?
 		CODEC_MM_FLAGS_TVP : 0;
-#ifdef VDEC_FCC_SUPPORT
-	int get_msg = 1;
-#endif
 
 	if (hw->timeout_processing &&
 	    (work_pending(&hw->work) || work_busy(&hw->work) ||
@@ -9468,7 +9840,7 @@
 		ret = is_buffer_available(vdec);
 
 #ifdef CONSTRAIN_MAX_BUF_NUM
-	if (hw->dpb.mDPB.size > 0) { /*make sure initilized*/
+	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
@@ -9481,12 +9853,15 @@
 		/*avoid more buffers consumed when
 		switching resolution*/
 		if (run_ready_max_buf_num == 0xff &&
-			!have_free_buf_spec(vdec))
+			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) {
@@ -9495,13 +9870,12 @@
 
 		if (ctx->param_sets_from_ucode) {
 			if (hw->v4l_params_parsed) {
-				if (!ctx->v4l_codec_dpb_ready &&
-					v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
-					run_ready_min_buf_num)
-					ret = 0;
-				else if (ctx->v4l_codec_dpb_ready &&
-					!is_buffer_available(vdec))
-					ret = 0;
+				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;
@@ -9511,19 +9885,12 @@
 				run_ready_min_buf_num)
 				ret = 0;
 		}
-
 	}
 
-#ifdef VDEC_FCC_SUPPORT
-	get_msg = vdec_has_get_fcc_new_msg(vdec);
-	ret &= get_msg;
-#endif
-
 	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;
@@ -9568,6 +9935,8 @@
 		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)
@@ -9595,10 +9964,8 @@
 	if (hw->reset_bufmgr_flag ||
 		((error_proc_policy & 0x40) &&
 		p_H264_Dpb->buf_alloc_fail)) {
-		if (p_H264_Dpb->buf_alloc_fail){
-			hw->reset_bufmgr_flag = 1;
-		}
 		h264_reset_bufmgr(vdec);
+		//flag must clear after reset for v4l buf_spec_init use
 		hw->reset_bufmgr_flag = 0;
 	}
 
@@ -9630,6 +9997,7 @@
 
 	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),
@@ -9699,7 +10067,7 @@
 			*/
 		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;
@@ -9730,13 +10098,18 @@
 			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;
 
@@ -9770,12 +10143,14 @@
 			WRITE_VREG(NAL_SEARCH_CTL,
 					READ_VREG(NAL_SEARCH_CTL) & (~0x2));
 	}
-	WRITE_VREG(NAL_SEARCH_CTL, READ_VREG(NAL_SEARCH_CTL) | (1 << 2));
+	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() >= MESON_CPU_MAJOR_ID_G12A) {
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
 
 		if (hw->mmu_enable)
 			SET_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3);
@@ -9800,6 +10175,7 @@
 	/* } */
 
 	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)
@@ -9916,6 +10292,12 @@
 			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;
@@ -10011,16 +10393,15 @@
 	__func__, hw->decode_pic_count+1,
 	hw->skip_frame_count);
 
-	/* Only the caller from inside decoder we call flush_dbp */
-	if (!hw->reset_bufmgr_flag){
-		flush_dpb(&hw->dpb);
-	}
+	flush_dpb(&hw->dpb);
 
-	timeout = jiffies + HZ;
-	while (kfifo_len(&hw->display_q) > 0) {
-		if (time_after(jiffies, timeout))
-			break;
-		schedule();
+	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);
@@ -10109,12 +10490,10 @@
 	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;
 	}
-	pr_info("%s:cts test\n",__func__);
 
 	hw = (struct vdec_h264_hw_s *)h264_alloc_hw_stru(&pdev->dev,
 		sizeof(struct vdec_h264_hw_s), GFP_KERNEL);
@@ -10125,14 +10504,22 @@
 	hw->id = pdev->id;
 	hw->platform_dev = pdev;
 
-	snprintf(hw->vdec_name, sizeof(hw->vdec_name),
+	snprintf(hw->trace.vdec_name, sizeof(hw->trace.vdec_name),
 		"h264-%d", hw->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);
+	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;
@@ -10169,6 +10556,7 @@
 	}
 
 	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)
@@ -10218,6 +10606,16 @@
 			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;
 
@@ -10234,9 +10632,6 @@
 			hw->enable_fence, hw->fence_usage);
 	}
 
-	if (hw->enable_fence)
-		pdata->sync.usage = hw->fence_usage;
-
 	if (!hw->is_used_v4l) {
 		hw->reorder_dpb_size_margin = reorder_dpb_size_margin;
 		hw->canvas_mode = mem_map_mode;
@@ -10289,11 +10684,6 @@
 	pdata->user_data_read = NULL;
 	pdata->reset_userdata_fifo = NULL;
 #endif
-
-#ifdef VDEC_FCC_SUPPORT
-	pdata->wakeup_fcc_poll = vmh264_wakeup_fcc_poll;
-#endif
-
 	if (pdata->use_vfm_path) {
 		snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
 			VFM_DEC_PROVIDER_NAME);
@@ -10301,24 +10691,38 @@
 	}
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
 	else if (vdec_dual(pdata)) {
-		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);
+		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);
 
-	vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
-		&vf_provider_ops, pdata);
+	if (!hw->is_used_v4l)
+		vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
+			&vf_provider_ops, pdata);
 
 	platform_set_drvdata(pdev, pdata);
 
@@ -10341,7 +10745,7 @@
 			DCAC_READ_MARGIN;
 	if (hw->mmu_enable) {
 		u32 extif_size = EXTIF_BUF_SIZE;
-		if (get_cpu_major_id() >=  MESON_CPU_MAJOR_ID_G12A)
+		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) {
@@ -10404,19 +10808,8 @@
 	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);
 
-	if (vdec_is_support_4k() ||
-		(clk_adj_frame_count > (VDEC_CLOCK_ADJUST_FRAME - 1)))
-		vdec_source_changed(VFORMAT_H264, 3840, 2160, 60);
-	else if (pdata->sys_info->height * pdata->sys_info->width < 1280 * 720)
-	{
-		vdec_source_changed(VFORMAT_H264, 1280, 720, 29);
-	} else if (pdata->sys_info->height * pdata->sys_info->width < 1920 * 1080)
-	{
-		vdec_source_changed(VFORMAT_H264, 1920, 1080, 29);
-	} else
-	{
-		vdec_source_changed(VFORMAT_H264, 3840, 2160, 60);
-	}
+	vdec_source_changed(VFORMAT_H264, 3840, 2160, 60);
+
 	if (hw->mmu_enable)
 		hevc_source_changed(VFORMAT_HEVC, 3840, 2160, 60);
 
@@ -10454,10 +10847,19 @@
 	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);
+		vdec_timeline_create(pdata->sync, DRIVER_NAME);
 	}
 
 	return 0;
@@ -10467,7 +10869,6 @@
 			       struct vdec_sync *sync)
 {
 	ulong expires;
-	int i;
 
 	/* clear display pool. */
 	clear_refer_bufs(hw);
@@ -10483,14 +10884,7 @@
 		}
 	}
 
-	for (i = 0; i < VF_POOL_SIZE; i++) {
-		struct vframe_s *vf = &hw->vfpool[hw->cur_pool][i];
-
-		if (vf->fence) {
-			vdec_fence_put(vf->fence);
-			vf->fence = NULL;
-		}
-	}
+	pr_info("fence start release\n");
 
 	/* decreases refcnt of timeline. */
 	vdec_timeline_put(sync);
@@ -10564,7 +10958,7 @@
 	}
 
 	if (hw->enable_fence)
-		vdec_fence_release(hw, &vdec->sync);
+		vdec_fence_release(hw, vdec->sync);
 
 	ammvdec_h264_mmu_release(hw);
 	h264_free_hw_stru(&pdev->dev, (void *)hw);
@@ -10574,32 +10968,16 @@
 }
 
 /****************************************/
-#ifdef CONFIG_PM
-static int mh264_suspend(struct device *dev)
-{
-	amvdec_suspend(to_platform_device(dev), dev->power.power_state);
-	return 0;
-}
-
-static int mh264_resume(struct device *dev)
-{
-	amvdec_resume(to_platform_device(dev));
-	return 0;
-}
-
-static const struct dev_pm_ops mh264_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(mh264_suspend, mh264_resume)
-};
-#endif
 
 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,
-#ifdef CONFIG_PM
-		.pm = &mh264_pm_ops,
-#endif
 	}
 };
 
@@ -10638,6 +11016,7 @@
 
 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");
@@ -10647,15 +11026,25 @@
 	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";
+					"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";
+			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;
 }
 
@@ -10816,6 +11205,9 @@
 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");
diff --git a/drivers/frame_provider/decoder/h265/vh265.c b/drivers/frame_provider/decoder/h265/vh265.c
old mode 100755
new mode 100644
index 2e9bafc..d5945ce
--- a/drivers/frame_provider/decoder/h265/vh265.c
+++ b/drivers/frame_provider/decoder/h265/vh265.c
@@ -38,7 +38,10 @@
 #include <linux/dma-contiguous.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/amlogic/tee.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"
@@ -57,6 +60,8 @@
 #define HEVC_8K_LFTOFFSET_FIX
 #define SUPPORT_LONG_TERM_RPS
 
+//#define CO_MV_COMPRESS
+
 #define CONSTRAIN_MAX_BUF_NUM
 
 #define SWAP_HEVC_UCODE
@@ -81,7 +86,7 @@
 #define DB_NUM 20
 
 #define MAX_FRAME_4K_NUM 0x1200
-#define MAX_FRAME_8K_NUM (0x1200*4)
+#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
@@ -89,8 +94,16 @@
 #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
@@ -104,9 +117,11 @@
 #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
@@ -133,6 +148,7 @@
 
 #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))
@@ -167,10 +183,11 @@
 #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(unsigned long arg);
+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"
@@ -239,6 +256,11 @@
 #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:
@@ -248,6 +270,7 @@
  *	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;
@@ -330,7 +353,14 @@
 static u32 dbg_cmd;
 static u32 dump_nal;
 static u32 dbg_skip_decode_index;
-static u32 endian = 0xff0;
+/*
+ * 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 */
@@ -474,8 +504,7 @@
  *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
- *
+ *		 1, When ucode always returns again, it does not support discarding data
  */
 
 static u32 error_handle_policy;
@@ -960,6 +989,10 @@
 	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;
@@ -971,7 +1004,7 @@
 //#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*/
+/*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
@@ -983,12 +1016,288 @@
 #define DW_VBH_BUF_SIZE_8K (VBH_BUF_SIZE_8K * 2)
 #define DW_VBH_BUF_SIZE(bufspec) (bufspec->mmu_vbh_dw.buf_size / 4)
 
-#define WORK_BUF_SPEC_NUM 3
+/* 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
@@ -1058,6 +1367,16 @@
 			(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,
 		},
@@ -1135,7 +1454,7 @@
 		},
 		.dblk_para  = {.buf_size = 0x19100, }, // dblk parameter
 		.dblk_data  = {.buf_size = 0x88800, }, // dblk data for left/top
-		.dblk_data2 = {.buf_size = 0x80000, }, // dblk data for adapter
+		.dblk_data2 = {.buf_size = 0x48800, }, // dblk data for adapter
 		.mmu_vbh = {
 			.buf_size = VBH_BUF_SIZE_4K, /*2*16*2304/4, 4K*/
 		},
@@ -1145,6 +1464,16 @@
 			(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,
 		},
@@ -1220,6 +1549,16 @@
 				MAX_REF_PIC_NUM, 	// 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
 		},
 #endif
+#ifdef H265_10B_MMU_DW
+		.mmu_vbh_dw = {
+			.buf_size = DW_VBH_BUF_SIZE_8K, //VBH_BUF_SIZE * VBH_BUF_COUNT, //2*16*2304/4, 4K
+		},
+#ifdef USE_FIXED_MMU_DW_HEADER
+		.cm_header_dw = {
+			.buf_size = MMU_COMPRESS_HEADER_SIZE_8K * DB_NUM, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
+		},
+#endif
+#endif
 		.mpred_above = {
 			.buf_size = 0x8000,
 		},
@@ -1240,64 +1579,66 @@
 static void init_buff_spec(struct hevc_state_s *hevc,
 	struct BuffInfo_s *buf_spec)
 {
-	buf_spec->ipp.buf_start = buf_spec->start_adr;
+	buf_spec->ipp.buf_start =
+		WORKBUF_ALIGN(buf_spec->start_adr);
 	buf_spec->sao_abv.buf_start =
-		buf_spec->ipp.buf_start + buf_spec->ipp.buf_size;
-
+		WORKBUF_ALIGN(buf_spec->ipp.buf_start + buf_spec->ipp.buf_size);
 	buf_spec->sao_vb.buf_start =
-		buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size;
+		WORKBUF_ALIGN(buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size);
 	buf_spec->short_term_rps.buf_start =
-		buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size;
+		WORKBUF_ALIGN(buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size);
 	buf_spec->vps.buf_start =
-		buf_spec->short_term_rps.buf_start +
-		buf_spec->short_term_rps.buf_size;
+		WORKBUF_ALIGN(buf_spec->short_term_rps.buf_start + buf_spec->short_term_rps.buf_size);
 	buf_spec->sps.buf_start =
-		buf_spec->vps.buf_start + buf_spec->vps.buf_size;
+		WORKBUF_ALIGN(buf_spec->vps.buf_start + buf_spec->vps.buf_size);
 	buf_spec->pps.buf_start =
-		buf_spec->sps.buf_start + buf_spec->sps.buf_size;
+		WORKBUF_ALIGN(buf_spec->sps.buf_start + buf_spec->sps.buf_size);
 	buf_spec->sao_up.buf_start =
-		buf_spec->pps.buf_start + buf_spec->pps.buf_size;
+		WORKBUF_ALIGN(buf_spec->pps.buf_start + buf_spec->pps.buf_size);
 	buf_spec->swap_buf.buf_start =
-		buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size;
+		WORKBUF_ALIGN(buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size);
 	buf_spec->swap_buf2.buf_start =
-		buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size;
+		WORKBUF_ALIGN(buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size);
 	buf_spec->scalelut.buf_start =
-		buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size;
+		WORKBUF_ALIGN(buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size);
 	buf_spec->dblk_para.buf_start =
-		buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size;
+		WORKBUF_ALIGN(buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size);
 	buf_spec->dblk_data.buf_start =
-		buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size;
+		WORKBUF_ALIGN(buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size);
 	buf_spec->dblk_data2.buf_start =
-		buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size;
+		WORKBUF_ALIGN(buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size);
 	buf_spec->mmu_vbh.buf_start  =
-		buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size;
+		WORKBUF_ALIGN(buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size);
+#ifdef H265_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->cm_header_dw.buf_start =
+		WORKBUF_ALIGN(buf_spec->mmu_vbh_dw.buf_start + buf_spec->mmu_vbh_dw.buf_size);
 	buf_spec->mpred_above.buf_start =
-		buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size;
+		WORKBUF_ALIGN(buf_spec->cm_header_dw.buf_start + buf_spec->cm_header_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
 #ifdef MV_USE_FIXED_BUF
 	buf_spec->mpred_mv.buf_start =
-		buf_spec->mpred_above.buf_start +
-		buf_spec->mpred_above.buf_size;
-
+		WORKBUF_ALIGN(buf_spec->mpred_above.buf_start + buf_spec->mpred_above.buf_size);
 	buf_spec->rpm.buf_start =
-		buf_spec->mpred_mv.buf_start +
-		buf_spec->mpred_mv.buf_size;
+		WORKBUF_ALIGN(buf_spec->mpred_mv.buf_start + buf_spec->mpred_mv.buf_size);
 #else
 	buf_spec->rpm.buf_start =
-		buf_spec->mpred_above.buf_start +
-		buf_spec->mpred_above.buf_size;
+		WORKBUF_ALIGN(buf_spec->mpred_above.buf_start + buf_spec->mpred_above.buf_size);
 #endif
 	buf_spec->lmem.buf_start =
-		buf_spec->rpm.buf_start +
-		buf_spec->rpm.buf_size;
+		WORKBUF_ALIGN(buf_spec->rpm.buf_start + buf_spec->rpm.buf_size);
 	buf_spec->end_adr =
-		buf_spec->lmem.buf_start +
-		buf_spec->lmem.buf_size;
+		WORKBUF_ALIGN(buf_spec->lmem.buf_start + buf_spec->lmem.buf_size);
 
 	if (hevc && get_dbg_flag2(hevc)) {
 		hevc_print(hevc, 0,
-				"%s workspace (%x %x) size = %x\n", __func__,
-			   buf_spec->start_adr, buf_spec->end_adr,
-			   buf_spec->end_adr - buf_spec->start_adr);
+			"%s workspace (%x %x) size = %x\n", __func__,
+			buf_spec->start_adr, buf_spec->end_adr,
+			buf_spec->end_adr - buf_spec->start_adr);
 
 		hevc_print(hevc, 0,
 			"ipp.buf_start             :%x\n",
@@ -1341,6 +1682,14 @@
 		hevc_print(hevc, 0,
 			"dblk_data2.buf_start       :%x\n",
 			buf_spec->dblk_data2.buf_start);
+#ifdef H265_10B_MMU_DW
+		hevc_print(hevc, 0,
+			"mmu_vbh_dw.buf_start       :%x\n",
+			buf_spec->mmu_vbh_dw.buf_start);
+		hevc_print(hevc, 0,
+			"cm_header_dw.buf_start     :%x\n",
+			buf_spec->cm_header_dw.buf_start);
+#endif
 		hevc_print(hevc, 0,
 			"mpred_above.buf_start     :%x\n",
 			buf_spec->mpred_above.buf_start);
@@ -1427,6 +1776,9 @@
 	unsigned int dw_y_adr;
 	unsigned int dw_u_v_adr;
 #endif
+	u32	luma_size;
+	u32	chroma_size;
+
 	int mc_canvas_y;
 	int mc_canvas_u_v;
 	int width;
@@ -1445,6 +1797,9 @@
 #ifdef LOSLESS_COMPRESS_MODE
 	unsigned int losless_comp_body_size;
 #endif
+#ifdef H265_10B_MMU_DW
+	u32 header_dw_adr;
+#endif
 	unsigned char pic_struct;
 	int vf_ref;
 
@@ -1477,11 +1832,10 @@
 
 	u32 hw_decode_time;
 	u32 frame_size; // For frame base mode
-	bool vframe_bound;
 	bool ip_mode;
 	u32 hdr10p_data_size;
 	char *hdr10p_data_buf;
-	struct fence *fence;
+	struct dma_fence *fence;
 	bool show_frame;
 } /*PIC_t */;
 
@@ -1500,6 +1854,8 @@
 #define SEI_MASTER_DISPLAY_COLOR_MASK 0x00000001
 #define SEI_CONTENT_LIGHT_LEVEL_MASK  0x00000002
 #define SEI_HDR10PLUS_MASK			  0x00000004
+#define SEI_HDR_CUVA_MASK	      0x00000008
+
 
 #define VF_POOL_SIZE        32
 
@@ -1516,7 +1872,6 @@
 #define DEC_RESULT_EOS              9
 #define DEC_RESULT_FORCE_EXIT       10
 #define DEC_RESULT_FREE_CANVAS      11
-#define DEC_RESULT_DISCARD_DATA      12
 
 
 static void vh265_work(struct work_struct *work);
@@ -1530,6 +1885,11 @@
 	uint8_t data; /*will alloc more size*/
 };
 
+struct mh265_fence_vf_t {
+	u32 used_size;
+	struct vframe_s *fence_vf[VF_POOL_SIZE];
+};
+
 struct hevc_state_s {
 #ifdef MULTI_INSTANCE_SUPPORT
 	struct platform_device *platform_dev;
@@ -1756,6 +2116,12 @@
 	void *mmu_box;
 	void *bmmu_box;
 	int mmu_enable;
+#ifdef H265_10B_MMU_DW
+	void *frame_dw_mmu_map_addr;
+	dma_addr_t frame_dw_mmu_map_phy_addr;
+	void *mmu_box_dw;
+	int dw_mmu_enable;
+#endif
 
 	unsigned int dec_status;
 
@@ -1781,8 +2147,8 @@
 	u32 start_shift_bytes;
 
 	u32 vf_pre_count;
-	u32 vf_get_count;
-	u32 vf_put_count;
+	atomic_t vf_get_count;
+	atomic_t vf_put_count;
 #ifdef SWAP_HEVC_UCODE
 	dma_addr_t mc_dma_handle;
 	void *mc_cpu_addr;
@@ -1812,6 +2178,7 @@
 	u32 skip_nal_count;
 	bool is_swap;
 	bool is_4k;
+
 	int frameinfo_enable;
 	struct vframe_qos_s vframe_qos;
 	bool is_used_v4l;
@@ -1820,7 +2187,6 @@
 	u32 mem_map_mode;
 	u32 performance_profile;
 	struct vdec_info *gvs;
-	u32 res_ch_flag;
 	bool ip_mode;
 	u32 kpi_first_i_comming;
 	u32 kpi_first_i_decoded;
@@ -1835,18 +2201,21 @@
 	bool discard_dv_data;
 	bool enable_fence;
 	int fence_usage;
+	int buffer_wrap[MAX_REF_PIC_NUM];
 	int low_latency_flag;
+	u32 metadata_config_flag;
+	int last_width;
+	int last_height;
+	int used_buf_num;
 	u32 dirty_shift_flag;
-	char vdec_name[32];
-	char set_canvas0_addr[32];
-	char get_canvas0_addr[32];
-	char put_canvas0_addr[32];
-	char vf_put_name[32];
-	char vf_get_name[32];
-	char new_q_name[32];
-	char disp_q_name[32];
-	char pts_name[32];
+	u32 endian;
+	ulong fb_token;
 	int dec_again_cnt;
+	struct mh265_fence_vf_t fence_vf_s;
+	struct mutex fence_mutex;
+	dma_addr_t rdma_phy_adr;
+	unsigned *rdma_adr;
+	struct trace_decoder_name trace;
 } /*hevc_stru_t */;
 
 #ifdef AGAIN_HAS_THRESHOLD
@@ -1870,6 +2239,9 @@
 	int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)?
 		MAX_SIZE_8K : 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;
 
@@ -1935,7 +2307,7 @@
 
 #ifdef SUPPORT_10BIT
 /* Losless compression body buffer size 4K per 64x32 (jt) */
-static  int  compute_losless_comp_body_size(struct hevc_state_s *hevc,
+static int compute_losless_comp_body_size(struct hevc_state_s *hevc,
 	int width, int height, int mem_saving_mode)
 {
 	int width_x64;
@@ -1958,7 +2330,7 @@
 }
 
 /* Losless compression header buffer size 32bytes per 128x64 (jt) */
-static  int  compute_losless_comp_header_size(int width, int height)
+static int compute_losless_comp_header_size(int width, int height)
 {
 	int     width_x128;
 	int     height_x64;
@@ -2042,10 +2414,18 @@
 #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
 static int get_valid_double_write_mode(struct hevc_state_s *hevc)
 {
-	return (hevc->m_ins_flag &&
+	u32 dw = (hevc->m_ins_flag &&
 		((double_write_mode & 0x80000000) == 0)) ?
 		hevc->double_write_mode :
 		(double_write_mode & 0x7fffffff);
+	if (dw & 0x20) {
+		if ((get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_T3)
+			&& ((dw & 0xf) == 2 || (dw & 0xf) == 3)) {
+			pr_info("MMU doueble write 1:4 not supported !!!\n");
+			dw = 0;
+		}
+	}
+	return dw;
 }
 
 static int get_dynamic_buf_num_margin(struct hevc_state_s *hevc)
@@ -2063,30 +2443,15 @@
 	int w = hevc->pic_w;
 	int h = hevc->pic_h;
 	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 v4l_parser_get_double_write_mode(struct hevc_state_s *hevc, int w, int h)
-{
-	u32 valid_dw_mode = get_valid_double_write_mode(hevc);
-	u32 dw = 0x1; /*1:1*/
+	if (hevc->is_used_v4l) {
+		unsigned int out;
+
+		vdec_v4l_get_dw_mode(hevc->v4l2_ctx, &out);
+		dw = out;
+		return dw;
+	}
+
 	switch (valid_dw_mode) {
 	case 0x100:
 		if (w > 1920 && h > 1088)
@@ -2115,19 +2480,6 @@
 	return dw;
 }
 
-
-static int get_double_write_ratio(struct hevc_state_s *hevc,
-	int dw_mode)
-{
-	int ratio = 1;
-	if ((dw_mode == 2) ||
-			(dw_mode == 3))
-		ratio = 4;
-	else if ((dw_mode == 4) ||
-				(dw_mode == 5))
-		ratio = 2;
-	return ratio;
-}
 #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
 static unsigned char get_idx(struct hevc_state_s *hevc)
 {
@@ -2140,7 +2492,7 @@
 static int hevc_print(struct hevc_state_s *hevc,
 	int flag, const char *fmt, ...)
 {
-#define HEVC_PRINT_BUF		256
+#define HEVC_PRINT_BUF		512
 	unsigned char buf[HEVC_PRINT_BUF];
 	int len = 0;
 #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
@@ -2239,7 +2591,7 @@
 		release_aux_data(hevc, hevc->decoding_pic);
 		hevc->decoding_pic = NULL;
 	}
-	if (vdec_stream_based(vdec) &&
+	/*if (vdec_stream_based(vdec) &&
 		(hevc->decode_idx - hevc->decode_idx_bak > 1)) {
 		int i;
 		hevc_print(hevc, 0, "decode_idx %d, decode_idx_bak %d\n",
@@ -2265,7 +2617,7 @@
 					release_aux_data(hevc, pic);
 			}
 		}
-	}
+	}*/
 	hevc->decode_idx = hevc->decode_idx_bak;
 	hevc->m_pocRandomAccess = hevc->m_pocRandomAccess_bak;
 	hevc->curr_POC = hevc->curr_POC_bak;
@@ -2391,6 +2743,10 @@
 static int H265_alloc_mmu(struct hevc_state_s *hevc,
 			struct PIC_s *new_pic,	unsigned short bit_depth,
 			unsigned int *mmu_index_adr);
+#ifdef H265_10B_MMU_DW
+static int H265_alloc_mmu_dw(struct hevc_state_s *hevc, struct PIC_s *new_pic,
+		unsigned short bit_depth, unsigned int *mmu_index_adr);
+#endif
 
 #ifdef DETREFILL_ENABLE
 #define DETREFILL_BUF_SIZE (4 * 0x4000)
@@ -2587,7 +2943,7 @@
 	uint16_t ctuy = (ctuPosition>> 0) & 0xffff;
 	int32_t aboveCtuAvailable = (ctuy) ? 1 : 0;
 
-	uint16_t cmBodyBuf[32 * 18];
+	uint16_t *cmBodyBuf = NULL;
 
 	uint32_t pic_width_x64_pre = picWidth + 0x3f;
 	uint32_t pic_width_x64 = pic_width_x64_pre >> 6;
@@ -2609,6 +2965,10 @@
 
 	int32_t blkIdx;
 
+	cmBodyBuf = vzalloc(sizeof(uint16_t) * 32 * 18);
+	if (!cmBodyBuf)
+		return;
+
 	WRITE_VREG(HEVC_SAO_CTRL10, cmHeaderAddrAbv);
 	WRITE_VREG(HEVC_SAO_CTRL11, cmHeaderAddrCur);
 	WRITE_VREG(HEVC_SAO_DBG_MODE0, hevc->detbuf_adr);
@@ -2727,6 +3087,7 @@
 	} while (tmpData32);
 	hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
 		"%s, %d\n", __func__, __LINE__);
+	vfree(cmBodyBuf);
 }
 
 static void delrefill(struct hevc_state_s *hevc)
@@ -2792,17 +3153,18 @@
 	struct PIC_s *pic;
 	int i;
 
-	for (i = 0; i < MAX_REF_PIC_NUM; i++) {
+	for (i = 0; i < hevc->used_buf_num; i++) {
 		pic = hevc->m_PIC[i];
-		if (pic == NULL ||
-			pic->index == -1 ||
-			pic->BUF_index == -1)
+		if ((pic == NULL) ||
+			(pic->index == -1) ||
+			(pic->BUF_index == -1))
 			continue;
 
-		if (pic->output_mark == 0 &&
-			pic->referenced == 0 &&
-			pic->output_ready == 0 &&
-			pic->cma_alloc_addr) {
+		if ((pic->output_mark == 0) &&
+			(pic->referenced == 0) &&
+			(pic->output_ready == 0) &&
+			(pic->vf_ref == 0) &&
+			(pic->cma_alloc_addr)) {
 			pic->output_ready = 1;
 			index = i;
 			break;
@@ -2877,80 +3239,46 @@
 
 static int init_buf_spec(struct hevc_state_s *hevc);
 
-static bool v4l_is_there_vframe_bound(struct hevc_state_s *hevc)
-{
-	int i;
-
-	for (i = 0; i < MAX_REF_PIC_NUM; i++) {
-		struct PIC_s *pic = hevc->m_PIC[i];
-
-		if (pic && pic->vframe_bound)
-			return true;
-	}
-
-	return false;
-}
-
-static void v4l_mmu_buffer_release(struct hevc_state_s *hevc)
-{
-	int i;
-
-	/* release workspace */
-	if (hevc->bmmu_box)
-		decoder_bmmu_box_free_idx(hevc->bmmu_box,
-			BMMU_WORKSPACE_ID);
-	/*
-	 * it's only when vframe get back to driver, right now we can be sure
-	 * that vframe and fd are related. if the playback exits, the capture
-	 * requires the upper app to release when the fd is closed, and others
-	 * buffers drivers are released by driver.
-	 */
-	for (i = 0; i < MAX_REF_PIC_NUM; i++) {
-		struct PIC_s *pic = hevc->m_PIC[i];
-
-		if (pic && !pic->vframe_bound) {
-			if (hevc->bmmu_box)
-				decoder_bmmu_box_free_idx(hevc->bmmu_box,
-					VF_BUFFER_IDX(i));
-			if (hevc->mmu_box)
-				decoder_mmu_box_free_idx(hevc->mmu_box, i);
-
-			hevc_print(hevc, PRINT_FLAG_V4L_DETAIL,
-				"%s free buffer[%d], bmmu_box: %p, mmu_box: %p\n",
-				__func__, i, hevc->bmmu_box, hevc->mmu_box);
-		}
-	}
-}
 
 static void uninit_mmu_buffers(struct hevc_state_s *hevc)
 {
-	if (hevc->is_used_v4l &&
-		v4l_is_there_vframe_bound(hevc)) {
-		if (get_double_write_mode(hevc) != 0x10) {
-			v4l_mmu_buffer_release(hevc);
-			return;
-		}
-	}
-
-	if (hevc->mmu_box)
+	if (hevc->mmu_box) {
 		decoder_mmu_box_free(hevc->mmu_box);
-	hevc->mmu_box = NULL;
-
-	if (hevc->bmmu_box)
+		hevc->mmu_box = NULL;
+	}
+#ifdef H265_10B_MMU_DW
+	if (hevc->mmu_box_dw) {
+		decoder_mmu_box_free(hevc->mmu_box_dw);
+		hevc->mmu_box_dw = NULL;
+	}
+#endif
+	if (hevc->bmmu_box) {
+		/* release workspace */
+		decoder_bmmu_box_free_idx(hevc->bmmu_box,
+			BMMU_WORKSPACE_ID);
 		decoder_bmmu_box_free(hevc->bmmu_box);
-	hevc->bmmu_box = NULL;
+		hevc->bmmu_box = NULL;
+	}
 }
 
-static int init_mmu_box(struct hevc_state_s *hevc)
+/* return in MB */
+static int hevc_max_mmu_buf_size(int max_w, int max_h)
+{
+	int buf_size = 64;
+
+	if ((max_w * max_h) > 0 &&
+		(max_w * max_h) <= 1920*1088) {
+		buf_size = 24;
+	}
+	return buf_size;
+}
+
+static int init_mmu_buffers(struct hevc_state_s *hevc, int bmmu_flag)
 {
 	int tvp_flag = vdec_secure(hw_to_vdec(hevc)) ?
 		CODEC_MM_FLAGS_TVP : 0;
-	int buf_size = 64;
-
-	if ((hevc->max_pic_w * hevc->max_pic_h) > 0 &&
-		(hevc->max_pic_w * hevc->max_pic_h) <= 1920*1088) {
-		buf_size = 24;
-	}
+	int buf_size = hevc_max_mmu_buf_size(hevc->max_pic_w,
+			hevc->max_pic_h);
 
 	if (get_dbg_flag(hevc)) {
 		hevc_print(hevc, 0, "%s max_w %d max_h %d\n",
@@ -2959,43 +3287,7 @@
 
 	hevc->need_cache_size = buf_size * SZ_1M;
 	hevc->sc_start_time = get_jiffies_64();
-	if (hevc->mmu_enable
-		&& ((get_double_write_mode(hevc) & 0x10) == 0)) {
-		hevc->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME,
-			hevc->index,
-			MAX_REF_PIC_NUM,
-			buf_size * SZ_1M,
-			tvp_flag
-			);
-		if (!hevc->mmu_box) {
-			hevc_print(hevc, 0, "h265 alloc mmu box failed!!\n");
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-static int init_mmu_buffers(struct hevc_state_s *hevc)
-{
-	int tvp_flag = vdec_secure(hw_to_vdec(hevc)) ?
-		CODEC_MM_FLAGS_TVP : 0;
-	int buf_size = 64;
-
-	if ((hevc->max_pic_w * hevc->max_pic_h) > 0 &&
-		(hevc->max_pic_w * hevc->max_pic_h) <= 1920*1088) {
-		buf_size = 24;
-	}
-
-	if (get_dbg_flag(hevc)) {
-		hevc_print(hevc, 0, "%s max_w %d max_h %d\n",
-			__func__, hevc->max_pic_w, hevc->max_pic_h);
-	}
-
-	hevc->need_cache_size = buf_size * SZ_1M;
-	hevc->sc_start_time = get_jiffies_64();
-	if (hevc->mmu_enable
-		&& ((get_double_write_mode(hevc) & 0x10) == 0)) {
+	if (hevc->mmu_enable && !hevc->is_used_v4l) {
 		hevc->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME,
 			hevc->index,
 			MAX_REF_PIC_NUM,
@@ -3006,7 +3298,21 @@
 			pr_err("h265 alloc mmu box failed!!\n");
 			return -1;
 		}
+#ifdef H265_10B_MMU_DW
+		if (hevc->dw_mmu_enable) {
+			hevc->mmu_box_dw = decoder_mmu_box_alloc_box(DRIVER_NAME,
+				hevc->index,
+				MAX_REF_PIC_NUM,
+				buf_size * SZ_1M,
+				tvp_flag
+				);
+			if (!hevc->mmu_box_dw)
+				goto dw_mmu_box_failed;
+		}
+#endif
 	}
+	if (bmmu_flag)
+		return 0;
 
 	hevc->bmmu_box = decoder_bmmu_box_alloc_box(DRIVER_NAME,
 			hevc->index,
@@ -3015,14 +3321,23 @@
 			CODEC_MM_FLAGS_CMA_CLEAR |
 			CODEC_MM_FLAGS_FOR_VDECODER |
 			tvp_flag);
-	if (!hevc->bmmu_box) {
-		if (hevc->mmu_box)
-			decoder_mmu_box_free(hevc->mmu_box);
-		hevc->mmu_box = NULL;
-		pr_err("h265 alloc mmu box failed!!\n");
-		return -1;
-	}
+	if (!hevc->bmmu_box)
+		goto bmmu_box_failed;
+
 	return 0;
+bmmu_box_failed:
+#ifdef H265_10B_MMU_DW
+	if (hevc->mmu_box_dw)
+		decoder_mmu_box_free(hevc->mmu_box_dw);
+	hevc->mmu_box_dw = NULL;
+dw_mmu_box_failed:
+#endif
+	if (hevc->mmu_box) {
+		decoder_mmu_box_free(hevc->mmu_box);
+	}
+	hevc->mmu_box = NULL;
+	pr_err("h265 %s failed!!\n", __func__);
+	return -1;
 }
 
 struct buf_stru_s
@@ -3040,7 +3355,7 @@
 		if (hevc->m_mv_BUF[i].start_adr) {
 			if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR)
 				hevc_print(hevc, 0,
-				"dealloc mv buf(%d) adr 0x%lx size 0x%x used_flag %d\n",
+				"dealloc mv buf(%d) adr 0x%p size 0x%x used_flag %d\n",
 				i, hevc->m_mv_BUF[i].start_adr,
 				hevc->m_mv_BUF[i].size,
 				hevc->m_mv_BUF[i].used_flag);
@@ -3238,10 +3553,20 @@
 #endif
 }
 
+static int hevc_get_header_size(int w, int h)
+{
+	if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+			(IS_8K_SIZE(w, h)))
+		return MMU_COMPRESS_HEADER_SIZE_8K;
+	else if (IS_4K_SIZE(w, h))
+		return MMU_COMPRESS_HEADER_SIZE_4K;
+	else
+		return MMU_COMPRESS_HEADER_SIZE_1080P;
+}
+
 static int cal_current_buf_size(struct hevc_state_s *hevc,
 	struct buf_stru_s *buf_stru)
 {
-
 	int buf_size;
 	int pic_width = hevc->pic_w;
 	int pic_height = hevc->pic_h;
@@ -3263,22 +3588,21 @@
 
 	int dw_mode = get_double_write_mode(hevc);
 
-	if (hevc->mmu_enable) {
-		if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
-			(IS_8K_SIZE(hevc->pic_w, hevc->pic_h)))
-			buf_size = ((MMU_COMPRESS_HEADER_SIZE_8K + 0xffff) >> 16)
-				<< 16;
-		else
-			buf_size = ((MMU_COMPRESS_HEADER_SIZE_4K + 0xffff) >> 16)
-				<< 16;
-	} else
+	if (hevc->mmu_enable)
+		buf_size = hevc_get_header_size(hevc->pic_w, hevc->pic_h);
+	else
 		buf_size = 0;
-
-	if (dw_mode) {
+#ifdef H265_10B_MMU_DW
+	if (hevc->dw_mmu_enable) {
+		buf_size = ((buf_size + 0xffff) >> 16) << 16;
+		buf_size <<= 1;
+	}
+#endif
+	if (dw_mode && ((dw_mode & 0x20) == 0)) {
 		int pic_width_dw = pic_width /
-			get_double_write_ratio(hevc, dw_mode);
+			get_double_write_ratio(dw_mode);
 		int pic_height_dw = pic_height /
-			get_double_write_ratio(hevc, dw_mode);
+			get_double_write_ratio(dw_mode);
 
 		int pic_width_lcu_dw = (pic_width_dw % lcu_size) ?
 			pic_width_dw / lcu_size + 1 :
@@ -3319,40 +3643,48 @@
 	return buf_size;
 }
 
+static struct internal_comp_buf* v4lfb_to_icomp_buf(
+		struct hevc_state_s *hevc,
+		struct vdec_v4l2_buffer *fb)
+{
+	struct aml_video_dec_buf *aml_fb = NULL;
+	struct aml_vcodec_ctx * v4l2_ctx = hevc->v4l2_ctx;
+
+	aml_fb = container_of(fb, struct aml_video_dec_buf, frame_buffer);
+	return &v4l2_ctx->comp_bufs[aml_fb->internal_index];
+}
+
+static struct internal_comp_buf* index_to_icomp_buf(
+		struct hevc_state_s *hevc, int index)
+{
+	struct aml_video_dec_buf *aml_fb = NULL;
+	struct aml_vcodec_ctx * v4l2_ctx = hevc->v4l2_ctx;
+	struct vdec_v4l2_buffer *fb = NULL;
+
+	fb = (struct vdec_v4l2_buffer *)
+		hevc->m_BUF[index].v4l_ref_buf_addr;
+	aml_fb = container_of(fb, struct aml_video_dec_buf, frame_buffer);
+	return &v4l2_ctx->comp_bufs[aml_fb->internal_index];
+}
+
 static int v4l_alloc_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
 {
 	int ret = -1;
 	int i = pic->index;
+	struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)hevc->v4l2_ctx;
 	struct vdec_v4l2_buffer *fb = NULL;
 
-	if (hevc->fatal_error & DECODER_FATAL_ERROR_NO_MEM)
-		return ret;
-
-	ret = vdec_v4l_get_buffer(hevc->v4l2_ctx, &fb);
+	ret = ctx->fb_ops.alloc(&ctx->fb_ops, hevc->fb_token, &fb, AML_FB_REQ_DEC);
 	if (ret < 0) {
-		hevc_print(hevc, 0, "[%d] H265 get buffer fail.\n",
-			((struct aml_vcodec_ctx *)(hevc->v4l2_ctx))->id);
+		hevc_print(hevc, 0, "[%d] H265 get buffer fail.\n", ctx->id);
 		return ret;
 	}
 
-	if (hevc->mmu_enable) {
-		if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
-			(IS_8K_SIZE(hevc->pic_w, hevc->pic_h)))
-			hevc->m_BUF[i].header_size =
-				ALIGN(MMU_COMPRESS_HEADER_SIZE_8K, 0x10000);
-		else
-			hevc->m_BUF[i].header_size =
-				ALIGN(MMU_COMPRESS_HEADER_SIZE_4K, 0x10000);
+	fb->status	= FB_ST_DECODER;
 
-		ret = decoder_bmmu_box_alloc_buf_phy(hevc->bmmu_box,
-			VF_BUFFER_IDX(i), hevc->m_BUF[i].header_size,
-			DRIVER_NAME, &hevc->m_BUF[i].header_addr);
-		if (ret < 0) {
-			hevc_print(hevc, PRINT_FLAG_ERROR,
-				"%s[%d], header size: %d, no mem fatal err\n",
-				__func__, i, hevc->m_BUF[i].header_size);
-			return ret;
-		}
+	if (hevc->mmu_enable) {
+		struct internal_comp_buf *ibuf = v4lfb_to_icomp_buf(hevc, fb);
+		hevc->m_BUF[i].header_addr = ibuf->header_addr;
 	}
 
 	hevc->m_BUF[i].used_flag	= 0;
@@ -3365,6 +3697,8 @@
 		fb->m.mem[0].bytes_used = fb->m.mem[0].size;
 		pic->dw_y_adr = hevc->m_BUF[i].start_adr;
 		pic->dw_u_v_adr = pic->dw_y_adr + hevc->m_BUF[i].luma_size;
+		pic->luma_size = fb->m.mem[0].offset;
+		pic->chroma_size = fb->m.mem[0].size - fb->m.mem[0].offset;
 	} else if (fb->num_planes == 2) {
 		hevc->m_BUF[i].start_adr = fb->m.mem[0].addr;
 		hevc->m_BUF[i].luma_size = fb->m.mem[0].size;
@@ -3375,6 +3709,8 @@
 		fb->m.mem[1].bytes_used = fb->m.mem[1].size;
 		pic->dw_y_adr = hevc->m_BUF[i].start_adr;
 		pic->dw_u_v_adr = hevc->m_BUF[i].chroma_addr;
+		pic->luma_size = fb->m.mem[0].size;
+		pic->chroma_size = fb->m.mem[1].size;
 	}
 
 	return ret;
@@ -3385,6 +3721,7 @@
 	int i;
 	int ret = -1;
 	int buf_size = cal_current_buf_size(hevc, NULL);
+	struct vdec_s *vdec = hw_to_vdec(hevc);
 
 	if (hevc->fatal_error & DECODER_FATAL_ERROR_NO_MEM)
 		return ret;
@@ -3412,6 +3749,11 @@
 			}
 
 			if (ret >= 0) {
+				if (hevc->enable_fence) {
+					vdec_fence_buffer_count_increase((ulong)vdec->sync);
+					INIT_LIST_HEAD(&vdec->sync->release_callback[VF_BUFFER_IDX(i)].node);
+					decoder_bmmu_box_add_callback_func(hevc->bmmu_box, VF_BUFFER_IDX(i), (void *)&vdec->sync->release_callback[VF_BUFFER_IDX(i)]);
+				}
 				hevc->m_BUF[i].size = buf_size;
 				hevc->m_BUF[i].used_flag = 0;
 				ret = 0;
@@ -3446,7 +3788,7 @@
 	if (ret >= 0) {
 		if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) {
 			hevc_print(hevc, 0,
-			"alloc buf(%d) for %d/%d size 0x%x) => %lx\n",
+			"alloc buf(%d) for %d/%d size 0x%x) => %p\n",
 			i, hevc->pic_w, hevc->pic_h,
 			buf_size,
 			hevc->m_BUF[i].start_adr);
@@ -3476,7 +3818,7 @@
 			hevc->m_BUF[i].used_flag == 0) {
 			if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) {
 				hevc_print(hevc, 0,
-					"dealloc buf(%d) adr 0x%lx size 0x%x\n",
+					"dealloc buf(%d) adr 0x%p size 0x%x\n",
 					i, hevc->m_BUF[i].start_adr,
 					hevc->m_BUF[i].size);
 			}
@@ -3485,6 +3827,7 @@
 					hevc->bmmu_box,
 					VF_BUFFER_IDX(i));
 			hevc->m_BUF[i].start_adr = 0;
+			hevc->m_BUF[i].header_addr = 0;
 			hevc->m_BUF[i].size = 0;
 		}
 	}
@@ -3500,7 +3843,7 @@
 		hevc->m_BUF[i].start_adr) {
 		if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) {
 			hevc_print(hevc, 0,
-				"dealloc buf(%d) adr 0x%lx size 0x%x\n",
+				"dealloc buf(%d) adr 0x%p size 0x%x\n",
 				i, hevc->m_BUF[i].start_adr,
 				hevc->m_BUF[i].size);
 		}
@@ -3511,6 +3854,7 @@
 				VF_BUFFER_IDX(i));
 		hevc->m_BUF[i].used_flag = 0;
 		hevc->m_BUF[i].start_adr = 0;
+		hevc->m_BUF[i].header_addr = 0;
 		hevc->m_BUF[i].size = 0;
 	}
 }
@@ -3601,10 +3945,8 @@
 			"save buf _mode : dynamic_buf_num_margin %d ----> %d \n",
 			dynamic_buf_num_margin,  hevc->dynamic_buf_num_margin);
 
-	if (sps_pic_buf_diff >= 4)
-	{
-		used_buf_num += sps_pic_buf_diff;;
-	}
+	if (sps_pic_buf_diff >= 3)
+		used_buf_num += sps_pic_buf_diff;
 
 	/* for eos add more buffer to flush.*/
 	used_buf_num++;
@@ -3681,26 +4023,35 @@
 
 	if (hevc->mmu_enable) {
 		pic->header_adr = hevc->m_BUF[i].start_adr;
-		if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
-			(IS_8K_SIZE(hevc->pic_w, hevc->pic_h)))
-			y_adr = hevc->m_BUF[i].start_adr +
-				MMU_COMPRESS_HEADER_SIZE_8K;
-		else
-			y_adr = hevc->m_BUF[i].start_adr +
-				MMU_COMPRESS_HEADER_SIZE_4K;
+		y_adr = hevc->m_BUF[i].start_adr +
+			hevc_get_header_size(hevc->pic_w, hevc->pic_h);
 	} else
 		y_adr = hevc->m_BUF[i].start_adr;
 
 	y_adr = ((y_adr + 0xffff) >> 16) << 16; /*64k alignment*/
 
+#ifdef H265_10B_MMU_DW
+	if (hevc->dw_mmu_enable) {
+#ifdef USE_FIXED_MMU_DW_HEADER
+		pic->header_dw_adr = hevc->work_space_buf->cm_header_dw.buf_start +
+			(i * hevc_get_header_size(hevc->pic_w, hevc->pic_h));
+#else
+		pic->header_dw_adr = y_adr;
+		y_adr = pic->header_dw_adr +
+			hevc_get_header_size(hevc->pic_w, hevc->pic_h);
+#endif
+		hevc_print(hevc, H265_DEBUG_BUFMGR,
+			"MMU header_dw_adr %d: %x\n", pic->header_dw_adr);
+	}
+#endif
+
 	pic->POC = INVALID_POC;
 	/*ensure get_pic_by_POC()
 	not get the buffer not decoded*/
 	pic->BUF_index = i;
 
 	if ((!hevc->mmu_enable) &&
-		((dw_mode & 0x10) == 0)
-		) {
+		((dw_mode & 0x10) == 0)) {
 		pic->mc_y_adr = y_adr;
 		y_adr += (buf_stru.mc_buffer_size_h << 16);
 	}
@@ -3715,7 +4066,7 @@
 
 		pic->dw_y_adr = pic->mc_y_adr;
 		pic->dw_u_v_adr = pic->mc_u_v_adr;
-	} else if (dw_mode) {
+	} else if (dw_mode && (dw_mode & 0x20) == 0) {
 		pic->dw_y_adr = y_adr;
 		pic->dw_u_v_adr = pic->dw_y_adr +
 			((buf_stru.mc_buffer_size_u_v_h << 16) << 1);
@@ -3726,8 +4077,7 @@
 		"%s index %d BUF_index %d mc_y_adr %x\n",
 		 __func__, pic->index,
 		 pic->BUF_index, pic->mc_y_adr);
-		if (hevc->mmu_enable &&
-			dw_mode)
+		if (hevc->mmu_enable && dw_mode)
 			hevc_print(hevc, 0,
 			"mmu double write  adr %ld\n",
 			 pic->cma_alloc_addr);
@@ -3784,6 +4134,7 @@
 		pic->width = hevc->pic_w;
 		pic->height = hevc->pic_h;
 		pic->double_write_mode = dw_mode;
+		pic->POC = INVALID_POC;
 
 		/*config canvas will be delay if work on v4l. */
 		if (!hevc->is_used_v4l) {
@@ -3874,7 +4225,34 @@
 		data32 |= (1<<10);
 		WRITE_VREG(HEVC_SAO_CTRL5, data32);
 	}
+#ifdef H265_10B_MMU_DW
+	if (hevc->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));
+		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)));
+		/* use HEVC_CM_HEADER_START_ADDR */
+		data32 |= (1 << 15);
+	} else
+		data32 &= ~(1 << 15);
+	WRITE_VREG(HEVC_SAO_CTRL5, data32);
+#endif
 	if (!hevc->m_ins_flag)
 		hevc_print(hevc, 0,
 			"%s: (%d, %d) body_size 0x%x header_size 0x%x\n",
@@ -4082,10 +4460,8 @@
 							decode_idx))
 								pic_display
 								= pic;
-
 				} else
 					pic_display = pic;
-
 			}
 		}
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
@@ -4098,7 +4474,6 @@
 			&& (!fisrt_pic_flag))
 			pic_display = NULL;
 #endif
-
 		if (pic_display) {
 			if ((num_pic_not_yet_display >
 				pic_display->num_reorder_pic)
@@ -4853,6 +5228,12 @@
 			"write HEVC_DBLK_CFG3 to %x\n", READ_VREG(HEVC_DBLK_CFG3));
 	}
 #endif
+#ifdef H265_10B_MMU_DW
+	if (hevc->dw_mmu_enable) {
+	    //WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR2, FRAME_MMU_MAP_ADDR_DW);
+	    WRITE_VREG(HEVC_SAO_MMU_DMA_CTRL2, hevc->frame_dw_mmu_map_phy_addr);
+	}
+#endif
 	/* cfg_p_addr */
 	WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start);
 	/* cfg_d_addr */
@@ -4992,9 +5373,13 @@
 	WRITE_VREG(HEVC_DEC_STATUS_REG, 0);
 
 	/* Initial IQIT_SCALELUT memory -- just to avoid X in simulation */
-	WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);	/* cfg_p_addr */
-	for (i = 0; i < 1024; i++)
-		WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0);
+	if (is_rdma_enable())
+		rdma_back_end_work(hevc->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);
@@ -5140,7 +5525,6 @@
 	WRITE_VREG(HEVCD_IPP_TOP_CNTL, (1 << 1) |	/* enable ipp */
 			   (0 << 0)	/* software reset ipp and mpp */
 			  );
-
 }
 
 #ifdef CONFIG_HEVC_CLK_FORCED_ON
@@ -5527,6 +5911,7 @@
 	int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16;
 	struct PIC_s *cur_pic = hevc->cur_pic;
 	struct aml_vcodec_ctx * v4l2_ctx = hevc->v4l2_ctx;
+	int dw_mode = get_double_write_mode(hevc);
 
 	data32 = READ_VREG(HEVC_SAO_CTRL0);
 	data32 &= (~0xf);
@@ -5543,34 +5928,50 @@
 		WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff);
 #ifdef LOSLESS_COMPRESS_MODE
 /*SUPPORT_10BIT*/
-	if ((get_double_write_mode(hevc) & 0x10) == 0) {
+	if ((dw_mode & 0x10) == 0) {
+		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 (((dw_mode & 0xf) == 8) ||
+			((dw_mode & 0xf) == 9)) {
+			data32 |= (0xff << 16);
+			WRITE_VREG(HEVC_SAO_CTRL5, data32);
+			WRITE_VREG(HEVC_SAO_CTRL26, 0xf);
+		} else {
+			if ((dw_mode & 0xf) == 2 ||
+				(dw_mode & 0xf) == 3)
+				data32 |= (0xff<<16);
+			else if ((dw_mode & 0xf) == 4 ||
+				(dw_mode & 0xf) == 5)
+				data32 |= (0x33<<16);
 
-		if (get_double_write_mode(hevc) == 2 ||
-			get_double_write_mode(hevc) == 3)
-			data32 |= (0xff<<16);
-		else if (get_double_write_mode(hevc) == 4 ||
-				get_double_write_mode(hevc) == 5)
-			data32 |= (0x33<<16);
-
-		if (hevc->mem_saving_mode == 1)
-			data32 |= (1 << 9);
-		else
-			data32 &= ~(1 << 9);
-		if (workaround_enable & 1)
-			data32 |= (1 << 7);
-		WRITE_VREG(HEVC_SAO_CTRL5, data32);
+			if (hevc->mem_saving_mode == 1)
+				data32 |= (1 << 9);
+			else
+				data32 &= ~(1 << 9);
+			if (workaround_enable & 1)
+				data32 |= (1 << 7);
+			WRITE_VREG(HEVC_SAO_CTRL5, data32);
+		}
 	}
 	data32 = cur_pic->mc_y_adr;
-	if (get_double_write_mode(hevc))
+	if (dw_mode && ((dw_mode & 0x20) == 0))
 		WRITE_VREG(HEVC_SAO_Y_START_ADDR, cur_pic->dw_y_adr);
 
-	if ((get_double_write_mode(hevc) & 0x10) == 0)
+	if ((dw_mode & 0x10) == 0)
 		WRITE_VREG(HEVC_CM_BODY_START_ADDR, data32);
 
 	if (hevc->mmu_enable)
 		WRITE_VREG(HEVC_CM_HEADER_START_ADDR, cur_pic->header_adr);
+#ifdef H265_10B_MMU_DW
+	if (hevc->dw_mmu_enable) {
+		WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0);
+		WRITE_VREG(HEVC_SAO_C_START_ADDR, 0);
+		WRITE_VREG(HEVC_CM_HEADER_START_ADDR2, cur_pic->header_dw_adr);
+	}
+#endif
 #else
 	data32 = cur_pic->mc_y_adr;
 	WRITE_VREG(HEVC_SAO_Y_START_ADDR, data32);
@@ -5580,7 +5981,7 @@
 
 #ifdef LOSLESS_COMPRESS_MODE
 /*SUPPORT_10BIT*/
-	if (get_double_write_mode(hevc))
+	if (dw_mode && ((dw_mode & 0x20) == 0))
 		WRITE_VREG(HEVC_SAO_C_START_ADDR, cur_pic->dw_u_v_adr);
 #else
 	data32 = cur_pic->mc_u_v_adr;
@@ -5589,9 +5990,20 @@
 	data32 = (mc_buffer_size_u_v_h << 16);
 	WRITE_VREG(HEVC_SAO_C_LENGTH, data32);
 
+	if (hevc->is_used_v4l) {
+		WRITE_VREG(HEVC_SAO_Y_LENGTH, cur_pic->luma_size);
+		WRITE_VREG(HEVC_SAO_C_LENGTH, cur_pic->chroma_size);
+		if (debug & PRINT_FLAG_V4L_DETAIL) {
+			pr_info("[%d] config pic, id: %d, Y:(%x, %d) C:(%x, %d).\n",
+				v4l2_ctx->id, cur_pic->index,
+				cur_pic->dw_y_adr, cur_pic->luma_size,
+				cur_pic->dw_u_v_adr, cur_pic->chroma_size);
+		}
+	}
+
 #ifdef LOSLESS_COMPRESS_MODE
 /*SUPPORT_10BIT*/
-	if (get_double_write_mode(hevc)) {
+	if (dw_mode && ((dw_mode & 0x20) == 0)) {
 		WRITE_VREG(HEVC_SAO_Y_WPTR, cur_pic->dw_y_adr);
 		WRITE_VREG(HEVC_SAO_C_WPTR, cur_pic->dw_u_v_adr);
 	}
@@ -5615,9 +6027,9 @@
 			if (hevc->pic_w >= 1280)
 				data32 |= (0x1 << 4); /*dblk pipeline mode=1 for performance*/
 			data32 &= (~0x300); /*[8]:first write enable (compress)  [9]:double write enable (uncompress)*/
-			if (get_double_write_mode(hevc) == 0)
+			if (dw_mode == 0)
 				data32 |= (0x1 << 8); /*enable first write*/
-			else if (get_double_write_mode(hevc) == 0x10)
+			else if (dw_mode == 0x10)
 				data32 |= (0x1 << 9); /*double write only*/
 			else
 				data32 |= ((0x1 << 8)  |(0x1 << 9));
@@ -5644,7 +6056,7 @@
 		data32 |=
 			(hevc->lcu_size ==
 			 64) ? 0 : ((hevc->lcu_size == 32) ? 1 : 2);
-
+		data32 |= (hevc->pic_w <= 64) ? (1 << 20) : 0;
 		WRITE_VREG(HEVC_DBLK_CFG1, data32);
 
 		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
@@ -5681,19 +6093,19 @@
 	/* m8baby test1902 */
 	data32 = READ_VREG(HEVC_SAO_CTRL1);
 	data32 &= (~0x3000);
-	data32 |= (hevc->mem_map_mode <<
-			   12);
-
-/*  [13:12] axi_aformat, 0-Linear,
- *				   1-32x32, 2-64x32
- */
+	/* [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32 */
+	data32 |= (hevc->mem_map_mode << 12);
 	data32 &= (~0xff0);
-	/* data32 |= 0x670;  // Big-Endian per 64-bit */
-	data32 |= endian;	/* Big-Endian per 64-bit */
+#ifdef H265_10B_MMU_DW
+	if (hevc->dw_mmu_enable == 0)
+		data32 |= ((hevc->endian >> 8) & 0xfff);
+#else
+	data32 |= ((hevc->endian >> 8) & 0xfff);	/* data32 |= 0x670; Big-Endian per 64-bit */
+#endif
 	data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/
-	if (get_double_write_mode(hevc) == 0)
+	if (dw_mode == 0)
 		data32 |= 0x2; /*disable double write*/
-	else if (get_double_write_mode(hevc) & 0x10)
+	else if (dw_mode & 0x10)
 		data32 |= 0x1; /*disable cm*/
 	 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
 			unsigned int data;
@@ -5702,9 +6114,9 @@
 			if (hevc->pic_w >= 1280)
 				data |= (0x1 << 4); /*dblk pipeline mode=1 for performance*/
 			data &= (~0x300); /*[8]:first write enable (compress)  [9]:double write enable (uncompress)*/
-			if (get_double_write_mode(hevc) == 0)
+			if (dw_mode == 0)
 				data |= (0x1 << 8); /*enable first write*/
-			else if (get_double_write_mode(hevc) & 0x10)
+			else if (dw_mode & 0x10)
 				data |= (0x1 << 9); /*double write only*/
 			else
 				data |= ((0x1 << 8)  |(0x1 << 9));
@@ -5721,7 +6133,8 @@
 		else
 			data32 |= (1 << 8); /* NV12 */
 	}
-
+	data32 &= (~(3 << 14));
+	data32 |= (2 << 14);
 	/*
 	*  [31:24] ar_fifo1_axi_thred
 	*  [23:16] ar_fifo0_axi_thred
@@ -5734,9 +6147,8 @@
 	*  [1]     dw_disable:disable double write output
 	*  [0]     cm_disable:disable compress output
 	*/
-
 	WRITE_VREG(HEVC_SAO_CTRL1, data32);
-	if (get_double_write_mode(hevc) & 0x10) {
+	if (dw_mode & 0x10) {
 		/* [23:22] dw_v1_ctrl
 		 *[21:20] dw_v0_ctrl
 		 *[19:18] dw_h1_ctrl
@@ -5751,11 +6163,9 @@
 	data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
 	data32 &= (~0x30);
 	/* [5:4]    -- address_format 00:linear 01:32x32 10:64x32 */
-	data32 |= (hevc->mem_map_mode <<
-			   4);
+	data32 |= (hevc->mem_map_mode << 4);
 	data32 &= (~0xF);
-	data32 |= 0xf;  /* valid only when double write only */
-		/*data32 |= 0x8;*/		/* Big-Endian per 64-bit */
+	data32 |= (hevc->endian & 0xf);  /* valid only when double write only */
 
 	/* swap uv */
 	if (hevc->is_used_v4l) {
@@ -5765,7 +6175,8 @@
 		else
 			data32 &= ~(1 << 12); /* NV12 */
 	}
-
+	data32 &= (~(3 << 8));
+	data32 |= (2 << 8);
 	/*
 	* [3:0]   little_endian
 	* [5:4]   address_format 00:linear 01:32x32 10:64x32
@@ -5887,7 +6298,9 @@
 			if (alloc_pic_count > work_pic_num) {
 				pic->width = 0;
 				pic->height = 0;
+				ATRACE_COUNTER(hevc->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_START);
 				release_pic_mmu_buf(hevc, pic);
+				ATRACE_COUNTER(hevc->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_END);
 				pic->index = -1;
 			} else {
 				pic->width = hevc->pic_w;
@@ -6003,6 +6416,21 @@
 				return NULL;
 			}
 		}
+#ifdef H265_10B_MMU_DW
+		if (hevc->dw_mmu_enable) {
+			ret = H265_alloc_mmu_dw(hevc, new_pic,
+				rpm_param->p.bit_depth,
+				hevc->frame_dw_mmu_map_addr);
+			if (ret != 0) {
+				put_mv_buf(hevc, new_pic);
+				hevc_print(hevc, 0,
+				"can't alloc need mmu_dw_1,idx %d ret =%d\n",
+				new_pic->decode_idx,
+				ret);
+				return NULL;
+			}
+		}
+#endif
 		new_pic->referenced = 1;
 		new_pic->decode_idx = hevc->decode_idx;
 		new_pic->slice_idx = 0;
@@ -6058,6 +6486,24 @@
 	return new_pic;
 }
 
+static int get_free_fb_idx(struct hevc_state_s *hevc)
+{
+	int i;
+
+	for (i = 0; i < MAX_REF_PIC_NUM; ++i) {
+		if (hevc->m_PIC[i] == NULL)
+			continue;
+
+		if ((hevc->m_PIC[i]->referenced == 0) &&
+			(hevc->m_PIC[i]->vf_ref == 0) &&
+			(!hevc->m_PIC[i]->cma_alloc_addr))
+			break;
+	}
+
+	return (hevc->m_PIC[i] &&
+		(i != MAX_REF_PIC_NUM)) ? i : -1;
+}
+
 static struct PIC_s *v4l_get_new_pic(struct hevc_state_s *hevc,
 		union param_u *rpm_param)
 {
@@ -6067,7 +6513,7 @@
 	struct v4l_buff_pool *pool = &v4l->cap_pool;
 	struct PIC_s *new_pic = NULL;
 	struct PIC_s *pic = NULL;
-	int i;
+	int i, j, idx;
 
 	for (i = 0; i < pool->in; ++i) {
 		u32 state = (pool->seq[i] >> 16);
@@ -6075,22 +6521,37 @@
 
 		switch (state) {
 		case V4L_CAP_BUFF_IN_DEC:
-			pic = hevc->m_PIC[i];
-			if (pic && (pic->index != -1) &&
-				(pic->output_mark == 0) &&
-				(pic->referenced == 0) &&
-				(pic->output_ready == 0) &&
-				(pic->width == hevc->pic_w) &&
-				(pic->height == hevc->pic_h) &&
-				(pic->vf_ref == 0) &&
-				pic->cma_alloc_addr) {
-					new_pic = pic;
+			for (j = 0; j < MAX_REF_PIC_NUM; j++) {
+				pic = hevc->m_PIC[j];
+				if (pic == NULL || pic->index == -1)
+					continue;
+
+				if (pic->output_mark == 0 &&
+					pic->referenced == 0 &&
+					pic->output_ready == 0 &&
+					pic->width == hevc->pic_w &&
+					pic->height == hevc->pic_h &&
+					pic->vf_ref == 0 &&
+					pic->cma_alloc_addr) {
+					if (new_pic) {
+						if (new_pic->POC != INVALID_POC) {
+							if (pic->POC == INVALID_POC ||
+								pic->POC < new_pic->POC)
+								new_pic = pic;
+						}
+					} else
+						new_pic = pic;
+				}
 			}
 			break;
 		case V4L_CAP_BUFF_IN_M2M:
-			pic = hevc->m_PIC[index];
+			idx = get_free_fb_idx(hevc);
+			if (idx < 0)
+				break;
+			pic = hevc->m_PIC[idx];
 			pic->width = hevc->pic_w;
 			pic->height = hevc->pic_h;
+			hevc->buffer_wrap[idx] = index;
 			if ((pic->index != -1) &&
 				!v4l_alloc_buf(hevc, pic)) {
 				v4l_config_pic(hevc, pic);
@@ -6140,10 +6601,10 @@
 	new_pic->dis_mark = 0;
 	/* new_pic->output_ready = 0; */
 	new_pic->num_reorder_pic = rpm_param->p.sps_num_reorder_pics_0;
-	new_pic->ip_mode = (!new_pic->num_reorder_pic &&
-							!(vdec->slave || vdec->master) &&
-							!disable_ip_mode &&
-							hevc->low_latency_flag) ? true : false;
+	new_pic->ip_mode = hevc->low_latency_flag ? true :
+			(!new_pic->num_reorder_pic &&
+			!(vdec->slave || vdec->master) &&
+			!disable_ip_mode) ? true : false;
 	new_pic->losless_comp_body_size = hevc->losless_comp_body_size;
 	new_pic->POC = hevc->curr_POC;
 	new_pic->pic_struct = hevc->curr_pic_struct;
@@ -6172,7 +6633,14 @@
 	new_pic->chroma_format_idc =
 			hevc->param.p.chroma_format_idc;
 
-	hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
+	if (new_pic) {
+		struct vdec_v4l2_buffer *fb =
+			(struct vdec_v4l2_buffer *)new_pic->cma_alloc_addr;
+
+		fb->status = FB_ST_DECODER;
+	}
+
+	hevc_print(hevc, H265_DEBUG_BUFMGR,
 		"%s: index %d, buf_idx %d, decode_idx %d, POC %d\n",
 		__func__, new_pic->index,
 		new_pic->BUF_index, new_pic->decode_idx,
@@ -6328,7 +6796,7 @@
 		aux_size =
 			hevc->prefix_aux_size;
 	}
-	if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) {
+	if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) {
 		hevc_print(hevc, 0,
 			"%s:pic 0x%p old size %d count %d,suf %d dv_flag %d\r\n",
 			__func__, pic, pic->aux_data_size,
@@ -6437,7 +6905,7 @@
 				h[6] = (padding_len >> 8) & 0xff;
 				h[7] = (padding_len) & 0xff;
 			}
-			if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) {
+			if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) {
 				hevc_print(hevc, 0,
 					"aux: (size %d) suffix_flag %d\n",
 					pic->aux_data_size, suffix_flag);
@@ -6473,6 +6941,39 @@
 	pic->aux_data_size = 0;
 }
 
+static int recycle_mmu_buf_tail(struct hevc_state_s *hevc,
+		bool check_dma)
+{
+	hevc_print(hevc,
+			H265_DEBUG_BUFMGR_MORE,
+			"%s pic index %d scatter_alloc %d page_start %d\n",
+			"decoder_mmu_box_free_idx_tail",
+			hevc->cur_pic->index,
+			hevc->cur_pic->scatter_alloc,
+			hevc->used_4k_num);
+	if (check_dma)
+		hevc_mmu_dma_check(hw_to_vdec(hevc));
+
+	if (hevc->is_used_v4l) {
+		int index = hevc->cur_pic->BUF_index;
+		struct internal_comp_buf *ibuf =
+			index_to_icomp_buf(hevc, index);
+
+		decoder_mmu_box_free_idx_tail(
+				ibuf->mmu_box,
+				ibuf->index,
+				hevc->used_4k_num);
+	} else {
+		decoder_mmu_box_free_idx_tail(
+				hevc->mmu_box,
+				hevc->cur_pic->index,
+				hevc->used_4k_num);
+	}
+	hevc->cur_pic->scatter_alloc = 2;
+	hevc->used_4k_num = -1;
+	return 0;
+}
+
 static inline void hevc_pre_pic(struct hevc_state_s *hevc,
 			struct PIC_s *pic)
 {
@@ -6521,22 +7022,10 @@
 						(hevc->used_4k_num >= 0) &&
 						(hevc->cur_pic->scatter_alloc
 						== 1)) {
-						hevc_print(hevc,
-						H265_DEBUG_BUFMGR_MORE,
-						"%s pic index %d scatter_alloc %d page_start %ld\n",
-						"decoder_mmu_box_free_idx_tail",
-						hevc->cur_pic->index,
-						hevc->cur_pic->scatter_alloc,
-						hevc->used_4k_num);
-						hevc_mmu_dma_check(hw_to_vdec(hevc));
-						decoder_mmu_box_free_idx_tail(
-						hevc->mmu_box,
-						hevc->cur_pic->index,
-						hevc->used_4k_num);
-						hevc->cur_pic->scatter_alloc
-							= 2;
-					}
-					hevc->used_4k_num = -1;
+							ATRACE_COUNTER(hevc->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_START);
+							recycle_mmu_buf_tail(hevc, true);
+							ATRACE_COUNTER(hevc->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_END);
+						}
 				}
 			}
 			if (!pic->ip_mode)
@@ -6624,7 +7113,7 @@
 			hevc_print(hevc, 0,
 			"clear referenced flag of all buffers\n");
 		}
-		if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR)
+		if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE)
 			dump_pic_list(hevc);
 		if (hevc->vf_pre_count == 1 &&
 				hevc->first_pic_flag == 1) {
@@ -7185,17 +7674,14 @@
 		union param_u *rpm_param,
 		int decode_pic_begin)
 {
+#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
 	struct vdec_s *vdec = hw_to_vdec(hevc);
+#endif
 	int i;
 	int lcu_x_num_div;
 	int lcu_y_num_div;
 	int Col_ref;
 	int dbg_skip_flag = 0;
-	struct aml_vcodec_ctx *ctx =
-		(struct aml_vcodec_ctx *)(hevc->v4l2_ctx);
-
-	if (hevc->is_used_v4l && ctx->param_sets_from_ucode)
-		hevc->res_ch_flag = 0;
 
 	if (hevc->wait_buf == 0) {
 		hevc->sps_num_reorder_pics_0 =
@@ -7209,11 +7695,22 @@
 			(rpm_param->p.profile_etc >> 2) & 0x1;
 		hevc->curr_pic_struct =
 			(rpm_param->p.sei_frame_field_info >> 3) & 0xf;
-		if (parser_sei_enable & 0x4) {
-			hevc->frame_field_info_present_flag =
-				(rpm_param->p.sei_frame_field_info >> 8) & 0x1;
+		hevc->frame_field_info_present_flag =
+			(rpm_param->p.sei_frame_field_info >> 8) & 0x1;
+
+		if (hevc->frame_field_info_present_flag) {
+			if (hevc->curr_pic_struct == 0
+				|| hevc->curr_pic_struct == 7
+				|| hevc->curr_pic_struct == 8)
+				hevc->interlace_flag = 0;
 		}
 
+		hevc_print(hevc, H265_DEBUG_PIC_STRUCT,
+				"frame_field_info_present_flag = %d curr_pic_struct = %d interlace_flag = %d\n",
+				   hevc->frame_field_info_present_flag,
+				   hevc->curr_pic_struct,
+				   hevc->interlace_flag);
+
 		/* if (interlace_enable == 0 || hevc->m_ins_flag) */
 		if (interlace_enable == 0)
 			hevc->interlace_flag = 0;
@@ -7268,6 +7765,7 @@
 				   rpm_param->p.pic_width_in_luma_samples,
 				   rpm_param->p.pic_height_in_luma_samples,
 				   hevc->interlace_flag);
+
 			hevc->pic_w = rpm_param->p.pic_width_in_luma_samples;
 			hevc->pic_h = rpm_param->p.pic_height_in_luma_samples;
 			hevc->frame_width = hevc->pic_w;
@@ -7434,7 +7932,7 @@
 		/**/
 		/* if((iPrevPOC != curr_POC)){ */
 		if (rpm_param->p.slice_segment_address == 0) {
-			struct PIC_s *pic;
+			struct PIC_s *pic = NULL;
 
 			hevc->new_pic = 1;
 #ifdef MULTI_INSTANCE_SUPPORT
@@ -7443,6 +7941,10 @@
 				check_pic_decoded_error_pre(hevc,
 					READ_VREG(HEVC_PARSER_LCU_START)
 					& 0xffffff);
+			if (vdec_stream_based(vdec) && ((READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff) != 0)) {
+				if (hevc->cur_pic)
+					hevc->cur_pic->error_mark = 1;
+			}
 			/**/ if (use_cma == 0) {
 				if (hevc->pic_list_init_flag == 0) {
 					init_pic_list(hevc);
@@ -7499,7 +8001,7 @@
 				v4l_get_new_pic(hevc, rpm_param) :
 				get_new_pic(hevc, rpm_param);
 			if (hevc->cur_pic == NULL) {
-				if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR)
+				if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE)
 					dump_pic_list(hevc);
 				hevc->wait_buf = 1;
 				return -1;
@@ -7821,7 +8323,7 @@
 		|| (dbg_skip_flag))
 		return 0xf;
 #endif
-
+	ATRACE_COUNTER(hevc->trace.decode_header_memory_time_name, TRACE_HEADER_REGISTER_START);
 	config_mc_buffer(hevc, hevc->cur_pic);
 
 	if (is_skip_decoding(hevc,
@@ -7869,7 +8371,7 @@
 	config_mpred_hw(hevc);
 
 	config_sao_hw(hevc, rpm_param);
-
+	ATRACE_COUNTER(hevc->trace.decode_header_memory_time_name, TRACE_HEADER_REGISTER_END);
 	if ((hevc->slice_type != 2) && (hevc->i_only & 0x2))
 		return 0xf;
 
@@ -7879,50 +8381,106 @@
 	return 0;
 }
 
-
-
-static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic,
-		unsigned short bit_depth, unsigned int *mmu_index_adr) {
-	int cur_buf_idx = new_pic->index;
-	int bit_depth_10 = (bit_depth != 0x00);
+/* return page number */
+static int hevc_mmu_page_num(struct hevc_state_s *hevc,
+		int w, int h, int save_mode)
+{
 	int picture_size;
-	int cur_mmu_4k_number;
-	int ret, max_frame_num;
-	picture_size = compute_losless_comp_body_size(hevc, new_pic->width,
-				new_pic->height, !bit_depth_10);
-	cur_mmu_4k_number = ((picture_size+(1<<12)-1) >> 12);
-	if (get_double_write_mode(hevc) == 0x10)
-		return 0;
-	/*hevc_print(hevc, 0,
-	"alloc_mmu cur_idx : %d picture_size : %d mmu_4k_number : %d\r\n",
-	cur_buf_idx, picture_size, cur_mmu_4k_number);*/
+	int page_num;
+	int max_frame_num;
+
+	picture_size = compute_losless_comp_body_size(hevc, w,
+				h, save_mode);
+	page_num = ((picture_size + PAGE_SIZE - 1) >> PAGE_SHIFT);
 
 	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) {
+
+	if (page_num > max_frame_num) {
 		hevc_print(hevc, 0, "over max !! 0x%x width %d height %d\n",
-			cur_mmu_4k_number,
-			new_pic->width,
-			new_pic->height);
+			page_num, w, h);
 		return -1;
 	}
-	ret = decoder_mmu_box_alloc_idx(
-		hevc->mmu_box,
-		cur_buf_idx,
-		cur_mmu_4k_number,
-		mmu_index_adr);
+	return page_num;
+}
+
+static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic,
+		unsigned short bit_depth, unsigned int *mmu_index_adr) {
+	int bit_depth_10 = (bit_depth != 0x00);
+	int cur_mmu_4k_number;
+	int ret;
+
+	if (get_double_write_mode(hevc) == 0x10)
+		return 0;
+
+	cur_mmu_4k_number = hevc_mmu_page_num(hevc, new_pic->width,
+			new_pic->height, !bit_depth_10);
+	if (cur_mmu_4k_number < 0)
+		return -1;
+
+	if (hevc->is_used_v4l) {
+		struct internal_comp_buf *ibuf =
+			index_to_icomp_buf(hevc, new_pic->BUF_index);
+
+		ret = decoder_mmu_box_alloc_idx(
+				ibuf->mmu_box,
+				ibuf->index,
+				ibuf->frame_buffer_size,
+				mmu_index_adr);
+	} else {
+		ATRACE_COUNTER(hevc->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_START);
+		ret = decoder_mmu_box_alloc_idx(
+				hevc->mmu_box,
+				new_pic->index,
+				cur_mmu_4k_number,
+				mmu_index_adr);
+		ATRACE_COUNTER(hevc->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_END);
+	}
 
 	new_pic->scatter_alloc = 1;
 
 	hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
 		"%s pic index %d page count(%d) ret =%d\n",
-		__func__, cur_buf_idx,
+		__func__, new_pic->index,
 		cur_mmu_4k_number, ret);
 	return ret;
 }
+#ifdef H265_10B_MMU_DW
+static int H265_alloc_mmu_dw(struct hevc_state_s *hevc, struct PIC_s *new_pic,
+		unsigned short bit_depth, unsigned int *mmu_index_adr) {
+	int bit_depth_10 = (bit_depth != 0x00);
+	int cur_mmu_4k_number;
+	int ret;
 
+	if (!hevc->mmu_box_dw) {
+		hevc_print(hevc, 0,
+			"%s, error no mmu box dw!\n", __func__);
+		return -1;
+	}
+
+	if (get_double_write_mode(hevc) == 0x10)
+		return 0;
+
+	cur_mmu_4k_number = hevc_mmu_page_num(hevc, new_pic->width,
+			new_pic->height, !bit_depth_10);
+	if (cur_mmu_4k_number < 0)
+		return -1;
+
+	ret = decoder_mmu_box_alloc_idx(
+			hevc->mmu_box_dw,
+			new_pic->index,
+			cur_mmu_4k_number,
+			mmu_index_adr);
+
+	hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
+		"%s pic index %d page count(%d) ret =%d\n",
+		__func__, new_pic->index,
+		cur_mmu_4k_number, ret);
+	return ret;
+}
+#endif
 
 static void release_pic_mmu_buf(struct hevc_state_s *hevc,
 	struct PIC_s *pic)
@@ -7933,9 +8491,20 @@
 	pic->scatter_alloc);
 
 	if (hevc->mmu_enable
-		&& ((hevc->double_write_mode & 0x10) == 0)
-		&& pic->scatter_alloc)
-		decoder_mmu_box_free_idx(hevc->mmu_box, pic->index);
+		&& !(hevc->double_write_mode & 0x10)
+		&& pic->scatter_alloc) {
+		if (!hevc->is_used_v4l)
+			decoder_mmu_box_free_idx(hevc->mmu_box, pic->index);
+		else {
+			struct internal_comp_buf *ibuf =
+				ibuf = index_to_icomp_buf(hevc, pic->BUF_index);
+			decoder_mmu_box_free_idx(ibuf->mmu_box, ibuf->index);
+		}
+	}
+#ifdef H265_10B_MMU_DW
+	if (hevc->dw_mmu_enable)
+		decoder_mmu_box_free_idx(hevc->mmu_box_dw, pic->index);
+#endif
 	pic->scatter_alloc = 0;
 }
 
@@ -7995,7 +8564,16 @@
 
 		hevc->frame_mmu_map_addr = NULL;
 	}
+#ifdef H265_10B_MMU_DW
+	if (hevc->dw_mmu_enable && hevc->frame_dw_mmu_map_addr) {
+		if (hevc->frame_dw_mmu_map_phy_addr)
+			dma_free_coherent(amports_get_dma_device(),
+				get_frame_mmu_map_size(), hevc->frame_dw_mmu_map_addr,
+					hevc->frame_dw_mmu_map_phy_addr);
 
+		hevc->frame_dw_mmu_map_addr = NULL;
+	}
+#endif
 	//pr_err("[%s line %d] hevc->gvs=0x%p operation\n",__func__, __LINE__, hevc->gvs);
 }
 
@@ -8007,20 +8585,34 @@
 	memset(&hevc->param, 0, sizeof(union param_u));
 
 	cur_buf_info = &hevc->work_space_buf_store;
+
 	if (force_bufspec) {
 		memcpy(cur_buf_info, &amvh265_workbuff_spec[force_bufspec & 0xf],
 		sizeof(struct BuffInfo_s));
 		pr_info("force buffer spec %d\n", force_bufspec & 0xf);
-	} else if (vdec_is_support_4k()) {
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)
-			memcpy(cur_buf_info, &amvh265_workbuff_spec[2],	/* 4k */
-			sizeof(struct BuffInfo_s));
-		else
-			memcpy(cur_buf_info, &amvh265_workbuff_spec[1],	/* 4k */
-			sizeof(struct BuffInfo_s));
-	} else
-		memcpy(cur_buf_info, &amvh265_workbuff_spec[0],	/* 1080p */
-		sizeof(struct BuffInfo_s));
+	} 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, &amvh265_workbuff_spec[2],	/* 4k */
+					sizeof(struct BuffInfo_s));
+				else
+					memcpy(cur_buf_info, &amvh265_workbuff_spec[1],	/* 4k */
+					sizeof(struct BuffInfo_s));
+			} else {
+				memcpy(cur_buf_info, &amvh265_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, &amvh265_workbuff_spec[5],	/* 4k */
+				sizeof(struct BuffInfo_s));
+			} else {
+				memcpy(cur_buf_info, &amvh265_workbuff_spec[3],	/* 1080p */
+				sizeof(struct BuffInfo_s));
+			}
+		}
+	}
 
 	cur_buf_info->start_adr = hevc->buf_start;
 	init_buff_spec(hevc, cur_buf_info);
@@ -8079,6 +8671,19 @@
 		}
 		memset(hevc->frame_mmu_map_addr, 0, get_frame_mmu_map_size());
 	}
+#ifdef H265_10B_MMU_DW
+	if (hevc->dw_mmu_enable) {
+		hevc->frame_dw_mmu_map_addr =
+				dma_alloc_coherent(amports_get_dma_device(),
+				get_frame_mmu_map_size(),
+				&hevc->frame_dw_mmu_map_phy_addr, GFP_KERNEL);
+		if (hevc->frame_dw_mmu_map_addr == NULL) {
+			pr_err("%s: failed to alloc count_buffer\n", __func__);
+			return -1;
+		}
+		memset(hevc->frame_dw_mmu_map_addr, 0, get_frame_mmu_map_size());
+	}
+#endif
 	ret = 0;
 	return ret;
 }
@@ -8115,16 +8720,14 @@
 
 	/*CANVAS_BLKMODE_64X32*/
 #ifdef SUPPORT_10BIT
-	if	(pic->double_write_mode) {
+	if	(pic->double_write_mode &&
+		((pic->double_write_mode & 0x20) == 0)) {
 		canvas_w = pic->width /
-			get_double_write_ratio(hevc, pic->double_write_mode);
+			get_double_write_ratio(pic->double_write_mode & 0xf);
 		canvas_h = pic->height /
-			get_double_write_ratio(hevc, pic->double_write_mode);
+			get_double_write_ratio(pic->double_write_mode & 0xf);
 
-		if (hevc->mem_map_mode == 0)
-			canvas_w = ALIGN(canvas_w, 32);
-		else
-			canvas_w = ALIGN(canvas_w, 64);
+		canvas_w = ALIGN(canvas_w, 64);
 		canvas_h = ALIGN(canvas_h, 32);
 
 		if (vdec->parallel_dec == 1) {
@@ -8137,12 +8740,12 @@
 			pic->uv_canvas_index = 128 + pic->index * 2 + 1;
 		}
 
-		canvas_config_ex(pic->y_canvas_index,
+		config_cav_lut_ex(pic->y_canvas_index,
 			pic->dw_y_adr, canvas_w, canvas_h,
-			CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
-		canvas_config_ex(pic->uv_canvas_index, pic->dw_u_v_adr,
+			CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7, VDEC_HEVC);
+		config_cav_lut_ex(pic->uv_canvas_index, pic->dw_u_v_adr,
 			canvas_w, canvas_h,
-			CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
+			CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7, VDEC_HEVC);
 #ifdef MULTI_INSTANCE_SUPPORT
 		pic->canvas_config[0].phy_addr =
 				pic->dw_y_adr;
@@ -8164,11 +8767,11 @@
 				blkmode;
 		pic->canvas_config[1].endian = hevc->is_used_v4l ? 0 : 7;
 
-		ATRACE_COUNTER(hevc->set_canvas0_addr, pic->canvas_config[0].phy_addr);
+		ATRACE_COUNTER(hevc->trace.set_canvas0_addr, pic->canvas_config[0].phy_addr);
 		hevc_print(hevc, H265_DEBUG_PIC_STRUCT,"%s(canvas0 addr:0x%x)\n",
 			__func__, pic->canvas_config[0].phy_addr);
 #else
-		ATRACE_COUNTER(hevc->set_canvas0_addr, spec2canvas(pic));
+		ATRACE_COUNTER(hevc->trace.set_canvas0_addr, spec2canvas(pic));
 		hevc_print(hevc, H265_DEBUG_PIC_STRUCT,"%s(canvas0 addr:0x%x)\n",
 			__func__, spec2canvas(pic));
 #endif
@@ -8184,14 +8787,14 @@
 				pic->uv_canvas_index = 128 + pic->index;
 			}
 
-			canvas_config_ex(pic->y_canvas_index,
+			config_cav_lut_ex(pic->y_canvas_index,
 				pic->mc_y_adr, canvas_w, canvas_h,
-				CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
-			canvas_config_ex(pic->uv_canvas_index, pic->mc_u_v_adr,
+				CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7, VDEC_HEVC);
+			config_cav_lut_ex(pic->uv_canvas_index, pic->mc_u_v_adr,
 				canvas_w, canvas_h,
-				CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
+				CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7, VDEC_HEVC);
 		}
-		ATRACE_COUNTER(hevc->set_canvas0_addr, spec2canvas(pic));
+		ATRACE_COUNTER(hevc->trace.set_canvas0_addr, spec2canvas(pic));
 		hevc_print(hevc, H265_DEBUG_PIC_STRUCT,"%s(canvas0 addr:0x%x)\n",
 			__func__, spec2canvas(pic));
 	}
@@ -8207,13 +8810,13 @@
 	}
 
 
-	canvas_config_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h,
-		CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
-	canvas_config_ex(pic->uv_canvas_index, pic->mc_u_v_adr,
+	config_cav_lut_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h,
+		CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7, VDEC_HEVC);
+	config_cav_lut_ex(pic->uv_canvas_index, pic->mc_u_v_adr,
 		canvas_w, canvas_h,
-		CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
+		CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7, VDEC_HEVC);
 
-	ATRACE_COUNTER(hevc->set_canvas0_addr, spec2canvas(pic));
+	ATRACE_COUNTER(hevc->trace.set_canvas0_addr, spec2canvas(pic));
 	hevc_print(hevc, H265_DEBUG_PIC_STRUCT,"%s(canvas0 addr:0x%x)\n",
 		__func__, spec2canvas(pic));
 #endif
@@ -8247,8 +8850,8 @@
 	char *p = sei_buf;
 	char *p_sei;
 	uint16_t header;
-	uint8_t nal_unit_type;
-	uint8_t payload_type, payload_size;
+	uint16_t nal_unit_type;
+	uint16_t payload_type, payload_size;
 	int i, j;
 
 	if (size < 2)
@@ -8260,9 +8863,16 @@
 	if ((nal_unit_type != NAL_UNIT_SEI)
 	&& (nal_unit_type != NAL_UNIT_SEI_SUFFIX))
 		return 0;
-	while (p+2 <= sei_buf+size) {
+	while (p+4 <= sei_buf+size) {
 		payload_type = *p++;
+		if (payload_type == 0xff) {
+			payload_type += *p++;
+		}
 		payload_size = *p++;
+		if (payload_size == 0xff) {
+			payload_size += *p++;
+		}
+
 		if (p+payload_size <= sei_buf+size) {
 			switch (payload_type) {
 			case SEI_PicTiming:
@@ -8301,6 +8911,25 @@
 						pic->hdr10p_data_buf = NULL;
 						pic->hdr10p_data_size = 0;
 					}
+				} else if (p_sei[0] == 0x26
+					&& p_sei[1] == 0x00
+					&& p_sei[2] == 0x04
+					&& p_sei[3] == 0x00
+					&& p_sei[4] == 0x05) {
+					hevc->sei_present_flag |= SEI_HDR_CUVA_MASK;
+
+					if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) {
+						hevc_print(hevc, 0,
+							"hdr cuva data: (size %d)\n",
+							payload_size);
+						for (i = 0; i < payload_size; i++) {
+							hevc_print_cont(hevc, 0,
+								"%02x ", p_sei[i]);
+							if (((i + 1) & 0xf) == 0)
+								hevc_print_cont(hevc, 0, "\n");
+						}
+						hevc_print_cont(hevc, 0, "\n");
+					}
 				}
 
 				break;
@@ -8460,9 +9089,9 @@
 		= &vf->prop.master_display_colour;
 
 	vf->width = pic->width /
-		get_double_write_ratio(hevc, pic->double_write_mode);
+		get_double_write_ratio(pic->double_write_mode);
 	vf->height = pic->height /
-		get_double_write_ratio(hevc, pic->double_write_mode);
+		get_double_write_ratio(pic->double_write_mode);
 
 	vf->duration = hevc->frame_dur;
 	vf->duration_pulldown = 0;
@@ -8520,6 +9149,14 @@
 			data = data | (0x30<<8);
 			vf->signal_type = data;
 		}
+
+		if (hevc->sei_present_flag & SEI_HDR_CUVA_MASK) {
+			u32 data;
+			data = vf->signal_type;
+			data = data & 0x7FFFFFFF;
+			data = data | (1<<31);
+			vf->signal_type = data;
+		}
 	}
 	else
 		vf->signal_type = 0;
@@ -8550,7 +9187,8 @@
 		vf_dp->content_light_level.present_flag = 0;
 
 	if (hevc->is_used_v4l &&
-		((hevc->sei_present_flag & SEI_HDR10PLUS_MASK) ||
+		((hevc->video_signal_type & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) ||
+		(hevc->sei_present_flag & SEI_HDR10PLUS_MASK) ||
 		(vf_dp->present_flag) ||
 		(vf_dp->content_light_level.present_flag))) {
 		struct aml_vdec_hdr_infos hdr;
@@ -8565,32 +9203,34 @@
 
 	if ((hevc->sei_present_flag & SEI_HDR10PLUS_MASK) && (pic->hdr10p_data_buf != NULL)
 		&& (pic->hdr10p_data_size != 0)) {
-		char *new_buf;
-		new_buf = vzalloc(pic->hdr10p_data_size);
+		if (pic->hdr10p_data_size <= 128) {
+			char *new_buf;
+			new_buf = kzalloc(pic->hdr10p_data_size, GFP_ATOMIC);
 
-		if (new_buf) {
-			memcpy(new_buf, pic->hdr10p_data_buf, pic->hdr10p_data_size);
-			if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) {
-				hevc_print(hevc, 0,
-					"hdr10p data: (size %d)\n",
-					pic->hdr10p_data_size);
-				for (i = 0; i < pic->hdr10p_data_size; i++) {
-					hevc_print_cont(hevc, 0,
-						"%02x ", pic->hdr10p_data_buf[i]);
-					if (((i + 1) & 0xf) == 0)
-						hevc_print_cont(hevc, 0, "\n");
+			if (new_buf) {
+				memcpy(new_buf, pic->hdr10p_data_buf, pic->hdr10p_data_size);
+				if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) {
+					hevc_print(hevc, 0,
+						"hdr10p data: (size %d)\n",
+						pic->hdr10p_data_size);
+					for (i = 0; i < pic->hdr10p_data_size; i++) {
+						hevc_print_cont(hevc, 0,
+							"%02x ", pic->hdr10p_data_buf[i]);
+						if (((i + 1) & 0xf) == 0)
+							hevc_print_cont(hevc, 0, "\n");
+					}
+					hevc_print_cont(hevc, 0, "\n");
 				}
-				hevc_print_cont(hevc, 0, "\n");
-			}
 
-			vf->hdr10p_data_size = pic->hdr10p_data_size;
-			vf->hdr10p_data_buf = new_buf;
-		} else {
-			hevc_print(hevc, 0,
-				"%s:hdr10p data vzalloc size(%d) fail\n",
-				__func__, pic->hdr10p_data_size);
-			vf->hdr10p_data_buf = NULL;
-			vf->hdr10p_data_size = 0;
+				vf->hdr10p_data_size = pic->hdr10p_data_size;
+				vf->hdr10p_data_buf = new_buf;
+			} else {
+				hevc_print(hevc, 0,
+					"%s:hdr10p data vzalloc size(%d) fail\n",
+					__func__, pic->hdr10p_data_size);
+				vf->hdr10p_data_buf = NULL;
+				vf->hdr10p_data_size = 0;
+			}
 		}
 
 		vfree(pic->hdr10p_data_buf);
@@ -8676,6 +9316,7 @@
 		return NULL;
 	else if (step == 1)
 		step = 2;
+
 #if 0
 	if (force_disp_pic_index & 0x100) {
 		int buffer_index = force_disp_pic_index & 0xff;
@@ -8740,9 +9381,9 @@
 		set_frame_info(hevc, vf);
 
 		vf->width = pic->width /
-			get_double_write_ratio(hevc, pic->double_write_mode);
+			get_double_write_ratio(pic->double_write_mode);
 		vf->height = pic->height /
-			get_double_write_ratio(hevc, pic->double_write_mode);
+			get_double_write_ratio(pic->double_write_mode);
 
 		force_disp_pic_index |= 0x200;
 		return vf;
@@ -8752,17 +9393,17 @@
 	if (kfifo_get(&hevc->display_q, &vf)) {
 		struct vframe_s *next_vf = NULL;
 
-		ATRACE_COUNTER(hevc->vf_get_name, (long)vf);
-		ATRACE_COUNTER(hevc->disp_q_name, kfifo_len(&hevc->display_q));
+		ATRACE_COUNTER(hevc->trace.vf_get_name, (long)vf);
+		ATRACE_COUNTER(hevc->trace.disp_q_name, kfifo_len(&hevc->display_q));
 #ifdef MULTI_INSTANCE_SUPPORT
-		ATRACE_COUNTER(hevc->set_canvas0_addr, vf->canvas0_config[0].phy_addr);
+		ATRACE_COUNTER(hevc->trace.set_canvas0_addr, vf->canvas0_config[0].phy_addr);
 #else
-		ATRACE_COUNTER(hevc->get_canvas0_addr, vf->canvas0Addr);
+		ATRACE_COUNTER(hevc->trace.get_canvas0_addr, vf->canvas0Addr);
 #endif
 
 		if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT) {
 			hevc_print(hevc, 0,
-				"%s(vf 0x%p type %d index 0x%x poc %d/%d) pts(%d,%ld) dur %d\n",
+				"%s(vf 0x%p type %d index 0x%x poc %d/%d) pts(%d,%d) dur %d\n",
 				__func__, vf, vf->type, vf->index,
 				get_pic_poc(hevc, vf->index & 0xff),
 				get_pic_poc(hevc, (vf->index >> 8) & 0xff),
@@ -8792,8 +9433,8 @@
 		}
 #endif
 		hevc->show_frame_num++;
-		vf->index_disp = hevc->vf_get_count;
-		hevc->vf_get_count++;
+		vf->index_disp = atomic_read(&hevc->vf_get_count);
+		atomic_add(1, &hevc->vf_get_count);
 
 		if (kfifo_peek(&hevc->display_q, &next_vf) && next_vf) {
 			vf->next_vf_pts_valid = true;
@@ -8831,23 +9472,39 @@
 	unsigned char index_top;
 	unsigned char index_bot;
 
-	if (vf && (vf_valid_check(vf, hevc) == false))
+	if (!vf)
 		return;
 	if (vf == (&hevc->vframe_dummy))
 		return;
-	if (!vf)
+	if (vf && (vf_valid_check(vf, hevc) == false))
 		return;
 
-	ATRACE_COUNTER(hevc->vf_put_name, (long)vf);
-#ifdef MULTI_INSTANCE_SUPPORT
-	ATRACE_COUNTER(hevc->put_canvas0_addr, vf->canvas0_config[0].phy_addr);
-#else
-	ATRACE_COUNTER(hevc->put_canvas0_addr, vf->canvas0Addr);
-#endif
+	if (hevc->enable_fence && vf->fence) {
+		int ret, i;
 
+		mutex_lock(&hevc->fence_mutex);
+		ret = dma_fence_get_status(vf->fence);
+		if (ret == 0) {
+			for (i = 0; i < VF_POOL_SIZE; i++) {
+				if (hevc->fence_vf_s.fence_vf[i] == NULL) {
+					hevc->fence_vf_s.fence_vf[i] = vf;
+					hevc->fence_vf_s.used_size++;
+					mutex_unlock(&hevc->fence_mutex);
+					return;
+				}
+			}
+		}
+		mutex_unlock(&hevc->fence_mutex);
+	}
+
+	ATRACE_COUNTER(hevc->trace.vf_put_name, (long)vf);
+#ifdef MULTI_INSTANCE_SUPPORT
+	ATRACE_COUNTER(hevc->trace.put_canvas0_addr, vf->canvas0_config[0].phy_addr);
+#else
+	ATRACE_COUNTER(hevc->trace.put_canvas0_addr, vf->canvas0Addr);
+#endif
 	index_top = vf->index & 0xff;
 	index_bot = (vf->index >> 8) & 0xff;
-
 	if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT)
 		hevc_print(hevc, 0,
 			"%s(vf 0x%p type %d index 0x%x put canvas0 addr:0x%x)\n",
@@ -8858,27 +9515,25 @@
 			, vf->canvas0Addr
 #endif
 			);
-
-	hevc->vf_put_count++;
+	atomic_add(1, &hevc->vf_put_count);
 	spin_lock_irqsave(&lock, flags);
 	kfifo_put(&hevc->newframe_q, (const struct vframe_s *)vf);
-	ATRACE_COUNTER(hevc->new_q_name, kfifo_len(&hevc->newframe_q));
+	ATRACE_COUNTER(hevc->trace.new_q_name, kfifo_len(&hevc->newframe_q));
 	if (hevc->enable_fence && vf->fence) {
 		vdec_fence_put(vf->fence);
 		vf->fence = NULL;
 	}
 
 	if (vf->hdr10p_data_buf) {
-		vfree(vf->hdr10p_data_buf);
+		kfree(vf->hdr10p_data_buf);
 		vf->hdr10p_data_buf = NULL;
 		vf->hdr10p_data_size = 0;
 	}
 
+
 	if (index_top != 0xff
 		&& index_top < MAX_REF_PIC_NUM
 		&& hevc->m_PIC[index_top]) {
-		if (hevc->is_used_v4l)
-			hevc->m_PIC[index_top]->vframe_bound = true;
 		if (hevc->m_PIC[index_top]->vf_ref > 0) {
 			hevc->m_PIC[index_top]->vf_ref--;
 
@@ -8896,8 +9551,6 @@
 	if (index_bot != 0xff
 		&& index_bot < MAX_REF_PIC_NUM
 		&& hevc->m_PIC[index_bot]) {
-		if (hevc->is_used_v4l)
-			hevc->m_PIC[index_bot]->vframe_bound = true;
 		if (hevc->m_PIC[index_bot]->vf_ref > 0) {
 			hevc->m_PIC[index_bot]->vf_ref--;
 
@@ -8944,13 +9597,14 @@
 		unsigned char index;
 
 		if (!req->vf) {
-			req->aux_size = hevc->vf_put_count;
+			req->aux_size = atomic_read(&hevc->vf_put_count);
 			return 0;
 		}
 		spin_lock_irqsave(&lock, flags);
 		index = req->vf->index & 0xff;
 		req->aux_buf = NULL;
 		req->aux_size = 0;
+		req->format = VFORMAT_HEVC;
 		if (req->bot_flag)
 			index = (req->vf->index >> 8) & 0xff;
 		if (index != 0xff
@@ -9023,6 +9677,8 @@
 
 	if (kfifo_len(&hevc->pending_q) > 1) {
 		unsigned long flags;
+		int index1;
+		int index2;
 		/* do not pending more than 1 frame */
 		if (kfifo_get(&hevc->pending_q, &vf) == 0) {
 			hevc_print(hevc, 0,
@@ -9031,34 +9687,45 @@
 		}
 		if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT)
 			hevc_print(hevc, 0,
-			"%s warning(1), vf=>display_q: (index 0x%x)\n",
-				__func__, vf->index);
+			"%s warning(1), vf=>display_q: (index 0x%x), vf 0x%px\n",
+				__func__, vf->index, vf);
 		if ((pair_pic->double_write_mode == 3) &&
 				(!(IS_8K_SIZE(vf->width, vf->height)))) {
 					vf->type |= VIDTYPE_COMPRESS;
 					if (hevc->mmu_enable)
 						vf->type |= VIDTYPE_SCATTER;
 		}
+
 		hevc->vf_pre_count++;
 		spin_lock_irqsave(&lock, flags);
 		kfifo_put(&hevc->newframe_q, (const struct vframe_s *)vf);
-		vf->index &= 0xff;
-		if (vf->index >= MAX_REF_PIC_NUM) {
+		index1 = vf->index & 0xff;
+		index2 = (vf->index >> 8) & 0xff;
+		if (index1 >= MAX_REF_PIC_NUM &&
+			index2 >= MAX_REF_PIC_NUM) {
 			spin_unlock_irqrestore(&lock, flags);
 			return -1;
 		}
-		hevc->m_PIC[vf->index]->vf_ref = 0;
-		hevc->m_PIC[vf->index]->output_ready = 0;
+
+		if (index1 < MAX_REF_PIC_NUM) {
+			hevc->m_PIC[index1]->vf_ref = 0;
+			hevc->m_PIC[index1]->output_ready = 0;
+		}
+		if (index2 < MAX_REF_PIC_NUM) {
+			hevc->m_PIC[index2]->vf_ref = 0;
+			hevc->m_PIC[index2]->output_ready = 0;
+		}
+
 		if (hevc->wait_buf != 0)
 			WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG,
 				0x1);
 		spin_unlock_irqrestore(&lock, flags);
 
-		ATRACE_COUNTER(hevc->pts_name, vf->pts);
+		ATRACE_COUNTER(hevc->trace.pts_name, vf->pts);
 	}
 
 	if (kfifo_peek(&hevc->pending_q, &vf)) {
-		if (pair_pic->vf_ref <= 0) {
+		if (pair_pic == NULL || pair_pic->vf_ref <= 0) {
 			/*
 			 *if pair_pic is recycled (pair_pic->vf_ref <= 0),
 			 *do not use it
@@ -9083,7 +9750,7 @@
 				vdec_vframe_ready(hw_to_vdec(hevc), vf);
 				kfifo_put(&hevc->display_q,
 				(const struct vframe_s *)vf);
-				ATRACE_COUNTER(hevc->pts_name, vf->pts);
+				ATRACE_COUNTER(hevc->trace.pts_name, vf->pts);
 			}
 		} else if ((!pair_frame_top_flag) &&
 			(((vf->index >> 8) & 0xff) == 0xff)) {
@@ -9105,7 +9772,7 @@
 				vdec_vframe_ready(hw_to_vdec(hevc), vf);
 				kfifo_put(&hevc->display_q,
 				(const struct vframe_s *)vf);
-				ATRACE_COUNTER(hevc->pts_name, vf->pts);
+				ATRACE_COUNTER(hevc->trace.pts_name, vf->pts);
 				hevc->vf_pre_count++;
 				if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT)
 					hevc_print(hevc, 0,
@@ -9132,7 +9799,7 @@
 				vdec_vframe_ready(hw_to_vdec(hevc), vf);
 				kfifo_put(&hevc->display_q,
 				(const struct vframe_s *)vf);
-				ATRACE_COUNTER(hevc->pts_name, vf->pts);
+				ATRACE_COUNTER(hevc->trace.pts_name, vf->pts);
 				hevc->vf_pre_count++;
 				if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT)
 					hevc_print(hevc, 0,
@@ -9147,16 +9814,33 @@
 static void update_vf_memhandle(struct hevc_state_s *hevc,
 	struct vframe_s *vf, struct PIC_s *pic)
 {
-	if (pic->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(
-				hevc->mmu_box, pic->index);
-		vf->mem_head_handle =
-			decoder_bmmu_box_get_mem_handle(
-				hevc->bmmu_box, VF_BUFFER_IDX(pic->BUF_index));
+	vf->mem_handle = NULL;
+	vf->mem_head_handle = NULL;
+
+	/* keeper not needed for v4l solution */
+	if (hevc->is_used_v4l)
+		return;
+
+	if (vf->type & VIDTYPE_SCATTER) {
+#ifdef H265_10B_MMU_DW
+		if (hevc->dw_mmu_enable) {
+			vf->mem_handle =
+				decoder_mmu_box_get_mem_handle(
+					hevc->mmu_box_dw, pic->index);
+			vf->mem_head_handle =
+				decoder_bmmu_box_get_mem_handle(
+					hevc->bmmu_box, VF_BUFFER_IDX(pic->BUF_index));
+		} else
+
+#endif
+		{
+			vf->mem_handle =
+				decoder_mmu_box_get_mem_handle(
+					hevc->mmu_box, pic->index);
+			vf->mem_head_handle =
+				decoder_bmmu_box_get_mem_handle(
+					hevc->bmmu_box, VF_BUFFER_IDX(pic->BUF_index));
+		}
 	} else {
 		vf->mem_handle =
 			decoder_bmmu_box_get_mem_handle(
@@ -9228,11 +9912,11 @@
 
 }
 
-static inline void hevc_update_gvs(struct hevc_state_s *hevc)
+static inline void hevc_update_gvs(struct hevc_state_s *hevc, struct PIC_s *pic)
 {
-	if (hevc->gvs->frame_height != hevc->frame_height) {
-		hevc->gvs->frame_width = hevc->frame_width;
-		hevc->gvs->frame_height = hevc->frame_height;
+	if (hevc->gvs->frame_height != pic->height) {
+		hevc->gvs->frame_width = pic->width;
+		hevc->gvs->frame_height = pic->height;
 	}
 	if (hevc->gvs->frame_dur != hevc->frame_dur) {
 		hevc->gvs->frame_dur = hevc->frame_dur;
@@ -9254,7 +9938,7 @@
 	decoder_do_frame_check(hw_to_vdec(hevc), vf);
 	vdec_vframe_ready(hw_to_vdec(hevc), vf);
 	kfifo_put(&hevc->display_q, (const struct vframe_s *)vf);
-	ATRACE_COUNTER(hevc->pts_name, vf->pts);
+	ATRACE_COUNTER(hevc->trace.pts_name, vf->pts);
 }
 
 static int post_prepare_process(struct vdec_s *vdec, struct PIC_s *frame)
@@ -9266,7 +9950,7 @@
 		frame->output_ready = 0;
 		frame->show_frame = false;
 		hevc_print(hevc, 0, "discard show frame.\n");
-		return -1;
+		return 0;
 	}
 
 	frame->show_frame = true;
@@ -9284,6 +9968,8 @@
 	u32 frame_size = 0;
 	struct vdec_info tmp4x;
 	struct aml_vcodec_ctx * v4l2_ctx = hevc->v4l2_ctx;
+	struct vdec_v4l2_buffer *fb = NULL;
+	int index;
 
 	/* swap uv */
 	if (hevc->is_used_v4l) {
@@ -9306,11 +9992,12 @@
 		if (hevc->is_used_v4l) {
 			vf->v4l_mem_handle
 				= hevc->m_BUF[pic->BUF_index].v4l_ref_buf_addr;
+			fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
 			if (hevc->mmu_enable) {
 				vf->mm_box.bmmu_box	= hevc->bmmu_box;
-				vf->mm_box.bmmu_idx	= VF_BUFFER_IDX(pic->BUF_index);
+				vf->mm_box.bmmu_idx	= VF_BUFFER_IDX(hevc->buffer_wrap[pic->BUF_index]);
 				vf->mm_box.mmu_box	= hevc->mmu_box;
-				vf->mm_box.mmu_idx	= pic->index;
+				vf->mm_box.mmu_idx	= hevc->buffer_wrap[pic->BUF_index];
 			}
 		}
 
@@ -9340,7 +10027,8 @@
 			if ((vdec->vbuf.no_parser == 0) || (vdec->vbuf.use_ptsserv)) {
 				if (pts_lookup_offset_us64
 					(PTS_TYPE_VIDEO, stream_offset, &vf->pts,
-					&frame_size, 0, &vf->pts_us64) != 0) {
+					&frame_size, 0,
+					 &vf->pts_us64) != 0) {
 #ifdef DEBUG_PTS
 					hevc->pts_missed++;
 #endif
@@ -9388,8 +10076,8 @@
 		hevc->last_pts_us64 = vf->pts_us64;
 		if ((get_dbg_flag(hevc) & H265_DEBUG_OUT_PTS) != 0) {
 			hevc_print(hevc, 0,
-			"H265 dec out pts: vf->pts=%d, vf->pts_us64 = %lld\n",
-			 vf->pts, vf->pts_us64);
+			"H265 dec out pts: vf->pts=%d, vf->pts_us64 = %lld, ts: %llu\n",
+			 vf->pts, vf->pts_us64, vf->timestamp);
 		}
 
 		/*
@@ -9409,26 +10097,44 @@
 			/* double write only */
 			vf->compBodyAddr = 0;
 			vf->compHeadAddr = 0;
+#ifdef H265_10B_MMU_DW
+			vf->dwBodyAddr = 0;
+			vf->dwHeadAddr = 0;
+#endif
 		} else {
-
-		if (hevc->mmu_enable) {
-			vf->compBodyAddr = 0;
-			vf->compHeadAddr = pic->header_adr;
-		} else {
-			vf->compBodyAddr = pic->mc_y_adr; /*body adr*/
-			vf->compHeadAddr = pic->mc_y_adr +
-						pic->losless_comp_body_size;
-			vf->mem_head_handle = NULL;
-		}
-
-					/*head adr*/
+			if (hevc->mmu_enable) {
+				vf->compBodyAddr = 0;
+				vf->compHeadAddr = pic->header_adr;
+#ifdef H265_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->header_dw_adr;
+					else if ((mode == 1 || mode == 2 || mode == 4)
+					&& (debug & H265_DEBUG_OUT_PTS) == 0) {
+						vf->compHeadAddr = pic->header_dw_adr;
+						pr_debug("Use dw mmu for display\n");
+					}
+				}
+#endif
+			} else {
+				vf->compBodyAddr = pic->mc_y_adr; /*body adr*/
+				vf->compHeadAddr = pic->mc_y_adr +
+							pic->losless_comp_body_size;
+				vf->mem_head_handle = NULL;
+			}
+			/*head adr*/
 			vf->canvas0Addr = vf->canvas1Addr = 0;
 		}
-		if (pic->double_write_mode) {
+		if (pic->double_write_mode &&
+			((pic->double_write_mode & 0x20) == 0)) {
 			vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
 			vf->type |= nv_order;
 
-			if (((pic->double_write_mode == 3) || (pic->double_write_mode == 5)) &&
+			if (((pic->double_write_mode == 3) || (pic->double_write_mode == 5) ||
+				(pic->double_write_mode == 9)) &&
 				(!(IS_8K_SIZE(pic->width, pic->height)))) {
 				vf->type |= VIDTYPE_COMPRESS;
 				if (hevc->mmu_enable)
@@ -9580,9 +10286,21 @@
 			vf->sar_height = hevc->cur_pic->sar_height;
 		}
 		vf->width = vf->width /
-			get_double_write_ratio(hevc, pic->double_write_mode);
+			get_double_write_ratio(pic->double_write_mode & 0xf);
 		vf->height = vf->height /
-			get_double_write_ratio(hevc, pic->double_write_mode);
+			get_double_write_ratio(pic->double_write_mode & 0xf);
+
+#ifdef H265_10B_MMU_DW
+		if ((pic->double_write_mode & 0x20) &&
+			((pic->double_write_mode & 0xf) == 2 ||
+			(pic->double_write_mode & 0xf) == 4)) {
+			vf->compWidth = vf->width;
+			vf->compHeight = vf->height;
+		}
+#endif
+		if (hevc->is_used_v4l && vdec->prog_only)
+			pic->pic_struct = 0;
+
 #ifdef HEVC_PIC_STRUCT_SUPPORT
 		if (pic->pic_struct == 3 || pic->pic_struct == 4) {
 			struct vframe_s *vf2;
@@ -9613,12 +10331,20 @@
 				vf2->type = VIDTYPE_INTERLACE_TOP
 				| nv_order;
 			}
-			put_vf_to_display_q(hevc, vf);
-			hevc->vf_pre_count++;
-			vdec_vframe_ready(hw_to_vdec(hevc), vf2);
-			kfifo_put(&hevc->display_q,
-			(const struct vframe_s *)vf2);
-			ATRACE_COUNTER(hevc->pts_name, vf2->pts);
+			if (pic->show_frame) {
+				put_vf_to_display_q(hevc, vf);
+				hevc->vf_pre_count++;
+				vdec_vframe_ready(hw_to_vdec(hevc), vf2);
+				kfifo_put(&hevc->display_q,
+				(const struct vframe_s *)vf2);
+				ATRACE_COUNTER(hevc->trace.pts_name, vf2->pts);
+			} else {
+				vh265_vf_put(vf, vdec);
+				vh265_vf_put(vf2, vdec);
+				atomic_add(2, &hevc->vf_get_count);
+				hevc->vf_pre_count += 2;
+				return 0;
+			}
 		} else if (pic->pic_struct == 5
 			|| pic->pic_struct == 6) {
 			struct vframe_s *vf2, *vf3;
@@ -9659,18 +10385,26 @@
 				vf3->type = VIDTYPE_INTERLACE_BOTTOM
 				| nv_order;
 			}
-			put_vf_to_display_q(hevc, vf);
-			hevc->vf_pre_count++;
-			vdec_vframe_ready(hw_to_vdec(hevc), vf2);
-			kfifo_put(&hevc->display_q,
-			(const struct vframe_s *)vf2);
-			ATRACE_COUNTER(hevc->pts_name, vf2->pts);
-			hevc->vf_pre_count++;
-			vdec_vframe_ready(hw_to_vdec(hevc), vf3);
-			kfifo_put(&hevc->display_q,
-			(const struct vframe_s *)vf3);
-			ATRACE_COUNTER(hevc->pts_name, vf3->pts);
-
+			if (pic->show_frame) {
+				put_vf_to_display_q(hevc, vf);
+				hevc->vf_pre_count++;
+				vdec_vframe_ready(hw_to_vdec(hevc), vf2);
+				kfifo_put(&hevc->display_q,
+				(const struct vframe_s *)vf2);
+				ATRACE_COUNTER(hevc->trace.pts_name, vf2->pts);
+				hevc->vf_pre_count++;
+				vdec_vframe_ready(hw_to_vdec(hevc), vf3);
+				kfifo_put(&hevc->display_q,
+				(const struct vframe_s *)vf3);
+				ATRACE_COUNTER(hevc->trace.pts_name, vf3->pts);
+			} else {
+				vh265_vf_put(vf, vdec);
+				vh265_vf_put(vf2, vdec);
+				vh265_vf_put(vf3, vdec);
+				atomic_add(3, &hevc->vf_get_count);
+				hevc->vf_pre_count += 3;;
+				return 0;
+			}
 		} else if (pic->pic_struct == 9
 			|| pic->pic_struct == 10) {
 			if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT)
@@ -9683,35 +10417,40 @@
 			/* process previous pending vf*/
 			process_pending_vframe(hevc,
 			pic, (pic->pic_struct == 9));
-
-			decoder_do_frame_check(vdec, vf);
-			vdec_vframe_ready(vdec, vf);
-			/* process current vf */
-			kfifo_put(&hevc->pending_q,
-			(const struct vframe_s *)vf);
 			vf->height <<= 1;
-			if (pic->pic_struct == 9) {
-				vf->type = VIDTYPE_INTERLACE_TOP
-				| nv_order | VIDTYPE_VIU_FIELD;
-				process_pending_vframe(hevc,
-				hevc->pre_bot_pic, 0);
+			if (pic->show_frame) {
+				decoder_do_frame_check(vdec, vf);
+				vdec_vframe_ready(vdec, vf);
+				/* process current vf */
+				kfifo_put(&hevc->pending_q,
+				(const struct vframe_s *)vf);
+				if (pic->pic_struct == 9) {
+					vf->type = VIDTYPE_INTERLACE_TOP
+					| nv_order | VIDTYPE_VIU_FIELD;
+					process_pending_vframe(hevc,
+					hevc->pre_bot_pic, 0);
+				} else {
+					vf->type = VIDTYPE_INTERLACE_BOTTOM |
+					nv_order | VIDTYPE_VIU_FIELD;
+					vf->index = (pic->index << 8) | 0xff;
+					process_pending_vframe(hevc,
+					hevc->pre_top_pic, 1);
+				}
+
+				if (hevc->vf_pre_count == 0)
+					hevc->vf_pre_count++;
+
+				/**/
+				if (pic->pic_struct == 9)
+					hevc->pre_top_pic = pic;
+				else
+					hevc->pre_bot_pic = pic;
 			} else {
-				vf->type = VIDTYPE_INTERLACE_BOTTOM |
-				nv_order | VIDTYPE_VIU_FIELD;
-				vf->index = (pic->index << 8) | 0xff;
-				process_pending_vframe(hevc,
-				hevc->pre_top_pic, 1);
-			}
-
-			if (hevc->vf_pre_count == 0)
+				vh265_vf_put(vf, vdec);
+				atomic_add(1, &hevc->vf_get_count);
 				hevc->vf_pre_count++;
-
-			/**/
-			if (pic->pic_struct == 9)
-				hevc->pre_top_pic = pic;
-			else
-				hevc->pre_bot_pic = pic;
-
+				return 0;
+			}
 		} else if (pic->pic_struct == 11
 		    || pic->pic_struct == 12) {
 			if (get_dbg_flag(hevc) & H265_DEBUG_PIC_STRUCT)
@@ -9734,19 +10473,25 @@
 				nv_order | VIDTYPE_VIU_FIELD;
 				vf->index = (pic->index << 8) | 0xff;
 			}
-			decoder_do_frame_check(vdec, vf);
-			vdec_vframe_ready(vdec, vf);
-			kfifo_put(&hevc->pending_q,
-			(const struct vframe_s *)vf);
-			if (hevc->vf_pre_count == 0)
+			if (pic->show_frame) {
+				decoder_do_frame_check(vdec, vf);
+				vdec_vframe_ready(vdec, vf);
+				kfifo_put(&hevc->pending_q,
+				(const struct vframe_s *)vf);
+				if (hevc->vf_pre_count == 0)
+					hevc->vf_pre_count++;
+
+				/**/
+				if (pic->pic_struct == 11)
+					hevc->pre_top_pic = pic;
+				else
+					hevc->pre_bot_pic = pic;
+			} else {
+				vh265_vf_put(vf, vdec);
+				atomic_add(1, &hevc->vf_get_count);
 				hevc->vf_pre_count++;
-
-			/**/
-			if (pic->pic_struct == 11)
-				hevc->pre_top_pic = pic;
-			else
-				hevc->pre_bot_pic = pic;
-
+				return 0;
+			}
 		} else {
 			pic->vf_ref = 1;
 
@@ -9779,50 +10524,81 @@
 				hevc->pre_bot_pic = pic;
 				break;
 			}
-			put_vf_to_display_q(hevc, vf);
+			if (pic->show_frame) {
+				put_vf_to_display_q(hevc, vf);
+			} else {
+				vh265_vf_put(vf, vdec);
+				atomic_add(1, &hevc->vf_get_count);
+				hevc->vf_pre_count++;
+				return 0;
+			}
 		}
 #else
 		vf->type_original = vf->type;
 		pic->vf_ref = 1;
 		put_vf_to_display_q(hevc, vf);
 #endif
-		ATRACE_COUNTER(hevc->new_q_name, kfifo_len(&hevc->newframe_q));
-		ATRACE_COUNTER(hevc->disp_q_name, kfifo_len(&hevc->display_q));
+		ATRACE_COUNTER(hevc->trace.new_q_name, kfifo_len(&hevc->newframe_q));
+		ATRACE_COUNTER(hevc->trace.disp_q_name, kfifo_len(&hevc->display_q));
 		/*count info*/
 		vdec_count_info(hevc->gvs, 0, stream_offset);
-		if (hevc->cur_pic != NULL) {
-			if (hevc->cur_pic->slice_type == I_SLICE) {
-				hevc->gvs->i_decoded_frames++;
-			} else if (hevc->cur_pic->slice_type == P_SLICE) {
-				hevc->gvs->p_decoded_frames++;
-			} else if (hevc->cur_pic->slice_type == B_SLICE) {
-				hevc->gvs->b_decoded_frames++;
-			}
+		if (pic->slice_type == I_SLICE) {
+			hevc->gvs->i_decoded_frames++;
+			vf->frame_type |= V4L2_BUF_FLAG_KEYFRAME;
+		} else if (pic->slice_type == P_SLICE) {
+			hevc->gvs->p_decoded_frames++;
+			vf->frame_type |= V4L2_BUF_FLAG_PFRAME;
+		} else if (pic->slice_type == B_SLICE) {
+			hevc->gvs->b_decoded_frames++;
+			vf->frame_type |= V4L2_BUF_FLAG_BFRAME;
 		}
-		hevc_update_gvs(hevc);
+		hevc_update_gvs(hevc, pic);
 		memcpy(&tmp4x, hevc->gvs, sizeof(struct vdec_info));
-		tmp4x.bit_depth_luma = hevc->bit_depth_luma;
-		tmp4x.bit_depth_chroma = hevc->bit_depth_chroma;
-		tmp4x.double_write_mode = get_double_write_mode(hevc);
+		tmp4x.bit_depth_luma = pic->bit_depth_luma;
+		tmp4x.bit_depth_chroma = pic->bit_depth_chroma;
+		tmp4x.double_write_mode = pic->double_write_mode;
 		vdec_fill_vdec_frame(vdec, &hevc->vframe_qos, &tmp4x, vf, pic->hw_decode_time);
 		vdec->vdec_fps_detec(vdec->id);
 		hevc_print(hevc, H265_DEBUG_BUFMGR,
-			"%s(type %d index 0x%x poc %d/%d) pts(%d,%lld) dur %d\n",
+			"%s(type %d index 0x%x poc %d/%d) pts(%d,%d) dur %d\n",
 			__func__, vf->type, vf->index,
 			get_pic_poc(hevc, vf->index & 0xff),
 			get_pic_poc(hevc, (vf->index >> 8) & 0xff),
 			vf->pts, vf->pts_us64,
 			vf->duration);
+
+		if (pic->pic_struct == 10 || pic->pic_struct == 12) {
+			index = (vf->index >> 8) & 0xff;
+		} else {
+			index = vf->index & 0xff;
+		}
+
 #ifdef AUX_DATA_CRC
-		if ((vf->index & 0xff) <= MAX_REF_PIC_NUM)
-			decoder_do_aux_data_check(vdec, hevc->m_PIC[vf->index & 0xff]->aux_data_buf,
-				hevc->m_PIC[vf->index & 0xff]->aux_data_size);
+		if (index <= MAX_REF_PIC_NUM)
+			decoder_do_aux_data_check(vdec, hevc->m_PIC[index]->aux_data_buf,
+				hevc->m_PIC[index]->aux_data_size);
 #endif
+
+		hevc_print(hevc, H265_DEBUG_PRINT_SEI,
+			"aux_data_size:%d, signal_type: %d, sei_present_flag: %d\n",
+			hevc->m_PIC[index]->aux_data_size, hevc->video_signal_type, hevc->sei_present_flag);
+
+		if (get_dbg_flag(hevc) & H265_DEBUG_PRINT_SEI) {
+			int i = 0;
+			PR_INIT(128);
+			for (i = 0; i < hevc->m_PIC[index]->aux_data_size; i++) {
+				PR_FILL("%02x ", hevc->m_PIC[index]->aux_data_buf[i]);
+				if (((i + 1) & 0xf) == 0)
+					PR_INFO(hevc->index);
+			}
+			PR_INFO(hevc->index);
+		}
+
 		if (hevc->is_used_v4l)
 			update_vframe_src_fmt(vf,
-				hevc->m_PIC[vf->index & 0xff]->aux_data_buf,
-				hevc->m_PIC[vf->index & 0xff]->aux_data_size,
-				false, hevc->provider_name, NULL);
+				hevc->m_PIC[index]->aux_data_buf,
+				hevc->m_PIC[index]->aux_data_size,
+				hevc->dv_duallayer, hevc->provider_name, NULL);
 
 		/*if (pic->vf_ref == hevc->vf_pre_count) {*/
 		if (hevc->kpi_first_i_decoded == 0) {
@@ -9832,8 +10608,16 @@
 		}
 
 		if (without_display_mode == 0) {
-			vf_notify_receiver(hevc->provider_name,
-				VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+			if (hevc->is_used_v4l) {
+				if (v4l2_ctx->is_stream_off) {
+					vh265_vf_put(vh265_vf_get(vdec), vdec);
+				} else {
+					fb->task->submit(fb->task, TASK_TYPE_DEC);
+				}
+			} else {
+				vf_notify_receiver(hevc->provider_name,
+					VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+			}
 		}
 		else
 			vh265_vf_put(vh265_vf_get(vdec), vdec);
@@ -9851,10 +10635,10 @@
 		return 0;
 
 	/* create fence for each buffers. */
-	if (vdec_timeline_create_fence(&vdec->sync))
+	if (vdec_timeline_create_fence(vdec->sync))
 		return -1;
 
-	pic->fence		= vdec->sync.fence;
+	pic->fence		= vdec->sync->fence;
 	pic->stream_offset	= READ_VREG(HEVC_SHIFT_BYTE_COUNT);
 
 	if (hevc->chunk) {
@@ -9862,7 +10646,7 @@
 		pic->pts64	= hevc->chunk->pts64;
 		pic->timestamp	= hevc->chunk->timestamp;
 	}
-
+	pic->show_frame = true;
 	post_video_frame(vdec, pic);
 
 	display_frame_count[hevc->index]++;
@@ -9876,6 +10660,10 @@
 		(struct hevc_state_s *)vdec->private;
 
 	if (hevc->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)
@@ -9884,16 +10672,35 @@
 		hevc->m_PIC[frame->index]->vf_ref = 1;
 
 		/* notify signal to wake up wq of fence. */
-		vdec_timeline_increase(&vdec->sync, 1);
+		vdec_timeline_increase(vdec->sync, 1);
+		mutex_lock(&hevc->fence_mutex);
+		used_size = hevc->fence_vf_s.used_size;
+		if (used_size) {
+			for (i = 0, j = 0; i < VF_POOL_SIZE && j < used_size; i++) {
+				if (hevc->fence_vf_s.fence_vf[i] != NULL) {
+					ret = dma_fence_get_status(hevc->fence_vf_s.fence_vf[i]->fence);
+					if (ret == 1) {
+						signed_fence[signed_count] = hevc->fence_vf_s.fence_vf[i];
+						hevc->fence_vf_s.fence_vf[i] = NULL;
+						hevc->fence_vf_s.used_size--;
+						signed_count++;
+					}
+					j++;
+				}
+			}
+		}
+		mutex_unlock(&hevc->fence_mutex);
+		if (signed_count != 0) {
+			for (i = 0; i < signed_count; i++)
+				vh265_vf_put(signed_fence[i], vdec);
+		}
+
 		return 0;
 	}
 
 	if (post_prepare_process(vdec, frame))
 		return -1;
 
-	if (!frame->show_frame)
-		return 0;
-
 	if (post_video_frame(vdec, frame))
 		return -1;
 
@@ -9920,7 +10727,8 @@
 			}
 
 			if (index == INVALID_IDX) {
-				if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) {
+				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;
 				}
@@ -9932,10 +10740,16 @@
 		vf->flag		= VFRAME_FLAG_EMPTY_FRAME_V4L;
 		vf->v4l_mem_handle	= (index == INVALID_IDX) ? (ulong)fb :
 					hw->m_BUF[index].v4l_ref_buf_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);
-		vf_notify_receiver(vdec->vf_provider_name,
-			VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+
+		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] H265 EOS notify.\n", (hw->is_used_v4l)?ctx->id:vdec->id);
 	}
@@ -10266,7 +11080,7 @@
 	struct vdec_s *vdec = hw_to_vdec(hevc);
 
 	if (get_dbg_flag(hevc) &
-		H265_DEBUG_BUFMGR_MORE)
+		H265_DEBUG_PRINT_SEI)
 		dump_aux_buf(hevc);
 	if (vdec->dolby_meta_with_el || vdec->slave) {
 		set_aux_data(hevc,
@@ -10297,49 +11111,123 @@
 	hevc->rps_set_id = (decode_info >> 8) & 0xff;
 }
 
-static int vh265_get_ps_info(struct hevc_state_s *hevc, int width, int height, struct aml_vdec_ps_infos *ps)
+static int vh265_get_ps_info(struct hevc_state_s *hevc,
+			     union param_u *rpm_param,
+			     struct aml_vdec_ps_infos *ps)
 {
-	int dw_mode = v4l_parser_get_double_write_mode(hevc, width, height);
+	u32 width = rpm_param->p.pic_width_in_luma_samples;
+	u32 height = rpm_param->p.pic_height_in_luma_samples;
+	u32 SubWidthC, SubHeightC;
 
-	ps->visible_width 	= width / get_double_write_ratio(hevc, dw_mode);
-	ps->visible_height 	= height / get_double_write_ratio(hevc, dw_mode);
-	ps->coded_width 	= ALIGN(width, 32) / get_double_write_ratio(hevc, dw_mode);
-	ps->coded_height 	= ALIGN(height, 32) / get_double_write_ratio(hevc, dw_mode);
+	switch (rpm_param->p.chroma_format_idc) {
+	case 1:
+		SubWidthC = 2;
+		SubHeightC = 2;
+		break;
+	case 2:
+		SubWidthC = 2;
+		SubHeightC = 1;
+		break;
+	default:
+		SubWidthC = 1;
+		SubHeightC = 1;
+		break;
+	}
+
+	width -= SubWidthC *
+		(rpm_param->p.conf_win_left_offset +
+		rpm_param->p.conf_win_right_offset);
+	height -= SubHeightC *
+		(rpm_param->p.conf_win_top_offset +
+		rpm_param->p.conf_win_bottom_offset);
+
+	hevc->last_width = rpm_param->p.pic_width_in_luma_samples;
+	hevc->last_height = rpm_param->p.pic_height_in_luma_samples;
+	hevc->sps_num_reorder_pics_0 =
+		rpm_param->p.sps_num_reorder_pics_0;
+	hevc->used_buf_num = v4l_parser_work_pic_num(hevc);
+
+	ps->visible_width 	= width;
+	ps->visible_height 	= height;
+	ps->coded_width 	= ALIGN(width, 64);
+	ps->coded_height 	= ALIGN(height, 64);
 	ps->dpb_size 		= v4l_parser_work_pic_num(hevc);
-	ps->field 		= hevc->interlace_flag ? V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
 
 	return 0;
 }
 
+static void get_comp_buf_info(struct hevc_state_s *hevc,
+		struct vdec_comp_buf_info *info)
+{
+	u16 bit_depth = hevc->param.p.bit_depth;
+	int w = hevc->param.p.pic_width_in_luma_samples;
+	int h = hevc->param.p.pic_height_in_luma_samples;
+
+	info->max_size = hevc_max_mmu_buf_size(
+			hevc->max_pic_w,
+			hevc->max_pic_h);
+	info->header_size = hevc_get_header_size(w,h);
+	info->frame_buffer_size = hevc_mmu_page_num(
+			hevc, w, h,	bit_depth == 0);
+
+	pr_info("hevc get comp info: %d %d %d\n",
+			info->max_size, info->header_size,
+			info->frame_buffer_size);
+}
+
 static int v4l_res_change(struct hevc_state_s *hevc, union param_u *rpm_param)
 {
 	struct aml_vcodec_ctx *ctx =
 			(struct aml_vcodec_ctx *)(hevc->v4l2_ctx);
-	int ret = 0;
+	int i, ret = 0;
 
-	if (ctx->param_sets_from_ucode &&
-		hevc->res_ch_flag == 0) {
+	if (ctx->param_sets_from_ucode) {
 		struct aml_vdec_ps_infos ps;
 		int width = rpm_param->p.pic_width_in_luma_samples;
 		int height = rpm_param->p.pic_height_in_luma_samples;
-		if ((hevc->pic_w != 0 &&
-			hevc->pic_h != 0) &&
-			(hevc->pic_w != width ||
-			hevc->pic_h != height)) {
+		if ((hevc->last_width != 0 &&
+			hevc->last_height != 0) &&
+			(hevc->last_width != width ||
+			hevc->last_height != height)) {
 			hevc_print(hevc, 0,
 				"v4l_res_change Pic Width/Height Change (%d,%d)=>(%d,%d), interlace %d\n",
-				hevc->pic_w, hevc->pic_h,
+				hevc->last_width, hevc->last_height,
 				width,
 				height,
 				hevc->interlace_flag);
 
-			vh265_get_ps_info(hevc, width, height, &ps);
+			if (get_valid_double_write_mode(hevc) != 16) {
+				struct vdec_comp_buf_info info;
+
+				get_comp_buf_info(hevc, &info);
+				vdec_v4l_set_comp_buf_info(ctx, &info);
+			}
+
+			vh265_get_ps_info(hevc, &hevc->param, &ps);
 			vdec_v4l_set_ps_infos(ctx, &ps);
 			vdec_v4l_res_ch_event(ctx);
 			hevc->v4l_params_parsed = false;
-			hevc->res_ch_flag = 1;
 			ctx->v4l_resolution_change = 1;
 			hevc->eos = 1;
+
+			/*
+			 * marks frame valid on the dpb is the ouput state,
+			 * then via flush_output all frames can be flushed out.
+			 */
+			for (i = 0; i < MAX_REF_PIC_NUM; ++i) {
+				if ((hevc->m_PIC[i] == NULL) ||
+					(hevc->m_PIC[i]->index == -1) ||
+					(hevc->m_PIC[i]->BUF_index == -1))
+					continue;
+
+				if ((hevc->m_PIC[i]->POC != INVALID_POC) &&
+					(hevc->m_PIC[i]->output_ready == 0) &&
+					hevc->m_PIC[i]->referenced &&
+					(hevc->m_PIC[i]->POC >= hevc->decoded_poc)) {
+						hevc->m_PIC[i]->output_mark = 1;
+				}
+			}
+
 			flush_output(hevc, NULL);
 			//del_timer_sync(&hevc->timer);
 			notify_v4l_eos(hw_to_vdec(hevc));
@@ -10366,55 +11254,6 @@
 	return 0;
 }
 
-#ifdef VDEC_FCC_SUPPORT
-static void fcc_discard_mode_process(struct vdec_s *vdec, struct hevc_state_s *hevc)
-{
-	if (vdec->fcc_status == AGAIN_STATUS &&
-		hevc->param.p.slice_type == I_SLICE) {
-		vdec->stream_offset = READ_VREG(HEVC_SHIFT_BYTE_COUNT);
-		hevc_print(hevc, PRINT_FLAG_VDEC_DETAIL,
-			"[%d][FCC]: Notify stream_offset: %u\n",
-			vdec->id, vdec->stream_offset);
-
-		vdec_wakeup_fcc_poll(vdec);
-		amhevc_stop();
-		vdec->fcc_status = WAIT_MSG_STATUS;
-		hevc->dec_result = DEC_RESULT_AGAIN;
-		vdec_schedule_work(&hevc->work);
-	} else if (vdec->fcc_status == DISCARD_STATUS ||
-		hevc->param.p.slice_type != I_SLICE) {
-		hevc_print(hevc, PRINT_FLAG_VDEC_DETAIL,
-			"[%d][FCC]: Discard current gop and to find next gop!\n",
-			vdec->id);
-
-		amhevc_stop();
-		vdec->fcc_status = AGAIN_STATUS;
-		hevc->dec_result = DEC_RESULT_DISCARD_DATA;
-		vdec_schedule_work(&hevc->work);
-	}
-}
-
-static int vh265_fcc_process(struct vdec_s *vdec, struct hevc_state_s *hevc)
-{
-	if (input_stream_based(vdec)) {
-		switch (vdec->fcc_mode) {
-		case FCC_DISCARD_MODE:
-			fcc_discard_mode_process(vdec, hevc);
-			return 1;
-		case FCC_DEC_MODE:
-			hevc_print(hevc, PRINT_FLAG_VDEC_DETAIL,
-					"[%d][FCC]: Current is Dec mode.\n", vdec->id);
-			break;
-		case FCC_BUTT:
-		default:
-			break;
-		}
-	}
-
-	return 0;
-}
-#endif
-
 static void aspect_ratio_set(struct hevc_state_s *hevc)
 {
 	int  aspect_ratio_idc = hevc->param.p.aspect_ratio_idc;
@@ -10517,6 +11356,13 @@
 
 	struct vdec_s *vdec = hw_to_vdec(hevc);
 
+	if (dec_status == HEVC_SLICE_SEGMENT_DONE) {
+		ATRACE_COUNTER(hevc->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_START);
+	}
+	else if (dec_status == HEVC_DECPIC_DATA_DONE) {
+		ATRACE_COUNTER(hevc->trace.decode_time_name, DECODER_ISR_THREAD_PIC_DONE_START);
+	}
+
 	if (hevc->eos)
 		return IRQ_HANDLED;
 	if (
@@ -10702,11 +11548,20 @@
 #endif
 			hevc->empty_flag = 0;
 pic_done:
+			if (vdec->master == NULL && vdec->slave == NULL &&
+				hevc->empty_flag == 0) {
+				hevc->over_decode =
+					(READ_VREG(HEVC_SHIFT_STATUS) >> 15) & 0x1;
+				if (hevc->over_decode)
+					hevc_print(hevc, 0,
+						"!!!Over decode %d\n", __LINE__);
+			}
 			if (input_frame_based(hw_to_vdec(hevc)) &&
 				frmbase_cont_bitlevel != 0 &&
 				(hevc->decode_size > READ_VREG(HEVC_SHIFT_BYTE_COUNT)) &&
 				(hevc->decode_size - (READ_VREG(HEVC_SHIFT_BYTE_COUNT))
 				 >	frmbase_cont_bitlevel)) {
+				check_pic_decoded_error(hevc, READ_VREG(HEVC_PARSER_LCU_START) & 0xffffff);
 				/*handle the case: multi pictures in one packet*/
 				hevc_print(hevc, PRINT_FLAG_VDEC_STATUS,
 				"%s  has more data index= %d, size=0x%x shiftcnt=0x%x)\n",
@@ -10762,27 +11617,12 @@
 							&& ((hevc->double_write_mode & 0x10) == 0)) {
 						if (!hevc->m_ins_flag) {
 							hevc->used_4k_num =
-							READ_VREG(HEVC_SAO_MMU_STATUS) >> 16;
-
+								READ_VREG(HEVC_SAO_MMU_STATUS) >> 16;
 							if ((!is_skip_decoding(hevc, pic)) &&
 								(hevc->used_4k_num >= 0) &&
 								(hevc->cur_pic->scatter_alloc
-								== 1)) {
-								hevc_print(hevc,
-								H265_DEBUG_BUFMGR_MORE,
-								"%s pic index %d scatter_alloc %d page_start %ld\n",
-								"decoder_mmu_box_free_idx_tail",
-								hevc->cur_pic->index,
-								hevc->cur_pic->scatter_alloc,
-								hevc->used_4k_num);
-								decoder_mmu_box_free_idx_tail(
-								hevc->mmu_box,
-								hevc->cur_pic->index,
-								hevc->used_4k_num);
-								hevc->cur_pic->scatter_alloc
-									= 2;
-							}
-							hevc->used_4k_num = -1;
+								== 1))
+								recycle_mmu_buf_tail(hevc, false);
 						}
 					}
 
@@ -10796,7 +11636,7 @@
 					}
 				}
 				/*Detects the first frame whether has an over decode error*/
-				if ((!vdec_dual(vdec)) &&
+				if (vdec->master == NULL && vdec->slave == NULL &&
 					hevc->empty_flag == 0) {
 					hevc->over_decode =
 						(READ_VREG(HEVC_SHIFT_STATUS) >> 15) & 0x1;
@@ -10848,7 +11688,7 @@
 					}
 				}
 			}
-
+			ATRACE_COUNTER(hevc->trace.decode_time_name, DECODER_ISR_THREAD_EDN);
 			vdec_schedule_work(&hevc->work);
 		}
 
@@ -10988,7 +11828,7 @@
 			}
 #endif
 			/*Detects frame whether has an over decode error*/
-			if ((!vdec_dual(vdec)) &&
+			if (vdec->master == NULL && vdec->slave == NULL &&
 					hevc->empty_flag == 0 && input_stream_based(vdec)) {
 					hevc->over_decode =
 						(READ_VREG(HEVC_SHIFT_STATUS) >> 15) & 0x1;
@@ -11196,7 +12036,7 @@
 			if (get_dbg_flag(hevc) & H265_DEBUG_SEND_PARAM_WITH_REG)
 				get_rpm_param(&hevc->param);
 			else {
-
+				ATRACE_COUNTER(hevc->trace.decode_header_memory_time_name, TRACE_HEADER_RPM_START);
 				for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) {
 					int ii;
 
@@ -11206,14 +12046,11 @@
 							- ii];
 					}
 				}
+				ATRACE_COUNTER(hevc->trace.decode_header_memory_time_name, TRACE_HEADER_RPM_END);
 #ifdef SEND_LMEM_WITH_RPM
 				check_head_error(hevc);
 #endif
 			}
-#ifdef VDEC_FCC_SUPPORT
-			if (vh265_fcc_process(vdec, hevc) > 0)
-				return IRQ_HANDLED;
-#endif
 			if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE) {
 				hevc_print(hevc, 0,
 					"rpm_param: (%d)\n", hevc->slice_idx);
@@ -11241,9 +12078,22 @@
 						struct aml_vdec_ps_infos ps;
 						int width = hevc->param.p.pic_width_in_luma_samples;
 						int height = hevc->param.p.pic_height_in_luma_samples;
+						int log = hevc->param.p.log2_min_coding_block_size_minus3;
+						int log_s = hevc->param.p.log2_diff_max_min_coding_block_size;
+
+						hevc->pic_w = width;
+						hevc->pic_h = height;
+						hevc->lcu_size = 1 << (log + 3 + log_s);
 
 						pr_debug("set ucode parse\n");
-						vh265_get_ps_info(hevc, width, height, &ps);
+						if (get_valid_double_write_mode(hevc) != 16) {
+							struct vdec_comp_buf_info info;
+
+							get_comp_buf_info(hevc, &info);
+							vdec_v4l_set_comp_buf_info(ctx, &info);
+						}
+
+						vh265_get_ps_info(hevc, &hevc->param, &ps);
 						/*notice the v4l2 codec.*/
 						vdec_v4l_set_ps_infos(ctx, &ps);
 						hevc->v4l_params_parsed = true;
@@ -11262,7 +12112,6 @@
 					reset_process_time(hevc);
 					vdec_schedule_work(&hevc->work);
 					return IRQ_HANDLED;
-
 				}
 			}
 
@@ -11275,7 +12124,7 @@
 				) {
 
 				if (get_dbg_flag(hevc) &
-					H265_DEBUG_BUFMGR_MORE)
+					H265_DEBUG_PRINT_SEI)
 					dump_aux_buf(hevc);
 			}
 
@@ -11401,15 +12250,16 @@
 		} else {
 			hevc->sps_num_reorder_pics_0 =
 			hevc->param.p.sps_num_reorder_pics_0;
-			hevc->ip_mode = (!hevc->sps_num_reorder_pics_0 &&
-								!(vdec->slave || vdec->master) &&
-								!disable_ip_mode &&
-								hevc->low_latency_flag) ? true : false;
+			hevc->ip_mode = hevc->low_latency_flag ? true :
+					(!hevc->sps_num_reorder_pics_0 &&
+					!(vdec->slave || vdec->master) &&
+					!disable_ip_mode) ? true : false;
 			hevc->pic_list_init_flag = 1;
 			if ((!IS_4K_SIZE(hevc->pic_w, hevc->pic_h)) &&
 				((hevc->param.p.profile_etc & 0xc) == 0x4)
 				&& (interlace_enable != 0)) {
 				hevc->double_write_mode = 1;
+				hevc->mmu_enable = 1;
 				hevc->interlace_flag = 1;
 				hevc->frame_ar = (hevc->pic_h * 0x100 / hevc->pic_w) * 2;
 				hevc_print(hevc, 0,
@@ -11417,7 +12267,7 @@
 					hevc->pic_w, hevc->pic_h, hevc->param.p.profile_etc, hevc->frame_ar,
 					get_double_write_mode(hevc));
 				/* When dw changed from 0x10 to 1, the mmu_box is NULL */
-				if (!hevc->mmu_box && init_mmu_box(hevc) != 0) {
+				if (!hevc->mmu_box && init_mmu_buffers(hevc, 1) != 0) {
 					hevc->dec_result = DEC_RESULT_FORCE_EXIT;
 					hevc->fatal_error |=
 						DECODER_FATAL_ERROR_NO_MEM;
@@ -11426,6 +12276,17 @@
 						0, "can not alloc mmu box, force exit\n");
 					return IRQ_HANDLED;
 				}
+				if (hevc->frame_mmu_map_addr == NULL) {
+					hevc->frame_mmu_map_addr =
+						dma_alloc_coherent(amports_get_dma_device(),
+						get_frame_mmu_map_size(),
+						&hevc->frame_mmu_map_phy_addr, GFP_KERNEL);
+					if (hevc->frame_mmu_map_addr == NULL) {
+						pr_err("%s: failed to alloc count_buffer\n", __func__);
+						return IRQ_HANDLED;
+					}
+					memset(hevc->frame_mmu_map_addr, 0, get_frame_mmu_map_size());
+				}
 			}
 #ifdef MULTI_INSTANCE_SUPPORT
 			if (hevc->m_ins_flag) {
@@ -11435,6 +12296,7 @@
 				up(&h265_sema);
 			hevc_print(hevc, 0, "set pic_list_init_flag 1\n");
 		}
+		ATRACE_COUNTER(hevc->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_END);
 		return IRQ_HANDLED;
 	}
 
@@ -11463,7 +12325,6 @@
 			hevc_print(hevc, H265_DEBUG_OUT_PTS,
 				"read stream_offset = 0x%x\n",
 				hevc->cur_pic->stream_offset);
-
 			hevc->cur_pic->aspect_ratio_idc =
 				hevc->param.p.aspect_ratio_idc;
 			hevc->cur_pic->sar_width =
@@ -11515,6 +12376,8 @@
 		WRITE_VREG(HEVC_MCPU_INTR_REQ, AMRISC_MAIN_REQ);
 	}
 
+	ATRACE_COUNTER(hevc->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_END);
+
 	} else if (dec_status == HEVC_DECODE_OVER_SIZE) {
 		hevc_print(hevc, 0 , "hevc  decode oversize !!\n");
 #ifdef MULTI_INSTANCE_SUPPORT
@@ -11548,6 +12411,14 @@
 	u32 debug_tag;
 	dec_status = READ_VREG(HEVC_DEC_STATUS_REG);
 
+
+	if (dec_status == HEVC_SLICE_SEGMENT_DONE) {
+		ATRACE_COUNTER(hevc->trace.decode_time_name, DECODER_ISR_HEAD_DONE);
+	}
+	else if (dec_status == HEVC_DECPIC_DATA_DONE) {
+		ATRACE_COUNTER(hevc->trace.decode_time_name, DECODER_ISR_PIC_DONE);
+	}
+
 	if (hevc->init_flag == 0)
 		return IRQ_HANDLED;
 	hevc->dec_status = dec_status;
@@ -11638,7 +12509,7 @@
 			return IRQ_HANDLED;
 		}
 	}
-
+	ATRACE_COUNTER(hevc->trace.decode_time_name, DECODER_ISR_END);
 	return IRQ_WAKE_THREAD;
 
 }
@@ -11656,10 +12527,10 @@
 			hevc->frame_height * fps;
 }
 
-static void vh265_check_timer_func(unsigned long arg)
+static void vh265_check_timer_func(struct timer_list *timer)
 {
-	struct hevc_state_s *hevc = (struct hevc_state_s *)arg;
-	struct timer_list *timer = &hevc->timer;
+	struct hevc_state_s *hevc = container_of(timer,
+		 struct hevc_state_s, timer);
 	unsigned char empty_flag;
 	unsigned int buf_level;
 
@@ -11965,11 +12836,17 @@
 				96000 / hevc->frame_dur : (96000 / hevc->frame_dur +1);
 	else
 		vstatus->frame_rate = -1;
-
+	vstatus->error_count = hevc->gvs->error_frame_count;
 	vstatus->status = hevc->stat | hevc->fatal_error;
+	if (!vdec_is_support_4k() &&
+		(IS_4K_SIZE(vstatus->frame_width, vstatus->frame_height)) &&
+		(vstatus->frame_width <= 4096 && vstatus->frame_height <= 2304)) {
+		vstatus->status |= DECODER_FATAL_ERROR_SIZE_OVERFLOW;
+	}
+
+	vstatus->bit_rate = hevc->gvs->bit_rate;
 	vstatus->frame_dur = hevc->frame_dur;
 	if (hevc->gvs) {
-		vstatus->error_count = hevc->gvs->error_frame_count;
 		vstatus->bit_rate = hevc->gvs->bit_rate;
 		vstatus->frame_data = hevc->gvs->frame_data;
 		vstatus->total_data = hevc->gvs->total_data;
@@ -12036,28 +12913,28 @@
 
 int vh265_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
 {
-    struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private;
-    hevc_print(hevc, 0,	"[%s %d] trickmode:%lu\n", __func__, __LINE__, trickmode);
+	struct hevc_state_s *hevc = (struct hevc_state_s *)vdec->private;
+	hevc_print(hevc, 0,	"[%s %d] trickmode:%lu\n", __func__, __LINE__, trickmode);
 
-    if (trickmode == TRICKMODE_I) {
+	if (trickmode == TRICKMODE_I) {
 		trickmode_i = 1;
 		i_only_flag = 0x1;
-    } else if (trickmode == TRICKMODE_NONE) {
+	} else if (trickmode == TRICKMODE_NONE) {
 		trickmode_i = 0;
 		i_only_flag = 0x0;
-    } else if (trickmode == 0x02) {
+	} else if (trickmode == 0x02) {
 		trickmode_i = 0;
 		i_only_flag = 0x02;
-    } else if (trickmode == 0x03) {
+	} else if (trickmode == 0x03) {
 		trickmode_i = 1;
 		i_only_flag = 0x03;
-    } else if (trickmode == 0x07) {
+	} else if (trickmode == 0x07) {
 		trickmode_i = 1;
 		i_only_flag = 0x07;
-    }
-    //hevc_print(hevc, 0, "i_only_flag: %d trickmode_i:%d\n", i_only_flag, trickmode_i);
+	}
+	//hevc_print(hevc, 0, "i_only_flag: %d trickmode_i:%d\n", i_only_flag, trickmode_i);
 
-    return 0;
+	return 0;
 }
 
 static void config_decode_mode(struct hevc_state_s *hevc)
@@ -12149,7 +13026,6 @@
 	} else {
 		/* check vps/sps/pps/i-slice in ucode */
 		unsigned ctl_val = 0x8;
-
 		if (hevc->PB_skip_mode == 0)
 			ctl_val = 0x4;	/* check vps/sps/pps only in ucode */
 		else if (hevc->PB_skip_mode == 3)
@@ -12288,7 +13164,7 @@
 	int fw_size = 0x1000 * 16;
 	struct firmware_s *fw = NULL;
 
-	init_timer(&hevc->timer);
+	timer_setup(&hevc->timer, vh265_check_timer_func, 0);
 
 	hevc->stat |= STAT_TIMER_INIT;
 
@@ -12307,11 +13183,11 @@
 	INIT_WORK(&hevc->notify_work, vh265_notify_work);
 	INIT_WORK(&hevc->set_clk_work, vh265_set_clk);
 
-	fw = vmalloc(sizeof(struct firmware_s) + fw_size);
+	fw = vzalloc(sizeof(struct firmware_s) + fw_size);
 	if (IS_ERR_OR_NULL(fw))
 		return -ENOMEM;
 
-	if (hevc->mmu_enable)
+	if (hevc->mmu_enable) {
 		if (get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_GXM)
 			size = get_firmware_data(VIDEO_DEC_HEVC_MMU, fw->data);
 		else {
@@ -12330,7 +13206,7 @@
 				size = get_firmware_data(VIDEO_DEC_HEVC_MMU,
 					fw->data);
 		}
-	else
+	} else
 		size = get_firmware_data(VIDEO_DEC_HEVC, fw->data);
 
 	if (size < 0) {
@@ -12360,7 +13236,7 @@
 				hevc->swap_size);
 
 			hevc_print(hevc, 0,
-				"vh265 mmu ucode swap loaded %llx\n",
+				"vh265 mmu ucode swap loaded %x\n",
 				hevc->mc_dma_handle);
 		}
 	}
@@ -12368,8 +13244,8 @@
 
 #ifdef MULTI_INSTANCE_SUPPORT
 	if (hevc->m_ins_flag) {
-		hevc->timer.data = (ulong) hevc;
-		hevc->timer.function = vh265_check_timer_func;
+		//hevc->timer.data = (ulong) hevc;
+		//hevc->timer.function = vh265_check_timer_func;
 		hevc->timer.expires = jiffies + PUT_INTERVAL;
 
 		hevc->fw = fw;
@@ -12435,21 +13311,23 @@
 	hevc->provider_name = PROVIDER_NAME;
 
 #ifdef MULTI_INSTANCE_SUPPORT
-	vf_provider_init(&vh265_vf_prov, hevc->provider_name,
-				&vh265_vf_provider, vdec);
-	vf_reg_provider(&vh265_vf_prov);
-	vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_START,
-				NULL);
-	if (hevc->frame_dur != 0) {
-		if (!is_reset) {
-			vf_notify_receiver(hevc->provider_name,
-					VFRAME_EVENT_PROVIDER_FR_HINT,
-					(void *)
-					((unsigned long)hevc->frame_dur));
-			fr_hint_status = VDEC_HINTED;
-		}
-	} else
-		fr_hint_status = VDEC_NEED_HINT;
+	if (!hevc->is_used_v4l) {
+		vf_provider_init(&vh265_vf_prov, hevc->provider_name,
+					&vh265_vf_provider, vdec);
+		vf_reg_provider(&vh265_vf_prov);
+		vf_notify_receiver(hevc->provider_name, VFRAME_EVENT_PROVIDER_START,
+					NULL);
+		if (hevc->frame_dur != 0) {
+			if (!is_reset) {
+				vf_notify_receiver(hevc->provider_name,
+						VFRAME_EVENT_PROVIDER_FR_HINT,
+						(void *)
+						((unsigned long)hevc->frame_dur));
+				fr_hint_status = VDEC_HINTED;
+			}
+		} else
+			fr_hint_status = VDEC_NEED_HINT;
+	}
 #else
 	vf_provider_init(&vh265_vf_prov, PROVIDER_NAME, &vh265_vf_provider,
 					 hevc);
@@ -12466,8 +13344,8 @@
 #endif
 	hevc->stat |= STAT_VF_HOOK;
 
-	hevc->timer.data = (ulong) hevc;
-	hevc->timer.function = vh265_check_timer_func;
+	//hevc->timer.data = (ulong) hevc;
+	//hevc->timer.function = vh265_check_timer_func;
 	hevc->timer.expires = jiffies + PUT_INTERVAL;
 
 	add_timer(&hevc->timer);
@@ -12781,6 +13659,38 @@
 }
 #endif
 
+static bool is_avaliable_buffer(struct hevc_state_s *hevc)
+{
+	struct aml_vcodec_ctx *ctx =
+		(struct aml_vcodec_ctx *)(hevc->v4l2_ctx);
+	struct PIC_s *pic = NULL;
+	int i, free_count = 0;
+
+	if (ctx->cap_pool.dec < hevc->used_buf_num) {
+		free_count = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx);
+		if (free_count &&
+			!ctx->fb_ops.query(&ctx->fb_ops, &hevc->fb_token)) {
+			return false;
+		}
+	}
+
+	for (i = 0; i < hevc->used_buf_num; i++) {
+		pic = hevc->m_PIC[i];
+		if (pic == NULL ||
+			pic->index == -1 ||
+			pic->BUF_index == -1)
+			continue;
+
+		if (pic->output_mark == 0 &&
+			pic->referenced == 0 &&
+			pic->output_ready == 0 &&
+			pic->cma_alloc_addr) {
+			free_count++;
+		}
+	}
+
+	return free_count < run_ready_min_buf_num ? 0 : 1;
+}
 
 static unsigned char is_new_pic_available(struct hevc_state_s *hevc)
 {
@@ -12812,7 +13722,7 @@
 				new_pic = pic;
 		}
 	}
-	if (new_pic == NULL) {
+	if (!hevc->is_used_v4l && new_pic == NULL) {
 		enum receviver_start_e state = RECEIVER_INACTIVE;
 		if (vf_get_receiver(vdec->vf_provider_name)) {
 			state =
@@ -12832,7 +13742,7 @@
 				if ((pic->referenced == 0) &&
 						(pic->error_mark == 1) &&
 						(pic->output_mark == 1)) {
-					if (pic->POC < poc) {
+					if (poc == INVALID_POC ||  (pic->POC < poc)) {
 						new_pic = pic;
 						poc = pic->POC;
 					}
@@ -12875,7 +13785,7 @@
 			if (!(error_handle_policy & 0x400)) {
 				spin_unlock_irqrestore(&lock, flags);
 				flush_output(hevc, NULL);
-				hevc_print(hevc, H265_DEBUG_BUFMGR_MORE, "flush dpb, ref_error_count %d, sps_max_dec_pic_buffering_minus1_0 %d\n",
+				hevc_print(hevc, H265_DEBUG_BUFMGR, "flush dpb, ref_error_count %d, sps_max_dec_pic_buffering_minus1_0 %d\n",
 						decode_count, hevc->param.p.sps_max_dec_pic_buffering_minus1_0);
 				return 0;
 			}
@@ -12893,6 +13803,10 @@
 	struct vdec_s *vdec = hw_to_vdec(hevc);
 
 	enum receviver_start_e state = RECEIVER_INACTIVE;
+
+	if (hevc->is_used_v4l)
+		return;
+
 	if (vf_get_receiver(vdec->vf_provider_name)) {
 		state =
 		vf_notify_receiver(vdec->vf_provider_name,
@@ -12920,7 +13834,7 @@
 			if ((pic->referenced == 0) &&
 					(pic->error_mark == 1) &&
 					(pic->output_mark == 1)) {
-				if (pic->POC < poc) {
+				if (poc == INVALID_POC ||  (pic->POC < poc)) {
 					new_pic = pic;
 					poc = pic->POC;
 				}
@@ -12962,7 +13876,7 @@
 		hevc->stat &= ~STAT_ISR_REG;
 	}
 
-	if (hevc->stat & STAT_VF_HOOK) {
+	if (!hevc->is_used_v4l && hevc->stat & STAT_VF_HOOK) {
 		if (fr_hint_status == VDEC_HINTED)
 			vf_notify_receiver(hevc->provider_name,
 					VFRAME_EVENT_PROVIDER_FR_END_HINT,
@@ -13025,6 +13939,14 @@
 	for (jj = 0; jj < size; jj++)
 		sum += data[jj];
 
+	hevc_print(hevc, PRINT_FLAG_VDEC_STATUS,
+		"%s: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n",
+		__func__, size, sum,
+		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 (!hevc->chunk->block->is_mapped)
 		codec_mm_unmap_phyaddr(data);
 	return sum;
@@ -13037,6 +13959,10 @@
 						struct hevc_state_s,
 						notify_work);
 	struct vdec_s *vdec = hw_to_vdec(hevc);
+
+	if (hevc->is_used_v4l)
+		return;
+
 #ifdef MULTI_INSTANCE_SUPPORT
 	if (vdec->fr_hint_state == VDEC_NEED_HINT) {
 		vf_notify_receiver(hevc->provider_name,
@@ -13067,6 +13993,11 @@
 static void vh265_work_implement(struct hevc_state_s *hevc,
 	struct vdec_s *vdec,int from)
 {
+	if (hevc->dec_result == DEC_RESULT_DONE) {
+		ATRACE_COUNTER(hevc->trace.decode_time_name, DECODER_WORKER_START);
+	} else if (hevc->dec_result == DEC_RESULT_AGAIN)
+		ATRACE_COUNTER(hevc->trace.decode_time_name, DECODER_WORKER_AGAIN);
+
 	if (hevc->dec_result == DEC_RESULT_FREE_CANVAS) {
 		/*USE_BUF_BLOCK*/
 		uninit_pic_list(hevc);
@@ -13248,34 +14179,20 @@
 		}
 	}
 #endif
-
 		if (hevc->mmu_enable && ((hevc->double_write_mode & 0x10) == 0)) {
 			hevc->used_4k_num =
 				READ_VREG(HEVC_SAO_MMU_STATUS) >> 16;
 			if (hevc->used_4k_num >= 0 &&
 				hevc->cur_pic &&
 				hevc->cur_pic->scatter_alloc
-				== 1) {
-				hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
-				"%s pic index %d scatter_alloc %d page_start %ld\n",
-				"decoder_mmu_box_free_idx_tail",
-				hevc->cur_pic->index,
-				hevc->cur_pic->scatter_alloc,
-				hevc->used_4k_num);
-				if (hevc->m_ins_flag)
-					hevc_mmu_dma_check(hw_to_vdec(hevc));
-				decoder_mmu_box_free_idx_tail(
-				hevc->mmu_box,
-				hevc->cur_pic->index,
-				hevc->used_4k_num);
-				hevc->cur_pic->scatter_alloc = 2;
-			}
+				== 1)
+				recycle_mmu_buf_tail(hevc, hevc->m_ins_flag);
 		}
 		hevc->pic_decoded_lcu_idx =
 			READ_VREG(HEVC_PARSER_LCU_START)
 			& 0xffffff;
 
-		if ((!vdec_dual(vdec)) &&
+		if (vdec->master == NULL && vdec->slave == NULL &&
 			hevc->empty_flag == 0) {
 			hevc->over_decode =
 				(READ_VREG(HEVC_SHIFT_STATUS) >> 15) & 0x1;
@@ -13286,7 +14203,7 @@
 
 		if (is_log_enable(hevc))
 			add_log(hevc,
-				"%s dec_result %d lcu %d used_mmu %ld shiftbyte 0x%x decbytes 0x%x",
+				"%s dec_result %d lcu %d used_mmu %d shiftbyte 0x%x decbytes 0x%x",
 				__func__,
 				hevc->dec_result,
 				hevc->pic_decoded_lcu_idx,
@@ -13297,7 +14214,7 @@
 				);
 
 		hevc_print(hevc, PRINT_FLAG_VDEC_STATUS,
-			"%s dec_result %d (%x %x %x) lcu %d used_mmu %ld shiftbyte 0x%x decbytes 0x%x\n",
+			"%s dec_result %d (%x %x %x) lcu %d used_mmu %d shiftbyte 0x%x decbytes 0x%x\n",
 			__func__,
 			hevc->dec_result,
 			READ_VREG(HEVC_STREAM_LEVEL),
@@ -13399,7 +14316,6 @@
 			stream base: stream buf empty or timeout
 			frame base: vdec_prepare_input fail
 		*/
-
 		if (!vdec_has_more_input(vdec)) {
 			hevc->dec_result = DEC_RESULT_EOS;
 			vdec_schedule_work(&hevc->work);
@@ -13475,11 +14391,6 @@
 		}
 		hevc_print(hevc, 0, "%s: force exit end\n",
 			__func__);
-	} else if (hevc->dec_result == DEC_RESULT_DISCARD_DATA) {
-		mutex_lock(&hevc->chunks_mutex);
-		vdec_vframe_dirty(hw_to_vdec(hevc), hevc->chunk);
-		hevc->chunk = NULL;
-		mutex_unlock(&hevc->chunks_mutex);
 	}
 
 	if (hevc->stat & STAT_VDEC_RUN) {
@@ -13491,8 +14402,10 @@
 		del_timer_sync(&hevc->timer);
 		hevc->stat &= ~STAT_TIMER_ARM;
 	}
-
+	ATRACE_COUNTER(hevc->trace.decode_work_time_name, TRACE_WORK_WAIT_SEARCH_DONE_START);
 	wait_hevc_search_done(hevc);
+	ATRACE_COUNTER(hevc->trace.decode_work_time_name, TRACE_WORK_WAIT_SEARCH_DONE_END);
+
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
 	if (hevc->switch_dvlayer_flag) {
 		if (vdec->slave)
@@ -13514,6 +14427,9 @@
 			//cancel_work_sync(&hevc->work);//reserved for future considraion
 		}
 	}
+	if (hevc->dec_result == DEC_RESULT_DONE) {
+		ATRACE_COUNTER(hevc->trace.decode_time_name, DECODER_WORKER_END);
+	}
 
 	/* mark itself has all HW resource released and input released */
 	if (vdec->parallel_dec == 1)
@@ -13555,12 +14471,6 @@
 	vh265_work_implement(hevc, vdec, 1);
 }
 
-#ifdef VDEC_FCC_SUPPORT
-static void vh265_wakeup_fcc_poll(struct vdec_s *vdec)
-{
-	amstream_wakeup_fcc_poll(vdec);
-}
-#endif
 
 static int vh265_hw_ctx_restore(struct hevc_state_s *hevc)
 {
@@ -13575,9 +14485,6 @@
 	int tvp = vdec_secure(hw_to_vdec(hevc)) ?
 		CODEC_MM_FLAGS_TVP : 0;
 	bool ret = 0;
-#ifdef VDEC_FCC_SUPPORT
-	int get_msg = 1;
-#endif
 	if (step == 0x12)
 		return 0;
 	else if (step == 0x11)
@@ -13599,7 +14506,17 @@
 	}
 	hevc->timeout_processing = 0;
 	if (!hevc->first_sc_checked && hevc->mmu_enable) {
-		int size = decoder_mmu_box_sc_check(hevc->mmu_box, tvp);
+		int size;
+		void * mmu_box;
+
+		if (hevc->is_used_v4l) {
+			struct aml_vcodec_ctx *ctx =
+				(struct aml_vcodec_ctx *)(hevc->v4l2_ctx);
+			mmu_box = ctx->mmu_box;
+		} else
+			mmu_box = hevc->mmu_box;
+
+		size = decoder_mmu_box_sc_check(mmu_box, tvp);
 		hevc->first_sc_checked =1;
 		hevc_print(hevc, 0,
 			"vh265 cached=%d  need_size=%d speed= %d ms\n",
@@ -13655,7 +14572,7 @@
 	}
 
 #ifdef CONSTRAIN_MAX_BUF_NUM
-	if (hevc->pic_list_init_flag == 3) {
+	if (hevc->pic_list_init_flag == 3 && !hevc->is_used_v4l) {
 		if (run_ready_max_vf_only_num > 0 &&
 			get_vf_ref_only_buf_count(hevc) >=
 			run_ready_max_vf_only_num
@@ -13687,10 +14604,12 @@
 
 		if (ctx->param_sets_from_ucode) {
 			if (hevc->v4l_params_parsed) {
-				if (!ctx->v4l_codec_dpb_ready &&
-				v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
-				run_ready_min_buf_num)
-					ret = 0;
+				if (ctx->cap_pool.dec < hevc->used_buf_num) {
+					if (is_avaliable_buffer(hevc))
+						ret = 1;
+					else
+						ret = 0;
+				}
 			} else {
 				if (ctx->v4l_resolution_change)
 					ret = 0;
@@ -13702,10 +14621,6 @@
 		}
 	}
 
-#ifdef VDEC_FCC_SUPPORT
-	get_msg = vdec_has_get_fcc_new_msg(vdec);
-	ret &= get_msg;
-#endif
 	if (ret)
 		not_run_ready[hevc->index] = 0;
 	else
@@ -13728,6 +14643,8 @@
 	hevc->vdec_cb_arg = arg;
 	hevc->vdec_cb = callback;
 	hevc->aux_data_dirty = 1;
+
+	ATRACE_COUNTER(hevc->trace.decode_time_name, DECODER_RUN_START);
 	hevc_reset_core(vdec);
 
 #ifdef AGAIN_HAS_THRESHOLD
@@ -13805,6 +14722,7 @@
 		if (!hevc->chunk->block->is_mapped)
 			codec_mm_unmap_phyaddr(data);
 	}
+	ATRACE_COUNTER(hevc->trace.decode_run_time_name, TRACE_RUN_LOADING_FW_START);
 	if (vdec->mc_loaded) {
 		/*firmware have load before,
 		  and not changes to another.
@@ -13814,7 +14732,7 @@
 			get_cpu_major_id() <= AM_MESON_CPU_MAJOR_ID_GXM)
 			WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, hevc->swap_addr);
 	} else {
-		if (hevc->mmu_enable)
+		if (hevc->mmu_enable) {
 			if (get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_GXM)
 				loadr = amhevc_vdec_loadmc_ex(VFORMAT_HEVC, vdec,
 						"h265_mmu", hevc->fw->data);
@@ -13839,9 +14757,10 @@
 						VFORMAT_HEVC, vdec,
 						"h265_mmu", hevc->fw->data);
 			}
-		else
+		} else
 			loadr = amhevc_vdec_loadmc_ex(VFORMAT_HEVC, vdec,
 					NULL, hevc->fw->data);
+
 		if (loadr < 0) {
 			amhevc_disable();
 			hevc_print(hevc, 0, "H265: the %s fw loading failed, err: %x\n",
@@ -13862,10 +14781,14 @@
 		vdec->mc_loaded = 1;
 		vdec->mc_type = VFORMAT_HEVC;
 	}
+	ATRACE_COUNTER(hevc->trace.decode_run_time_name, TRACE_RUN_LOADING_FW_END);
+
+	ATRACE_COUNTER(hevc->trace.decode_run_time_name, TRACE_RUN_LOADING_RESTORE_START);
 	if (vh265_hw_ctx_restore(hevc) < 0) {
 		vdec_schedule_work(&hevc->work);
 		return;
 	}
+	ATRACE_COUNTER(hevc->trace.decode_run_time_name, TRACE_RUN_LOADING_RESTORE_END);
 	vdec_enable_input(vdec);
 
 	WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE);
@@ -13894,6 +14817,7 @@
 	if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR_MORE)
 		dump_pic_list(hevc);
 	backup_decode_state(hevc);
+
 	start_process_time(hevc);
 	mod_timer(&hevc->timer, jiffies);
 	hevc->stat |= STAT_TIMER_ARM;
@@ -13902,6 +14826,8 @@
 		vdec->mvfrm->hw_decode_start = local_clock();
 	amhevc_start();
 	hevc->stat |= STAT_VDEC_RUN;
+
+	ATRACE_COUNTER(hevc->trace.decode_time_name, DECODER_RUN_END);
 }
 
 static void aml_free_canvas(struct vdec_s *vdec)
@@ -13919,6 +14845,7 @@
 				vdec->free_canvas_ex(pic->uv_canvas_index, vdec->id);
 			}
 		}
+		hevc->buffer_wrap[i] = i;
 	}
 }
 
@@ -14026,7 +14953,15 @@
 		else
 			hevc->mmu_enable = 1;
 	}
-	if (init_mmu_buffers(hevc)) {
+#ifdef H265_10B_MMU_DW
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T5D) {
+		hevc->dw_mmu_enable =
+			get_double_write_mode(hevc) & 0x20 ? 1 : 0;
+	} else {
+		hevc->dw_mmu_enable = 0;
+	}
+#endif
+	if (init_mmu_buffers(hevc, 0)) {
 		hevc_print(hevc, 0,
 			"\n 265 mmu init failed!\n");
 		vfree(hevc);
@@ -14080,6 +15015,13 @@
 		hevc->vh265_amstream_dec_info.height = 0;
 		hevc->vh265_amstream_dec_info.rate = 30;
 	}
+
+	hevc->endian = HEVC_CONFIG_LITTLE_ENDIAN;
+	if (is_support_vdec_canvas())
+		hevc->endian = HEVC_CONFIG_BIG_ENDIAN;
+	if (endian)
+		hevc->endian = endian;
+
 #ifndef MULTI_INSTANCE_SUPPORT
 	if (pdata->flag & DEC_FLAG_HEVC_WORKAROUND) {
 		workaround_enable |= 3;
@@ -14212,7 +15154,7 @@
 		input_empty[hevc->index]
 		);
 
-	if (vf_get_receiver(vdec->vf_provider_name)) {
+	if (hevc->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,
@@ -14241,16 +15183,17 @@
 
 	for (i = 0; i < BUF_POOL_SIZE; i++) {
 		hevc_print(hevc, 0,
-			"Buf(%d) start_adr 0x%lx size 0x%x used %d\n",
+			"Buf(%d) start_adr 0x%x header_addr 0x%x size 0x%x used %d\n",
 			i,
 			hevc->m_BUF[i].start_adr,
+			hevc->m_BUF[i].header_addr,
 			hevc->m_BUF[i].size,
 			hevc->m_BUF[i].used_flag);
 	}
 
 	for (i = 0; i < MAX_REF_PIC_NUM; i++) {
 		hevc_print(hevc, 0,
-			"mv_Buf(%d) start_adr 0x%lx size 0x%x used %d\n",
+			"mv_Buf(%d) start_adr 0x%x size 0x%x used %d\n",
 			i,
 			hevc->m_mv_BUF[i].start_adr,
 			hevc->m_mv_BUF[i].size,
@@ -14347,17 +15290,17 @@
 	struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
 	struct hevc_state_s *hevc = NULL;
 	int ret;
+	int i;
 #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
 	int config_val;
 #endif
-	//pr_err("[%s pid=%d tgid=%d] \n",__func__, current->pid, current->tgid);
+
 	if (pdata == NULL) {
 		pr_info("\nammvdec_h265 memory resource undefined.\n");
 		return -EFAULT;
 	}
 
-	/* hevc = (struct hevc_state_s *)devm_kzalloc(&pdev->dev,
-		sizeof(struct hevc_state_s), GFP_KERNEL); */
+
 	hevc = vmalloc(sizeof(struct hevc_state_s));
 	if (hevc == NULL) {
 		pr_info("\nammvdec_h265 device data allocation failed\n");
@@ -14377,30 +15320,48 @@
 	pdata->irq_handler = vh265_irq_cb;
 	pdata->threaded_irq_handler = vh265_threaded_irq_cb;
 	pdata->dump_state = vh265_dump_state;
-#ifdef VDEC_FCC_SUPPORT
-	pdata->wakeup_fcc_poll = vh265_wakeup_fcc_poll;
-#endif
+
 	hevc->index = pdev->id;
 	hevc->m_ins_flag = 1;
 
-	snprintf(hevc->vdec_name, sizeof(hevc->vdec_name),
+	if (is_rdma_enable()) {
+		hevc->rdma_adr = dma_alloc_coherent(amports_get_dma_device(), RDMA_SIZE, &hevc->rdma_phy_adr, GFP_KERNEL);
+		for (i = 0; i < SCALELUT_DATA_WRITE_NUM; i++) {
+			hevc->rdma_adr[i * 4] = HEVC_IQIT_SCALELUT_WR_ADDR & 0xfff;
+			hevc->rdma_adr[i * 4 + 1] = i;
+			hevc->rdma_adr[i * 4 + 2] = HEVC_IQIT_SCALELUT_DATA & 0xfff;
+			hevc->rdma_adr[i * 4 + 3] = 0;
+			if (i == SCALELUT_DATA_WRITE_NUM - 1) {
+				hevc->rdma_adr[i * 4 + 2] = (HEVC_IQIT_SCALELUT_DATA & 0xfff) | 0x20000;
+			}
+		}
+	}
+	snprintf(hevc->trace.vdec_name, sizeof(hevc->trace.vdec_name),
 		"h265-%d", hevc->index);
-	snprintf(hevc->pts_name, sizeof(hevc->pts_name),
-		"%s-pts", hevc->vdec_name);
-	snprintf(hevc->vf_get_name, sizeof(hevc->vf_get_name),
-		"%s-vf_get", hevc->vdec_name);
-	snprintf(hevc->vf_put_name, sizeof(hevc->vf_put_name),
-		"%s-vf_put", hevc->vdec_name);
-	snprintf(hevc->set_canvas0_addr, sizeof(hevc->set_canvas0_addr),
-		"%s-set_canvas0_addr", hevc->vdec_name);
-	snprintf(hevc->get_canvas0_addr, sizeof(hevc->get_canvas0_addr),
-		"%s-get_canvas0_addr", hevc->vdec_name);
-	snprintf(hevc->put_canvas0_addr, sizeof(hevc->put_canvas0_addr),
-		"%s-put_canvas0_addr", hevc->vdec_name);
-	snprintf(hevc->new_q_name, sizeof(hevc->new_q_name),
-		"%s-newframe_q", hevc->vdec_name);
-	snprintf(hevc->disp_q_name, sizeof(hevc->disp_q_name),
-		"%s-dispframe_q", hevc->vdec_name);
+	snprintf(hevc->trace.pts_name, sizeof(hevc->trace.pts_name),
+		"%s-pts", hevc->trace.vdec_name);
+	snprintf(hevc->trace.vf_get_name, sizeof(hevc->trace.vf_get_name),
+		"%s-vf_get", hevc->trace.vdec_name);
+	snprintf(hevc->trace.vf_put_name, sizeof(hevc->trace.vf_put_name),
+		"%s-vf_put", hevc->trace.vdec_name);
+	snprintf(hevc->trace.set_canvas0_addr, sizeof(hevc->trace.set_canvas0_addr),
+		"%s-set_canvas0_addr", hevc->trace.vdec_name);
+	snprintf(hevc->trace.get_canvas0_addr, sizeof(hevc->trace.get_canvas0_addr),
+		"%s-get_canvas0_addr", hevc->trace.vdec_name);
+	snprintf(hevc->trace.put_canvas0_addr, sizeof(hevc->trace.put_canvas0_addr),
+		"%s-put_canvas0_addr", hevc->trace.vdec_name);
+	snprintf(hevc->trace.new_q_name, sizeof(hevc->trace.new_q_name),
+		"%s-newframe_q", hevc->trace.vdec_name);
+	snprintf(hevc->trace.disp_q_name, sizeof(hevc->trace.disp_q_name),
+		"%s-dispframe_q", hevc->trace.vdec_name);
+	snprintf(hevc->trace.decode_time_name, sizeof(hevc->trace.decode_time_name),
+		"decoder_time%d", pdev->id);
+	snprintf(hevc->trace.decode_run_time_name, sizeof(hevc->trace.decode_run_time_name),
+		"decoder_run_time%d", pdev->id);
+	snprintf(hevc->trace.decode_header_memory_time_name, sizeof(hevc->trace.decode_header_memory_time_name),
+		"decoder_header_time%d", pdev->id);
+	snprintf(hevc->trace.decode_work_time_name, sizeof(hevc->trace.decode_work_time_name),
+		"decoder_work_time%d", pdev->id);
 
 	if (pdata->use_vfm_path) {
 		snprintf(pdata->vf_provider_name,
@@ -14412,16 +15373,30 @@
 	else if (vdec_dual(pdata)) {
 		struct hevc_state_s *hevc_pair = NULL;
 
-		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);
+		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);
+		}
+
 		hevc->dolby_enhance_flag = pdata->master ? 1 : 0;
 		if (pdata->master)
 			hevc_pair = (struct hevc_state_s *)
@@ -14438,16 +15413,13 @@
 		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,
-		&vh265_vf_provider, pdata);
-
 	hevc->provider_name = pdata->vf_provider_name;
 	platform_set_drvdata(pdev, pdata);
 
 	hevc->platform_dev = pdev;
 
 	if (((get_dbg_flag(hevc) & IGNORE_PARAM_FROM_CONFIG) == 0) &&
-			pdata->config && pdata->config_len) {
+			pdata->config_len) {
 #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
 		/*use ptr config for doubel_write_mode, etc*/
 		hevc_print(hevc, 0, "pdata->config=%s\n", pdata->config);
@@ -14496,18 +15468,18 @@
 			&config_val) == 0)
 			hevc->mem_map_mode = config_val;
 
-		if (get_config_int(pdata->config, "dv_duallayer",
-				&config_val) == 0)
-			hevc->dv_duallayer = config_val;
-		else
-			hevc->dv_duallayer = false;
-
 		if (get_config_int(pdata->config, "negative_dv",
 			&config_val) == 0) {
 			hevc->discard_dv_data = config_val;
 			hevc_print(hevc, 0, "discard dv data\n");
 		}
 
+		if (get_config_int(pdata->config, "dv_duallayer",
+			&config_val) == 0) {
+			hevc->dv_duallayer = config_val;
+			hevc_print(hevc, 0, "dv dual layer\n");
+		}
+
 		if (get_config_int(pdata->config,
 			"parm_enable_fence",
 			&config_val) == 0)
@@ -14523,6 +15495,17 @@
 			&config_val) == 0)
 			hevc->low_latency_flag = config_val;
 
+		if (get_config_int(pdata->config,
+			"parm_v4l_metadata_config_flag",
+			&config_val) == 0) {
+			hevc->metadata_config_flag = config_val;
+			hevc->discard_dv_data = hevc->metadata_config_flag & VDEC_CFG_FLAG_DV_NEGATIVE;
+			hevc->dv_duallayer = hevc->metadata_config_flag & VDEC_CFG_FLAG_DV_TWOLARYER;
+			if (hevc->discard_dv_data)
+				hevc_print(hevc, 0, "discard dv data\n");
+			if (hevc->dv_duallayer)
+				hevc_print(hevc, 0, "dv_duallayer\n");
+		}
 #endif
 	} else {
 		if (pdata->sys_info)
@@ -14534,8 +15517,10 @@
 		}
 		hevc->double_write_mode = double_write_mode;
 	}
-	/* get valid double write from configure or node */
-	//hevc->double_write_mode = get_double_write_mode(hevc);
+
+
+	vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
+		&vh265_vf_provider, pdata);
 
 	if (force_config_fence) {
 		hevc->enable_fence = true;
@@ -14547,31 +15532,45 @@
 			hevc->enable_fence, hevc->fence_usage);
 	}
 
-	if (hevc->enable_fence)
-		pdata->sync.usage = hevc->fence_usage;
+	if (hevc->save_buffer_mode && dynamic_buf_num_margin > 2)
+		hevc->dynamic_buf_num_margin = dynamic_buf_num_margin -2;
+	else
+		hevc->dynamic_buf_num_margin = dynamic_buf_num_margin;
+
+	hevc->mem_map_mode = mem_map_mode;
+
+	hevc->endian = HEVC_CONFIG_LITTLE_ENDIAN;
+	if (is_support_vdec_canvas())
+		hevc->endian = HEVC_CONFIG_BIG_ENDIAN;
+	if (endian)
+		hevc->endian = endian;
 
 	if ((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5) &&
 			(hevc->double_write_mode == 3))
 		hevc->double_write_mode = 0x1000;
 
-	if (!hevc->is_used_v4l) {
-		/* get valid double write from configure or node */
-		//hevc->double_write_mode = get_double_write_mode(hevc);
-		if (hevc->save_buffer_mode && dynamic_buf_num_margin > 2)
-			hevc->dynamic_buf_num_margin = dynamic_buf_num_margin -2;
-		else
-			hevc->dynamic_buf_num_margin = dynamic_buf_num_margin;
-		hevc->mem_map_mode = mem_map_mode;
-	}
+	/* get valid double write from node */
+	if (double_write_mode)
+		hevc->double_write_mode = get_double_write_mode(hevc);
 
-	if (mmu_enable_force == 0) {
-		if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL)
+	if (mmu_enable_force) {
+		hevc->mmu_enable = 1;
+	} else {
+		if ((get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL) ||
+			(hevc->double_write_mode & 0x10))
 			hevc->mmu_enable = 0;
 		else
 			hevc->mmu_enable = 1;
 	}
-
-	if (init_mmu_buffers(hevc) < 0) {
+#ifdef H265_10B_MMU_DW
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T5D) {
+		hevc->dw_mmu_enable =
+			get_double_write_mode(hevc) & 0x20 ? 1 : 0;
+	} else {
+		hevc->dw_mmu_enable = 0;
+	}
+#endif
+	if (init_mmu_buffers(hevc, 0) < 0) {
 		hevc_print(hevc, 0,
 			"\n 265 mmu init failed!\n");
 		mutex_unlock(&vh265_mutex);
@@ -14660,9 +15659,25 @@
 		vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
 					| CORE_MASK_COMBINE);
 
+	mutex_init(&hevc->fence_mutex);
 	if (hevc->enable_fence) {
+		pdata->sync = vdec_sync_get();
+		if (!pdata->sync) {
+			hevc_print(hevc, 0, "alloc fence timeline error\n");
+			hevc_local_uninit(hevc);
+			if (hevc->gvs)
+				kfree(hevc->gvs);
+			hevc->gvs = NULL;
+			uninit_mmu_buffers(hevc);
+			/* devm_kfree(&pdev->dev, (void *)hevc); */
+			if (hevc)
+				vfree((void *)hevc);
+			pdata->dec_status = NULL;
+			return -ENODEV;
+		}
+		pdata->sync->usage = hevc->fence_usage;
 		/* creat timeline. */
-		vdec_timeline_create(&pdata->sync, DRIVER_NAME);
+		vdec_timeline_create(pdata->sync, DRIVER_NAME);
 	}
 
 	return 0;
@@ -14672,7 +15687,6 @@
 			       struct vdec_sync *sync)
 {
 	ulong expires;
-	int i;
 
 	/* notify signal to wake up all fences. */
 	vdec_timeline_increase(sync, VF_POOL_SIZE);
@@ -14685,15 +15699,6 @@
 		}
 	}
 
-	for (i = 0; i < VF_POOL_SIZE; i++) {
-		struct vframe_s *vf = &hw->vfpool[i];
-
-		if (vf->fence) {
-			vdec_fence_put(vf->fence);
-			vf->fence = NULL;
-		}
-	}
-
 	/* decreases refcnt of timeline. */
 	vdec_timeline_put(sync);
 }
@@ -14728,8 +15733,9 @@
 	vdec_set_status(hw_to_vdec(hevc), VDEC_STATUS_DISCONNECTED);
 
 	if (hevc->enable_fence)
-		vdec_fence_release(hevc, &vdec->sync);
-
+		vdec_fence_release(hevc, vdec->sync);
+	if (is_rdma_enable())
+		dma_free_coherent(amports_get_dma_device(), RDMA_SIZE, hevc->rdma_adr, hevc->rdma_phy_adr);
 	vfree((void *)hevc);
 
 	return 0;
@@ -14816,13 +15822,20 @@
 {
 	struct BuffInfo_s *p_buf_info;
 
-	if (vdec_is_support_4k()) {
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)
-			p_buf_info = &amvh265_workbuff_spec[2];
+	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 = &amvh265_workbuff_spec[2];
+			else
+				p_buf_info = &amvh265_workbuff_spec[1];
+		} else
+			p_buf_info = &amvh265_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 = &amvh265_workbuff_spec[5];
 		else
-			p_buf_info = &amvh265_workbuff_spec[1];
-	} else
-		p_buf_info = &amvh265_workbuff_spec[0];
+			p_buf_info = &amvh265_workbuff_spec[3];
+	}
 
 	init_buff_spec(NULL, p_buf_info);
 	work_buf_size =
@@ -14862,19 +15875,26 @@
 			amvdec_h265_profile.profile = "4k";
 		} else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
 			amvdec_h265_profile.profile =
-				"8k, 8bit, 10bit, dwrite, compressed, frame_dv, fence";
+				"8k, 8bit, 10bit, dwrite, compressed, frame_dv, fence, v4l-uvm";
 		}else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB) {
 			amvdec_h265_profile.profile =
-				"4k, 8bit, 10bit, dwrite, compressed, frame_dv, fence";
+				"4k, 8bit, 10bit, dwrite, compressed, frame_dv, fence, v4l-uvm";
 		} else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_MG9TV)
 			amvdec_h265_profile.profile = "4k";
+	} else {
+		if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5D || is_cpu_s4_s805x2()) {
+				amvdec_h265_profile.profile =
+					"8bit, 10bit, dwrite, compressed, frame_dv, v4l";
+		} else {
+				amvdec_h265_profile.profile =
+					"8bit, 10bit, dwrite, compressed, v4l";
+		}
 	}
 #endif
 	if (codec_mm_get_total_size() < 80 * SZ_1M) {
 		pr_info("amvdec_h265 default mmu enabled.\n");
 		mmu_enable = 1;
 	}
-
 	vcodec_profile_register(&amvdec_h265_profile);
 	amvdec_h265_profile_single = amvdec_h265_profile;
 	amvdec_h265_profile_single.name = "h265";
@@ -14884,6 +15904,7 @@
 	vcodec_profile_register(&amvdec_h265_profile_mult);
 	INIT_REG_NODE_CONFIGS("media.decoder", &decoder_265_node,
 		"h265", h265_configs, CONFIG_FOR_RW);
+	vcodec_feature_register(VFORMAT_HEVC, 0);
 	return 0;
 }
 
diff --git a/drivers/frame_provider/decoder/mjpeg/vmjpeg.c b/drivers/frame_provider/decoder/mjpeg/vmjpeg.c
index 6b87d4a..917a2a1 100644
--- a/drivers/frame_provider/decoder/mjpeg/vmjpeg.c
+++ b/drivers/frame_provider/decoder/mjpeg/vmjpeg.c
@@ -28,7 +28,6 @@
 #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/vdec_reg.h>
 #include "../../../stream_input/amports/amports_priv.h"
 #include <linux/amlogic/media/registers/register.h>
@@ -36,9 +35,6 @@
 #include "../utils/decoder_bmmu_box.h"
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
 #include <linux/amlogic/media/codec_mm/configs.h>
-#include <linux/amlogic/tee.h>
-
-
 
 #ifdef CONFIG_AM_VDEC_MJPEG_LOG
 #define AMLOG
@@ -397,10 +393,8 @@
 	}
 }
 
-static void vmjpeg_put_timer_func(unsigned long arg)
+static void vmjpeg_put_timer_func(struct timer_list *timer)
 {
-	struct timer_list *timer = (struct timer_list *)arg;
-
 	while (!kfifo_is_empty(&recycle_q) &&
 			(READ_VREG(MREG_TO_AMRISC) == 0)) {
 		struct vframe_s *vf;
@@ -489,61 +483,61 @@
 		if (ret < 0)
 			return ret;
 #ifdef NV21
-		canvas_config(index2canvas0(i) & 0xff,
+		config_cav_lut_ex(index2canvas0(i) & 0xff,
 			buf_start,
 			canvas_width, canvas_height,
 			CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_LINEAR);
-		canvas_config((index2canvas0(i) >> 8) & 0xff,
+			CANVAS_BLKMODE_LINEAR, 0, VDEC_1);
+		config_cav_lut_ex((index2canvas0(i) >> 8) & 0xff,
 			buf_start +
 			decbuf_y_size, canvas_width,
 			canvas_height / 2, CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_LINEAR);
-		canvas_config(index2canvas1(i) & 0xff,
+			CANVAS_BLKMODE_LINEAR, 0, VDEC_1);
+		config_cav_lut_ex(index2canvas1(i) & 0xff,
 			buf_start +
 			decbuf_size / 2, canvas_width,
 			canvas_height, CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_LINEAR);
-		canvas_config((index2canvas1(i) >> 8) & 0xff,
+			CANVAS_BLKMODE_LINEAR, 0, VDEC_1);
+		config_cav_lut_ex((index2canvas1(i) >> 8) & 0xff,
 			buf_start +
 			decbuf_y_size + decbuf_uv_size / 2,
 			canvas_width, canvas_height / 2,
 			CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_LINEAR);
+			CANVAS_BLKMODE_LINEAR, 0, VDEC_1);
 #else
-		canvas_config(index2canvas0(i) & 0xff,
+		config_cav_lut_ex(index2canvas0(i) & 0xff,
 			buf_start,
 			canvas_width, canvas_height,
 			CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_LINEAR);
-		canvas_config((index2canvas0(i) >> 8) & 0xff,
+			CANVAS_BLKMODE_LINEAR, 0, VDEC_1);
+		config_cav_lut_ex((index2canvas0(i) >> 8) & 0xff,
 			buf_start +
 			decbuf_y_size, canvas_width / 2,
 			canvas_height / 2, CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_LINEAR);
-		canvas_config((index2canvas0(i) >> 16) & 0xff,
+			CANVAS_BLKMODE_LINEAR, 0, VDEC_1);
+		config_cav_lut_ex((index2canvas0(i) >> 16) & 0xff,
 			buf_start +
 			decbuf_y_size + decbuf_uv_size,
 			canvas_width / 2, canvas_height / 2,
 			CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_LINEAR);
-		canvas_config(index2canvas1(i) & 0xff,
+			CANVAS_BLKMODE_LINEAR, 0, VDEC_1);
+		config_cav_lut_ex(index2canvas1(i) & 0xff,
 			buf_start +
 			decbuf_size / 2, canvas_width,
 			canvas_height, CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_LINEAR);
-		canvas_config((index2canvas1(i) >> 8) & 0xff,
+			CANVAS_BLKMODE_LINEAR, 0, VDEC_1);
+		config_cav_lut_ex((index2canvas1(i) >> 8) & 0xff,
 			buf_start +
 			decbuf_y_size + decbuf_uv_size / 2,
 			canvas_width / 2, canvas_height / 2,
 			CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_LINEAR);
-		canvas_config((index2canvas1(i) >> 16) & 0xff,
+			CANVAS_BLKMODE_LINEAR, 0, VDEC_1);
+		config_cav_lut_ex((index2canvas1(i) >> 16) & 0xff,
 			buf_start +
 			decbuf_y_size + decbuf_uv_size +
 			decbuf_uv_size / 2, canvas_width / 2,
 			canvas_height / 2, CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_LINEAR);
+			CANVAS_BLKMODE_LINEAR, 0, VDEC_1);
 #endif
 
 	}
@@ -740,7 +734,7 @@
 	if (IS_ERR_OR_NULL(buf))
 		return -ENOMEM;
 
-	init_timer(&recycle_timer);
+	timer_setup(&recycle_timer, vmjpeg_put_timer_func, 0);
 
 	stat |= STAT_TIMER_INIT;
 
@@ -805,10 +799,7 @@
 
 	stat |= STAT_VF_HOOK;
 
-	recycle_timer.data = (ulong)&recycle_timer;
-	recycle_timer.function = vmjpeg_put_timer_func;
 	recycle_timer.expires = jiffies + PUT_INTERVAL;
-
 	add_timer(&recycle_timer);
 
 	stat |= STAT_TIMER_ARM;
@@ -911,32 +902,16 @@
 }
 
 /****************************************/
-#ifdef CONFIG_PM
-static int mjpeg_suspend(struct device *dev)
-{
-	amvdec_suspend(to_platform_device(dev), dev->power.power_state);
-	return 0;
-}
-
-static int mjpeg_resume(struct device *dev)
-{
-	amvdec_resume(to_platform_device(dev));
-	return 0;
-}
-
-static const struct dev_pm_ops mjpeg_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(mjpeg_suspend, mjpeg_resume)
-};
-#endif
 
 static struct platform_driver amvdec_mjpeg_driver = {
 	.probe = amvdec_mjpeg_probe,
 	.remove = amvdec_mjpeg_remove,
+#ifdef CONFIG_PM
+	.suspend = amvdec_suspend,
+	.resume = amvdec_resume,
+#endif
 	.driver = {
 		.name = DRIVER_NAME,
-#ifdef CONFIG_PM
-		.pm = &mjpeg_pm_ops,
-#endif
 	}
 };
 
diff --git a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
index 108f5da..22d7dbd 100644
--- a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
+++ b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
@@ -29,7 +29,8 @@
 #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/tee.h>
+//#include <linux/amlogic/tee.h>
+#include <uapi/linux/tee.h>
 
 #include <linux/amlogic/media/utils/vdec_reg.h>
 #include <linux/amlogic/media/registers/register.h>
@@ -47,6 +48,7 @@
 #include "../utils/vdec_v4l2_buffer_ops.h"
 #include "../utils/config_parser.h"
 #include <media/v4l2-mem2mem.h>
+#include "../utils/vdec_feature.h"
 
 #define MEM_NAME "codec_mmjpeg"
 
@@ -96,6 +98,7 @@
 static int vmjpeg_vf_states(struct vframe_states *states, void *);
 static int vmjpeg_event_cb(int type, void *data, void *private_data);
 static void vmjpeg_work(struct work_struct *work);
+static int notify_v4l_eos(struct vdec_s *vdec);
 static int pre_decode_buf_level = 0x800;
 static int start_decode_buf_level = 0x2000;
 static u32 without_display_mode;
@@ -124,14 +127,19 @@
 	if (((debug_enable & debug_flag) &&
 		((1 << index) & mmjpeg_debug_mask))
 		|| (debug_flag == PRINT_FLAG_ERROR)) {
-		unsigned char buf[512];
+		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_info("%s", buf);
 		va_end(args);
+		kfree(buf);
 	}
 	return 0;
 }
@@ -208,7 +216,7 @@
 	struct firmware_s *fw;
 	struct timer_list check_timer;
 	u32 decode_timeout_count;
-	unsigned long int start_process_time;
+	u32 start_process_time;
 	u32 last_vld_level;
 	u8 eos;
 	u32 frame_num;
@@ -229,6 +237,7 @@
 	u32 res_ch_flag;
 	u32 canvas_mode;
 	u32 canvas_endian;
+	ulong fb_token;
 	char vdec_name[32];
 	char pts_name[32];
 	char new_q_name[32];
@@ -326,7 +335,8 @@
 			hw->res_ch_flag = 1;
 			ctx->v4l_resolution_change = 1;
 			hw->eos = 1;
-			notify_v4l_eos(hw_to_vdec(hw));
+			if (hw->is_used_v4l)
+				notify_v4l_eos(hw_to_vdec(hw));
 
 			ret = 1;
 		}
@@ -338,6 +348,8 @@
 static irqreturn_t vmjpeg_isr_thread_fn(struct vdec_s *vdec, int irq)
 {
 	struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)(vdec->private);
+	struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+	struct vdec_v4l2_buffer *fb = NULL;
 	u32 reg;
 	struct vframe_s *vf = NULL;
 	u32 index, offset = 0, pts;
@@ -400,6 +412,7 @@
 	if (hw->is_used_v4l) {
 		vf->v4l_mem_handle
 			= hw->buffer_spec[index].v4l_ref_buf_addr;
+		fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
 		mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
 			"[%d] %s(), v4l mem handle: 0x%lx\n",
 			((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id,
@@ -455,9 +468,17 @@
 	vf->pts, vf->pts_us64, vf->duration);
 	vdec->vdec_fps_detec(vdec->id);
 	if (without_display_mode == 0) {
-		vf_notify_receiver(vdec->vf_provider_name,
-				VFRAME_EVENT_PROVIDER_VFRAME_READY,
-				NULL);
+		if (hw->is_used_v4l) {
+			if (v4l2_ctx->is_stream_off) {
+				vmjpeg_vf_put(vmjpeg_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
 		vmjpeg_vf_put(vmjpeg_vf_get(vdec), vdec);
 
@@ -650,12 +671,12 @@
 			hw->buffer_spec[i].v_canvas_index = canvas_v(canvas);
 		}
 
-		canvas_config_ex(hw->buffer_spec[i].y_canvas_index,
+		config_cav_lut_ex(hw->buffer_spec[i].y_canvas_index,
 			hw->buffer_spec[i].y_addr,
 			canvas_width,
 			canvas_height,
 			CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_LINEAR, endian);
+			CANVAS_BLKMODE_LINEAR, endian, VDEC_1);
 		hw->buffer_spec[i].canvas_config[0].phy_addr =
 			hw->buffer_spec[i].y_addr;
 		hw->buffer_spec[i].canvas_config[0].width =
@@ -667,12 +688,12 @@
 		hw->buffer_spec[i].canvas_config[0].endian =
 			endian;
 
-		canvas_config_ex(hw->buffer_spec[i].u_canvas_index,
+		config_cav_lut_ex(hw->buffer_spec[i].u_canvas_index,
 			hw->buffer_spec[i].u_addr,
 			canvas_width / 2,
 			canvas_height / 2,
 			CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_LINEAR, endian);
+			CANVAS_BLKMODE_LINEAR, endian, VDEC_1);
 		hw->buffer_spec[i].canvas_config[1].phy_addr =
 			hw->buffer_spec[i].u_addr;
 		hw->buffer_spec[i].canvas_config[1].width =
@@ -684,12 +705,12 @@
 		hw->buffer_spec[i].canvas_config[1].endian =
 			endian;
 
-		canvas_config_ex(hw->buffer_spec[i].v_canvas_index,
+		config_cav_lut_ex(hw->buffer_spec[i].v_canvas_index,
 			hw->buffer_spec[i].v_addr,
 			canvas_width / 2,
 			canvas_height / 2,
 			CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_LINEAR, endian);
+			CANVAS_BLKMODE_LINEAR, endian, VDEC_1);
 		hw->buffer_spec[i].canvas_config[2].phy_addr =
 			hw->buffer_spec[i].v_addr;
 		hw->buffer_spec[i].canvas_config[2].width =
@@ -812,7 +833,7 @@
 		hw->not_run_ready,
 		hw->input_empty
 		);
-	if (vf_get_receiver(vdec->vf_provider_name)) {
+	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,
@@ -915,9 +936,10 @@
 	vdec_schedule_work(&hw->work);
 }
 
-static void check_timer_func(unsigned long arg)
+static void check_timer_func(struct timer_list *timer)
 {
-	struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)arg;
+	struct vdec_mjpeg_hw_s *hw = container_of(timer,
+		struct vdec_mjpeg_hw_s, check_timer);
 	struct vdec_s *vdec = hw_to_vdec(hw);
 	int timeout_val = decode_timeout_val;
 
@@ -986,10 +1008,16 @@
 	struct aml_vcodec_ctx *ctx =
 		(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
 
-	if (hw->buffer_spec[i].v4l_ref_buf_addr)
-		return 0;
+	if (hw->buffer_spec[i].v4l_ref_buf_addr) {
+		struct vdec_v4l2_buffer *fb =
+			(struct vdec_v4l2_buffer *)
+			hw->buffer_spec[i].v4l_ref_buf_addr;
 
-	ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
+		fb->status = FB_ST_DECODER;
+		return 0;
+	}
+
+	ret = ctx->fb_ops.alloc(&ctx->fb_ops, hw->fb_token, &fb, AML_FB_REQ_DEC);
 	if (ret < 0) {
 		mmjpeg_debug_print(DECODE_ID(hw), 0,
 			"[%d] get fb fail.\n",
@@ -998,6 +1026,8 @@
 		return ret;
 	}
 
+	fb->status	= FB_ST_DECODER;
+
 	if (!hw->frame_width || !hw->frame_height) {
 			struct vdec_pic_info pic;
 			vdec_v4l_get_pic_info(ctx, &pic);
@@ -1023,7 +1053,7 @@
 		decbuf_start	= fb->m.mem[0].addr;
 		decbuf_y_size	= fb->m.mem[0].size;
 		decbuf_u_start	= fb->m.mem[1].addr;
-		decbuf_u_size	= fb->m.mem[1].size;
+		decbuf_u_size	= fb->m.mem[1].size >> 1;
 		decbuf_v_start	= decbuf_u_start + decbuf_u_size;
 		decbuf_v_size	= decbuf_u_size;
 		canvas_width	= ALIGN(hw->frame_width, 64);
@@ -1045,7 +1075,7 @@
 	}
 
 	mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
-		"[%d] v4l ref buf addr: 0x%px\n", ctx->id, fb);
+		"[%d] v4l ref buf addr: 0x%x\n", ctx->id, fb);
 
 	if (vdec->parallel_dec == 1) {
 		if (hw->buffer_spec[i].y_canvas_index == -1)
@@ -1075,8 +1105,8 @@
 	hw->buffer_spec[i].canvas_config[0].endian =
 		hw->canvas_endian;
 
-	canvas_config_config(hw->buffer_spec[i].y_canvas_index,
-			&hw->buffer_spec[i].canvas_config[0]);
+	config_cav_lut(hw->buffer_spec[i].y_canvas_index,
+			&hw->buffer_spec[i].canvas_config[0], VDEC_1);
 
 	hw->buffer_spec[i].canvas_config[1].phy_addr =
 		decbuf_u_start;
@@ -1089,8 +1119,8 @@
 	hw->buffer_spec[i].canvas_config[1].endian =
 		hw->canvas_endian;
 
-	canvas_config_config(hw->buffer_spec[i].u_canvas_index,
-			&hw->buffer_spec[i].canvas_config[1]);
+	config_cav_lut(hw->buffer_spec[i].u_canvas_index,
+			&hw->buffer_spec[i].canvas_config[1], VDEC_1);
 
 	hw->buffer_spec[i].canvas_config[2].phy_addr =
 		decbuf_v_start;
@@ -1103,8 +1133,8 @@
 	hw->buffer_spec[i].canvas_config[2].endian =
 		hw->canvas_endian;
 
-	canvas_config_config(hw->buffer_spec[i].v_canvas_index,
-			&hw->buffer_spec[i].canvas_config[2]);
+	config_cav_lut(hw->buffer_spec[i].v_canvas_index,
+			&hw->buffer_spec[i].canvas_config[2], VDEC_1);
 
 	/* mjpeg decoder canvas need to be revert to match display. */
 	hw->buffer_spec[i].canvas_config[0].endian = hw->canvas_endian ? 0 : 7;
@@ -1157,6 +1187,9 @@
 			/*run to parser csd data*/
 			i = 0;
 		} else {
+			if (!ctx->fb_ops.query(&ctx->fb_ops, &hw->fb_token))
+				return -1;
+
 			if (vmjpeg_v4l_alloc_buff_config_canvas(hw, i))
 				return -1;
 		}
@@ -1183,12 +1216,12 @@
 		if (!hw->is_used_v4l) {
 			for (i = 0; i < hw->buf_num; i++) {
 				buff_spec = &hw->buffer_spec[i];
-				canvas_config_config(buff_spec->y_canvas_index,
-							&buff_spec->canvas_config[0]);
-				canvas_config_config(buff_spec->u_canvas_index,
-							&buff_spec->canvas_config[1]);
-				canvas_config_config(buff_spec->v_canvas_index,
-							&buff_spec->canvas_config[2]);
+				config_cav_lut(buff_spec->y_canvas_index,
+							&buff_spec->canvas_config[0], VDEC_1);
+				config_cav_lut(buff_spec->u_canvas_index,
+							&buff_spec->canvas_config[1], VDEC_1);
+				config_cav_lut(buff_spec->v_canvas_index,
+							&buff_spec->canvas_config[2], VDEC_1);
 			}
 		}
 	}
@@ -1284,10 +1317,7 @@
 		CODEC_MM_FLAGS_CMA_CLEAR |
 		CODEC_MM_FLAGS_FOR_VDECODER);
 
-	init_timer(&hw->check_timer);
-
-	hw->check_timer.data = (unsigned long)hw;
-	hw->check_timer.function = check_timer_func;
+	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;
@@ -1490,9 +1520,12 @@
 
 		if (hw->is_used_v4l) {
 			index = find_free_buffer(hw);
-			if ((index == -1) && vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
-				pr_err("[%d] get fb fail.\n", ctx->id);
-				return -1;
+			if (index == -1) {
+				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] get fb fail.\n", ctx->id);
+					return -1;
+				}
 			}
 		}
 
@@ -1501,13 +1534,18 @@
 		vf->v4l_mem_handle = (index == -1) ? (ulong)fb :
 			hw->buffer_spec[index].v4l_ref_buf_addr;
 		vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+		fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
 
 		vdec_vframe_ready(vdec, vf);
 		kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
-		vf_notify_receiver(vdec->vf_provider_name,
-			VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
 
-		pr_info("[%d] mpeg12 EOS notify.\n", (hw->is_used_v4l)?ctx->id:vdec->id);
+		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] mjpeg EOS notify.\n", (hw->is_used_v4l)?ctx->id:vdec->id);
 	}
 
 	return 0;
@@ -1718,8 +1756,9 @@
 
 	hw->buf_num = vmjpeg_get_buf_num(hw);
 
-	vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
-		&vf_provider_ops, pdata);
+	if (!hw->is_used_v4l)
+		vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
+			&vf_provider_ops, pdata);
 
 	platform_set_drvdata(pdev, pdata);
 
@@ -1774,6 +1813,7 @@
 			vdec->free_canvas_ex(hw->buffer_spec[i].v_canvas_index, vdec->id);
 		}
 	}
+
 	vfree(hw);
 
 	pr_info("%s\n", __func__);
@@ -1781,38 +1821,22 @@
 }
 
 /****************************************/
-#ifdef CONFIG_PM
-static int mmjpeg_suspend(struct device *dev)
-{
-	amvdec_suspend(to_platform_device(dev), dev->power.power_state);
-	return 0;
-}
-
-static int mmjpeg_resume(struct device *dev)
-{
-	amvdec_resume(to_platform_device(dev));
-	return 0;
-}
-
-static const struct dev_pm_ops mmjpeg_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(mmjpeg_suspend, mmjpeg_resume)
-};
-#endif
 
 static struct platform_driver ammvdec_mjpeg_driver = {
 	.probe = ammvdec_mjpeg_probe,
 	.remove = ammvdec_mjpeg_remove,
+#ifdef CONFIG_PM
+	.suspend = amvdec_suspend,
+	.resume = amvdec_resume,
+#endif
 	.driver = {
 		.name = DRIVER_NAME,
-#ifdef CONFIG_PM
-		.pm = &mmjpeg_pm_ops,
-#endif
 	}
 };
 
 static struct codec_profile_t ammvdec_mjpeg_profile = {
 	.name = "mmjpeg",
-	.profile = ""
+	.profile = "v4l"
 };
 
 static int __init ammvdec_mjpeg_driver_init_module(void)
@@ -1822,6 +1846,7 @@
 		return -ENODEV;
 	}
 	vcodec_profile_register(&ammvdec_mjpeg_profile);
+	vcodec_feature_register(VFORMAT_MJPEG, 0);
 	return 0;
 }
 
diff --git a/drivers/frame_provider/decoder/mpeg12/vmpeg12.c b/drivers/frame_provider/decoder/mpeg12/vmpeg12.c
index 29757a0..a813ac7 100644
--- a/drivers/frame_provider/decoder/mpeg12/vmpeg12.c
+++ b/drivers/frame_provider/decoder/mpeg12/vmpeg12.c
@@ -29,7 +29,7 @@
 #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/cpu_version.h>
+#include <linux/amlogic/media/registers/cpu_version.h>
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
@@ -41,7 +41,8 @@
 #include "../utils/decoder_bmmu_box.h"
 #include <linux/uaccess.h>
 #include <linux/amlogic/media/codec_mm/configs.h>
-#include <linux/amlogic/tee.h>
+//#include <linux/amlogic/tee.h>
+#include <uapi/linux/tee.h>
 
 
 
@@ -1310,11 +1311,9 @@
 }
 
 
-static void vmpeg_put_timer_func(unsigned long arg)
+static void vmpeg_put_timer_func(struct timer_list *timer)
 {
-	struct timer_list *timer = (struct timer_list *)arg;
 	int fatal_reset = 0;
-
 	enum receviver_start_e state = RECEIVER_INACTIVE;
 
 	if (vf_get_receiver(PROVIDER_NAME)) {
@@ -1765,30 +1764,30 @@
 
 		} else {
 #ifdef NV21
-			canvas_config(2 * i + 0,
+			config_cav_lut_ex(2 * i + 0,
 				buf_start,
 				canvas_width, canvas_height,
-				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
-			canvas_config(2 * i + 1,
+				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32, 0, VDEC_1);
+			config_cav_lut_ex(2 * i + 1,
 				buf_start +
 				decbuf_y_size, canvas_width,
 				canvas_height / 2, CANVAS_ADDR_NOWRAP,
-				CANVAS_BLKMODE_32X32);
+				CANVAS_BLKMODE_32X32, 0, VDEC_1);
 #else
-			canvas_config(3 * i + 0,
+			config_cav_lut_ex(3 * i + 0,
 				buf_start,
 				canvas_width, canvas_height,
-				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
-			canvas_config(3 * i + 1,
+				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32, 0, VDEC_1);
+			config_cav_lut_ex(3 * i + 1,
 				buf_start +
 				decbuf_y_size, canvas_width / 2,
 				canvas_height / 2, CANVAS_ADDR_NOWRAP,
-				CANVAS_BLKMODE_32X32);
-			canvas_config(3 * i + 2,
+				CANVAS_BLKMODE_32X32, 0, VDEC_1);
+			config_cav_lut_ex(3 * i + 2,
 				buf_start +
 				decbuf_y_size + decbuf_uv_size,
 				canvas_width / 2, canvas_height / 2,
-				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
+				CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32, 0, VDEC_1);
 #endif
 		}
 	}
@@ -1949,7 +1948,7 @@
 	if (IS_ERR_OR_NULL(buf))
 		return -ENOMEM;
 
-	init_timer(&recycle_timer);
+	timer_setup(&recycle_timer, vmpeg_put_timer_func, 0);
 
 	stat |= STAT_TIMER_INIT;
 
@@ -2014,10 +2013,7 @@
 
 	stat |= STAT_VF_HOOK;
 
-	recycle_timer.data = (ulong)&recycle_timer;
-	recycle_timer.function = vmpeg_put_timer_func;
 	recycle_timer.expires = jiffies + PUT_INTERVAL;
-
 	add_timer(&recycle_timer);
 
 	stat |= STAT_TIMER_ARM;
@@ -2159,32 +2155,16 @@
 }
 
 /****************************************/
-#ifdef CONFIG_PM
-static int mpeg12_suspend(struct device *dev)
-{
-	amvdec_suspend(to_platform_device(dev), dev->power.power_state);
-	return 0;
-}
-
-static int mpeg12_resume(struct device *dev)
-{
-	amvdec_resume(to_platform_device(dev));
-	return 0;
-}
-
-static const struct dev_pm_ops mpeg12_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(mpeg12_suspend, mpeg12_resume)
-};
-#endif
 
 static struct platform_driver amvdec_mpeg12_driver = {
 	.probe = amvdec_mpeg12_probe,
 	.remove = amvdec_mpeg12_remove,
+#ifdef CONFIG_PM
+	.suspend = amvdec_suspend,
+	.resume = amvdec_resume,
+#endif
 	.driver = {
 		.name = DRIVER_NAME,
-#ifdef CONFIG_PM
-		.pm = &mpeg12_pm_ops,
-#endif
 	}
 };
 
diff --git a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
index 76a021e..f77bb7f 100644
--- a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
+++ b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
@@ -15,6 +15,7 @@
  *
 */
 
+#define DEBUG
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -26,19 +27,19 @@
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-
+#include <linux/sched/clock.h>
 #include <linux/amlogic/media/frame_sync/ptsserv.h>
 #include <linux/amlogic/media/utils/amstream.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/tee.h>
+//#include <linux/amlogic/tee.h>
+#include <uapi/linux/tee.h>
 
 #include <linux/amlogic/media/utils/vdec_reg.h>
 #include <linux/amlogic/media/registers/register.h>
 #include "../../../stream_input/amports/amports_priv.h"
-
 #include "../utils/vdec_input.h"
 #include "../utils/vdec.h"
 #include "../utils/amvdec.h"
@@ -51,8 +52,7 @@
 #include "../utils/vdec_v4l2_buffer_ops.h"
 #include "../utils/config_parser.h"
 #include <media/v4l2-mem2mem.h>
-
-
+#include "../utils/vdec_feature.h"
 
 #define MEM_NAME "codec_mmpeg12"
 #define CHECK_INTERVAL        (HZ/100)
@@ -88,7 +88,6 @@
 #define PICINFO_RPT_FIRST   0x4000
 #define PICINFO_TOP_FIRST   0x2000
 #define PICINFO_FRAME       0x1000
-
 #define TOP_FIELD            0x1000
 #define BOTTOM_FIELD         0x2000
 #define FRAME_PICTURE        0x3000
@@ -112,6 +111,8 @@
 #define CTX_DECBUF_OFFSET       (CTX_CO_MV_OFFSET + 0x11000)
 
 #define DEFAULT_MEM_SIZE	(32*SZ_1M)
+#define INVALID_IDX 		(-1)  /* Invalid buffer index.*/
+
 static u32 buf_size = 32 * 1024 * 1024;
 static int pre_decode_buf_level = 0x800;
 static int start_decode_buf_level = 0x4000;
@@ -179,7 +180,6 @@
 #define DEC_RESULT_EOS 5
 #define DEC_RESULT_GET_DATA         6
 #define DEC_RESULT_GET_DATA_RETRY   7
-#define DEC_RESULT_DISCARD_DATA      8
 
 #define DEC_DECODE_TIMEOUT         0x21
 #define DECODE_ID(hw) (hw_to_vdec(hw)->id)
@@ -217,6 +217,7 @@
 	ulong v4l_ref_buf_addr;
 	u32 hw_decode_time;
 	u32 frame_size; // For frame base mode
+	u64 timestamp;
 };
 
 struct vdec_mpeg12_hw_s {
@@ -270,6 +271,7 @@
 	s32 refs[2];
 	int dec_result;
 	u32 timeout_processing;
+	wait_queue_head_t wait_q;
 	struct work_struct work;
 	struct work_struct timeout_work;
 	struct work_struct notify_work;
@@ -301,6 +303,7 @@
 	u32 pre_parser_wr_ptr;
 	u8 next_again_flag;
 #endif
+
 	struct work_struct userdata_push_work;
 	struct mutex userdata_mutex;
 	struct mmpeg2_userdata_info_t userdata_info;
@@ -339,17 +342,18 @@
 	u32 level_idc;
 	int dec_again_cnt;
 	int vdec_pg_enable_flag;
+	ulong fb_token;
 	char vdec_name[32];
 	char pts_name[32];
 	char new_q_name[32];
 	char disp_q_name[32];
-	u32 last_frame_offset;
+	bool run_flag;
 };
 
 static void vmpeg12_local_init(struct vdec_mpeg12_hw_s *hw);
 static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw);
 static void reset_process_time(struct vdec_mpeg12_hw_s *hw);
-static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw);
+static int vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw);
 static void flush_output(struct vdec_mpeg12_hw_s *hw);
 static struct vframe_s *vmpeg_vf_peek(void *);
 static struct vframe_s *vmpeg_vf_get(void *);
@@ -359,14 +363,12 @@
 static int notify_v4l_eos(struct vdec_s *vdec);
 static void start_process_time_set(struct vdec_mpeg12_hw_s *hw);
 static int check_dirty_data(struct vdec_s *vdec);
-
 static int debug_enable;
 /*static struct work_struct userdata_push_work;*/
 #undef pr_info
 #define pr_info printk
 unsigned int mpeg12_debug_mask = 0xff;
 /*static int counter_max = 5;*/
-
 static u32 run_ready_min_buf_num = 2;
 static int dirty_again_threshold = 100;
 static int error_proc_policy = 0x1;
@@ -374,7 +376,7 @@
 #define PRINT_FLAG_ERROR              0x0
 #define PRINT_FLAG_RUN_FLOW           0X0001
 #define PRINT_FLAG_TIMEINFO           0x0002
-#define PRINT_FLAG_UCODE_DETAIL       0x0004
+#define PRINT_FLAG_UCODE_DETAIL		  0x0004
 #define PRINT_FLAG_VLD_DETAIL         0x0008
 #define PRINT_FLAG_DEC_DETAIL         0x0010
 #define PRINT_FLAG_BUFFER_DETAIL      0x0020
@@ -388,25 +390,28 @@
 #define PRINT_FLAG_USERDATA_DETAIL    0x2000
 #define PRINT_FLAG_TIMEOUT_STATUS     0x4000
 #define PRINT_FLAG_V4L_DETAIL         0x8000
-#define PRINT_FLAG_FCC_STATUS         0x10000
 #define IGNORE_PARAM_FROM_CONFIG      0x8000000
 
 
 
-
 int debug_print(int index, int debug_flag, const char *fmt, ...)
 {
 	if (((debug_enable & debug_flag) &&
 		((1 << index) & mpeg12_debug_mask))
 		|| (debug_flag == PRINT_FLAG_ERROR)) {
-		unsigned char buf[512];
+		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_info("%s", buf);
 		va_end(args);
+		kfree(buf);
 	}
 	return 0;
 }
@@ -444,10 +449,16 @@
 	struct aml_vcodec_ctx *ctx =
 		(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
 
-	if (hw->pics[i].v4l_ref_buf_addr)
-		return 0;
+	if (hw->pics[i].v4l_ref_buf_addr) {
+		struct vdec_v4l2_buffer *fb =
+			(struct vdec_v4l2_buffer *)
+			hw->pics[i].v4l_ref_buf_addr;
 
-	ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
+		fb->status = FB_ST_DECODER;
+		return 0;
+	}
+
+	ret = ctx->fb_ops.alloc(&ctx->fb_ops, hw->fb_token, &fb, AML_FB_REQ_DEC);
 	if (ret < 0) {
 		debug_print(DECODE_ID(hw), 0,
 			"[%d] get fb fail %d/%d.\n",
@@ -455,6 +466,8 @@
 		return ret;
 	}
 
+	fb->status	= FB_ST_DECODER;
+
 	if (!hw->frame_width || !hw->frame_height) {
 		struct vdec_pic_info pic;
 		vdec_v4l_get_pic_info(ctx, &pic);
@@ -485,7 +498,7 @@
 		fb->m.mem[1].bytes_used = decbuf_uv_size;
 	}
 
-	debug_print(DECODE_ID(hw), 0, "[%d] %s(), v4l ref buf addr: 0x%px\n",
+	debug_print(DECODE_ID(hw), 0, "[%d] %s(), v4l ref buf addr: 0x%x\n",
 		ctx->id, __func__, fb);
 
 	if (vdec->parallel_dec == 1) {
@@ -513,7 +526,11 @@
 	hw->canvas_config[i][0].block_mode	= hw->canvas_mode;
 	hw->canvas_config[i][0].endian		=
 		(hw->canvas_mode == CANVAS_BLKMODE_LINEAR) ? 7 : 0;
-	canvas_config_config(canvas_y(canvas), &hw->canvas_config[i][0]);
+	config_cav_lut(canvas_y(canvas), &hw->canvas_config[i][0], VDEC_1);
+
+	/* mpeg2 decoder canvas need to be revert to match display canvas */
+	hw->canvas_config[i][0].endian          =
+		(hw->canvas_mode != CANVAS_BLKMODE_LINEAR) ? 7 : 0;
 
 	hw->canvas_config[i][1].phy_addr	= decbuf_uv_start;
 	hw->canvas_config[i][1].width		= canvas_width;
@@ -521,10 +538,14 @@
 	hw->canvas_config[i][1].block_mode	= hw->canvas_mode;
 	hw->canvas_config[i][1].endian		=
 		(hw->canvas_mode == CANVAS_BLKMODE_LINEAR) ? 7 : 0;
-	canvas_config_config(canvas_u(canvas), &hw->canvas_config[i][1]);
+	config_cav_lut(canvas_u(canvas), &hw->canvas_config[i][1], VDEC_1);
+
+	/* mpeg2 decoder canvas need to be revert to match display canvas */
+	hw->canvas_config[i][1].endian          =
+		(hw->canvas_mode != CANVAS_BLKMODE_LINEAR) ? 7 : 0;
 
 	debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL,
-		"[%d] %s(), canvas: 0x%x mode: %d y: %lx uv: %lx w: %d h: %d\n",
+		"[%d] %s(), canvas: 0x%x mode: %d y: %x uv: %x w: %d h: %d\n",
 		ctx->id, __func__, canvas, hw->canvas_mode,
 		decbuf_start, decbuf_uv_start,
 		canvas_width, canvas_height);
@@ -532,6 +553,7 @@
 	return 0;
 }
 
+
 static unsigned int vmpeg12_get_buf_num(struct vdec_mpeg12_hw_s *hw)
 {
 	unsigned int buf_num = DECODE_BUFFER_NUM_DEF;
@@ -576,6 +598,9 @@
 			/*run to parser csd data*/
 			i = 0;
 		} else {
+			if (!ctx->fb_ops.query(&ctx->fb_ops, &hw->fb_token))
+				return -1;
+
 			if (vmpeg12_v4l_alloc_buff_config_canvas(hw, i))
 				return -1;
 		}
@@ -1456,6 +1481,11 @@
 
 	offset = READ_VREG(AV_SCRATCH_I);
 
+	codec_mm_dma_flush(
+		hw->ccbuf_phyAddress_virt,
+		CCBUF_SIZE,
+		DMA_FROM_DEVICE);
+
 	mutex_lock(&hw->userdata_mutex);
 	if (hw->ccbuf_phyAddress_virt) {
 		pdata = (u8 *)hw->ccbuf_phyAddress_virt + hw->ucode_cc_last_wp;
@@ -1538,6 +1568,7 @@
 		if (pdata >= hw->userdata_info.data_buf_end)
 			pdata = hw->userdata_info.data_buf;
 	}
+
 	pcur_ud_rec = hw->ud_record + hw->cur_ud_idx;
 
 	pcur_ud_rec->meta_info = meta_info;
@@ -1564,7 +1595,6 @@
 
 	hw->cur_ud_idx++;
 	WRITE_VREG(AV_SCRATCH_J, 0);
-
 }
 
 
@@ -1611,12 +1641,10 @@
 	u32 info = pic->buffer_info;
 	struct vdec_s *vdec = hw_to_vdec(hw);
 	struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+	struct vdec_v4l2_buffer *fb = NULL;
 	ulong nv_order = VIDTYPE_VIU_NV21;
 	bool pb_skip = false;
 
-#ifdef NV21
-	type = nv_order;
-#endif
 	/* swap uv */
 	if (hw->is_used_v4l) {
 		if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) ||
@@ -1624,6 +1652,9 @@
 			nv_order = VIDTYPE_VIU_NV12;
 	}
 
+#ifdef NV21
+	type = nv_order;
+#endif
 	if (hw->i_only) {
 		pb_skip = 1;
 	}
@@ -1645,6 +1676,10 @@
 		field_num = (info & PICINFO_RPT_FIRST) ? 3 : 2;
 	}
 
+	if ((hw->is_used_v4l) &&
+		(vdec->prog_only))
+		field_num = 1;
+
 	for (i = 0; i < field_num; i++) {
 		if (kfifo_get(&hw->newframe_q, &vf) == 0) {
 			debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
@@ -1657,6 +1692,7 @@
 		if (hw->is_used_v4l) {
 			vf->v4l_mem_handle
 				= hw->pics[index].v4l_ref_buf_addr;
+			fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
 			debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
 				"[%d] %s(), v4l mem handle: 0x%lx\n",
 				((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id,
@@ -1701,9 +1737,11 @@
 		if (i > 0) {
 			vf->pts = 0;
 			vf->pts_us64 = 0;
+			vf->timestamp = 0;
 		} else {
 			vf->pts = (pic->pts_valid) ? pic->pts : 0;
 			vf->pts_us64 = (pic->pts_valid) ? pic->pts64 : 0;
+			vf->timestamp = pic->timestamp;
 		}
 		vf->type_original = vf->type;
 
@@ -1780,9 +1818,17 @@
 					__func__);
 			}
 			if (without_display_mode == 0) {
-				vf_notify_receiver(vdec->vf_provider_name,
-					VFRAME_EVENT_PROVIDER_VFRAME_READY,
-					NULL);
+				if (hw->is_used_v4l) {
+					if (v4l2_ctx->is_stream_off) {
+						vmpeg_vf_put(vmpeg_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
 				vmpeg_vf_put(vmpeg_vf_get(vdec), vdec);
 
@@ -1863,20 +1909,18 @@
 	return 0;
 }
 
-static int vmpeg2_get_ps_info(struct vdec_mpeg12_hw_s *hw, int width, int height,
-	bool frame_prog, struct aml_vdec_ps_infos *ps)
+static int vmpeg2_get_ps_info(struct vdec_mpeg12_hw_s *hw, int width, int height, struct aml_vdec_ps_infos *ps)
 {
 	ps->visible_width	= width;
 	ps->visible_height	= height;
 	ps->coded_width		= ALIGN(width, 64);
 	ps->coded_height 	= ALIGN(height, 32);
 	ps->dpb_size 		= hw->buf_num;
-	ps->field 		= frame_prog ? V4L2_FIELD_NONE : V4L2_FIELD_INTERLACED;
 
 	return 0;
 }
 
-static int v4l_res_change(struct vdec_mpeg12_hw_s *hw, int width, int height, bool frame_prog)
+static int v4l_res_change(struct vdec_mpeg12_hw_s *hw, int width, int height)
 {
 	struct aml_vcodec_ctx *ctx =
 			(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
@@ -1895,7 +1939,7 @@
 				hw->frame_width, hw->frame_height,
 				width,
 				height);
-			vmpeg2_get_ps_info(hw, width, height, frame_prog, &ps);
+			vmpeg2_get_ps_info(hw, width, height, &ps);
 			vdec_v4l_set_ps_infos(ctx, &ps);
 			vdec_v4l_res_ch_event(ctx);
 			hw->v4l_params_parsed = false;
@@ -1903,7 +1947,8 @@
 			ctx->v4l_resolution_change = 1;
 			hw->eos = 1;
 			flush_output(hw);
-			notify_v4l_eos(hw_to_vdec(hw));
+			if (hw->is_used_v4l)
+				notify_v4l_eos(hw_to_vdec(hw));
 
 			ret = 1;
 		}
@@ -1912,65 +1957,6 @@
 	return ret;
 }
 
-#ifdef VDEC_FCC_SUPPORT
-static void fcc_discard_mode_process(struct vdec_s *vdec)
-{
-	struct vdec_mpeg12_hw_s *hw =
-		(struct vdec_mpeg12_hw_s *)(vdec->private);
-	int wrap_count;
-	u32 rp;
-	u32 first_ptr;
-
-	if (vdec->fcc_status == AGAIN_STATUS) {
-		wrap_count = READ_VREG(VLD_MEM_VIFIFO_WRAP_COUNT);
-		rp = READ_VREG(VLD_MEM_VIFIFO_RP);
-		first_ptr = vdec->vbuf.ext_buf_addr;
-
-		vdec->stream_offset = rp + vdec->input.size * wrap_count - first_ptr;
-		debug_print(DECODE_ID(hw), PRINT_FLAG_FCC_STATUS,
-			"[%d][FCC]: Notify stream_offset: %d\n",
-			vdec->id, vdec->stream_offset);
-
-		debug_print(DECODE_ID(hw), PRINT_FLAG_FCC_STATUS,
-			"[%d][FCC]: rp : 0x%x size: 0x%x wrap_count:%d first_ptr: 0x%x\n",
-			vdec->id, rp, vdec->input.size, wrap_count, first_ptr);
-		vdec_wakeup_fcc_poll(vdec);
-		vdec->fcc_status = WAIT_MSG_STATUS;
-		hw->dec_result = DEC_RESULT_AGAIN;
-		vdec_schedule_work(&hw->work);
-	} else if (vdec->fcc_status == DISCARD_STATUS) {
-		debug_print(DECODE_ID(hw), PRINT_FLAG_FCC_STATUS,
-			"[%d][FCC]: Discard current gop and to find next gop!\n",
-			vdec->id);
-		vdec->fcc_status = AGAIN_STATUS;
-		hw->dec_result = DEC_RESULT_DISCARD_DATA;
-		vdec_schedule_work(&hw->work);
-	}
-}
-
-static int vmpeg2_fcc_process(struct vdec_s *vdec)
-{
-	struct vdec_mpeg12_hw_s *hw =
-		(struct vdec_mpeg12_hw_s *)(vdec->private);
-
-	if (input_stream_based(vdec)) {
-		switch (vdec->fcc_mode) {
-		case FCC_DISCARD_MODE:
-			fcc_discard_mode_process(vdec);
-			return 1;
-		case FCC_DEC_MODE:
-			debug_print(DECODE_ID(hw), PRINT_FLAG_FCC_STATUS,
-			"[%d][FCC]: Current is Dec mode.\n", vdec->id);
-			break;
-		case FCC_BUTT:
-		default:
-			break;
-		}
-	}
-
-	return 0;
-}
-#endif
 
 static irqreturn_t vmpeg12_isr_thread_fn(struct vdec_s *vdec, int irq)
 {
@@ -2002,26 +1988,16 @@
 				"[vdec_kpi][%s] First I frame coming.\n",
 				__func__);
 		}
-
-#ifdef VDEC_FCC_SUPPORT
-		if (vmpeg2_fcc_process(vdec) > 0) {
-			WRITE_VREG(AV_SCRATCH_G, 0);
-			return IRQ_HANDLED;
-		}
-#endif
 		if (hw->is_used_v4l) {
 			int frame_width = READ_VREG(MREG_PIC_WIDTH);
 			int frame_height = READ_VREG(MREG_PIC_HEIGHT);
-			int info = READ_VREG(MREG_SEQ_INFO);
-			bool frame_prog = info & 0x10000;
-
-			if (!v4l_res_change(hw, frame_width, frame_height, frame_prog)) {
+			if (!v4l_res_change(hw, frame_width, frame_height)) {
 				struct aml_vcodec_ctx *ctx =
 					(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
 				if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) {
 					struct aml_vdec_ps_infos ps;
 
-					vmpeg2_get_ps_info(hw, frame_width, frame_height, frame_prog, &ps);
+					vmpeg2_get_ps_info(hw, frame_width, frame_height, &ps);
 					hw->v4l_params_parsed = true;
 					vdec_v4l_set_ps_infos(ctx, &ps);
 					userdata_pushed_drop(hw);
@@ -2043,7 +2019,7 @@
 	}
 
 	reg = READ_VREG(AV_SCRATCH_J);
-	if (reg & (1 << 16)) {
+	if (reg & (1<<16)) {
 		vdec_schedule_work(&hw->userdata_push_work);
 		return IRQ_HANDLED;
 	}
@@ -2066,6 +2042,7 @@
 			READ_VREG(VLD_MEM_VIFIFO_LEVEL),
 			READ_VREG(VLD_MEM_VIFIFO_CONTROL),
 			READ_VREG(VIFF_BIT_CNT));
+
 		if (vdec_frame_based(vdec)) {
 			userdata_pushed_drop(hw);
 			hw->dec_result = DEC_RESULT_DONE;
@@ -2142,6 +2119,7 @@
 				new_pic->pts_valid = hw->chunk->pts_valid;
 				new_pic->pts = hw->chunk->pts;
 				new_pic->pts64 = hw->chunk->pts64;
+				new_pic->timestamp = hw->chunk->timestamp;
 				if (hw->last_chunk_pts == hw->chunk->pts) {
 					new_pic->pts_valid = 0;
 					debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO,
@@ -2161,12 +2139,9 @@
 		} else {
 			if (hw->chunk) {
 				hw->last_chunk_pts = hw->chunk->pts;
-				new_pic->pts_valid = hw->chunk->pts_valid;
-				new_pic->pts = hw->chunk->pts;
-				new_pic->pts64 = hw->chunk->pts64;
-			} else {
-				new_pic->pts_valid = false;
+				new_pic->timestamp = hw->chunk->timestamp;
 			}
+			new_pic->pts_valid = false;
 		}
 
 		debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
@@ -2224,9 +2199,10 @@
 		}
 
 		debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
-			"mmpeg12: disp_pic=%d(%c), ind=%d, offst=%x, pts=(%d,%lld)(%d)\n",
+			"mmpeg12: disp_pic=%d(%c), ind=%d, offst=%x, pts=(%d,%lld,%llx)(%d)\n",
 			hw->disp_num, GET_SLICE_TYPE(info), index, disp_pic->offset,
-			disp_pic->pts, disp_pic->pts64, disp_pic->pts_valid);
+			disp_pic->pts, disp_pic->pts64,
+			disp_pic->timestamp, disp_pic->pts_valid);
 
 		prepare_display_buf(hw, disp_pic);
 		vdec_schedule_work(&hw->work);
@@ -2238,32 +2214,30 @@
 {
 	u32 info, offset;
 	struct vdec_mpeg12_hw_s *hw =
-		(struct vdec_mpeg12_hw_s *)(vdec->private);
+	(struct vdec_mpeg12_hw_s *)(vdec->private);
 	if (hw->eos)
 		return IRQ_HANDLED;
 	info = READ_VREG(MREG_PIC_INFO);
 	offset = READ_VREG(MREG_FRAME_OFFSET);
-	if (offset != hw->last_frame_offset) {
-		vdec_count_info(&hw->gvs, info & PICINFO_ERROR, offset);
-		if (info & PICINFO_ERROR) {
-			if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) {
-				hw->gvs.i_concealed_frames++;
-			} else if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P) {
-				hw->gvs.p_concealed_frames++;
-			} else if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_B) {
-				hw->gvs.b_concealed_frames++;
-			}
+
+	vdec_count_info(&hw->gvs, info & PICINFO_ERROR, offset);
+	if (info &PICINFO_ERROR) {
+		if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) {
+			hw->gvs.i_concealed_frames++;
+		} else if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P) {
+			hw->gvs.p_concealed_frames++;
+		} else if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_B) {
+			hw->gvs.b_concealed_frames++;
 		}
-		if (offset) {
-			if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) {
-				hw->gvs.i_decoded_frames++;
-			} else if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P) {
-				hw->gvs.p_decoded_frames++;
-			} else if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_B) {
-				hw->gvs.b_decoded_frames++;
-			}
+	}
+	if (offset) {
+		if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) {
+			hw->gvs.i_decoded_frames++;
+		} else if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_P) {
+			hw->gvs.p_decoded_frames++;
+		} else if ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_B) {
+			hw->gvs.b_decoded_frames++;
 		}
-		hw->last_frame_offset = offset;
 	}
 
 	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
@@ -2277,7 +2251,7 @@
 					struct vdec_mpeg12_hw_s, notify_work);
 	struct vdec_s *vdec = hw_to_vdec(hw);
 
-	if (vdec->fr_hint_state == VDEC_NEED_HINT) {
+	if (!hw->is_used_v4l && 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));
@@ -2329,7 +2303,7 @@
 	struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
 	struct vframe_s *vf = NULL;
 	struct vdec_v4l2_buffer *fb = NULL;
-	int index = -1;
+	int index = INVALID_IDX;
 
 	if (hw->eos) {
 		if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) {
@@ -2340,24 +2314,31 @@
 		}
 		if (hw->is_used_v4l) {
 			index = find_free_buffer(hw);
-			if ((index == -1) &&
-				vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
-				pr_err("[%d] get fb fail.\n", ctx->id);
-				return -1;
+			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] get fb fail.\n", ctx->id);
+					return -1;
+				}
 			}
 		}
 
 		vf->type |= VIDTYPE_V4L_EOS;
 		vf->timestamp = ULONG_MAX;
-		vf->v4l_mem_handle = (index == -1) ? (ulong)fb :
+		vf->v4l_mem_handle = (index == INVALID_IDX) ? (ulong)fb :
 							hw->pics[index].v4l_ref_buf_addr;
 		vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+		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->pts_name, vf->pts);
-		vf_notify_receiver(vdec->vf_provider_name,
-			VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+
+		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] mpeg12 EOS notify.\n", (hw->is_used_v4l)?ctx->id:vdec->id);
 	}
@@ -2474,10 +2455,6 @@
 		debug_print(DECODE_ID(hw), 0,
 			"%s: end of stream, num %d(%d)\n",
 			__func__, hw->disp_num, hw->dec_num);
-	} else if (hw->dec_result == DEC_RESULT_DISCARD_DATA) {
-		hw->dec_again_cnt = 0;
-		vdec_vframe_dirty(vdec, hw->chunk);
-		hw->chunk = NULL;
 	}
 	if (hw->stat & STAT_VDEC_RUN) {
 		amvdec_stop();
@@ -2506,6 +2483,7 @@
 	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);
@@ -2725,7 +2703,7 @@
 
 
 /****************************************/
-static void vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw)
+static int vmpeg12_canvas_init(struct vdec_mpeg12_hw_s *hw)
 {
 	int i, ret;
 	u32 canvas_width, canvas_height;
@@ -2762,9 +2740,9 @@
 			ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i,
 					decbuf_size, DRIVER_NAME, &decbuf_start);
 			if (ret < 0) {
-				pr_err("mmu alloc failed! size 0x%d  idx %d\n",
+				pr_err("bmmu alloc failed! size 0x%d  idx %d\n",
 					decbuf_size, i);
-				return;
+				return ret;
 			}
 		}
 
@@ -2775,7 +2753,7 @@
 						  GFP_KERNEL);
 			if (hw->ccbuf_phyAddress_virt == NULL) {
 				pr_err("%s: failed to alloc cc buffer\n", __func__);
-				return;
+				return -ENOMEM;
 			}
 			hw->buf_start = decbuf_start;
 			WRITE_VREG(MREG_CO_MV_START, hw->buf_start);
@@ -2813,8 +2791,8 @@
 			hw->canvas_config[i][0].endian =
 				(hw->canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0;
 
-			canvas_config_config(canvas_y(canvas),
-			&hw->canvas_config[i][0]);
+			config_cav_lut(canvas_y(canvas),
+			&hw->canvas_config[i][0], VDEC_1);
 
 			hw->canvas_config[i][1].phy_addr =
 				decbuf_start + decbuf_y_size;
@@ -2824,11 +2802,11 @@
 			hw->canvas_config[i][1].endian =
 				(hw->canvas_mode == CANVAS_BLKMODE_LINEAR)?7:0;
 
-			canvas_config_config(canvas_u(canvas),
-				&hw->canvas_config[i][1]);
+			config_cav_lut(canvas_u(canvas),
+				&hw->canvas_config[i][1], VDEC_1);
 		}
 	}
-	return;
+	return 0;
 }
 
 static void vmpeg2_dump_state(struct vdec_s *vdec)
@@ -2839,11 +2817,12 @@
 	debug_print(DECODE_ID(hw), 0,
 		"====== %s\n", __func__);
 	debug_print(DECODE_ID(hw), 0,
-		"width/height (%d/%d),i_first %d, buf_num %d\n",
+		"width/height (%d/%d),i_first %d, buf_num %d, run_flag %d\n",
 		hw->frame_width,
 		hw->frame_height,
 		hw->first_i_frame_ready,
-		hw->buf_num
+		hw->buf_num,
+		hw->run_flag
 		);
 	debug_print(DECODE_ID(hw), 0,
 		"is_framebase(%d), eos %d, state 0x%x, dec_result 0x%x dec_frm %d put_frm %d run %d not_run_ready %d,input_empty %d\n",
@@ -2864,7 +2843,7 @@
 			hw->vfbuf_use[i], hw->ref_use[i]);
 	}
 
-	if (vf_get_receiver(vdec->vf_provider_name)) {
+	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,
@@ -2962,7 +2941,6 @@
 		hw->decode_timeout_count = 10;
 	hw->start_process_time = jiffies;
 }
-
 static void timeout_process(struct vdec_mpeg12_hw_s *hw)
 {
 	struct vdec_s *vdec = hw_to_vdec(hw);
@@ -2994,9 +2972,10 @@
 	vdec_schedule_work(&hw->timeout_work);
 }
 
-static void check_timer_func(unsigned long arg)
+static void check_timer_func(struct timer_list *timer)
 {
-	struct vdec_mpeg12_hw_s *hw = (struct vdec_mpeg12_hw_s *)arg;
+	struct vdec_mpeg12_hw_s *hw = container_of(timer,
+		struct vdec_mpeg12_hw_s, check_timer);
 	struct vdec_s *vdec = hw_to_vdec(hw);
 	unsigned int timeout_val = decode_timeout_val;
 
@@ -3036,24 +3015,26 @@
 
 static int vmpeg12_hw_ctx_restore(struct vdec_mpeg12_hw_s *hw)
 {
-	int index = -1;
-	u32 i;
+	u32 index = -1, i;
 	struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
 
 	index = find_free_buffer(hw);
 	if (index < 0 || index >= hw->buf_num)
 		return -1;
-	if (!hw->init_flag)
-		vmpeg12_canvas_init(hw);
-	else {
+	if (!hw->init_flag) {
+		if (vmpeg12_canvas_init(hw) < 0) {
+			debug_print(DECODE_ID(hw), 0, "vmpeg12_canvas_init failed\n");
+			return -1;
+		}
+	} else {
 		WRITE_VREG(MREG_CO_MV_START, hw->buf_start);
 		WRITE_VREG(MREG_CC_ADDR, hw->ccbuf_phyAddress);
 		if (!hw->is_used_v4l) {
 			for (i = 0; i < hw->buf_num; i++) {
-				canvas_config_config(canvas_y(hw->canvas_spec[i]),
-					&hw->canvas_config[i][0]);
-				canvas_config_config(canvas_u(hw->canvas_spec[i]),
-					&hw->canvas_config[i][1]);
+				config_cav_lut(canvas_y(hw->canvas_spec[i]),
+					&hw->canvas_config[i][0], VDEC_1);
+				config_cav_lut(canvas_u(hw->canvas_spec[i]),
+					&hw->canvas_config[i][1], VDEC_1);
 			}
 		}
 	}
@@ -3078,6 +3059,7 @@
 	READ_VREG(MREG_REF1),
 	READ_VREG(REC_CANVAS_ADDR),
 	hw->ctx_valid, index);
+
 	/* set to mpeg1 default */
 	WRITE_VREG(MPEG1_2_REG,
 	(hw->ctx_valid) ? hw->reg_mpeg1_2_reg : 0);
@@ -3225,6 +3207,7 @@
 	hw->dec_again_cnt = 0;
 	hw->error_frame_skip_level = error_frame_skip_level;
 
+	init_waitqueue_head(&hw->wait_q);
 	if (dec_control)
 		hw->dec_control = dec_control;
 }
@@ -3272,9 +3255,10 @@
 			USER_DATA_SIZE);
 
 	//amvdec_enable();
-	init_timer(&hw->check_timer);
-	hw->check_timer.data = (unsigned long)hw;
-	hw->check_timer.function = check_timer_func;
+	timer_setup(&hw->check_timer, check_timer_func, 0);
+	//init_timer(&hw->check_timer);
+	//hw->check_timer.data = (unsigned long)hw;
+	//hw->check_timer.function = check_timer_func;
 	hw->check_timer.expires = jiffies + CHECK_INTERVAL;
 
 	hw->stat |= STAT_TIMER_ARM;
@@ -3286,13 +3270,6 @@
 	return 0;
 }
 
-#ifdef VDEC_FCC_SUPPORT
-static void vmmpeg2_wakeup_fcc_poll(struct vdec_s *vdec)
-{
-	amstream_wakeup_fcc_poll(vdec);
-}
-#endif
-
 static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
 {
 	struct vdec_mpeg12_hw_s *hw =
@@ -3306,6 +3283,7 @@
 			"mpeg12 work pending,not ready for run.\n");
 		return 0;
 	}
+	hw->timeout_processing = 0;
 	if (vdec_stream_based(vdec) && (hw->init_flag == 0)
 		&& pre_decode_buf_level != 0) {
 		u32 rp, wp, level;
@@ -3363,17 +3341,10 @@
 	}
 
 	if (!is_enough_free_buffer(hw)) {
+		hw->not_run_ready++;
 		hw->buffer_not_ready++;
 		return 0;
 	}
-
-#ifdef VDEC_FCC_SUPPORT
-	if (!vdec_has_get_fcc_new_msg(vdec)) {
-		hw->buffer_not_ready++;
-		return 0;
-	}
-#endif
-
 	hw->not_run_ready = 0;
 	hw->buffer_not_ready = 0;
 	if (vdec->parallel_dec == 1)
@@ -3420,6 +3391,7 @@
 
 	if (level > (vdec->input.size / 2))
 		hw->dec_again_cnt++;
+
 	if (hw->dec_again_cnt > dirty_again_threshold) {
 		debug_print(DECODE_ID(hw), 0, "mpeg12 data skipped %x\n", level);
 		hw->dec_again_cnt = 0;
@@ -3437,6 +3409,8 @@
 		(struct vdec_mpeg12_hw_s *)vdec->private;
 	int save_reg;
 	int size, ret;
+
+	hw->run_flag = 1;
 	if (!hw->vdec_pg_enable_flag) {
 		hw->vdec_pg_enable_flag = 1;
 		amvdec_enable();
@@ -3467,6 +3441,7 @@
 		debug_print(DECODE_ID(hw), PRINT_FLAG_DEC_DETAIL,
 			"vdec_prepare_input: Insufficient data\n");
 		vdec_schedule_work(&hw->work);
+		hw->run_flag = 0;
 		return;
 	}
 
@@ -3495,8 +3470,8 @@
 		u8 *data = NULL;
 		if (hw->chunk)
 			debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
-				"run: chunk offset 0x%x, size %d, pts %d, pts64 %lld\n",
-				hw->chunk->offset, hw->chunk->size, hw->chunk->pts, hw->chunk->pts64);
+				"run: chunk offset 0x%x, size %d\n",
+				hw->chunk->offset, hw->chunk->size);
 
 		if (!hw->chunk->block->is_mapped)
 			data = codec_mm_vmap(hw->chunk->block->start +
@@ -3557,6 +3532,7 @@
 				hw->fw->name, tee_enabled() ? "TEE" : "local", ret);
 			hw->dec_result = DEC_RESULT_FORCE_EXIT;
 			vdec_schedule_work(&hw->work);
+			hw->run_flag = 0;
 			return;
 		}
 		vdec->mc_loaded = 1;
@@ -3567,7 +3543,7 @@
 		hw->dec_result = DEC_RESULT_ERROR;
 		debug_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
 		"ammvdec_mpeg12: error HW context restore\n");
-		vdec_schedule_work(&hw->work);
+		hw->run_flag = 0;
 		return;
 	}
 	/*wmb();*/
@@ -3580,14 +3556,29 @@
 		vdec->mvfrm->hw_decode_start = local_clock();
 	amvdec_start();
 	hw->stat |= STAT_VDEC_RUN;
+	hw->stat |= STAT_TIMER_ARM;
 	hw->init_flag = 1;
-
-	mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL);
+	if (hw->mm_blk_handle)
+		mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL);
+	hw->run_flag = 0;
 }
 
 static void reset(struct vdec_s *vdec)
 {
+	struct vdec_mpeg12_hw_s *hw = (struct vdec_mpeg12_hw_s *)vdec->private;
+
 	pr_info("ammvdec_mpeg12: reset.\n");
+
+	vmpeg12_local_init(hw);
+
+	if (hw->is_used_v4l) {
+		u32 i, buf_num = vmpeg12_get_buf_num(hw);
+		for (i = 0; i < buf_num; i++) {
+			hw->pics[i].v4l_ref_buf_addr = 0;
+		}
+	}
+
+	hw->ctx_valid = 0;
 }
 
 static int vmpeg12_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
@@ -3643,9 +3634,6 @@
 	pdata->reset_userdata_fifo = vmmpeg2_reset_userdata_fifo;
 	pdata->wakeup_userdata_poll = vmmpeg2_wakeup_userdata_poll;
 
-#ifdef VDEC_FCC_SUPPORT
-	pdata->wakeup_fcc_poll = vmmpeg2_wakeup_fcc_poll;
-#endif
 	snprintf(hw->vdec_name, sizeof(hw->vdec_name),
 		"mpeg12-%d", pdev->id);
 	snprintf(hw->pts_name, sizeof(hw->pts_name),
@@ -3738,7 +3726,6 @@
 		vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
 					| CORE_MASK_COMBINE);
 	}
-	hw->last_frame_offset = 0xFFFFFFFF;
 #ifdef DUMP_USER_DATA
 	amvdec_mmpeg12_init_userdata_dump(hw);
 	reset_user_data_buf(hw);
@@ -3757,6 +3744,17 @@
 	struct vdec_s *vdec = hw_to_vdec(hw);
 	int i;
 
+	if (vdec->next_status == VDEC_STATUS_DISCONNECTED
+		&& (vdec->status == VDEC_STATUS_ACTIVE)) {
+		debug_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 */
+	}
+
 	if (hw->stat & STAT_VDEC_RUN) {
 		amvdec_stop();
 		hw->stat &= ~STAT_VDEC_RUN;
@@ -3777,8 +3775,12 @@
 	cancel_work_sync(&hw->timeout_work);
 
 	if (hw->mm_blk_handle) {
-		decoder_bmmu_box_free(hw->mm_blk_handle);
+		void *bmmu_box_tmp = hw->mm_blk_handle;
 		hw->mm_blk_handle = NULL;
+		while (hw->run_flag)
+			usleep_range(1000, 2000);
+		decoder_bmmu_box_free(bmmu_box_tmp);
+		bmmu_box_tmp = NULL;
 	}
 	if (vdec->parallel_dec == 1)
 		vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1);
@@ -3823,38 +3825,22 @@
 }
 
 /****************************************/
-#ifdef CONFIG_PM
-static int mmpeg12_suspend(struct device *dev)
-{
-	amvdec_suspend(to_platform_device(dev), dev->power.power_state);
-	return 0;
-}
-
-static int mmpeg12_resume(struct device *dev)
-{
-	amvdec_resume(to_platform_device(dev));
-	return 0;
-}
-
-static const struct dev_pm_ops mmpeg12_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(mmpeg12_suspend, mmpeg12_resume)
-};
-#endif
 
 static struct platform_driver ammvdec_mpeg12_driver = {
 	.probe = ammvdec_mpeg12_probe,
 	.remove = ammvdec_mpeg12_remove,
+#ifdef CONFIG_PM
+	.suspend = amvdec_suspend,
+	.resume = amvdec_resume,
+#endif
 	.driver = {
 		.name = DRIVER_NAME,
-#ifdef CONFIG_PM
-		.pm = &mmpeg12_pm_ops,
-#endif
 	}
 };
 
 static struct codec_profile_t ammvdec_mpeg12_profile = {
 	.name = "mmpeg12",
-	.profile = ""
+	.profile = "v4l"
 };
 
 static struct mconfig mmpeg12_configs[] = {
@@ -3886,6 +3872,7 @@
 	vcodec_profile_register(&ammvdec_mpeg12_profile);
 	INIT_REG_NODE_CONFIGS("media.decoder", &mmpeg12_node,
 		"mmpeg12", mmpeg12_configs, CONFIG_FOR_RW);
+	vcodec_feature_register(VFORMAT_MPEG12, 0);
 	return 0;
 }
 
diff --git a/drivers/frame_provider/decoder/mpeg4/vmpeg4.c b/drivers/frame_provider/decoder/mpeg4/vmpeg4.c
index b13ca9c..7d33a75 100644
--- a/drivers/frame_provider/decoder/mpeg4/vmpeg4.c
+++ b/drivers/frame_provider/decoder/mpeg4/vmpeg4.c
@@ -26,12 +26,10 @@
 #include <linux/dma-mapping.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/canvas/canvas.h>
-
 #include <linux/amlogic/media/utils/vdec_reg.h>
 #include "vmpeg4.h"
 #include <linux/amlogic/media/registers/register.h>
@@ -40,10 +38,12 @@
 #include "../utils/decoder_bmmu_box.h"
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
 #include <linux/amlogic/media/codec_mm/configs.h>
-#include <linux/amlogic/tee.h>
+//#include <linux/amlogic/tee.h>
+#include <uapi/linux/tee.h>
 #include "../../../common/chips/decoder_cpu_ver_info.h"
 
 
+
 /* #define CONFIG_AM_VDEC_MPEG4_LOG */
 #ifdef CONFIG_AM_VDEC_MPEG4_LOG
 #define AMLOG
@@ -182,7 +182,6 @@
 static struct work_struct notify_work;
 static struct work_struct set_clk_work;
 static bool is_reset;
-static bool first_i_frame_ready;
 
 static DEFINE_SPINLOCK(lock);
 
@@ -436,8 +435,8 @@
 
 				pts += vop_time_inc_since_last_anch *
 					PTS_UNIT / rate;
-				pts_us64 += (u64)(vop_time_inc_since_last_anch *
-					PTS_UNIT / rate) * 100 / 9;
+				pts_us64 += div_u64((u64)(vop_time_inc_since_last_anch *
+					PTS_UNIT / rate) * 100, 9);
 
 				if (vop_time_inc_since_last_anch > (1 << 14)) {
 					/* avoid overflow */
@@ -463,11 +462,6 @@
 			}
 		}
 
-		if ( (first_i_frame_ready == 0) &&
-			(picture_type == I_PICTURE)) {
-			first_i_frame_ready = 1;
-		}
-
 		if (reg & INTERLACE_FLAG) {	/* interlace */
 			if (kfifo_get(&newframe_q, &vf) == 0) {
 				printk
@@ -498,23 +492,17 @@
 			set_aspect_ratio(vf, READ_VREG(MP4_PIC_RATIO));
 
 			vfbuf_use[buffer_index]++;
-
-			if (first_i_frame_ready == 0) {
-			    kfifo_put(&recycle_q, (const struct vframe_s *)vf);
-			} else {
-			    vf->mem_handle =
-			        decoder_bmmu_box_get_mem_handle(
+			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);
+			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);
-
-			}
+			vf_notify_receiver(PROVIDER_NAME,
+					VFRAME_EVENT_PROVIDER_VFRAME_READY,
+					NULL);
 
 			if (kfifo_get(&newframe_q, &vf) == 0) {
 				printk(
@@ -545,29 +533,23 @@
 
 			set_aspect_ratio(vf, READ_VREG(MP4_PIC_RATIO));
 
+			vfbuf_use[buffer_index]++;
+			vf->mem_handle =
+				decoder_bmmu_box_get_mem_handle(
+					mm_blk_handle,
+					buffer_index);
+
 			amlog_mask(LOG_MASK_PTS,
 			"[%s:%d] [inte] dur=0x%x rate=%d picture_type=%d\n",
 				__func__, __LINE__, vf->duration,
 				vmpeg4_amstream_dec_info.rate, picture_type);
 
-			vfbuf_use[buffer_index]++;
+			kfifo_put(&display_q, (const struct vframe_s *)vf);
+			ATRACE_COUNTER(MODULE_NAME, vf->pts);
 
-			if (first_i_frame_ready == 0) {
-			    kfifo_put(&recycle_q, (const struct vframe_s *)vf);
-			} else {
-			    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,
+			vf_notify_receiver(PROVIDER_NAME,
+				VFRAME_EVENT_PROVIDER_VFRAME_READY,
 				NULL);
-			}
-
 
 		} else {	/* progressive */
 			if (kfifo_get(&newframe_q, &vf) == 0) {
@@ -604,25 +586,18 @@
 			__func__, __LINE__, vf->duration,
 			vmpeg4_amstream_dec_info.rate, picture_type);
 
-
 			vfbuf_use[buffer_index]++;
-
-			if (first_i_frame_ready == 0) {
-			    kfifo_put(&recycle_q, (const struct vframe_s *)vf);
-			} else {
-			    vf->mem_handle =
+			vf->mem_handle =
 				decoder_bmmu_box_get_mem_handle(
-				mm_blk_handle,
-				buffer_index);
+					mm_blk_handle,
+					buffer_index);
 
-			    kfifo_put(&display_q, (const struct vframe_s *)vf);
-			    ATRACE_COUNTER(MODULE_NAME, vf->pts);
+			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);
-			}
-
+			vf_notify_receiver(PROVIDER_NAME,
+				VFRAME_EVENT_PROVIDER_VFRAME_READY,
+				NULL);
 		}
 
 		total_frame += repeat_cnt + 1;
@@ -750,10 +725,8 @@
 			frame_width, frame_height, fps);
 }
 
-static void vmpeg_put_timer_func(unsigned long arg)
+static void vmpeg_put_timer_func(struct timer_list *timer)
 {
-	struct timer_list *timer = (struct timer_list *)arg;
-
 	while (!kfifo_is_empty(&recycle_q) && (READ_VREG(MREG_BUFFERIN) == 0)) {
 		struct vframe_s *vf;
 
@@ -769,7 +742,7 @@
 
 	if (frame_dur > 0 && saved_resolution !=
 		frame_width * frame_height * (96000 / frame_dur))
-		schedule_work(&set_clk_work);
+	schedule_work(&set_clk_work);
 
 	if (READ_VREG(AV_SCRATCH_L)) {
 		pr_info("mpeg4 fatal error happened,need reset    !!\n");
@@ -899,30 +872,30 @@
 
 
 #ifdef NV21
-		canvas_config(2 * i + 0,
+		config_cav_lut_ex(2 * i + 0,
 			buf_start,
 			canvas_width, canvas_height,
-			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
-		canvas_config(2 * i + 1,
+			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32, 0, VDEC_1);
+		config_cav_lut_ex(2 * i + 1,
 			buf_start +
 			decbuf_y_size, canvas_width,
 			canvas_height / 2, CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_32X32);
+			CANVAS_BLKMODE_32X32, 0, VDEC_1);
 #else
-		canvas_config(3 * i + 0,
+		config_cav_lut_ex(3 * i + 0,
 			buf_start,
 			canvas_width, canvas_height,
-			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
-		canvas_config(3 * i + 1,
+			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32, 0, VDEC_1);
+		config_cav_lut_ex(3 * i + 1,
 			buf_start +
 			decbuf_y_size, canvas_width / 2,
 			canvas_height / 2, CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_32X32);
-		canvas_config(3 * i + 2,
+			CANVAS_BLKMODE_32X32, 0, VDEC_1);
+		config_cav_lut_ex(3 * i + 2,
 			buf_start +
 			decbuf_y_size + decbuf_uv_size,
 			canvas_width / 2, canvas_height / 2,
-			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
+			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32, 0, VDEC_1);
 #endif
 
 	}
@@ -1024,7 +997,6 @@
 
 	frame_num_since_last_anch = 0;
 
-	first_i_frame_ready = 0;
 #ifdef CONFIG_AM_VDEC_MPEG4_LOG
 	pts_hit = pts_missed = pts_i_hit = pts_i_missed = 0;
 #endif
@@ -1101,7 +1073,7 @@
 	stat |= STAT_MC_LOAD;
 	query_video_status(0, &trickmode_fffb);
 
-	init_timer(&recycle_timer);
+	timer_setup(&recycle_timer, vmpeg_put_timer_func, 0);
 	stat |= STAT_TIMER_INIT;
 
 	if (vdec_request_irq(VDEC_IRQ_1, vmpeg4_isr,
@@ -1146,10 +1118,7 @@
 
 	stat |= STAT_VF_HOOK;
 
-	recycle_timer.data = (ulong)&recycle_timer;
-	recycle_timer.function = vmpeg_put_timer_func;
 	recycle_timer.expires = jiffies + PUT_INTERVAL;
-
 	add_timer(&recycle_timer);
 
 	stat |= STAT_TIMER_ARM;
@@ -1256,32 +1225,16 @@
 }
 
 /****************************************/
-#ifdef CONFIG_PM
-static int mpeg4_suspend(struct device *dev)
-{
-	amvdec_suspend(to_platform_device(dev), dev->power.power_state);
-	return 0;
-}
-
-static int mpeg4_resume(struct device *dev)
-{
-	amvdec_resume(to_platform_device(dev));
-	return 0;
-}
-
-static const struct dev_pm_ops mpeg4_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(mpeg4_suspend, mpeg4_resume)
-};
-#endif
 
 static struct platform_driver amvdec_mpeg4_driver = {
 	.probe = amvdec_mpeg4_probe,
 	.remove = amvdec_mpeg4_remove,
+#ifdef CONFIG_PM
+	.suspend = amvdec_suspend,
+	.resume = amvdec_resume,
+#endif
 	.driver = {
 		.name = DRIVER_NAME,
-#ifdef CONFIG_PM
-		.pm = &mpeg4_pm_ops,
-#endif
 	}
 };
 
diff --git a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
index 167204c..00ceb71 100644
--- a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
+++ b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
@@ -24,15 +24,17 @@
 #include <linux/kfifo.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/delay.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/canvas/canvas.h>
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
-#include <linux/amlogic/tee.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 <linux/amlogic/media/registers/register.h>
 #include "../../../stream_input/amports/amports_priv.h"
@@ -47,8 +49,8 @@
 #include "../utils/firmware.h"
 #include "../utils/vdec_v4l2_buffer_ops.h"
 #include "../utils/config_parser.h"
-#include "../../../common/chips/decoder_cpu_ver_info.h"
 #include <media/v4l2-mem2mem.h>
+#include "../utils/vdec_feature.h"
 
 #define DRIVER_NAME "ammvdec_mpeg4"
 
@@ -185,14 +187,19 @@
 	if (((debug_enable & debug_flag) &&
 		((1 << index) & mpeg4_debug_mask))
 		|| (debug_flag == PRINT_FLAG_ERROR)) {
-		unsigned char buf[512];
+		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_info("%s", buf);
 		va_end(args);
+		kfree(buf);
 	}
 	return 0;
 }
@@ -209,6 +216,7 @@
 	ulong v4l_ref_buf_addr;
 	u32 hw_decode_time;
 	u32 frame_size; // For frame base mode;
+	u64 timestamp;
 	u32 offset;
 	u32 height;
 	u32 width;
@@ -321,6 +329,8 @@
 	int sidebind_type;
 	int sidebind_channel_id;
 	u32 res_ch_flag;
+	u32 profile_idc;
+	u32 level_idc;
 	unsigned int i_decoded_frames;
 	unsigned int i_lost_frames;
 	unsigned int i_concealed_frames;
@@ -330,13 +340,13 @@
 	unsigned int b_decoded_frames;
 	unsigned int b_lost_frames;
 	unsigned int b_concealed_frames;
-	u32 profile_idc;
-	u32 level_idc;
 	int vdec_pg_enable_flag;
+	ulong fb_token;
 	char vdec_name[32];
 	char pts_name[32];
 	char new_q_name[32];
 	char disp_q_name[32];
+	bool run_flag;
 };
 static void vmpeg4_local_init(struct vdec_mpeg4_hw_s *hw);
 static int vmpeg4_hw_ctx_restore(struct vdec_mpeg4_hw_s *hw);
@@ -371,7 +381,6 @@
 
 static void reset_process_time(struct vdec_mpeg4_hw_s *hw);
 
-
 static int vmpeg4_get_buf_num(struct vdec_mpeg4_hw_s *hw)
 {
 	int buf_num = DECODE_BUFFER_NUM_DEF;
@@ -395,10 +404,16 @@
 	struct aml_vcodec_ctx *ctx =
 		(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
 
-	if (hw->pic[i].v4l_ref_buf_addr)
-		return 0;
+	if (hw->pic[i].v4l_ref_buf_addr) {
+		struct vdec_v4l2_buffer *fb =
+			(struct vdec_v4l2_buffer *)
+			hw->pic[i].v4l_ref_buf_addr;
 
-	ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
+		fb->status = FB_ST_DECODER;
+		return 0;
+	}
+
+	ret = ctx->fb_ops.alloc(&ctx->fb_ops, hw->fb_token, &fb, AML_FB_REQ_DEC);
 	if (ret < 0) {
 		mmpeg4_debug_print(DECODE_ID(hw), 0,
 			"[%d] get fb fail.\n",
@@ -407,6 +422,8 @@
 		return ret;
 	}
 
+	fb->status	= FB_ST_DECODER;
+
 	if (!hw->frame_width || !hw->frame_height) {
 			struct vdec_pic_info pic;
 			vdec_v4l_get_pic_info(ctx, &pic);
@@ -437,8 +454,8 @@
 		fb->m.mem[1].bytes_used = decbuf_uv_size;
 	}
 
-	mmpeg4_debug_print(DECODE_ID(hw), 0, "[%d] %s(), v4l ref buf addr: 0x%px\n",
-		ctx->id, __func__, fb);
+	mmpeg4_debug_print(DECODE_ID(hw), 0, "[%d] %s(), v4l ref buf addr: 0x%x\n",
+		((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id, __func__, fb);
 
 	if (vdec->parallel_dec == 1) {
 		u32 tmp;
@@ -467,8 +484,11 @@
 		hw->canvas_config[i][0].endian = 7;
 	else
 		hw->canvas_config[i][0].endian = 0;
-	canvas_config_config(canvas_y(canvas),
-			&hw->canvas_config[i][0]);
+	config_cav_lut(canvas_y(canvas),
+			&hw->canvas_config[i][0], VDEC_1);
+	/* mpeg4 decoder canvas need to be revert to match display canvas */
+	hw->canvas_config[i][0].endian =
+		(hw->blkmode != CANVAS_BLKMODE_LINEAR) ? 7 : 0;
 
 	hw->canvas_config[i][1].phy_addr =
 		decbuf_uv_start;
@@ -479,8 +499,11 @@
 		hw->canvas_config[i][1].endian = 7;
 	else
 		hw->canvas_config[i][1].endian = 0;
-	canvas_config_config(canvas_u(canvas),
-			&hw->canvas_config[i][1]);
+	config_cav_lut(canvas_u(canvas),
+			&hw->canvas_config[i][1], VDEC_1);
+	/* mpeg4 decoder canvas need to be revert to match display canvas */
+	hw->canvas_config[i][1].endian =
+		(hw->blkmode != CANVAS_BLKMODE_LINEAR) ? 7 : 0;
 
 	return 0;
 }
@@ -514,14 +537,16 @@
 			(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
 		if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) {
 			/*run to parser csd data*/
-			i = 0;
+			i = 0xffffff;
 		} else {
+			if (!ctx->fb_ops.query(&ctx->fb_ops, &hw->fb_token))
+				return -1;
+
 			if (vmpeg4_v4l_alloc_buff_config_canvas(hw, i))
 				return -1;
 		}
 	}
 
-
 	return i;
 }
 
@@ -689,6 +714,7 @@
 	struct vframe_s *vf = NULL;
 	struct vdec_s *vdec = hw_to_vdec(hw);
 	struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+	struct vdec_v4l2_buffer *fb = NULL;
 	ulong nv_order = VIDTYPE_VIU_NV21;
 	int index = pic->index;
 	bool pb_skip = false;
@@ -699,6 +725,8 @@
 		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 (vdec->prog_only)
+			pic->pic_info &= ~INTERLACE_FLAG;
 	}
 
 	if (hw->i_only)
@@ -714,6 +742,7 @@
 		if (hw->is_used_v4l) {
 			vf->v4l_mem_handle
 				= hw->pic[index].v4l_ref_buf_addr;
+			fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
 			mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
 				"[%d] %s(), v4l mem handle: 0x%lx\n",
 				((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id,
@@ -728,6 +757,7 @@
 		vf->orientation = hw->vmpeg4_rotation;
 		vf->pts = pic->pts;
 		vf->pts_us64 = pic->pts64;
+		vf->timestamp = pic->timestamp;
 		vf->duration = pic->duration >> 1;
 		vf->duration_pulldown = 0;
 		vf->type = (pic->pic_info & TOP_FIELD_FIRST_FLAG) ?
@@ -741,7 +771,6 @@
 		mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO,
 			"field0: pts %d, pts64 %lld, w %d, h %d, dur %d\n",
 			vf->pts, vf->pts_us64, vf->width, vf->height, vf->duration);
-
 		if (vdec_stream_based(vdec) && (!vdec->vbuf.use_ptsserv)) {
 			vf->pts_us64 =
 				(((u64)vf->duration << 32) &
@@ -779,11 +808,20 @@
 				hw->b_decoded_frames++;
 			}
 			if (without_display_mode == 0) {
-				vf_notify_receiver(vdec->vf_provider_name,
-					VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+				if (hw->is_used_v4l) {
+					if (v4l2_ctx->is_stream_off) {
+						vmpeg_vf_put(vmpeg_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
 				vmpeg_vf_put(vmpeg_vf_get(vdec), vdec);
 		}
+
 		if (kfifo_get(&hw->newframe_q, &vf) == 0) {
 			mmpeg4_debug_print(DECODE_ID(hw), 0,
 				"error, no available buf.\n");
@@ -791,16 +829,6 @@
 			return -1;
 		}
 
-		if (hw->is_used_v4l) {
-			vf->v4l_mem_handle
-				= hw->pic[index].v4l_ref_buf_addr;
-			mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
-				"[%d] %s(), v4l mem handle: 0x%lx\n",
-				((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id,
-				__func__, vf->v4l_mem_handle);
-		}
-
-
 		vf->index = pic->index;
 		vf->width = pic->width;
 		vf->height = pic->height;
@@ -809,6 +837,7 @@
 		vf->orientation = hw->vmpeg4_rotation;
 		vf->pts = 0;
 		vf->pts_us64 = 0;
+		vf->timestamp = 0;
 		vf->duration = pic->duration >> 1;
 		vf->duration_pulldown = 0;
 		vf->type = (pic->pic_info & TOP_FIELD_FIRST_FLAG) ?
@@ -827,7 +856,6 @@
 			vf->pts_us64 = (u64)-1;
 			vf->pts = 0;
 		}
-
 		if (((hw->first_i_frame_ready == 0) || pb_skip)
 			&& (pic->pic_type != I_PICTURE)) {
 			hw->drop_frame_count++;
@@ -862,8 +890,16 @@
 				hw->b_decoded_frames++;
 			}
 			if (without_display_mode == 0) {
-				vf_notify_receiver(vdec->vf_provider_name,
-					VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+				if (hw->is_used_v4l) {
+					if (v4l2_ctx->is_stream_off) {
+						vmpeg_vf_put(vmpeg_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
 				vmpeg_vf_put(vmpeg_vf_get(vdec), vdec);
 		}
@@ -875,6 +911,7 @@
 			hw->dec_result = DEC_RESULT_ERROR;
 			return -1;
 		}
+
 		if (hw->is_used_v4l) {
 			vf->v4l_mem_handle
 				= hw->pic[index].v4l_ref_buf_addr;
@@ -892,6 +929,7 @@
 		vf->orientation = hw->vmpeg4_rotation;
 		vf->pts = pic->pts;
 		vf->pts_us64 = pic->pts64;
+		vf->timestamp = pic->timestamp;
 		vf->duration = pic->duration;
 		vf->duration_pulldown = pic->repeat_cnt *
 			pic->duration;
@@ -908,14 +946,12 @@
 		mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO,
 			"prog: pts %d, pts64 %lld, w %d, h %d, dur %d\n",
 			vf->pts, vf->pts_us64, vf->width, vf->height, vf->duration);
-
 		if (vdec_stream_based(vdec) && (!vdec->vbuf.use_ptsserv)) {
 			vf->pts_us64 =
 				(((u64)vf->duration << 32) &
 				0xffffffff00000000) | pic->offset;
 			vf->pts = 0;
 		}
-
 		if (((hw->first_i_frame_ready == 0) || pb_skip)
 			&& (pic->pic_type != I_PICTURE)) {
 			hw->drop_frame_count++;
@@ -956,8 +992,16 @@
 			vdec_fill_vdec_frame(vdec, NULL,
 				&vinfo, vf, pic->hw_decode_time);
 			if (without_display_mode == 0) {
-				vf_notify_receiver(vdec->vf_provider_name,
-					VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+				if (hw->is_used_v4l) {
+					if (v4l2_ctx->is_stream_off) {
+						vmpeg_vf_put(vmpeg_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
 				vmpeg_vf_put(vmpeg_vf_get(vdec), vdec);
 		}
@@ -983,8 +1027,7 @@
 	/* reset VLD fifo for all vdec */
 	WRITE_VREG(DOS_SW_RESET0, (1<<5) | (1<<4) | (1<<3));
 	WRITE_VREG(DOS_SW_RESET0, 0);
-	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SC2)
-		dummy = READ_RESET_REG(RESET0_REGISTER);
+
 	WRITE_VREG(POWER_CTL_VLD, 1 << 4);
 
 	/*
@@ -1026,19 +1069,18 @@
 	}
 }
 
-static int vmpeg4_get_ps_info(struct vdec_mpeg4_hw_s *hw, int width, int height, int interlace, struct aml_vdec_ps_infos *ps)
+static int vmpeg4_get_ps_info(struct vdec_mpeg4_hw_s *hw, int width, int height, struct aml_vdec_ps_infos *ps)
 {
 	ps->visible_width	= width;
 	ps->visible_height	= height;
 	ps->coded_width		= ALIGN(width, 64);
 	ps->coded_height 	= ALIGN(height, 64);
 	ps->dpb_size 		= hw->buf_num;
-	ps->field       	= interlace ? V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE;
 
 	return 0;
 }
 
-static int v4l_res_change(struct vdec_mpeg4_hw_s *hw, int width, int height, int interlace)
+static int v4l_res_change(struct vdec_mpeg4_hw_s *hw, int width, int height)
 {
 	struct aml_vcodec_ctx *ctx =
 			(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
@@ -1057,7 +1099,7 @@
 				hw->frame_width, hw->frame_height,
 				width,
 				height);
-			vmpeg4_get_ps_info(hw, width, height, interlace, &ps);
+			vmpeg4_get_ps_info(hw, width, height, &ps);
 			vdec_v4l_set_ps_infos(ctx, &ps);
 			vdec_v4l_res_ch_event(ctx);
 			hw->v4l_params_parsed = false;
@@ -1065,7 +1107,8 @@
 			ctx->v4l_resolution_change = 1;
 			hw->eos = 1;
 			flush_output(hw);
-			notify_v4l_eos(hw_to_vdec(hw));
+			if (hw->is_used_v4l)
+				notify_v4l_eos(hw_to_vdec(hw));
 
 			ret = 1;
 		}
@@ -1087,7 +1130,6 @@
 	u32 repeat_cnt, duration = 3200;
 	struct pic_info_t *dec_pic, *disp_pic;
 	struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)(vdec->private);
-
 	if (hw->eos)
 		return IRQ_HANDLED;
 
@@ -1095,16 +1137,13 @@
 		if (hw->is_used_v4l) {
 			int frame_width = READ_VREG(MP4_PIC_WH)>> 16;
 			int frame_height = READ_VREG(MP4_PIC_WH) & 0xffff;
-			int interlace = (READ_VREG(MP4_PIC_RATIO) & 0x80000000) >> 31;
-			mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL,
-				"interlace = %d\n", interlace);
-			if (!v4l_res_change(hw, frame_width, frame_height, interlace)) {
+			if (!v4l_res_change(hw, frame_width, frame_height)) {
 				struct aml_vcodec_ctx *ctx =
 					(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
 				if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) {
 					struct aml_vdec_ps_infos ps;
 
-					vmpeg4_get_ps_info(hw, frame_width, frame_height, interlace, &ps);
+					vmpeg4_get_ps_info(hw, frame_width, frame_height, &ps);
 					hw->v4l_params_parsed = true;
 					vdec_v4l_set_ps_infos(ctx, &ps);
 					reset_process_time(hw);
@@ -1123,6 +1162,14 @@
 		return IRQ_HANDLED;
 	}
 
+	if ((hw->is_used_v4l) && !hw->v4l_params_parsed) {
+		mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
+			"The head was not found, can not to decode\n");
+		hw->dec_result = DEC_RESULT_DONE;
+		vdec_schedule_work(&hw->work);
+		return IRQ_HANDLED;
+	}
+
 	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
 	if (READ_VREG(AV_SCRATCH_M) != 0 &&
 		(debug_enable & PRINT_FLAG_UCODE_DETAIL)) {
@@ -1220,6 +1267,7 @@
 		dec_pic->pts_valid = false;
 		dec_pic->pts = 0;
 		dec_pic->pts64 = 0;
+		dec_pic->timestamp = 0;
 		mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_BUFFER_DETAIL,
 			"new pic: index=%d, used=%d, repeat=%d, time_inc=%d\n",
 			index, hw->vfbuf_use[index], repeat_cnt, vop_time_inc);
@@ -1234,6 +1282,7 @@
 			hw->frame_height = dec_h;
 			dec_pic->height = dec_h;
 		}
+		hw->res_ch_flag = 0;
 
 		if (hw->vmpeg4_amstream_dec_info.rate == 0) {
 			if (vop_time_inc < hw->last_vop_time_inc) {
@@ -1278,6 +1327,7 @@
 			dec_pic->pts_valid = hw->chunk->pts_valid;
 			dec_pic->pts = hw->chunk->pts;
 			dec_pic->pts64 = hw->chunk->pts64;
+			dec_pic->timestamp = hw->chunk->timestamp;
 			if ((B_PICTURE == picture_type) ||
 				(hw->last_dec_pts == dec_pic->pts))
 				dec_pic->pts_valid = 0;
@@ -1290,6 +1340,7 @@
 				dec_pic->pts_valid = hw->chunk->pts_valid;
 				dec_pic->pts = hw->chunk->pts;
 				dec_pic->pts64 = hw->chunk->pts64;
+				dec_pic->timestamp = hw->chunk->timestamp;
 			} else {
 				dec_pic->offset = offset;
 				if ((vdec->vbuf.no_parser == 0) || (vdec->vbuf.use_ptsserv)) {
@@ -1317,10 +1368,11 @@
 		dec_pic->duration = duration;
 		hw->vfbuf_use[index] = 0;
 		mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
-			"mmpeg4: pic_num: %d, index %d, type %c, pts %x, pts64 %lld, height %d, width %d\n",
+			"mmpeg4: pic_num: %d, index %d, type %c, pts %x\n",
 			hw->frame_num, index,
 			GET_PIC_TYPE(picture_type),
-			dec_pic->pts, dec_pic->pts64, dec_pic->height, dec_pic->width);
+			dec_pic->pts);
+
 		/* buffer management */
 		if ((picture_type == I_PICTURE) ||
 			(picture_type == P_PICTURE)) {
@@ -1440,15 +1492,17 @@
 			if (!disp_pic->pts_valid) {
 				disp_pic->pts = 0;
 				disp_pic->pts64 = 0;
+				disp_pic->timestamp = 0;
 			}
 		}
 		mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_TIMEINFO,
-			"disp: pic_type %c, pts %d(%lld), diff %d, cnt %d\n",
+			"disp: pic_type %c, pts %d(%lld), diff %d, cnt %d, disp_pic->timestamp %llu\n",
 			GET_PIC_TYPE(disp_pic->pic_type),
 			disp_pic->pts,
 			disp_pic->pts64,
 			disp_pic->pts - hw->last_pts,
-			hw->chunk_frame_count);
+			hw->chunk_frame_count,
+			disp_pic->timestamp);
 		hw->last_pts = disp_pic->pts;
 		hw->last_pts64 = disp_pic->pts64;
 		hw->frame_dur = duration;
@@ -1543,10 +1597,12 @@
 
 		if (hw->is_used_v4l) {
 			index = find_free_buffer(hw);
-			if ((index == -1) &&
-					vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
-				pr_err("[%d] get fb fail.\n", ctx->id);
-				return -1;
+			if ((index == -1) || (index == 0xffffff)) {
+				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] get fb fail.\n", ctx->id);
+					return -1;
+				}
 			}
 		}
 
@@ -1555,12 +1611,17 @@
 		vf->v4l_mem_handle = (index == -1) ? (ulong)fb :
 							hw->pic[index].v4l_ref_buf_addr;;
 		vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+		fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
 
 		vdec_vframe_ready(vdec, vf);
 		kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
+
+		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);
 		ATRACE_COUNTER(hw->pts_name, vf->pts);
-		vf_notify_receiver(vdec->vf_provider_name,
-			VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
 
 		pr_info("[%d] mpeg4 EOS notify.\n", (hw->is_used_v4l)?ctx->id:vdec->id);
 	}
@@ -1587,7 +1648,7 @@
 			hw->ctx_valid = 1;
 
 	} else if ((hw->dec_result == DEC_RESULT_DONE) ||
-		((input_frame_based(&vdec->input)) && hw->chunk)) {
+		((!hw->is_used_v4l) && (input_frame_based(&vdec->input)) && hw->chunk)) {
 		if (!hw->ctx_valid)
 			hw->ctx_valid = 1;
 
@@ -1622,6 +1683,7 @@
 		hw->chunk = NULL;
 		vdec_clean_input(vdec);
 		flush_output(hw);
+
 		notify_v4l_eos(vdec);
 
 		mmpeg4_debug_print(DECODE_ID(hw), 0,
@@ -1851,25 +1913,26 @@
 			ret = decoder_bmmu_box_alloc_buf_phy(hw->mm_blk_handle, i,
 					decbuf_size, DRIVER_NAME, &decbuf_start);
 			if (ret < 0) {
-				pr_err("mmu alloc failed! size %d  idx %d\n",
+				pr_err("bmmu alloc failed! size %d  idx %d\n",
 					decbuf_size, i);
 				return ret;
 			}
-			if (!vdec_secure(vdec)) {
-				/*init internal buf*/
-				char *tmpbuf = (char *)codec_mm_phys_to_virt(decbuf_start);
+		}
+
+		if (!vdec_secure(vdec)) {
+			/*init internal buf*/
+			char *tmpbuf = (char *)codec_mm_phys_to_virt(decbuf_start);
+			if (tmpbuf) {
+				memset(tmpbuf, 0, decbuf_size);
+				codec_mm_dma_flush(tmpbuf,
+					   decbuf_size, DMA_TO_DEVICE);
+			} else {
+				tmpbuf = codec_mm_vmap(decbuf_start, decbuf_size);
 				if (tmpbuf) {
 					memset(tmpbuf, 0, decbuf_size);
 					codec_mm_dma_flush(tmpbuf,
 						   decbuf_size, DMA_TO_DEVICE);
-				} else {
-					tmpbuf = codec_mm_vmap(decbuf_start, decbuf_size);
-					if (tmpbuf) {
-						memset(tmpbuf, 0, decbuf_size);
-						codec_mm_dma_flush(tmpbuf,
-							   decbuf_size, DMA_TO_DEVICE);
-						codec_mm_unmap_phyaddr(tmpbuf);
-					}
+					codec_mm_unmap_phyaddr(tmpbuf);
 				}
 			}
 		}
@@ -1906,8 +1969,8 @@
 				hw->canvas_config[i][0].endian = 7;
 			else
 				hw->canvas_config[i][0].endian = 0;
-			canvas_config_config(canvas_y(canvas),
-					&hw->canvas_config[i][0]);
+			config_cav_lut(canvas_y(canvas),
+					&hw->canvas_config[i][0], VDEC_1);
 
 			hw->canvas_config[i][1].phy_addr =
 				decbuf_start + decbuf_y_size;
@@ -1918,8 +1981,8 @@
 				hw->canvas_config[i][1].endian = 7;
 			else
 				hw->canvas_config[i][1].endian = 0;
-			canvas_config_config(canvas_u(canvas),
-					&hw->canvas_config[i][1]);
+			config_cav_lut(canvas_u(canvas),
+					&hw->canvas_config[i][1], VDEC_1);
 		}
 	}
 
@@ -1934,12 +1997,13 @@
 	mmpeg4_debug_print(DECODE_ID(hw), 0,
 		"====== %s\n", __func__);
 	mmpeg4_debug_print(DECODE_ID(hw), 0,
-		"width/height (%d/%d), i_fram:%d, buffer_not_ready %d, buf_num %d\n",
+		"width/height (%d/%d), i_fram:%d, buffer_not_ready %d, buf_num %d, run_flag %d\n",
 		hw->frame_width,
 		hw->frame_height,
 		hw->first_i_frame_ready,
 		hw->buffer_not_ready,
-		hw->buf_num
+		hw->buf_num,
+		hw->run_flag
 		);
 	for (i = 0; i < hw->buf_num; i++) {
 		mmpeg4_debug_print(DECODE_ID(hw), 0,
@@ -1964,7 +2028,7 @@
 		hw->drop_frame_count
 		);
 
-	if (vf_get_receiver(vdec->vf_provider_name)) {
+	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,
@@ -2079,9 +2143,10 @@
 }
 
 
-static void check_timer_func(unsigned long arg)
+static void check_timer_func(struct timer_list *timer)
 {
-	struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)arg;
+	struct vdec_mpeg4_hw_s *hw = container_of(timer,
+		struct vdec_mpeg4_hw_s, check_timer);
 	struct vdec_s *vdec = hw_to_vdec(hw);
 	unsigned int timeout_val = decode_timeout_val;
 
@@ -2135,10 +2200,10 @@
 	} else {
 		if (!hw->is_used_v4l) {
 			for (i = 0; i < hw->buf_num; i++) {
-				canvas_config_config(canvas_y(hw->canvas_spec[i]),
-							&hw->canvas_config[i][0]);
-				canvas_config_config(canvas_u(hw->canvas_spec[i]),
-							&hw->canvas_config[i][1]);
+				config_cav_lut(canvas_y(hw->canvas_spec[i]),
+							&hw->canvas_config[i][0], VDEC_1);
+				config_cav_lut(canvas_u(hw->canvas_spec[i]),
+							&hw->canvas_config[i][1], VDEC_1);
 			}
 		}
 	}
@@ -2151,14 +2216,17 @@
 		WRITE_VREG(MREG_REF0, (hw->refs[1] == -1) ? 0xffffffff :
 					hw->canvas_spec[hw->refs[1]]);
 	} else {
-		WRITE_VREG(MREG_REF0, (hw->refs[0] == -1) ? 0xffffffff :
-					hw->canvas_spec[hw->refs[0]]);
+		WRITE_VREG(MREG_REF0, hw->canvas_spec[hw->refs[0]]);
 	}
 	WRITE_VREG(MREG_REF1, (hw->refs[1] == -1) ? 0xffffffff :
 				hw->canvas_spec[hw->refs[1]]);
-
-	WRITE_VREG(REC_CANVAS_ADDR, hw->canvas_spec[index]);
-	WRITE_VREG(ANC2_CANVAS_ADDR, hw->canvas_spec[index]);
+	if ((hw->is_used_v4l) && (index == 0xffffff)) {
+		WRITE_VREG(REC_CANVAS_ADDR, 0xffffff);
+		WRITE_VREG(ANC2_CANVAS_ADDR, 0xffffff);
+	} else {
+		WRITE_VREG(REC_CANVAS_ADDR, hw->canvas_spec[index]);
+		WRITE_VREG(ANC2_CANVAS_ADDR, hw->canvas_spec[index]);
+	}
 
 	mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RESTORE,
 	"restore ref0=0x%x, ref1=0x%x, rec=0x%x, ctx_valid=%d,index=%d\n",
@@ -2254,7 +2322,7 @@
 	hw->unstable_pts =
 	   (((unsigned long) hw->vmpeg4_amstream_dec_info.param & 0x40) >> 6);
 	mmpeg4_debug_print(DECODE_ID(hw), 0,
-		"param = 0x%px unstable_pts = %d\n",
+		"param = 0x%x unstable_pts = %d\n",
 		hw->vmpeg4_amstream_dec_info.param,
 		hw->unstable_pts);
 	hw->last_dec_pts = -1;
@@ -2354,9 +2422,10 @@
 
 	//amvdec_enable();
 
-	init_timer(&hw->check_timer);
-	hw->check_timer.data = (unsigned long)hw;
-	hw->check_timer.function = check_timer_func;
+	timer_setup(&hw->check_timer, check_timer_func, 0);
+	//init_timer(&hw->check_timer);
+	//hw->check_timer.data = (unsigned long)hw;
+	//hw->check_timer.function = check_timer_func;
 	hw->check_timer.expires = jiffies + CHECK_INTERVAL;
 	hw->stat |= STAT_TIMER_ARM;
 	hw->eos = 0;
@@ -2371,7 +2440,6 @@
 static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
 {
 	struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private;
-
 	if (hw->eos)
 		return 0;
 	if (vdec_stream_based(vdec) && (hw->init_flag == 0)
@@ -2451,6 +2519,8 @@
 {
 	struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private;
 	int size = 0, ret = 0;
+
+	hw->run_flag = 1;
 	if (!hw->vdec_pg_enable_flag) {
 		hw->vdec_pg_enable_flag = 1;
 		amvdec_enable();
@@ -2470,6 +2540,7 @@
 			hw->input_empty++;
 			hw->dec_result = DEC_RESULT_AGAIN;
 			vdec_schedule_work(&hw->work);
+			hw->run_flag = 0;
 			return;
 		}
 		if ((vdec_frame_based(vdec)) &&
@@ -2496,10 +2567,10 @@
 
 		if (!hw->chunk->block->is_mapped)
 			data = codec_mm_vmap(hw->chunk->block->start +
-				hw->chunk->offset, size);
+				hw->chunk_offset, size);
 		else
 			data = ((u8 *)hw->chunk->block->start_virt) +
-				hw->chunk->offset;
+				hw->chunk_offset;
 
 		mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_VDEC_STATUS,
 			"%s: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n",
@@ -2554,6 +2625,7 @@
 				hw->fw->name, tee_enabled() ? "TEE" : "local", ret);
 			hw->dec_result = DEC_RESULT_FORCE_EXIT;
 			vdec_schedule_work(&hw->work);
+			hw->run_flag = 0;
 			return;
 		}
 		vdec->mc_loaded = 1;
@@ -2563,7 +2635,7 @@
 		hw->dec_result = DEC_RESULT_ERROR;
 		mmpeg4_debug_print(DECODE_ID(hw), 0,
 			"amvdec_mpeg4: error HW context restore\n");
-		vdec_schedule_work(&hw->work);
+		hw->run_flag = 0;
 		return;
 	}
 	if (vdec_frame_based(vdec)) {
@@ -2584,8 +2656,10 @@
 		vdec->mvfrm->hw_decode_start = local_clock();
 	amvdec_start();
 	hw->stat |= STAT_VDEC_RUN;
+	hw->stat |= STAT_TIMER_ARM;
 	hw->init_flag = 1;
 	mod_timer(&hw->check_timer, jiffies + CHECK_INTERVAL);
+	hw->run_flag = 0;
 }
 
 static int vmpeg4_stop(struct vdec_mpeg4_hw_s *hw)
@@ -2593,8 +2667,12 @@
 	cancel_work_sync(&hw->work);
 
 	if (hw->mm_blk_handle) {
-			decoder_bmmu_box_free(hw->mm_blk_handle);
-			hw->mm_blk_handle = NULL;
+		void *bmmu_box_tmp = hw->mm_blk_handle;
+		hw->mm_blk_handle = NULL;
+		while (hw->run_flag)
+			usleep_range(1000, 2000);
+		decoder_bmmu_box_free(bmmu_box_tmp);
+		bmmu_box_tmp = NULL;
 	}
 
 	if (hw->stat & STAT_TIMER_ARM) {
@@ -2616,6 +2694,12 @@
 
 	vmpeg4_local_init(hw);
 
+	if (hw->is_used_v4l) {
+		u32 i, buf_num = vmpeg4_get_buf_num(hw);
+		for (i = 0; i < buf_num; i++) {
+			hw->pic[i].v4l_ref_buf_addr = 0;
+		}
+	}
 	hw->ctx_valid = 0;
 }
 
@@ -2687,15 +2771,24 @@
 	platform_set_drvdata(pdev, pdata);
 	hw->platform_dev = pdev;
 
+	if (((debug_enable & IGNORE_PARAM_FROM_CONFIG) == 0) && pdata->config_len) {
+		mmpeg4_debug_print(DECODE_ID(hw), 0, "pdata->config: %s\n", pdata->config);
+		if (get_config_int(pdata->config, "parm_v4l_buffer_margin",
+			&config_val) == 0)
+			hw->dynamic_buf_num_margin = config_val;
+		else
+			hw->dynamic_buf_num_margin = dynamic_buf_num_margin;
+	} else {
+		hw->dynamic_buf_num_margin = dynamic_buf_num_margin;
+	}
+	hw->buf_num = vmpeg4_get_buf_num(hw);
+
 	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, &vf_provider_ops, pdata);
-
 	hw->blkmode = pdata->canvas_mode;
 
 	if (pdata->sys_info) {
@@ -2717,7 +2810,6 @@
 			hw->vmpeg4_amstream_dec_info.height,
 			hw->vmpeg4_amstream_dec_info.rate);
 	}
-
 	if (((debug_enable & IGNORE_PARAM_FROM_CONFIG) == 0) && pdata->config_len) {
 		mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_RUN_FLOW,
 			 "pdata->config: %s\n", pdata->config);
@@ -2747,6 +2839,10 @@
 	} else
 		hw->dynamic_buf_num_margin = dynamic_buf_num_margin;
 
+	if (!hw->is_used_v4l)
+		vf_provider_init(&pdata->vframe_provider,
+			pdata->vf_provider_name, &vf_provider_ops, pdata);
+
 	hw->buf_num = vmpeg4_get_buf_num(hw);
 
 	if (vmmpeg4_init(hw) < 0) {
@@ -2817,38 +2913,22 @@
 }
 
 /****************************************/
-#ifdef CONFIG_PM
-static int mmpeg4_suspend(struct device *dev)
-{
-	amvdec_suspend(to_platform_device(dev), dev->power.power_state);
-	return 0;
-}
-
-static int mmpeg4_resume(struct device *dev)
-{
-	amvdec_resume(to_platform_device(dev));
-	return 0;
-}
-
-static const struct dev_pm_ops mmpeg4_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(mmpeg4_suspend, mmpeg4_resume)
-};
-#endif
 
 static struct platform_driver ammvdec_mpeg4_driver = {
 	.probe = ammvdec_mpeg4_probe,
 	.remove = ammvdec_mpeg4_remove,
+#ifdef CONFIG_PM
+	.suspend = amvdec_suspend,
+	.resume = amvdec_resume,
+#endif
 	.driver = {
 		.name = DRIVER_NAME,
-#ifdef CONFIG_PM
-		.pm = &mmpeg4_pm_ops,
-#endif
 	}
 };
 
 static struct codec_profile_t amvdec_mpeg4_profile = {
 	.name = "mmpeg4",
-	.profile = ""
+	.profile = "v4l, no_single"
 };
 
 static int __init ammvdec_mpeg4_driver_init_module(void)
@@ -2860,6 +2940,7 @@
 		return -ENODEV;
 	}
 	vcodec_profile_register(&amvdec_mpeg4_profile);
+	vcodec_feature_register(VFORMAT_MPEG4, 0);
 	return 0;
 }
 
diff --git a/drivers/frame_provider/decoder/real/Makefile b/drivers/frame_provider/decoder/real/Makefile
deleted file mode 100644
index ab03ef2..0000000
--- a/drivers/frame_provider/decoder/real/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_REAL) += amvdec_real.o
-amvdec_real-objs += vreal.o
diff --git a/drivers/frame_provider/decoder/real/vreal.c b/drivers/frame_provider/decoder/real/vreal.c
deleted file mode 100644
index f6474b6..0000000
--- a/drivers/frame_provider/decoder/real/vreal.c
+++ /dev/null
@@ -1,1069 +0,0 @@
-/*
- * drivers/amlogic/amports/vreal.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/fs.h>
-#include <linux/kfifo.h>
-#include <linux/platform_device.h>
-
-#include <linux/amlogic/media/canvas/canvas.h>
-
-#include <linux/dma-mapping.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/vfm/vframe.h>
-#include <linux/amlogic/media/vfm/vframe_provider.h>
-#include <linux/amlogic/media/vfm/vframe_receiver.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/uaccess.h>
-#include "../../../stream_input/amports/amports_priv.h"
-#include "../utils/vdec.h"
-#include <linux/amlogic/media/utils/vdec_reg.h>
-#include "../utils/amvdec.h"
-
-#include "../../../stream_input/amports/streambuf.h"
-#include "../../../stream_input/amports/streambuf_reg.h"
-#include "../../../stream_input/parser/rmparser.h"
-
-#include "vreal.h"
-#include <linux/amlogic/media/registers/register.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 <linux/amlogic/tee.h>
-
-
-
-#define DRIVER_NAME "amvdec_real"
-#define MODULE_NAME "amvdec_real"
-
-#if 1	/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
-#define NV21
-#endif
-
-#define RM_DEF_BUFFER_ADDR        0x01000000
-/* protocol registers */
-#define STATUS_AMRISC   AV_SCRATCH_4
-
-#define RV_PIC_INFO     AV_SCRATCH_5
-#define VPTS_TR         AV_SCRATCH_6
-#define VDTS            AV_SCRATCH_7
-#define FROM_AMRISC     AV_SCRATCH_8
-#define TO_AMRISC       AV_SCRATCH_9
-#define SKIP_B_AMRISC   AV_SCRATCH_A
-#define INT_REASON      AV_SCRATCH_B
-#define WAIT_BUFFER     AV_SCRATCH_E
-
-#if 1	/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
-#define MDEC_WIDTH      AV_SCRATCH_I
-#define MDEC_HEIGHT     AV_SCRATCH_J
-#else
-#define MDEC_WIDTH      HARM_ASB_MB2
-#define MDEC_HEIGHT     HASB_ARM_MB0
-#endif
-
-#define PARC_FORBIDDEN              0
-#define PARC_SQUARE                 1
-#define PARC_CIF                    2
-#define PARC_10_11                  3
-#define PARC_16_11                  4
-#define PARC_40_33                  5
-#define PARC_RESERVED               6
-/* values between 6 and 14 are reserved */
-#define PARC_EXTENDED              15
-
-#define VF_POOL_SIZE        16
-#define VF_BUF_NUM          4
-#define PUT_INTERVAL        (HZ/100)
-#define WORKSPACE_SIZE		(1 * SZ_1M)
-#define MAX_BMMU_BUFFER_NUM	(VF_BUF_NUM + 1)
-#define RV_AI_BUFF_START_IP	 0x01f00000
-
-static struct vframe_s *vreal_vf_peek(void *);
-static struct vframe_s *vreal_vf_get(void *);
-static void vreal_vf_put(struct vframe_s *, void *);
-static int vreal_vf_states(struct vframe_states *states, void *);
-static int vreal_event_cb(int type, void *data, void *private_data);
-
-static int vreal_prot_init(void);
-static void vreal_local_init(void);
-
-static const char vreal_dec_id[] = "vreal-dev";
-
-#define PROVIDER_NAME   "decoder.real"
-
-/*
- *int query_video_status(int type, int *value);
- */
-static const struct vframe_operations_s vreal_vf_provider = {
-	.peek = vreal_vf_peek,
-	.get = vreal_vf_get,
-	.put = vreal_vf_put,
-	.event_cb = vreal_event_cb,
-	.vf_states = vreal_vf_states,
-};
-
-static struct vframe_provider_s vreal_vf_prov;
-static void *mm_blk_handle;
-
-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 struct vframe_s vfpool[VF_POOL_SIZE];
-static s32 vfbuf_use[VF_BUF_NUM];
-
-static u32 frame_width, frame_height, frame_dur, frame_prog;
-static u32 saved_resolution;
-static struct timer_list recycle_timer;
-static u32 stat;
-static u32 buf_size = 32 * 1024 * 1024;
-static u32 buf_offset;
-static u32 vreal_ratio;
-u32 vreal_format;
-static u32 wait_key_frame;
-static u32 last_tr;
-static u32 frame_count;
-static u32 current_vdts;
-static u32 hold;
-static u32 decoder_state;
-static u32 real_err_count;
-
-static u32 fatal_flag;
-static s32 wait_buffer_counter;
-static struct work_struct set_clk_work;
-static bool is_reset;
-
-static DEFINE_SPINLOCK(lock);
-
-static unsigned short pic_sz_tbl[12] ____cacheline_aligned;
-static dma_addr_t pic_sz_tbl_map;
-static const unsigned char RPR_size[9] = { 0, 1, 1, 2, 2, 3, 3, 3, 3 };
-
-static struct dec_sysinfo vreal_amstream_dec_info;
-
-static unsigned char aspect_ratio_table[16] = {
-	PARC_FORBIDDEN,
-	PARC_SQUARE,
-	PARC_CIF,
-	PARC_10_11,
-	PARC_16_11,
-	PARC_40_33,
-	PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED,
-	PARC_RESERVED, PARC_RESERVED, PARC_RESERVED, PARC_RESERVED,
-	PARC_RESERVED, PARC_EXTENDED
-};
-
-static inline u32 index2canvas(u32 index)
-{
-	const u32 canvas_tab[4] = {
-#ifdef NV21
-		0x010100, 0x030302, 0x050504, 0x070706
-#else
-		0x020100, 0x050403, 0x080706, 0x0b0a09
-#endif
-	};
-
-	return canvas_tab[index];
-}
-
-static void set_aspect_ratio(struct vframe_s *vf, unsigned int pixel_ratio)
-{
-	int ar = 0;
-
-	if (vreal_ratio == 0) {
-		vf->ratio_control |= (0x90 <<
-			DISP_RATIO_ASPECT_RATIO_BIT);
-		/* always stretch to 16:9 */
-	} else {
-		switch (aspect_ratio_table[pixel_ratio]) {
-		case 0:
-			ar = vreal_amstream_dec_info.height * vreal_ratio /
-				 vreal_amstream_dec_info.width;
-			break;
-		case 1:
-		case 0xff:
-			ar = vreal_ratio * vf->height / vf->width;
-			break;
-		case 2:
-			ar = (vreal_ratio * vf->height * 12) / (vf->width * 11);
-			break;
-		case 3:
-			ar = (vreal_ratio * vf->height * 11) / (vf->width * 10);
-			break;
-		case 4:
-			ar = (vreal_ratio * vf->height * 11) / (vf->width * 16);
-			break;
-		case 5:
-			ar = (vreal_ratio * vf->height * 33) / (vf->width * 40);
-			break;
-		default:
-			ar = vreal_ratio * vf->height / vf->width;
-			break;
-		}
-	}
-
-	ar = min(ar, DISP_RATIO_ASPECT_RATIO_MAX);
-
-	vf->ratio_control |= (ar << DISP_RATIO_ASPECT_RATIO_BIT);
-}
-
-static irqreturn_t vreal_isr(int irq, void *dev_id)
-{
-	u32 from;
-	struct vframe_s *vf = NULL;
-	u32 buffer_index;
-	unsigned int status;
-	unsigned int vdts;
-	unsigned int info;
-	unsigned int tr;
-	unsigned int pictype;
-	u32 r = READ_VREG(INT_REASON);
-
-	if (decoder_state == 0)
-		return IRQ_HANDLED;
-
-	status = READ_VREG(STATUS_AMRISC);
-	if (status & (PARSER_ERROR_WRONG_PACKAGE_SIZE |
-		PARSER_ERROR_WRONG_HEAD_VER |
-		DECODER_ERROR_VLC_DECODE_TBL)) {
-		/* decoder or parser error */
-		real_err_count++;
-		/* pr_info("real decoder or parser
-		 *error, status 0x%x\n", status);
-		 */
-	}
-
-	if (r == 2) {
-		pr_info("first vpts = 0x%x\n", READ_VREG(VDTS));
-		pts_checkin_offset(PTS_TYPE_AUDIO, 0, READ_VREG(VDTS) * 90);
-		WRITE_VREG(AV_SCRATCH_B, 0);
-		WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
-		return IRQ_HANDLED;
-	} else if (r == 3) {
-		pr_info("first apts = 0x%x\n", READ_VREG(VDTS));
-		pts_checkin_offset(PTS_TYPE_VIDEO, 0, READ_VREG(VDTS) * 90);
-		WRITE_VREG(AV_SCRATCH_B, 0);
-		WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
-		return IRQ_HANDLED;
-	}
-
-	from = READ_VREG(FROM_AMRISC);
-	if ((hold == 0) && from) {
-		tr = READ_VREG(VPTS_TR);
-		pictype = (tr >> 13) & 3;
-		tr = (tr & 0x1fff) * 96;
-
-		if (kfifo_get(&newframe_q, &vf) == 0) {
-			pr_info("fatal error, no available buffer slot.");
-			return IRQ_HANDLED;
-		}
-
-		vdts = READ_VREG(VDTS);
-		if (last_tr == -1)	/* ignore tr for first time */
-			vf->duration = frame_dur;
-		else {
-			if (tr > last_tr)
-				vf->duration = tr - last_tr;
-			else
-				vf->duration = (96 << 13) + tr - last_tr;
-
-			if (vf->duration > 10 * frame_dur) {
-				/* not a reasonable duration,
-				 *should not happen
-				 */
-				vf->duration = frame_dur;
-			}
-#if 0
-			else {
-				if (check_frame_duration == 0) {
-					frame_dur = vf->duration;
-					check_frame_duration = 1;
-				}
-			}
-#endif
-		}
-
-		last_tr = tr;
-		buffer_index = from & 0x03;
-
-		if (pictype == 0) {	/* I */
-			current_vdts = vdts * 90 + 1;
-			vf->pts = current_vdts;
-			if (wait_key_frame)
-				wait_key_frame = 0;
-		} else {
-			if (wait_key_frame) {
-				while (READ_VREG(TO_AMRISC))
-					;
-				WRITE_VREG(TO_AMRISC, ~(1 << buffer_index));
-				WRITE_VREG(FROM_AMRISC, 0);
-				return IRQ_HANDLED;
-			} else {
-				current_vdts +=
-					vf->duration - (vf->duration >> 4);
-				vf->pts = current_vdts;
-			}
-		}
-
-		/* pr_info("pts %d, picture type %d\n", vf->pts, pictype); */
-
-		info = READ_VREG(RV_PIC_INFO);
-		vf->signal_type = 0;
-		vf->index = buffer_index;
-		vf->width = info >> 16;
-		vf->height = (info >> 4) & 0xfff;
-		vf->bufWidth = 1920;
-		vf->flag = 0;
-		vf->ratio_control = 0;
-		set_aspect_ratio(vf, info & 0x0f);
-		vf->duration_pulldown = 0;
-#ifdef NV21
-		vf->type = VIDTYPE_PROGRESSIVE |
-				VIDTYPE_VIU_FIELD | VIDTYPE_VIU_NV21;
-#else
-		vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
-#endif
-		vf->canvas0Addr = vf->canvas1Addr = index2canvas(buffer_index);
-		vf->orientation = 0;
-		vf->type_original = vf->type;
-
-		vfbuf_use[buffer_index] = 1;
-		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);
-
-		frame_count++;
-		vf_notify_receiver(PROVIDER_NAME,
-			VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
-		WRITE_VREG(FROM_AMRISC, 0);
-	}
-
-	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
-
-	return IRQ_HANDLED;
-}
-
-static struct vframe_s *vreal_vf_peek(void *op_arg)
-{
-	struct vframe_s *vf;
-
-	if (kfifo_peek(&display_q, &vf))
-		return vf;
-
-	return NULL;
-}
-
-static struct vframe_s *vreal_vf_get(void *op_arg)
-{
-	struct vframe_s *vf;
-
-	if (kfifo_get(&display_q, &vf))
-		return vf;
-
-	return NULL;
-}
-
-static void vreal_vf_put(struct vframe_s *vf, void *op_arg)
-{
-	kfifo_put(&recycle_q, (const struct vframe_s *)vf);
-}
-
-static int vreal_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(&vreal_vf_prov);
-#endif
-		spin_lock_irqsave(&lock, flags);
-		vreal_local_init();
-		vreal_prot_init();
-		spin_unlock_irqrestore(&lock, flags);
-#ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
-		vf_reg_provider(&vreal_vf_prov);
-#endif
-		amvdec_start();
-	}
-	return 0;
-}
-
-static int vreal_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;
-}
-#if 0
-#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
-static void vreal_ppmgr_reset(void)
-{
-	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL);
-
-	vreal_local_init();
-
-	pr_info("vrealdec: vf_ppmgr_reset\n");
-}
-#endif
-#endif
-
-static void vreal_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_REAL,
-			frame_width, frame_height, fps);
-	}
-}
-
-static void vreal_put_timer_func(unsigned long arg)
-{
-	struct timer_list *timer = (struct timer_list *)arg;
-	/* unsigned int status; */
-
-#if 0
-	enum receviver_start_e state = RECEIVER_INACTIVE;
-
-	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;
-
-	if ((READ_VREG(WAIT_BUFFER) != 0) &&
-		kfifo_is_empty(&display_q) &&
-		kfifo_is_empty(&recycle_q) && (state == RECEIVER_INACTIVE)) {
-		pr_info("$$$$$$decoder is waiting for buffer\n");
-		if (++wait_buffer_counter > 2) {
-			amvdec_stop();
-
-#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
-			vreal_ppmgr_reset();
-#else
-			vf_light_unreg_provider(&vreal_vf_prov);
-			vreal_local_init();
-			vf_reg_provider(&vreal_vf_prov);
-#endif
-			vreal_prot_init();
-			amvdec_start();
-		}
-	}
-#endif
-
-	while (!kfifo_is_empty(&recycle_q) && (READ_VREG(TO_AMRISC) == 0)) {
-		struct vframe_s *vf;
-
-		if (kfifo_get(&recycle_q, &vf)) {
-			if ((vf->index < VF_BUF_NUM)
-				&& (--vfbuf_use[vf->index] == 0)) {
-				WRITE_VREG(TO_AMRISC, ~(1 << vf->index));
-				vf->index = VF_BUF_NUM;
-			}
-
-			kfifo_put(&newframe_q, (const struct vframe_s *)vf);
-		}
-	}
-
-	schedule_work(&set_clk_work);
-
-	timer->expires = jiffies + PUT_INTERVAL;
-
-	add_timer(timer);
-}
-
-int vreal_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
-{
-	if (!(stat & STAT_VDEC_RUN))
-		return -1;
-
-	vstatus->frame_width = vreal_amstream_dec_info.width;
-	vstatus->frame_height = vreal_amstream_dec_info.height;
-	if (0 != vreal_amstream_dec_info.rate)
-		vstatus->frame_rate = 96000 / vreal_amstream_dec_info.rate;
-	else
-		vstatus->frame_rate = 96000;
-	vstatus->error_count = real_err_count;
-	vstatus->status =
-		((READ_VREG(STATUS_AMRISC) << 16) | fatal_flag) | stat;
-	/* pr_info("vreal_dec_status 0x%x\n", vstatus->status); */
-	return 0;
-}
-
-int vreal_set_isreset(struct vdec_s *vdec, int isreset)
-{
-	is_reset = isreset;
-	return 0;
-}
-
-/****************************************/
-static int  vreal_canvas_init(void)
-{
-	int i, ret;
-	unsigned long buf_start;
-	u32 canvas_width, canvas_height;
-	u32 alloc_size, decbuf_size, decbuf_y_size, decbuf_uv_size;
-
-	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 */
-	#if 1
-		int w = vreal_amstream_dec_info.width;
-		int h = vreal_amstream_dec_info.height;
-		int align_w, align_h;
-		int max, min;
-
-		align_w = ALIGN(w, 64);
-		align_h = ALIGN(h, 64);
-		if (align_w > align_h) {
-			max = align_w;
-			min = align_h;
-		} else {
-			canvas_width = 1920;
-			canvas_height = 1088;
-			max = align_h;
-			min = align_w;
-		}
-		/* HD & SD */
-		if ((max > 1920 || min > 1088) &&
-			ALIGN(align_w * align_h * 3/2, SZ_64K) * 9 <=
-			buf_size) {
-			canvas_width = align_w;
-			canvas_height = align_h;
-			decbuf_y_size = ALIGN(align_w * align_h, SZ_64K);
-			decbuf_uv_size = ALIGN(align_w * align_h/4, SZ_64K);
-			decbuf_size = ALIGN(align_w * align_h * 3/2, SZ_64K);
-		} else { /*1080p*/
-			if (h > w) {
-				canvas_width = 1088;
-				canvas_height = 1920;
-			} else {
-				canvas_width = 1920;
-				canvas_height = 1088;
-			}
-			decbuf_y_size = 0x200000;
-			decbuf_uv_size = 0x80000;
-			decbuf_size = 0x300000;
-		}
-		#endif
-	}
-
-	for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) {
-		/* workspace mem */
-		if (i == (MAX_BMMU_BUFFER_NUM - 1))
-			alloc_size =  WORKSPACE_SIZE;
-		else
-			alloc_size = decbuf_size;
-
-		ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, i,
-				alloc_size, DRIVER_NAME, &buf_start);
-		if (ret < 0)
-			return ret;
-
-		if (i == (MAX_BMMU_BUFFER_NUM - 1)) {
-			buf_offset = buf_start - RV_AI_BUFF_START_IP;
-			continue;
-		}
-
-#ifdef NV21
-		canvas_config(2 * i + 0,
-			buf_start,
-			canvas_width, canvas_height,
-			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
-		canvas_config(2 * i + 1,
-			buf_start +
-			decbuf_y_size, canvas_width,
-			canvas_height / 2, CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_32X32);
-#else
-		canvas_config(3 * i + 0,
-			buf_start,
-			canvas_width, canvas_height,
-			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
-		canvas_config(3 * i + 1,
-			buf_start +
-			decbuf_y_size, canvas_width / 2,
-			canvas_height / 2, CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_32X32);
-		canvas_config(3 * i + 2,
-			buf_start +
-			decbuf_y_size + decbuf_uv_size,
-			canvas_width / 2, canvas_height / 2,
-			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
-#endif
-	}
-
-	return 0;
-}
-
-static int vreal_prot_init(void)
-{
-	int r;
-#if 1	/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
-	WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6));
-	WRITE_VREG(DOS_SW_RESET0, 0);
-#else
-	WRITE_RESET_REG(RESET0_REGISTER, RESET_IQIDCT | RESET_MC);
-#endif
-
-
-
-	r = vreal_canvas_init();
-
-	/* index v << 16 | u << 8 | y */
-#ifdef NV21
-	WRITE_VREG(AV_SCRATCH_0, 0x010100);
-	WRITE_VREG(AV_SCRATCH_1, 0x030302);
-	WRITE_VREG(AV_SCRATCH_2, 0x050504);
-	WRITE_VREG(AV_SCRATCH_3, 0x070706);
-#else
-	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);
-
-#if 1	/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
-	WRITE_VREG(DOS_SW_RESET0, (1 << 9) | (1 << 8));
-	WRITE_VREG(DOS_SW_RESET0, 0);
-#else
-	WRITE_RESET_REG(RESET2_REGISTER, RESET_PIC_DC | RESET_DBLK);
-#endif
-
-	/* disable PSCALE for hardware sharing */
-	WRITE_VREG(PSCALE_CTRL, 0);
-
-	WRITE_VREG(FROM_AMRISC, 0);
-	WRITE_VREG(TO_AMRISC, 0);
-	WRITE_VREG(STATUS_AMRISC, 0);
-
-	WRITE_VREG(RV_PIC_INFO, 0);
-	WRITE_VREG(VPTS_TR, 0);
-	WRITE_VREG(VDTS, 0);
-	WRITE_VREG(SKIP_B_AMRISC, 0);
-
-	WRITE_VREG(MDEC_WIDTH, (frame_width + 15) & 0xfff0);
-	WRITE_VREG(MDEC_HEIGHT, (frame_height + 15) & 0xfff0);
-
-	/* clear mailbox interrupt */
-	WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1);
-
-	/* enable mailbox interrupt */
-	WRITE_VREG(ASSIST_MBOX1_MASK, 1);
-
-	/* clear wait buffer status */
-	WRITE_VREG(WAIT_BUFFER, 0);
-
-#ifdef NV21
-	SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17);
-#endif
-	return r;
-}
-
-static void vreal_local_init(void)
-{
-	int i;
-
-	/* vreal_ratio = vreal_amstream_dec_info.ratio; */
-	vreal_ratio = 0x100;
-
-	frame_prog = 0;
-
-	frame_width = vreal_amstream_dec_info.width;
-	frame_height = vreal_amstream_dec_info.height;
-	frame_dur = vreal_amstream_dec_info.rate;
-
-	for (i = 0; i < VF_BUF_NUM; i++)
-		vfbuf_use[i] = 0;
-
-	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;
-		kfifo_put(&newframe_q, vf);
-	}
-
-	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);
-
-	decoder_state = 1;
-	hold = 0;
-	last_tr = -1;
-	wait_key_frame = 1;
-	frame_count = 0;
-	current_vdts = 0;
-	real_err_count = 0;
-
-	pic_sz_tbl_map = 0;
-	saved_resolution = 0;
-	fatal_flag = 0;
-	wait_buffer_counter = 0;
-}
-
-static void load_block_data(void *dest, unsigned int count)
-{
-	unsigned short *pdest = (unsigned short *)dest;
-	unsigned short src_tbl[12];
-	unsigned int i;
-
-	src_tbl[0] = RPR_size[vreal_amstream_dec_info.extra + 1];
-	memcpy((void *)&src_tbl[1], vreal_amstream_dec_info.param,
-		   2 << src_tbl[0]);
-
-#if 0
-	for (i = 0; i < 12; i++)
-		pr_info("src_tbl[%d]: 0x%x\n", i, src_tbl[i]);
-#endif
-
-	for (i = 0; i < count / 4; i++) {
-		pdest[i * 4] = src_tbl[i * 4 + 3];
-		pdest[i * 4 + 1] = src_tbl[i * 4 + 2];
-		pdest[i * 4 + 2] = src_tbl[i * 4 + 1];
-		pdest[i * 4 + 3] = src_tbl[i * 4];
-	}
-
-	pic_sz_tbl_map = dma_map_single(amports_get_dma_device(), &pic_sz_tbl,
-				sizeof(pic_sz_tbl), DMA_TO_DEVICE);
-
-}
-
-s32 vreal_init(struct vdec_s *vdec)
-{
-	int ret = -1, size = -1;
-	char fw_name[32] = {0};
-	char *buf = vmalloc(0x1000 * 16);
-
-	if (IS_ERR_OR_NULL(buf))
-		return -ENOMEM;
-
-	pr_info("vreal_init\n");
-
-	init_timer(&recycle_timer);
-
-	stat |= STAT_TIMER_INIT;
-
-	amvdec_enable();
-
-	vreal_local_init();
-
-	ret = rmparser_init(vdec);
-	if (ret) {
-		amvdec_disable();
-		vfree(buf);
-		pr_info("rm parser init failed\n");
-		return ret;
-	}
-
-	if (vreal_amstream_dec_info.format == VIDEO_DEC_FORMAT_REAL_8) {
-		if (vreal_amstream_dec_info.param == NULL) {
-			rmparser_release();
-			amvdec_disable();
-			vfree(buf);
-			return -1;
-		}
-		load_block_data((void *)pic_sz_tbl, 12);
-
-		/* TODO: need to load the table into lmem */
-		WRITE_VREG(LMEM_DMA_ADR, (unsigned int)pic_sz_tbl_map);
-		WRITE_VREG(LMEM_DMA_COUNT, 10);
-		WRITE_VREG(LMEM_DMA_CTRL, 0xc178 | (3 << 11));
-		while (READ_VREG(LMEM_DMA_CTRL) & 0x8000)
-			;
-		size = get_firmware_data(VIDEO_DEC_REAL_V8, buf);
-		strncpy(fw_name, "vreal_mc_8", sizeof(fw_name));
-
-		pr_info("load VIDEO_DEC_FORMAT_REAL_8\n");
-	} else if (vreal_amstream_dec_info.format == VIDEO_DEC_FORMAT_REAL_9) {
-		size = get_firmware_data(VIDEO_DEC_REAL_V9, buf);
-		strncpy(fw_name, "vreal_mc_9", sizeof(fw_name));
-
-		pr_info("load VIDEO_DEC_FORMAT_REAL_9\n");
-	} else
-		pr_info("unsurpported real format\n");
-
-	if (size < 0) {
-		rmparser_release();
-		amvdec_disable();
-		pr_err("get firmware fail.");
-		vfree(buf);
-		return -1;
-	}
-
-	ret = amvdec_loadmc_ex(VFORMAT_REAL, fw_name, buf);
-	if (ret < 0) {
-		rmparser_release();
-		amvdec_disable();
-		vfree(buf);
-		pr_err("%s: the %s fw loading failed, err: %x\n",
-			fw_name, tee_enabled() ? "TEE" : "local", ret);
-		return -EBUSY;
-	}
-
-	vfree(buf);
-
-	stat |= STAT_MC_LOAD;
-
-	/* enable AMRISC side protocol */
-	ret = vreal_prot_init();
-	if (ret < 0) {
-		rmparser_release();
-		amvdec_disable();
-		return ret;
-	}
-	if (vdec_request_irq(VDEC_IRQ_1,  vreal_isr,
-		    "vreal-irq", (void *)vreal_dec_id)) {
-		rmparser_release();
-		amvdec_disable();
-
-		pr_info("vreal irq register error.\n");
-		return -ENOENT;
-	}
-
-	stat |= STAT_ISR_REG;
-#ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER
-	vf_provider_init(&vreal_vf_prov, PROVIDER_NAME, &vreal_vf_provider,
-					 NULL);
-	vf_reg_provider(&vreal_vf_prov);
-	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL);
-#else
-	vf_provider_init(&vreal_vf_prov, PROVIDER_NAME, &vreal_vf_provider,
-					 NULL);
-	vf_reg_provider(&vreal_vf_prov);
-#endif
-
-	if (!is_reset)
-		vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_FR_HINT,
-			(void *)((unsigned long)vreal_amstream_dec_info.rate));
-
-	stat |= STAT_VF_HOOK;
-
-	recycle_timer.data = (ulong)&recycle_timer;
-	recycle_timer.function = vreal_put_timer_func;
-	recycle_timer.expires = jiffies + PUT_INTERVAL;
-
-	add_timer(&recycle_timer);
-
-	stat |= STAT_TIMER_ARM;
-
-	amvdec_start();
-
-	stat |= STAT_VDEC_RUN;
-
-	pr_info("vreal init finished\n");
-
-	return 0;
-}
-
-void vreal_set_fatal_flag(int flag)
-{
-	if (flag)
-		fatal_flag = PARSER_FATAL_ERROR;
-}
-
-static int amvdec_real_probe(struct platform_device *pdev)
-{
-	struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
-
-	if (pdata == NULL) {
-		pr_info("amvdec_real memory resource undefined.\n");
-		return -EFAULT;
-	}
-	if (pdata->sys_info)
-		vreal_amstream_dec_info = *pdata->sys_info;
-
-	pdata->dec_status = vreal_dec_status;
-	pdata->set_isreset = vreal_set_isreset;
-	is_reset = 0;
-
-	INIT_WORK(&set_clk_work, vreal_set_clk);
-	if (vreal_init(pdata) < 0) {
-		pr_info("amvdec_real init failed.\n");
-		pdata->dec_status = NULL;
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static int amvdec_real_remove(struct platform_device *pdev)
-{
-	cancel_work_sync(&set_clk_work);
-	if (stat & STAT_VDEC_RUN) {
-		amvdec_stop();
-		stat &= ~STAT_VDEC_RUN;
-	}
-
-	if (stat & STAT_ISR_REG) {
-		vdec_free_irq(VDEC_IRQ_1, (void *)vreal_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 (!is_reset)
-			vf_notify_receiver(PROVIDER_NAME,
-				VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL);
-
-		vf_unreg_provider(&vreal_vf_prov);
-		stat &= ~STAT_VF_HOOK;
-	}
-
-	if (pic_sz_tbl_map != 0) {
-		dma_unmap_single(NULL, pic_sz_tbl_map, sizeof(pic_sz_tbl),
-						 DMA_TO_DEVICE);
-	}
-
-	rmparser_release();
-
-	vdec_source_changed(VFORMAT_REAL, 0, 0, 0);
-
-	amvdec_disable();
-
-	if (mm_blk_handle) {
-		decoder_bmmu_box_free(mm_blk_handle);
-		mm_blk_handle = NULL;
-	}
-	pr_info("frame duration %d, frames %d\n", frame_dur, frame_count);
-	return 0;
-}
-
-/****************************************/
-#ifdef CONFIG_PM
-static int real_suspend(struct device *dev)
-{
-	amvdec_suspend(to_platform_device(dev), dev->power.power_state);
-	return 0;
-}
-
-static int real_resume(struct device *dev)
-{
-	amvdec_resume(to_platform_device(dev));
-	return 0;
-}
-
-static const struct dev_pm_ops real_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(real_suspend, real_resume)
-};
-#endif
-
-static struct platform_driver amvdec_real_driver = {
-	.probe = amvdec_real_probe,
-	.remove = amvdec_real_remove,
-	.driver = {
-		.name = DRIVER_NAME,
-#ifdef CONFIG_PM
-		.pm = &real_pm_ops,
-#endif
-	}
-};
-
-static struct codec_profile_t amvdec_real_profile = {
-	.name = "real",
-	.profile = "rmvb,1080p+"
-};
-static struct mconfig real_configs[] = {
-	MC_PU32("stat", &stat),
-};
-static struct mconfig_node real_node;
-
-static int __init amvdec_real_driver_init_module(void)
-{
-	pr_debug("amvdec_real module init\n");
-
-	if (platform_driver_register(&amvdec_real_driver)) {
-		pr_err("failed to register amvdec_real driver\n");
-		return -ENODEV;
-	}
-	vcodec_profile_register(&amvdec_real_profile);
-	INIT_REG_NODE_CONFIGS("media.decoder", &real_node,
-		"real", real_configs, CONFIG_FOR_R);
-	return 0;
-}
-
-static void __exit amvdec_real_driver_remove_module(void)
-{
-	pr_debug("amvdec_real module remove.\n");
-
-	platform_driver_unregister(&amvdec_real_driver);
-}
-
-/****************************************/
-
-module_init(amvdec_real_driver_init_module);
-module_exit(amvdec_real_driver_remove_module);
-
-MODULE_DESCRIPTION("AMLOGIC REAL Video Decoder Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/frame_provider/decoder/utils/Makefile b/drivers/frame_provider/decoder/utils/Makefile
index 1e7552b..6f8540b 100644
--- a/drivers/frame_provider/decoder/utils/Makefile
+++ b/drivers/frame_provider/decoder/utils/Makefile
@@ -1,10 +1,13 @@
 obj-m	+=	decoder_common.o
 decoder_common-objs	+=	utils.o vdec.o vdec_input.o amvdec.o
 decoder_common-objs	+=	decoder_mmu_box.o decoder_bmmu_box.o
-decoder_common-objs	+=	config_parser.o secprot.o vdec_profile.o
+decoder_common-objs	+=	config_parser.o vdec_profile.o
 decoder_common-objs	+=	amstream_profile.o 
 decoder_common-objs	+=	frame_check.o amlogic_fbc_hook.o
 decoder_common-objs	+=	vdec_v4l2_buffer_ops.o
 decoder_common-objs	+=	vdec_sync.o
 decoder_common-objs	+=	vdec_power_ctrl.o
+decoder_common-objs	+=	vdec_canvas_utils.o
+decoder_common-objs	+=	vdec_feature.o
+decoder_common-objs	+=	vdec_ge2d_utils.o
 
diff --git a/drivers/frame_provider/decoder/utils/amstream_profile.c b/drivers/frame_provider/decoder/utils/amstream_profile.c
index c8033ce..0e2b9c8 100644
--- a/drivers/frame_provider/decoder/utils/amstream_profile.c
+++ b/drivers/frame_provider/decoder/utils/amstream_profile.c
@@ -66,5 +66,3 @@
 	return ret;
 }
 EXPORT_SYMBOL(is_support_profile);
-
-
diff --git a/drivers/frame_provider/decoder/utils/amvdec.c b/drivers/frame_provider/decoder/utils/amvdec.c
index af36ef1..d525fe8 100644
--- a/drivers/frame_provider/decoder/utils/amvdec.c
+++ b/drivers/frame_provider/decoder/utils/amvdec.c
@@ -43,7 +43,8 @@
 #include "amvdec.h"
 #include <linux/amlogic/media/utils/amports_config.h>
 #include "firmware.h"
-#include <linux/amlogic/tee.h>
+//#include <linux/amlogic/tee.h>
+#include <uapi/linux/tee.h>
 #include "../../../common/chips/decoder_cpu_ver_info.h"
 
 #define MC_SIZE (4096 * 16)
@@ -484,9 +485,16 @@
 		} else
 			format = VIDEO_DEC_H264;
 		break;
-
+	case VFORMAT_JPEG_ENC:
+		format = VIDEO_ENC_JPEG;
+		vdec = OPTEE_VDEC_HCDEC;
+		break;
+	case VFORMAT_H264_ENC:
+		format = VIDEO_ENC_H264;
+		vdec = OPTEE_VDEC_HCDEC;
+		break;
 	default:
-		pr_info("Unknow vdec format!\n");
+		pr_info("Unknow vdec format: %u\n", (u32)type);
 		break;
 	}
 
@@ -675,13 +683,17 @@
 
 		WRITE_VREG(HEVC_IMEM_DMA_ADR, mc_addr_map);
 		WRITE_VREG(HEVC_IMEM_DMA_COUNT, 0x1000);
-		WRITE_VREG(HEVC_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));
+		if ((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) ||
+			(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T3))
+			WRITE_VREG(HEVC_IMEM_DMA_CTRL, (0x8000 | (0xf << 16)));
+		else
+			WRITE_VREG(HEVC_IMEM_DMA_CTRL, (0x8000 | (0x7 << 16)));
 
 		while (READ_VREG(HEVC_IMEM_DMA_CTRL) & 0x8000) {
 			if (time_before(jiffies, timeout))
 				schedule();
 			else {
-				pr_err("vdec2 load mc error\n");
+				pr_err("hevc load mc error\n");
 				ret = -EBUSY;
 				break;
 			}
@@ -966,6 +978,14 @@
 #ifdef CONFIG_PM
 int amvdec_suspend(struct platform_device *dev, pm_message_t event)
 {
+	struct vdec_s *vdec = *(struct vdec_s **)dev->dev.platform_data;;
+
+	if (vdec) {
+		wait_event_interruptible_timeout(vdec->idle_wait,
+			(vdec->status != VDEC_STATUS_ACTIVE),
+			msecs_to_jiffies(100));
+	}
+
 	amvdec_pg_enable(false);
 
 	/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */
@@ -1000,6 +1020,14 @@
 
 int amhevc_suspend(struct platform_device *dev, pm_message_t event)
 {
+	struct vdec_s *vdec = *(struct vdec_s **)dev->dev.platform_data;;
+
+	if (vdec) {
+		wait_event_interruptible_timeout(vdec->idle_wait,
+			(vdec->status != VDEC_STATUS_ACTIVE),
+			msecs_to_jiffies(100));
+	}
+
 	if (has_hevc_vdec()) {
 		amhevc_pg_enable(false);
 		/*vdec_set_suspend_clk(1, 1);*//*DEBUG_TMP*/
@@ -1161,9 +1189,8 @@
 
 module_init(amvdec_init);
 module_exit(amvdec_exit);
-
+#endif
 
 MODULE_DESCRIPTION("Amlogic Video Decoder Utility Driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>");
-#endif
diff --git a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c
index 461621b..33a9e4b 100644
--- a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c
+++ b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c
@@ -141,7 +141,7 @@
 	int memflags = mem_flags;
 
 	if (!box || idx < 0 || idx >= box->max_mm_num) {
-		pr_err("can't alloc mmu box(%p),idx:%d\n",
+		pr_err("can't alloc bmmu box(%p),idx:%d\n",
 				box, idx);
 		return -1;
 	}
@@ -324,7 +324,7 @@
 }
 
 /*flags: &0x1 for wait,*/
-int decoder_bmmu_box_check_and_wait_size(int size, int flags)
+int decoder_bmmu_box_check_and_wait_size(int size, int flags, int mem_flags)
 {
 	if ((flags & BMMU_ALLOC_FLAGS_CAN_CLEAR_KEEPER) &&
 		codec_mm_get_free_size() < size) {
@@ -335,7 +335,7 @@
 	}
 
 	return codec_mm_enough_for_size(size,
-			flags & BMMU_ALLOC_FLAGS_WAIT);
+			flags & BMMU_ALLOC_FLAGS_WAIT, mem_flags);
 }
 
 int decoder_bmmu_box_alloc_idx_wait(
@@ -361,7 +361,8 @@
 	}
 	have_space = decoder_bmmu_box_check_and_wait_size(
 					size,
-					wait_flags);
+					wait_flags,
+					mem_flags);
 	if (have_space) {
 		ret = decoder_bmmu_box_alloc_idx(handle,
 				idx, size, aligned_2n, mem_flags);
@@ -382,9 +383,14 @@
 	int size, unsigned char *driver_name,
 	unsigned long *buf_phy_addr)
 {
+	struct decoder_bmmu_box *bmmu_box = (struct decoder_bmmu_box *)handle;
+
+	if (bmmu_box == NULL)
+		return -EINVAL;
+
 	if (!decoder_bmmu_box_check_and_wait_size(
 			size,
-			1)) {
+			1, bmmu_box->mem_flags)) {
 		pr_info("%s not enough buf for buf_idx = %d\n",
 					driver_name, idx);
 		return	-ENOMEM;
@@ -394,9 +400,8 @@
 			idx,
 			size,
 			-1,
-			-1,
-			BMMU_ALLOC_FLAGS_WAITCLEAR
-			)) {
+			bmmu_box->mem_flags,
+			BMMU_ALLOC_FLAGS_WAITCLEAR)) {
 		*buf_phy_addr =
 			decoder_bmmu_box_get_phy_addr(
 			handle,
@@ -414,6 +419,25 @@
 }
 EXPORT_SYMBOL(decoder_bmmu_box_alloc_buf_phy);
 
+int decoder_bmmu_box_add_callback_func(
+	void *handle, int idx,
+	void *cb)
+{
+	struct decoder_bmmu_box *box = handle;
+	struct codec_mm_s *mm;
+
+	if (!box || idx < 0 || idx >= box->max_mm_num)
+		return 0;
+
+	mutex_lock(&box->mutex);
+	mm = box->mm_list[idx];
+	codec_mm_add_release_callback(mm, (struct codec_mm_cb_s *)cb);
+	mutex_unlock(&box->mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(decoder_bmmu_box_add_callback_func);
+
 static int decoder_bmmu_box_dump(struct decoder_bmmu_box *box, void *buf,
 								 int size)
 {
@@ -422,6 +446,7 @@
 	int tsize = 0;
 	int s;
 	int i;
+
 	if (!buf) {
 		pbuf = sbuf;
 		size = 512;
@@ -466,6 +491,7 @@
 	int s;
 	int i;
 	struct list_head *head, *list;
+
 	if (!buf) {
 		pbuf = sbuf;
 		size = 512;
@@ -523,7 +549,7 @@
 	return ret;
 }
 
-static ssize_t box_debug_show(struct class *class,
+static ssize_t debug_show(struct class *class,
 		struct class_attribute *attr,
 		char *buf)
 {
@@ -537,8 +563,7 @@
 	return size;
 }
 
-
-static ssize_t box_debug_store(struct class *class,
+static ssize_t debug_store(struct class *class,
 		struct class_attribute *attr,
 		const char *buf, size_t size)
 {
@@ -559,19 +584,21 @@
 
 }
 
+static CLASS_ATTR_RO(box_dump);
+static CLASS_ATTR_RW(debug);
 
-
-static struct class_attribute decoder_bmmu_box_class_attrs[] = {
-	__ATTR_RO(box_dump),
-	__ATTR(debug, S_IRUGO | S_IWUSR | S_IWGRP,
-		box_debug_show, box_debug_store),
-	__ATTR_NULL
+static struct attribute *decoder_bmmu_box_class_attrs[] = {
+	&class_attr_box_dump.attr,
+	&class_attr_debug.attr,
+	NULL
 };
 
+ATTRIBUTE_GROUPS(decoder_bmmu_box_class);
+
 static struct class decoder_bmmu_box_class = {
-		.name = "decoder_bmmu_box",
-		.class_attrs = decoder_bmmu_box_class_attrs,
-	};
+	.name = "decoder_bmmu_box",
+	.class_groups = decoder_bmmu_box_class_groups,
+};
 
 int decoder_bmmu_box_init(void)
 {
diff --git a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h
index 778cb8e..93974ec 100644
--- a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h
+++ b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h
@@ -41,13 +41,17 @@
 
 /*flags: &0x1 for wait,*/
 int decoder_bmmu_box_check_and_wait_size(
-	int size, int flags);
+	int size, int flags, int mem_flags);
 
 int decoder_bmmu_box_alloc_buf_phy(
 	void *handle, int idx,
 	int size, unsigned char *driver_name,
 	unsigned long *buf_phy_addr);
 
+int decoder_bmmu_box_add_callback_func(
+	void *handle, int idx,
+	void *cb);
+
 #define BMMU_ALLOC_FLAGS_WAIT (1 << 0)
 #define BMMU_ALLOC_FLAGS_CAN_CLEAR_KEEPER (1 << 1)
 #define BMMU_ALLOC_FLAGS_WAITCLEAR \
diff --git a/drivers/frame_provider/decoder/utils/decoder_mmu_box.c b/drivers/frame_provider/decoder/utils/decoder_mmu_box.c
index 75862ec..57180dd 100644
--- a/drivers/frame_provider/decoder/utils/decoder_mmu_box.c
+++ b/drivers/frame_provider/decoder/utils/decoder_mmu_box.c
@@ -28,13 +28,11 @@
 #include <linux/slab.h>
 #include <linux/amlogic/media/codec_mm/codec_mm_scatter.h>
 #include <linux/platform_device.h>
-
 struct decoder_mmu_box {
 	int max_sc_num;
 	const char *name;
 	int channel_id;
 	int tvp_mode;
-	int box_ref_cnt;
 	struct mutex mutex;
 	struct list_head list;
 	struct codec_mm_scatter *sc_list[1];
@@ -76,51 +74,6 @@
 	return 0;
 }
 
-bool decoder_mmu_box_valide_check(void *box)
-{
-	struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr();
-	struct decoder_mmu_box *mmu_box = NULL;
-	bool is_valide = false;
-
-	mutex_lock(&mgr->mutex);
-	list_for_each_entry(mmu_box, &mgr->box_list, list) {
-		if (mmu_box && mmu_box == box) {
-			is_valide = true;
-			break;
-		}
-	}
-	mutex_unlock(&mgr->mutex);
-
-	return is_valide;
-}
-EXPORT_SYMBOL(decoder_mmu_box_valide_check);
-
-void decoder_mmu_try_to_release_box(void *handle)
-{
-	struct decoder_mmu_box *box = handle;
-	bool is_keep = false;
-	int i;
-
-	if (!box || box->box_ref_cnt)
-		return;
-
-	mutex_lock(&box->mutex);
-	for (i = 0; i < box->max_sc_num; i++) {
-		if (box->sc_list[i]) {
-			is_keep = true;
-			break;
-		}
-	}
-	mutex_unlock(&box->mutex);
-
-	if (!is_keep) {
-		decoder_mmu_box_mgr_del_box(box);
-		codec_mm_scatter_mgt_delay_free_swith(0, 0, 0, box->tvp_mode);
-		kfree(box);
-	}
-}
-EXPORT_SYMBOL(decoder_mmu_try_to_release_box);
-
 int decoder_mmu_box_sc_check(void *handle, int is_tvp)
 {
 	struct decoder_mmu_box *box = handle;
@@ -162,7 +115,7 @@
 	mutex_init(&box->mutex);
 	INIT_LIST_HEAD(&box->list);
 	decoder_mmu_box_mgr_add_box(box);
-	codec_mm_scatter_mgt_delay_free_swith(1, 2000,
+	codec_mm_scatter_mgt_delay_free_switch(1, 2000,
 		min_size_M, box->tvp_mode);
 	return (void *)box;
 }
@@ -189,7 +142,6 @@
 			ret = codec_mm_scatter_alloc_want_pages(sc,
 				num_pages);
 		else {
-			box->box_ref_cnt--;
 			codec_mm_scatter_dec_owner_user(sc, 0);
 			box->sc_list[idx] = NULL;
 			sc = NULL;
@@ -206,7 +158,6 @@
 			return -1;
 		}
 		box->sc_list[idx] = sc;
-		box->box_ref_cnt++;
 	}
 
 	for (i = 0; i < num_pages; i++)
@@ -252,17 +203,15 @@
 			box ? (box->max_sc_num - 1) : 0);
 		return -1;
 	}
+
 	mutex_lock(&box->mutex);
 	sc = box->sc_list[idx];
 	if (sc && sc->page_cnt > 0) {
 		codec_mm_scatter_dec_owner_user(sc, 0);
 		box->sc_list[idx] = NULL;
-		box->box_ref_cnt--;
 	}
-	mutex_unlock(&box->mutex);
 
-	if (sc && box->box_ref_cnt == 0)
-		codec_mm_scatter_mgt_delay_free_swith(0, 0, 0, box->tvp_mode);
+	mutex_unlock(&box->mutex);
 
 	return 0;
 }
@@ -278,18 +227,24 @@
 		pr_err("can't free box of NULL box!\n");
 		return -1;
 	}
+
 	mutex_lock(&box->mutex);
 	for (i = 0; i < box->max_sc_num; i++) {
 		sc = box->sc_list[i];
 		if (sc) {
 			codec_mm_scatter_dec_owner_user(sc, 0);
 			box->sc_list[i] = NULL;
+
 		}
 	}
+
+	codec_mm_scatter_mgt_delay_free_switch(0, 0, 0, box->tvp_mode);
+
 	mutex_unlock(&box->mutex);
+
 	decoder_mmu_box_mgr_del_box(box);
-	codec_mm_scatter_mgt_delay_free_swith(0, 0, 0, box->tvp_mode);
 	kfree(box);
+
 	return 0;
 }
 EXPORT_SYMBOL(decoder_mmu_box_free);
@@ -411,16 +366,18 @@
 	return ret;
 }
 
+static CLASS_ATTR_RO(box_dump);
 
-
-static struct class_attribute decoder_mmu_box_class_attrs[] = {
-	__ATTR_RO(box_dump),
-	__ATTR_NULL
+static struct attribute *decoder_mmu_box_class_attrs[] = {
+	&class_attr_box_dump.attr,
+	NULL
 };
 
+ATTRIBUTE_GROUPS(decoder_mmu_box_class);
+
 static struct class decoder_mmu_box_class = {
 	.name = "decoder_mmu_box",
-	.class_attrs = decoder_mmu_box_class_attrs,
+	.class_groups = decoder_mmu_box_class_groups,
 };
 
 int decoder_mmu_box_init(void)
diff --git a/drivers/frame_provider/decoder/utils/decoder_mmu_box.h b/drivers/frame_provider/decoder/utils/decoder_mmu_box.h
index 029f91a..13b3dd9 100644
--- a/drivers/frame_provider/decoder/utils/decoder_mmu_box.h
+++ b/drivers/frame_provider/decoder/utils/decoder_mmu_box.h
@@ -40,11 +40,13 @@
 int decoder_mmu_box_move_keep_idx(void *box_handle,
 	int keep_idx);
 int decoder_mmu_box_free_keep(int keep_id);
+
 int decoder_mmu_box_free_all_keep(void);
+
 void *decoder_mmu_box_get_mem_handle(void *box_handle, int idx);
-bool decoder_mmu_box_valide_check(void *box);
-void decoder_mmu_try_to_release_box(void *handle);
+
 int decoder_mmu_box_init(void);
+
 void decoder_mmu_box_exit(void);
 
 #endif
diff --git a/drivers/frame_provider/decoder/utils/firmware.h b/drivers/frame_provider/decoder/utils/firmware.h
index c799fd0..cd48036 100644
--- a/drivers/frame_provider/decoder/utils/firmware.h
+++ b/drivers/frame_provider/decoder/utils/firmware.h
@@ -22,6 +22,9 @@
 
 #include "../../../common/firmware/firmware_type.h"
 #include <linux/amlogic/media/utils/vformat.h>
+#if defined(CONFIG_AMLOGIC_TEE) || defined(CONFIG_AMLOGIC_TEE_MODULE)
+#include <linux/amlogic/tee.h>
+#endif
 
 #define FW_LOAD_FORCE	(0x1)
 #define FW_LOAD_TRY	(0X2)
@@ -38,4 +41,16 @@
 extern int get_firmware_data(unsigned int foramt, char *buf);
 extern int video_fw_reload(int mode);
 
+#if !defined(CONFIG_AMLOGIC_TEE) && !defined(CONFIG_AMLOGIC_TEE_MODULE)
+static inline bool tee_enabled(void) { return false; }
+static inline int tee_load_video_fw_swap(u32 index, u32 vdec, bool is_swap)
+{
+	return -1;
+}
+static inline int tee_load_video_fw(u32 index, u32 vdec)
+{
+	return -1;
+}
+#endif
+
 #endif
diff --git a/drivers/frame_provider/decoder/utils/frame_check.c b/drivers/frame_provider/decoder/utils/frame_check.c
index 4cd80c0..0600f8e 100644
--- a/drivers/frame_provider/decoder/utils/frame_check.c
+++ b/drivers/frame_provider/decoder/utils/frame_check.c
@@ -25,9 +25,8 @@
 #include <linux/timer.h>
 #include <linux/kfifo.h>
 #include <linux/kthread.h>
+#include <linux/vmalloc.h>
 #include <linux/platform_device.h>
-#include <linux/amlogic/media/canvas/canvas.h>
-#include <linux/amlogic/media/canvas/canvas_mgr.h>
 #include <linux/amlogic/media/vfm/vframe.h>
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
 #include <linux/dma-mapping.h>
@@ -72,7 +71,7 @@
 #define dbg_print(mask, ...) do {					\
 			if ((fc_debug & mask) ||				\
 				(mask == FC_ERROR))					\
-				printk("[FRMAE_CHECK] "__VA_ARGS__);\
+				printk("[FRAME_CHECK] "__VA_ARGS__);\
 		} while(0)
 
 
@@ -167,6 +166,18 @@
 	return false;
 }
 
+unsigned long vdec_cav_get_addr(int index);
+unsigned int vdec_cav_get_width(int index);
+unsigned int vdec_cav_get_height(int index);
+#define canvas_0(v) ((v) & 0xff)
+#define canvas_1(v) (((v) >> 8) & 0xff)
+#define canvas_2(v) (((v) >> 16) & 0xff)
+#define canvas_3(v) (((v) >> 24) & 0xff)
+
+#define canvasY(v) canvas_0(v)
+#define canvasU(v) canvas_1(v)
+#define canvasV(v) canvas_2(v)
+#define canvasUV(v) canvas_1(v)
 
 static int get_frame_size(struct pic_check_mgr_t *pic,
 	struct vframe_s *vf)
@@ -188,10 +199,10 @@
 	if ((vf->canvas0Addr == vf->canvas1Addr) &&
 		(vf->canvas0Addr != 0) &&
 		(vf->canvas0Addr != -1)) {
-		pic->canvas_w =
-			canvas_get_width(canvasY(vf->canvas0Addr));
-		pic->canvas_h =
-			canvas_get_height(canvasY(vf->canvas0Addr));
+		pic->canvas_w = vdec_cav_get_width(canvasY(vf->canvas0Addr));
+			//canvas_get_width(canvasY(vf->canvas0Addr));
+		pic->canvas_h = vdec_cav_get_height(canvasY(vf->canvas0Addr));
+			//canvas_get_height(canvasY(vf->canvas0Addr));
 	} else {
 		pic->canvas_w = vf->canvas0_config[0].width;
 		pic->canvas_h = vf->canvas0_config[0].height;
@@ -221,8 +232,8 @@
 	if ((vf->canvas0Addr == vf->canvas1Addr) &&
 		(vf->canvas0Addr != 0) &&
 		(vf->canvas0Addr != -1)) {
-		phy_y_addr = canvas_get_addr(canvasY(vf->canvas0Addr));
-		phy_uv_addr = canvas_get_addr(canvasU(vf->canvas0Addr));
+		phy_y_addr = vdec_cav_get_addr(canvasY(vf->canvas0Addr)); //canvas_get_addr(canvasY(vf->canvas0Addr));
+		phy_uv_addr = vdec_cav_get_addr(canvasUV(vf->canvas0Addr)); //canvas_get_addr(canvasUV(vf->canvas0Addr));
 	} else {
 		phy_y_addr = vf->canvas0_config[0].phy_addr;
 		phy_uv_addr = vf->canvas0_config[1].phy_addr;
@@ -426,10 +437,14 @@
 static int write_crc_work(struct pic_check_mgr_t *mgr)
 {
 	unsigned int wr_size;
-	char *crc_buf, crc_tmp[64*30];
+	char *crc_buf, *crc_tmp = NULL;
 	mm_segment_t old_fs;
 	struct pic_check_t *check = &mgr->pic_check;
 
+	crc_tmp = (char *)vzalloc(64 * 30);
+	if (!crc_tmp)
+		return -1;
+
 	if (mgr->enable & CRC_MASK) {
 		wr_size = 0;
 		while (kfifo_get(&check->wr_chk_q, &crc_buf) != 0) {
@@ -453,10 +468,11 @@
 			set_fs(old_fs);
 		}
 	}
+
+	vfree(crc_tmp);
 	return 0;
 }
 
-
 static int write_aux_data_crc_work(struct aux_data_check_mgr_t *mgr)
 {
 	unsigned int wr_size;
@@ -490,8 +506,6 @@
 	return 0;
 }
 
-
-
 static void do_check_work(struct work_struct *work)
 {
 	struct pic_check_mgr_t *mgr = container_of(work,
@@ -1109,6 +1123,10 @@
 		single_mode_vdec = NULL;
 	}
 
+	if (!single_mode_vdec &&
+		unlikely(in_interrupt()))
+		return 0;
+
 	if ((mgr == NULL) || (vf == NULL) ||
 		(mgr->enable == 0))
 		return 0;
@@ -1131,7 +1149,8 @@
 		resize = 0;
 	mgr->last_size_pic = mgr->size_pic;
 
-	if ((vf->type & VIDTYPE_VIU_NV21) || (mgr->mjpeg_flag)) {
+	if ((vf->type & VIDTYPE_VIU_NV21) || (mgr->mjpeg_flag) ||
+		(vf->type & VIDTYPE_VIU_NV12)) {
 		int flush_size;
 
 		if (canvas_get_virt_addr(mgr, vf) < 0)
diff --git a/drivers/frame_provider/decoder/utils/secprot.c b/drivers/frame_provider/decoder/utils/secprot.c
deleted file mode 100644
index a1e7fa7..0000000
--- a/drivers/frame_provider/decoder/utils/secprot.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * drivers/amlogic/amports/arch/secprot.c
- *
- * 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.
- *
-*/
-
-#include <linux/kernel.h>
-#include <asm/compiler.h>
-#include "secprot.h"
-#ifndef CONFIG_ARM64
-#include <asm/opcodes-sec.h>
-#endif
-
-#ifdef CONFIG_ARM64
-
-int tee_config_device_secure(int dev_id, int secure)
-{
-	int ret = 0;
-	register unsigned x0 asm("x0");
-	register unsigned x1 asm("x1");
-	register unsigned x2 asm("x2");
-
-	x0 = OPTEE_SMC_CONFIG_DEVICE_SECURE;
-	x1 = dev_id;
-	x2 = secure;
-
-	asm volatile(
-		__asmeq("%0", "x0")
-		__asmeq("%1", "x0")
-		__asmeq("%2", "x1")
-		__asmeq("%3", "x2")
-		"smc    #0\n"
-		: "=r"(x0)
-		: "r"(x0), "r"(x1), "r"(x2));
-	ret = x0;
-
-	return ret;
-}
-#else
-int tee_config_device_secure(int dev_id, int secure)
-{
-	int ret = 0;
-	register unsigned int r0 asm("r0");
-	register unsigned int r1 asm("r1");
-	register unsigned int r2 asm("r2");
-
-	r0 = OPTEE_SMC_CONFIG_DEVICE_SECURE;
-	r1 = dev_id;
-	r2 = secure;
-
-	asm volatile(
-		__asmeq("%0", "r0")
-		__asmeq("%1", "r0")
-		__asmeq("%2", "r1")
-		__asmeq("%3", "r2")
-		__SMC(0)
-		: "=r"(r0)
-		: "r"(r0), "r"(r1), "r"(r2));
-	ret = r0;
-
-	return ret;
-}
-#endif
-
diff --git a/drivers/frame_provider/decoder/utils/secprot.h b/drivers/frame_provider/decoder/utils/secprot.h
deleted file mode 100644
index 28ee477..0000000
--- a/drivers/frame_provider/decoder/utils/secprot.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * drivers/amlogic/amports/arch/secprot.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 __SECPROT_H_
-#define __SECPROT_H_
-
-#define DMC_DEV_TYPE_NON_SECURE        0
-#define DMC_DEV_TYPE_SECURE            1
-
-#define DMC_DEV_ID_GPU                 1
-#define DMC_DEV_ID_HEVC                4
-#define DMC_DEV_ID_PARSER              7
-#define DMC_DEV_ID_VPU                 8
-#define DMC_DEV_ID_VDEC                13
-#define DMC_DEV_ID_HCODEC              14
-#define DMC_DEV_ID_GE2D                15
-
-#define OPTEE_SMC_CONFIG_DEVICE_SECURE 0xb200000e
-
-/*#define __asmeq(x, y)  ".ifnc " x "," y " ; .err ; .endif\n\t"*/
-
-extern int tee_config_device_secure(int dev_id, int secure);
-
-#endif /* __SECPROT_H_ */
-
diff --git a/drivers/frame_provider/decoder/utils/utils.c b/drivers/frame_provider/decoder/utils/utils.c
index 44b1626..0372a18 100644
--- a/drivers/frame_provider/decoder/utils/utils.c
+++ b/drivers/frame_provider/decoder/utils/utils.c
@@ -69,5 +69,6 @@
 
 module_init(decoder_common_init);
 module_exit(decoder_common_exit);
+
 MODULE_DESCRIPTION("AMLOGIC decoder_common driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL");
\ No newline at end of file
diff --git a/drivers/frame_provider/decoder/utils/vdec.c b/drivers/frame_provider/decoder/utils/vdec.c
index 69ec60c..98f0e3c 100644
--- a/drivers/frame_provider/decoder/utils/vdec.c
+++ b/drivers/frame_provider/decoder/utils/vdec.c
@@ -37,9 +37,11 @@
 #include <linux/amlogic/media/video_sink/v4lvideo_ext.h>
 #endif
 #include <linux/amlogic/media/vfm/vfm_ext.h>
+#include <linux/sched/clock.h>
+#include <uapi/linux/sched/types.h>
+#include <linux/signal.h>
 /*for VDEC_DEBUG_SUPPORT*/
 #include <linux/time.h>
-
 #include <linux/amlogic/media/utils/vdec_reg.h>
 #include "../../../stream_input/amports/streambuf.h"
 #include "vdec.h"
@@ -47,6 +49,7 @@
 #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
 #include "vdec_profile.h"
 #endif
+#include <linux/sched/clock.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/libfdt_env.h>
@@ -65,21 +68,27 @@
 
 #include "../../../common/media_clock/clk/clk.h"
 #include <linux/reset.h>
-#include <linux/amlogic/cpu_version.h>
+#include <linux/amlogic/media/registers/cpu_version.h>
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
 #include <linux/amlogic/media/video_sink/video_keeper.h>
 #include <linux/amlogic/media/codec_mm/configs.h>
 #include <linux/amlogic/media/frame_sync/ptsserv.h>
-#include "secprot.h"
 #include "../../../common/chips/decoder_cpu_ver_info.h"
 #include "frame_check.h"
+#include <linux/amlogic/tee.h>
+#include "vdec_canvas_utils.h"
+#include "../../../amvdec_ports/aml_vcodec_drv.h"
+
 
 #ifdef CONFIG_AMLOGIC_POWER
 #include <linux/amlogic/power_ctrl.h>
 #endif
 
-#include <dt-bindings/power/sc2-pd.h>
-#include <linux/amlogic/pwr_ctrl.h>
+#ifdef CONFIG_AMLOGIC_IONVIDEO
+#include <linux/amlogic/media/video_sink/ionvideo_ext.h>
+#endif
+//#include <dt-bindings/power/sc2-pd.h>
+//#include <linux/amlogic/pwr_ctrl.h>
 #include <linux/of_device.h>
 #include "vdec_power_ctrl.h"
 
@@ -96,10 +105,12 @@
 static unsigned int debug_trace_num = 16 * 20;
 static int step_mode;
 static unsigned int clk_config;
-#ifdef VDEC_FCC_SUPPORT
-static int fcc_debug;
-static void vdec_fcc_jump_back(struct vdec_s *vdec);
-#endif
+/*
+0x1 : enable rdma
+0x2 : check rdma result
+*/
+static int rdma_mode = 0x1;
+
 /*
  * 0x1  : sched_priority to MAX_RT_PRIO -1.
  * 0x2  : always reload firmware.
@@ -111,23 +122,36 @@
 #define VDEC_DBG_CANVAS_STATUS	(0x4)
 #define VDEC_DBG_ENABLE_FENCE	(0x100)
 
-#define FRAME_BASE_PATH_DI_V4LVIDEO_0 (29)
-#define FRAME_BASE_PATH_DI_V4LVIDEO_1 (30)
-#define FRAME_BASE_PATH_DI_V4LVIDEO_2 (31)
 
-u32 debug = VDEC_DBG_ALWAYS_LOAD_FW;
-EXPORT_SYMBOL(debug);
+#define HEVC_RDMA_F_CTRL                           0x30f0
+#define HEVC_RDMA_F_START_ADDR                     0x30f1
+#define HEVC_RDMA_F_END_ADDR                       0x30f2
+#define HEVC_RDMA_F_STATUS0                        0x30f3
+
+#define HEVC_RDMA_B_CTRL                           0x30f8
+#define HEVC_RDMA_B_START_ADDR                     0x30f9
+#define HEVC_RDMA_B_END_ADDR                       0x30fa
+#define HEVC_RDMA_B_STATUS0                        0x30fb
+
+
+static u32 debug = VDEC_DBG_ALWAYS_LOAD_FW;
+
+u32 vdec_get_debug(void)
+{
+    return debug;
+}
+EXPORT_SYMBOL(vdec_get_debug);
+
 
 int hevc_max_reset_count;
 EXPORT_SYMBOL(hevc_max_reset_count);
 
 int no_powerdown;
 EXPORT_SYMBOL(no_powerdown);
-
 static int parallel_decode = 1;
 static int fps_detection;
 static int fps_clear;
-
+static bool prog_only;
 
 static int force_nosecure_even_drm;
 static int disable_switch_single_to_mult;
@@ -143,8 +167,12 @@
 #define RESET7_REGISTER_LEVEL 0x1127
 #define P_RESETCTRL_RESET5_LEVEL 0x15
 
+#define str(a) #a
+#define xstr(a) str(a)
+
 static int frameinfo_flag = 0;
 static int v4lvideo_add_di = 1;
+static int v4lvideo_add_ppmgr = 0;
 static int max_di_instance = 2;
 static int max_supported_di_instance = 4;
 
@@ -153,12 +181,39 @@
 static int enable_mvdec_info = 1;
 
 int decode_underflow = 0;
+u32 debug_meta;
 
 static int enable_stream_mode_multi_dec;
 
-#define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1)
+st_userdata userdata;
 
+typedef void (*vdec_frame_rate_event_func)(int);
+
+#if 1
 extern void vframe_rate_uevent(int duration);
+vdec_frame_rate_event_func frame_rate_notify = vframe_rate_uevent;
+#else
+vdec_frame_rate_event_func frame_rate_notify = NULL;
+#endif
+
+void vdec_frame_rate_uevent(int dur)
+{
+	if (frame_rate_notify == NULL)
+		return;
+
+	if (unlikely(in_interrupt()))
+		return;
+	pr_info("vdec_frame_rate_uevent %d\n", dur);
+	frame_rate_notify(dur);
+}
+EXPORT_SYMBOL(vdec_frame_rate_uevent);
+
+
+void register_frame_rate_uevent_func(vdec_frame_rate_event_func func)
+{
+	frame_rate_notify = func;
+}
+EXPORT_SYMBOL(register_frame_rate_uevent_func);
 
 struct am_reg {
 	char *name;
@@ -211,15 +266,9 @@
 	unsigned long stream_buff_flag;
 	struct power_manager_s *pm;
 	u32 vdec_resouce_status;
+	struct post_task_mgr_s post;
 };
 
-struct canvas_status_s {
-	int type;
-	int canvas_used_flag;
-	int id;
-};
-
-
 static struct vdec_core_s *vdec_core;
 
 static const char * const vdec_status_string[] = {
@@ -229,6 +278,7 @@
 	"VDEC_STATUS_ACTIVE"
 };
 /*
+bit [29] enable steam mode dv multi;
 bit [28] enable print
 bit [23:16] etc
 bit [15:12]
@@ -286,9 +336,6 @@
 	"reserved",
 };
 
-static struct canvas_status_s canvas_stat[AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1];
-
-
 int vdec_get_debug_flags(void)
 {
 	return debugflags;
@@ -302,15 +349,6 @@
 }
 EXPORT_SYMBOL(VDEC_PRINT_FUN_LINENO);
 
-bool is_support_no_parser(void)
-{
-	if ((enable_stream_mode_multi_dec) ||
-		(get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2))
-		return true;
-	return false;
-}
-EXPORT_SYMBOL(is_support_no_parser);
-
 unsigned char is_mult_inc(unsigned int type)
 {
 	unsigned char ret = 0;
@@ -323,6 +361,16 @@
 }
 EXPORT_SYMBOL(is_mult_inc);
 
+bool is_support_no_parser(void)
+{
+	if ((enable_stream_mode_multi_dec) ||
+		(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_SC2) ||
+		(get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T7))
+		return true;
+	return false;
+}
+EXPORT_SYMBOL(is_support_no_parser);
+
 static const bool cores_with_input[VDEC_MAX] = {
 	true,   /* VDEC_1 */
 	false,  /* VDEC_HCODEC */
@@ -339,17 +387,17 @@
 	VDEC_IRQ_HEVC_BACK
 };
 
-unsigned long vdec_canvas_lock(struct vdec_core_s *core)
+unsigned long vdec_canvas_lock(void)
 {
 	unsigned long flags;
-	spin_lock_irqsave(&core->canvas_lock, flags);
+	spin_lock_irqsave(&vdec_core->canvas_lock, flags);
 
 	return flags;
 }
 
-void vdec_canvas_unlock(struct vdec_core_s *core, unsigned long flags)
+void vdec_canvas_unlock(unsigned long flags)
 {
-	spin_unlock_irqrestore(&core->canvas_lock, flags);
+	spin_unlock_irqrestore(&vdec_core->canvas_lock, flags);
 }
 
 unsigned long vdec_fps_lock(struct vdec_core_s *core)
@@ -415,14 +463,9 @@
 	up(&core->sem);
 }
 
-
 static u64 vdec_get_us_time_system(void)
 {
-	struct timeval tv;
-
-	do_gettimeofday(&tv);
-
-	return div64_u64(timeval_to_ns(&tv), 1000);
+	return div64_u64(local_clock(), 1000);
 }
 
 static void vdec_fps_clear(int id)
@@ -483,130 +526,6 @@
 	vdec_fps_unlock(vdec_core, flags);
 }
 
-
-
-static int get_canvas(unsigned int index, unsigned int base)
-{
-	int start;
-	int canvas_index = index * base;
-	int ret;
-
-	if ((base > 4) || (base == 0))
-		return -1;
-
-	if ((AMVDEC_CANVAS_START_INDEX + canvas_index + base - 1)
-		<= AMVDEC_CANVAS_MAX1) {
-		start = AMVDEC_CANVAS_START_INDEX + base * index;
-	} else {
-		canvas_index -= (AMVDEC_CANVAS_MAX1 -
-			AMVDEC_CANVAS_START_INDEX + 1) / base * base;
-		if (canvas_index <= AMVDEC_CANVAS_MAX2)
-			start = canvas_index / base;
-		else
-			return -1;
-	}
-
-	if (base == 1) {
-		ret = start;
-	} else if (base == 2) {
-		ret = ((start + 1) << 16) | ((start + 1) << 8) | start;
-	} else if (base == 3) {
-		ret = ((start + 2) << 16) | ((start + 1) << 8) | start;
-	} else if (base == 4) {
-		ret = (((start + 3) << 24) | (start + 2) << 16) |
-			((start + 1) << 8) | start;
-	}
-
-	return ret;
-}
-
-static int get_canvas_ex(int type, int id)
-{
-	int i;
-	unsigned long flags;
-
-	flags = vdec_canvas_lock(vdec_core);
-
-	for (i = 0; i < CANVAS_MAX_SIZE; i++) {
-		if ((canvas_stat[i].type == type) &&
-			(canvas_stat[i].id & (1 << id)) == 0) {
-			canvas_stat[i].canvas_used_flag++;
-			canvas_stat[i].id |= (1 << id);
-			if (debug & 4)
-				pr_debug("get used canvas %d\n", i);
-			vdec_canvas_unlock(vdec_core, flags);
-			if (i < AMVDEC_CANVAS_MAX2 + 1)
-				return i;
-			else
-				return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1);
-		}
-	}
-
-	for (i = 0; i < CANVAS_MAX_SIZE; i++) {
-		if (canvas_stat[i].type == 0) {
-			canvas_stat[i].type = type;
-			canvas_stat[i].canvas_used_flag = 1;
-			canvas_stat[i].id = (1 << id);
-			if (debug & 4) {
-				pr_debug("get canvas %d\n", i);
-				pr_debug("canvas_used_flag %d\n",
-					canvas_stat[i].canvas_used_flag);
-				pr_debug("canvas_stat[i].id %d\n",
-					canvas_stat[i].id);
-			}
-			vdec_canvas_unlock(vdec_core, flags);
-			if (i < AMVDEC_CANVAS_MAX2 + 1)
-				return i;
-			else
-				return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1);
-		}
-	}
-	vdec_canvas_unlock(vdec_core, flags);
-
-	pr_info("cannot get canvas\n");
-
-	return -1;
-}
-
-static void free_canvas_ex(int index, int id)
-{
-	unsigned long flags;
-	int offset;
-
-	flags = vdec_canvas_lock(vdec_core);
-	if (index >= 0 &&
-		index < AMVDEC_CANVAS_MAX2 + 1)
-		offset = index;
-	else if ((index >= AMVDEC_CANVAS_START_INDEX) &&
-		(index <= AMVDEC_CANVAS_MAX1))
-		offset = index + AMVDEC_CANVAS_MAX2 + 1 - AMVDEC_CANVAS_START_INDEX;
-	else {
-		vdec_canvas_unlock(vdec_core, flags);
-		return;
-	}
-
-	if ((canvas_stat[offset].canvas_used_flag > 0) &&
-		(canvas_stat[offset].id & (1 << id))) {
-		canvas_stat[offset].canvas_used_flag--;
-		canvas_stat[offset].id &= ~(1 << id);
-		if (canvas_stat[offset].canvas_used_flag == 0) {
-			canvas_stat[offset].type = 0;
-			canvas_stat[offset].id = 0;
-		}
-		if (debug & 4) {
-			pr_debug("free index %d used_flag %d, type = %d, id = %d\n",
-				offset,
-				canvas_stat[offset].canvas_used_flag,
-				canvas_stat[offset].type,
-				canvas_stat[offset].id);
-		}
-	}
-	vdec_canvas_unlock(vdec_core, flags);
-
-	return;
-
-}
-
 static void vdec_dmc_pipeline_reset(void)
 {
 	/*
@@ -657,42 +576,143 @@
 	}
 }
 
+#define VDEC_ASSIST_DBUS_DISABLE		0x0046
+#define HEVC_ASSIST_AXI_STATUS2_LO		0x307f
+
+static void vdec_dbus_ctrl(bool enable)
+{
+	if (enable) {
+		WRITE_VREG(VDEC_ASSIST_DBUS_DISABLE, 0);
+	} else {
+		u32 nop_cnt = 200;
+		WRITE_VREG(VDEC_ASSIST_DBUS_DISABLE, 0xffff);
+		while (READ_VREG(VDEC_ASSIST_DBUS_DISABLE) != 0xffff);
+		while (nop_cnt--);
+	}
+}
+
+static void hevc_arb_ctrl(bool enable)
+{
+	u32 axi_ctrl, axi_status, nop_cnt = 200;
+
+	if (enable) {
+		axi_ctrl = READ_VREG(HEVC_ASSIST_AXI_CTRL);
+		axi_ctrl &= (~((1 << 6) | (1 << 14)));
+		WRITE_VREG(HEVC_ASSIST_AXI_CTRL, axi_ctrl);		//enable front/back arbitor
+	} else {
+		axi_ctrl = READ_VREG(HEVC_ASSIST_AXI_CTRL);
+		axi_ctrl |= (1 << 6);
+		WRITE_VREG(HEVC_ASSIST_AXI_CTRL, axi_ctrl);	 // disable front arbitor
+
+		do {
+			axi_status = READ_VREG(HEVC_ASSIST_AXI_STATUS);
+			if (axi_status & ((1 << 15) | (1 << 11)))		//read/write disable
+				break;
+		} while (1);
+
+		axi_ctrl |= (1 << 14);
+		WRITE_VREG(HEVC_ASSIST_AXI_CTRL, axi_ctrl);	 // disable back arbitor
+
+		do {
+			axi_status = READ_VREG(HEVC_ASSIST_AXI_STATUS2_LO);
+			if (axi_status & ((1 << 15) | (1 << 11)))		//read/write disable
+				break;
+		} while (1);
+
+		while (nop_cnt--);
+	}
+}
+
+static void dec_dmc_port_ctrl(bool dmc_on, u32 target)
+{
+	unsigned long flags;
+	unsigned int sts_reg_addr = DMC_CHAN_STS;
+	unsigned int mask = 0;
+	unsigned int cpu_type = get_cpu_major_id();
+
+	if (target == VDEC_INPUT_TARGET_VLD) {
+		mask = (1 << 13);	/*bit13: DOS VDEC interface*/
+		if (cpu_type >= AM_MESON_CPU_MAJOR_ID_G12A)
+			mask = (1 << 21);
+	} else if (target == VDEC_INPUT_TARGET_HEVC) {
+		mask = (1 << 4); /*hevc*/
+		if (cpu_type >= AM_MESON_CPU_MAJOR_ID_G12A)
+			mask |= (1 << 8); /*hevcb */
+	}
+
+	if (!mask) {
+		pr_info("debug dmc ctrl return\n");
+		return;
+	}
+
+	if (dmc_on) {
+		/* dmc async on requset */
+		spin_lock_irqsave(&vdec_spin_lock, flags);
+
+		codec_dmcbus_write(DMC_REQ_CTRL,
+			codec_dmcbus_read(DMC_REQ_CTRL) | mask);
+
+		spin_unlock_irqrestore(&vdec_spin_lock, flags);
+	} else {
+		/* dmc async off requset */
+		spin_lock_irqsave(&vdec_spin_lock, flags);
+
+		codec_dmcbus_write(DMC_REQ_CTRL,
+			codec_dmcbus_read(DMC_REQ_CTRL) & ~mask);
+
+		spin_unlock_irqrestore(&vdec_spin_lock, flags);
+
+		switch (cpu_type) {
+		case AM_MESON_CPU_MAJOR_ID_S4:
+		case AM_MESON_CPU_MAJOR_ID_S4D:
+		case AM_MESON_CPU_MAJOR_ID_T5W:
+			sts_reg_addr = S4_DMC_CHAN_STS;
+			break;
+		case AM_MESON_CPU_MAJOR_ID_T5:
+		case AM_MESON_CPU_MAJOR_ID_T5D:
+			sts_reg_addr = T5_DMC_CHAN_STS;
+			break;
+		case AM_MESON_CPU_MAJOR_ID_SC2:
+			sts_reg_addr = TM2_REVB_DMC_CHAN_STS;
+			break;
+		case AM_MESON_CPU_MAJOR_ID_TM2:
+			if (is_cpu_meson_revb())
+				sts_reg_addr = TM2_REVB_DMC_CHAN_STS;
+			else
+				sts_reg_addr = DMC_CHAN_STS;
+			break;
+		default:
+			sts_reg_addr = DMC_CHAN_STS;
+			break;
+		}
+		while (!(codec_dmcbus_read(sts_reg_addr)
+				& mask))
+				;
+	}
+}
+
 static void vdec_disable_DMC(struct vdec_s *vdec)
 {
 	/*close first,then wait pedding end,timing suggestion from vlsi*/
 	struct vdec_input_s *input = &vdec->input;
-	unsigned long flags;
-	unsigned int mask = 0;
-
-	if (input->target == VDEC_INPUT_TARGET_VLD) {
-		mask = (1 << 13);
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
-			mask = (1 << 21);
-	} else if (input->target == VDEC_INPUT_TARGET_HEVC) {
-		mask = (1 << 4); /*hevc*/
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
-			mask |= (1 << 8); /*hevcb */
-	}
 
 	/* need to stop armrisc. */
 	if (!IS_ERR_OR_NULL(vdec->dev))
 		vdec_stop_armrisc(input->target);
 
-	spin_lock_irqsave(&vdec_spin_lock, flags);
-	codec_dmcbus_write(DMC_REQ_CTRL,
-		codec_dmcbus_read(DMC_REQ_CTRL) & ~mask);
-	spin_unlock_irqrestore(&vdec_spin_lock, flags);
-
-	if (is_cpu_tm2_revb() ||
-		(get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2)) {
-		while (!(codec_dmcbus_read(TM2_REVB_DMC_CHAN_STS)
-			& mask))
-			;
-	} else {
-		while (!(codec_dmcbus_read(DMC_CHAN_STS)
-				& mask))
-				;
-	}
+	if ((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) ||
+		(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T3)) {
+		if (input->target == VDEC_INPUT_TARGET_VLD) {
+			if (!vdec_on(VDEC_1))
+				return;
+			vdec_dbus_ctrl(0);
+		} else if (input->target == VDEC_INPUT_TARGET_HEVC) {
+			if (!vdec_on(VDEC_HEVC))
+				return;
+			hevc_arb_ctrl(0);
+		}
+	} else
+		dec_dmc_port_ctrl(0, input->target);
 
 	pr_debug("%s input->target= 0x%x\n", __func__,  input->target);
 }
@@ -700,27 +720,22 @@
 static void vdec_enable_DMC(struct vdec_s *vdec)
 {
 	struct vdec_input_s *input = &vdec->input;
-	unsigned long flags;
-	unsigned int mask = 0;
 
-	if (input->target == VDEC_INPUT_TARGET_VLD) {
-		mask = (1 << 13);
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
-			mask = (1 << 21);
-	} else if (input->target == VDEC_INPUT_TARGET_HEVC) {
-		mask = (1 << 4); /*hevc*/
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
-			mask |= (1 << 8); /*hevcb */
+	if ((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) ||
+		(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T3)) {
+		if (input->target == VDEC_INPUT_TARGET_VLD)
+			vdec_dbus_ctrl(1);
+		else if (input->target == VDEC_INPUT_TARGET_HEVC)
+			hevc_arb_ctrl(1);
+		return;
 	}
 
 	/*must to be reset the dmc pipeline if it's g12b.*/
 	if (get_cpu_type() == AM_MESON_CPU_MAJOR_ID_G12B)
 		vdec_dmc_pipeline_reset();
 
-	spin_lock_irqsave(&vdec_spin_lock, flags);
-	codec_dmcbus_write(DMC_REQ_CTRL,
-		codec_dmcbus_read(DMC_REQ_CTRL) | mask);
-	spin_unlock_irqrestore(&vdec_spin_lock, flags);
+	dec_dmc_port_ctrl(1, input->target);
+
 	pr_debug("%s input->target= 0x%x\n", __func__,  input->target);
 }
 
@@ -852,6 +867,7 @@
 int vdec_set_trickmode(struct vdec_s *vdec, unsigned long trickmode)
 {
 	int r;
+
 	if (vdec->set_trickmode) {
 		r = vdec->set_trickmode(vdec, trickmode);
 
@@ -860,6 +876,7 @@
 				trickmode);
 		return r;
 	}
+
 	return -1;
 }
 EXPORT_SYMBOL(vdec_set_trickmode);
@@ -921,7 +938,9 @@
 EXPORT_SYMBOL(vdec_count_info);
 int vdec_is_support_4k(void)
 {
-	return !is_meson_gxl_package_805X();
+	return ((!is_meson_gxl_package_805X()) &&
+			(!is_cpu_s4_s805x2()) &&
+			(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5D));
 }
 EXPORT_SYMBOL(vdec_is_support_4k);
 
@@ -948,6 +967,12 @@
 	return vdec_core->cma_dev;
 }
 
+int vdec_get_core_nr(void)
+{
+	return (int)atomic_read(&vdec_core->vdec_nr);
+}
+EXPORT_SYMBOL(vdec_get_core_nr);
+
 #ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
 static const char * const vdec_device_name[] = {
 	"amvdec_mpeg12",     "ammvdec_mpeg12",
@@ -1107,7 +1132,6 @@
 	struct vdec_s *vdec;
 	int type = VDEC_TYPE_SINGLE;
 	int id;
-
 	if (is_mult_inc(port->type))
 		type = (port->type & PORT_TYPE_FRAME) ?
 			VDEC_TYPE_FRAME_BLOCK :
@@ -1131,11 +1155,14 @@
 
 		INIT_LIST_HEAD(&vdec->list);
 
+		init_waitqueue_head(&vdec->idle_wait);
+
 		atomic_inc(&vdec_core->vdec_nr);
 #ifdef CONFIG_AMLOGIC_V4L_VIDEO3
 		v4lvideo_dec_count_increase();
 #endif
 		vdec->id = id;
+		vdec->video_id = 0xffffffff;
 		vdec_input_init(&vdec->input, vdec);
 		vdec->input.vdec_is_input_frame_empty = vdec_is_input_frame_empty;
 		vdec->input.vdec_up = vdec_up;
@@ -1171,6 +1198,7 @@
 		vdec->slave->format = format;
 		vdec->slave->port_flag |= PORT_FLAG_VFORMAT;
 	}
+
 	//trace_vdec_set_format(vdec, format);/*DEBUG_TMP*/
 
 	return 0;
@@ -1194,6 +1222,34 @@
 }
 EXPORT_SYMBOL(vdec_set_timestamp);
 
+void vdec_set_metadata(struct vdec_s *vdec, ulong meta_ptr)
+{
+	char *tmp_buf = NULL;
+	u32 size = 0;
+
+	if (!meta_ptr)
+		return;
+
+	tmp_buf = vmalloc(META_DATA_SIZE + 4);
+	if (!tmp_buf) {
+		pr_err("%s:vmalloc 256+4 fail\n", __func__);
+		return;
+	}
+	memcpy(tmp_buf, (void *)meta_ptr, META_DATA_SIZE + 4);
+
+	size = tmp_buf[0] + (tmp_buf[1] << 8) +
+		(tmp_buf[2] << 16) + (tmp_buf[3] << 24);
+
+	if ((size > 0) && (size <= META_DATA_SIZE)) {
+		memcpy(vdec->hdr10p_data_buf, tmp_buf + 4, size);
+		vdec->hdr10p_data_size = size;
+		vdec->hdr10p_data_valid = true;
+	}
+
+	vfree(tmp_buf);
+}
+EXPORT_SYMBOL(vdec_set_metadata);
+
 int vdec_set_pts64(struct vdec_s *vdec, u64 pts64)
 {
 	vdec->pts64 = pts64;
@@ -1422,6 +1478,8 @@
 }
 EXPORT_SYMBOL(vdec_stream_skip_data);
 
+
+
 /*
  *get next frame from input chain
  */
@@ -1579,9 +1637,6 @@
 				while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7))
 					;
 				WRITE_VREG(VLD_MEM_SWAP_CTL, 0);
-#ifdef VDEC_FCC_SUPPORT
-				vdec_fcc_jump_back(vdec);
-#endif
 
 				/* restore wrap count */
 				WRITE_VREG(VLD_MEM_VIFIFO_WRAP_COUNT,
@@ -1615,9 +1670,7 @@
 					& (1<<7))
 					;
 				WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0);
-#ifdef VDEC_FCC_SUPPORT
-				vdec_fcc_jump_back(vdec);
-#endif
+
 				/* restore stream offset */
 				WRITE_VREG(HEVC_SHIFT_BYTE_COUNT,
 					input->stream_cookie);
@@ -1650,7 +1703,6 @@
 				else
 					first_set_rp = input->start;
 			}
-
 			if (input->target == VDEC_INPUT_TARGET_VLD) {
 				WRITE_VREG(VLD_MEM_VIFIFO_START_PTR,
 					input->start);
@@ -1712,6 +1764,57 @@
 }
 EXPORT_SYMBOL(vdec_prepare_input);
 
+u32 vdec_offset_prepare_input(struct vdec_s *vdec, u32 consume_byte, u32 data_offset, u32 data_size)
+{
+	struct vdec_input_s *input = &vdec->input;
+	u32 res_byte, header_offset, header_data_size, data_invalid;
+
+	res_byte = data_size - consume_byte;
+	header_offset = data_offset;
+	header_data_size = data_size;
+	data_offset += consume_byte;
+	data_size = res_byte;
+
+	if (input->target == VDEC_INPUT_TARGET_VLD) {
+		//to do
+	} else if (input->target == VDEC_INPUT_TARGET_HEVC) {
+		data_invalid = data_offset - round_down(data_offset, 0x40);
+		data_offset -= data_invalid;
+		data_size += data_invalid;
+
+		if (data_offset < header_offset) {
+			data_invalid = consume_byte;
+			data_offset = header_offset;
+			data_size = header_data_size;
+		}
+
+		if (input_frame_based(input)) {
+			struct vframe_chunk_s *chunk = vdec_input_next_chunk(&vdec->input);
+			struct vframe_block_list_s *block = NULL;
+			int dummy;
+
+			block = chunk->block;
+			WRITE_VREG(HEVC_STREAM_START_ADDR, block->start);
+			WRITE_VREG(HEVC_STREAM_END_ADDR, block->start +
+					block->size);
+			WRITE_VREG(HEVC_STREAM_RD_PTR, block->start +
+					data_offset);
+			dummy = data_offset + data_size +
+					HEVC_PADDING_SIZE;
+			if (dummy >= block->size)
+				dummy -= block->size;
+			WRITE_VREG(HEVC_STREAM_WR_PTR,
+				round_down(block->start + dummy,
+					VDEC_FIFO_ALIGN));
+
+			/* set endian */
+			SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
+		}
+	}
+	return data_invalid;
+}
+EXPORT_SYMBOL(vdec_offset_prepare_input);
+
 void vdec_enable_input(struct vdec_s *vdec)
 {
 	struct vdec_input_s *input = &vdec->input;
@@ -1909,29 +2012,13 @@
 EXPORT_SYMBOL(vdec_need_more_data);
 
 
-void hevc_wait_ddr(void)
+static void hevc_wait_ddr(void)
 {
-	unsigned long flags;
-	unsigned int mask = 0;
-
-	mask = 1 << 4; /* hevc */
-	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
-		mask |= (1 << 8); /* hevcb */
-
-	spin_lock_irqsave(&vdec_spin_lock, flags);
-	codec_dmcbus_write(DMC_REQ_CTRL,
-		codec_dmcbus_read(DMC_REQ_CTRL) & ~mask);
-	spin_unlock_irqrestore(&vdec_spin_lock, flags);
-
-	if (is_cpu_tm2_revb() ||
-		(get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2)) {
-		while (!(codec_dmcbus_read(TM2_REVB_DMC_CHAN_STS)
-			& mask))
-			;
+	if ((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) ||
+		(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T3)) {
+		hevc_arb_ctrl(0);
 	} else {
-		while (!(codec_dmcbus_read(DMC_CHAN_STS)
-			& mask))
-			;
+		dec_dmc_port_ctrl(0, VDEC_INPUT_TARGET_HEVC);
 	}
 }
 
@@ -2248,7 +2335,18 @@
 	return 0;
 discon_timeout:
 	pr_err("%s timeout!!! status: 0x%x force it to 2\n", __func__, vdec->status);
-	vdec_set_status(vdec, VDEC_STATUS_CONNECTED);
+	if (vdec->status == VDEC_STATUS_ACTIVE) {
+		if (vdec->input.target == VDEC_INPUT_TARGET_VLD) {
+			amvdec_stop();
+			WRITE_VREG(ASSIST_MBOX1_MASK, 0);
+			vdec_free_irq(VDEC_IRQ_1, NULL);
+		} else if (vdec->input.target == VDEC_INPUT_TARGET_HEVC) {
+			amhevc_stop();
+			WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0);
+			vdec_free_irq(VDEC_IRQ_0, NULL);
+		}
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL(vdec_disconnect);
@@ -2284,41 +2382,10 @@
 		true : false;
 }
 
-static bool is_nontunnel_pipeline(u32 pl)
+static bool is_res_locked(u32 pre, u32 cur)
 {
-	return (pl & BIT(FRAME_BASE_PATH_DI_V4LVIDEO)) ? true : false;
-}
-
-static bool is_v4lvideo_already_used(u32 pre, int vf_receiver_inst)
-{
-	if (vf_receiver_inst == 0) {
-		if (pre & BIT(FRAME_BASE_PATH_DI_V4LVIDEO_0)) {
-			return true;
-		}
-	} else if (vf_receiver_inst == 1) {
-		if (pre & BIT(FRAME_BASE_PATH_DI_V4LVIDEO_1)) {
-			return true;
-		}
-	} else if (vf_receiver_inst == 2) {
-		if (pre & BIT(FRAME_BASE_PATH_DI_V4LVIDEO_2)) {
-			return true;
-		}
-	}
-	return false;
-}
-
-static bool is_res_locked(u32 pre, u32 cur, int vf_receiver_inst)
-{
-	if (is_tunnel_pipeline(pre)) {
-		if (is_tunnel_pipeline(cur)) {
-			return true;
-		}
-	} else if (is_nontunnel_pipeline(cur)) {
-		if (is_v4lvideo_already_used(pre,vf_receiver_inst)) {
-			return true;
-		}
-	}
-	return false;
+	return is_tunnel_pipeline(pre) ?
+		(is_tunnel_pipeline(cur) ? true : false) : false;
 }
 
 int vdec_resource_checking(struct vdec_s *vdec)
@@ -2329,9 +2396,9 @@
 	 * pipeline these are being released.
 	 */
 	ulong expires = jiffies + msecs_to_jiffies(2000);
+
 	while (is_res_locked(vdec_core->vdec_resouce_status,
-		BIT(vdec->frame_base_video_path),
-		vdec->vf_receiver_inst)) {
+		BIT(vdec->frame_base_video_path))) {
 		if (time_after(jiffies, expires)) {
 			pr_err("wait vdec resource timeout.\n");
 			return -EBUSY;
@@ -2347,29 +2414,32 @@
  *register vdec_device
  * create output, vfm or create ionvideo output
  */
-s32 vdec_init(struct vdec_s *vdec, int is_4k)
+s32 vdec_init(struct vdec_s *vdec, int is_4k, bool is_v4l)
 {
 	int r = 0;
 	struct vdec_s *p = vdec;
-	const char *dev_name;
+	const char *pdev_name;
+	char dev_name[32] = {0};
 	int id = PLATFORM_DEVID_AUTO;/*if have used my self*/
 	int max_di_count = max_di_instance;
-
+	char postprocess_name[64] = {0};
 	if (vdec_stream_based(vdec))
 		max_di_count = max_supported_di_instance;
-
+	vdec->is_v4l = is_v4l ? 1 : 0;
 	if (is_res_locked(vdec_core->vdec_resouce_status,
-		BIT(vdec->frame_base_video_path),
-		vdec->vf_receiver_inst))
+		BIT(vdec->frame_base_video_path)))
 		return -EBUSY;
-	//pr_err("%s [pid=%d,tgid=%d]\n", __func__, current->pid, current->tgid);
-	dev_name = get_dev_name(vdec_single(vdec), vdec->format);
 
-	if (dev_name == NULL)
+	//pr_err("%s [pid=%d,tgid=%d]\n", __func__, current->pid, current->tgid);
+	pdev_name = get_dev_name(vdec_single(vdec), vdec->format);
+	if (pdev_name == NULL)
 		return -ENODEV;
 
-	pr_info("vdec_init, dev_name:%s, vdec_type=%s  id = %d\n",
-		dev_name, vdec_type_str(vdec), vdec->id);
+	snprintf(dev_name, sizeof(dev_name),
+		"%s%s", pdev_name, is_v4l ? "_v4l": "");
+
+	pr_info("vdec_init, dev_name:%s, vdec_type=%s, format: %d\n",
+		dev_name, vdec_type_str(vdec), vdec->format);
 
 	snprintf(vdec->name, sizeof(vdec->name),
 		 "vdec-%d", vdec->id);
@@ -2409,24 +2479,31 @@
 	if (vdec_single(vdec) || (vdec_get_debug_flags() & 0x2))
 		vdec_enable_DMC(vdec);
 	p->cma_dev = vdec_core->cma_dev;
-	p->get_canvas = get_canvas;
-	p->get_canvas_ex = get_canvas_ex;
-	p->free_canvas_ex = free_canvas_ex;
+
+	vdec_canvas_port_register(vdec);
+
 	p->vdec_fps_detec = vdec_fps_detec;
 	/* todo */
 	if (!vdec_dual(vdec)) {
 		p->use_vfm_path =
-			(is_support_no_parser()) ?
+			is_support_no_parser() ?
 			vdec_single(vdec) :
 			vdec_stream_based(vdec);
 	}
 
+	if (debugflags & (1 << 29))
+		p->is_stream_mode_dv_multi = true;
+	else
+		p->is_stream_mode_dv_multi = false;
+
 	if (debugflags & 0x4)
 		p->use_vfm_path = 1;
 	/* vdec_dev_reg.flag = 0; */
 	if (vdec->id >= 0)
 		id = vdec->id;
 	p->parallel_dec = parallel_decode;
+	p->prog_only = prog_only;
+
 	vdec_core->parallel_dec = parallel_decode;
 	vdec->canvas_mode = CANVAS_BLKMODE_32X32;
 #ifdef FRAME_CHECK
@@ -2489,7 +2566,7 @@
 	if (p->use_vfm_path) {
 		vdec->vf_receiver_inst = -1;
 		vdec->vfm_map_id[0] = 0;
-	} else if (!vdec_dual(vdec)) {
+	} else if (!vdec_dual(vdec) && !vdec->disable_vfm) {
 		/* create IONVIDEO instance and connect decoder's
 		 * vf_provider interface to it
 		 */
@@ -2609,21 +2686,32 @@
 				mutex_unlock(&vdec_mutex);
 				goto error;
 			}
-			if (!v4lvideo_add_di)
+			if (v4lvideo_add_ppmgr)
+				snprintf(postprocess_name, sizeof(postprocess_name),
+					"%s ", "ppmgr");
+			if (debug_vdetect && (vdec->vf_receiver_inst == 0))
+				snprintf(postprocess_name + strlen(postprocess_name), sizeof(postprocess_name),
+					 "%s ", "vdetect.0");
+			/* 8K remove di */
+			if ((vdec->sys_info->width * vdec->sys_info->height > (4096 * 2304))
+				|| (!v4lvideo_add_di))
 				snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
-					"%s %s", vdec->vf_provider_name,
+					"%s %s%s", vdec->vf_provider_name,
+					postprocess_name,
 					vdec->vf_receiver_name);
 			else {
 				if ((vdec->vf_receiver_inst == 0)
 					&& (max_di_count > 0))
 					if (max_di_count == 1)
 						snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
-							"%s %s %s", vdec->vf_provider_name,
+							"%s %s%s %s", vdec->vf_provider_name,
+							postprocess_name,
 							"deinterlace",
 							vdec->vf_receiver_name);
 					else
 						snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
-							"%s %s %s", vdec->vf_provider_name,
+							"%s %s%s %s", vdec->vf_provider_name,
+							postprocess_name,
 							"dimulti.1",
 							vdec->vf_receiver_name);
 				else if ((vdec->vf_receiver_inst <
@@ -2685,6 +2773,27 @@
 				"amlvideo amvideo");
 			snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
 				"vdec-map-%d", vdec->id);
+		} else if (p->frame_base_video_path ==
+			FRAME_BASE_PATH_V4LVIDEO_FENCE) {
+#ifdef CONFIG_AMLOGIC_V4L_VIDEO3
+			r = v4lvideo_assign_map(&vdec->vf_receiver_name,
+					&vdec->vf_receiver_inst);
+#else
+			r = -1;
+#endif
+			if (r < 0) {
+				pr_err("V4lVideo frame receiver allocation failed.\n");
+				mutex_lock(&vdec_mutex);
+				inited_vcodec_num--;
+				mutex_unlock(&vdec_mutex);
+				goto error;
+			}
+
+			snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
+					"%s %s", vdec->vf_provider_name,
+					vdec->vf_receiver_name);
+			snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
+					"vdec-map-%d", vdec->id);
 		}
 
 		if (vfm_map_add(vdec->vfm_map_id,
@@ -2720,7 +2829,7 @@
 
 	}
 
-	if (!vdec_single(vdec)) {
+	if (!vdec_single(vdec) && !vdec->disable_vfm) {
 		vf_reg_provider(&p->vframe_provider);
 
 		vf_notify_receiver(p->vf_provider_name,
@@ -2752,15 +2861,6 @@
 
 	mutex_lock(&vdec_mutex);
 	vdec_core->vdec_resouce_status |= BIT(p->frame_base_video_path);
-	if (p->frame_base_video_path == FRAME_BASE_PATH_DI_V4LVIDEO) {
-		if (p->vf_receiver_inst == 0) {
-			vdec_core->vdec_resouce_status |= BIT(FRAME_BASE_PATH_DI_V4LVIDEO_0);
-		} else if (p->vf_receiver_inst == 1) {
-			vdec_core->vdec_resouce_status |= BIT(FRAME_BASE_PATH_DI_V4LVIDEO_1);
-		} else if (p->vf_receiver_inst == 2) {
-			vdec_core->vdec_resouce_status |= BIT(FRAME_BASE_PATH_DI_V4LVIDEO_2);
-		}
-	}
 	mutex_unlock(&vdec_mutex);
 
 	vdec_input_prepare_bufs(/*prepared buffer for fast playing.*/
@@ -2769,13 +2869,6 @@
 		vdec->sys_info->height);
 	/* vdec is now ready to be active */
 	vdec_set_status(vdec, VDEC_STATUS_DISCONNECTED);
-
-#ifdef VDEC_FCC_SUPPORT
-	init_waitqueue_head(&vdec->jump_back_wq);
-	mutex_init(&vdec->jump_back_mutex);
-	vdec->fcc_mode = FCC_BUTT;
-	vdec->fcc_status = STATUS_BUTT;
-#endif
 	return 0;
 
 error:
@@ -2815,6 +2908,36 @@
 	vdec_core_unlock(core, flags);
 }
 
+st_userdata *get_vdec_userdata_ctx()
+{
+	return &userdata;
+}
+EXPORT_SYMBOL(get_vdec_userdata_ctx);
+
+static void vdec_userdata_ctx_release(struct vdec_s *vdec)
+{
+	int i;
+	st_userdata *userdata = get_vdec_userdata_ctx();
+
+	mutex_lock(&userdata->mutex);
+
+	for (i = 0; i < MAX_USERDATA_CHANNEL_NUM; i++) {
+		if (userdata->used[i] == 1 && vdec->video_id != 0xffffffff) {
+			if (vdec_get_debug_flags() & 0x10000000)
+				pr_info("ctx_release i: %d userdata.id %d\n",
+				i, userdata->id[i]);
+			userdata->ready_flag[i] = 0;
+			userdata->id[i] = -1;
+			userdata->used[i] = 0;
+			userdata->set_id_flag = 0;
+		}
+	}
+
+	mutex_unlock(&userdata->mutex);
+
+	return;
+}
+
 /* vdec_create/init/release/destroy are applied to both dual running decoders
  */
 void vdec_release(struct vdec_s *vdec)
@@ -2831,10 +2954,10 @@
 	}
 #endif
 	/* When release, userspace systemctl need this duration 0 event */
-	vframe_rate_uevent(0);
+	vdec_frame_rate_uevent(0);
 	vdec_disconnect(vdec);
 
-	if (vdec->vframe_provider.name) {
+	if (!vdec->disable_vfm && vdec->vframe_provider.name) {
 		if (!vdec_single(vdec)) {
 			if (vdec_core->hint_fr_vdec == vdec
 			&& vdec->fr_hint_state == VDEC_HINTED)
@@ -2887,27 +3010,20 @@
 	if (vdec->vbuf.ops && !vdec->master)
 		vdec->vbuf.ops->release(&vdec->vbuf);
 
-	pr_debug("vdec_release instance %p, total %d id = %d\n", vdec,
-		atomic_read(&vdec_core->vdec_nr), vdec->id);
+	vdec_userdata_ctx_release(vdec);
+
+	pr_debug("vdec_release instance %p, total %d\n", vdec,
+		atomic_read(&vdec_core->vdec_nr));
 
 	mutex_lock(&vdec_mutex);
-	if (vdec->frame_base_video_path == FRAME_BASE_PATH_DI_V4LVIDEO) {
-		if (vdec->vf_receiver_inst == 0) {
-			vdec_core->vdec_resouce_status &= ~BIT(FRAME_BASE_PATH_DI_V4LVIDEO_0);
-		} else if (vdec->vf_receiver_inst == 1) {
-			vdec_core->vdec_resouce_status &= ~BIT(FRAME_BASE_PATH_DI_V4LVIDEO_1);
-		} else if (vdec->vf_receiver_inst == 2) {
-			vdec_core->vdec_resouce_status &= ~BIT(FRAME_BASE_PATH_DI_V4LVIDEO_2);
-		}
-	}
 	vdec_core->vdec_resouce_status &= ~BIT(vdec->frame_base_video_path);
 	mutex_unlock(&vdec_mutex);
-
 	vdec_destroy(vdec);
 
 	mutex_lock(&vdec_mutex);
 	inited_vcodec_num--;
 	mutex_unlock(&vdec_mutex);
+
 }
 EXPORT_SYMBOL(vdec_release);
 
@@ -2919,11 +3035,13 @@
 
 	vdec_disconnect(vdec);
 
-	if (vdec->vframe_provider.name)
-		vf_unreg_provider(&vdec->vframe_provider);
+	if (!vdec->disable_vfm) {
+		if (vdec->vframe_provider.name)
+			vf_unreg_provider(&vdec->vframe_provider);
 
-	if ((vdec->slave) && (vdec->slave->vframe_provider.name))
-		vf_unreg_provider(&vdec->slave->vframe_provider);
+		if ((vdec->slave) && (vdec->slave->vframe_provider.name))
+			vf_unreg_provider(&vdec->slave->vframe_provider);
+	}
 
 	if (vdec->reset) {
 		vdec->reset(vdec);
@@ -2938,15 +3056,17 @@
 	vdec_input_prepare_bufs(&vdec->input, vdec->sys_info->width,
 		vdec->sys_info->height);
 
-	vf_reg_provider(&vdec->vframe_provider);
-	vf_notify_receiver(vdec->vf_provider_name,
-			VFRAME_EVENT_PROVIDER_START, vdec);
+	if (!vdec->disable_vfm) {
+		vf_reg_provider(&vdec->vframe_provider);
+		vf_notify_receiver(vdec->vf_provider_name,
+				VFRAME_EVENT_PROVIDER_START, vdec);
 
-	if (vdec->slave) {
-		vf_reg_provider(&vdec->slave->vframe_provider);
-		vf_notify_receiver(vdec->slave->vf_provider_name,
-			VFRAME_EVENT_PROVIDER_START, vdec->slave);
-		vdec->slave->mc_loaded = 0;/*clear for reload firmware*/
+		if (vdec->slave) {
+			vf_reg_provider(&vdec->slave->vframe_provider);
+			vf_notify_receiver(vdec->slave->vf_provider_name,
+				VFRAME_EVENT_PROVIDER_START, vdec->slave);
+			vdec->slave->mc_loaded = 0;/*clear for reload firmware*/
+		}
 	}
 
 	vdec_connect(vdec);
@@ -2961,11 +3081,13 @@
 	pr_debug("vdec_v4l2_reset %d\n", flag);
 	vdec_disconnect(vdec);
 	if (flag != 2) {
-		if (vdec->vframe_provider.name)
-			vf_unreg_provider(&vdec->vframe_provider);
+		if (!vdec->disable_vfm) {
+			if (vdec->vframe_provider.name)
+				vf_unreg_provider(&vdec->vframe_provider);
 
-		if ((vdec->slave) && (vdec->slave->vframe_provider.name))
-			vf_unreg_provider(&vdec->slave->vframe_provider);
+			if ((vdec->slave) && (vdec->slave->vframe_provider.name))
+				vf_unreg_provider(&vdec->slave->vframe_provider);
+		}
 
 		if (vdec->reset) {
 			vdec->reset(vdec);
@@ -2981,15 +3103,17 @@
 		vdec_input_prepare_bufs(&vdec->input, vdec->sys_info->width,
 			vdec->sys_info->height);
 
-		vf_reg_provider(&vdec->vframe_provider);
-		vf_notify_receiver(vdec->vf_provider_name,
-				VFRAME_EVENT_PROVIDER_START, vdec);
+		if (!vdec->disable_vfm) {
+			vf_reg_provider(&vdec->vframe_provider);
+			vf_notify_receiver(vdec->vf_provider_name,
+					VFRAME_EVENT_PROVIDER_START, vdec);
 
-		if (vdec->slave) {
-			vf_reg_provider(&vdec->slave->vframe_provider);
-			vf_notify_receiver(vdec->slave->vf_provider_name,
-				VFRAME_EVENT_PROVIDER_START, vdec->slave);
-			vdec->slave->mc_loaded = 0;/*clear for reload firmware*/
+			if (vdec->slave) {
+				vf_reg_provider(&vdec->slave->vframe_provider);
+				vf_notify_receiver(vdec->slave->vf_provider_name,
+					VFRAME_EVENT_PROVIDER_START, vdec->slave);
+				vdec->slave->mc_loaded = 0;/*clear for reload firmware*/
+			}
 		}
 	} else {
 		if (vdec->reset) {
@@ -3001,13 +3125,10 @@
 
 	vdec_connect(vdec);
 
-	vdec_frame_check_init(vdec);
-
 	return 0;
 }
 EXPORT_SYMBOL(vdec_v4l2_reset);
 
-
 void vdec_free_cmabuf(void)
 {
 	mutex_lock(&vdec_mutex);
@@ -3070,8 +3191,10 @@
 		t &= ~(1 << i);
 	}
 
-	if (vdec->active_mask == 0)
+	if (vdec->active_mask == 0) {
 		vdec_set_status(vdec, VDEC_STATUS_CONNECTED);
+		wake_up_interruptible(&vdec->idle_wait);
+	}
 
 	mutex_unlock(&vdec_mutex);
 }
@@ -3202,6 +3325,30 @@
 	return ret;
 }
 
+int vdec_check_rec_num_enough(struct vdec_s *vdec) {
+
+	if (vdec->vbuf.use_ptsserv) {
+		return (pts_get_rec_num(PTS_TYPE_VIDEO,
+					vdec->input.total_rd_count) >= 2);
+	} else {
+		u64 total_rd_count = vdec->input.total_rd_count;
+
+		if (vdec->input.target == VDEC_INPUT_TARGET_VLD) {
+			//total_rd_count -= vdec->input.start;
+			/*just like use ptsserv, alway return true*/
+			return 1;
+		}
+		if ((total_rd_count >= vdec->vbuf.last_offset[0]) &&
+			(total_rd_count - vdec->vbuf.last_offset[0] < 0x80000000))
+			return 0;
+		else if ((total_rd_count >= vdec->vbuf.last_offset[1]) &&
+			(total_rd_count - vdec->vbuf.last_offset[1] < 0x80000000))
+			return 0;
+
+		return 1;
+	}
+}
+
 unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask)
 {
 	unsigned long ready_mask;
@@ -3229,7 +3376,6 @@
 	inc_profi_count(mask, vdec->check_count);
 #endif
 	if (vdec_core_with_input(mask)) {
-
 		/* check frame based input underrun */
 		if (input && !input->eos && input_frame_based(input)
 			&& (!vdec_input_next_chunk(input))) {
@@ -3250,8 +3396,7 @@
 				level = wp - rp;
 
 			if ((level < input->prepare_level) &&
-				(pts_get_rec_num(PTS_TYPE_VIDEO,
-					vdec->input.total_rd_count) < 2)) {
+				!vdec_check_rec_num_enough(vdec)) {
 				vdec->need_more_data |= VDEC_NEED_MORE_DATA;
 #ifdef VDEC_DEBUG_SUPPORT
 				inc_profi_count(mask, vdec->input_underrun_count);
@@ -3320,6 +3465,9 @@
  * Perform need_more_data checking and set flag is decoder
  * is not consuming data.
  */
+#define DMC_DEV_TYPE_NON_SECURE        0
+#define DMC_DEV_TYPE_SECURE            1
+
 void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask)
 {
 	struct vdec_input_s *input = &vdec->input;
@@ -3333,12 +3481,12 @@
 
 	if (vdec_stream_based(vdec) && !vdec_secure(vdec))
 	{
-		tee_config_device_secure(DMC_DEV_ID_PARSER, 0);
+		tee_config_device_state(DMC_DEV_ID_PARSER, 0);
 	}
 	if (input->target == VDEC_INPUT_TARGET_VLD)
-		tee_config_device_secure(DMC_DEV_ID_VDEC, secure);
+		tee_config_device_state(DMC_DEV_ID_VDEC, secure);
 	else if (input->target == VDEC_INPUT_TARGET_HEVC)
-		tee_config_device_secure(DMC_DEV_ID_HEVC, secure);
+		tee_config_device_state(DMC_DEV_ID_HEVC, secure);
 
 	if (vdec_stream_based(vdec) &&
 		((vdec->need_more_data & VDEC_NEED_MORE_DATA_RUN) &&
@@ -3350,7 +3498,6 @@
 	vdec->need_more_data &= ~VDEC_NEED_MORE_DATA_DIRTY;
 }
 
-
 /* struct vdec_core_shread manages all decoder instance in active list. When
  * a vdec is added into the active list, it can onlt be in two status:
  * VDEC_STATUS_CONNECTED(the decoder does not own HW resource and ready to run)
@@ -3550,7 +3697,6 @@
 			inc_profi_count(mask, vdec->run_count);
 			update_profi_clk_run(vdec, mask, get_current_clk());
 #endif
-
 			vdec->run(vdec, mask, vdec_callback, core);
 
 
@@ -3650,6 +3796,7 @@
 }
 EXPORT_SYMBOL(vdec_power_reset);
 
+
 void vdec_poweron(enum vdec_type_e core)
 {
 	if (core >= VDEC_MAX)
@@ -3797,27 +3944,12 @@
 
 void vdec_reset_core(struct vdec_s *vdec)
 {
-	unsigned long flags;
-	unsigned int mask = 0;
-
-	mask = 1 << 13; /*bit13: DOS VDEC interface*/
-	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
-		mask = 1 << 21; /*bit21: DOS VDEC interface*/
-
-	spin_lock_irqsave(&vdec_spin_lock, flags);
-	codec_dmcbus_write(DMC_REQ_CTRL,
-		codec_dmcbus_read(DMC_REQ_CTRL) & ~mask);
-	spin_unlock_irqrestore(&vdec_spin_lock, flags);
-
-	if (is_cpu_tm2_revb() ||
-		(get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2)) {
-		while (!(codec_dmcbus_read(TM2_REVB_DMC_CHAN_STS)
-			& mask))
-			;
+	if ((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) ||
+		(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T3)) {
+		/* t7 no dmc req for vdec only */
+		vdec_dbus_ctrl(0);
 	} else {
-		while (!(codec_dmcbus_read(DMC_CHAN_STS)
-			& mask))
-			;
+		dec_dmc_port_ctrl(0, VDEC_INPUT_TARGET_VLD);
 	}
 	/*
 	 * 2: assist
@@ -3837,10 +3969,11 @@
 	WRITE_VREG(DOS_SW_RESET0, (1<<3)|(1<<4)|(1<<5)|(1<<7)|(1<<8)|(1<<9));
 	WRITE_VREG(DOS_SW_RESET0, 0);
 
-	spin_lock_irqsave(&vdec_spin_lock, flags);
-	codec_dmcbus_write(DMC_REQ_CTRL,
-		codec_dmcbus_read(DMC_REQ_CTRL) | mask);
-	spin_unlock_irqrestore(&vdec_spin_lock, flags);
+	if ((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) ||
+		(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T3))
+		vdec_dbus_ctrl(1);
+	else
+		dec_dmc_port_ctrl(1, VDEC_INPUT_TARGET_VLD);
 }
 EXPORT_SYMBOL(vdec_reset_core);
 
@@ -3880,39 +4013,25 @@
 
 void hevc_reset_core(struct vdec_s *vdec)
 {
-	unsigned long flags;
-	unsigned int mask = 0;
-	int cpu_type;
+	int cpu_type = get_cpu_major_id();
 
-	mask = 1 << 4; /*bit4: hevc*/
-	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
-		mask |= 1 << 8; /*bit8: hevcb*/
-
-	WRITE_VREG(HEVC_STREAM_CONTROL, 0);
-	spin_lock_irqsave(&vdec_spin_lock, flags);
-	codec_dmcbus_write(DMC_REQ_CTRL,
-		codec_dmcbus_read(DMC_REQ_CTRL) & ~mask);
-	spin_unlock_irqrestore(&vdec_spin_lock, flags);
-
-	if (is_cpu_tm2_revb()  ||
-		(get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2)) {
-		while (!(codec_dmcbus_read(TM2_REVB_DMC_CHAN_STS)
-			& mask))
-			;
+	if ((cpu_type == AM_MESON_CPU_MAJOR_ID_T7) ||
+		(cpu_type == AM_MESON_CPU_MAJOR_ID_T3)) {
+		/* t7 no dmc req for hevc only */
+		hevc_arb_ctrl(0);
 	} else {
-		while (!(codec_dmcbus_read(DMC_CHAN_STS)
-			& mask))
-			;
+		WRITE_VREG(HEVC_STREAM_CONTROL, 0);
+
+		dec_dmc_port_ctrl(0, VDEC_INPUT_TARGET_HEVC);
 	}
 
 	if (vdec == NULL || input_frame_based(vdec))
 		WRITE_VREG(HEVC_STREAM_CONTROL, 0);
 
-
 	WRITE_VREG(HEVC_SAO_MMU_RESET_CTRL,
 			READ_VREG(HEVC_SAO_MMU_RESET_CTRL) | 1);
 
-		/*
+	/*
 	 * 2: assist
 	 * 3: parser
 	 * 4: parser_state
@@ -3929,25 +4048,17 @@
 	 * 24:hevc_afifo
 	 * 26:rst_mmu_n
 	 */
-	if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2) &&
-		(vdec->format == VFORMAT_AVS2)) {
-			WRITE_VREG(DOS_SW_RESET3,
-		(1<<3)|(1<<4)|(1<<8)|(1<<11)|
-		(1<<12)|(1<<14)|(1<<15)|
-		(1<<17)|(1<<18)|(1<<19));
-	} else {
-		WRITE_VREG(DOS_SW_RESET3,
-			(1<<3)|(1<<4)|(1<<8)|(1<<10)|(1<<11)|
-			(1<<12)|(1<<13)|(1<<14)|(1<<15)|
-			(1<<17)|(1<<18)|(1<<19)|(1<<24)|(1<<26));
-	}
+	WRITE_VREG(DOS_SW_RESET3,
+		(1<<3)|(1<<4)|(1<<8)|(1<<10)|(1<<11)|
+		(1<<12)|(1<<13)|(1<<14)|(1<<15)|
+		(1<<17)|(1<<18)|(1<<19)|(1<<24)|(1<<26));
 
 	WRITE_VREG(DOS_SW_RESET3, 0);
 	while (READ_VREG(HEVC_WRRSP_LMEM) & 0xfff)
 		;
 	WRITE_VREG(HEVC_SAO_MMU_RESET_CTRL,
 			READ_VREG(HEVC_SAO_MMU_RESET_CTRL) & (~1));
-	cpu_type = get_cpu_major_id();
+
 	if (cpu_type == AM_MESON_CPU_MAJOR_ID_TL1 &&
 			is_meson_rev_b())
 		cpu_type = AM_MESON_CPU_MAJOR_ID_G12B;
@@ -3962,12 +4073,17 @@
 	case AM_MESON_CPU_MAJOR_ID_SM1:
 	case AM_MESON_CPU_MAJOR_ID_TL1:
 	case AM_MESON_CPU_MAJOR_ID_TM2:
+	case AM_MESON_CPU_MAJOR_ID_T5:
+	case AM_MESON_CPU_MAJOR_ID_T5D:
+	case AM_MESON_CPU_MAJOR_ID_T5W:
 		WRITE_RESET_REG((RESET7_REGISTER_LEVEL),
 				READ_RESET_REG(RESET7_REGISTER_LEVEL) & (~((1<<13))));
 		WRITE_RESET_REG((RESET7_REGISTER_LEVEL),
 				READ_RESET_REG((RESET7_REGISTER_LEVEL)) | ((1<<13)));
 		break;
 	case AM_MESON_CPU_MAJOR_ID_SC2:
+	case AM_MESON_CPU_MAJOR_ID_S4:
+	case AM_MESON_CPU_MAJOR_ID_S4D:
 		WRITE_RESET_REG(P_RESETCTRL_RESET5_LEVEL,
 				READ_RESET_REG(P_RESETCTRL_RESET5_LEVEL) & (~((1<<1)|(1<<12)|(1<<13))));
 		WRITE_RESET_REG(P_RESETCTRL_RESET5_LEVEL,
@@ -3977,12 +4093,11 @@
 		break;
 	}
 
-
-	spin_lock_irqsave(&vdec_spin_lock, flags);
-	codec_dmcbus_write(DMC_REQ_CTRL,
-		codec_dmcbus_read(DMC_REQ_CTRL) | mask);
-	spin_unlock_irqrestore(&vdec_spin_lock, flags);
-
+	if ((cpu_type == AM_MESON_CPU_MAJOR_ID_T7) ||
+		(cpu_type == AM_MESON_CPU_MAJOR_ID_T3))
+		hevc_arb_ctrl(1);
+	else
+		dec_dmc_port_ctrl(1, VDEC_INPUT_TARGET_HEVC);
 }
 EXPORT_SYMBOL(hevc_reset_core);
 
@@ -4130,7 +4245,7 @@
 	int i;
 	char *pbuf = buf;
 	ssize_t ret;
-	u16 *trace_buf = vzalloc(debug_trace_num * 2);
+	u16 *trace_buf = kmalloc(debug_trace_num * 2, GFP_KERNEL);
 
 	if (!trace_buf) {
 		pbuf += sprintf(pbuf, "No Memory bug\n");
@@ -4141,7 +4256,7 @@
 		mutex_lock(&vdec_mutex);
 		if (!vdec_on(VDEC_1)) {
 			mutex_unlock(&vdec_mutex);
-			vfree(trace_buf);
+			kfree(trace_buf);
 			pbuf += sprintf(pbuf, "amrisc is power off\n");
 			ret = pbuf - buf;
 			return ret;
@@ -4197,7 +4312,7 @@
 	}
 	while (i < debug_trace_num)
 		;
-	vfree(trace_buf);
+	kfree(trace_buf);
 	pbuf += sprintf(pbuf, "\n");
 	ret = pbuf - buf;
 	return ret;
@@ -4241,8 +4356,7 @@
 
 	return count;
 }
-
-static ssize_t store_poweron_clock_level(struct class *class,
+static ssize_t poweron_clock_level_store(struct class *class,
 		struct class_attribute *attr,
 		const char *buf, size_t size)
 {
@@ -4258,7 +4372,7 @@
 	return size;
 }
 
-static ssize_t show_poweron_clock_level(struct class *class,
+static ssize_t poweron_clock_level_show(struct class *class,
 		struct class_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%d\n", poweron_clock_level);
@@ -4269,7 +4383,7 @@
  *always don't release
  *vdec 64 memory for fast play.
  */
-static ssize_t store_keep_vdec_mem(struct class *class,
+static ssize_t keep_vdec_mem_store(struct class *class,
 		struct class_attribute *attr,
 		const char *buf, size_t size)
 {
@@ -4284,15 +4398,14 @@
 	return size;
 }
 
-static ssize_t show_keep_vdec_mem(struct class *class,
+static ssize_t keep_vdec_mem_show(struct class *class,
 		struct class_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%d\n", keep_vdec_mem);
 }
 
-
 #ifdef VDEC_DEBUG_SUPPORT
-static ssize_t store_debug(struct class *class,
+static ssize_t debug_store(struct class *class,
 		struct class_attribute *attr,
 		const char *buf, size_t size)
 {
@@ -4331,6 +4444,10 @@
 			"VDEC_DEBUG: HHI_VDEC4_CLK_CNTL = 0x%x, HHI_VDEC2_CLK_CNTL = 0x%x\n",
 			READ_HHI_REG(HHI_VDEC4_CLK_CNTL),
 			READ_HHI_REG(HHI_VDEC2_CLK_CNTL));
+	} else if (strcmp(cbuf, "no_interlace") == 0) {
+		prog_only ^= 1;
+		pr_info("set prog only %d, %s output\n",
+			prog_only, prog_only?"force one filed only":"interlace");
 	}
 
 	flags = vdec_core_lock(vdec_core);
@@ -4349,7 +4466,7 @@
 	return size;
 }
 
-static ssize_t show_debug(struct class *class,
+static ssize_t debug_show(struct class *class,
 		struct class_attribute *attr, char *buf)
 {
 	char *pbuf = buf;
@@ -4375,6 +4492,8 @@
 	pbuf += sprintf(pbuf,
 		"read_hevc_clk_reg - read HHI register for hevc clk\n");
 	pbuf += sprintf(pbuf,
+		"no_interlace - force v4l no_interlace output. %d\n", prog_only);
+	pbuf += sprintf(pbuf,
 		"===================\n");
 
 	pbuf += sprintf(pbuf,
@@ -4412,7 +4531,6 @@
 
 }
 #endif
-
 int show_stream_buffer_status(char *buf,
 	int (*callback) (struct stream_buf_s *, char *))
 {
@@ -4436,7 +4554,7 @@
 }
 EXPORT_SYMBOL(show_stream_buffer_status);
 
-static ssize_t store_vdec_vfm_path(struct class *class,
+static ssize_t vdec_vfm_path_store(struct class *class,
 		 struct class_attribute *attr,
 		 const char *buf, size_t count)
 {
@@ -4495,7 +4613,7 @@
 	return count;
 }
 
-static ssize_t show_vdec_vfm_path(struct class *class,
+static ssize_t vdec_vfm_path_show(struct class *class,
 	struct class_attribute *attr, char *buf)
 {
 	int len = 0;
@@ -4550,7 +4668,6 @@
 		vdec_core->isr_context[num].dev_isr = handler;
 		vdec_core->isr_context[num].dev_threaded_isr = thread_fn;
 		vdec_core->isr_context[num].dev_id = dev;
-
 		ret = request_threaded_irq(res_irq,
 			vdec_isr,
 			vdec_thread_isr,
@@ -4608,6 +4725,20 @@
 }
 EXPORT_SYMBOL(vdec_free_irq);
 
+void vdec_sync_irq(enum vdec_irq_num num)
+{
+#if 0
+	if (!vdec)
+		return;
+	if (vdec->input.target == VDEC_INPUT_TARGET_HEVC)
+		synchronize_irq(vdec_core->isr_context[VDEC_IRQ_0].irq);
+	else (vdec->input.target == VDEC_INPUT_TARGET_VLD)
+		synchronize_irq(vdec_core->isr_context[VDEC_IRQ_1].irq);
+#endif
+	synchronize_irq(vdec_core->isr_context[num].irq);
+}
+EXPORT_SYMBOL(vdec_sync_irq);
+
 struct vdec_s *vdec_get_default_vdec_for_userdata(void)
 {
 	struct vdec_s *vdec;
@@ -4734,192 +4865,6 @@
 }
 EXPORT_SYMBOL(vdec_set_profile_level);
 
-#ifdef VDEC_FCC_SUPPORT
-int vdec_wakeup_fcc_poll(struct vdec_s *vdec)
-{
-	if (vdec) {
-		if (vdec->wakeup_fcc_poll)
-			vdec->wakeup_fcc_poll(vdec);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(vdec_wakeup_fcc_poll);
-
-int vdec_has_get_fcc_new_msg(struct vdec_s *vdec)
-{
-	int ret = 1;
-
-	if (vdec == NULL) {
-		pr_info("Error, invalid vdec instance!\n");
-		return 0;
-	}
-
-	if (input_stream_based(vdec)) {
-		if (vdec->fcc_mode == FCC_DISCARD_MODE &&
-			vdec->fcc_status == STATUS_BUTT) {
-			ret = 1;
-			vdec->fcc_status = AGAIN_STATUS;
-		} else if (vdec->fcc_mode == FCC_DEC_MODE &&
-			vdec->fcc_status != SWITCH_DONE_STATUS) {
-			ret = 1;
-
-			if (wait_event_interruptible_timeout(vdec->jump_back_wq, vdec->jump_back_done | vdec->jump_back_error,
-					HZ / 2) <= 0) {
-				pr_info("[%d][FCC]: Error! Wait jump back wp timeout 500ms!\n",
-					vdec->id);
-				vdec->fcc_status = SWITCH_DONE_STATUS;
-			} else {
-				if (fcc_debug_enable())
-					pr_info("[%d][FCC]: jump_back_done = %d\n",
-					vdec->id, vdec->jump_back_done);
-				if (vdec->jump_back_done) {
-					vdec->fcc_status = JUMP_BACK_STATUS;
-					vdec->jump_back_done = 0;
-				} else {
-					vdec->fcc_status = SWITCH_DONE_STATUS;
-					vdec->jump_back_error = 0;
-				}
-			}
-
-			if (fcc_debug_enable())
-				pr_info("[%d][FCC]: It is DEC mode now! fcc_status: %d\n",
-					vdec->id, vdec->fcc_status);
-		} else if (vdec->fcc_mode == FCC_DISCARD_MODE &&
-			!vdec->fcc_new_msg) {
-			if (vdec->fcc_status == WAIT_MSG_STATUS) {
-				if (fcc_debug_enable())
-					pr_info("[%d][FCC]: Wait msg!\n", vdec->id);
-				ret = 0;
-			} else {
-				if (fcc_debug_enable())
-					pr_info("[%d][FCC]: Continue to find header!\n", vdec->id);
-				ret = 1;
-			}
-		} else if (vdec->fcc_new_msg) {
-			if (fcc_debug_enable())
-				pr_info("[%d][FCC]: Got discard msg!\n", vdec->id);
-			ret = 1;
-			vdec->fcc_new_msg = 0;
-			if (vdec->fcc_mode == FCC_DISCARD_MODE) {
-				vdec->fcc_status = DISCARD_STATUS;
-			}
-		}
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(vdec_has_get_fcc_new_msg);
-void vdec_set_dmc_urgent(struct vdec_s *vdec, int urgentType)
-{
-#ifndef DMC_AXI4_G12_CHAN_CTRL
-#define DMC_AXI4_G12_CHAN_CTRL 		(0x90 << 2)
-#endif
-#define DMC_URGENT_TYPE_NORMAL 1
-#define DMC_URGENT_TYPE_URGENT 2
-#define DMC_URGENT_TYPE_SUPERURGENT 4
-
-	if (vdec) {
-		if (urgentType == DMC_URGENT_TYPE_NORMAL ||
-			urgentType == DMC_URGENT_TYPE_URGENT ||
-			urgentType == DMC_URGENT_TYPE_SUPERURGENT) {
-			int type;
-			unsigned int val;
-
-			type = vdec_get_hw_type(vdec->port->vformat);
-			if (type == CORE_MASK_HEVC) {
-				if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_G12A) {
-					val = READ_DMCREG(DMC_AXI4_CHAN_CTRL);
-					val &= (~(0x7 << 16));
-					val |= ((urgentType & 0x7) << 16);
-					WRITE_DMCREG(DMC_AXI4_CHAN_CTRL, val);
-				} else {
-					val = READ_DMCREG(DMC_AXI4_G12_CHAN_CTRL);
-					val &= (~(0x7 << 16));
-					val |= ((urgentType & 0x7) << 16);
-					WRITE_DMCREG(DMC_AXI4_G12_CHAN_CTRL, val);
-				}
-			}
-		}
-	}
-
-}
-EXPORT_SYMBOL(vdec_set_dmc_urgent);
-
-int fcc_debug_enable(void)
-{
-	return fcc_debug;
-}
-EXPORT_SYMBOL(fcc_debug_enable);
-
-static void vdec_fcc_jump_back(struct vdec_s *vdec)
-{
-	u32 cur_rp, set_rp;
-	struct vdec_input_s *input = &vdec->input;
-
-	if (fcc_debug_enable())
-		pr_info("[%d][FCC]: fcc_mode = %d fcc_status = %d\n",
-			vdec->id, vdec->fcc_mode, vdec->fcc_status);
-
-	if (input->target == VDEC_INPUT_TARGET_VLD) {
-		if (vdec->fcc_mode == FCC_DEC_MODE &&
-			vdec->fcc_status == JUMP_BACK_STATUS) {
-			set_rp = vdec->jump_back_rp;
-			cur_rp =READ_VREG(VLD_MEM_VIFIFO_RP);
-			input->stream_cookie = READ_VREG(VLD_MEM_VIFIFO_WRAP_COUNT);
-			if (cur_rp < set_rp) {
-				if (fcc_debug_enable())
-					pr_info("[%d][FCC]: Packet is wrapped! VLD_MEM_VIFIFO_WRAP_COUNT = %d\n",
-						vdec->id, input->stream_cookie);
-				input->stream_cookie = (input->stream_cookie - 1) < 0 ?
-								0 : input->stream_cookie - 1;
-			}
-
-			WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR, set_rp);
-			WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1);
-			WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
-
-			WRITE_VREG(VLD_MEM_SWAP_ADDR,
-				input->swap_page_phys);
-			WRITE_VREG(VLD_MEM_SWAP_CTL, 3);
-			while (READ_VREG(VLD_MEM_SWAP_CTL) & (1<<7))
-				;
-			WRITE_VREG(VLD_MEM_SWAP_CTL, 0);
-			vdec->fcc_status = SWITCH_DONE_STATUS;
-			if (fcc_debug_enable()) {
-				pr_info("[%d][FCC]:Current VLD_MEM_VIFIFO_WRAP_COUNT = %d cur_rp = %x set_rp = %x\n",
-					vdec->id, input->stream_cookie, cur_rp, set_rp);
-			}
-		}
-	} else if (input->target == VDEC_INPUT_TARGET_HEVC) {
-		if (vdec->fcc_mode == FCC_DEC_MODE &&
-			vdec->fcc_status == JUMP_BACK_STATUS) {
-			set_rp = vdec->jump_back_rp;
-			cur_rp = READ_VREG(HEVC_STREAM_RD_PTR);
-			if (cur_rp < set_rp) {
-				input->stream_cookie = input->stream_cookie + set_rp - cur_rp - vdec->input.size;
-			} else {
-				input->stream_cookie = input->stream_cookie - cur_rp + set_rp;
-			}
-
-			WRITE_VREG(HEVC_STREAM_RD_PTR, set_rp);
-			vdec->fcc_status = SWITCH_DONE_STATUS;
-
-			WRITE_VREG(HEVC_STREAM_SWAP_ADDR,
-				input->swap_page_phys);
-			WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 3);
-
-			while (READ_VREG(HEVC_STREAM_SWAP_CTRL)
-				& (1<<7))
-				;
-			WRITE_VREG(HEVC_STREAM_SWAP_CTRL, 0);
-		}
-	}
-
-	return;
-}
-#endif
-
 static int dump_mode;
 static ssize_t dump_risc_mem_store(struct class *class,
 		struct class_attribute *attr,
@@ -5036,10 +4981,11 @@
 
 		list_for_each_entry(vdec, &core->connected_vdec_list, list) {
 			pbuf += sprintf(pbuf,
-				"\tvdec.%d (%p (%s)), status = %s,\ttype = %s, \tactive_mask = %lx\n",
+				"\tvdec.%d (%p (%s%s)), status = %s,\ttype = %s, \tactive_mask = %lx\n",
 				vdec->id,
 				vdec,
 				vdec_device_name[vdec->format * 2],
+				(vdec->is_v4l == 1) ? "_v4l" : "",
 				vdec_status_str(vdec),
 				vdec_type_str(vdec),
 				vdec->active_mask);
@@ -5209,6 +5155,28 @@
 	return pbuf - buf;
 }
 
+static ssize_t version_show(struct class *class,
+			struct class_attribute *attr, char *buf)
+{
+	char *pbuf = buf;
+#ifdef DECODER_VERSION
+	pbuf += sprintf(pbuf, "DECODER VERSION: V" xstr(DECODER_VERSION) "\n");
+#else
+#ifdef RELEASED_VERSION
+		pbuf += sprintf(pbuf, "Due to project compilation environment problems,\
+the current decoder version could not be detected,\
+Please Use The DECODER BASE Version for traceability\n");
+		pbuf += sprintf(pbuf, "DECODER BASE Version: " xstr(RELEASED_VERSION) "\n");
+#endif
+#endif
+
+#ifdef UCODE_VERSION
+		pbuf += sprintf(pbuf, "UCODE VERSION: V" xstr(UCODE_VERSION) "\n");
+#endif
+
+	return pbuf - buf;
+}
+
 static char * parser_h264_profile(char *pbuf, struct vdec_s *vdec)
 {
 	switch (vdec->profile_idc) {
@@ -5476,71 +5444,65 @@
 	return pbuf - buf;
 }
 
-#ifdef VDEC_FCC_SUPPORT
-static ssize_t store_fcc_debug(struct class *class,
-		struct class_attribute *attr,
-		const char *buf, size_t size)
-{
-	unsigned int val;
-	ssize_t ret;
-
-	ret = kstrtoint(buf, 0, &val);
-	if (ret != 0)
-		return -EINVAL;
-	fcc_debug = val;
-	return size;
-}
-
-static ssize_t show_fcc_debug(struct class *class,
-		struct class_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%d\n", fcc_debug);
-}
-#endif
-
-static struct class_attribute vdec_class_attrs[] = {
-	__ATTR_RO(amrisc_regs),
-	__ATTR_RO(dump_trace),
-	__ATTR_RO(clock_level),
-	__ATTR(enable_mvdec_info, S_IRUGO | S_IWUSR | S_IWGRP,
-	enable_mvdec_info_show, enable_mvdec_info_store),
-	__ATTR(poweron_clock_level, S_IRUGO | S_IWUSR | S_IWGRP,
-	show_poweron_clock_level, store_poweron_clock_level),
-	__ATTR(dump_risc_mem, S_IRUGO | S_IWUSR | S_IWGRP,
-	dump_risc_mem_show, dump_risc_mem_store),
-	__ATTR(keep_vdec_mem, S_IRUGO | S_IWUSR | S_IWGRP,
-	show_keep_vdec_mem, store_keep_vdec_mem),
-	__ATTR_RO(core),
-	__ATTR_RO(vdec_status),
-	__ATTR_RO(dump_vdec_blocks),
-	__ATTR_RO(dump_vdec_chunks),
-	__ATTR_RO(dump_decoder_state),
+static CLASS_ATTR_RO(amrisc_regs);
+static CLASS_ATTR_RO(dump_trace);
+static CLASS_ATTR_RO(clock_level);
+static CLASS_ATTR_RW(poweron_clock_level);
+static CLASS_ATTR_RW(dump_risc_mem);
+static CLASS_ATTR_RW(keep_vdec_mem);
+static CLASS_ATTR_RW(enable_mvdec_info);
+static CLASS_ATTR_RO(core);
+static CLASS_ATTR_RO(vdec_status);
+static CLASS_ATTR_RO(dump_vdec_blocks);
+static CLASS_ATTR_RO(dump_vdec_chunks);
+static CLASS_ATTR_RO(dump_decoder_state);
 #ifdef VDEC_DEBUG_SUPPORT
-	__ATTR(debug, S_IRUGO | S_IWUSR | S_IWGRP,
-	show_debug, store_debug),
+static CLASS_ATTR_RW(debug);
 #endif
+static CLASS_ATTR_RW(vdec_vfm_path);
 #ifdef FRAME_CHECK
-	__ATTR(dump_yuv, S_IRUGO | S_IWUSR | S_IWGRP,
-	dump_yuv_show, dump_yuv_store),
-	__ATTR(frame_check, S_IRUGO | S_IWUSR | S_IWGRP,
-	frame_check_show, frame_check_store),
+static CLASS_ATTR_RW(dump_yuv);
+static CLASS_ATTR_RW(frame_check);
 #endif
-	__ATTR_RO(dump_fps),
-	__ATTR_RO(profile_idc),
-	__ATTR_RO(level_idc),
-	__ATTR(vfm_path, S_IRUGO | S_IWUSR | S_IWGRP,
-	show_vdec_vfm_path, store_vdec_vfm_path),
-#ifdef VDEC_FCC_SUPPORT
-	__ATTR(fcc_debug, S_IRUGO | S_IWUSR | S_IWGRP,
-	show_fcc_debug, store_fcc_debug),
+static CLASS_ATTR_RO(dump_fps);
+static CLASS_ATTR_RO(profile_idc);
+static CLASS_ATTR_RO(level_idc);
+static CLASS_ATTR_RO(version);
+
+static struct attribute *vdec_class_attrs[] = {
+	&class_attr_amrisc_regs.attr,
+	&class_attr_dump_trace.attr,
+	&class_attr_clock_level.attr,
+	&class_attr_poweron_clock_level.attr,
+	&class_attr_dump_risc_mem.attr,
+	&class_attr_keep_vdec_mem.attr,
+	&class_attr_enable_mvdec_info.attr,
+	&class_attr_core.attr,
+	&class_attr_vdec_status.attr,
+	&class_attr_dump_vdec_blocks.attr,
+	&class_attr_dump_vdec_chunks.attr,
+	&class_attr_dump_decoder_state.attr,
+#ifdef VDEC_DEBUG_SUPPORT
+	&class_attr_debug.attr,
 #endif
-	__ATTR_NULL
+	&class_attr_vdec_vfm_path.attr,
+#ifdef FRAME_CHECK
+	&class_attr_dump_yuv.attr,
+	&class_attr_frame_check.attr,
+#endif
+	&class_attr_dump_fps.attr,
+	&class_attr_profile_idc.attr,
+	&class_attr_level_idc.attr,
+	&class_attr_version.attr,
+	NULL
 };
 
+ATTRIBUTE_GROUPS(vdec_class);
+
 static struct class vdec_class = {
-		.name = "vdec",
-		.class_attrs = vdec_class_attrs,
-	};
+	.name = "vdec",
+	.class_groups = vdec_class_groups,
+};
 
 struct device *get_vdec_device(void)
 {
@@ -5548,6 +5510,119 @@
 }
 EXPORT_SYMBOL(get_vdec_device);
 
+static int vdec_post_task_recycle(void *args)
+{
+	struct post_task_mgr_s *post =
+		(struct post_task_mgr_s *)args;
+
+	while (post->running &&
+		down_interruptible(&post->sem) == 0) {
+		if (kthread_should_stop())
+			break;
+		mutex_lock(&post->mutex);
+		if (!list_empty(&post->task_recycle)) {
+			struct vdec_post_task_parms_s *parms, *tmp;
+			list_for_each_entry_safe(parms, tmp, &post->task_recycle, recycle) {
+				if (parms->scheduled) {
+					list_del(&parms->recycle);
+					kthread_stop(parms->task);
+					kfree(parms);
+					parms = NULL;
+				}
+			}
+		}
+		mutex_unlock(&post->mutex);
+	}
+
+	return 0;
+}
+
+static void vdec_post_task_exit(void)
+{
+	struct post_task_mgr_s *post = &vdec_core->post;
+
+	post->running = false;
+	up(&post->sem);
+
+	kthread_stop(post->task);
+}
+
+static int vdec_post_task_init(void)
+{
+	struct post_task_mgr_s *post = &vdec_core->post;
+
+	sema_init(&post->sem, 0);
+	INIT_LIST_HEAD(&post->task_recycle);
+	mutex_init(&post->mutex);
+	post->running = true;
+
+	post->task = kthread_run(vdec_post_task_recycle,
+		post, "task-post-daemon-thread");
+	if (IS_ERR(post->task)) {
+		pr_err("%s, creat task post daemon thread faild %ld\n",
+			__func__, PTR_ERR(post->task));
+		return PTR_ERR(post->task);
+	}
+
+	return 0;
+}
+
+static int vdec_post_handler(void *args)
+{
+	struct vdec_post_task_parms_s *parms =
+		(struct vdec_post_task_parms_s *) args;
+	struct post_task_mgr_s *post = &vdec_core->post;
+
+	complete(&parms->park);
+
+	/* process client task. */
+	parms->func(parms->private);
+	parms->scheduled = 1;
+	up(&post->sem);
+
+	while (!kthread_should_stop()) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		usleep_range(1000, 2000);
+	}
+
+	return 0;
+}
+
+int vdec_post_task(post_task_handler func, void *args)
+{
+	struct vdec_post_task_parms_s *parms;
+	struct post_task_mgr_s *post = &vdec_core->post;
+
+	parms = kzalloc(sizeof(*parms), GFP_KERNEL);
+	if (parms == NULL)
+		return -ENOMEM;
+
+	parms->func	= func;
+	parms->private	= args;
+	init_completion(&parms->park);
+	parms->scheduled = 0;
+	parms->task	= kthread_run(vdec_post_handler,
+				parms, "task-post-thread");
+	if (IS_ERR(parms->task)) {
+		pr_err("%s, creat task post thread faild %ld\n",
+			__func__, PTR_ERR(parms->task));
+		kfree(parms);
+		return PTR_ERR(parms->task);
+	}
+	if (!__kthread_should_park(parms->task))
+		wait_for_completion(&parms->park);
+
+	mutex_lock(&post->mutex);
+	/* add to list for resource recycle in post daemon kthread */
+	list_add_tail(&parms->recycle, &post->task_recycle);
+	mutex_unlock(&post->mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(vdec_post_task);
+
+
+
 static int vdec_probe(struct platform_device *pdev)
 {
 	s32 i, r;
@@ -5628,6 +5703,8 @@
 		WQ_MEM_RECLAIM |WQ_HIGHPRI/*high priority*/, "vdec-work");
 	/*work queue priority lower than vdec-core.*/
 
+	vdec_post_task_init();
+
 	/* power manager init. */
 	vdec_core->pm = (struct power_manager_s *)
 		of_device_get_match_data(&pdev->dev);
@@ -5637,6 +5714,7 @@
 			pr_err("vdec power manager init failed\n");
 			return r;
 		}
+		pr_err("vdec power init success!\n");
 	}
 
 	return 0;
@@ -5657,6 +5735,8 @@
 		}
 	}
 
+	vdec_post_task_exit();
+
 	kthread_stop(vdec_core->thread);
 
 	destroy_workqueue(vdec_core->vdec_core_wq);
@@ -5812,9 +5892,9 @@
 				ready = (ready + fifo[slot].frame_dur) / 2;
 			else
 				ready = fifo[slot].frame_dur;
-		pr_debug("%s inner driver dur%u \n",__func__, ready);
-	    }
-	    goto end_handle;
+			pr_debug("%s inner driver dur%u \n",__func__, ready);
+		}
+		goto end_handle;
 	}
 
 	if (slot == 1) {
@@ -5853,7 +5933,7 @@
 end_handle:
 	if (must_send) {
 		++must_send;
-		vframe_rate_uevent(ready);
+		vdec_frame_rate_uevent(ready);
 	}
 }
 
@@ -5891,7 +5971,7 @@
 		fifo_buf[i].pts_us64 = vf->pts_us64;
 
 		/* Calculate the duration from pts */
-		if (mvfrm->wr < MINIMUM_FRAMES && mvfrm->wr > 0)
+		if (!vdec->is_v4l && (mvfrm->wr < MINIMUM_FRAMES && mvfrm->wr > 0))
 			cal_dur_from_pts(vdec, i);
 	}
 	mvfrm->wr++;
@@ -5907,6 +5987,76 @@
 }
 EXPORT_SYMBOL(vdec_vframe_ready);
 
+void set_meta_data_to_vf(struct vframe_s *vf, u32 type, void *v4l2_ctx)
+{
+	struct aml_vcodec_ctx *ctx =
+			(struct aml_vcodec_ctx *)(v4l2_ctx);
+	struct aml_meta_head_s		head;
+	struct aml_vf_base_info_s	vfb_infos;
+
+	if ((ctx == NULL) || (vf == NULL))
+		return ;
+
+	if (vf->meta_data_buf == NULL) {
+		vf->meta_data_buf = ctx->meta_infos.meta_bufs[ctx->meta_infos.index].buf;
+		ctx->meta_infos.index = (ctx->meta_infos.index + 1) % V4L_CAP_BUFF_MAX;
+	}
+
+	switch (type) {
+	case UVM_META_DATA_VF_BASE_INFOS:
+		if ((vf->meta_data_size + sizeof(struct aml_vf_base_info_s) + AML_META_HEAD_SIZE) <= META_DATA_SIZE) {
+			head.magic = META_DATA_MAGIC;
+			head.type = UVM_META_DATA_VF_BASE_INFOS;
+			head.data_size = sizeof(struct aml_vf_base_info_s);
+
+			memcpy(vf->meta_data_buf + vf->meta_data_size,
+				&head, AML_META_HEAD_SIZE);
+			vf->meta_data_size += AML_META_HEAD_SIZE;
+
+			vfb_infos.width = vf->width;
+			vfb_infos.height = vf->height;
+			vfb_infos.duration = vf->duration;
+			vfb_infos.frame_type = vf->frame_type;
+			vfb_infos.type = vf->type;
+
+			memcpy(vf->meta_data_buf + vf->meta_data_size,
+				&vfb_infos, sizeof(struct aml_vf_base_info_s));
+			vf->meta_data_size += sizeof(struct aml_vf_base_info_s);
+
+			if (debug_meta) {
+				pr_debug("vf->meta_data_size = %d\n", vf->meta_data_size);
+				pr_debug("vf:width:%d height:%d duration:%d frame_type:%d type:%d\n",
+					vfb_infos.width, vfb_infos.height, vfb_infos.duration,
+					vfb_infos.frame_type, vfb_infos.type);
+			}
+		}
+		break;
+	case UVM_META_DATA_HDR10P_DATA:
+		if ((vf->meta_data_size + vf->hdr10p_data_size + AML_META_HEAD_SIZE) <= META_DATA_SIZE) {
+			head.magic = META_DATA_MAGIC;
+			head.type = UVM_META_DATA_HDR10P_DATA;
+			head.data_size = vf->hdr10p_data_size;
+
+			memcpy(vf->meta_data_buf + vf->meta_data_size,
+				&head, AML_META_HEAD_SIZE);
+			vf->meta_data_size += AML_META_HEAD_SIZE;
+
+			memcpy(vf->meta_data_buf + vf->meta_data_size,
+				vf->hdr10p_data_buf, vf->hdr10p_data_size);
+			vf->meta_data_size += vf->hdr10p_data_size;
+
+			if (debug_meta) {
+				pr_debug("vf->meta_data_size = %d\n", vf->meta_data_size);
+				pr_debug("vf->hdr10p_data_size = %d\n", vf->hdr10p_data_size);
+			}
+		}
+		break;
+	default:
+		break;
+	}
+}
+EXPORT_SYMBOL(set_meta_data_to_vf);
+
 /* In this function,if we use copy_to_user, we may encounter sleep,
 which may block the vdec_fill_vdec_frame,this is not acceptable.
 So, we should use a tmp buffer(passed by caller) to get the content */
@@ -5963,6 +6113,23 @@
 }
 EXPORT_SYMBOL(vdec_get_frame_vdec);
 
+int get_double_write_ratio(int dw_mode)
+{
+	int ratio = 1;
+
+	if ((dw_mode == 2) ||
+			(dw_mode == 3))
+		ratio = 4;
+	else if ((dw_mode == 4) ||
+				(dw_mode == 5))
+		ratio = 2;
+	else if ((dw_mode == 8) ||
+		(dw_mode == 9))
+		ratio = 8;
+	return ratio;
+}
+EXPORT_SYMBOL(get_double_write_ratio);
+
 void vdec_set_vld_wp(struct vdec_s *vdec, u32 wp)
 {
 	if (vdec_single(vdec)) {
@@ -6010,6 +6177,111 @@
 }
 EXPORT_SYMBOL(vdec_config_vld_reg);
 
+static void check_rdma_result(int num)
+{
+	int i, wr,rd,data;
+	int flag = 1;
+	for (i = 0; i < num; i++) {
+		wr = READ_VREG(HEVC_IQIT_SCALELUT_WR_ADDR);
+		rd = READ_VREG(HEVC_IQIT_SCALELUT_RD_ADDR);
+		data = READ_VREG(HEVC_IQIT_SCALELUT_DATA);
+		if (wr != (num & 0x3ff)) {
+			pr_info("--->HEVC_IQIT_SCALELUT_WR_ADDR = 0x%x\n", wr);
+			flag = 0;
+			break;
+		}
+		if (rd != i) {
+			pr_info("--->HEVC_IQIT_SCALELUT_RD_ADDR = 0x%x\n", rd);
+			flag = 0;
+			break;
+		}
+
+		if (data != 0) {
+			pr_info("--->HEVC_IQIT_SCALELUT_DATA = 0x%x\n", data);
+			flag = 0;
+			break;
+		}
+	}
+	if (flag == 0)
+		pr_info("-->%d--rdma flail\n", i);
+	else
+		pr_info("rdma ok\n");
+	return;
+
+}
+
+int is_rdma_enable(void)
+{
+	if (rdma_mode && (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T3))
+		return 1;
+	else
+		return 0;
+}
+EXPORT_SYMBOL(is_rdma_enable);
+
+void rdma_front_end_wrok(dma_addr_t ddr_phy_addr, u32 size)
+{
+	ulong expires;
+
+	WRITE_VREG(HEVC_RDMA_F_CTRL,
+		(0X0 << 7) | //axi id
+		(0X7 << 3) | //axi length
+		(0X0 << 2) | //rdma force cg en
+		(0X1 << 1)); //rdma path en
+	WRITE_VREG(HEVC_RDMA_F_START_ADDR, ddr_phy_addr); //rdma start address
+	WRITE_VREG(HEVC_RDMA_F_END_ADDR,   ddr_phy_addr + 0xff); //rdma end address
+	WRITE_VREG(HEVC_RDMA_F_STATUS0,    0X1); //trigger rdma start to work
+
+	expires = jiffies + msecs_to_jiffies(2000);
+	while (1) {
+		if ((READ_VREG(HEVC_RDMA_F_STATUS0) & 0x1) == 0) {
+			//pr_info("rdma front_end done\n");
+			break;
+		}
+		if (time_after(jiffies, expires)) {
+			pr_info("wait rdma done timeout\n");
+			break;
+		}
+	}
+
+	if (rdma_mode & 0x2)
+		check_rdma_result(SCALELUT_DATA_WRITE_NUM);
+
+	return;
+}
+EXPORT_SYMBOL(rdma_front_end_wrok);
+
+void rdma_back_end_work(dma_addr_t back_ddr_phy_addr, u32 size)
+{
+	ulong expires;
+
+	WRITE_VREG(HEVC_RDMA_B_CTRL,
+		(0X0 << 7) | //axi id
+		(0X7 << 3) | //axi length
+		(0X0 << 2) | //rdma force cg en
+		(0X1 << 1)); //rdma path en
+	WRITE_VREG(HEVC_RDMA_B_START_ADDR, back_ddr_phy_addr); //rdma start address
+	WRITE_VREG(HEVC_RDMA_B_END_ADDR,   back_ddr_phy_addr + size -1); //rdma end address
+	WRITE_VREG(HEVC_RDMA_B_STATUS0,    0X1); //trigger rdma start to work
+
+	expires = jiffies + msecs_to_jiffies(2000);
+	while (1) {
+		if ((READ_VREG(HEVC_RDMA_B_STATUS0) & 0x1) == 0) {
+			//pr_info("rdma back_end done\n");
+			break;
+		}
+		if (time_after(jiffies, expires)) {
+			pr_info("wait rdma done timeout\n");
+			break;
+		}
+	}
+	if (rdma_mode & 0x2)
+		check_rdma_result(SCALELUT_DATA_WRITE_NUM);
+
+	return;
+}
+EXPORT_SYMBOL(rdma_back_end_work);
+
 RESERVEDMEM_OF_DECLARE(vdec, "amlogic, vdec-memory", vdec_mem_setup);
 /*
 uint force_hevc_clock_cntl;
@@ -6029,6 +6301,8 @@
 module_param(force_nosecure_even_drm, int, 0664);
 module_param(disable_switch_single_to_mult, int, 0664);
 
+module_param(debug_meta, uint, 0664);
+
 module_param(frameinfo_flag, int, 0664);
 MODULE_PARM_DESC(frameinfo_flag,
 				"\n frameinfo_flag\n");
@@ -6036,6 +6310,10 @@
 MODULE_PARM_DESC(v4lvideo_add_di,
 				"\n v4lvideo_add_di\n");
 
+module_param(v4lvideo_add_ppmgr, int, 0664);
+MODULE_PARM_DESC(v4lvideo_add_ppmgr,
+				"\n v4lvideo_add_ppmgr\n");
+
 module_param(max_di_instance, int, 0664);
 MODULE_PARM_DESC(max_di_instance,
 				"\n max_di_instance\n");
@@ -6043,19 +6321,16 @@
 module_param(max_supported_di_instance, int, 0664);
 MODULE_PARM_DESC(max_supported_di_instance,
 				"\n max_supported_di_instance\n");
-
 module_param(debug_vdetect, int, 0664);
 MODULE_PARM_DESC(debug_vdetect, "\n debug_vdetect\n");
 
-#ifdef VDEC_FCC_SUPPORT
-module_param(fcc_debug, int, 0664);
-MODULE_PARM_DESC(fcc_debug, "\n fcc_debug\n");
-#endif
-
 module_param(enable_stream_mode_multi_dec, int, 0664);
-EXPORT_SYMBOL(enable_stream_mode_multi_dec);
 MODULE_PARM_DESC(enable_stream_mode_multi_dec,
 	"\n enable multi-decoding on stream mode. \n");
+
+module_param(rdma_mode, int, 0664);
+MODULE_PARM_DESC(rdma_mode, "\n rdma_enable\n");
+
 /*
 *module_init(vdec_module_init);
 *module_exit(vdec_module_exit);
diff --git a/drivers/frame_provider/decoder/utils/vdec.h b/drivers/frame_provider/decoder/utils/vdec.h
index 302bfad..a50bdb5 100644
--- a/drivers/frame_provider/decoder/utils/vdec.h
+++ b/drivers/frame_provider/decoder/utils/vdec.h
@@ -23,7 +23,7 @@
 #include <linux/list.h>
 #include <linux/completion.h>
 #include <linux/irqreturn.h>
-
+#include <linux/videodev2.h>
 #include <linux/amlogic/media/utils/amstream.h>
 #include <linux/amlogic/media/vfm/vframe.h>
 #include <linux/amlogic/media/vfm/vframe_provider.h>
@@ -37,6 +37,7 @@
 #include "vdec_input.h"
 #include "frame_check.h"
 #include "vdec_sync.h"
+#include "vdec_canvas_utils.h"
 
 s32 vdec_dev_register(void);
 s32 vdec_dev_unregister(void);
@@ -56,17 +57,84 @@
 
 #define VDEC_FIFO_ALIGN 8
 
-#define VDEC_FCC_SUPPORT
-
 enum vdec_type_e {
 	VDEC_1 = 0,
 	VDEC_HCODEC,
 	VDEC_2,
 	VDEC_HEVC,
 	VDEC_HEVCB,
+	VDEC_WAVE,
 	VDEC_MAX
 };
 
+struct trace_decoder_name {
+	char set_canvas0_addr[32];
+	char get_canvas0_addr[32];
+	char put_canvas0_addr[32];
+	char vf_put_name[32];
+	char vf_get_name[32];
+	char vdec_name[32];
+	char pts_name[32];
+	char new_q_name[32];
+	char disp_q_name[32];
+	char decode_time_name[32];
+	char decode_run_time_name[32];
+	char decode_header_time_name[32];
+	char decode_work_time_name[32];
+	char decode_header_memory_time_name[32];
+};
+
+
+enum e_trace_decoder_status {
+	DECODER_RUN_START = 1,
+	DECODER_RUN_END   = 2,
+	DECODER_ISR_HEAD_DONE = 3,
+	DECODER_ISR_PIC_DONE = 4,
+	DECODER_ISR_END   = 5,
+	DECODER_ISR_THREAD_HEAD_START = 6,
+	DECODER_ISR_THREAD_PIC_DONE_START = 7,
+	DECODER_ISR_THREAD_EDN = 8,
+	DECODER_WORKER_START   = 9,
+	DECODER_WORKER_END = 10,
+	DECODER_WORKER_AGAIN = 11,
+	DECODER_ISR_SEI_DONE = 12,
+	DECODER_ISR_THREAD_SEI_START = 13,
+	DECODER_ISR_AUX_DONE = 14,
+	DECODER_ISR_THREAD_AUX_START = 15,
+	DECODER_ISR_THREAD_HEAD_END = 16,
+};
+
+enum e_trace_run_status {
+	TRACE_RUN_LOADING_FW_START = 1,
+	TRACE_RUN_LOADING_FW_END   = 2,
+	TRACE_RUN_LOADING_RESTORE_START = 3,
+	TRACE_RUN_LOADING_RESTORE_END = 4,
+};
+
+enum e_trace_header_status {
+	TRACE_HEADER_MEMORY_START = 1,
+	TRACE_HEADER_MEMORY_END   = 2,
+	TRACE_HEADER_REGISTER_START = 3,
+	TRACE_HEADER_REGISTER_END   = 4,
+	TRACE_HEADER_RPM_START = 5,
+	TRACE_HEADER_RPM_END   = 6,
+};
+
+enum e_trace_work_status {
+	TRACE_WORK_WAIT_SEARCH_DONE_START = 1,
+	TRACE_WORK_WAIT_SEARCH_DONE_END   = 2,
+};
+
+
+#define VDEC_CFG_FLAG_DV_TWOLARYER (1 << 0)
+#define VDEC_CFG_FLAG_DV_NEGATIVE  (1 << 1)
+#define VDEC_CFG_FLAG_DIS_ERR_POLICY (1 << 11)
+
+#define VDEC_CFG_FLAG_PROG_ONLY (1 << 16)
+
+#define UVM_META_DATA_VF_BASE_INFOS (1 << 0)
+#define UVM_META_DATA_HDR10P_DATA (1 << 1)
+
 #define CORE_MASK_VDEC_1 (1 << VDEC_1)
 #define CORE_MASK_HCODEC (1 << VDEC_HCODEC)
 #define CORE_MASK_VDEC_2 (1 << VDEC_2)
@@ -75,14 +143,16 @@
 #define CORE_MASK_HEVC_BACK (1 << VDEC_HEVCB)
 #define CORE_MASK_COMBINE (1UL << 31)
 
+#define META_DATA_SIZE	(256)
+
+#define SEI_TYPE	(1)
+#define DV_TYPE		(2)
+
 extern void vdec2_power_mode(int level);
 extern void vdec_poweron(enum vdec_type_e core);
 extern void vdec_poweroff(enum vdec_type_e core);
 extern bool vdec_on(enum vdec_type_e core);
 extern void vdec_power_reset(void);
-extern void vdec_set_dmc_urgent(struct vdec_s *vdec, int urgentType);
-
-
 
 /*irq num as same as .dts*/
 
@@ -116,19 +186,6 @@
 	VDEC_NEED_HINT,
 	VDEC_HINTED,
 };
-
-#ifdef VDEC_FCC_SUPPORT
-typedef enum {
-	DISCARD_STATUS = 1,
-	AGAIN_STATUS,
-	WAIT_MSG_STATUS,
-	SWITCHING_STATUS,
-	JUMP_BACK_STATUS,
-	SWITCH_DONE_STATUS,
-	STATUS_BUTT
-} FCC_STATUS;
-#endif
-
 extern s32 vdec_request_threaded_irq(enum vdec_irq_num num,
 			irq_handler_t handler,
 			irq_handler_t thread_fn,
@@ -151,7 +208,6 @@
 extern void vdec_vframe_ready(struct vdec_s *vdec, struct vframe_s *vf);
 extern void vdec_set_vframe_comm(struct vdec_s *vdec, char *n);
 
-
 struct vdec_s;
 enum vformat_t;
 
@@ -190,6 +246,9 @@
 #define VDEC_NEED_MORE_DATA_DIRTY 0x02
 #define VDEC_NEED_MORE_DATA       0x04
 
+#define SCALELUT_DATA_WRITE_NUM   1024
+#define RDMA_SIZE                 (1024 * 4 * 4)
+
 struct vdec_s {
 	u32 magic;
 	struct list_head list;
@@ -215,7 +274,7 @@
 	int flag;
 	int sched;
 	int need_more_data;
-	u32 canvas_mode;
+	u32 canvas_mode;	//canvas block mode
 
 	struct completion inactive_done;
 
@@ -277,9 +336,6 @@
 			struct userdata_param_t *puserdata_para);
 	void (*reset_userdata_fifo)(struct vdec_s *vdec, int bInit);
 	void (*wakeup_userdata_poll)(struct vdec_s *vdec);
-#ifdef VDEC_FCC_SUPPORT
-	void (*wakeup_fcc_poll)(struct vdec_s *vdec);
-#endif
 	/* private */
 	void *private;       /* decoder per instance specific data */
 #ifdef VDEC_DEBUG_SUPPORT
@@ -296,7 +352,7 @@
 	u64 irq_cnt;
 	int parallel_dec;
 	struct vdec_frames_s *mvfrm;
-	struct vdec_sync sync;
+	struct vdec_sync *sync;
 
 	/*aux data check*/
 	struct aux_data_check_mgr_t adc;
@@ -306,29 +362,90 @@
 	bool hdr10p_data_valid;
 	u32 profile_idc;
 	u32 level_idc;
-#ifdef VDEC_FCC_SUPPORT
-	enum fcc_mode_e fcc_mode;
-	u32 stream_offset;
-	int fcc_new_msg;
-	FCC_STATUS fcc_status;
-	wait_queue_head_t jump_back_wq;
-	struct mutex jump_back_mutex;
-	u32 jump_back_done;
-	u32 jump_back_error;
-	u32 jump_back_rp;
-#endif
-	u32 video_id;
+	bool prog_only;
+	bool disable_vfm;
 	char name[32];
 	char dec_spend_time[32];
 	char dec_spend_time_ave[32];
 	u32 discard_start_data_flag;
+	u32 video_id;
+	int is_v4l;
+	bool is_stream_mode_dv_multi;
+	wait_queue_head_t idle_wait;
 };
 
+#define CODEC_MODE(a, b, c, d)\
+	(((u8)(a) << 24) | ((u8)(b) << 16) | ((u8)(c) << 8) | (u8)(d))
+
+#define META_DATA_MAGIC		CODEC_MODE('M', 'E', 'T', 'A')
+#define AML_META_HEAD_NUM	8
+#define AML_META_HEAD_SIZE	(AML_META_HEAD_NUM * sizeof(u32))
+
+
+struct aml_meta_head_s {
+	u32 magic;
+	u32 type;
+	u32 data_size;
+	u32 data[5];
+};
+
+struct aml_vf_base_info_s {
+	u32 width;
+	u32 height;
+	u32 duration;
+	u32 frame_type;
+	u32 type;
+	u32 data[12];
+};
+
+struct aml_meta_info_s {
+	union {
+		struct aml_meta_head_s head;
+		u32 buf[AML_META_HEAD_NUM];
+	};
+	u8 data[0];
+};
+
+typedef int (*post_task_handler)(void *args);
+
+struct post_task_mgr_s {
+	struct list_head	task_recycle;
+	struct task_struct	*task;
+	struct semaphore        sem;
+	struct mutex		mutex;
+	bool 			running;
+	void			*private;
+};
+
+struct vdec_post_task_parms_s {
+	struct list_head	recycle;
+	struct task_struct	*task;
+	struct completion	park;
+	post_task_handler	func;
+	void			*private;
+	int			scheduled;
+};
+
+#define MAX_USERDATA_CHANNEL_NUM 9
+
+typedef struct {
+	struct mutex mutex;
+	wait_queue_head_t userdata_wait;
+	u32 video_id;
+	u32 set_id_flag;
+	u32 ready_flag[MAX_USERDATA_CHANNEL_NUM];
+	int used[MAX_USERDATA_CHANNEL_NUM];
+	u32 id[MAX_USERDATA_CHANNEL_NUM];
+} st_userdata;
+
 /* common decoder vframe provider name to use default vfm path */
 #define VFM_DEC_PROVIDER_NAME "decoder"
 #define VFM_DEC_DVBL_PROVIDER_NAME "dvbldec"
 #define VFM_DEC_DVEL_PROVIDER_NAME "dveldec"
 
+#define VFM_DEC_DVBL_PROVIDER_NAME2 "dvbldec2"
+#define VFM_DEC_DVEL_PROVIDER_NAME2 "dveldec2"
+
 #define hw_to_vdec(hw) ((struct vdec_s *) \
 	(platform_get_drvdata(hw->platform_dev)))
 
@@ -352,6 +469,24 @@
 #define vdec_secure(vdec) \
 	(((vdec)->port_flag & PORT_FLAG_DRM))
 
+#define PR_INIT(s)					\
+	int __len = 0, __size = s;			\
+	u8 __buf[s] = {0}
+
+#define PR_FILL(args...)				\
+	do {						\
+		if ((__size - __len) <= 0) break;	\
+		__len += snprintf(__buf + __len,	\
+		__size - __len, ##args);		\
+	} while (0)
+
+#define PR_INFO(id)					\
+	do {						\
+		if (__len == 0) break;			\
+		pr_info("[%d] %s\n", id, __buf);	\
+		__len = 0;				\
+	} while (0)
+
 /* construct vdec strcture */
 extern struct vdec_s *vdec_create(struct stream_port_s *port,
 				struct vdec_s *master);
@@ -384,6 +519,9 @@
 /* prepare decoder input */
 extern int vdec_prepare_input(struct vdec_s *vdec, struct vframe_chunk_s **p);
 
+extern u32 vdec_offset_prepare_input(struct vdec_s *vdec, u32 consume_byte,
+	u32 data_offset, u32 data_size);
+
 /* clean decoder input */
 extern void vdec_clean_input(struct vdec_s *vdec);
 
@@ -422,14 +560,13 @@
 extern int vdec_reset(struct vdec_s *vdec);
 
 extern int vdec_v4l2_reset(struct vdec_s *vdec, int flag);
-
 extern void vdec_set_status(struct vdec_s *vdec, int status);
 
 extern void vdec_set_next_status(struct vdec_s *vdec, int status);
 
 extern int vdec_set_decinfo(struct vdec_s *vdec, struct dec_sysinfo *p);
 
-extern int vdec_init(struct vdec_s *vdec, int is_4k);
+extern int vdec_init(struct vdec_s *vdec, int is_4k, bool is_v4l);
 
 extern void vdec_release(struct vdec_s *vdec);
 
@@ -484,7 +621,9 @@
 #ifdef VDEC_DEBUG_SUPPORT
 extern void vdec_set_step_mode(void);
 #endif
+
 extern void hevc_mmu_dma_check(struct vdec_s *vdec);
+
 int vdec_read_user_data(struct vdec_s *vdec,
 				struct userdata_param_t *p_userdata_param);
 
@@ -496,12 +635,6 @@
 struct vdec_s *vdec_get_vdec_by_id(int vdec_id);
 
 
-#ifdef VDEC_FCC_SUPPORT
-int vdec_wakeup_fcc_poll(struct vdec_s *vdec);
-int vdec_has_get_fcc_new_msg(struct vdec_s *vdec);
-int fcc_debug_enable(void);
-#endif
-
 #ifdef VDEC_DEBUG_SUPPORT
 extern void vdec_set_step_mode(void);
 #endif
@@ -509,12 +642,12 @@
 
 void VDEC_PRINT_FUN_LINENO(const char *fun, int line);
 
-
 unsigned char is_mult_inc(unsigned int);
 
 int vdec_get_status(struct vdec_s *vdec);
 
 void vdec_set_timestamp(struct vdec_s *vdec, u64 timestamp);
+void vdec_set_metadata(struct vdec_s *vdec, ulong meta_ptr);
 
 extern u32  vdec_get_frame_vdec(struct vdec_s *vdec,  struct vframe_counter_s *tmpbuf);
 
@@ -523,12 +656,13 @@
 int show_stream_buffer_status(char *buf,
 	int (*callback) (struct stream_buf_s *, char *));
 
-bool is_support_no_parser(void);
+extern int get_double_write_ratio(int dw_mode);
 
-extern u32 timestamp_avsync_counter_get(void);
+bool is_support_no_parser(void);
 
 int vdec_resource_checking(struct vdec_s *vdec);
 
+void set_meta_data_to_vf(struct vframe_s *vf, u32 type, void *v4l2_ctx);
 
 void vdec_set_profile_level(struct vdec_s *vdec, u32 profile_idc, u32 level_idc);
 
@@ -536,4 +670,28 @@
 void vdec_set_vld_wp(struct vdec_s *vdec, u32 wp);
 void vdec_config_vld_reg(struct vdec_s *vdec, u32 addr, u32 size);
 
+extern u32 timestamp_avsync_counter_get(void);
+
+void vdec_canvas_unlock(unsigned long flags);
+
+unsigned long vdec_canvas_lock(void);
+
+int vdec_get_core_nr(void);
+
+
+int vdec_post_task(post_task_handler func, void *args);
+
+void rdma_front_end_wrok(dma_addr_t ddr_phy_addr, u32 size);
+
+void rdma_back_end_work(dma_addr_t back_ddr_phy_addr, u32 size);
+
+int is_rdma_enable(void);
+
+st_userdata *get_vdec_userdata_ctx(void);
+
+void vdec_frame_rate_uevent(int dur);
+
+void vdec_sync_irq(enum vdec_irq_num num);
+
+
 #endif				/* VDEC_H */
diff --git a/drivers/frame_provider/decoder/utils/vdec_canvas_utils.c b/drivers/frame_provider/decoder/utils/vdec_canvas_utils.c
new file mode 100644
index 0000000..46fc003
--- /dev/null
+++ b/drivers/frame_provider/decoder/utils/vdec_canvas_utils.c
@@ -0,0 +1,415 @@
+/*
+ * drivers/amlogic/media/frame_provider/decoder/utils/vdec_canvas_utils.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/types.h>
+#include "vdec_canvas_utils.h"
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "vdec.h"
+
+static struct canvas_status_s canvas_stat[CANVAS_MAX_SIZE];
+static struct canvas_status_s mdec_cav_stat[MDEC_CAV_LUT_MAX];
+static struct canvas_config_s *mdec_cav_pool = NULL;
+
+extern u32 vdec_get_debug(void);
+
+
+bool is_support_vdec_canvas(void)
+{
+	/* vdec canvas note:
+	 * 1. canvas params config to display, do not use
+	 *    vf->canvasxAddr, should use vf->canvasxconfig[].
+	 * 2. the endian can not config with canvas. and hevc
+	 *    core should not config canvas. config endian in
+	 *    probe function like h265/vp9/av1/avs2.
+	*/
+	if ((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) ||
+		(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T3) ||
+		(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5W))
+		return true;
+	return false;
+}
+EXPORT_SYMBOL(is_support_vdec_canvas);
+
+static int get_canvas(unsigned int index, unsigned int base)
+{
+	int start;
+	int canvas_index = index * base;
+	int ret = 0;
+
+	if ((base > 4) || (base == 0))
+		return -1;
+
+	if ((AMVDEC_CANVAS_START_INDEX + canvas_index + base - 1)
+		<= AMVDEC_CANVAS_MAX1) {
+		start = AMVDEC_CANVAS_START_INDEX + base * index;
+	} else {
+		canvas_index -= (AMVDEC_CANVAS_MAX1 -
+			AMVDEC_CANVAS_START_INDEX + 1) / base * base;
+		if (canvas_index <= AMVDEC_CANVAS_MAX2)
+			start = canvas_index / base;
+		else
+			return -1;
+	}
+
+	if (base == 1) {
+		ret = start;
+	} else if (base == 2) {
+		ret = ((start + 1) << 16) | ((start + 1) << 8) | start;
+	} else if (base == 3) {
+		ret = ((start + 2) << 16) | ((start + 1) << 8) | start;
+	} else if (base == 4) {
+		ret = (((start + 3) << 24) | (start + 2) << 16) |
+			((start + 1) << 8) | start;
+	}
+
+	return ret;
+}
+
+static int get_canvas_ex(int type, int id)
+{
+	int i;
+	unsigned long flags;
+
+	flags = vdec_canvas_lock();
+
+	for (i = 0; i < CANVAS_MAX_SIZE; i++) {
+		/*0x10-0x15 has been used by rdma*/
+		if ((i >= 0x10) && (i <= 0x15))
+				continue;
+		if ((canvas_stat[i].type == type) &&
+			(canvas_stat[i].id & (1 << id)) == 0) {
+			canvas_stat[i].canvas_used_flag++;
+			canvas_stat[i].id |= (1 << id);
+			if (vdec_get_debug() & 4)
+				pr_debug("get used canvas %d\n", i);
+			vdec_canvas_unlock(flags);
+			if (i < AMVDEC_CANVAS_MAX2 + 1)
+				return i;
+			else
+				return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1);
+		}
+	}
+
+	for (i = 0; i < CANVAS_MAX_SIZE; i++) {
+		/*0x10-0x15 has been used by rdma*/
+		if ((i >= 0x10) && (i <= 0x15))
+				continue;
+		if (canvas_stat[i].type == 0) {
+			canvas_stat[i].type = type;
+			canvas_stat[i].canvas_used_flag = 1;
+			canvas_stat[i].id = (1 << id);
+			if (vdec_get_debug() & 4) {
+				pr_debug("get canvas %d\n", i);
+				pr_debug("canvas_used_flag %d\n",
+					canvas_stat[i].canvas_used_flag);
+				pr_debug("canvas_stat[i].id %d\n",
+					canvas_stat[i].id);
+			}
+			vdec_canvas_unlock(flags);
+			if (i < AMVDEC_CANVAS_MAX2 + 1)
+				return i;
+			else
+				return (i + AMVDEC_CANVAS_START_INDEX - AMVDEC_CANVAS_MAX2 - 1);
+		}
+	}
+	vdec_canvas_unlock(flags);
+
+	pr_info("cannot get canvas\n");
+
+	return -1;
+}
+
+static void free_canvas_ex(int index, int id)
+{
+	unsigned long flags;
+	int offset;
+
+	flags = vdec_canvas_lock();
+	if (index >= 0 &&
+		index < AMVDEC_CANVAS_MAX2 + 1)
+		offset = index;
+	else if ((index >= AMVDEC_CANVAS_START_INDEX) &&
+		(index <= AMVDEC_CANVAS_MAX1))
+		offset = index + AMVDEC_CANVAS_MAX2 + 1 - AMVDEC_CANVAS_START_INDEX;
+	else {
+		vdec_canvas_unlock(flags);
+		return;
+	}
+
+	if ((canvas_stat[offset].canvas_used_flag > 0) &&
+		(canvas_stat[offset].id & (1 << id))) {
+		canvas_stat[offset].canvas_used_flag--;
+		canvas_stat[offset].id &= ~(1 << id);
+		if (canvas_stat[offset].canvas_used_flag == 0) {
+			canvas_stat[offset].type = 0;
+			canvas_stat[offset].id = 0;
+		}
+		if (vdec_get_debug() & 4) {
+			pr_debug("free index %d used_flag %d, type = %d, id = %d\n",
+				offset,
+				canvas_stat[offset].canvas_used_flag,
+				canvas_stat[offset].type,
+				canvas_stat[offset].id);
+		}
+	}
+	vdec_canvas_unlock(flags);
+
+	return;
+}
+
+
+static int get_internal_cav_lut(unsigned int index, unsigned int base)
+{
+	int start;
+	int canvas_index = index * base;
+	int ret = 0;
+
+	if ((base > 4) || (base == 0))
+		return -1;
+
+	if (canvas_index + base - 1 < MDEC_CAV_LUT_MAX)
+		start = canvas_index;
+	else
+		return -1;
+
+	if (base == 1) {
+		ret = start;
+	} else if (base == 2) {
+		ret = ((start + 1) << 16) | ((start + 1) << 8) | start;
+	} else if (base == 3) {
+		ret = ((start + 2) << 16) | ((start + 1) << 8) | start;
+	} else if (base == 4) {
+		ret = (((start + 3) << 24) | (start + 2) << 16) |
+			((start + 1) << 8) | start;
+	}
+
+	return ret;
+}
+
+static int get_internal_cav_lut_ex(int type, int id)
+{
+	int i;
+	unsigned long flags;
+
+	flags = vdec_canvas_lock();
+
+	for (i = 0; i < MDEC_CAV_LUT_MAX; i++) {
+		if ((mdec_cav_stat[i].type == type) &&
+			(mdec_cav_stat[i].id & (1 << id)) == 0) {
+			mdec_cav_stat[i].canvas_used_flag++;
+			mdec_cav_stat[i].id |= (1 << id);
+			if (vdec_get_debug() & 4)
+				pr_debug("get used cav lut %d\n", i);
+			vdec_canvas_unlock(flags);
+			return i;
+		}
+	}
+
+	for (i = 0; i < MDEC_CAV_LUT_MAX; i++) {
+		if (mdec_cav_stat[i].type == 0) {
+			mdec_cav_stat[i].type = type;
+			mdec_cav_stat[i].canvas_used_flag = 1;
+			mdec_cav_stat[i].id = (1 << id);
+			if (vdec_get_debug() & 4)
+				pr_debug("get cav lut %d\n", i);
+			vdec_canvas_unlock(flags);
+			return i;
+		}
+	}
+	vdec_canvas_unlock(flags);
+
+	pr_info("cannot get cav lut\n");
+
+	return -1;
+}
+
+static void free_internal_cav_lut(int index, int id)
+{
+	unsigned long flags;
+	int offset;
+
+	flags = vdec_canvas_lock();
+	if (index > 0 && index < MDEC_CAV_LUT_MAX)
+		offset = index;
+	else {
+		vdec_canvas_unlock(flags);
+		return;
+	}
+	if ((mdec_cav_stat[offset].canvas_used_flag > 0) &&
+		(mdec_cav_stat[offset].id & (1 << id))) {
+		mdec_cav_stat[offset].canvas_used_flag--;
+		mdec_cav_stat[offset].id &= ~(1 << id);
+		if (mdec_cav_stat[offset].canvas_used_flag == 0) {
+			mdec_cav_stat[offset].type = 0;
+			mdec_cav_stat[offset].id = 0;
+		}
+		if (vdec_get_debug() & 4) {
+			pr_debug("free index %d used_flag %d, type = %d, id = %d\n",
+				offset,
+				mdec_cav_stat[offset].canvas_used_flag,
+				mdec_cav_stat[offset].type,
+				mdec_cav_stat[offset].id);
+		}
+	}
+	vdec_canvas_unlock(flags);
+
+	return;
+}
+
+unsigned long vdec_cav_get_addr(int index)
+{
+	if (index < 0 || index >= MDEC_CAV_LUT_MAX) {
+		pr_err("%s, error index %d\n", __func__, index);
+		return -1;
+	}
+
+	return mdec_cav_pool[index & MDEC_CAV_INDEX_MASK].phy_addr;
+}
+EXPORT_SYMBOL(vdec_cav_get_addr);
+
+unsigned int vdec_cav_get_width(int index)
+{
+	if (index < 0 || index >= MDEC_CAV_LUT_MAX) {
+		pr_err("%s, error index %d\n", __func__, index);
+		return -1;
+	}
+
+	return mdec_cav_pool[index & MDEC_CAV_INDEX_MASK].width;
+}
+EXPORT_SYMBOL(vdec_cav_get_width);
+
+unsigned int vdec_cav_get_height(int index)
+{
+	if (index < 0 || index >= MDEC_CAV_LUT_MAX) {
+		pr_err("%s, error index %d\n", __func__, index);
+		return -1;
+	}
+	return mdec_cav_pool[index & MDEC_CAV_INDEX_MASK].height;
+}
+EXPORT_SYMBOL(vdec_cav_get_height);
+
+void cav_lut_info_store(u32 index, ulong addr, u32 width,
+	u32 height, u32 wrap, u32 blkmode, u32 endian)
+{
+	struct canvas_config_s *pool = NULL;
+
+	if (index < 0 || index >= MDEC_CAV_LUT_MAX) {
+		pr_err("%s, error index %d\n", __func__, index);
+		return;
+	}
+	if (mdec_cav_pool == NULL)
+		mdec_cav_pool = vzalloc(sizeof(struct canvas_config_s)
+			* (MDEC_CAV_LUT_MAX + 1));
+
+	if (mdec_cav_pool == NULL) {
+		pr_err("%s failed, mdec_cav_pool null\n", __func__);
+		return;
+	}
+	pool = &mdec_cav_pool[index];
+	pool->width = width;
+	pool->height = height;
+	pool->block_mode = blkmode;
+	pool->endian = endian;
+	pool->phy_addr = addr;
+}
+
+void config_cav_lut_ex(u32 index, ulong addr, u32 width,
+	u32 height, u32 wrap, u32 blkmode,
+	u32 endian, enum vdec_type_e core)
+{
+	unsigned long datah_temp, datal_temp;
+
+	if (!is_support_vdec_canvas()) {
+		canvas_config_ex(index, addr, width, height, wrap, blkmode, endian);
+		if (vdec_get_debug() & 0x40000000) {
+			pr_info("%s %2d) addr: %lx, width: %d, height: %d, blkm: %d, endian: %d\n",
+				__func__, index, addr, width, height, blkmode, endian);
+		}
+	} else {
+		/*
+		datal_temp = (cav_lut.start_addr & 0x1fffffff) |
+			((cav_lut.cav_width & 0x7 ) << 29 );
+		datah_temp = ((cav_lut.cav_width  >> 3) & 0x1ff) |
+			(( cav_lut.cav_hight & 0x1fff) <<9 ) |
+			((cav_lut.x_wrap_en & 1) << 22 ) |
+			(( cav_lut.y_wrap_en & 1) << 23) |
+			(( cav_lut.blk_mode & 0x3) << 24);
+		*/
+		u32 addr_bits_l = ((((addr + 7) >> 3) & CANVAS_ADDR_LMASK) << CAV_WADDR_LBIT);
+		u32 width_l     = ((((width    + 7) >> 3) & CANVAS_WIDTH_LMASK) << CAV_WIDTH_LBIT);
+		u32 width_h     = ((((width    + 7) >> 3) >> CANVAS_WIDTH_LWID) << CAV_WIDTH_HBIT);
+		u32 height_h    = (height & CANVAS_HEIGHT_MASK) << CAV_HEIGHT_HBIT;
+		u32 blkmod_h    = (blkmode & CANVAS_BLKMODE_MASK) << CAV_BLKMODE_HBIT;
+		u32 switch_bits_ctl = (endian & 0xf) << CAV_ENDIAN_HBIT;
+		u32 wrap_h      = (0 << 23);
+		datal_temp = addr_bits_l | width_l;
+		datah_temp = width_h | height_h | wrap_h | blkmod_h | switch_bits_ctl;
+
+		if (core == VDEC_1) {
+			if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T3) && (endian == 7))
+				WRITE_VREG(MDEC_CAV_CFG0, 0x1ff << 17);
+			else
+				WRITE_VREG(MDEC_CAV_CFG0, 0); //[0]canv_mode, by default is non-canv-mode
+			WRITE_VREG(MDEC_CAV_LUT_DATAL, datal_temp);
+			WRITE_VREG(MDEC_CAV_LUT_DATAH, datah_temp);
+			WRITE_VREG(MDEC_CAV_LUT_ADDR,  index);
+		}
+
+		cav_lut_info_store(index, addr, width, height, wrap, blkmode, endian);
+
+		if (vdec_get_debug() & 0x40000000) {
+			pr_info("%s %2d) addr: %lx, width: %d, height: %d, blkm: %d, endian: %d\n",
+				__func__, index, addr, width, height, blkmode, endian);
+			pr_info("data(h,l): 0x%8lx, 0x%8lx\n", datah_temp, datal_temp);
+	    }
+	}
+}
+EXPORT_SYMBOL(config_cav_lut_ex);
+
+void config_cav_lut(int index, struct canvas_config_s *cfg,
+	enum vdec_type_e core)
+{
+	config_cav_lut_ex(index,
+		cfg->phy_addr,
+		cfg->width,
+		cfg->height,
+		CANVAS_ADDR_NOWRAP,
+		cfg->block_mode,
+		cfg->endian,
+		core);
+}
+EXPORT_SYMBOL(config_cav_lut);
+
+
+void vdec_canvas_port_register(struct vdec_s *vdec)
+{
+	if (is_support_vdec_canvas()) {
+		vdec->get_canvas = get_internal_cav_lut;
+		vdec->get_canvas_ex = get_internal_cav_lut_ex;
+		vdec->free_canvas_ex = free_internal_cav_lut;
+		if (mdec_cav_pool == NULL) {
+			mdec_cav_pool = vzalloc(sizeof(struct canvas_config_s)
+			* (MDEC_CAV_LUT_MAX + 1));
+		}
+	} else {
+		vdec->get_canvas = get_canvas;
+		vdec->get_canvas_ex = get_canvas_ex;
+		vdec->free_canvas_ex = free_canvas_ex;
+	}
+}
+EXPORT_SYMBOL(vdec_canvas_port_register);
diff --git a/drivers/frame_provider/decoder/utils/vdec_canvas_utils.h b/drivers/frame_provider/decoder/utils/vdec_canvas_utils.h
new file mode 100644
index 0000000..add83cf
--- /dev/null
+++ b/drivers/frame_provider/decoder/utils/vdec_canvas_utils.h
@@ -0,0 +1,70 @@
+/*
+ * drivers/amlogic/media/frame_provider/decoder/utils/vdec_canvas_utils.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 __CANVAS_UTILS_H__
+#define __CANVAS_UTILS_H__
+
+#include "vdec.h"
+
+/* external canvas */
+struct canvas_status_s {
+	int type;
+	int canvas_used_flag;
+	int id;
+};
+
+#define CANVAS_MAX_SIZE (AMVDEC_CANVAS_MAX1 - AMVDEC_CANVAS_START_INDEX + 1 + AMVDEC_CANVAS_MAX2 + 1)
+
+
+/* internal canvas */
+#define CANVAS_ADDR_LMASK       0x1fffffff
+#define CANVAS_WIDTH_LMASK      0x7
+#define CANVAS_WIDTH_LWID       3
+#define CANVAS_HEIGHT_MASK      0x1fff
+#define CANVAS_BLKMODE_MASK     3
+
+#define CAV_WADDR_LBIT       0
+#define CAV_WIDTH_LBIT       29
+#define CAV_WIDTH_HBIT       0
+#define CAV_HEIGHT_HBIT      (41 - 32)
+#define CAV_WRAPX_HBIT       (54 - 32)
+#define CAV_WRAPY_HBIT       (55 - 32)
+#define CAV_BLKMODE_HBIT     (56 - 32)
+#define CAV_ENDIAN_HBIT      (58 - 32)
+
+#define MDEC_CAV_LUT_MAX 128
+#define MDEC_CAV_INDEX_MASK 0x7f
+
+enum vdec_type_e;
+
+void config_cav_lut(int index, struct canvas_config_s *cfg, enum vdec_type_e core);
+
+void config_cav_lut_ex(u32 index, ulong addr, u32 width,
+	u32 height, u32 wrap, u32 blkmode,
+	u32 endian, enum vdec_type_e core);
+
+unsigned int vdec_cav_get_width(int index);
+
+unsigned int vdec_cav_get_height(int index);
+
+unsigned long vdec_cav_get_addr(int index);
+
+bool is_support_vdec_canvas(void);
+
+void vdec_canvas_port_register(struct vdec_s *vdec);
+
+#endif
+
diff --git a/drivers/frame_provider/decoder/utils/vdec_feature.c b/drivers/frame_provider/decoder/utils/vdec_feature.c
new file mode 100644
index 0000000..ea3a75d
--- /dev/null
+++ b/drivers/frame_provider/decoder/utils/vdec_feature.c
@@ -0,0 +1,522 @@
+/*
+ * drivers/amlogic/media/stream_input/amports/amstream_profile.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/fs.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/utils/vformat.h>
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+#include "vdec.h"
+
+
+
+//static const struct codec_profile_t *vcodec_feature[SUPPORT_VDEC_NUM] = { 0 };
+
+struct vcodec_feature {
+	int format;
+	int is_v4l;
+};
+
+static struct vcodec_feature feature[SUPPORT_VDEC_NUM];
+
+static int vcodec_feature_idx;
+static ulong last_time;
+u8 buf[4096];
+
+
+static const char * const format_name[] = {
+	"ammvdec_mpeg12",
+	"ammvdec_mpeg4",
+	"ammvdec_h264",
+	"ammvdec_mjpeg",
+	"ammvdec_real",
+	"ammjpegdec",
+	"ammvdec_vc1",
+	"ammvdec_avs",
+	"ammvdec_yuv",
+	"ammvdec_h264mvc",
+	"ammvdec_h264_4k2k",
+	"ammvdec_h265",
+	"amvenc_avc",
+	"jpegenc",
+	"ammvdec_vp9",
+	"ammvdec_avs2",
+	"ammvdec_av1",
+};
+
+static int vcodec_feature_CC(u8 *buf, int size, int vformat, int is_v4l)
+{
+	u8 *pbuf = buf;
+
+	if (!is_v4l) {
+		switch (vformat) {
+			case VFORMAT_MPEG12:
+			case VFORMAT_H264:
+			case VFORMAT_AVS:
+				pbuf += snprintf(pbuf, size, "        \"CC subtitle\" : \"true\"\n");
+				break;
+			default:
+				break;
+		}
+	}
+
+	return pbuf - buf;
+}
+
+static int vcodec_feature_report_information(u8 *buf, int size, int vformat, int is_v4l)
+{
+	u8 *pbuf = buf;
+
+	if (!is_v4l) {
+		pbuf += snprintf(pbuf, size, "        \"Decoder information report\" : \"true\"\n");
+	}
+
+	return pbuf - buf;
+}
+
+static int vcodec_feature_i_only_mode(u8 *buf, int size, int vformat)
+{
+	u8 *pbuf = buf;
+
+	switch (vformat) {
+		case VFORMAT_MPEG12:
+		case VFORMAT_H264:
+		case VFORMAT_MPEG4:
+		case VFORMAT_HEVC:
+		case VFORMAT_AVS2:
+			pbuf += snprintf(pbuf, size, "        \"I only mode\" : \"true\"\n");
+			break;
+		default:
+			break;
+	}
+
+	return pbuf - buf;
+}
+
+static int vcodec_feature_dolbyVison(u8 *buf, int size, int vformat)
+{
+	u8 *pbuf = buf;
+
+	switch (vformat) {
+		case VFORMAT_H264:
+		case VFORMAT_HEVC:
+		case VFORMAT_AV1:
+			if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM) &&
+				(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5) &&
+				(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5D) &&
+				(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_S4))
+				pbuf += snprintf(pbuf, size, "        \"DolbyVision\" : \"true\"\n");
+			break;
+		default:
+			break;
+	}
+
+	return pbuf - buf;
+}
+
+static int vcodec_feature_HDR(u8 *buf, int size, int vformat)
+{
+	u8 *pbuf = buf;
+
+	switch (vformat) {
+		case VFORMAT_H264:
+		case VFORMAT_HEVC:
+		case VFORMAT_AV1:
+		case VFORMAT_AVS2:
+		case VFORMAT_VP9:
+				pbuf += snprintf(pbuf, size, "        \"HDR\" : \"true\"\n");
+			break;
+		default:
+			break;
+	}
+
+	return pbuf - buf;
+}
+
+
+static int vcodec_feature_doublewrite(u8 *buf, int size, int vformat)
+{
+	u8 *pbuf = buf;
+	int tsize = 0;
+	int s;
+
+	switch (vformat) {
+		case VFORMAT_HEVC:
+		case VFORMAT_VP9:
+		case VFORMAT_AVS2:
+		case VFORMAT_AV1:
+			s = snprintf(pbuf, size - tsize, "        \"DoubleWrite\" ");
+			tsize += s;
+			pbuf += s;
+			if ((get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T7) &&
+				(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T3)) {
+				s = snprintf(pbuf, size - tsize, "[ \"0\", \"1\", \"2\", \"3\", \"4\", \"0x10\", \"0x10000\", \"0x20000\"]\n");
+				tsize += s;
+				pbuf += s;
+			}
+			else {
+				s = snprintf(pbuf, size - tsize, "[ \"0\", \"1\", \"2\", \"3\", \"4\", \"8\", \"0x10\", \"0x10000\", \"0x20000\"]\n");
+				tsize += s;
+				pbuf += s;
+			}
+			break;
+		default:
+			break;
+	}
+
+	return pbuf - buf;
+}
+
+static int vcodec_feature_vdec_fence(u8 *buf, int size, int vformat)
+{
+	u8 *pbuf = buf;
+
+	switch (vformat) {
+		case VFORMAT_H264:
+		case VFORMAT_HEVC:
+		case VFORMAT_VP9:
+			if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM)
+				pbuf += snprintf(pbuf, size, "        \"GameMode\" : \"true\"\n");
+			break;
+		default:
+			break;
+	}
+
+	return pbuf - buf;
+}
+
+static int vcodec_feature_bitdepth(u8 *buf, int size, int vformat)
+{
+	u8 *pbuf = buf;
+
+	switch (vformat) {
+		case VFORMAT_HEVC:
+		case VFORMAT_VP9:
+		case VFORMAT_AVS2:
+		case VFORMAT_AV1:
+			if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXBB)
+				pbuf += snprintf(pbuf, size, "        \"BitDepth\" : \"10\"\n");
+			else
+				pbuf += snprintf(pbuf, size, "        \"BitDepth\" : \"8\"\n");
+			break;
+		default:
+			break;
+	}
+
+	return pbuf - buf;
+}
+
+
+static int vcodec_feature_MaxResolution(u8 *buf, int size, int vformat)
+{
+	u8 *pbuf = buf;
+
+	switch (vformat) {
+		case VFORMAT_HEVC:
+		case VFORMAT_VP9:
+		case VFORMAT_AVS2:
+		case VFORMAT_AV1:
+			if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+				(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5D))
+				pbuf += snprintf(pbuf, size, "        \"MaximumResolution\" : \"8k\"\n");
+			else if (vdec_is_support_4k() &&
+					(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5D))
+				pbuf += snprintf(pbuf, size, "        \"MaximumResolution\" : \"4k60\"\n");
+			else
+				pbuf += snprintf(pbuf, size, "        \"MaximumResolution\" : \"1080p60\"\n");
+			break;
+		case VFORMAT_H264:
+			if (vdec_is_support_4k())
+				pbuf += snprintf(pbuf, size, "        \"MaximumResolution\" : \"4k30\"\n");
+			else
+				pbuf += snprintf(pbuf, size, "        \"MaximumResolution\" : \"1080p60\"\n");
+			break;
+		case VFORMAT_MPEG12:
+		case VFORMAT_MPEG4:
+		case VFORMAT_MJPEG:
+		case VFORMAT_VC1:
+		case VFORMAT_AVS:
+			pbuf += snprintf(pbuf, size, "        \"MaximumResolution\" : \"1080p60\"\n");
+			break;
+		default:
+			break;
+	}
+
+	return pbuf - buf;
+}
+
+static int vcodec_feature_clock(u8 *buf, int size, int vformat)
+{
+	u8 *pbuf = buf;
+
+	switch (vformat) {
+		case VFORMAT_HEVC:
+		case VFORMAT_VP9:
+		case VFORMAT_AVS2:
+		case VFORMAT_AV1:
+			if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12B) &&
+				(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXLX2) &&
+				(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5) &&
+				(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5D))
+				pbuf += snprintf(pbuf, size, "        \"ClockFrequency\" : \"800MHZ\"\n");
+			else
+				pbuf += snprintf(pbuf, size, "        \"ClockFrequency\" : \"667MHZ\"\n");
+			break;
+		case VFORMAT_H264:
+		case VFORMAT_MPEG12:
+		case VFORMAT_MPEG4:
+		case VFORMAT_MJPEG:
+		case VFORMAT_VC1:
+		case VFORMAT_AVS:
+			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_GXLX2) &&
+				(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5) &&
+				(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5D))
+				pbuf += snprintf(pbuf, size, "        \"ClockFrequency\" : \"800MHZ\"\n");
+			else
+				pbuf += snprintf(pbuf, size, "        \"ClockFrequency\" : \"667MHZ\"\n");
+			break;
+		default:
+			break;
+	}
+
+	return pbuf - buf;
+}
+
+static int vcodec_feature_support_format(int vformat)
+{
+
+	switch (vformat) {
+		case VFORMAT_VP9:
+			if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) &&
+				(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5))
+				return 1;
+			else
+				return 0;
+		case VFORMAT_AVS2:
+			if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) &&
+				(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5D))
+				return 1;
+			else
+				return 0;
+		case VFORMAT_AV1:
+			if (((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_TM2) &&
+					is_cpu_tm2_revb()) ||
+				((get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_TM2) &&
+				(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5)))
+				return 1;
+			else
+				return 0;
+		case VFORMAT_AVS:
+			if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXM))
+				return 1;
+			else
+				return 0;
+		case VFORMAT_MJPEG:
+		case VFORMAT_VC1:
+		case VFORMAT_MPEG4:
+		case VFORMAT_MPEG12:
+		case VFORMAT_H264:
+		case VFORMAT_HEVC:
+			return 1;
+		default:
+			break;
+	}
+
+	return 0;
+}
+
+static int vcodec_feature_FCC(u8 *buf, int size, int vformat, int is_v4l)
+{
+	u8 *pbuf = buf;
+
+	if (!is_v4l) {
+		switch (vformat) {
+			case VFORMAT_HEVC:
+			case VFORMAT_H264:
+			case VFORMAT_MPEG12:
+				pbuf += snprintf(pbuf, size, "        \"Decoder FCC support\" : \"true\"\n");
+				break;
+			default:
+				break;
+		}
+	}
+
+	return pbuf - buf;
+}
+
+static int vcodec_feature_RDMA(u8 *buf, int size, int vformat)
+{
+	u8 *pbuf = buf;
+
+	if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T3)
+		pbuf += snprintf(pbuf, size, "        \"Decoder RDMA support\" : \"true\"\n");
+
+	return pbuf - buf;
+}
+
+static int vcodec_feature_v4ldec_nr(u8 *buf, int size, int vformat, int is_v4l)
+{
+	u8 *pbuf = buf;
+
+	if (is_v4l) {
+		pbuf += snprintf(pbuf, size, "        \"V4ldec nr\" : \"true\"\n");
+	}
+
+	return pbuf - buf;
+}
+
+static int vcodec_feature_ge2d_wrapper(u8 *buf, int size, int vformat, int is_v4l)
+{
+	u8 *pbuf = buf;
+
+	if (is_v4l && (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7)) {
+		pbuf += snprintf(pbuf, size, "        \"Ge2d wrapper\" : \"true\"\n");
+	}
+
+	return pbuf - buf;
+}
+
+
+
+int vcodec_feature_get_feature(u8 *buf, int vformat, int is_v4l)
+{
+	u8 *pbuf = buf;
+	int size = PAGE_SIZE;
+	int tsize = 0;
+	int s;
+
+	s = snprintf(pbuf, size - tsize, "    \"%s%s\": ", format_name[vformat], is_v4l ? "_v4l" : "");
+	tsize += s;
+	pbuf += s;
+
+	s = snprintf(pbuf, size - tsize, "{\n");
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_CC(pbuf, size - tsize, vformat, is_v4l);
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_report_information(pbuf, size - tsize, vformat, is_v4l);
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_vdec_fence(pbuf, size - tsize, vformat);
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_i_only_mode(pbuf, size - tsize, vformat);
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_dolbyVison(pbuf, size - tsize, vformat);
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_HDR(pbuf, size - tsize, vformat);
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_doublewrite(pbuf, size - tsize, vformat);
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_bitdepth(pbuf, size - tsize, vformat);
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_MaxResolution(pbuf, size - tsize, vformat);
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_clock(pbuf, size - tsize, vformat);
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_FCC(pbuf, size - tsize, vformat, is_v4l);
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_RDMA(pbuf, size - tsize, vformat);
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_v4ldec_nr(pbuf, size - tsize, vformat, is_v4l);
+	tsize += s;
+	pbuf += s;
+
+	s = vcodec_feature_ge2d_wrapper(pbuf, size - tsize, vformat, is_v4l);
+	tsize += s;
+	pbuf += s;
+
+	s = snprintf(pbuf, size - tsize, "        \"UcodeVersionRequest\" : \"0.3.10\"\n");
+	tsize += s;
+	pbuf += s;
+
+	s = snprintf(pbuf, size - tsize, "    }\n");
+	tsize += s;
+	pbuf += s;
+
+	return pbuf - buf;
+}
+
+
+ssize_t vcodec_feature_read(char *buf)
+{
+	static int read_count;
+	char *pbuf = buf;
+
+	if (jiffies - last_time > 5 * HZ) {
+		read_count = 0;
+		/*timeout :not continue dump,dump from first. */
+	}
+
+	if (vcodec_feature_idx > 0) {
+		if (read_count == 0)
+			pbuf += snprintf(pbuf, PAGE_SIZE - (pbuf - buf), "{\n");
+		pbuf += vcodec_feature_get_feature(pbuf, feature[read_count].format, feature[read_count].is_v4l);
+		read_count++;
+		if (read_count >= vcodec_feature_idx) {
+			read_count = 0;
+			pbuf += snprintf(pbuf, PAGE_SIZE - (pbuf - buf), "}");
+		}
+	}
+	last_time = jiffies;
+	return pbuf - buf;
+}
+EXPORT_SYMBOL(vcodec_feature_read);
+
+
+int vcodec_feature_register(int vformat, int is_v4l)
+{
+	if ((vcodec_feature_idx < SUPPORT_VDEC_NUM) && vcodec_feature_support_format(vformat)) {
+		feature[vcodec_feature_idx].format = vformat;
+		feature[vcodec_feature_idx].is_v4l = is_v4l;
+		vcodec_feature_idx++;
+		//pr_debug("regist %s codec profile\n", vdec_profile->name);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(vcodec_feature_register);
+
+
+
diff --git a/drivers/frame_provider/decoder/real/vreal.h b/drivers/frame_provider/decoder/utils/vdec_feature.h
similarity index 63%
copy from drivers/frame_provider/decoder/real/vreal.h
copy to drivers/frame_provider/decoder/utils/vdec_feature.h
index 734cc6f..a2918fd 100644
--- a/drivers/frame_provider/decoder/real/vreal.h
+++ b/drivers/frame_provider/decoder/utils/vdec_feature.h
@@ -1,7 +1,7 @@
 /*
- * drivers/amlogic/amports/vreal.h
+ * drivers/amlogic/amports/vdec_profile.h
  *
- * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * 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
@@ -13,14 +13,15 @@
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  *
- */
+*/
 
-#ifndef VREAL_H
-#define VREAL_H
+#ifndef VDEC_FEATURE_H
+#define VDEC_FEATURE_H
 
-#if 1				/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
-/* TODO: move to register headers */
-#define VPP_VD1_POSTBLEND           (1 << 10)
-#endif
+int vcodec_feature_register(int vformat, int is_v4l);
 
-#endif				/* VREAL_H */
+ssize_t vcodec_feature_read(char *buf);
+
+
+
+#endif /* VDEC_FEATURE_H */
diff --git a/drivers/frame_provider/decoder/utils/vdec_ge2d_utils.c b/drivers/frame_provider/decoder/utils/vdec_ge2d_utils.c
new file mode 100644
index 0000000..08cd0d7
--- /dev/null
+++ b/drivers/frame_provider/decoder/utils/vdec_ge2d_utils.c
@@ -0,0 +1,487 @@
+/*
+ * 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/slab.h>
+#include <linux/module.h>
+#include <linux/amlogic/media/ge2d/ge2d.h>
+#include <linux/amlogic/media/canvas/canvas_mgr.h>
+#include "vdec.h"
+#include "vdec_ge2d_utils.h"
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+
+static u32 vdec_ge2d_debug = 0;
+
+#ifndef  CONFIG_AMLOGIC_MEDIA_GE2D
+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
+
+enum videocom_source_type {
+	DECODER_8BIT_NORMAL = 0,
+	DECODER_8BIT_BOTTOM,
+	DECODER_8BIT_TOP,
+	DECODER_10BIT_NORMAL,
+	DECODER_10BIT_BOTTOM,
+	DECODER_10BIT_TOP
+};
+
+static void vdec_canvas_cache_free(struct vdec_canvas_cache *canche)
+{
+	int i = -1;
+
+	for (i = 0; i < ARRAY_SIZE(canche->res); i++) {
+		if (canche->res[i].cid > 0) {
+			if (vdec_ge2d_debug)
+				pr_info("canvas-free, name:%s, canvas id:%d\n",
+					canche->res[i].name,
+					canche->res[i].cid);
+
+			canvas_pool_map_free_canvas(canche->res[i].cid);
+
+			canche->res[i].cid = 0;
+		}
+	}
+}
+
+static void vdec_canvas_cache_put(struct vdec_ge2d *ge2d)
+{
+	struct vdec_canvas_cache *canche = &ge2d->canche;
+
+	mutex_lock(&canche->lock);
+
+	pr_info("canvas-put, ref:%d\n", canche->ref);
+
+	canche->ref--;
+
+	if (canche->ref == 0) {
+		vdec_canvas_cache_free(canche);
+	}
+
+	mutex_unlock(&canche->lock);
+}
+
+static int vdec_canvas_cache_get(struct vdec_ge2d *ge2d, char *usr)
+{
+	struct vdec_canvas_cache *canche = &ge2d->canche;
+	int i;
+
+	mutex_lock(&canche->lock);
+
+	canche->ref++;
+
+	for (i = 0; i < ARRAY_SIZE(canche->res); i++) {
+		if (canche->res[i].cid <= 0) {
+			snprintf(canche->res[i].name, 32, "%s-%d", usr, i);
+			canche->res[i].cid =
+				canvas_pool_map_alloc_canvas(canche->res[i].name);
+		}
+
+		if (vdec_ge2d_debug)
+			pr_info("canvas-alloc, name:%s, canvas id:%d\n",
+				canche->res[i].name,
+				canche->res[i].cid);
+
+		if (canche->res[i].cid <= 0) {
+			pr_err("canvas-fail, name:%s, canvas id:%d.\n",
+				canche->res[i].name,
+				canche->res[i].cid);
+
+			mutex_unlock(&canche->lock);
+			goto err;
+		}
+	}
+
+	if (vdec_ge2d_debug)
+		pr_info("canvas-get, ref:%d\n", canche->ref);
+
+	mutex_unlock(&canche->lock);
+	return 0;
+err:
+	vdec_canvas_cache_put(ge2d);
+	return -1;
+}
+
+static int vdec_canvas_cache_init(struct vdec_ge2d *ge2d)
+{
+	ge2d->canche.ref = 0;
+	mutex_init(&ge2d->canche.lock);
+
+	pr_info("canvas-init, ref:%d\n", ge2d->canche.ref);
+
+	return 0;
+}
+
+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;
+}
+
+int vdec_ge2d_init(struct vdec_ge2d** ge2d_handle, int mode)
+{
+	int ret;
+	struct vdec_ge2d *ge2d;
+
+	if (!ge2d_handle)
+		return -EINVAL;
+
+	ge2d = kzalloc(sizeof(*ge2d), GFP_KERNEL);
+	if (!ge2d)
+		return -ENOMEM;
+
+	vdec_canvas_cache_init(ge2d);
+
+	ge2d->work_mode = mode;
+	if (!ge2d->work_mode) {
+		ge2d->work_mode = GE2D_MODE_CONVERT_LE;
+	}
+	pr_info("vdec_ge2d_init work_mode:%d\n", ge2d->work_mode);
+
+	ge2d->ge2d_context = create_ge2d_work_queue();
+	if (!ge2d->ge2d_context) {
+		pr_err("ge2d_create_instance fail\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	if (vdec_canvas_cache_get(ge2d, "vdec-ge2d-dec") < 0) {
+		pr_err("canvas pool alloc fail. src(%d, %d, %d) dst(%d, %d, %d).\n",
+			ge2d->canche.res[0].cid,
+			ge2d->canche.res[1].cid,
+			ge2d->canche.res[2].cid,
+			ge2d->canche.res[3].cid,
+			ge2d->canche.res[4].cid,
+			ge2d->canche.res[5].cid);
+		ret = -ENOMEM;
+		goto error1;
+	}
+
+	*ge2d_handle = ge2d;
+
+	return 0;
+error1:
+	destroy_ge2d_work_queue(ge2d->ge2d_context);
+error:
+	kfree(ge2d);
+
+	return ret;
+}
+EXPORT_SYMBOL(vdec_ge2d_init);
+
+int vdec_ge2d_copy_data(struct vdec_ge2d *ge2d, struct vdec_ge2d_info *ge2d_info)
+{
+	struct config_para_ex_s ge2d_config;
+	u32 src_fmt = 0, dst_fmt = 0;
+	struct canvas_s cd;
+
+	if (!ge2d)
+		return -1;
+
+	if (vdec_ge2d_debug)
+		pr_info("vdec_ge2d_copy_data start\n");
+
+	memset(&ge2d_config, 0, sizeof(ge2d_config));
+
+	src_fmt = get_input_format(ge2d_info->dst_vf);
+	if (ge2d_info->src_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(ge2d_info->dst_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) {
+		ge2d_info->dst_vf->type |= VIDTYPE_VIU_NV12;
+		ge2d_info->dst_vf->type &= ~VIDTYPE_VIU_NV21;
+	} else if ((dst_fmt & GE2D_COLOR_MAP_MASK) == GE2D_COLOR_MAP_NV21) {
+		ge2d_info->dst_vf->type |= VIDTYPE_VIU_NV21;
+		ge2d_info->dst_vf->type &= ~VIDTYPE_VIU_NV12;
+	}
+	if ((dst_fmt & GE2D_ENDIAN_MASK) == GE2D_LITTLE_ENDIAN) {
+		ge2d_info->dst_vf->canvas0_config[0].endian = 0;
+		ge2d_info->dst_vf->canvas0_config[1].endian = 0;
+		ge2d_info->dst_vf->canvas0_config[2].endian = 0;
+	} else if ((dst_fmt & GE2D_ENDIAN_MASK) == GE2D_BIG_ENDIAN){
+		ge2d_info->dst_vf->canvas0_config[0].endian = 7;
+		ge2d_info->dst_vf->canvas0_config[1].endian = 7;
+		ge2d_info->dst_vf->canvas0_config[2].endian = 7;
+	}
+
+	ge2d_info->dst_vf->mem_sec = ge2d_info->dst_vf->flag & VFRAME_FLAG_VIDEO_SECURE ? 1 : 0;
+
+	mutex_lock(&ge2d->canche.lock);
+
+	/* src canvas configure. */
+	if ((ge2d_info->dst_vf->canvas0Addr == 0) ||
+		(ge2d_info->dst_vf->canvas0Addr == (u32)-1)) {
+		canvas_config_config(ge2d->canche.res[0].cid, &ge2d_info->src_canvas0_config[0]);
+		canvas_config_config(ge2d->canche.res[1].cid, &ge2d_info->src_canvas0_config[1]);
+		canvas_config_config(ge2d->canche.res[2].cid, &ge2d_info->src_canvas0_config[2]);
+		ge2d_config.src_para.canvas_index =
+			ge2d->canche.res[0].cid |
+			ge2d->canche.res[1].cid << 8 |
+			ge2d->canche.res[2].cid << 16;
+
+		ge2d_config.src_planes[0].addr =
+			ge2d_info->src_canvas0_config[0].phy_addr;
+		ge2d_config.src_planes[0].w =
+			ge2d_info->src_canvas0_config[0].width;
+		ge2d_config.src_planes[0].h =
+			ge2d_info->src_canvas0_config[0].height;
+		ge2d_config.src_planes[1].addr =
+			ge2d_info->src_canvas0_config[1].phy_addr;
+		ge2d_config.src_planes[1].w =
+			ge2d_info->src_canvas0_config[1].width;
+		ge2d_config.src_planes[1].h =
+			ge2d_info->src_canvas0_config[1].height;
+		ge2d_config.src_planes[2].addr =
+			ge2d_info->src_canvas0_config[2].phy_addr;
+		ge2d_config.src_planes[2].w =
+			ge2d_info->src_canvas0_config[2].width;
+		ge2d_config.src_planes[2].h =
+			ge2d_info->src_canvas0_config[2].height;
+	} else {
+		ge2d_config.src_para.canvas_index = ge2d_info->src_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	= ge2d_info->dst_vf->width;
+	if (ge2d_info->dst_vf->type & VIDTYPE_INTERLACE)
+		ge2d_config.src_para.height = ge2d_info->dst_vf->height >> 1;
+	else
+		ge2d_config.src_para.height = ge2d_info->dst_vf->height;
+
+	/* dst canvas configure. */
+	canvas_config_config(ge2d->canche.res[3].cid, &ge2d_info->dst_vf->canvas0_config[0]);
+	if ((ge2d_config.src_para.format & 0xfffff) == GE2D_FORMAT_M24_YUV420) {
+		ge2d_info->dst_vf->canvas0_config[1].width <<= 1;
+	}
+	canvas_config_config(ge2d->canche.res[4].cid, &ge2d_info->dst_vf->canvas0_config[1]);
+	canvas_config_config(ge2d->canche.res[5].cid, &ge2d_info->dst_vf->canvas0_config[2]);
+	ge2d_config.dst_para.canvas_index =
+		ge2d->canche.res[3].cid |
+		ge2d->canche.res[4].cid << 8;
+	canvas_read(ge2d->canche.res[3].cid, &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->canche.res[4].cid, &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	= ge2d_info->dst_vf->width;
+	ge2d_config.dst_para.height	= ge2d_info->dst_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;
+	ge2d_config.mem_sec	= ge2d_info->dst_vf->flag & VFRAME_FLAG_VIDEO_SECURE ? 1 : 0;
+
+	if (ge2d_context_config_ex(ge2d->ge2d_context, &ge2d_config) < 0) {
+		pr_err("vdec_ge2d_context_config_ex error.\n");
+		mutex_unlock(&ge2d->canche.lock);
+		return -1;
+	}
+
+	if (!(ge2d_info->dst_vf->type & VIDTYPE_V4L_EOS)) {
+		if (ge2d_info->dst_vf->type & VIDTYPE_INTERLACE) {
+			stretchblt_noalpha(ge2d->ge2d_context,
+				0, 0, ge2d_info->dst_vf->width, ge2d_info->dst_vf->height / 2,
+				0, 0, ge2d_info->dst_vf->width, ge2d_info->dst_vf->height);
+		} else {
+			stretchblt_noalpha(ge2d->ge2d_context,
+				0, 0, ge2d_info->dst_vf->width, ge2d_info->dst_vf->height,
+				0, 0, ge2d_info->dst_vf->width, ge2d_info->dst_vf->height);
+		}
+	}
+	mutex_unlock(&ge2d->canche.lock);
+	if (vdec_ge2d_debug)
+		pr_info("vdec_ge2d_copy_data done\n");
+
+	return 0;
+}
+EXPORT_SYMBOL(vdec_ge2d_copy_data);
+
+int vdec_ge2d_destroy(struct vdec_ge2d *ge2d)
+{
+	if (!ge2d)
+		return -1;
+
+	pr_info("vdec ge2d destroy begin\n");
+
+	destroy_ge2d_work_queue(ge2d->ge2d_context);
+	vdec_canvas_cache_put(ge2d);
+	kfree(ge2d);
+
+	pr_info("vdec ge2d destroy done\n");
+
+	return 0;
+}
+EXPORT_SYMBOL(vdec_ge2d_destroy);
+
+module_param(vdec_ge2d_debug, int, 0664);
+MODULE_PARM_DESC(vdec_ge2d_debug, "\n vdec_ge2d_debug\n");
diff --git a/drivers/frame_provider/decoder/utils/vdec_ge2d_utils.h b/drivers/frame_provider/decoder/utils/vdec_ge2d_utils.h
new file mode 100644
index 0000000..31018f7
--- /dev/null
+++ b/drivers/frame_provider/decoder/utils/vdec_ge2d_utils.h
@@ -0,0 +1,69 @@
+/*
+ * 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 __GE2D_UTILS_H__
+#define __GE2D_UTILS_H__
+
+//#include "../../../amvdec_ports/aml_vcodec_drv.h"
+#include <linux/amlogic/media/vfm/vframe.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)
+
+struct vdec_canvas_res {
+	int	cid;
+	u8	name[32];
+};
+
+struct vdec_canvas_cache {
+	int	ref;
+	struct vdec_canvas_res	res[6];
+	struct mutex		lock;
+};
+
+struct vdec_ge2d {
+	u32	work_mode; /* enum ge2d_work_mode */
+	struct ge2d_context_s	*ge2d_context; /* handle of GE2D */
+	struct aml_vcodec_ctx	*ctx;
+	struct vdec_canvas_cache	canche;
+	void *hw;
+};
+
+struct vdec_ge2d_info {
+	struct vframe_s *dst_vf;
+	u32 src_canvas0Addr;
+	u32 src_canvas1Addr;;
+	struct canvas_config_s src_canvas0_config[3];
+	struct canvas_config_s src_canvas1_config[3];
+};
+
+int vdec_ge2d_init(struct vdec_ge2d** ge2d_handle, int mode);
+
+int vdec_ge2d_copy_data(struct vdec_ge2d *ge2d, struct vdec_ge2d_info *ge2d_info);
+
+int vdec_ge2d_destroy(struct vdec_ge2d *ge2d);
+
+#endif
+
diff --git a/drivers/frame_provider/decoder/utils/vdec_input.c b/drivers/frame_provider/decoder/utils/vdec_input.c
index 5deb374..6fec0ad 100644
--- a/drivers/frame_provider/decoder/utils/vdec_input.c
+++ b/drivers/frame_provider/decoder/utils/vdec_input.c
@@ -20,15 +20,12 @@
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
-
 #include "../../../stream_input/amports/amports_priv.h"
 #include "vdec.h"
 #include "vdec_input.h"
-
 #include <asm/cacheflush.h>
 #include <linux/crc32.h>
 
-
 #define VFRAME_BLOCK_SIZE (512 * SZ_1K)/*512 for 1080p default init.*/
 #define VFRAME_BLOCK_SIZE_4K (2 * SZ_1M) /*2M for 4K default.*/
 #define VFRAME_BLOCK_SIZE_MAX (4 * SZ_1M)
@@ -64,7 +61,7 @@
 {
 	int ret =0;
 
-	if (likely(access_ok(VERIFY_READ, from, n)))
+	if (likely(access_ok(from, n)))
 		ret = copy_from_user(to, from, n);
 	else
 		memcpy(to, from, n);
@@ -348,6 +345,7 @@
 	char sbuf[512];
 	int tsize = 0;
 	int s;
+
 	if (!pbuf) {
 		pbuf = sbuf;
 		size = 512;
@@ -434,6 +432,7 @@
 		s += vdec_input_dump_block_locked(block, lbuf, size - s);
 	}
 	vdec_input_unlock(input, flags);
+
 	return s;
 }
 
@@ -446,6 +445,7 @@
 	char sbuf[512];
 	int tsize = 0;
 	int s;
+
 	if (!pbuf) {
 		pbuf = sbuf;
 		size = 512;
@@ -492,6 +492,7 @@
 
 	if (size <= 0)
 		return 0;
+
 	if (!bufs)
 		lbuf = sbuf;
 	s = snprintf(lbuf + s, size - s,
@@ -522,6 +523,7 @@
 			break;
 	}
 	vdec_input_unlock(input, flags);
+
 	return s;
 }
 
@@ -549,6 +551,7 @@
 
 	if (input->swap_page_phys == 0)
 		return -ENOMEM;
+
 	return 0;
 }
 EXPORT_SYMBOL(vdec_input_set_buffer);
@@ -788,6 +791,7 @@
 	struct vframe_chunk_s *chunk;
 	struct vdec_s *vdec = input->vdec;
 	struct vframe_block_list_s *block;
+
 	int need_pading_size = MIN_FRAME_PADDING_SIZE;
 
 	if (vdec_secure(vdec)) {
@@ -1212,5 +1216,3 @@
 	return handle;
 }
 EXPORT_SYMBOL(vdec_input_get_freed_handle);
-
-
diff --git a/drivers/frame_provider/decoder/utils/vdec_power_ctrl.c b/drivers/frame_provider/decoder/utils/vdec_power_ctrl.c
index 9057a80..e43c45a 100644
--- a/drivers/frame_provider/decoder/utils/vdec_power_ctrl.c
+++ b/drivers/frame_provider/decoder/utils/vdec_power_ctrl.c
@@ -19,8 +19,10 @@
 #include "vdec_power_ctrl.h"
 #include <linux/amlogic/media/utils/vdec_reg.h>
 #include <linux/amlogic/power_ctrl.h>
+//#include <dt-bindings/power/sc2-pd.h>
+//#include <linux/amlogic/pwr_ctrl.h>
+#include <linux/amlogic/power_domain.h>
 #include <dt-bindings/power/sc2-pd.h>
-#include <linux/amlogic/pwr_ctrl.h>
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
 #include "../../../common/media_clock/switch/amports_gate.h"
 #include "../../../common/chips/decoder_cpu_ver_info.h"
@@ -29,6 +31,12 @@
 #define HEVC_TEST_LIMIT		(100)
 #define GXBB_REV_A_MINOR	(0xa)
 
+#define PDID_DSP            0
+#define PDID_DOS_HCODEC             1
+#define PDID_DOS_HEVC               2
+#define PDID_DOS_VDEC               3
+#define PDID_DOS_WAVE               4
+
 extern int no_powerdown;
 extern int hevc_max_reset_count;
 
@@ -136,14 +144,20 @@
 		hcodec_clock_enable();
 	} else if (id == VDEC_HEVC) {
 		/* enable hevc clock */
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2)
+		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))
 			amports_switch_gate("clk_hevcf_mux", 1);
 		else
 			amports_switch_gate("clk_hevc_mux", 1);
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
+		if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) &&
+			!is_hevc_front_back_clk_combined())
 			amports_switch_gate("clk_hevcb_mux", 1);
+
 		hevc_clock_hi_enable();
-		hevc_back_clock_hi_enable();
+
+		if (!is_hevc_front_back_clk_combined())
+			hevc_back_clock_hi_enable();
 	}
 }
 
@@ -156,7 +170,8 @@
 	} else if (id == VDEC_HEVC) {
 		/* disable hevc clock */
 		hevc_clock_off();
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
+		if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) &&
+			!is_hevc_front_back_clk_combined())
 			hevc_back_clock_off();
 	}
 }
@@ -693,7 +708,6 @@
 
 	pm_vdec_clock_on(id);
 	pwr_ctrl_psci_smc(pd_id, PWR_ON);
-
 }
 
 static void pm_vdec_pd_sec_api_power_off(struct device *dev, int id)
@@ -720,7 +734,7 @@
 #if 0
 	int pd_id = (id == VDEC_1) ? PM_DOS_VDEC :
 		    (id == VDEC_HEVC) ? PM_DOS_HEVC :
-		    PM_DOS_HCODEC;
+			PM_DOS_HCODEC;
 
 	pm_vdec_clock_on(id);
 	power_domain_switch(pd_id, PWR_ON);
diff --git a/drivers/frame_provider/decoder/utils/vdec_power_ctrl.h b/drivers/frame_provider/decoder/utils/vdec_power_ctrl.h
index 53545f8..e7ab77e 100644
--- a/drivers/frame_provider/decoder/utils/vdec_power_ctrl.h
+++ b/drivers/frame_provider/decoder/utils/vdec_power_ctrl.h
@@ -90,10 +90,10 @@
 #define DL_FLAG_RPM_ACTIVE		BIT(3)
 #define DL_FLAG_AUTOREMOVE_SUPPLIER	BIT(4)
 
-//struct device_link {
-//	u32 flags;
-//	/* ... */
-//};
+struct device_link {
+	u32 flags;
+	/* ... */
+};
 
 static inline struct device *dev_pm_domain_attach_by_name(struct device *dev,
 							  const char *name)
diff --git a/drivers/frame_provider/decoder/utils/vdec_profile.c b/drivers/frame_provider/decoder/utils/vdec_profile.c
index 94f8b8f..dfffeb1 100644
--- a/drivers/frame_provider/decoder/utils/vdec_profile.c
+++ b/drivers/frame_provider/decoder/utils/vdec_profile.c
@@ -20,14 +20,12 @@
 #include <linux/types.h>
 #include <linux/debugfs.h>
 #include <linux/moduleparam.h>
-
-
+#include <linux/sched/clock.h>
 #include <linux/amlogic/media/utils/vdec_reg.h>
 #include <trace/events/meson_atrace.h>
 #include "vdec_profile.h"
 #include "vdec.h"
 
-
 #define ISA_TIMERE 0x2662
 #define ISA_TIMERE_HI 0x2663
 
@@ -112,11 +110,7 @@
 
 static u64 get_us_time_system(void)
 {
-	struct timeval tv;
-
-	do_gettimeofday(&tv);
-
-	return div64_u64(timeval_to_ns(&tv), 1000);
+	return div64_u64(local_clock(), 1000);
 }
 
 static void vdec_profile_update_alloc_time(
diff --git a/drivers/frame_provider/decoder/utils/vdec_sync.c b/drivers/frame_provider/decoder/utils/vdec_sync.c
index 314a4f0..b4192f6 100644
--- a/drivers/frame_provider/decoder/utils/vdec_sync.c
+++ b/drivers/frame_provider/decoder/utils/vdec_sync.c
@@ -21,15 +21,24 @@
 #include <linux/fs.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
+#include <linux/sched/clock.h>
 #include <linux/sync_file.h>
 #include "vdec_sync.h"
 
 #define VDEC_DBG_ENABLE_FENCE	(0x100)
+#define VDEC_SYNC_COUNT 32
 
-extern u32 debug;
+struct vdec_sync_core_s {
+	struct vdec_sync s_vdec_sync[VDEC_SYNC_COUNT];
+	spinlock_t vdec_sync_lock;
+};
 
-static const struct fence_ops timeline_fence_ops;
-static inline struct sync_pt *fence_to_sync_pt(struct fence *fence)
+static struct vdec_sync_core_s vdec_sync_core;
+
+extern u32 vdec_get_debug(void);
+
+static const struct dma_fence_ops timeline_fence_ops;
+static inline struct sync_pt *fence_to_sync_pt(struct dma_fence *fence)
 {
 	if (fence->ops != &timeline_fence_ops)
 		return NULL;
@@ -52,7 +61,7 @@
 		return NULL;
 
 	kref_init(&obj->kref);
-	obj->context = fence_context_alloc(1);
+	obj->context = dma_fence_context_alloc(1);
 	obj->timestamp = local_clock();
 	strlcpy(obj->name, name, sizeof(obj->name));
 	INIT_LIST_HEAD(&obj->active_list_head);
@@ -66,9 +75,12 @@
 {
 	struct sync_timeline *obj =
 		container_of(kref, struct sync_timeline, kref);
+	struct vdec_sync *sync = obj->parent_sync;
 
 	pr_info("[VDEC-FENCE] free timeline: %lx\n", (ulong) obj);
 	kfree(obj);
+	atomic_set(&sync->use_flag, 0);
+	sync->timeline = NULL;
 }
 
 static void sync_timeline_get(struct sync_timeline *obj)
@@ -81,21 +93,21 @@
 	kref_put(&obj->kref, sync_timeline_free);
 }
 
-static const char *timeline_fence_get_driver_name(struct fence *fence)
+static const char *timeline_fence_get_driver_name(struct dma_fence *fence)
 {
 	struct sync_timeline *parent = fence_parent(fence);
 
 	return parent->name;
 }
 
-static const char *timeline_fence_get_timeline_name(struct fence *fence)
+static const char *timeline_fence_get_timeline_name(struct dma_fence *fence)
 {
 	struct sync_timeline *parent = fence_parent(fence);
 
 	return parent->name;
 }
 
-static void timeline_fence_release(struct fence *fence)
+static void timeline_fence_release(struct dma_fence *fence)
 {
 	struct sync_pt *pt = fence_to_sync_pt(fence);
 	struct sync_timeline *parent = fence_parent(fence);
@@ -109,15 +121,15 @@
 		list_del(&pt->active_list);
 	spin_unlock_irqrestore(fence->lock, flags);
 	sync_timeline_put(parent);
-	fence_free(fence);
+	dma_fence_free(fence);
 }
 
-static bool timeline_fence_signaled(struct fence *fence)
+static bool timeline_fence_signaled(struct dma_fence *fence)
 {
 	struct sync_timeline *parent = fence_parent(fence);
 	struct sync_pt *pt = get_sync_pt(fence);
 
-	if (__fence_is_later(fence->seqno, parent->value))
+	if (__dma_fence_is_later(fence->seqno, parent->value, fence->ops))
 		return false;
 
 	if (pt->timestamp > parent->timestamp)
@@ -126,7 +138,7 @@
 	return true;
 }
 
-static bool timeline_fence_enable_signaling(struct fence *fence)
+static bool timeline_fence_enable_signaling(struct dma_fence *fence)
 {
 	struct sync_pt *pt = container_of(fence, struct sync_pt, fence);
 	struct sync_timeline *parent = fence_parent(fence);
@@ -138,20 +150,22 @@
 	return true;
 }
 
-static void timeline_fence_disable_signaling(struct fence *fence)
+#if 0
+static void timeline_fence_disable_signaling(struct dma_fence *fence)
 {
 	struct sync_pt *pt = container_of(fence, struct sync_pt, fence);
 
 	list_del_init(&pt->active_list);
 }
+#endif
 
-static void timeline_fence_value_str(struct fence *fence,
+static void timeline_fence_value_str(struct dma_fence *fence,
 				    char *str, int size)
 {
-	snprintf(str, size, "%d", fence->seqno);
+	snprintf(str, size, "%llu", fence->seqno);
 }
 
-static void timeline_fence_timeline_value_str(struct fence *fence,
+static void timeline_fence_timeline_value_str(struct dma_fence *fence,
 					     char *str, int size)
 {
 	struct sync_timeline *parent = fence_parent(fence);
@@ -159,13 +173,13 @@
 	snprintf(str, size, "%d", parent->value);
 }
 
-static const struct fence_ops timeline_fence_ops = {
+static const struct dma_fence_ops timeline_fence_ops = {
 	.get_driver_name	= timeline_fence_get_driver_name,
 	.get_timeline_name	= timeline_fence_get_timeline_name,
 	.enable_signaling	= timeline_fence_enable_signaling,
-	.disable_signaling	= timeline_fence_disable_signaling,
+	//.disable_signaling	= timeline_fence_disable_signaling,
 	.signaled		= timeline_fence_signaled,
-	.wait			= fence_default_wait,
+	.wait			= dma_fence_default_wait,
 	.release		= timeline_fence_release,
 	.fence_value_str	= timeline_fence_value_str,
 	.timeline_value_str	= timeline_fence_timeline_value_str,
@@ -188,7 +202,7 @@
 	obj->value += inc;
 	list_for_each_entry_safe(pt, next, &obj->active_list_head,
 				 active_list) {
-		if (fence_is_signaled(&pt->fence))
+		if (dma_fence_is_signaled_locked(&pt->fence))
 			list_del_init(&pt->active_list);
 	}
 	spin_unlock_irqrestore(&obj->lock, flags);
@@ -215,7 +229,7 @@
 		return NULL;
 	spin_lock_irqsave(&obj->lock, flags);
 	sync_timeline_get(obj);
-	fence_init(&pt->fence, &timeline_fence_ops, &obj->lock,
+	dma_fence_init(&pt->fence, &timeline_fence_ops, &obj->lock,
 		   obj->context, value);
 	list_add_tail(&pt->link, &obj->pt_list);
 	INIT_LIST_HEAD(&pt->active_list);
@@ -238,7 +252,7 @@
 }
 
 static int timeline_create_fence(struct vdec_sync *sync, int usage,
-				    struct fence **fence, int *fd, u32 value)
+				    struct dma_fence **fence, int *fd, u32 value)
 {
 	int ret;
 	struct sync_pt *pt;
@@ -256,7 +270,7 @@
 	if (usage == FENCE_USE_FOR_APP) {
 		*fd =  get_unused_fd_flags(O_CLOEXEC);
 		if (*fd < 0) {
-			ret = -EBADF;
+			return -EBADF;
 			goto err;
 		}
 
@@ -269,16 +283,16 @@
 		fd_install(*fd, sync_file->file);
 
 		/* decreases refcnt. */
-		fence_put(&pt->fence);
+		dma_fence_put(&pt->fence);
 	}
 
 	*fence = &pt->fence;
 
 	pt->timestamp = local_clock();
 
-	if (debug & VDEC_DBG_ENABLE_FENCE)
+	if (vdec_get_debug() & VDEC_DBG_ENABLE_FENCE)
 		pr_info("[VDEC-FENCE]: create fence: %lx, fd: %d, ref: %d, usage: %d\n",
-			(ulong) &pt->fence, *fd, atomic_read(&pt->fence.refcount.refcount), usage);
+			(ulong) &pt->fence, *fd, atomic_read(&pt->fence.refcount.refcount.refs), usage);
 	return 0;
 err:
 	put_unused_fd(*fd);
@@ -288,35 +302,64 @@
 	return ret;
 }
 
-struct fence *vdec_fence_get(int fd)
+struct dma_fence *vdec_fence_get(int fd)
 {
 	return sync_file_get_fence(fd);
 }
 EXPORT_SYMBOL(vdec_fence_get);
 
-void vdec_fence_put(struct fence *fence)
+void vdec_fence_put(struct dma_fence *fence)
 {
-	if (debug & VDEC_DBG_ENABLE_FENCE)
+	if (vdec_get_debug() & VDEC_DBG_ENABLE_FENCE)
 		pr_info("[VDEC-FENCE]: the fence (%px) cost time: %lld ns\n",
 			fence, local_clock() - get_sync_pt(fence)->timestamp);
-	fence_put(fence);
+	dma_fence_put(fence);
 }
 EXPORT_SYMBOL(vdec_fence_put);
 
-int vdec_fence_wait(struct fence *fence, long timeout)
+int vdec_fence_wait(struct dma_fence *fence, long timeout)
 {
-	if (debug & VDEC_DBG_ENABLE_FENCE)
+	if (vdec_get_debug() & VDEC_DBG_ENABLE_FENCE)
 		pr_info("[VDEC-FENCE]: wait fence %lx.\n", (ulong) fence);
 
-	return fence_wait_timeout(fence, false, timeout);
+	return dma_fence_wait_timeout(fence, false, timeout);
 }
 EXPORT_SYMBOL(vdec_fence_wait);
 
+struct vdec_sync *vdec_sync_get(void)
+{
+	int i;
+	struct vdec_sync_core_s *core = &vdec_sync_core;
+	ulong flags;
+
+	spin_lock_irqsave(&core->vdec_sync_lock, flags);
+
+	for (i = 0; i < VDEC_SYNC_COUNT; i++) {
+		if (atomic_read(&core->s_vdec_sync[i].use_flag) == 0) {
+			int j;
+			atomic_set(&core->s_vdec_sync[i].use_flag, 1);
+			for (j = 0; j < 64; j++) {
+				core->s_vdec_sync[i].release_callback[j].func = vdec_fence_buffer_count_decrease;
+				core->s_vdec_sync[i].release_callback[j].private_data = (void *)&core->s_vdec_sync[i];
+			}
+			spin_unlock_irqrestore(&core->vdec_sync_lock, flags);
+			return &core->s_vdec_sync[i];
+		}
+	}
+	spin_unlock_irqrestore(&core->vdec_sync_lock, flags);
+	return 0;
+}
+EXPORT_SYMBOL(vdec_sync_get);
+
 void vdec_timeline_create(struct vdec_sync *sync, u8 *name)
 {
+	struct sync_timeline *obj;
 	snprintf(sync->name, sizeof(sync->name), "%s", name);
 
-	sync->timeline = (void *)sync_timeline_create(sync->name);
+	obj = sync_timeline_create(sync->name);
+	obj->parent_sync = sync;
+	sync->timeline = (void *)obj;
+
 	if (sync->timeline)
 		pr_info("[VDEC-FENCE]: create timeline %lx, name: %s\n",
 			(ulong) sync->timeline, sync->name);
@@ -337,13 +380,12 @@
 
 	spin_lock_irqsave(&obj->lock, flags);
 
-	pt = list_last_entry(&obj->pt_list, struct sync_pt, link);
 	value = obj->value + 1;
 
 	if (!list_empty(&obj->pt_list)) {
 		pt = list_last_entry(&obj->pt_list, struct sync_pt, link);
-		if (value == pt->fence.seqno) {
-			value++;
+		if (value <= pt->fence.seqno) {
+			value = pt->fence.seqno + 1;
 		}
 	}
 	spin_unlock_irqrestore(&obj->lock, flags);
@@ -365,7 +407,7 @@
 
 	obj->timestamp = local_clock();
 
-	if (debug & VDEC_DBG_ENABLE_FENCE)
+	if (vdec_get_debug() & VDEC_DBG_ENABLE_FENCE)
 		pr_info("[VDEC-FENCE]: update timeline %d.\n",
 			obj->value + value);
 
@@ -373,6 +415,15 @@
 }
 EXPORT_SYMBOL(vdec_timeline_increase);
 
+void vdec_timeline_get(struct vdec_sync *sync)
+{
+	struct sync_timeline *obj = sync->timeline;
+
+	sync_timeline_get(obj);
+}
+EXPORT_SYMBOL(vdec_timeline_get);
+
+
 void vdec_timeline_put(struct vdec_sync *sync)
 {
 	struct sync_timeline *obj = sync->timeline;
@@ -381,15 +432,15 @@
 }
 EXPORT_SYMBOL(vdec_timeline_put);
 
-void vdec_fence_status_set(struct fence *fence, int status)
+void vdec_fence_status_set(struct dma_fence *fence, int status)
 {
 	fence->error = status;
 }
 EXPORT_SYMBOL(vdec_fence_status_set);
 
-int vdec_fence_status_get(struct fence *fence)
+int vdec_fence_status_get(struct dma_fence *fence)
 {
-	return fence_get_status(fence);
+	return dma_fence_get_status(fence);
 }
 EXPORT_SYMBOL(vdec_fence_status_get);
 
@@ -409,19 +460,72 @@
 
 int vdec_clean_all_fence(struct vdec_sync *sync)
 {
-	struct sync_timeline *obj = sync->timeline;
+	/*struct sync_timeline *obj = sync->timeline;
 	struct sync_pt *pt, *next;
 
 	spin_lock_irq(&obj->lock);
 
 	list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
-		fence_set_error(&pt->fence, -ENOENT);
-		fence_signal_locked(&pt->fence);
+		dma_fence_set_error(&pt->fence, -ENOENT);
+		dma_fence_signal_locked(&pt->fence);
 	}
 
-	spin_unlock_irq(&obj->lock);
+	spin_unlock_irq(&obj->lock);*/
+
+	struct sync_pt *pt, *next;
+	struct sync_timeline *obj = sync->timeline;
+
+	list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
+		pr_err("vdec_clean_all_fence %px\n" , obj->parent_sync);
+			vdec_fence_put(&pt->fence);
+	}
+
+	sync_timeline_put(obj);
 
 	return 0;
 }
 EXPORT_SYMBOL(vdec_clean_all_fence);
 
+void vdec_fence_buffer_count_increase(ulong fence)
+{
+	struct vdec_sync *sync = (struct vdec_sync *)fence;
+	struct sync_timeline *obj = sync->timeline;
+
+	spin_lock_irq(&obj->lock);
+
+	if (atomic_read(&sync->buffer_count) == 0) {
+			sync_timeline_get(obj);
+	}
+
+	atomic_inc(&sync->buffer_count);
+
+	spin_unlock_irq(&obj->lock);
+}
+EXPORT_SYMBOL(vdec_fence_buffer_count_increase);
+
+void vdec_fence_buffer_count_decrease(struct codec_mm_s *mm, struct codec_mm_cb_s *cb)
+{
+	struct vdec_sync *sync = (struct vdec_sync *)cb->private_data;
+	struct sync_pt *pt, *next;
+	struct sync_timeline *obj = sync->timeline;
+
+	atomic_dec(&sync->buffer_count);
+
+	if (atomic_read(&sync->buffer_count) == 0) {
+		sync_timeline_put(obj);
+		list_for_each_entry_safe(pt, next, &obj->pt_list, link) {
+			vdec_fence_put(&pt->fence);
+		}
+		return;
+	}
+	return ;
+}
+EXPORT_SYMBOL(vdec_fence_buffer_count_decrease);
+
+void vdec_sync_core_init(void)
+{
+	spin_lock_init(&vdec_sync_core.vdec_sync_lock);
+}
+EXPORT_SYMBOL(vdec_sync_core_init);
+
+
diff --git a/drivers/frame_provider/decoder/utils/vdec_sync.h b/drivers/frame_provider/decoder/utils/vdec_sync.h
index 0622341..6637b42 100644
--- a/drivers/frame_provider/decoder/utils/vdec_sync.h
+++ b/drivers/frame_provider/decoder/utils/vdec_sync.h
@@ -20,9 +20,11 @@
 #include <linux/list.h>
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 #include <linux/sync_file.h>
 #include <uapi/linux/sync_file.h>
+#include <linux/device.h>
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
 
 #define FENCE_USE_FOR_DRIVER	(0)
 #define FENCE_USE_FOR_APP	(1)
@@ -40,10 +42,11 @@
 	spinlock_t		lock;
 
 	u64			timestamp;
+	struct vdec_sync *parent_sync;
 };
 
 struct sync_pt {
-	struct fence		fence;
+	struct dma_fence		fence;
 	struct list_head	link;
 	struct list_head	active_list;
 	u64			timestamp;
@@ -54,24 +57,27 @@
 	void			*timeline;
 	int			usage;
 	int			fd;
-	struct fence		*fence;
+	struct dma_fence		*fence;
+	atomic_t 		buffer_count;
+	atomic_t 		use_flag;
+	struct codec_mm_cb_s release_callback[64];
 };
 
-static inline struct sync_timeline *fence_parent(struct fence *fence)
+static inline struct sync_timeline *fence_parent(struct dma_fence *fence)
 {
 	return container_of(fence->lock, struct sync_timeline, lock);
 }
 
-static inline struct sync_pt *get_sync_pt(struct fence *fence)
+static inline struct sync_pt *get_sync_pt(struct dma_fence *fence)
 {
 	return container_of(fence, struct sync_pt, fence);
 }
 
-struct fence *vdec_fence_get(int fd);
+struct dma_fence *vdec_fence_get(int fd);
 
-void vdec_fence_put(struct fence *fence);
+void vdec_fence_put(struct dma_fence *fence);
 
-int vdec_fence_wait(struct fence *fence, long timeout);
+int vdec_fence_wait(struct dma_fence *fence, long timeout);
 
 void vdec_timeline_create(struct vdec_sync *sync, u8 *name);
 
@@ -79,13 +85,23 @@
 
 void vdec_timeline_increase(struct vdec_sync *sync, u32 value);
 
+void vdec_timeline_get(struct vdec_sync *sync);
+
 void vdec_timeline_put(struct vdec_sync *sync);
 
-int vdec_fence_status_get(struct fence *fence);
+int vdec_fence_status_get(struct dma_fence *fence);
 
-void vdec_fence_status_set(struct fence *fence, int status);
+void vdec_fence_status_set(struct dma_fence *fence, int status);
 
 bool check_objs_all_signaled(struct vdec_sync *sync);
 
 int vdec_clean_all_fence(struct vdec_sync *sync);
 
+void vdec_fence_buffer_count_increase(ulong fence);
+
+void vdec_fence_buffer_count_decrease(struct codec_mm_s *mm, struct codec_mm_cb_s *cb);
+
+struct vdec_sync *vdec_sync_get(void);
+
+void vdec_sync_core_init(void);
+
diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
index e892127..34bc21a 100644
--- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
+++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
@@ -21,21 +21,6 @@
 #include <media/v4l2-mem2mem.h>
 #include <linux/printk.h>
 
-int vdec_v4l_get_buffer(struct aml_vcodec_ctx *ctx,
-	struct vdec_v4l2_buffer **out)
-{
-	int ret = -1;
-
-	if (ctx->drv_handle == 0)
-		return -EIO;
-
-	ret = ctx->dec_if->get_param(ctx->drv_handle,
-		GET_PARAM_FREE_FRAME_BUFFER, out);
-
-	return ret;
-}
-EXPORT_SYMBOL(vdec_v4l_get_buffer);
-
 int vdec_v4l_get_pic_info(struct aml_vcodec_ctx *ctx,
 	struct vdec_pic_info *pic)
 {
@@ -51,6 +36,21 @@
 }
 EXPORT_SYMBOL(vdec_v4l_get_pic_info);
 
+int vdec_v4l_set_cfg_infos(struct aml_vcodec_ctx *ctx,
+	struct aml_vdec_cfg_infos *cfg)
+{
+	int ret = 0;
+
+	if (ctx->drv_handle == 0)
+		return -EIO;
+
+	ret = ctx->dec_if->set_param(ctx->drv_handle,
+		SET_PARAM_CFG_INFO, cfg);
+
+	return ret;
+}
+EXPORT_SYMBOL(vdec_v4l_set_cfg_infos);
+
 int vdec_v4l_set_ps_infos(struct aml_vcodec_ctx *ctx,
 	struct aml_vdec_ps_infos *ps)
 {
@@ -66,6 +66,22 @@
 }
 EXPORT_SYMBOL(vdec_v4l_set_ps_infos);
 
+int vdec_v4l_set_comp_buf_info(struct aml_vcodec_ctx *ctx,
+		struct vdec_comp_buf_info *info)
+{
+	int ret = 0;
+
+	if (ctx->drv_handle == 0)
+		return -EIO;
+
+	ret = ctx->dec_if->set_param(ctx->drv_handle,
+		SET_PARAM_COMP_BUF_INFO, info);
+
+	return ret;
+
+}
+EXPORT_SYMBOL(vdec_v4l_set_comp_buf_info);
+
 int vdec_v4l_set_hdr_infos(struct aml_vcodec_ctx *ctx,
 	struct aml_vdec_hdr_infos *hdr)
 {
@@ -81,50 +97,10 @@
 }
 EXPORT_SYMBOL(vdec_v4l_set_hdr_infos);
 
-static void aml_wait_dpb_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)) {
-			pr_err("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->dpb_size)
-			ctx->v4l_codec_dpb_ready = true;
-	}
-}
-
 void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx)
 {
-	unsigned int dpbsize = 0;
-	int ret;
-
-	if (ctx->dec_if->get_param(ctx->drv_handle, GET_PARAM_PIC_INFO, &ctx->last_decoded_picinfo)) {
-		pr_err("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) {
-		pr_err("Cannot get correct pic info\n");
-		return;
-	}
-
-	ret = ctx->dec_if->get_param(ctx->drv_handle, GET_PARAM_DPB_SIZE, &dpbsize);
-	if (dpbsize == 0)
-		pr_err("Incorrect dpb size, ret=%d\n", ret);
-
-	/* update picture information */
-	ctx->dpb_size = dpbsize;
-	ctx->picinfo = ctx->last_decoded_picinfo;
+	if (ctx != NULL)
+		ctx->vdec_pic_info_update(ctx);
 }
 
 int vdec_v4l_post_evet(struct aml_vcodec_ctx *ctx, u32 event)
@@ -150,9 +126,6 @@
 	if (ctx->drv_handle == 0)
 		return -EIO;
 
-	/* wait the DPB state to be ready. */
-	aml_wait_dpb_ready(ctx);
-
 	aml_vdec_pic_info_update(ctx);
 
 	mutex_lock(&ctx->state_lock);
@@ -163,8 +136,9 @@
 
 	mutex_unlock(&ctx->state_lock);
 
-	ctx->q_data[AML_Q_DATA_SRC].resolution_changed = true;
-	v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
+	while (ctx->m2m_ctx->job_flags & TRANS_RUNNING) {
+		v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
+	}
 
 	return ret;
 }
@@ -185,3 +159,17 @@
 }
 EXPORT_SYMBOL(vdec_v4l_write_frame_sync);
 
+int vdec_v4l_get_dw_mode(struct aml_vcodec_ctx *ctx,
+	unsigned int *dw_mode)
+{
+	int ret = -1;
+
+	if (ctx->drv_handle == 0)
+		return -EIO;
+
+	ret = ctx->dec_if->get_param(ctx->drv_handle,
+		GET_PARAM_DW_MODE, dw_mode);
+
+	return ret;
+}
+EXPORT_SYMBOL(vdec_v4l_get_dw_mode);
diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
index 1494f10..98513d9 100644
--- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
+++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
@@ -23,18 +23,22 @@
 #include "../../../amvdec_ports/vdec_drv_base.h"
 #include "../../../amvdec_ports/aml_vcodec_adapt.h"
 
-int vdec_v4l_get_buffer(
-	struct aml_vcodec_ctx *ctx,
-	struct vdec_v4l2_buffer **out);
-
 int vdec_v4l_get_pic_info(
 	struct aml_vcodec_ctx *ctx,
 	struct vdec_pic_info *pic);
 
+int vdec_v4l_set_cfg_infos(
+	struct aml_vcodec_ctx *ctx,
+	struct aml_vdec_cfg_infos *cfg);
+
 int vdec_v4l_set_ps_infos(
 	struct aml_vcodec_ctx *ctx,
 	struct aml_vdec_ps_infos *ps);
 
+int vdec_v4l_set_comp_buf_info(
+	struct aml_vcodec_ctx *ctx,
+	struct vdec_comp_buf_info *info);
+
 int vdec_v4l_set_hdr_infos(
 	struct aml_vcodec_ctx *ctx,
 	struct aml_vdec_hdr_infos *hdr);
@@ -49,4 +53,8 @@
 int vdec_v4l_res_ch_event(
 	struct aml_vcodec_ctx *ctx);
 
+int vdec_v4l_get_dw_mode(
+	struct aml_vcodec_ctx *ctx,
+	unsigned int *dw_mode);
+
 #endif
diff --git a/drivers/frame_provider/decoder/vav1/av1_bufmgr.c b/drivers/frame_provider/decoder/vav1/av1_bufmgr.c
index 41a522f..1e45320 100644
--- a/drivers/frame_provider/decoder/vav1/av1_bufmgr.c
+++ b/drivers/frame_provider/decoder/vav1/av1_bufmgr.c
@@ -530,16 +530,23 @@
 
 void av1_bufmgr_ctx_reset(AV1Decoder *pbi, BufferPool *const pool, AV1_COMMON *cm)
 {
+	u32 save_w, save_h;
+
 	if (!pbi || !pool || !cm)
 		return;
 
 	reset_frame_buffers(pbi);
 	memset(pbi, 0, sizeof(*pbi));
+	/*save w,h for resolution change after seek */
+	save_w = cm->width;
+	save_h = cm->height;
 	memset(cm, 0, sizeof(*cm));
 
 	cm->current_frame.frame_number	= 0;
 	cm->seq_params.bit_depth	= AOM_BITS_8;
 	cm->error.setjmp = 0;
+	cm->width = save_w;
+	cm->height = save_h;
 
 	pbi->bufmgr_proc_count		= 0;
 	pbi->need_resync		= 1;
@@ -585,6 +592,17 @@
   }
 }
 
+void clear_frame_buf_ref_count(AV1Decoder *pbi)
+{
+	int i;
+
+	for (i = 0; i < pbi->num_output_frames; i++) {
+		decrease_ref_count(pbi, pbi->output_frames[i],
+			pbi->common->buffer_pool);
+	}
+	pbi->num_output_frames = 0;
+}
+
 static void swap_frame_buffers(AV1Decoder *pbi, int frame_decoded) {
   int ref_index = 0, mask;
   AV1_COMMON *const cm = pbi->common;
@@ -958,9 +976,10 @@
 
 #ifdef ORI_CODE
 fail:
+#endif
   // clear the mi_* values to force a realloc on resync
   av1_set_mb_mi(cm, 0, 0);
-
+#ifdef ORI_CODE
   av1_free_context_buffers(cm);
 #endif
   return 1;
@@ -2016,6 +2035,7 @@
       // See if this frame can be used as show_existing_frame in future
       cm->showable_frame = params->p.showable_frame;//aom_rb_read_bit(rb);
     }
+    cm->cur_frame->show_frame = cm->show_frame;
     cm->cur_frame->showable_frame = cm->showable_frame;
     cm->error_resilient_mode =
         frame_is_sframe(cm) ||
@@ -2926,6 +2946,14 @@
           // TODO(wtc): Verify that the frame_header_obu is identical to the
           // original frame_header_obu. For now just skip frame_header_size
           // bytes in the bit buffer.
+          if (frame_header_size > payload_size) {
+            cm->error.error_code = AOM_CODEC_CORRUPT_FRAME;
+            return -1;
+          }
+          assert(rb.bit_offset == 0);
+#ifdef ORI_CODE
+          rb.bit_offset = 8 * frame_header_size;
+#endif
         }
 
         decoded_payload_size = frame_header_size;
@@ -2984,7 +3012,6 @@
 			}
 		}
 	}
-
 	return i;
 }
 
diff --git a/drivers/frame_provider/decoder/vav1/av1_global.h b/drivers/frame_provider/decoder/vav1/av1_global.h
index 75af688..e12b224 100644
--- a/drivers/frame_provider/decoder/vav1/av1_global.h
+++ b/drivers/frame_provider/decoder/vav1/av1_global.h
@@ -52,13 +52,6 @@
 #define AOMMIN(x, y) (((x) < (y)) ? (x) : (y))
 #define AOMMAX(x, y) (((x) > (y)) ? (x) : (y))
 
-//typedef char int8_t;
-//#ifndef BUFMGR_FOR_SIM
-typedef unsigned char uint8_t;
-//#endif
-typedef unsigned int uint32_t;
-//typedef int int32_t;
-//typedef long long int64_t;
 
 #ifdef AML
 #define AOM_AV1_MMU
@@ -108,9 +101,12 @@
 } BuffInfo_t;
 #endif
 
+#if 0
 #define va_start(v,l)   __builtin_va_start(v,l)
 #define va_end(v)       __builtin_va_end(v)
 #define va_arg(v,l)     __builtin_va_arg(v,l)
+#endif
+
 /*
 mem.h
 */
@@ -1322,8 +1318,9 @@
   int min_mv;
   int avg_mv;
 #endif
-	bool vframe_bound;
-	u64 timestamp;
+  u64 timestamp;
+  u32 hw_decode_time;
+  u32 frame_size2; // For frame base mode
 } PIC_BUFFER_CONFIG;
 
 /*
@@ -1564,6 +1561,7 @@
 
   FRAME_CONTEXT frame_context;
 #endif
+  int show_frame;
 } RefCntBuffer;
 
 typedef struct BufferPool_s {
@@ -2227,7 +2225,9 @@
         unsigned short seg_lf_info_c[8];
 		unsigned short video_signal_type;
 		unsigned short color_description;
-
+		unsigned short mmu_used_num;
+		unsigned short dw_mmu_used_num;
+		unsigned short seq_flags_2;
         /*ucode end*/
         /*other*/
         unsigned short enable_superres;
@@ -2317,6 +2317,7 @@
 #define AV1_DEBUG_DUMP_DATA              0x800000
 #define AV1_DEBUG_CACHE                  0x1000000
 #define AV1_DEBUG_CACHE_HIT_RATE         0x2000000
+#define AV1_DEBUG_SEI_DETAIL             0x4000000
 #define IGNORE_PARAM_FROM_CONFIG         0x8000000
 #if 1
 /*def MULTI_INSTANCE_SUPPORT*/
diff --git a/drivers/frame_provider/decoder/vav1/vav1.c b/drivers/frame_provider/decoder/vav1/vav1.c
index 8379316..c67757a 100644
--- a/drivers/frame_provider/decoder/vav1/vav1.c
+++ b/drivers/frame_provider/decoder/vav1/vav1.c
@@ -25,6 +25,7 @@
 #include <linux/timer.h>
 #include <linux/kfifo.h>
 #include <linux/kthread.h>
+#include <linux/sched/clock.h>
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
 #include <linux/amlogic/media/vfm/vframe.h>
@@ -73,6 +74,7 @@
 #include <media/v4l2-mem2mem.h>
 #endif
 #include "../../../amvdec_ports/utils/common.h"
+#include "../utils/vdec_feature.h"
 
 #define AML
 #include "aom_av1_define.h"
@@ -88,6 +90,8 @@
 
 #define USE_DEC_PIC_END
 
+#define SANITY_CHECK
+#define CO_MV_COMPRESS
 
 #include "vav1.h"
 
@@ -168,6 +172,7 @@
 #define AOM_AV1_DUMP_LMEM                    7
 #define AOM_AV1_FGS_PARAM_CONT               8
 #define AOM_AV1_DISCARD_NAL                  0x10
+#define AOM_AV1_RESULT_NEED_MORE_BUFFER      0x11
 
 /*status*/
 #define AOM_AV1_DEC_PIC_END                  0xe0
@@ -192,7 +197,6 @@
 #define AOM_EOS                     0x24
 #define AOM_NAL_DECODE_DONE            0x25
 
-
 #define VF_POOL_SIZE        32
 
 #undef pr_info
@@ -265,8 +269,8 @@
 #ifdef AOM_AV1_MMU_DW
 static unsigned int dw_mmu_enable[MAX_DECODE_INSTANCE_NUM];
 #endif
-/* disable timeout for av1 mosaic JIRA SWPL-23326 */
-static u32 decode_timeout_val = 0;
+
+static u32 decode_timeout_val = 600;
 static int start_decode_buf_level = 0x8000;
 //static u32 work_buf_size;
 static u32 force_pts_unstable;
@@ -281,9 +285,10 @@
  *	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
+ *	5, (1/2):(1/2) ratio, with both compressed frame included
+ *	8, (1/8):(1/8) ratio;
  *	0x10, double write only
- *  0x20, mmu double write
+ *	0x20, mmu double write
  *	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;
@@ -309,7 +314,7 @@
 
 #define DUR2PTS(x) ((x)*90/96)
 #define PTS2DUR(x) ((x)*96/90)
-
+#define PTS2DUR_u64(x) (div_u64((x)*96, 90))
 
 struct AV1HW_s;
 static int vav1_vf_states(struct vframe_states *states, void *);
@@ -326,7 +331,7 @@
 #endif
 static void vav1_prot_init(struct AV1HW_s *hw, u32 mask);
 static int vav1_local_init(struct AV1HW_s *hw);
-static void vav1_put_timer_func(unsigned long arg);
+static void vav1_put_timer_func(struct timer_list *timer);
 static void dump_data(struct AV1HW_s *hw, int size);
 static unsigned int get_data_check_sum
 	(struct AV1HW_s *hw, int size);
@@ -371,6 +376,8 @@
 static u32 video_signal_type;
 static u32 on_no_keyframe_skiped;
 static u32 without_display_mode;
+static u32 v4l_bitstream_id_enable = 1;
+
 #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
 static u32 force_dv_enable;
 #endif
@@ -432,10 +439,6 @@
 #define LOSLESS_COMPRESS_MODE
 #endif
 
-typedef unsigned int u32;
-typedef unsigned short u16;
-
-
 static u32 get_picture_qos;
 
 static u32 debug;
@@ -534,6 +537,7 @@
 //#define MMU_COMPRESS_8K_HEADER_SIZE  (0x48000*4)
 #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))
 
@@ -595,7 +599,7 @@
 static int  compute_losless_comp_body_size(int width, int height,
 				uint8_t is_bit_depth_10);
 
-
+void clear_frame_buf_ref_count(AV1Decoder *pbi);
 
 #ifdef MULTI_INSTANCE_SUPPORT
 #define DEC_RESULT_NONE             0
@@ -752,23 +756,10 @@
 	u32 video_signal_type;
 
 	u32 pts_unstable;
-	bool av1_first_pts_ready;
-	bool dur_recalc_flag;
-	u8  first_pts_index;
-	u32 frame_mode_pts_save[FRAME_BUFFERS];
-	u64 frame_mode_pts64_save[FRAME_BUFFERS];
-	u64 frame_mode_timestamp_save[FRAME_BUFFERS];
-	u64 timestamp_duration;
+	u32 last_chunk_pts;
+	u32 pts_diff_count;
+	u64 pts_diff_sum;
 
-	int last_pts;
-	u64 last_pts_us64;
-	u64 last_timestamp;
-	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;
@@ -861,17 +852,23 @@
 	int buffer_wrap[FRAME_BUFFERS];
 	int sidebind_type;
 	int sidebind_channel_id;
-	char vdec_name[32];
-	char pts_name[32];
-	char new_q_name[32];
-	char disp_q_name[32];
+	u32 cur_obu_type;
+	u32 multi_frame_cnt;
+	u32 endian;
+	u32 run_ready_min_buf_num;
+	int one_package_frame_cnt;
+	ulong fb_token;
+	dma_addr_t rdma_phy_adr;
+	unsigned *rdma_adr;
+	struct trace_decoder_name trace;
 };
+
 static void av1_dump_state(struct vdec_s *vdec);
 
 int av1_print(struct AV1HW_s *hw,
 	int flag, const char *fmt, ...)
 {
-#define HEVC_PRINT_BUF		256
+#define HEVC_PRINT_BUF		512
 	unsigned char buf[HEVC_PRINT_BUF];
 	int len = 0;
 
@@ -921,6 +918,9 @@
 	int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)?
 		MAX_SIZE_8K : 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;
 
@@ -1015,48 +1015,16 @@
 	u32 dw = ((double_write_mode & 0x80000000) == 0) ?
 		hw->double_write_mode :
 		(double_write_mode & 0x7fffffff);
-	if ((dw & 0x20) &&
-		((dw & 0xf) == 2 || (dw & 0xf) == 3)) {
-		pr_info("MMU doueble write 1:4 not supported !!!\n");
-		dw = 0;
+	if (dw & 0x20) {
+		if ((get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_T3)
+			&& ((dw & 0xf) == 2 || (dw & 0xf) == 3)) {
+			pr_info("MMU doueble write 1:4 not supported !!!\n");
+			dw = 0;
+		}
 	}
 	return dw;
 }
 
-static int v4l_parser_get_double_write_mode(struct AV1HW_s *hw)
-{
-	u32 valid_dw_mode = get_valid_double_write_mode(hw);
-	u32 dw;
-	int w, h;
-
-	/* mask for supporting double write value bigger than 0x100 */
-	if (valid_dw_mode & 0xffffff00) {
-		w = hw->frame_width;
-		h = hw->frame_height;
-
-		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:
-			break;
-		}
-		return dw;
-	}
-
-	return valid_dw_mode;
-}
-
 static int get_double_write_mode(struct AV1HW_s *hw)
 {
 	u32 valid_dw_mode = get_valid_double_write_mode(hw);
@@ -1067,6 +1035,15 @@
 
 	if (!cm->cur_frame)
 		return 1;/*no valid frame,*/
+
+	if (hw->is_used_v4l) {
+		unsigned int out;
+
+		vdec_v4l_get_dw_mode(hw->v4l2_ctx, &out);
+		dw = out;
+		return dw;
+	}
+
 	cur_pic_config = &cm->cur_frame->buf;
 	w = cur_pic_config->y_crop_width;
 	h = cur_pic_config->y_crop_height;
@@ -1122,19 +1099,6 @@
 }
 #endif
 
-static int get_double_write_ratio(struct AV1HW_s *hw,
-	int dw_mode)
-{
-	int ratio = 1;
-	int dw_mode_ratio = dw_mode & 0xf;
-	if ((dw_mode_ratio == 2) ||
-			(dw_mode_ratio == 3))
-		ratio = 4;
-	else if (dw_mode_ratio == 4)
-		ratio = 2;
-	return ratio;
-}
-
 /* return page number */
 static int av1_mmu_page_num(struct AV1HW_s *hw,
 		int w, int h, int save_mode)
@@ -1159,6 +1123,32 @@
 	return cur_mmu_4k_number;
 }
 
+static struct internal_comp_buf* v4lfb_to_icomp_buf(
+		struct AV1HW_s *hw,
+		struct vdec_v4l2_buffer *fb)
+{
+	struct aml_video_dec_buf *aml_fb = NULL;
+	struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+
+	aml_fb = container_of(fb, struct aml_video_dec_buf, frame_buffer);
+
+	return &v4l2_ctx->comp_bufs[aml_fb->internal_index];
+}
+
+static struct internal_comp_buf* index_to_icomp_buf(
+		struct AV1HW_s *hw, int index)
+{
+	struct aml_video_dec_buf *aml_fb = NULL;
+	struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+	struct vdec_v4l2_buffer *fb = NULL;
+
+	fb = (struct vdec_v4l2_buffer *)
+		hw->m_BUF[index].v4l_ref_buf_addr;
+	aml_fb = container_of(fb, struct aml_video_dec_buf, frame_buffer);
+
+	return &v4l2_ctx->comp_bufs[aml_fb->internal_index];
+}
+
 //#define	MAX_4K_NUM		0x1200
 int av1_alloc_mmu(
 	struct AV1HW_s *hw,
@@ -1172,11 +1162,6 @@
 	int bit_depth_10 = (bit_depth == AOM_BITS_10);
 	int cur_mmu_4k_number;
 
-	if (!hw->mmu_box) {
-		pr_err("error no mmu box!\n");
-		return -1;
-	}
-
 	if (hw->double_write_mode & 0x10)
 		return 0;
 
@@ -1193,11 +1178,22 @@
 	if (cur_mmu_4k_number < 0)
 		return -1;
 
-	ret = decoder_mmu_box_alloc_idx(
-		hw->mmu_box,
-		hw->buffer_wrap[cur_buf_idx],
-		cur_mmu_4k_number,
-		mmu_index_adr);
+	if (hw->is_used_v4l) {
+		struct internal_comp_buf *ibuf =
+			index_to_icomp_buf(hw, cur_buf_idx);
+
+		ret = decoder_mmu_box_alloc_idx(
+				ibuf->mmu_box,
+				ibuf->index,
+				ibuf->frame_buffer_size,
+				mmu_index_adr);
+	} else {
+		ret = decoder_mmu_box_alloc_idx(
+			hw->mmu_box,
+			cur_buf_idx,
+			cur_mmu_4k_number,
+			mmu_index_adr);
+	}
 
 	return ret;
 }
@@ -1245,7 +1241,7 @@
 	}
 	ret = decoder_mmu_box_alloc_idx(
 		hw->mmu_box_dw,
-		hw->buffer_wrap[cur_buf_idx],
+		cur_buf_idx,
 		cur_mmu_4k_number,
 		mmu_index_adr);
 	return ret;
@@ -1278,6 +1274,13 @@
 	int i, int size)
 {
 	int ret = 0;
+
+	if (hw->m_mv_BUF[i].start_adr &&
+		size > hw->m_mv_BUF[i].size) {
+		dealloc_mv_bufs(hw);
+	} else if (hw->m_mv_BUF[i].start_adr)
+		return 0;
+
 	if (decoder_bmmu_box_alloc_buf_phy
 		(hw->bmmu_box,
 		MV_BUFFER_IDX(i), size,
@@ -1353,10 +1356,7 @@
 			__func__, size);
 
 	if ((hw->is_used_v4l) && !IS_8K_SIZE(pic_width, pic_height)) {
-		if (vdec_is_support_4k())
-			size = 0xb0000;
-		else
-			size = 0x30000;
+		size = 0x100000;
 	}
 
 	if (hw->init_pic_w > 4096 && hw->init_pic_h > 2048)
@@ -1502,6 +1502,26 @@
 
 static void init_pic_list_hw(struct AV1HW_s *pbi);
 
+static void update_hide_frame_timestamp(struct AV1HW_s *hw)
+{
+	RefCntBuffer *const frame_bufs = hw->common.buffer_pool->frame_bufs;
+	int i;
+
+	for (i = 0; i < hw->used_buf_num; ++i) {
+		if ((!frame_bufs[i].show_frame) &&
+			(frame_bufs[i].showable_frame) &&
+			(!frame_bufs[i].buf.vf_ref) &&
+			(frame_bufs[i].buf.BUF_index != -1)) {
+			frame_bufs[i].buf.timestamp = hw->chunk->timestamp;
+			frame_bufs[i].buf.pts = hw->chunk->pts;
+			frame_bufs[i].buf.pts64 = hw->chunk->pts64;
+			av1_print(hw, AV1_DEBUG_OUT_PTS,
+				"%s, update %d hide frame ts: %lld, pts %d, pts64 %lld\n",
+				__func__, i, frame_bufs[i].buf.timestamp, hw->chunk->pts, hw->chunk->pts64);
+		}
+	}
+}
+
 static int get_free_fb_idx(AV1_COMMON *cm)
 {
 	int i;
@@ -1513,7 +1533,7 @@
 			break;
 	}
 
-	return i;
+	return (i != FRAME_BUFFERS) ? i : -1;
 }
 
 static int v4l_get_free_fb(struct AV1HW_s *hw)
@@ -1545,6 +1565,9 @@
 			break;
 		case V4L_CAP_BUFF_IN_M2M:
 			idx = get_free_fb_idx(cm);
+			if (idx < 0)
+				break;
+
 			pic = &frame_bufs[idx].buf;
 			pic->y_crop_width = hw->frame_width;
 			pic->y_crop_height = hw->frame_height;
@@ -1578,8 +1601,30 @@
 		}
 	}
 
+	if (free_pic && hw->chunk) {
+		free_pic->timestamp = hw->chunk->timestamp;
+		update_hide_frame_timestamp(hw);
+	}
+
 	unlock_buffer_pool(cm->buffer_pool, flags);
 
+	if (free_pic) {
+		struct vdec_v4l2_buffer *fb =
+			(struct vdec_v4l2_buffer *)
+			hw->m_BUF[free_pic->index].v4l_ref_buf_addr;
+
+		fb->status = FB_ST_DECODER;
+	}
+
+	if (debug & AV1_DEBUG_OUT_PTS) {
+		if (free_pic) {
+			pr_debug("%s, idx: %d, ts: %lld\n",
+				__func__, free_pic->index, free_pic->timestamp);
+		} else {
+			pr_debug("%s, av1 get free pic null\n", __func__);
+		}
+	}
+
 	return free_pic ? free_pic->index : INVALID_IDX;
 }
 
@@ -1619,7 +1664,25 @@
 		i = INVALID_IDX;
 	}
 
+	if (i != INVALID_IDX) {
+		struct PIC_BUFFER_CONFIG_s *pic = &frame_bufs[i].buf;
+		struct AV1HW_s *hw = container_of(cm, struct AV1HW_s, common);
+
+		if (pic && hw->chunk) {
+			pic->timestamp = hw->chunk->timestamp;
+			pic->pts = hw->chunk->pts;
+			pic->pts64 = hw->chunk->pts64;
+			update_hide_frame_timestamp(hw);
+		}
+
+		if (pic)
+			av1_print(hw, AV1_DEBUG_OUT_PTS,
+				"%s, idx: %d, ts: %lld, pts %d, pts64 %lld\n",
+				__func__, i, pic->timestamp, pic->pts, pic->pts64);
+	}
+
 	unlock_buffer_pool(cm->buffer_pool, flags);
+
 	return i;
 }
 
@@ -1634,14 +1697,42 @@
 {
 	struct AV1_Common_s *const cm = &hw->common;
 	struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
-	int i;
-	int free_buf_count = 0;
-	for (i = 0; i < hw->used_buf_num; ++i)
-		if ((frame_bufs[i].ref_count == 0) &&
-			(frame_bufs[i].buf.vf_ref == 0) &&
-			(frame_bufs[i].buf.index != -1)
-			)
-			free_buf_count++;
+	struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+	int i, free_buf_count = 0;
+
+	if (hw->is_used_v4l) {
+		for (i = 0; i < hw->used_buf_num; ++i) {
+			if ((frame_bufs[i].ref_count == 0) &&
+				(frame_bufs[i].buf.vf_ref == 0) &&
+				frame_bufs[i].buf.cma_alloc_addr) {
+				free_buf_count++;
+			}
+		}
+
+		if (ctx->cap_pool.dec < hw->used_buf_num) {
+			free_buf_count +=
+				v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx);
+		}
+		/* trigger to parse head data. */
+		if (!hw->v4l_params_parsed) {
+			free_buf_count = hw->run_ready_min_buf_num;
+		}
+		if ((debug & AV1_DEBUG_BUFMGR_MORE) &&
+			(free_buf_count <= 0)) {
+			pr_info("%s, free count %d, m2m_ready %d\n",
+				__func__,
+				free_buf_count,
+				v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx));
+		}
+	} else {
+		for (i = 0; i < hw->used_buf_num; ++i)
+			if ((frame_bufs[i].ref_count == 0) &&
+				(frame_bufs[i].buf.vf_ref == 0) &&
+				(frame_bufs[i].buf.index != -1)) {
+				free_buf_count++;
+			}
+	}
+
 	return free_buf_count;
 }
 
@@ -1687,18 +1778,13 @@
 	hw->wait_buf = 0;
 	hw->error_flag = 0;
 
-	hw->last_pts = 0;
-	hw->last_pts_us64 = 0;
-	hw->last_timestamp = 0;
-	hw->shift_byte_count = 0;
-	hw->shift_byte_count_lo = 0;
-	hw->shift_byte_count_hi = 0;
-	hw->pts_mode_switching_count = 0;
-	hw->pts_mode_recovery_count = 0;
-
 	hw->buf_num = 0;
 	hw->pic_num = 0;
 
+	hw->last_chunk_pts = 0;
+	hw->pts_diff_count = 0;
+	hw->pts_diff_sum = 0;
+
 	return 0;
 }
 
@@ -1740,7 +1826,14 @@
 static u32 pop_shorts;
 static u32 dbg_cmd;
 static u32 dbg_skip_decode_index;
-static u32 endian = 0xff0;
+/*
+ * 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)
+
 static u32 multi_frames_in_one_pack = 1;
 #ifdef ERROR_HANDLE_DEBUG
 static u32 dbg_nal_skip_flag;
@@ -1932,9 +2025,12 @@
 #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. fix case1440 dec timeout */
+#define WORKBUF_ALIGN(addr) (ALIGN(addr, PAGE_SIZE))
+
 #define WORK_BUF_SPEC_NUM 3
 
-static struct BuffInfo_s  aom_workbuff_spec[WORK_BUF_SPEC_NUM] = {
+static struct BuffInfo_s aom_workbuff_spec[WORK_BUF_SPEC_NUM] = {
 	{ //8M bytes
 		.max_width = 1920,
 		.max_height = 1088,
@@ -2617,82 +2713,73 @@
 {
 	void *mem_start_virt;
 
-    buf_spec->ipp.buf_start =
-		buf_spec->start_adr;
-    buf_spec->sao_abv.buf_start =
-		buf_spec->ipp.buf_start + buf_spec->ipp.buf_size;
-
-    buf_spec->sao_vb.buf_start =
-		buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size;
-    buf_spec->short_term_rps.buf_start =
-		buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size;
-    buf_spec->vps.buf_start =
-		buf_spec->short_term_rps.buf_start + buf_spec->short_term_rps.buf_size;
-    buf_spec->seg_map.buf_start =
-		buf_spec->vps.buf_start + buf_spec->vps.buf_size;
-    buf_spec->daala_top.buf_start =
-		buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size;
-    buf_spec->sao_up.buf_start =
-		buf_spec->daala_top.buf_start + buf_spec->daala_top.buf_size;
-    buf_spec->swap_buf.buf_start =
-		buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size;
-    buf_spec->cdf_buf.buf_start =
-		buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size;
-    buf_spec->gmc_buf.buf_start =
-		buf_spec->cdf_buf.buf_start + buf_spec->cdf_buf.buf_size;
-    buf_spec->scalelut.buf_start =
-		buf_spec->gmc_buf.buf_start + buf_spec->gmc_buf.buf_size;
-    buf_spec->dblk_para.buf_start =
-		buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size;
-    buf_spec->dblk_data.buf_start =
-		buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size;
-    buf_spec->cdef_data.buf_start =
-		buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size;
-    buf_spec->ups_data.buf_start =
-		buf_spec->cdef_data.buf_start + buf_spec->cdef_data.buf_size;
-    buf_spec->fgs_table.buf_start =
-		buf_spec->ups_data.buf_start + buf_spec->ups_data.buf_size;
+	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->vps.buf_start =
+		WORKBUF_ALIGN(buf_spec->short_term_rps.buf_start + buf_spec->short_term_rps.buf_size);
+	buf_spec->seg_map.buf_start =
+		WORKBUF_ALIGN(buf_spec->vps.buf_start + buf_spec->vps.buf_size);
+	buf_spec->daala_top.buf_start =
+		WORKBUF_ALIGN(buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size);
+	buf_spec->sao_up.buf_start =
+		WORKBUF_ALIGN(buf_spec->daala_top.buf_start + buf_spec->daala_top.buf_size);
+	buf_spec->swap_buf.buf_start =
+		WORKBUF_ALIGN(buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size);
+	buf_spec->cdf_buf.buf_start =
+		WORKBUF_ALIGN(buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size);
+	buf_spec->gmc_buf.buf_start =
+		WORKBUF_ALIGN(buf_spec->cdf_buf.buf_start + buf_spec->cdf_buf.buf_size);
+	buf_spec->scalelut.buf_start =
+		WORKBUF_ALIGN(buf_spec->gmc_buf.buf_start + buf_spec->gmc_buf.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->cdef_data.buf_start =
+		WORKBUF_ALIGN(buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size);
+	buf_spec->ups_data.buf_start =
+		WORKBUF_ALIGN(buf_spec->cdef_data.buf_start + buf_spec->cdef_data.buf_size);
+	buf_spec->fgs_table.buf_start =
+		WORKBUF_ALIGN(buf_spec->ups_data.buf_start + buf_spec->ups_data.buf_size);
 #ifdef AOM_AV1_MMU
-    buf_spec->mmu_vbh.buf_start =
-		buf_spec->fgs_table.buf_start + buf_spec->fgs_table.buf_size;
-    buf_spec->cm_header.buf_start =
-		buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size;
+	buf_spec->mmu_vbh.buf_start =
+		WORKBUF_ALIGN(buf_spec->fgs_table.buf_start + buf_spec->fgs_table.buf_size);
+	buf_spec->cm_header.buf_start =
+		WORKBUF_ALIGN(buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size);
 #ifdef AOM_AV1_MMU_DW
-    buf_spec->mmu_vbh_dw.buf_start =
-		buf_spec->cm_header.buf_start + buf_spec->cm_header.buf_size;
-    buf_spec->cm_header_dw.buf_start =
-		buf_spec->mmu_vbh_dw.buf_start + buf_spec->mmu_vbh_dw.buf_size;
-    buf_spec->mpred_above.buf_start =
-		buf_spec->cm_header_dw.buf_start + buf_spec->cm_header_dw.buf_size;
+	buf_spec->mmu_vbh_dw.buf_start =
+		WORKBUF_ALIGN(buf_spec->cm_header.buf_start + buf_spec->cm_header.buf_size);
+	buf_spec->cm_header_dw.buf_start =
+		WORKBUF_ALIGN(buf_spec->mmu_vbh_dw.buf_start + buf_spec->mmu_vbh_dw.buf_size);
+	buf_spec->mpred_above.buf_start =
+		WORKBUF_ALIGN(buf_spec->cm_header_dw.buf_start + buf_spec->cm_header_dw.buf_size);
 #else
-    buf_spec->mpred_above.buf_start =
-		buf_spec->cm_header.buf_start + buf_spec->cm_header.buf_size;
+	buf_spec->mpred_above.buf_start =
+		WORKBUF_ALIGN(buf_spec->cm_header.buf_start + buf_spec->cm_header.buf_size);
 #endif
 #else
-    buf_spec->mpred_above.buf_start =
-		buf_spec->fgs_table.buf_start + buf_spec->fgs_table.buf_size;
+	buf_spec->mpred_above.buf_start =
+		WORKBUF_ALIGN(buf_spec->fgs_table.buf_start + buf_spec->fgs_table.buf_size);
 #endif
-
 #ifdef MV_USE_FIXED_BUF
 	buf_spec->mpred_mv.buf_start =
-		buf_spec->mpred_above.buf_start +
-		buf_spec->mpred_above.buf_size;
-
+		WORKBUF_ALIGN(buf_spec->mpred_above.buf_start + buf_spec->mpred_above.buf_size);
 	buf_spec->rpm.buf_start =
-		buf_spec->mpred_mv.buf_start +
-		buf_spec->mpred_mv.buf_size;
+		WORKBUF_ALIGN(buf_spec->mpred_mv.buf_start + buf_spec->mpred_mv.buf_size);
 #else
 	buf_spec->rpm.buf_start =
-		buf_spec->mpred_above.buf_start +
-		buf_spec->mpred_above.buf_size;
-
+		WORKBUF_ALIGN(buf_spec->mpred_above.buf_start + buf_spec->mpred_above.buf_size);
 #endif
 	buf_spec->lmem.buf_start =
-		buf_spec->rpm.buf_start +
-		buf_spec->rpm.buf_size;
+		WORKBUF_ALIGN(buf_spec->rpm.buf_start + buf_spec->rpm.buf_size);
 	buf_spec->end_adr =
-		buf_spec->lmem.buf_start +
-		buf_spec->lmem.buf_size;
+		WORKBUF_ALIGN(buf_spec->lmem.buf_start + buf_spec->lmem.buf_size);
 
 	if (!hw)
 		return;
@@ -2780,64 +2867,13 @@
 	}
 }
 
-static bool v4l_is_there_vframe_bound(struct AV1HW_s *hw)
-{
-	int i;
-	struct AV1_Common_s *const cm = &hw->common;
-	struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs;
 
-	for (i = 0; i < hw->used_buf_num; ++i) {
-		if (frame_bufs[i].buf.vframe_bound)
-			return true;
-	}
-
-	return false;
-}
-
-static void v4l_mmu_buffer_release(struct AV1HW_s *hw)
-{
-	struct AV1_Common_s *const cm = &hw->common;
-	struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs;
-	int i;
-
-	/* release workspace */
-	if (hw->bmmu_box)
-		decoder_bmmu_box_free_idx(hw->bmmu_box,
-			WORK_SPACE_BUF_ID);
-	/*
-	 * it's only when vframe get back to driver, right now we can be sure
-	 * that vframe and fd are related. if the playback exits, the capture
-	 * requires the upper app to release when the fd is closed, and others
-	 * buffers drivers are released by driver.
-	 */
-	for (i = 0; i < hw->used_buf_num; ++i) {
-		if (!frame_bufs[i].buf.vframe_bound) {
-			if (hw->bmmu_box)
-				decoder_bmmu_box_free_idx(hw->bmmu_box,
-					HEADER_BUFFER_IDX(hw->buffer_wrap[i]));
-			if (hw->mmu_box)
-				decoder_mmu_box_free_idx(hw->mmu_box, hw->buffer_wrap[i]);
-
-			av1_print(hw, PRINT_FLAG_V4L_DETAIL,
-				"%s free buffer[%d], bmmu_box: %p, mmu_box: %p\n",
-				__func__, i, hw->bmmu_box, hw->mmu_box);
-		}
-	}
-}
 
 static void uninit_mmu_buffers(struct AV1HW_s *hw)
 {
 #ifndef MV_USE_FIXED_BUF
 	dealloc_mv_bufs(hw);
 #endif
-	if (hw->is_used_v4l &&
-		v4l_is_there_vframe_bound(hw)) {
-		if (get_double_write_mode(hw) != 0x10) {
-			v4l_mmu_buffer_release(hw);
-			return;
-		}
-	}
-
 	if (hw->mmu_box)
 		decoder_mmu_box_free(hw->mmu_box);
 	hw->mmu_box = NULL;
@@ -2864,6 +2900,33 @@
 	return pic_width_lcu * pic_height_lcu;
 }
 
+/* return in MB */
+static int av1_max_mmu_buf_size(int max_w, int max_h)
+{
+	int buf_size = 48;
+
+	if ((max_w * max_h > 1280*736) &&
+		(max_w * max_h <= 1920*1088)) {
+		buf_size = 12;
+	} else if ((max_w * max_h > 0) &&
+		(max_w * max_h <= 1280*736)) {
+		buf_size = 4;
+	}
+
+	return buf_size;
+}
+
+static int av1_get_header_size(int w, int h)
+{
+	if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+		IS_8K_SIZE(w, h))
+		return MMU_COMPRESS_HEADER_SIZE_8K;
+	if (IS_4K_SIZE(w, h))
+		return MMU_COMPRESS_HEADER_SIZE_4K;
+
+	return MMU_COMPRESS_HEADER_SIZE_1080P;
+}
+
 static int v4l_alloc_and_config_pic(struct AV1HW_s *hw,
 	struct PIC_BUFFER_CONFIG_s *pic)
 {
@@ -2882,21 +2945,24 @@
 	  int32_t mv_buffer_size = hw->max_one_mv_buffer_size;
 //#endif
 #endif
+	struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)hw->v4l2_ctx;
 	struct vdec_v4l2_buffer *fb = NULL;
 
 	if (i < 0)
 		return ret;
 
-	ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
+	ret = ctx->fb_ops.alloc(&ctx->fb_ops, hw->fb_token, &fb, AML_FB_REQ_DEC);
 	if (ret < 0) {
-		av1_print(hw, 0, "[%d] AV1 get buffer fail.\n",
-			((struct aml_vcodec_ctx *) (hw->v4l2_ctx))->id);
+		av1_print(hw, 0, "[%d] AV1 get buffer fail.\n", ctx->id);
 		return ret;
 	}
 
+	fb->status	= FB_ST_DECODER;
+
 	if (hw->mmu_enable) {
-		hw->m_BUF[i].header_addr = decoder_bmmu_box_get_phy_addr(
-			hw->bmmu_box, HEADER_BUFFER_IDX(hw->buffer_wrap[i]));
+		struct internal_comp_buf *ibuf = v4lfb_to_icomp_buf(hw, fb);
+
+		hw->m_BUF[i].header_addr = ibuf->header_addr;
 		if (debug & AV1_DEBUG_BUFMGR_MORE) {
 			pr_info("MMU header_adr %d: %ld\n",
 				i, hw->m_BUF[i].header_addr);
@@ -3028,9 +3094,9 @@
 
 	if (dw_mode && (dw_mode & 0x20) == 0) {
 		int pic_width_dw = pic_width /
-			get_double_write_ratio(hw, dw_mode);
+			get_double_write_ratio(dw_mode & 0xf);
 		int pic_height_dw = pic_height /
-			get_double_write_ratio(hw, dw_mode);
+			get_double_write_ratio(dw_mode & 0xf);
 
 		int pic_width_64_dw = (pic_width_dw + 63) & (~0x3f);
 		int pic_height_32_dw = (pic_height_dw + 31) & (~0x1f);
@@ -3073,26 +3139,26 @@
 /*!USE_SPEC_BUF_FOR_MMU_HEAD*/
 	if (hw->mmu_enable) {
 		pic_config->header_adr = decoder_bmmu_box_get_phy_addr(
-			hw->bmmu_box, HEADER_BUFFER_IDX(hw->buffer_wrap[pic_config->index]));
+			hw->bmmu_box, HEADER_BUFFER_IDX(pic_config->index));
 
 #ifdef AOM_AV1_MMU_DW
 		if (hw->dw_mmu_enable) {
 			pic_config->header_dw_adr = decoder_bmmu_box_get_phy_addr(
-				hw->bmmu_box, DW_HEADER_BUFFER_IDX(hw->buffer_wrap[pic_config->index]));
+				hw->bmmu_box, DW_HEADER_BUFFER_IDX(pic_config->index));
 
 		}
 		if (debug & AV1_DEBUG_BUFMGR_MORE) {
 			pr_info("MMU dw header_adr (%d, %d) %d: %d\n",
 				hw->dw_mmu_enable,
-				DW_HEADER_BUFFER_IDX(hw->buffer_wrap[pic_config->index]),
-				hw->buffer_wrap[pic_config->index],
+				DW_HEADER_BUFFER_IDX(pic_config->index),
+				pic_config->index,
 				pic_config->header_dw_adr);
 		}
 #endif
 
 		if (debug & AV1_DEBUG_BUFMGR_MORE) {
 			pr_info("MMU header_adr %d: %d\n",
-				hw->buffer_wrap[pic_config->index], pic_config->header_adr);
+				pic_config->index, pic_config->header_adr);
 		}
 	}
 #endif
@@ -3106,13 +3172,13 @@
 #endif
 		if (buf_size > 0) {
 			ret = decoder_bmmu_box_alloc_buf_phy(hw->bmmu_box,
-					VF_BUFFER_IDX(hw->buffer_wrap[i]),
+					VF_BUFFER_IDX(i),
 					buf_size, DRIVER_NAME,
 					&pic_config->cma_alloc_addr);
 			if (ret < 0) {
 				pr_info(
 					"decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n",
-					VF_BUFFER_IDX(hw->buffer_wrap[i]),
+					VF_BUFFER_IDX(i),
 					buf_size
 					);
 				return ret;
@@ -3123,7 +3189,7 @@
 			else {
 				pr_info(
 					"decoder_bmmu_box_alloc_buf_phy idx %d size %d return null\n",
-					VF_BUFFER_IDX(hw->buffer_wrap[i]),
+					VF_BUFFER_IDX(i),
 					buf_size
 					);
 				return -1;
@@ -3556,8 +3622,10 @@
     seg_map_size =
 	((frame_width + 127) >> 7) * ((frame_height + 127) >> 7) * 384 ;
 	*/
-	WRITE_VREG(HEVC_PARSER_PICTURE_SIZE,
-		(frame_height << 16) | frame_width);
+	if (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T3) {
+		WRITE_VREG(HEVC_PARSER_PICTURE_SIZE,
+			(frame_height << 16) | frame_width);
+	}
 #ifdef DUAL_DECODE
 #else
 	WRITE_VREG(HEVC_ASSIST_PIC_SIZE_FB_READ,
@@ -3830,7 +3898,15 @@
 	cur_pic_config->index, last_frame_pic_config->index);*/
 
 	//WRITE_VREG(HEVC_MPRED_CTRL3,0x24122412);
-	WRITE_VREG(HEVC_MPRED_CTRL3, 0x13151315); // 'd19, 'd21 for AV1
+#ifdef CO_MV_COMPRESS
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T5D) {
+		WRITE_VREG(HEVC_MPRED_CTRL3,0x10151015); // 'd10, 'd21 for AV1
+	} else {
+		WRITE_VREG(HEVC_MPRED_CTRL3,0x13151315); // 'd19, 'd21 for AV1
+	}
+#else
+	WRITE_VREG(HEVC_MPRED_CTRL3,0x13151315); // 'd19, 'd21 for AV1
+#endif
 	WRITE_VREG(HEVC_MPRED_ABV_START_ADDR,
 	hw->pbi->work_space_buf->mpred_above.buf_start);
 
@@ -3856,11 +3932,19 @@
 			"WRITE_VREG(HEVC_MPRED_CTRL4, 0x%x)\n", data32);
 	}
 #if 1
-	data32 = (
-		(cm->seq_params.order_hint_info.enable_order_hint << 27) |
+	data32 = ((cm->seq_params.order_hint_info.enable_order_hint << 27) |
 		(cm->seq_params.order_hint_info.order_hint_bits_minus_1 << 24) |
-		(cm->cur_frame->order_hint <<16 ) |
-		(0x13 << 8) | (0x13 << 0));
+		(cm->cur_frame->order_hint << 16 ));
+#ifdef CO_MV_COMPRESS
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T5D) {
+		data32 |= (0x10 << 8) | (0x10 << 0);
+	} else {
+		data32 |= (0x13 << 8) | (0x13 << 0);
+	}
+#else
+		data32 |= (0x13 << 8) | (0x13 << 0);
+#endif
+
 #else
 	data32 = READ_VREG(HEVC_MPRED_L0_REF00_POC);
 	data32 &= (~(0xff << 16));
@@ -3989,7 +4073,7 @@
 	WRITE_VREG(HEVC_MPRED_MV_WPTR,
 		cur_pic_config->mpred_mv_wr_start_addr);
 
-	if ((inter_flag) && (mv_cal_tpl_count <= 3)) {
+	if (inter_flag) {
 		for (i = 0; i < mv_cal_tpl_count; i++) {
 			PIC_BUFFER_CONFIG *pic_config =
 			av1_get_ref_frame_spec_buf(cm, mv_ref_id[i]);
@@ -4010,6 +4094,9 @@
 					pic_config->mpred_mv_wr_start_addr);
 				WRITE_VREG(HEVC_MPRED_MV_RPTR_2,
 					pic_config->mpred_mv_wr_start_addr);
+			} else {
+				av1_print(hw, AOM_DEBUG_HW_MORE,
+					"%s: mv_ref_id error\n", __func__);
 			}
 		}
 	}
@@ -4049,7 +4136,7 @@
 	!!!!!!!!!!!!!!!!!!!!!!!!!TODO .... !!!!!!!!!!!
 	mem_map_mode, endian, get_double_write_mode
 	*/
-    AV1_COMMON *cm = &hw->common;
+	AV1_COMMON *cm = &hw->common;
     PIC_BUFFER_CONFIG* pic_config = &cm->cur_frame->buf;
     uint32_t data32;
     int32_t lcu_size =
@@ -4156,7 +4243,7 @@
 #ifdef DOS_PROJECT
     data32 = READ_VREG(HEVC_SAO_CTRL1);
     data32 &= (~0x3000);
-    data32 |= (MEM_MAP_MODE << 12); // [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32
+    data32 |= (hw->mem_map_mode << 12); // [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32
     data32 &= (~0x3);
     data32 |= 0x1; // [1]:dw_disable [0]:cm_disable
     WRITE_VREG(HEVC_SAO_CTRL1, data32);
@@ -4167,13 +4254,13 @@
 
     data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
     data32 &= (~0x30);
-    data32 |= (MEM_MAP_MODE << 4); // [5:4]	-- address_format 00:linear 01:32x32 10:64x32
+    data32 |= (hw->mem_map_mode << 4); // [5:4]	-- address_format 00:linear 01:32x32 10:64x32
     WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32);
 #else
 // m8baby test1902
    data32 = READ_VREG(HEVC_SAO_CTRL1);
 	data32 &= (~0x3000);
-	data32 |= (MEM_MAP_MODE << 12); // [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32
+	data32 |= (hw->mem_map_mode << 12); // [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32
     data32 &= (~0xff0);
 	//data32 |= 0x670;  // Big-Endian per 64-bit
     data32 |= 0x880;  // Big-Endian per 64-bit
@@ -4187,7 +4274,7 @@
 
     data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
 	data32 &= (~0x30);
-	data32 |= (MEM_MAP_MODE << 4); // [5:4]	-- address_format 00:linear 01:32x32 10:64x32
+	data32 |= (hw->mem_map_mode << 4); // [5:4]	-- address_format 00:linear 01:32x32 10:64x32
 	data32 &= (~0xF);
     data32 |= 0x8;	// Big-Endian per 64-bit
     WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32);
@@ -4196,19 +4283,14 @@
 /*CHANGE_DONE nnn*/
 	data32 = READ_VREG(HEVC_SAO_CTRL1);
 	data32 &= (~0x3000);
-	data32 |= (mem_map_mode <<
-			   12);
-
-/*  [13:12] axi_aformat, 0-Linear,
- *				   1-32x32, 2-64x32
- */
+	data32 |= (hw->mem_map_mode << 12); /* [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32 */
 	data32 &= (~0xff0);
 	/* data32 |= 0x670;  // Big-Endian per 64-bit */
 #ifdef AOM_AV1_MMU_DW
 	if (hw->dw_mmu_enable == 0)
-		data32 |= endian;	/* Big-Endian per 64-bit */
+		data32 |= ((hw->endian >> 8) & 0xfff);	/* Big-Endian per 64-bit */
 #else
-	data32 |= endian;	/* Big-Endian per 64-bit */
+	data32 |= ((hw->endian >> 8) & 0xfff);	/* Big-Endian per 64-bit */
 #endif
 	data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/
 	if (get_double_write_mode(hw) == 0)
@@ -4236,7 +4318,8 @@
 		else
 			data32 |= (1 << 8); /* NV12 */
 	}
-
+	data32 &= (~(3 << 14));
+	data32 |= (2 << 14);
 	/*
 	*  [31:24] ar_fifo1_axi_thred
 	*  [23:16] ar_fifo0_axi_thred
@@ -4262,9 +4345,14 @@
 		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(hw) & 0xf) == 2 ||
+		if ((get_double_write_mode(hw) & 0xf) == 8) {
+			WRITE_VREG(HEVC_SAO_CTRL26, 0xf);
+			data32 |= (0xff << 16);
+		} else if ((get_double_write_mode(hw) & 0xf) == 2 ||
 			(get_double_write_mode(hw) & 0xf) == 3)
 			data32 |= (0xff<<16);
 		else if ((get_double_write_mode(hw) & 0xf) == 4 ||
@@ -4276,11 +4364,9 @@
 	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 |= 0xf;  /* valid only when double write only */
-		/*data32 |= 0x8;*/		/* Big-Endian per 64-bit */
+	data32 |= (hw->mem_map_mode << 4);
+	data32 &= (~0xf);
+	data32 |= (hw->endian & 0xf);  /* valid only when double write only */
 
 	/* swap uv */
 	if (hw->is_used_v4l) {
@@ -4290,7 +4376,8 @@
 		else
 			data32 &= ~(1 << 12); /* NV12 */
 	}
-
+	data32 &= (~(3 << 8));
+	data32 |= (2 << 8);
 	/*
 	* [3:0]   little_endian
 	* [5:4]   address_format 00:linear 01:32x32 10:64x32
@@ -4855,7 +4942,7 @@
 	lf->sharpness_level =
 		hw->aom_param.p.loop_filter_sharpness_level;
 	if (((hw->aom_param.p.loop_filter_mode_ref_delta_enabled)&3) == 3) { // enabled but and update
-		if (cm->prev_frame == NULL) {
+		if (cm->prev_frame <= 0) {
 		  // already initialized in Microcode
 			lf->ref_deltas[0] = conv2int8((uint8_t)(hw->aom_param.p.loop_filter_ref_deltas_0),7);
 			lf->ref_deltas[1]	= conv2int8((uint8_t)(hw->aom_param.p.loop_filter_ref_deltas_0>>8),7);
@@ -4901,7 +4988,7 @@
 		}
 	} //else if (hw->aom_param.p.loop_filter_mode_ref_delta_enabled == 1) { // enabled but no update
 	  else { // match c code -- not enabled, still need to copy prev to used for next
-		if ((cm->prev_frame == NULL) | (hw->aom_param.p.loop_filter_mode_ref_delta_enabled & 4)) {
+		if ((cm->prev_frame <= 0) | (hw->aom_param.p.loop_filter_mode_ref_delta_enabled & 4)) {
 			av1_print(hw, AOM_DEBUG_HW_MORE,
 				"[test.c] mode_ref_delta set to default\n");
 			lf->ref_deltas[0] = conv2int8((uint8_t)1,7);
@@ -4917,18 +5004,16 @@
 		} else {
 			av1_print(hw, AOM_DEBUG_HW_MORE,
 				"[test.c] mode_ref_delta copy from prev_frame\n");
-			if (cm->prev_frame) {
-				lf->ref_deltas[0]			   = cm->prev_frame->ref_deltas[0];
-				lf->ref_deltas[1]			   = cm->prev_frame->ref_deltas[1];
-				lf->ref_deltas[2]			   = cm->prev_frame->ref_deltas[2];
-				lf->ref_deltas[3]			   = cm->prev_frame->ref_deltas[3];
-				lf->ref_deltas[4]			   = cm->prev_frame->ref_deltas[4];
-				lf->ref_deltas[5]			   = cm->prev_frame->ref_deltas[5];
-				lf->ref_deltas[6]			   = cm->prev_frame->ref_deltas[6];
-				lf->ref_deltas[7]			   = cm->prev_frame->ref_deltas[7];
-				lf->mode_deltas[0]			  = cm->prev_frame->mode_deltas[0];
-				lf->mode_deltas[1]			  = cm->prev_frame->mode_deltas[1];
-			}
+			lf->ref_deltas[0]			   = cm->prev_frame->ref_deltas[0];
+			lf->ref_deltas[1]			   = cm->prev_frame->ref_deltas[1];
+			lf->ref_deltas[2]			   = cm->prev_frame->ref_deltas[2];
+			lf->ref_deltas[3]			   = cm->prev_frame->ref_deltas[3];
+			lf->ref_deltas[4]			   = cm->prev_frame->ref_deltas[4];
+			lf->ref_deltas[5]			   = cm->prev_frame->ref_deltas[5];
+			lf->ref_deltas[6]			   = cm->prev_frame->ref_deltas[6];
+			lf->ref_deltas[7]			   = cm->prev_frame->ref_deltas[7];
+			lf->mode_deltas[0]			  = cm->prev_frame->mode_deltas[0];
+			lf->mode_deltas[1]			  = cm->prev_frame->mode_deltas[1];
 		}
 	}
 	lf->filter_level[0]			 = hw->aom_param.p.loop_filter_level_0;
@@ -4936,24 +5021,23 @@
 	lf->filter_level_u    		  = hw->aom_param.p.loop_filter_level_u;
 	lf->filter_level_v    		  = hw->aom_param.p.loop_filter_level_v;
 
-	if (cm->cur_frame) {
-		cm->cur_frame->ref_deltas[0] = lf->ref_deltas[0];
-		cm->cur_frame->ref_deltas[1] = lf->ref_deltas[1];
-		cm->cur_frame->ref_deltas[2] = lf->ref_deltas[2];
-		cm->cur_frame->ref_deltas[3] = lf->ref_deltas[3];
-		cm->cur_frame->ref_deltas[4] = lf->ref_deltas[4];
-		cm->cur_frame->ref_deltas[5] = lf->ref_deltas[5];
-		cm->cur_frame->ref_deltas[6] = lf->ref_deltas[6];
-		cm->cur_frame->ref_deltas[7] = lf->ref_deltas[7];
-		cm->cur_frame->mode_deltas[0] = lf->mode_deltas[0];
-		cm->cur_frame->mode_deltas[1] = lf->mode_deltas[1];
+	cm->cur_frame->ref_deltas[0] = lf->ref_deltas[0];
+	cm->cur_frame->ref_deltas[1] = lf->ref_deltas[1];
+	cm->cur_frame->ref_deltas[2] = lf->ref_deltas[2];
+	cm->cur_frame->ref_deltas[3] = lf->ref_deltas[3];
+	cm->cur_frame->ref_deltas[4] = lf->ref_deltas[4];
+	cm->cur_frame->ref_deltas[5] = lf->ref_deltas[5];
+	cm->cur_frame->ref_deltas[6] = lf->ref_deltas[6];
+	cm->cur_frame->ref_deltas[7] = lf->ref_deltas[7];
+	cm->cur_frame->mode_deltas[0] = lf->mode_deltas[0];
+	cm->cur_frame->mode_deltas[1] = lf->mode_deltas[1];
 
-		// get seg_4lf parameters from parser
-		seg_4lf->enabled = hw->aom_param.p.segmentation_enabled & 1;
-		cm->cur_frame->segmentation_enabled = hw->aom_param.p.segmentation_enabled & 1;
-		cm->cur_frame->intra_only = (hw->aom_param.p.segmentation_enabled >> 2) & 1;
-		cm->cur_frame->segmentation_update_map = (hw->aom_param.p.segmentation_enabled >> 3) & 1;
-	}
+	// get seg_4lf parameters from parser
+	seg_4lf->enabled = hw->aom_param.p.segmentation_enabled & 1;
+	cm->cur_frame->segmentation_enabled = hw->aom_param.p.segmentation_enabled & 1;
+	cm->cur_frame->intra_only = (hw->aom_param.p.segmentation_enabled >> 2) & 1;
+	cm->cur_frame->segmentation_update_map = (hw->aom_param.p.segmentation_enabled >> 3) & 1;
+
 	if (hw->aom_param.p.segmentation_enabled & 1) { // segmentation_enabled
 		if (hw->aom_param.p.segmentation_enabled & 2) { // segmentation_update_data
 			for (i = 0; i < MAX_SEGMENTS; i++) {
@@ -4966,7 +5050,7 @@
 				}
 			} // segmentation_update_data
 			else { // no segmentation_update_data
-				if (cm->prev_frame == NULL) {
+				if (cm->prev_frame <= 0) {
 					for (i=0;i<MAX_SEGMENTS;i++) {
 						seg_4lf->seg_lf_info_y[i] = 0;
 						seg_4lf->seg_lf_info_c[i] = 0;
@@ -5022,7 +5106,7 @@
 	av1_print(hw, AOM_DEBUG_HW_MORE,
 		"[test.c] cur_frame : %p prev_frame : %p - %p \n",
 		cm->cur_frame, cm->prev_frame, av1_get_primary_ref_frame_buf(cm));
-	if (cm->cur_frame == NULL) {
+	if (cm->cur_frame <= 0) {
 		WRITE_VREG(AOM_AV1_CDF_BUFFER_W, buf_spec->cdf_buf.buf_start);
 		WRITE_VREG(AOM_AV1_SEG_MAP_BUFFER_W, buf_spec->seg_map.buf_start);
 	}
@@ -5037,7 +5121,7 @@
 	}
 	cm->cur_frame->seg_mi_rows = cm->cur_frame->mi_rows;
 	cm->cur_frame->seg_mi_cols = cm->cur_frame->mi_cols;
-	if (cm->prev_frame == NULL) {
+	if (cm->prev_frame <= 0) {
 		WRITE_VREG(AOM_AV1_CDF_BUFFER_R, buf_spec->cdf_buf.buf_start);
 		WRITE_VREG(AOM_AV1_SEG_MAP_BUFFER_R, buf_spec->seg_map.buf_start);
 	} else {
@@ -5322,6 +5406,13 @@
 	}
 #endif
 #endif
+#ifdef CO_MV_COMPRESS
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T5D) {
+	    data32 = READ_VREG(HEVC_MPRED_CTRL4);
+	    data32 |=  (1 << 1);
+	    WRITE_VREG(HEVC_MPRED_CTRL4, data32);
+	}
+#endif
 	}
 
 	config_aux_buf(hw);
@@ -5427,10 +5518,13 @@
 	if (mask & HW_MASK_BACK) {
 		/*Initial IQIT_SCALELUT memory
 		-- just to avoid X in simulation*/
-
-		WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);/*cfg_p_addr*/
-		for (i = 0; i < 1024; i++)
-			WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0);
+		if (is_rdma_enable())
+			rdma_back_end_work(hw->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);
+		}
 	}
 
 	if (mask & HW_MASK_FRONT) {
@@ -5758,25 +5852,14 @@
 		buf_alloc_width = 8192;
 		buf_alloc_height = 4608;
 	}
-#if 0
-	hw->init_pic_w = hw->max_pic_w ? hw->max_pic_w :
-		(buf_alloc_width ? buf_alloc_width :
-		(hw->vav1_amstream_dec_info.width ?
-		hw->vav1_amstream_dec_info.width :
-		hw->work_space_buf->max_width));
-	hw->init_pic_h = hw->max_pic_h ? hw->max_pic_h :
-		(buf_alloc_height ? buf_alloc_height :
-		(hw->vav1_amstream_dec_info.height ?
-		hw->vav1_amstream_dec_info.height :
-		hw->work_space_buf->max_height));
-#else
+
 	hw->init_pic_w = hw->max_pic_w ? hw->max_pic_w :
 		(hw->vav1_amstream_dec_info.width ? hw->vav1_amstream_dec_info.width :
 		(buf_alloc_width ? buf_alloc_width : hw->work_space_buf->max_width));
 	hw->init_pic_h = hw->max_pic_h ? hw->max_pic_h :
 		(hw->vav1_amstream_dec_info.height ? hw->vav1_amstream_dec_info.height :
 		(buf_alloc_height ? buf_alloc_height : hw->work_space_buf->max_height));
-#endif
+
     hw->pbi->frame_width = hw->init_pic_w;
     hw->pbi->frame_height = hw->init_pic_h;
 
@@ -5789,9 +5872,9 @@
 		(hw->vav1_amstream_dec_info.width % 64) != 0)) {
 		if (hw_to_vdec(hw)->canvas_mode !=
 			CANVAS_BLKMODE_LINEAR)
-			mem_map_mode = 2;
+			hw->mem_map_mode = 2;
 		else {
-			mem_map_mode = 0;
+			hw->mem_map_mode = 0;
 			av1_print(hw, AOM_DEBUG_HW_MORE, "vdec blkmod linear, force mem_map_mode 0\n");
 		}
 	}
@@ -5895,6 +5978,7 @@
 	}
 	memset(hw->count_buffer_addr, 0, COUNT_BUF_SIZE);
 
+	vdec_set_vframe_comm(hw_to_vdec(hw), DRIVER_NAME);
 	ret = vav1_mmu_map_alloc(hw);
 	if (ret < 0)
 		goto dma_alloc_fail;
@@ -5919,20 +6003,18 @@
 	struct vdec_s *vdec = hw_to_vdec(hw);
 	int canvas_w = ALIGN(pic_config->y_crop_width, 64)/4;
 	int canvas_h = ALIGN(pic_config->y_crop_height, 32)/4;
-	int blkmode = mem_map_mode;
+	int blkmode = hw->mem_map_mode;
 	/*CANVAS_BLKMODE_64X32*/
 	if	(pic_config->double_write_mode) {
 		canvas_w = pic_config->y_crop_width	/
-				get_double_write_ratio(hw,
-					pic_config->double_write_mode);
+				get_double_write_ratio(
+					pic_config->double_write_mode & 0xf);
 		canvas_h = pic_config->y_crop_height /
-				get_double_write_ratio(hw,
-					pic_config->double_write_mode);
+				get_double_write_ratio(
+					pic_config->double_write_mode & 0xf);
 
-		if (mem_map_mode == 0)
-			canvas_w = ALIGN(canvas_w, 32);
-		else
-			canvas_w = ALIGN(canvas_w, 64);
+		/* sao ctrl1 config aligned with 64, so aligned with 64 same */
+		canvas_w = ALIGN(canvas_w, 64);
 		canvas_h = ALIGN(canvas_h, 32);
 
 		if (vdec->parallel_dec == 1) {
@@ -5947,12 +6029,12 @@
 			pic_config->uv_canvas_index = 128 + pic_config->index * 2 + 1;
 		}
 
-		canvas_config_ex(pic_config->y_canvas_index,
+		config_cav_lut_ex(pic_config->y_canvas_index,
 			pic_config->dw_y_adr, canvas_w, canvas_h,
-			CANVAS_ADDR_NOWRAP, blkmode, hw->is_used_v4l ? 0 : 7);
-		canvas_config_ex(pic_config->uv_canvas_index,
+			CANVAS_ADDR_NOWRAP, blkmode, hw->is_used_v4l ? 0 : 7, VDEC_HEVC);
+		config_cav_lut_ex(pic_config->uv_canvas_index,
 			pic_config->dw_u_v_adr,	canvas_w, canvas_h,
-			CANVAS_ADDR_NOWRAP, blkmode, hw->is_used_v4l ? 0 : 7);
+			CANVAS_ADDR_NOWRAP, blkmode, hw->is_used_v4l ? 0 : 7, VDEC_HEVC);
 
 #ifdef MULTI_INSTANCE_SUPPORT
 		pic_config->canvas_config[0].phy_addr =
@@ -6061,10 +6143,11 @@
 	if (kfifo_get(&hw->display_q, &vf)) {
 		struct vframe_s *next_vf = NULL;
 		uint8_t index = vf->index & 0xff;
-		ATRACE_COUNTER(hw->disp_q_name, kfifo_len(&hw->display_q));
+		ATRACE_COUNTER(hw->trace.disp_q_name, kfifo_len(&hw->display_q));
 		if (index < hw->used_buf_num ||
 			(vf->type & VIDTYPE_V4L_EOS)) {
 			hw->vf_get_count++;
+			vf->index_disp = hw->vf_get_count;
 			if (debug & AOM_DEBUG_VFRAME) {
 				struct BufferPool_s *pool = hw->common.buffer_pool;
 				struct PIC_BUFFER_CONFIG_s *pic =
@@ -6110,16 +6193,14 @@
 static void vav1_vf_put(struct vframe_s *vf, void *op_arg)
 {
 	struct AV1HW_s *hw = (struct AV1HW_s *)op_arg;
-	uint8_t index;
+	uint8_t index = vf->index & 0xff;
 	unsigned long flags;
 
 	if ((vf == NULL) || (hw == NULL))
 		return;
 
-	index = vf->index & 0xff;
-
 	kfifo_put(&hw->newframe_q, (const struct vframe_s *)vf);
-	ATRACE_COUNTER(hw->new_q_name, kfifo_len(&hw->newframe_q));
+	ATRACE_COUNTER(hw->trace.new_q_name, kfifo_len(&hw->newframe_q));
 	hw->vf_put_count++;
 	if (debug & AOM_DEBUG_VFRAME) {
 		lock_buffer_pool(hw->common.buffer_pool, flags);
@@ -6141,10 +6222,6 @@
 			if (pool->frame_bufs[index].buf.vf_ref > 0)
 				pool->frame_bufs[index].buf.vf_ref--;
 		}
-
-		if (hw->is_used_v4l)
-			pool->frame_bufs[index].buf.vframe_bound = true;
-
 		if (hw->wait_buf)
 			WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG,
 						0x1);
@@ -6325,27 +6402,27 @@
 			(debug & AOM_DEBUG_DW_DISP_MAIN) == 0) {
 			vf->mem_handle =
 				decoder_mmu_box_get_mem_handle(
-					hw->mmu_box_dw, hw->buffer_wrap[pic->index]);
+					hw->mmu_box_dw, pic->index);
 			vf->mem_head_handle =
 				decoder_bmmu_box_get_mem_handle(
 					hw->bmmu_box,
-					DW_HEADER_BUFFER_IDX(hw->buffer_wrap[pic->BUF_index]));
+					DW_HEADER_BUFFER_IDX(pic->BUF_index));
 			vf->mem_dw_handle = NULL;
 		} else
 #endif
 		{
 		vf->mem_handle =
 			decoder_mmu_box_get_mem_handle(
-				hw->mmu_box, hw->buffer_wrap[pic->index]);
+				hw->mmu_box, pic->index);
 		vf->mem_head_handle =
 			decoder_bmmu_box_get_mem_handle(
 				hw->bmmu_box,
-				HEADER_BUFFER_IDX(hw->buffer_wrap[pic->BUF_index]));
+				HEADER_BUFFER_IDX(pic->BUF_index));
 		if (hw->double_write_mode == 3)
 			vf->mem_dw_handle =
 				decoder_bmmu_box_get_mem_handle(
 					hw->bmmu_box,
-					VF_BUFFER_IDX(hw->buffer_wrap[pic->BUF_index]));
+					VF_BUFFER_IDX(pic->BUF_index));
 		else
 			vf->mem_dw_handle = NULL;
 		}
@@ -6355,7 +6432,7 @@
 	} else {
 		vf->mem_handle =
 			decoder_bmmu_box_get_mem_handle(
-				hw->bmmu_box, VF_BUFFER_IDX(hw->buffer_wrap[pic->BUF_index]));
+				hw->bmmu_box, VF_BUFFER_IDX(pic->BUF_index));
 		vf->mem_head_handle = NULL;
 		vf->mem_dw_handle = NULL;
 		/*vf->mem_head_handle =
@@ -6365,22 +6442,47 @@
 	}
 }
 
+static inline void av1_update_gvs(struct AV1HW_s *hw, struct vframe_s *vf,
+				  struct PIC_BUFFER_CONFIG_s *pic_config)
+{
+	if (hw->gvs->frame_height != pic_config->y_crop_height) {
+		hw->gvs->frame_width = pic_config->y_crop_width;
+		hw->gvs->frame_height = pic_config->y_crop_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;
+	}
+	if (vf && hw->gvs->ratio_control != vf->ratio_control)
+		hw->gvs->ratio_control = vf->ratio_control;
+
+	hw->gvs->status = hw->stat | hw->fatal_error;
+	hw->gvs->error_count = hw->gvs->error_frame_count;
+
+}
+
 static int prepare_display_buf(struct AV1HW_s *hw,
 				struct PIC_BUFFER_CONFIG_s *pic_config)
 {
 	struct vframe_s *vf = NULL;
+	struct vdec_info tmp4x;
 	int stream_offset = pic_config->stream_offset;
 	struct aml_vcodec_ctx * v4l2_ctx = hw->v4l2_ctx;
+	struct vdec_v4l2_buffer *fb = NULL;
 	ulong nv_order = VIDTYPE_VIU_NV21;
 	u32 pts_valid = 0, pts_us64_valid = 0;
-	u32 frame_size = 0;
-	int i, reclac_flag = 0;
+	u32 frame_size;
 
 	av1_print(hw, AOM_DEBUG_VFRAME, "%s index = %d\r\n", __func__, pic_config->index);
 	if (kfifo_get(&hw->newframe_q, &vf) == 0) {
 		av1_print(hw, 0, "fatal error, no available buffer slot.");
 		return -1;
 	}
+
 	/* swap uv */
 	if (hw->is_used_v4l) {
 		if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) ||
@@ -6394,49 +6496,10 @@
 
 	display_frame_count[hw->index]++;
 	if (vf) {
-		if (!force_pts_unstable && (hw->av1_first_pts_ready)) {
-			if (hw->is_used_v4l) {
-				if ((pic_config->timestamp == 0) || (pic_config->timestamp <= hw->last_timestamp)) {
-					for (i = (FRAME_BUFFERS - 1); i > 0; i--) {
-						if (hw->last_timestamp == hw->frame_mode_timestamp_save[i]) {
-							pic_config->timestamp = hw->frame_mode_timestamp_save[i - 1];
-							break;
-						}
-					}
-
-					if ((i == 0) || (pic_config->timestamp <= hw->last_timestamp)) {
-						av1_print(hw, AV1_DEBUG_OUT_PTS,
-							"no found timestamp %d, set 0. %lld, %lld\n",
-							i, pic_config->timestamp, hw->last_timestamp);
-						pic_config->timestamp = 0;
-					}
-				}
-			} else {
-				if ((pic_config->pts == 0) || ((pic_config->pts <= hw->last_pts) &&
-					(pic_config->pts64 <= hw->last_pts_us64))) {
-					for (i = (FRAME_BUFFERS - 1); i > 0; i--) {
-						if ((hw->last_pts == hw->frame_mode_pts_save[i]) ||
-							(hw->last_pts_us64 == hw->frame_mode_pts64_save[i])) {
-							pic_config->pts = hw->frame_mode_pts_save[i - 1];
-							pic_config->pts64 = hw->frame_mode_pts64_save[i - 1];
-							break;
-						}
-					}
-
-					if ((i == 0) || (pic_config->pts <= hw->last_pts)) {
-						av1_print(hw, AV1_DEBUG_OUT_PTS,
-							"no found pts %d, set 0. %d, %d\n",
-							i, pic_config->pts, hw->last_pts);
-						pic_config->pts = 0;
-						pic_config->pts64 = 0;
-					}
-				}
-			}
-		}
-
 		if (hw->is_used_v4l) {
 			vf->v4l_mem_handle
 				= hw->m_BUF[pic_config->BUF_index].v4l_ref_buf_addr;
+			fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
 			if (hw->mmu_enable) {
 				vf->mm_box.bmmu_box	= hw->bmmu_box;
 				vf->mm_box.bmmu_idx	= HEADER_BUFFER_IDX(hw->buffer_wrap[pic_config->BUF_index]);
@@ -6449,7 +6512,12 @@
 		if (vdec_frame_based(hw_to_vdec(hw))) {
 			vf->pts = pic_config->pts;
 			vf->pts_us64 = pic_config->pts64;
-			vf->timestamp = pic_config->timestamp;
+
+			if (hw->is_used_v4l && v4l_bitstream_id_enable)
+				vf->timestamp = pic_config->timestamp;
+			else
+				vf->timestamp = pic_config->pts64;
+
 			if (vf->pts != 0 || vf->pts_us64 != 0) {
 				pts_valid = 1;
 				pts_us64_valid = 1;
@@ -6477,68 +6545,6 @@
 			pts_valid = 1;
 			pts_us64_valid = 1;
 		}
-
-		if (hw->av1_first_pts_ready) {
-			if (hw->is_used_v4l) {
-				if (hw->frame_dur && (vf->timestamp == 0)) {
-					vf->timestamp = hw->last_timestamp +
-						hw->timestamp_duration;
-				}
-
-				if (!close_to(vf->timestamp, (hw->last_timestamp +
-					hw->timestamp_duration), 100)) {
-					vf->timestamp = hw->last_timestamp +
-						hw->timestamp_duration;
-				}
-			} else {
-				if (hw->frame_dur && ((vf->pts == 0) || (vf->pts_us64 == 0))) {
-					vf->pts = hw->last_pts + DUR2PTS(hw->frame_dur);
-					vf->pts_us64 = hw->last_pts_us64 +
-						(DUR2PTS(hw->frame_dur) * 100 / 9);
-					reclac_flag = 1;
-				}
-
-				if (!close_to(vf->pts, (hw->last_pts + DUR2PTS(hw->frame_dur)), 100)) {
-					vf->pts = hw->last_pts + DUR2PTS(hw->frame_dur);
-					vf->pts_us64 = hw->last_pts_us64 +
-						(DUR2PTS(hw->frame_dur) * 100 / 9);
-					reclac_flag = 2;
-				}
-			}
-
-			/* try find the closed pts in saved pts pool */
-			if (reclac_flag) {
-				for (i = 0; i < FRAME_BUFFERS - 1; i++) {
-					if ((hw->frame_mode_pts_save[i] > vf->pts) &&
-						(hw->frame_mode_pts_save[i + 1] < vf->pts)) {
-						if ((hw->frame_mode_pts_save[i] - vf->pts) >
-							(vf->pts - hw->frame_mode_pts_save[i + 1])) {
-							vf->pts = hw->frame_mode_pts_save[i + 1];
-							vf->pts_us64 = hw->frame_mode_pts64_save[i + 1];
-						} else {
-							vf->pts = hw->frame_mode_pts_save[i];
-							vf->pts_us64 = hw->frame_mode_pts64_save[i];
-						}
-						break;
-					}
-				}
-				if (i == (FRAME_BUFFERS - 1))
-					hw->dur_recalc_flag = 1;
-			}
-		} else {
-			av1_print(hw, AV1_DEBUG_OUT_PTS,
-				"first pts %d change to save[%d] %d, ts: %llu\n",
-				vf->pts, hw->first_pts_index - 1,
-				hw->frame_mode_pts_save[hw->first_pts_index - 1],
-				hw->frame_mode_timestamp_save[hw->first_pts_index - 1]);
-			vf->pts = hw->frame_mode_pts_save[hw->first_pts_index - 1];
-			vf->pts_us64 = hw->frame_mode_pts64_save[hw->first_pts_index - 1];
-			vf->timestamp  = hw->frame_mode_timestamp_save[hw->first_pts_index - 1];
-		}
-		hw->last_pts = vf->pts;
-		hw->last_pts_us64 = vf->pts_us64;
-		hw->last_timestamp = vf->timestamp;
-		hw->av1_first_pts_ready = true;
 		av1_print(hw, AV1_DEBUG_OUT_PTS,
 			"av1 output slice type %d, dur %d, pts %d, pts64 %lld, ts: %llu\n",
 			pic_config->slice_type, hw->frame_dur, vf->pts, vf->pts_us64, vf->timestamp);
@@ -6569,10 +6575,10 @@
 						vf->dwHeadAddr = pic_config->header_dw_adr;
 					else if ((mode == 1 || mode == 2 || mode == 4)
 					&& (debug & AOM_DEBUG_DW_DISP_MAIN) == 0) {
-					vf->compHeadAddr = pic_config->header_dw_adr;
-					vf->fgs_valid = 0;
-					av1_print(hw, AOM_DEBUG_VFRAME,
-						"Use dw mmu for display\n");
+						vf->compHeadAddr = pic_config->header_dw_adr;
+						vf->fgs_valid = 0;
+						av1_print(hw, 0,
+							"Use dw mmu for display\n");
 					}
 				}
 #endif
@@ -6588,7 +6594,7 @@
 			(pic_config->double_write_mode & 0x20) == 0) {
 			vf->type = VIDTYPE_PROGRESSIVE |
 				VIDTYPE_VIU_FIELD;
-			vf->type |= VIDTYPE_VIU_NV21;
+			vf->type |= nv_order;
 			if ((pic_config->double_write_mode == 3 ||
 				pic_config->double_write_mode == 5) &&
 				(!IS_8K_SIZE(pic_config->y_crop_width,
@@ -6649,11 +6655,11 @@
 		   vf->width,vf->height, pic_config->width,
 			pic_config->height); */
 		vf->width = pic_config->y_crop_width /
-			get_double_write_ratio(hw,
-				pic_config->double_write_mode);
+			get_double_write_ratio(
+				pic_config->double_write_mode & 0xf);
 		vf->height = pic_config->y_crop_height /
-			get_double_write_ratio(hw,
-				pic_config->double_write_mode);
+			get_double_write_ratio(
+				pic_config->double_write_mode & 0xf);
 		if (force_w_h != 0) {
 			vf->width = (force_w_h >> 16) & 0xffff;
 			vf->height = force_w_h & 0xffff;
@@ -6662,11 +6668,11 @@
 			((pic_config->double_write_mode & 0xf) == 2 ||
 			(pic_config->double_write_mode & 0xf) == 4)) {
 			vf->compWidth = pic_config->y_crop_width /
-				get_double_write_ratio(hw,
-					pic_config->double_write_mode);
+				get_double_write_ratio(
+					pic_config->double_write_mode & 0xf);
 			vf->compHeight = pic_config->y_crop_height /
-				get_double_write_ratio(hw,
-					pic_config->double_write_mode);
+				get_double_write_ratio(
+					pic_config->double_write_mode & 0xf);
 		} else {
 			vf->compWidth = pic_config->y_crop_width;
 			vf->compHeight = pic_config->y_crop_height;
@@ -6686,20 +6692,60 @@
 		decoder_do_frame_check(hw_to_vdec(hw), vf);
 		vdec_vframe_ready(hw_to_vdec(hw), 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));
+		ATRACE_COUNTER(hw->trace.pts_name, vf->pts);
+		ATRACE_COUNTER(hw->trace.new_q_name, kfifo_len(&hw->newframe_q));
+		ATRACE_COUNTER(hw->trace.disp_q_name, kfifo_len(&hw->display_q));
 
 		hw->vf_pre_count++;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
 		/*count info*/
-		gvs->frame_dur = hw->frame_dur;
-		vdec_count_info(gvs, 0, stream_offset);
-#endif
+		hw->gvs->frame_dur = hw->frame_dur;
+		vdec_count_info(hw->gvs, 0, stream_offset);
+
 		hw_to_vdec(hw)->vdec_fps_detec(hw_to_vdec(hw)->id);
+
+#ifdef AUX_DATA_CRC
+		decoder_do_aux_data_check(hw_to_vdec(hw), pic_config->aux_data_buf,
+			pic_config->aux_data_size);
+#endif
+
+		av1_print(hw, AV1_DEBUG_SEI_DETAIL, "%s aux_data_size = %d\n",
+				__func__, pic_config->aux_data_size);
+
+		if (debug & AV1_DEBUG_SEI_DETAIL) {
+			int i = 0;
+			PR_INIT(128);
+			for (i = 0; i < pic_config->aux_data_size; i++) {
+				PR_FILL("%02x ", pic_config->aux_data_buf[i]);
+				if (((i + 1) & 0xf) == 0)
+					PR_INFO(hw->index);
+			}
+			PR_INFO(hw->index);
+		}
+
+		if (hw->is_used_v4l) {
+			update_vframe_src_fmt(vf,
+				pic_config->aux_data_buf,
+				pic_config->aux_data_size,
+				false, hw->provider_name, NULL);
+		}
+
+		av1_update_gvs(hw, vf, pic_config);
+		memcpy(&tmp4x, hw->gvs, sizeof(struct vdec_info));
+		tmp4x.bit_depth_luma = bit_depth_luma;
+		tmp4x.bit_depth_chroma = bit_depth_chroma;
+		tmp4x.double_write_mode = pic_config->double_write_mode;
+		vdec_fill_vdec_frame(hw_to_vdec(hw), &hw->vframe_qos, &tmp4x, vf, pic_config->hw_decode_time);
 		if (without_display_mode == 0) {
-			vf_notify_receiver(hw->provider_name,
-				VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+			if (hw->is_used_v4l) {
+				if (v4l2_ctx->is_stream_off) {
+					vav1_vf_put(vav1_vf_get(hw), hw);
+				} else {
+					fb->task->submit(fb->task, TASK_TYPE_DEC);
+				}
+			} else {
+				vf_notify_receiver(hw->provider_name,
+					VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+			}
 		} else
 			vav1_vf_put(vav1_vf_get(hw), hw);
 	}
@@ -6733,7 +6779,8 @@
 			}
 
 			if (index == INVALID_IDX) {
-				if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) {
+				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;
 				}
@@ -6745,14 +6792,18 @@
 		vf->flag		= VFRAME_FLAG_EMPTY_FRAME_V4L;
 		vf->v4l_mem_handle	= (index == INVALID_IDX) ? (ulong)fb :
 					hw->m_BUF[index].v4l_ref_buf_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);
-		vf_notify_receiver(vdec->vf_provider_name,
-			VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
 
-		av1_print(hw, PRINT_FLAG_V4L_DETAIL,
-			"[%d] AV1 EOS notify.\n", (hw->is_used_v4l)?ctx->id:vdec->id);
+		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);
+
+		av1_print(hw, 0, "[%d] AV1 EOS notify.\n", (hw->is_used_v4l)?ctx->id:vdec->id);
 	}
 
 	return 0;
@@ -6793,10 +6844,21 @@
 	if (check_dma)
 		hevc_mmu_dma_check(hw_to_vdec(hw));
 
-	decoder_mmu_box_free_idx_tail(
-			hw->mmu_box,
-			hw->buffer_wrap[cm->cur_fb_idx_mmu],
-			hw->used_4k_num);
+	if (hw->is_used_v4l) {
+		int index = cm->cur_fb_idx_mmu;
+		struct internal_comp_buf *ibuf =
+			index_to_icomp_buf(hw, index);
+
+		decoder_mmu_box_free_idx_tail(
+				ibuf->mmu_box,
+				ibuf->index,
+				hw->used_4k_num);
+	} else {
+		decoder_mmu_box_free_idx_tail(
+				hw->mmu_box,
+				cm->cur_fb_idx_mmu,
+				hw->used_4k_num);
+	}
 
 	cm->cur_fb_idx_mmu = INVALID_IDX;
 	hw->used_4k_num = -1;
@@ -6831,7 +6893,7 @@
 		return;
 	if (cm->cur_fb_idx_mmu != INVALID_IDX) {
 		decoder_mmu_box_free_idx(hw->mmu_box,
-			hw->buffer_wrap[cm->cur_fb_idx_mmu]);
+			cm->cur_fb_idx_mmu);
 
 		cm->cur_fb_idx_mmu = INVALID_IDX;
 		hw->used_4k_num = -1;
@@ -7102,12 +7164,12 @@
 		av1_print(hw, AV1_DEBUG_CACHE_HIT_RATE, "MCRCC_HIT_RATE : %d\n", hitrate);
 		hitrate = 100*(byp_mcr_cnt_nchoutwin + byp_mcr_cnt_nchcanv)/raw_mcr_cnt;
 		av1_print(hw, AV1_DEBUG_CACHE_HIT_RATE, "MCRCC_BYP_RATE : %d\n", hitrate);
-	    mcrcc_hit_rate = 100*hit_mcr_cnt/raw_mcr_cnt;
-		mcrcc_bypass_rate = 100*(byp_mcr_cnt_nchoutwin + byp_mcr_cnt_nchcanv)/raw_mcr_cnt;
 	} else {
 		av1_print(hw, AV1_DEBUG_CACHE_HIT_RATE, "MCRCC_HIT_RATE : na\n");
 		av1_print(hw, AV1_DEBUG_CACHE_HIT_RATE, "MCRCC_BYP_RATE : na\n");
 	}
+	mcrcc_hit_rate = 100*hit_mcr_cnt/raw_mcr_cnt;
+	mcrcc_bypass_rate = 100*(byp_mcr_cnt_nchoutwin + byp_mcr_cnt_nchcanv)/raw_mcr_cnt;
 
 	return;
 }
@@ -7137,7 +7199,7 @@
 
 	if ( raw_mcr_cnt != 0 ) {
 		hitrate = 100*hit_mcr_cnt/raw_mcr_cnt;
-		av1_print(hw, AV1_DEBUG_CACHE_HIT_RATE, "DECOMP_HCACHE_HIT_RATE : %d\n", hitrate);
+		av1_print(hw, AV1_DEBUG_CACHE_HIT_RATE, "DECOMP_HCACHE_HIT_RATE : %.2f\%\n", hitrate);
 	} else {
 		av1_print(hw, AV1_DEBUG_CACHE_HIT_RATE, "DECOMP_HCACHE_HIT_RATE : na\n");
 	}
@@ -7337,9 +7399,36 @@
 
 #endif
 
+#if 0
+void release_unused_4k_ext(MMU_BUFF_MGR *mmumgr, int32_t cur_buf_idx, long used_4k_num)
+{
+  int32_t release_4k_position;
+  int32_t i;
+
+  if(mmumgr->mmu_pic_count < 0) return;
+
+  mmumgr->mmu_offset_seed = used_4k_num & 0xff;
+  if(used_4k_num > mmumgr->mmu_buf[cur_buf_idx].mmu_4k_number) {
+    printk("[MMU MEM ERROR] : Use more 4K Page than allocated  %d > ([%d] = %d)!!\r\n", used_4k_num, cur_buf_idx, mmumgr->mmu_buf[cur_buf_idx].mmu_4k_number);
+  }
+  else printk("[MMU MEM RELEASE] : P%d(buffer %d) used %d of %d 4k buffer (%d%c)\r\n", mmumgr->mmu_pic_count, cur_buf_idx, used_4k_num, mmumgr->mmu_buf[cur_buf_idx].mmu_4k_number, used_4k_num*100/mmumgr->mmu_buf[cur_buf_idx].mmu_4k_number, '%');
+
+  for(i = used_4k_num; i<mmumgr->mmu_buf[cur_buf_idx].mmu_4k_number; i++){
+    release_4k_position = mmumgr->mmu_buf[cur_buf_idx].mmu_4k_index[i] - mmumgr->MC_BUFFER_START_4K_ADR;
+    printk("[MMU MEM RELEASE DEBUG] release_4k_position[%d] : 0x%x\n", i, release_4k_position+mmumgr->MC_BUFFER_START_4K_ADR);
+    mmumgr->mmu_4k_status[release_4k_position] = 0;
+  }
+  mmumgr->cur_mem_usage -= (mmumgr->mmu_buf[cur_buf_idx].mmu_4k_number - used_4k_num)*4096;
+  mmumgr->mmu_buf[cur_buf_idx].mmu_4k_number = used_4k_num;
+}
+#endif
+
 int av1_continue_decoding(struct AV1HW_s *hw, int obu_type)
 {
-	int ret;
+	int ret = 0;
+#ifdef SANITY_CHECK
+	param_t* params = &hw->aom_param;
+#endif
 #if 1
 	//def CHANGE_DONE
 	AV1Decoder *pbi = hw->pbi;
@@ -7383,18 +7472,70 @@
 	} else {
 		hw->new_compressed_data = 0;
 	}
-	ret = av1_bufmgr_process(pbi, &hw->aom_param,
-		hw->new_compressed_data, obu_type);
-	av1_print(hw, AOM_DEBUG_HW_MORE,
-		"%s: pbi %p cm %p cur_frame %p\n",
-		__func__, pbi, cm, cm->cur_frame);
+#ifdef SEND_MMU_USED_NUM
+      if (cm->prev_fb_idx != INVALID_IDX) {
+            long used_4k_num = aom_param.p.mmu_used_num;
+            if (used_4k_num != 0) {
+                  printk("mmu free tail, index %d used_num 0x%x\n",
+                  cm->prev_fb_idx, used_4k_num);
+                  release_unused_4k_ext(&av1_mmumgr_m, cm->prev_fb_idx, used_4k_num);
+            }
 
-	av1_print(hw, AOM_DEBUG_HW_MORE,
-		"1+++++++++++++++++++++++++++++++++++%d %p\n",
-		ret, cm->cur_frame);
-	if (hw->new_compressed_data)
-		WRITE_VREG(PIC_END_LCU_COUNT, 0);
+#ifdef AOM_AV1_MMU_DW
+            used_4k_num = aom_param.p.dw_mmu_used_num;
+            if (used_4k_num != 0) {
+                  release_unused_4k_ext(&av1_mmumgr_dw, cm->prev_fb_idx, used_4k_num);
+                  printk("dw mmu free tail, index %d used_num 0x%x\n",
+                        cm->prev_fb_idx, used_4k_num);
+            }
+#endif
+      }
+      cm->prev_fb_idx = INVALID_IDX;
 
+#endif
+#ifdef SANITY_CHECK
+	ret = 0;
+	av1_print(hw, AOM_DEBUG_HW_MORE,
+		"Check Picture size, max (%d, %d), width/height (%d, %d), dec_width %d\n",
+		params->p.max_frame_width,
+		params->p.max_frame_height,
+		params->p.frame_width_scaled,
+		params->p.frame_height,
+		params->p.dec_frame_width
+	);
+
+	if (/*params->p.max_frame_width > MAX_PIC_WIDTH ||
+	params->p.max_frame_height > MAX_PIC_HEIGHT ||*/
+	(params->p.frame_width_scaled * params->p.frame_height) > MAX_SIZE_8K ||
+	(params->p.dec_frame_width * params->p.frame_height) > MAX_SIZE_8K ||
+	params->p.frame_width_scaled <= 0 ||
+	params->p.dec_frame_width <= 0 ||
+	params->p.frame_height <= 0) {
+		av1_print(hw, 0, "!!Picture size error, max (%d, %d), width/height (%d, %d), dec_width %d\n",
+			params->p.max_frame_width,
+			params->p.max_frame_height,
+			params->p.frame_width_scaled,
+			params->p.frame_height,
+			params->p.dec_frame_width
+		);
+		ret = -1;
+	}
+#endif
+	if (ret >= 0) {
+		ret = av1_bufmgr_process(pbi, &hw->aom_param,
+			hw->new_compressed_data, obu_type);
+		if (ret < 0)
+			return -1;
+		av1_print(hw, AOM_DEBUG_HW_MORE,
+			"%s: pbi %p cm %p cur_frame %p\n",
+			__func__, pbi, cm, cm->cur_frame);
+
+		av1_print(hw, AOM_DEBUG_HW_MORE,
+			"1+++++++++++++++++++++++++++++++++++%d %p\n",
+			ret, cm->cur_frame);
+		if (hw->new_compressed_data)
+			WRITE_VREG(PIC_END_LCU_COUNT, 0);
+	}
 	if (ret > 0) {
 		/* the case when cm->show_existing_frame is 1 */
 		/*case 3016*/
@@ -7416,16 +7557,16 @@
 
 		av1_print(hw, AOM_DEBUG_HW_MORE,
 			"aom_bufmgr_process=> %d,decode done, AOM_AV1_SEARCH_HEAD\r\n", ret);
-			WRITE_VREG(HEVC_DEC_STATUS_REG, AOM_AV1_SEARCH_HEAD);
+		WRITE_VREG(HEVC_DEC_STATUS_REG, AOM_AV1_SEARCH_HEAD);
 		pbi->decode_idx++;
 		pbi->bufmgr_proc_count++;
 		hw->frame_decoded = 1;
 		return 0;
-	}
-	else if (ret < 0) {
+	} else if (ret < 0) {
 		hw->frame_decoded = 1;
 		av1_print(hw, AOM_DEBUG_HW_MORE,
-		"aom_bufmgr_process=> %d, bufmgr e.r.r.o.r., AOM_AV1_SEARCH_HEAD\r\n", ret);
+		"aom_bufmgr_process=> %d, bufmgr e.r.r.o.r. %d, AOM_AV1_SEARCH_HEAD\r\n",
+		ret, cm->error.error_code);
 		WRITE_VREG(HEVC_DEC_STATUS_REG, AOM_AV1_SEARCH_HEAD);
 		return 0;
 	}
@@ -7487,18 +7628,25 @@
 		pbi->bufmgr_proc_count);
 		pbi->decode_idx++;
 		hw->frame_count++;
+#ifdef SEND_MMU_USED_NUM
+		cm->prev_fb_idx = cm->cur_fb_idx_mmu;
+		cm->cur_fb_idx_mmu = cm->cur_frame->buf.index;
+#endif
 		cur_pic_config->slice_type = cm->cur_frame->frame_type;
 		if (hw->chunk) {
 			av1_print(hw, AV1_DEBUG_OUT_PTS,
-				"%s, config pic pts %d, pts64 %lld\n",
-				__func__, hw->chunk->pts, hw->chunk->pts64);
+				"%s, config pic pts %d, pts64 %lld, ts: %lld\n",
+				__func__, hw->chunk->pts, hw->chunk->pts64, hw->chunk->timestamp);
 			cur_pic_config->pts = hw->chunk->pts;
 			cur_pic_config->pts64 = hw->chunk->pts64;
 			cur_pic_config->timestamp =  hw->chunk->timestamp;
-			hw->chunk->pts = 0;
-			hw->chunk->pts64 = 0;
-			hw->chunk->timestamp = 0;
+
+			if (hw->is_used_v4l && !v4l_bitstream_id_enable) {
+				cur_pic_config->pts64 = hw->chunk->timestamp;
+				hw->chunk->timestamp = 0;
+			}
 		}
+		ATRACE_COUNTER(hw->trace.decode_header_memory_time_name, TRACE_HEADER_REGISTER_START);
 #ifdef DUAL_DECODE
 #else
 		config_pic_size(hw, hw->aom_param.p.bit_depth);
@@ -7511,12 +7659,14 @@
 		}
 
 		if (ret >= 0 && hw->mmu_enable && ((hw->double_write_mode & 0x10) == 0)) {
+			ATRACE_COUNTER(hw->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_START);
 			ret = av1_alloc_mmu(hw,
 				cm->cur_frame->buf.index,
 				cur_pic_config->y_crop_width,
 				cur_pic_config->y_crop_height,
 				hw->aom_param.p.bit_depth,
 				hw->frame_mmu_map_addr);
+			ATRACE_COUNTER(hw->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_END);
 			if (ret >= 0)
 				cm->cur_fb_idx_mmu = cm->cur_frame->buf.index;
 			else
@@ -7567,6 +7717,16 @@
 
 		config_dblk_hw(hw);
 
+		/* store segment_feature before shared sub-module run to fix mosaic on t5d */
+		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2)
+			WRITE_VREG(HEVC_PARSER_MEM_WR_ADDR, 0x11b0 + (cur_pic_config->index));
+		else
+			WRITE_VREG(HEVC_PARSER_MEM_WR_ADDR, 0x1010 + (cur_pic_config->index));
+		if (hw->aom_param.p.segmentation_enabled & 1) // segmentation_enabled
+			WRITE_VREG(HEVC_PARSER_MEM_RW_DATA, READ_VREG(AV1_REF_SEG_INFO));
+		else
+			WRITE_VREG(HEVC_PARSER_MEM_RW_DATA, 0);
+
 		av1_print(hw, AOM_DEBUG_HW_MORE, "HEVC_DEC_STATUS_REG <= AOM_AV1_DECODE_SLICE\n");
 		WRITE_VREG(HEVC_DEC_STATUS_REG, AOM_AV1_DECODE_SLICE);
 
@@ -7580,15 +7740,13 @@
 				cm->cur_frame->segment_feature[i] = (0x80000000 | (i << 22));
 			}
 		}
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SC2)
-			WRITE_VREG(HEVC_PARSER_MEM_WR_ADDR, 0x11b0 + (cur_pic_config->index));
-		else
-			WRITE_VREG(HEVC_PARSER_MEM_WR_ADDR, 0x1010 + (cur_pic_config->index));
-		if (hw->aom_param.p.segmentation_enabled & 1) // segmentation_enabled
-			WRITE_VREG(HEVC_PARSER_MEM_RW_DATA, READ_VREG(AV1_REF_SEG_INFO));
-		else
-			WRITE_VREG(HEVC_PARSER_MEM_RW_DATA, 0);
+	} else {
+		av1_print(hw, AOM_DEBUG_HW_MORE, "Sequence head, Search next start code\n");
+		cm->prev_fb_idx = INVALID_IDX;
+		//skip, search next start code
+		WRITE_VREG(HEVC_DEC_STATUS_REG, AOM_AV1_DECODE_SLICE);
 	}
+	ATRACE_COUNTER(hw->trace.decode_header_memory_time_name, TRACE_HEADER_REGISTER_END);
 	return ret;
 
 #else
@@ -7793,7 +7951,7 @@
 		frame->min_mv = a[0];
 
 		av1_print(hw, AV1_DEBUG_QOS_INFO,
-			"mv data %lx  a[0]= %x a[1]= %x a[2]= %x\n",
+			"mv data %x  a[0]= %x a[1]= %x a[2]= %x\n",
 			data, a[0], a[1], a[2]);
 
 		data = READ_VREG(HEVC_QP_INFO);
@@ -7820,7 +7978,7 @@
 		frame->min_qp = a[0];
 
 		av1_print(hw, AV1_DEBUG_QOS_INFO,
-			"qp data %lx  a[0]= %x a[1]= %x a[2]= %x\n",
+			"qp data %x  a[0]= %x a[1]= %x a[2]= %x\n",
 			data, a[0], a[1], a[2]);
 
 		data = READ_VREG(HEVC_SKIP_INFO);
@@ -7847,7 +8005,7 @@
 		frame->min_skip = a[0];
 
 		av1_print(hw, AV1_DEBUG_QOS_INFO,
-			"skip data %lx  a[0]= %x a[1]= %x a[2]= %x\n",
+			"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;
@@ -8183,19 +8341,20 @@
 	  //printf("Error, dec_status of 0x%x, not supported!!!\n", dec_status);
 	  return -1;
 	}
-    av1_print2(AOM_DEBUG_HW_MORE, "load_param: ret 0x%x\n", head_type);
-
-	    if (debug&AOM_AV1_DEBUG_SEND_PARAM_WITH_REG) {
-		    get_rpm_param(params);
-		}
-	    else {
-		    for (i = 0; i < (RPM_END-RPM_BEGIN); i += 4) {
-			    int32_t ii;
-			    for (ii = 0; ii < 4; ii++) {
-				    params->l.data[i+ii]=hw->rpm_ptr[i+3-ii];
-				}
+	av1_print2(AOM_DEBUG_HW_MORE, "load_param: ret 0x%x\n", head_type);
+	ATRACE_COUNTER(hw->trace.decode_header_memory_time_name, TRACE_HEADER_RPM_START);
+	if (debug&AOM_AV1_DEBUG_SEND_PARAM_WITH_REG) {
+		get_rpm_param(params);
+	}
+	else {
+		for (i = 0; i < (RPM_END-RPM_BEGIN); i += 4) {
+			int32_t ii;
+			for (ii = 0; ii < 4; ii++) {
+				params->l.data[i+ii]=hw->rpm_ptr[i+3-ii];
 			}
 		}
+	}
+	ATRACE_COUNTER(hw->trace.decode_header_memory_time_name, TRACE_HEADER_RPM_END);
 
     params->p.enable_ref_frame_mvs = (params->p.seq_flags >> 7) & 0x1;
     params->p.enable_superres = (params->p.seq_flags >> 15) & 0x1;
@@ -8222,14 +8381,29 @@
 	return av1_bufmgr_postproc(hw->pbi, hw->frame_decoded);
 }
 
+static void vav1_get_comp_buf_info(struct AV1HW_s *hw,
+					struct vdec_comp_buf_info *info)
+{
+	u16 bit_depth = hw->param.p.bit_depth;
+
+	info->max_size = av1_max_mmu_buf_size(
+			hw->max_pic_w,
+			hw->max_pic_h);
+	info->header_size = av1_get_header_size(
+			hw->frame_width,
+			hw->frame_height);
+	info->frame_buffer_size = av1_mmu_page_num(
+			hw, hw->frame_width,
+			hw->frame_height,
+			bit_depth == 0);
+}
+
 static int vav1_get_ps_info(struct AV1HW_s *hw, struct aml_vdec_ps_infos *ps)
 {
-	int dw_mode = v4l_parser_get_double_write_mode(hw);
-
-	ps->visible_width 	= hw->frame_width / get_double_write_ratio(hw, dw_mode);
-	ps->visible_height 	= hw->frame_height / get_double_write_ratio(hw, dw_mode);
-	ps->coded_width 	= ALIGN(hw->frame_width, 32) / get_double_write_ratio(hw, dw_mode);
-	ps->coded_height 	= ALIGN(hw->frame_height, 32) / get_double_write_ratio(hw, dw_mode);
+	ps->visible_width 	= hw->frame_width;
+	ps->visible_height 	= hw->frame_height;
+	ps->coded_width 	= ALIGN(hw->frame_width, 64);
+	ps->coded_height 	= ALIGN(hw->frame_height, 64);
 	ps->dpb_size 		= hw->used_buf_num;
 
 	return 0;
@@ -8246,6 +8420,7 @@
 	if (ctx->param_sets_from_ucode &&
 		hw->res_ch_flag == 0) {
 		struct aml_vdec_ps_infos ps;
+		struct vdec_comp_buf_info comp;
 
 		if ((cm->width != 0 &&
 			cm->height != 0) &&
@@ -8256,6 +8431,11 @@
 				"%s (%d,%d)=>(%d,%d)\r\n", __func__, cm->width,
 				cm->height, hw->frame_width, hw->frame_height);
 
+			if (get_valid_double_write_mode(hw) != 16) {
+				vav1_get_comp_buf_info(hw, &comp);
+				vdec_v4l_set_comp_buf_info(ctx, &comp);
+			}
+
 			vav1_get_ps_info(hw, &ps);
 			vdec_v4l_set_ps_infos(ctx, &ps);
 			vdec_v4l_res_ch_event(ctx);
@@ -8279,9 +8459,16 @@
 	int obu_type;
 	int ret = 0;
 
-	/*if (hw->wait_buf)
-	 *	pr_info("set wait_buf to 0\r\n");
-	 */
+	if (dec_status == AOM_AV1_FRAME_HEAD_PARSER_DONE ||
+		dec_status == AOM_AV1_SEQ_HEAD_PARSER_DONE ||
+		dec_status == AOM_AV1_FRAME_PARSER_DONE) {
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_START);
+	}
+	else if (dec_status == AOM_AV1_DEC_PIC_END ||
+		dec_status == AOM_NAL_DECODE_DONE) {
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_PIC_DONE_START);
+	}
+
 	if (hw->eos)
 		return IRQ_HANDLED;
 	hw->wait_buf = 0;
@@ -8295,6 +8482,7 @@
 				dec_again_process(hw);
 			else {
 				hw->dec_result = DEC_RESULT_DONE;
+				ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_EDN);
 				vdec_schedule_work(&hw->work);
 			}
 		}
@@ -8302,6 +8490,8 @@
 		return IRQ_HANDLED;
 	} else if (dec_status == AOM_AV1_DEC_PIC_END) {
 		struct AV1_Common_s *const cm = &hw->common;
+		struct PIC_BUFFER_CONFIG_s *frame = &cm->cur_frame->buf;
+		struct vdec_s *vdec = hw_to_vdec(hw);
 #if 1
 		u32 fg_reg0, fg_reg1, num_y_points, num_cb_points, num_cr_points;
 		WRITE_VREG(HEVC_FGS_IDX, 0);
@@ -8331,6 +8521,12 @@
 #ifdef USE_DEC_PIC_END
 			if (READ_VREG(PIC_END_LCU_COUNT) != 0) {
 				hw->frame_decoded = 1;
+				if (cm->cur_frame && vdec->mvfrm && frame) {
+					frame->hw_decode_time =
+					local_clock() - vdec->mvfrm->hw_decode_start;
+					frame->frame_size2 = vdec->mvfrm->frame_size;
+				}
+				hw->gvs->frame_count = hw->frame_count;
 				/*
 				In c module, multi obus are put in one packet, which is decoded
 				with av1_receive_compressed_data().
@@ -8361,17 +8557,27 @@
 				if (cm->cur_frame != NULL) {
 					hevc_mmu_dma_check(hw_to_vdec(hw));
 
-					av1_print(hw, AOM_DEBUG_HW_MORE, "mmu free tail, index %d used_num 0x%lx\n",
+					av1_print(hw, AOM_DEBUG_HW_MORE, "mmu free tail, index %d used_num 0x%x\n",
 						cm->cur_frame->buf.index, used_4k_num);
-					decoder_mmu_box_free_idx_tail(hw->mmu_box,
-						hw->buffer_wrap[cm->cur_frame->buf.index], used_4k_num);
+					if (hw->is_used_v4l) {
+						struct internal_comp_buf *ibuf =
+							index_to_icomp_buf(hw, cm->cur_fb_idx_mmu);
+
+						decoder_mmu_box_free_idx_tail(
+							ibuf->mmu_box,
+							ibuf->index,
+							used_4k_num);
+					} else {
+						decoder_mmu_box_free_idx_tail(hw->mmu_box,
+							cm->cur_frame->buf.index, used_4k_num);
+					}
 #ifdef AOM_AV1_MMU_DW
 					if (hw->dw_mmu_enable) {
 						used_4k_num =
 						(READ_VREG(HEVC_SAO_MMU_STATUS2) >> 16);
 						decoder_mmu_box_free_idx_tail(hw->mmu_box_dw,
-							hw->buffer_wrap[cm->cur_frame->buf.index], used_4k_num);
-						av1_print(hw, AOM_DEBUG_HW_MORE, "dw mmu free tail, index %d used_num 0x%lx\n",
+							cm->cur_frame->buf.index, used_4k_num);
+						av1_print(hw, AOM_DEBUG_HW_MORE, "dw mmu free tail, index %d used_num 0x%x\n",
 							cm->cur_frame->buf.index, used_4k_num);
 					}
 #endif
@@ -8393,7 +8599,7 @@
 			hw->frame_decoded &&
 			READ_VREG(HEVC_SHIFT_BYTE_COUNT) < hw->data_size) {
 #ifdef DEBUG_CRC_ERROR
-				if (crc_debug_flag & 0x40)
+				if ((crc_debug_flag & 0x40) && cm->cur_frame)
 					dump_mv_buffer(hw, &cm->cur_frame->buf);
 #endif
 				WRITE_VREG(HEVC_DEC_STATUS_REG, AOM_AV1_SEARCH_HEAD);
@@ -8402,9 +8608,10 @@
 				hw->fgs_valid);
 				if (hw->config_next_ref_info_flag)
 					config_next_ref_info_hw(hw);
+				ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_EDN);
 			} else {
 #ifdef DEBUG_CRC_ERROR
-				if (crc_debug_flag & 0x40)
+				if ((crc_debug_flag & 0x40) && cm->cur_frame)
 					dump_mv_buffer(hw, &cm->cur_frame->buf);
 #endif
 				hw->dec_result = DEC_RESULT_DONE;
@@ -8413,13 +8620,13 @@
 				if (mcrcc_cache_alg_flag)
 					dump_hit_rate(hw);
 #endif
+				ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_EDN);
 				vdec_schedule_work(&hw->work);
 			}
 		} else {
             av1_print(hw, AOM_DEBUG_HW_MORE,
             	"PIC_END, fgs_valid %d search head ...\n",
             	hw->fgs_valid);
-            WRITE_VREG(HEVC_DEC_STATUS_REG, AOM_AV1_SEARCH_HEAD);
 #ifdef USE_DEC_PIC_END
 		    if (READ_VREG(PIC_END_LCU_COUNT) != 0) {
 			    hw->frame_decoded = 1;
@@ -8430,11 +8637,13 @@
 				    we assume each packet must and only include one picture of data (LCUs)
 					 or cm->show_existing_frame is 1
 					*/
-				av1_print(hw, AOM_DEBUG_HW_MORE, "Decoding done (index %d)\n",
-					cm->cur_frame? cm->cur_frame->buf.index:-1);
+				if (cm->cur_frame)
+					av1_print(hw, AOM_DEBUG_HW_MORE, "Decoding done (index %d)\n",
+						cm->cur_frame? cm->cur_frame->buf.index:-1);
 				config_next_ref_info_hw(hw);
 			}
 #endif
+			WRITE_VREG(HEVC_DEC_STATUS_REG, AOM_AV1_SEARCH_HEAD);
 			/*
 			if (debug &
 				AV1_DEBUG_BUFMGR_MORE)
@@ -8512,8 +8721,9 @@
 					hw->mv_buf_margin = hw->used_buf_num - REF_FRAMES_4K + 1;
 				if (((hw->max_pic_w % 64) != 0) &&
 					(hw_to_vdec(hw)->canvas_mode != CANVAS_BLKMODE_LINEAR))
-					mem_map_mode = 2;
-				av1_print(hw, 0, "force 8k double write 4, mem_map_mode %d\n", mem_map_mode);
+					hw->mem_map_mode = 2;
+				av1_print(hw, 0,
+					"force 8k double write 4, mem_map_mode %d\n", hw->mem_map_mode);
 			}
 			vav1_mmu_map_alloc(hw);
 			if (hw->mmu_enable)
@@ -8526,6 +8736,15 @@
 			    WRITE_VREG(HEVC_SAO_C_START_ADDR, 0);
 			}
 #endif
+
+			/*v4l2 alloc new mv when max size changed */
+			if (hw->is_used_v4l) {
+				/* now less than 8k use fix mv buf size */
+				if (IS_8K_SIZE(hw->max_pic_w, hw->max_pic_h) && hw->pic_list_init_done) {
+					if (init_mv_buf_list(hw) < 0)
+						pr_err("%s: !!!!Error, reinit_mv_buf_list fail\n", __func__);
+				}
+			}
 		}
 		bit_depth_luma = hw->aom_param.p.bit_depth;
 		bit_depth_chroma = hw->aom_param.p.bit_depth;
@@ -8563,6 +8782,7 @@
 			"AOM_AV1_SEQ_HEAD_PARSER_DONE, search head ...\n");
 	    WRITE_VREG(HEVC_DEC_STATUS_REG, AOM_AV1_SEARCH_HEAD);
 		hw->process_busy = 0;
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_END);
 		return IRQ_HANDLED;
 	}
 #ifndef USE_DEC_PIC_END
@@ -8577,8 +8797,9 @@
 			    we assume each packet must and only include one picture of data (LCUs)
 				 or cm->show_existing_frame is 1
 				*/
-				av1_print(hw, AOM_DEBUG_HW_MORE, "Decoding done (index %d)\n",
-					cm->cur_frame? cm->cur_frame->buf.index:-1);
+				if (cm->cur_frame)
+					av1_print(hw, AOM_DEBUG_HW_MORE, "Decoding done (index %d)\n",
+						cm->cur_frame? cm->cur_frame->buf.index:-1);
 			}
 		}
 #endif
@@ -8628,8 +8849,14 @@
 		if (!v4l_res_change(hw)) {
 			if (ctx->param_sets_from_ucode && !hw->v4l_params_parsed) {
 				struct aml_vdec_ps_infos ps;
+				struct vdec_comp_buf_info comp;
 
 				pr_info("set ucode parse\n");
+				if (get_valid_double_write_mode(hw) != 16) {
+					vav1_get_comp_buf_info(hw, &comp);
+					vdec_v4l_set_comp_buf_info(ctx, &comp);
+				}
+
 				vav1_get_ps_info(hw, &ps);
 				/*notice the v4l2 codec.*/
 				vdec_v4l_set_ps_infos(ctx, &ps);
@@ -8647,6 +8874,18 @@
 		}
 	}
 
+	if (hw->one_package_frame_cnt) {
+		if (get_free_buf_count(hw) <= 0) {
+			hw->dec_result = AOM_AV1_RESULT_NEED_MORE_BUFFER;
+			hw->cur_obu_type = obu_type;
+			hw->process_busy = 0;
+			vdec_schedule_work(&hw->work);
+			ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_END);
+			return IRQ_HANDLED;
+		}
+	}
+	hw->one_package_frame_cnt++;
+
 	ret = av1_continue_decoding(hw, obu_type);
 	hw->postproc_done = 0;
 	hw->process_busy = 0;
@@ -8660,7 +8899,7 @@
 			vdec_schedule_work(&hw->work);
 		}
 	}
-
+	ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_END);
 	return IRQ_HANDLED;
 }
 
@@ -8675,6 +8914,16 @@
 	WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1);
 
 	dec_status = READ_VREG(HEVC_DEC_STATUS_REG) & 0xff;
+
+	if (dec_status == AOM_AV1_FRAME_HEAD_PARSER_DONE ||
+		dec_status == AOM_AV1_SEQ_HEAD_PARSER_DONE ||
+		dec_status == AOM_AV1_FRAME_PARSER_DONE) {
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_HEAD_DONE);
+	}
+	else if (dec_status == AOM_AV1_DEC_PIC_END ||
+		dec_status == AOM_NAL_DECODE_DONE) {
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_PIC_DONE);
+	}
 	if (!hw)
 		return IRQ_HANDLED;
 	if (hw->init_flag == 0)
@@ -8799,19 +9048,20 @@
 			hw->process_busy = 0;
 			return IRQ_HANDLED;
 		}
-	}
-	if (get_free_buf_count(hw) <= 0) {
-		/*
-		if (hw->wait_buf == 0)
+		if (get_free_buf_count(hw) <= 0) {
+			/*
+			if (hw->wait_buf == 0)
 			pr_info("set wait_buf to 1\r\n");
-		*/
-		hw->wait_buf = 1;
-		hw->process_busy = 0;
-		av1_print(hw, AV1_DEBUG_BUFMGR,
-			"free buf not enough = %d\n",
-			get_free_buf_count(hw));
-		return IRQ_HANDLED;
+			*/
+			hw->wait_buf = 1;
+			hw->process_busy = 0;
+			av1_print(hw, AV1_DEBUG_BUFMGR,
+				"free buf not enough = %d\n",
+				get_free_buf_count(hw));
+			return IRQ_HANDLED;
+		}
 	}
+	ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_ISR_END);
 	return IRQ_WAKE_THREAD;
 }
 
@@ -8827,10 +9077,10 @@
 		frame_height * fps;
 }
 
-static void vav1_put_timer_func(unsigned long arg)
+static void vav1_put_timer_func(struct timer_list *timer)
 {
-	struct AV1HW_s *hw = (struct AV1HW_s *)arg;
-	struct timer_list *timer = &hw->timer;
+	struct AV1HW_s *hw = container_of(timer,
+		struct AV1HW_s, timer);
 	uint8_t empty_flag;
 	unsigned int buf_level;
 
@@ -9036,19 +9286,18 @@
 	vstatus->error_count = 0;
 	vstatus->status = av1->stat | av1->fatal_error;
 	vstatus->frame_dur = av1->frame_dur;
-#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
-	vstatus->bit_rate = gvs->bit_rate;
-	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;
+//#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
+	vstatus->bit_rate = av1->gvs->bit_rate;
+	vstatus->frame_data = av1->gvs->frame_data;
+	vstatus->total_data = av1->gvs->total_data;
+	vstatus->frame_count = av1->gvs->frame_count;
+	vstatus->error_frame_count = av1->gvs->error_frame_count;
+	vstatus->drop_frame_count = av1->gvs->drop_frame_count;
+	vstatus->samp_cnt = av1->gvs->samp_cnt;
+	vstatus->offset = av1->gvs->offset;
 	snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
 		"%s", DRIVER_NAME);
-#endif
+//#endif
 	return 0;
 }
 
@@ -9192,9 +9441,6 @@
 	hw->saved_resolution = 0;
 	hw->get_frame_dur = false;
 	on_no_keyframe_skiped = 0;
-	hw->first_pts_index = 0;
-	hw->dur_recalc_flag = 0;
-	hw->av1_first_pts_ready = false;
 	width = hw->vav1_amstream_dec_info.width;
 	height = hw->vav1_amstream_dec_info.height;
 	hw->frame_dur =
@@ -9275,12 +9521,10 @@
 	fw->len = fw_size;
 
 	INIT_WORK(&hw->set_clk_work, av1_set_clk);
-	init_timer(&hw->timer);
+	timer_setup(&hw->timer, vav1_put_timer_func, 0);
 
 #ifdef MULTI_INSTANCE_SUPPORT
 	if (hw->m_ins_flag) {
-		hw->timer.data = (ulong) hw;
-		hw->timer.function = vav1_put_timer_func;
 		hw->timer.expires = jiffies + PUT_INTERVAL;
 
 		/*add_timer(&hw->timer);
@@ -9330,16 +9574,18 @@
 #endif
 		hw->provider_name = PROVIDER_NAME;
 #ifdef MULTI_INSTANCE_SUPPORT
-	vf_provider_init(&vav1_vf_prov, hw->provider_name,
-				&vav1_vf_provider, hw);
-	vf_reg_provider(&vav1_vf_prov);
-	vf_notify_receiver(hw->provider_name, VFRAME_EVENT_PROVIDER_START, NULL);
-	if (hw->frame_dur != 0) {
-		if (!is_reset)
-			vf_notify_receiver(hw->provider_name,
-					VFRAME_EVENT_PROVIDER_FR_HINT,
-					(void *)
-					((unsigned long)hw->frame_dur));
+	if (!hw->is_used_v4l) {
+		vf_provider_init(&vav1_vf_prov, hw->provider_name,
+					&vav1_vf_provider, hw);
+		vf_reg_provider(&vav1_vf_prov);
+		vf_notify_receiver(hw->provider_name, VFRAME_EVENT_PROVIDER_START, NULL);
+		if (hw->frame_dur != 0) {
+			if (!is_reset)
+				vf_notify_receiver(hw->provider_name,
+						VFRAME_EVENT_PROVIDER_FR_HINT,
+						(void *)
+						((unsigned long)hw->frame_dur));
+		}
 	}
 #else
 	vf_provider_init(&vav1_vf_prov, hw->provider_name, &vav1_vf_provider,
@@ -9352,13 +9598,10 @@
 #endif
 	hw->stat |= STAT_VF_HOOK;
 
-	hw->timer.data = (ulong)hw;
-	hw->timer.function = vav1_put_timer_func;
 	hw->timer.expires = jiffies + PUT_INTERVAL;
+	add_timer(&hw->timer);
 
 	hw->stat |= STAT_VDEC_RUN;
-
-	add_timer(&hw->timer);
 	hw->stat |= STAT_TIMER_ARM;
 
 	amhevc_start();
@@ -9387,7 +9630,7 @@
 		hw->stat &= ~STAT_TIMER_ARM;
 	}
 
-	if (hw->stat & STAT_VF_HOOK) {
+	if (!hw->is_used_v4l && (hw->stat & STAT_VF_HOOK)) {
 		if (!is_reset)
 			vf_notify_receiver(hw->provider_name,
 					VFRAME_EVENT_PROVIDER_FR_END_HINT,
@@ -9431,7 +9674,7 @@
 		hw->stat &= ~STAT_TIMER_ARM;
 	}
 
-	if (hw->stat & STAT_VF_HOOK) {
+	if (!hw->is_used_v4l && (hw->stat & STAT_VF_HOOK)) {
 		if (!is_reset)
 			vf_notify_receiver(hw->provider_name,
 					VFRAME_EVENT_PROVIDER_FR_END_HINT,
@@ -9472,7 +9715,7 @@
 	}
 	hw->need_cache_size = buf_size * SZ_1M;
 	hw->sc_start_time = get_jiffies_64();
-	if (hw->mmu_enable) {
+	if (hw->mmu_enable && !hw->is_used_v4l) {
 		int count = FRAME_BUFFERS;
 		hw->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME,
 			hw->index /* * 2*/, count,
@@ -9532,13 +9775,12 @@
 #ifndef MULTI_INSTANCE_SUPPORT
 	int i;
 #endif
-	pr_debug("%s\n", __func__);
-
-	if (!(is_cpu_tm2_revb() ||
-	(get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_TM2))) {
-		pr_err("unsupport av1, cpu %d, is_tm2_revb %d\n",
+	if ((get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TM2) ||
+		(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5) ||
+		((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_TM2) && !is_meson_rev_b())) {
+		pr_err("av1 unsupported on cpu %d, is_tm2_revb %d\n",
 			get_cpu_major_id(), is_cpu_tm2_revb());
-		return -EFAULT;
+		return -EINVAL;
 	}
 
 	mutex_lock(&vav1_mutex);
@@ -9690,6 +9932,12 @@
 	cma_dev = pdata->cma_dev;
 #endif
 
+	hw->endian = HEVC_CONFIG_LITTLE_ENDIAN;
+	if (is_support_vdec_canvas())
+		hw->endian = HEVC_CONFIG_BIG_ENDIAN;
+	if (endian)
+		hw->endian = endian;
+
 #ifdef MULTI_INSTANCE_SUPPORT
 	pdata->private = hw;
 	pdata->dec_status = vav1_dec_status;
@@ -9862,6 +10110,12 @@
 	/* finished decoding one frame or error,
 	 * notify vdec core to switch context
 	 */
+	if (hw->dec_result != AOM_AV1_RESULT_NEED_MORE_BUFFER)
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_WORKER_START);
+
+	if (hw->dec_result == DEC_RESULT_AGAIN)
+		ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_WORKER_AGAIN);
+
 	av1_print(hw, PRINT_FLAG_VDEC_DETAIL,
 		"%s dec_result %d %x %x %x\n",
 		__func__,
@@ -9869,6 +10123,21 @@
 		READ_VREG(HEVC_STREAM_LEVEL),
 		READ_VREG(HEVC_STREAM_WR_PTR),
 		READ_VREG(HEVC_STREAM_RD_PTR));
+
+	if (hw->dec_result == AOM_AV1_RESULT_NEED_MORE_BUFFER) {
+		reset_process_time(hw);
+		if (get_free_buf_count(hw) <= 0) {
+			hw->dec_result = AOM_AV1_RESULT_NEED_MORE_BUFFER;
+			vdec_schedule_work(&hw->work);
+		} else {
+			av1_release_bufs(hw);
+			av1_continue_decoding(hw, hw->cur_obu_type);
+			hw->postproc_done = 0;
+			start_process_time(hw);
+		}
+		return;
+	}
+
 	if (((hw->dec_result == DEC_RESULT_GET_DATA) ||
 		(hw->dec_result == DEC_RESULT_GET_DATA_RETRY))
 		&& (hw_to_vdec(hw)->next_status !=
@@ -9891,7 +10160,7 @@
 		}
 
 		if (get_free_buf_count(hw) >=
-			run_ready_min_buf_num) {
+			hw->run_ready_min_buf_num) {
 			int r;
 			int decode_size;
 			r = vdec_prepare_input(vdec, &hw->chunk);
@@ -10004,6 +10273,7 @@
 		del_timer_sync(&hw->timer);
 		hw->stat &= ~STAT_TIMER_ARM;
 	}
+	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)
 		vdec_core_finish_run(vdec, CORE_MASK_HEVC);
@@ -10018,6 +10288,35 @@
 	vav1_prot_init(hw, HW_MASK_FRONT | HW_MASK_BACK);
 	return 0;
 }
+
+static bool is_avaliable_buffer(struct AV1HW_s *hw)
+{
+	AV1_COMMON *cm = &hw->common;
+	RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
+	struct aml_vcodec_ctx *ctx =
+		(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+	int i, free_count = 0;
+
+	if (ctx->cap_pool.dec < hw->used_buf_num) {
+		free_count = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx);
+		if (free_count &&
+			!ctx->fb_ops.query(&ctx->fb_ops, &hw->fb_token)) {
+			return false;
+		}
+	}
+
+	for (i = 0; i < hw->used_buf_num; ++i) {
+		if ((frame_bufs[i].ref_count == 0) &&
+			(frame_bufs[i].buf.vf_ref == 0) &&
+			(frame_bufs[i].buf.index >= 0) &&
+			frame_bufs[i].buf.cma_alloc_addr) {
+			free_count++;
+		}
+	}
+
+	return free_count < hw->run_ready_min_buf_num ? 0 : 1;
+}
+
 static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
 {
 	struct AV1HW_s *hw =
@@ -10030,8 +10329,17 @@
 		return ret;
 
 	if (!hw->first_sc_checked && hw->mmu_enable) {
-		int size = decoder_mmu_box_sc_check(hw->mmu_box, tvp);
+		int size;
+		void * mmu_box;
 
+		if (hw->is_used_v4l) {
+			struct aml_vcodec_ctx *ctx =
+				(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+			mmu_box = ctx->mmu_box;
+		} else
+			mmu_box = hw->mmu_box;
+
+		size = decoder_mmu_box_sc_check(mmu_box, tvp);
 		hw->first_sc_checked = 1;
 		av1_print(hw, 0, "av1 cached=%d  need_size=%d speed= %d ms\n",
 			size, (hw->need_cache_size >> PAGE_SHIFT),
@@ -10045,7 +10353,7 @@
 	}
 
 	if (get_free_buf_count(hw) >=
-		run_ready_min_buf_num) {
+		hw->run_ready_min_buf_num) {
 		if (vdec->parallel_dec == 1)
 			ret = CORE_MASK_HEVC;
 		else
@@ -10058,17 +10366,19 @@
 
 		if (ctx->param_sets_from_ucode) {
 			if (hw->v4l_params_parsed) {
-				if ((ctx->cap_pool.in < hw->used_buf_num) &&
-				v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
-				run_ready_min_buf_num)
-					ret = 0;
+				if (ctx->cap_pool.dec < hw->used_buf_num) {
+					if (is_avaliable_buffer(hw))
+						ret = CORE_MASK_HEVC;
+					else
+						ret = 0;
+				}
 			} else {
 				if (ctx->v4l_resolution_change)
 					ret = 0;
 			}
 		} else if (ctx->cap_pool.in < ctx->dpb_size) {
 			if (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
-				run_ready_min_buf_num)
+				hw->run_ready_min_buf_num)
 				ret = 0;
 		}
 	}
@@ -10084,105 +10394,30 @@
 	return ret;
 }
 
-static void av1_frame_mode_pts_save(struct AV1HW_s *hw)
+static void av1_frame_mode_cal_dur(struct AV1HW_s *hw)
 {
-	u64 i, valid_pts_diff_cnt, pts_diff_sum;
-	u64 in_pts_diff, last_valid_pts_diff, calc_dur;
-
 	if (hw->chunk == NULL)
-		return;
-	/* no return when first pts is 0 */
-	if (hw->first_pts_index) {
-		/* filtration pts 0 and continuous same pts */
-		if ((hw->chunk->pts == 0) ||
-			(hw->frame_mode_pts_save[0] == hw->chunk->pts))
-		return;
+			return;
+		av1_print(hw, AV1_DEBUG_OUT_PTS,
+			"run_front: pts %d, pts64 %lld, ts: %llu\n",
+			hw->chunk->pts, hw->chunk->pts64, hw->chunk->timestamp);
 
-		/* fps change, frame dur change to lower or higher,
-		 * can't find closed pts in saved pool */
-		if ((hw->dur_recalc_flag) ||
-			(hw->last_pts >  hw->chunk->pts)) {
-			hw->av1_first_pts_ready = 0;
-			hw->first_pts_index = 0;
-			hw->get_frame_dur = 0;
-			hw->dur_recalc_flag = 0;
-			memset(hw->frame_mode_pts_save, 0,
-			        sizeof(hw->frame_mode_pts_save));
-			memset(hw->frame_mode_pts64_save, 0,
-			        sizeof(hw->frame_mode_pts64_save));
-			/*v4l use*/
-			memset(hw->frame_mode_timestamp_save, 0,
-			        sizeof(hw->frame_mode_timestamp_save));
-		}
-	}
-	av1_print(hw, AV1_DEBUG_OUT_PTS,
-		"run_front: pts %d, pts64 %lld, ts: %llu\n",
-		hw->chunk->pts, hw->chunk->pts64, hw->chunk->timestamp);
+		if (hw->pts_diff_count > FRAME_BUFFERS)
+			return ;
 
-	for (i = (FRAME_BUFFERS - 1); i > 0; i--) {
-		hw->frame_mode_pts_save[i] = hw->frame_mode_pts_save[i - 1];
-		hw->frame_mode_pts64_save[i] = hw->frame_mode_pts64_save[i - 1];
-		hw->frame_mode_timestamp_save[i] = hw->frame_mode_timestamp_save[i - 1];
-	}
-	hw->frame_mode_pts_save[0] = hw->chunk->pts;
-	hw->frame_mode_pts64_save[0] = hw->chunk->pts64;
-	hw->frame_mode_timestamp_save[0] = hw->chunk->timestamp;
-	if (hw->first_pts_index < ARRAY_SIZE(hw->frame_mode_pts_save))
-		hw->first_pts_index++;
-	/* frame duration check, vdec_secure return for nts problem */
-	if ((!hw->first_pts_index) || hw->get_frame_dur || vdec_secure(hw_to_vdec(hw)))
-		return;
-	valid_pts_diff_cnt = 0;
-	pts_diff_sum = 0;
-
-	for (i = 0; i < FRAME_BUFFERS - 1; i++) {
-		if (hw->is_used_v4l) {
-			if ((hw->frame_mode_timestamp_save[i] > hw->frame_mode_timestamp_save[i + 1]) &&
-				(hw->frame_mode_timestamp_save[i + 1] != 0))
-				in_pts_diff = hw->frame_mode_timestamp_save[i]
-					- hw->frame_mode_timestamp_save[i + 1];
-			else
-				in_pts_diff = 0;
-		} else {
-			if ((hw->frame_mode_pts_save[i] > hw->frame_mode_pts_save[i + 1]) &&
-				(hw->frame_mode_pts_save[i + 1] != 0))
-				in_pts_diff = hw->frame_mode_pts_save[i]
-					- hw->frame_mode_pts_save[i + 1];
-			else
-				in_pts_diff = 0;
+		if ((hw->chunk->pts > hw->last_chunk_pts) && (hw->last_chunk_pts > 0)) {
+			hw->pts_diff_count++;
+			hw->pts_diff_sum  = hw->pts_diff_sum + (hw->chunk->pts - hw->last_chunk_pts);
+			if (hw->pts_diff_count > FRAME_BUFFERS) {
+				u32 calc_dur = (u32)div_u64(div_u64(hw->pts_diff_sum, hw->pts_diff_count)*96, 90);
+				if ((calc_dur <= 16000) && (calc_dur >= 800)) {
+					av1_print(hw, 0, "change to calc dur %d, old dur %d\n", calc_dur, hw->frame_dur);
+					hw->frame_dur = calc_dur;
+				}
+			}
 		}
 
-		if (in_pts_diff < 100 ||
-			(valid_pts_diff_cnt && (!close_to(in_pts_diff, last_valid_pts_diff, 100))))
-			in_pts_diff = 0;
-		else {
-			last_valid_pts_diff = in_pts_diff;
-			valid_pts_diff_cnt++;
-		}
-
-		pts_diff_sum += in_pts_diff;
-	}
-
-	if (!valid_pts_diff_cnt) {
-		av1_print(hw, 0, "checked no avaliable pts\n");
-		return;
-	}
-
-	calc_dur = PTS2DUR(pts_diff_sum / valid_pts_diff_cnt);
-	if ((!close_to(calc_dur, hw->frame_dur, 10)) &&
-		(calc_dur < 9601) && (calc_dur > 800)) {
-		av1_print(hw, 0, "change to calc dur %lld, old dur %d\n", calc_dur, hw->frame_dur);
-		hw->frame_dur = calc_dur;
-		hw->get_frame_dur = true;
-	} else {
-		if (hw->frame_count > FRAME_BUFFERS)
-			hw->get_frame_dur = true;
-	}
-
-	if (hw->is_used_v4l) {
-		hw->timestamp_duration =
-			pts_diff_sum / valid_pts_diff_cnt;
-	}
+		hw->last_chunk_pts = hw->chunk->pts;
 }
 
 static void run_front(struct vdec_s *vdec)
@@ -10211,7 +10446,8 @@
 	hw->dec_result = DEC_RESULT_NONE;
 	hw->start_shift_bytes = READ_VREG(HEVC_SHIFT_BYTE_COUNT);
 
-	av1_frame_mode_pts_save(hw);
+	av1_frame_mode_cal_dur(hw);
+
 	if (debug & PRINT_FLAG_VDEC_STATUS) {
 		if (vdec_frame_based(vdec) && hw->chunk && !vdec_secure(vdec)) {
 			u8 *data = NULL;
@@ -10258,6 +10494,7 @@
 				hw->start_shift_bytes);
 		}
 	}
+	ATRACE_COUNTER(hw->trace.decode_run_time_name, TRACE_RUN_LOADING_FW_START);
 	if (vdec->mc_loaded) {
 	/*firmware have load before,
 	  and not changes to another.
@@ -10285,12 +10522,14 @@
 		vdec->mc_type = VFORMAT_AV1;
 #endif
 	}
+	ATRACE_COUNTER(hw->trace.decode_run_time_name, TRACE_RUN_LOADING_FW_END);
 
+	ATRACE_COUNTER(hw->trace.decode_run_time_name, TRACE_RUN_LOADING_RESTORE_START);
 	if (av1_hw_ctx_restore(hw) < 0) {
 		vdec_schedule_work(&hw->work);
 		return;
 	}
-
+	ATRACE_COUNTER(hw->trace.decode_run_time_name, TRACE_RUN_LOADING_RESTORE_END);
 	vdec_enable_input(vdec);
 
 	WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE);
@@ -10302,6 +10541,8 @@
 		WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0);
 		size = hw->chunk->size +
 			(hw->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+		if (vdec->mvfrm)
+			vdec->mvfrm->frame_size = hw->chunk->size;
 	}
 	hw->data_size = size;
 	WRITE_VREG(HEVC_DECODE_SIZE, size);
@@ -10334,14 +10575,19 @@
 	struct AV1HW_s *hw =
 		(struct AV1HW_s *)vdec->private;
 
+	ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_RUN_START);
 	av1_print(hw,
 		PRINT_FLAG_VDEC_DETAIL, "%s mask %lx\r\n",
 		__func__, mask);
 
 	run_count[hw->index]++;
+	if (vdec->mvfrm)
+		vdec->mvfrm->hw_decode_start = local_clock();
 	hw->vdec_cb_arg = arg;
 	hw->vdec_cb = callback;
+	hw->one_package_frame_cnt = 0;
 		run_front(vdec);
+	ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_RUN_END);
 }
 
 static void  av1_decode_ctx_reset(struct AV1HW_s *hw)
@@ -10362,11 +10608,6 @@
 
 	for (i = 0; i < MV_BUFFER_NUM; i++) {
 		if (hw->m_mv_BUF[i].start_adr) {
-			if (mv_buf_dynamic_alloc) {
-				decoder_bmmu_box_free_idx(hw->bmmu_box, MV_BUFFER_IDX(i));
-				hw->m_mv_BUF[i].start_adr = 0;
-				hw->m_mv_BUF[i].size = 0;
-			}
 			hw->m_mv_BUF[i].used_flag = 0;
 		}
 	}
@@ -10459,7 +10700,7 @@
 		hw->no_head
 		);
 
-	if (vf_get_receiver(vdec->vf_provider_name)) {
+	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,
@@ -10481,14 +10722,14 @@
 	hw->vf_get_count,
 	hw->vf_put_count,
 	get_free_buf_count(hw),
-	run_ready_min_buf_num
+	hw->run_ready_min_buf_num
 	);
 
 	dump_pic_list(hw);
 
 	for (i = 0; i < MAX_BUF_NUM; i++) {
 		av1_print(hw, 0,
-			"mv_Buf(%d) start_adr 0x%lx size 0x%x used %d\n",
+			"mv_Buf(%d) start_adr 0x%x size 0x%x used %d\n",
 			i,
 			hw->m_mv_BUF[i].start_adr,
 			hw->m_mv_BUF[i].size,
@@ -10580,20 +10821,19 @@
 	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;
 	u32 work_buf_size;
 	struct BuffInfo_s *p_buf_info;
-
-	struct BUF_s BUF[MAX_BUF_NUM];
 	struct AV1HW_s *hw = NULL;
-	pr_debug("%s\n", __func__);
 
-	if (!(is_cpu_tm2_revb() ||
-	(get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_TM2))) {
-		pr_err("unsupport av1, cpu %d, is_tm2_revb %d\n",
+	if ((get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TM2) ||
+		(get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5) ||
+		((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_TM2) && !is_meson_rev_b())) {
+		pr_err("av1 unsupported on cpu %d, is_tm2_revb %d\n",
 			get_cpu_major_id(), is_cpu_tm2_revb());
-		return -EFAULT;
+		return -EINVAL;
 	}
 
 	if (pdata == NULL) {
@@ -10636,19 +10876,35 @@
 	pdata->threaded_irq_handler = av1_threaded_irq_cb;
 	pdata->dump_state = av1_dump_state;
 
-	memcpy(&BUF[0], &hw->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
-	memcpy(&hw->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
-
 	hw->index = pdev->id;
-
-	snprintf(hw->vdec_name, sizeof(hw->vdec_name),
+	if (is_rdma_enable()) {
+		hw->rdma_adr = dma_alloc_coherent(amports_get_dma_device(), RDMA_SIZE, &hw->rdma_phy_adr, GFP_KERNEL);
+		for (i = 0; i < SCALELUT_DATA_WRITE_NUM; i++) {
+			hw->rdma_adr[i * 4] = HEVC_IQIT_SCALELUT_WR_ADDR & 0xfff;
+			hw->rdma_adr[i * 4 + 1] = i;
+			hw->rdma_adr[i * 4 + 2] = HEVC_IQIT_SCALELUT_DATA & 0xfff;
+			hw->rdma_adr[i * 4 + 3] = 0;
+			if (i == SCALELUT_DATA_WRITE_NUM - 1) {
+				hw->rdma_adr[i * 4 + 2] = (HEVC_IQIT_SCALELUT_DATA & 0xfff) | 0x20000;
+			}
+		}
+	}
+	snprintf(hw->trace.vdec_name, sizeof(hw->trace.vdec_name),
 		"av1-%d", hw->index);
-	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);
+	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_memory_time_name, sizeof(hw->trace.decode_header_memory_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);
 	if (pdata->use_vfm_path)
 		snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
 			VFM_DEC_PROVIDER_NAME);
@@ -10670,18 +10926,12 @@
 			hevc_pair = (struct AV1HW_s *)pdata->master->private;
 		else if (pdata->slave)
 			hevc_pair = (struct AV1HW_s *)pdata->slave->private;
-
-		if (hevc_pair)
-			hw->shift_byte_count_lo = hevc_pair->shift_byte_count_lo;
 	}
 #endif
 	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,
-		&vav1_vf_provider, hw);
-
 	hw->provider_name = pdata->vf_provider_name;
 	platform_set_drvdata(pdev, pdata);
 
@@ -10819,25 +11069,38 @@
 		}
 		hw->vf_dp = vf_dp;
 	} else {
-		/*hw->vav1_amstream_dec_info.width = 0;
-		hw->vav1_amstream_dec_info.height = 0;
-		hw->vav1_amstream_dec_info.rate = 30;*/
+		u32 force_w, force_h;
+		if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5D) {
+			force_w = 1920;
+			force_h = 1088;
+		} else {
+			force_w = 8192;
+			force_h = 4608;
+		}
 		if (hw->vav1_amstream_dec_info.width)
 			hw->max_pic_w = hw->vav1_amstream_dec_info.width;
 		else
-			hw->max_pic_w = 8192;
+			hw->max_pic_w = force_w;
 
 		if (hw->vav1_amstream_dec_info.height)
 			hw->max_pic_h = hw->vav1_amstream_dec_info.height;
 		else
-			hw->max_pic_h = 4608;
+			hw->max_pic_h = force_h;
 		hw->double_write_mode = double_write_mode;
 	}
 
+	hw->endian = HEVC_CONFIG_LITTLE_ENDIAN;
 	if (!hw->is_used_v4l) {
-		hw->mem_map_mode = mem_map_mode;
+		vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
+			&vav1_vf_provider, hw);
 	}
 
+	hw->mem_map_mode = mem_map_mode;
+	if (is_support_vdec_canvas())
+		hw->endian = HEVC_CONFIG_BIG_ENDIAN;
+	if (endian)
+		hw->endian = endian;
+
 	if (is_oversize(hw->max_pic_w, hw->max_pic_h)) {
 		pr_err("over size: %dx%d, probe failed\n",
 			hw->max_pic_w, hw->max_pic_h);
@@ -10905,8 +11168,8 @@
 
 #endif
 	av1_print(hw, 0,
-			"no_head %d  low_latency %d\n",
-			hw->no_head, hw->low_latency_flag);
+			"no_head %d  low_latency %d, signal_type 0x%x\n",
+			hw->no_head, hw->low_latency_flag, hw->video_signal_type);
 #if 0
 	hw->buf_start = pdata->mem_start;
 	hw->buf_size = pdata->mem_end - pdata->mem_start + 1;
@@ -10938,6 +11201,7 @@
 	hw->first_sc_checked = 0;
 	hw->fatal_error = 0;
 	hw->show_frame_num = 0;
+	hw->run_ready_min_buf_num = run_ready_min_buf_num;
 
 	if (debug) {
 		av1_print(hw, AOM_DEBUG_HW_MORE, "===AV1 decoder mem resource 0x%lx size 0x%x\n",
@@ -10955,6 +11219,11 @@
 		pdata->dec_status = NULL;
 		return -ENODEV;
 	}
+
+#ifdef AUX_DATA_CRC
+	vdec_aux_data_check_init(pdata);
+#endif
+
 	vdec_set_prepare_level(pdata, start_decode_buf_level);
 	hevc_source_changed(VFORMAT_AV1, 4096, 2048, 60);
 
@@ -10977,6 +11246,10 @@
 	if (debug)
 		av1_print(hw, AOM_DEBUG_HW_MORE, "amvdec_av1_remove\n");
 
+#ifdef AUX_DATA_CRC
+	vdec_aux_data_check_exit(vdec);
+#endif
+
 	vmav1_stop(hw);
 
 	if (vdec->parallel_dec == 1)
@@ -11002,6 +11275,8 @@
 		   hw->pts_missed, hw->pts_hit, hw->frame_dur);
 #endif
 	/* devm_kfree(&pdev->dev, (void *)hw); */
+	if (is_rdma_enable())
+		dma_free_coherent(amports_get_dma_device(), RDMA_SIZE, hw->rdma_adr, hw->rdma_phy_adr);
 	vfree(hw->pbi);
 	release_dblk_struct(hw);
 	vfree((void *)hw);
@@ -11068,7 +11343,10 @@
 #endif
 	/*
 	if (vdec_is_support_4k()) {
-		p_buf_info = &aom_workbuff_spec[1];
+		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)
+			p_buf_info = &aom_workbuff_spec[1];
+		else
+			p_buf_info = &aom_workbuff_spec[1];
 	} else
 		p_buf_info = &aom_workbuff_spec[0];
 
@@ -11102,10 +11380,13 @@
 		pr_err("failed to register amvdec_av1 driver\n");
 		return -ENODEV;
 	}
-
-	if ((get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_TM2) || is_cpu_tm2_revb()) {
+	if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5D) {
 		amvdec_av1_profile.profile =
-				"8k, 10bit, dwrite, compressed, no_head, frame_dv";
+				"10bit, dwrite, compressed, no_head, v4l-uvm";
+	} else if (((get_cpu_major_id() > AM_MESON_CPU_MAJOR_ID_TM2) || is_cpu_tm2_revb())
+		&& (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5)) {
+		amvdec_av1_profile.profile =
+				"8k, 10bit, dwrite, compressed, no_head, frame_dv, v4l-uvm";
 	} else {
 		amvdec_av1_profile.name = "av1_unsupport";
 	}
@@ -11125,6 +11406,7 @@
 	INIT_REG_NODE_CONFIGS("media.decoder", &av1_node,
 		"av1", av1_configs, CONFIG_FOR_RW);
 #endif
+	vcodec_feature_register(VFORMAT_AV1, 0);
 
 	return 0;
 }
@@ -11363,6 +11645,9 @@
 module_param(without_display_mode, uint, 0664);
 MODULE_PARM_DESC(without_display_mode, "\n without_display_mode\n");
 
+module_param(v4l_bitstream_id_enable, uint, 0664);
+MODULE_PARM_DESC(v4l_bitstream_id_enable, "\n v4l_bitstream_id_enable\n");
+
 module_init(amvdec_av1_driver_init_module);
 module_exit(amvdec_av1_driver_remove_module);
 
diff --git a/drivers/frame_provider/decoder/vc1/vvc1.c b/drivers/frame_provider/decoder/vc1/vvc1.c
index aa215a9..1f0dfa9 100644
--- a/drivers/frame_provider/decoder/vc1/vvc1.c
+++ b/drivers/frame_provider/decoder/vc1/vvc1.c
@@ -30,7 +30,6 @@
 #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/vdec_reg.h>
 #include "../utils/amvdec.h"
 #include "../utils/vdec.h"
@@ -41,10 +40,11 @@
 #include <linux/amlogic/media/codec_mm/codec_mm.h>
 #include <linux/amlogic/media/codec_mm/configs.h>
 #include "../utils/firmware.h"
-#include <linux/amlogic/tee.h>
+//#include <linux/amlogic/tee.h>
+#include <uapi/linux/tee.h>
 #include <linux/delay.h>
 #include "../../../common/chips/decoder_cpu_ver_info.h"
-
+#include "../utils/vdec_feature.h"
 
 #define DRIVER_NAME "amvdec_vc1"
 #define MODULE_NAME "amvdec_vc1"
@@ -146,6 +146,7 @@
 static bool is_reset;
 static struct work_struct set_clk_work;
 static struct work_struct error_wd_work;
+static struct canvas_config_s vc1_canvas_config[DECODE_BUFFER_NUM_MAX][3];
 spinlock_t vc1_rp_lock;
 
 
@@ -516,9 +517,9 @@
 					}
 					if (next_pts_us64 != 0) {
 						next_pts_us64 +=
-						(u64)((vf->duration) -
+						div_u64((u64)((vf->duration) -
 						((vf->duration) >> 4)) *
-						100 / 9;
+						100, 9);
 					}
 				} else {
 					vf->duration =
@@ -550,6 +551,17 @@
 				decoder_bmmu_box_get_mem_handle(
 					mm_blk_handle,
 					buffer_index);
+			if (is_support_vdec_canvas()) {
+				vf->canvas0Addr = vf->canvas1Addr = -1;
+				vf->canvas0_config[0] = vc1_canvas_config[buffer_index][0];
+				vf->canvas0_config[1] = vc1_canvas_config[buffer_index][1];
+#ifdef NV21
+				vf->plane_num = 2;
+#else
+				vf->canvas0_config[2] = vc1_canvas_config[buffer_index][2];
+				vf->plane_num = 3;
+#endif
+			}
 			kfifo_put(&display_q, (const struct vframe_s *)vf);
 			ATRACE_COUNTER(MODULE_NAME, vf->pts);
 
@@ -582,8 +594,8 @@
 						 ((vf->duration) >> 4));
 				}
 				if (next_pts_us64 != 0) {
-					next_pts_us64 += (u64)((vf->duration) -
-					((vf->duration) >> 4)) * 100 / 9;
+					next_pts_us64 += div_u64((u64)((vf->duration) -
+					((vf->duration) >> 4)) * 100, 9);
 				}
 			} else {
 				vf->duration =
@@ -614,6 +626,18 @@
 				decoder_bmmu_box_get_mem_handle(
 					mm_blk_handle,
 					buffer_index);
+
+			if (is_support_vdec_canvas()) {
+				vf->canvas0Addr = vf->canvas1Addr = -1;
+				vf->canvas0_config[0] = vc1_canvas_config[buffer_index][0];
+				vf->canvas0_config[1] = vc1_canvas_config[buffer_index][1];
+#ifdef NV21
+				vf->plane_num = 2;
+#else
+				vf->canvas0_config[2] = vc1_canvas_config[buffer_index][2];
+				vf->plane_num = 3;
+#endif
+			}
 			kfifo_put(&display_q, (const struct vframe_s *)vf);
 			ATRACE_COUNTER(MODULE_NAME, vf->pts);
 
@@ -673,9 +697,9 @@
 					}
 					if (next_pts_us64 != 0) {
 						next_pts_us64 +=
-						(u64)((vf->duration) -
+						div_u64((u64)((vf->duration) -
 						((vf->duration) >> 4)) *
-						100 / 9;
+						100, 9);
 					}
 				} else {
 					vf->duration =
@@ -709,7 +733,17 @@
 				decoder_bmmu_box_get_mem_handle(
 					mm_blk_handle,
 					buffer_index);
-
+			if (is_support_vdec_canvas()) {
+				vf->canvas0Addr = vf->canvas1Addr = -1;
+				vf->canvas0_config[0] = vc1_canvas_config[buffer_index][0];
+				vf->canvas0_config[1] = vc1_canvas_config[buffer_index][1];
+#ifdef NV21
+				vf->plane_num = 2;
+#else
+				vf->canvas0_config[2] = vc1_canvas_config[buffer_index][2];
+				vf->plane_num = 3;
+#endif
+			}
 			kfifo_put(&display_q, (const struct vframe_s *)vf);
 			ATRACE_COUNTER(MODULE_NAME, vf->pts);
 
@@ -893,30 +927,57 @@
 		}
 
 #ifdef NV21
-		canvas_config(2 * i + 0,
+		config_cav_lut_ex(2 * i + 0,
 			buf_start,
 			canvas_width, canvas_height,
-			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
-		canvas_config(2 * i + 1,
+			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32, 0, VDEC_1);
+		vc1_canvas_config[i][0].endian = 0;
+		vc1_canvas_config[i][0].width = canvas_width;
+		vc1_canvas_config[i][0].height = canvas_height;
+		vc1_canvas_config[i][0].block_mode = CANVAS_BLKMODE_32X32;
+		vc1_canvas_config[i][0].phy_addr = buf_start;
+
+		config_cav_lut_ex(2 * i + 1,
 			buf_start +
 			decbuf_y_size, canvas_width,
 			canvas_height / 2, CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_32X32);
+			CANVAS_BLKMODE_32X32, 0, VDEC_1);
+		vc1_canvas_config[i][1].endian = 0;
+		vc1_canvas_config[i][1].width = canvas_width;
+		vc1_canvas_config[i][1].height = canvas_height >> 1;
+		vc1_canvas_config[i][1].block_mode = CANVAS_BLKMODE_32X32;
+		vc1_canvas_config[i][1].phy_addr = buf_start + decbuf_y_size;
 #else
-		canvas_config(3 * i + 0,
+		config_cav_lut_ex(3 * i + 0,
 			buf_start,
 			canvas_width, canvas_height,
-			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
-		canvas_config(3 * i + 1,
+			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32, 0, VDEC_1);
+		vc1_canvas_config[i][0].endian = 0;
+		vc1_canvas_config[i][0].width = canvas_width;
+		vc1_canvas_config[i][0].height = canvas_height;
+		vc1_canvas_config[i][0].block_mode = CANVAS_BLKMODE_32X32;
+		vc1_canvas_config[i][0].phy_addr = buf_start;
+		config_cav_lut_ex(3 * i + 1,
 			buf_start +
 			decbuf_y_size, canvas_width / 2,
 			canvas_height / 2, CANVAS_ADDR_NOWRAP,
-			CANVAS_BLKMODE_32X32);
-		canvas_config(3 * i + 2,
+			CANVAS_BLKMODE_32X32, 0, VDEC_1);
+		vc1_canvas_config[i][1].endian = 0;
+		vc1_canvas_config[i][1].width = canvas_width >> 1;
+		vc1_canvas_config[i][1].height = canvas_height >> 1;
+		vc1_canvas_config[i][1].block_mode = CANVAS_BLKMODE_32X32;
+		vc1_canvas_config[i][1].phy_addr = buf_start + decbuf_y_size;
+		config_cav_lut_ex(3 * i + 2,
 			buf_start +
 			decbuf_y_size + decbuf_uv_size,
 			canvas_width / 2, canvas_height / 2,
-			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32);
+			CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32, 0, VDEC_1);
+		vc1_canvas_config[i][2].endian = 0;
+		vc1_canvas_config[i][2].width = canvas_width >> 1;
+		vc1_canvas_config[i][2].height = canvas_height >> 1;
+		vc1_canvas_config[i][2].block_mode = CANVAS_BLKMODE_32X32;
+		vc1_canvas_config[i][2].phy_addr = buf_start +
+			decbuf_y_size + decbuf_uv_size;
 #endif
 
 	}
@@ -994,6 +1055,8 @@
 #ifdef NV21
 	SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17);
 #endif
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
+
 	return r;
 }
 
@@ -1100,11 +1163,8 @@
 		amvdec_start();
 }
 
-
-static void vvc1_put_timer_func(unsigned long arg)
+static void vvc1_put_timer_func(struct timer_list *timer)
 {
-	struct timer_list *timer = (struct timer_list *)arg;
-
 	if (READ_VREG(VC1_SOS_COUNT) > 10)
 		schedule_work(&error_wd_work);
 
@@ -1142,7 +1202,7 @@
 		return -ENOMEM;
 
 	pr_info("vvc1_init, format %d\n", vvc1_amstream_dec_info.format);
-	init_timer(&recycle_timer);
+	timer_setup(&recycle_timer, vvc1_put_timer_func, 0);
 
 	stat |= STAT_TIMER_INIT;
 
@@ -1216,10 +1276,7 @@
 
 	stat |= STAT_VF_HOOK;
 
-	recycle_timer.data = (ulong)&recycle_timer;
-	recycle_timer.function = vvc1_put_timer_func;
 	recycle_timer.expires = jiffies + PUT_INTERVAL;
-
 	add_timer(&recycle_timer);
 
 	stat |= STAT_TIMER_ARM;
@@ -1327,32 +1384,16 @@
 }
 
 /****************************************/
-#ifdef CONFIG_PM
-static int vc1_suspend(struct device *dev)
-{
-	amvdec_suspend(to_platform_device(dev), dev->power.power_state);
-	return 0;
-}
-
-static int vc1_resume(struct device *dev)
-{
-	amvdec_resume(to_platform_device(dev));
-	return 0;
-}
-
-static const struct dev_pm_ops vc1_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(vc1_suspend, vc1_resume)
-};
-#endif
 
 static struct platform_driver amvdec_vc1_driver = {
 	.probe = amvdec_vc1_probe,
 	.remove = amvdec_vc1_remove,
+#ifdef CONFIG_PM
+	.suspend = amvdec_suspend,
+	.resume = amvdec_resume,
+#endif
 	.driver = {
 		.name = DRIVER_NAME,
-#ifdef CONFIG_PM
-		.pm = &vc1_pm_ops,
-#endif
 	}
 };
 
@@ -1377,6 +1418,7 @@
 		return -ENODEV;
 	}
 	vcodec_profile_register(&amvdec_vc1_profile);
+	vcodec_feature_register(VFORMAT_VC1, 0);
 	return 0;
 }
 
diff --git a/drivers/frame_provider/decoder/vp9/vvp9.c b/drivers/frame_provider/decoder/vp9/vvp9.c
index fa75afb..e6a47fd 100644
--- a/drivers/frame_provider/decoder/vp9/vvp9.c
+++ b/drivers/frame_provider/decoder/vp9/vvp9.c
@@ -37,14 +37,15 @@
 #include <linux/dma-mapping.h>
 #include <linux/dma-contiguous.h>
 #include <linux/slab.h>
-#include <linux/amlogic/tee.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"
 
 #define MEM_NAME "codec_vp9"
-/* #include <mach/am_regs.h> */
 #include <linux/amlogic/media/utils/vdec_reg.h>
 #include "../utils/vdec.h"
 #include "../utils/amvdec.h"
@@ -59,16 +60,17 @@
 #include "../../../common/chips/decoder_cpu_ver_info.h"
 #include "../utils/vdec_v4l2_buffer_ops.h"
 #include <media/v4l2-mem2mem.h>
+#include "../utils/vdec_feature.h"
 
 #define MIX_STREAM_SUPPORT
 
 #include "vvp9.h"
 
-
+#define VP9_10B_MMU_DW
 /*#define SUPPORT_FB_DECODING*/
 /*#define FB_DECODING_TEST_SCHEDULE*/
 
-
+#define CO_MV_COMPRESS
 #define HW_MASK_FRONT    0x1
 #define HW_MASK_BACK     0x2
 
@@ -81,11 +83,21 @@
 #define HEVCD_MPP_ANC2AXI_TBL_DATA                 0x3464
 #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_MV_INFO                               0x310d
 #define HEVC_QP_INFO                               0x3137
 #define HEVC_SKIP_INFO                             0x3136
 
+#define HEVC_SAO_CTRL9                             0x362d
+#define HEVC_CM_HEADER_START_ADDR2                 0x364a
+#define HEVC_SAO_MMU_DMA_CTRL2                     0x364c
+#define HEVC_SAO_MMU_VH0_ADDR2                     0x364d
+#define HEVC_SAO_MMU_VH1_ADDR2                     0x364e
+#define HEVC_SAO_MMU_STATUS2                       0x3650
+#define HEVC_DW_VH0_ADDDR                          0x365e
+#define HEVC_DW_VH1_ADDDR                          0x365f
+
 #define VP9_10B_DEC_IDLE                           0
 #define VP9_10B_DEC_FRAME_HEADER                   1
 #define VP9_10B_DEC_SLICE_SEGMENT                  2
@@ -148,6 +160,7 @@
 #ifdef MULTI_INSTANCE_SUPPORT
 #define MAX_DECODE_INSTANCE_NUM     9
 #define MULTI_DRIVER_NAME "ammvdec_vp9"
+
 static unsigned int max_decode_instance_num
 				= MAX_DECODE_INSTANCE_NUM;
 static unsigned int decode_frame_count[MAX_DECODE_INSTANCE_NUM];
@@ -174,6 +187,7 @@
  *	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;
@@ -211,7 +225,7 @@
 #endif
 static void vvp9_prot_init(struct VP9Decoder_s *pbi, u32 mask);
 static int vvp9_local_init(struct VP9Decoder_s *pbi);
-static void vvp9_put_timer_func(unsigned long arg);
+static void vvp9_put_timer_func(struct timer_list *timer);
 static void dump_data(struct VP9Decoder_s *pbi, int size);
 static unsigned char get_data_check_sum
 	(struct VP9Decoder_s *pbi, int size);
@@ -223,7 +237,15 @@
 		int pic_height,
 		unsigned short bit_depth,
 		unsigned int *mmu_index_adr);
-
+#ifdef VP9_10B_MMU_DW
+int vp9_alloc_mmu_dw(
+	struct VP9Decoder_s *pbi,
+	int cur_buf_idx,
+	int pic_width,
+	int pic_height,
+	unsigned short bit_depth,
+	unsigned int *mmu_index_adr);
+#endif
 
 static const char vvp9_dec_id[] = "vvp9-dev";
 
@@ -256,6 +278,20 @@
 #define MAX_FRAME_8K_NUM 0x4800
 
 #define HEVC_ASSIST_MMU_MAP_ADDR                   0x3009
+// bit[31:20] -- fb_read_lcu_y
+// READ only// bit[19:8]  -- fb_read_lcu_x
+// READ only// bit[7]     -- fb_read_lcu_latch
+// bit[6:5]   -- reserved
+// bit[4]  -- fb_disable_wr_iqit_buf
+// bit[3]  -- fb_read_avs2_enable
+// bit[2]  -- fb_read_vp9_enable
+// bit[1]  -- fb_avs2_enable
+// bit[0]  -- fb_vp9_enable
+#define HEVC_ASSIST_HED_FB_CTL                     0x300c
+// [31:16] height// [15:0] width
+#define HEVC_ASSIST_PIC_SIZE_FB_READ               0x300d
+#define HEVC_ASSIST_MMU_MAP_ADDR2                  0x300e
+
 
 #ifdef SUPPORT_FB_DECODING
 /* register define */
@@ -269,6 +305,7 @@
 #define MAX_STAGE_PAGE_NUM 0x1200
 #define STAGE_MMU_MAP_SIZE (MAX_STAGE_PAGE_NUM * 4)
 #endif
+
 static inline int div_r32(int64_t m, int n)
 {
 /*
@@ -337,11 +374,6 @@
 #define DOUBLE_WRITE_YSTART_TEMP 0x02000000
 #define DOUBLE_WRITE_CSTART_TEMP 0x02900000
 
-
-
-typedef unsigned int u32;
-typedef unsigned short u16;
-
 #define VP9_DEBUG_BUFMGR                   0x01
 #define VP9_DEBUG_BUFMGR_MORE              0x02
 #define VP9_DEBUG_BUFMGR_DETAIL            0x04
@@ -401,6 +433,8 @@
 
 static u32 without_display_mode;
 
+static u32 v4l_bitstream_id_enable = 1;
+
 /*
  *[3:0] 0: default use config from omx.
  *      1: force enable fence.
@@ -441,9 +475,12 @@
 //#define MMU_COMPRESS_8K_HEADER_SIZE  (MMU_COMPRESS_HEADER_SIZE * 4)
 
 #define MMU_COMPRESS_HEADER_SIZE  0x48000
-#define MMU_COMPRESS_8K_HEADER_SIZE  (0x48000*4)
+#define MMU_COMPRESS_HEADER_SIZE_DW  0x48000
+#define MMU_COMPRESS_8K_HEADER_SIZE  (MMU_COMPRESS_HEADER_SIZE * 4)
+
 #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))
 
@@ -547,6 +584,9 @@
 	int slice_idx;
 	/*buffer*/
 	unsigned long header_adr;
+#ifdef VP9_10B_MMU_DW
+	unsigned long header_dw_adr;
+#endif
 	unsigned long mpred_mv_wr_start_addr;
 	int mv_size;
 	/*unsigned long mc_y_adr;
@@ -554,6 +594,8 @@
 	 */
 	unsigned int dw_y_adr;
 	unsigned int dw_u_v_adr;
+	u32	luma_size;
+	u32	chroma_size;
 	int mc_canvas_y;
 	int mc_canvas_u_v;
 
@@ -608,10 +650,9 @@
 
 	u32 hw_decode_time;
 	u32 frame_size2; // For frame base mode
-	bool vframe_bound;
 
 	/* vdec sync. */
-	struct fence *fence;
+	struct dma_fence *fence;
 
 	/* hdr10 plus data */
 	u32 hdr10p_data_size;
@@ -707,6 +748,8 @@
  */
 	int row;
 	int col;
+
+	int show_frame;
 } RefCntBuffer;
 
 struct RefBuffer_s {
@@ -860,7 +903,6 @@
 	struct BufferPool_s *buffer_pool;
 
 	int above_context_alloc_cols;
-
 };
 
 static void set_canvas(struct VP9Decoder_s *pbi,
@@ -958,6 +1000,10 @@
 	struct buff_s seg_map;
 	struct buff_s mmu_vbh;
 	struct buff_s cm_header;
+#ifdef VP9_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;
@@ -1017,6 +1063,11 @@
 #endif
 #endif
 
+struct vp9_fence_vf_t {
+	u32 used_size;
+	struct vframe_s *fence_vf[VF_POOL_SIZE];
+};
+
 struct VP9Decoder_s {
 #ifdef MULTI_INSTANCE_SUPPORT
 	unsigned char index;
@@ -1084,7 +1135,10 @@
 
 	void *frame_mmu_map_addr;
 	dma_addr_t frame_mmu_map_phy_addr;
-
+#ifdef VP9_10B_MMU_DW
+	void *frame_mmu_dw_map_addr;
+	dma_addr_t frame_mmu_dw_map_phy_addr;
+#endif
 	unsigned int use_cma_flag;
 
 	struct BUF_s m_BUF[MAX_BUF_NUM];
@@ -1101,7 +1155,6 @@
 	int pic_num;
 	int lcu_size_log2;
 	unsigned int losless_comp_body_size;
-
 	u32 video_signal_type;
 
 	int pts_mode;
@@ -1179,6 +1232,10 @@
 	void *mmu_box;
 	void *bmmu_box;
 	int mmu_enable;
+#ifdef VP9_10B_MMU_DW
+	void *mmu_box_dw;
+	int dw_mmu_enable;
+#endif
 	struct vframe_master_display_colour_s vf_dp;
 	struct firmware_s *fw;
 	int max_pic_w;
@@ -1237,18 +1294,24 @@
 	u64 frame_mode_pts64_save[FRAME_BUFFERS];
 	int run_ready_min_buf_num;
 	int one_package_frame_cnt;
+	int buffer_wrap[FRAME_BUFFERS];
+	int last_width;
+	int last_height;
 	u32 error_frame_width;
 	u32 error_frame_height;
-	char vdec_name[32];
-	char pts_name[32];
-	char new_q_name[32];
-	char disp_q_name[32];
+	u32 endian;
+	ulong fb_token;
+	struct vp9_fence_vf_t fence_vf_s;
+	struct mutex fence_mutex;
+	dma_addr_t rdma_phy_adr;
+	unsigned *rdma_adr;
+	struct trace_decoder_name trace;
 };
 
 static int vp9_print(struct VP9Decoder_s *pbi,
 	int flag, const char *fmt, ...)
 {
-#define HEVC_PRINT_BUF		256
+#define HEVC_PRINT_BUF		512
 	unsigned char buf[HEVC_PRINT_BUF];
 	int len = 0;
 
@@ -1272,6 +1335,9 @@
 	int max = (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)?
 		MAX_SIZE_8K : 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;
 
@@ -1281,6 +1347,26 @@
 	return false;
 }
 
+static int vvp9_mmu_compress_header_size(int w, int h)
+{
+	if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+		IS_8K_SIZE(w, h))
+		return (MMU_COMPRESS_HEADER_SIZE_8K);
+	if (IS_4K_SIZE(w, h))
+		return (MMU_COMPRESS_HEADER_SIZE_4K);
+	return (MMU_COMPRESS_HEADER_SIZE_1080P);
+}
+
+/*#define FRAME_MMU_MAP_SIZE  (MAX_FRAME_4K_NUM * 4)*/
+static int vvp9_frame_mmu_map_size(struct VP9Decoder_s *pbi)
+{
+	if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+		IS_8K_SIZE(pbi->max_pic_w, pbi->max_pic_h))
+		return (MAX_FRAME_8K_NUM << 2);
+
+	return (MAX_FRAME_4K_NUM << 2);
+}
+
 static int v4l_alloc_and_config_pic(struct VP9Decoder_s *pbi,
 	struct PIC_BUFFER_CONFIG_s *pic);
 
@@ -1293,8 +1379,9 @@
 			pbi->vp9_first_pts_ready = 0;
 			pbi->duration_from_pts_done = 0;
 		}
-		pr_info("%s (%d,%d)=>(%d,%d)\r\n", __func__, cm->width,
-			cm->height, width, height);
+		pr_info("%s (%d,%d)=>(%d,%d)\r\n", __func__,
+			cm->width, cm->height,
+			width, height);
 		cm->width = width;
 		cm->height = height;
 	}
@@ -1330,6 +1417,7 @@
 		struct VP9Decoder_s *pbi,
 		struct VP9_Common_s *cm, union param_u *params,
 		unsigned int *mmu_index_adr,
+		unsigned int *mmu_dw_index_adr,
 		int print_header_info) {
 	int width, height;
 	struct BufferPool_s * const pool = cm->buffer_pool;
@@ -1373,7 +1461,19 @@
 		}
 		cm->cur_fb_idx_mmu = cm->new_fb_idx;
 	}
-
+#ifdef VP9_10B_MMU_DW
+	if (pbi->dw_mmu_enable && (mmu_dw_index_adr != NULL)) {
+		ret = vp9_alloc_mmu_dw(pbi, cm->new_fb_idx,
+			params->p.width, params->p.height,
+			params->p.bit_depth, mmu_dw_index_adr);
+		if (ret != 0) {
+				pr_err("can't alloc need mmu1 dw,idx %d ret =%d\n",
+					cm->new_fb_idx,
+					ret);
+				return ret;
+		}
+	}
+#endif
 	resize_context_buffers(pbi, cm, width, height);
 	setup_display_size(cm, params, print_header_info);
 #if 0
@@ -1416,6 +1516,7 @@
 		struct VP9_Common_s *cm,
 		union param_u *params,
 		unsigned int *mmu_index_adr,
+		unsigned int *mmu_dw_index_adr,
 		int print_header_info) {
 
 	int width, height;
@@ -1501,7 +1602,18 @@
 		}
 		cm->cur_fb_idx_mmu = cm->new_fb_idx;
 	}
-
+#ifdef VP9_10B_MMU_DW
+	if (pbi->dw_mmu_enable && (mmu_dw_index_adr != NULL)) {
+		ret = vp9_alloc_mmu_dw(pbi, cm->new_fb_idx,
+			params->p.width, params->p.height,
+			params->p.bit_depth, mmu_dw_index_adr);
+		if (ret != 0) {
+			pr_err("can't alloc need mmu dw,idx %d\r\n",
+				cm->new_fb_idx);
+			return ret;
+		}
+	}
+#endif
 	/*Check to make sure at least one of frames that this frame references
 	 *has valid dimensions.
 	 */
@@ -1644,46 +1756,19 @@
 
 static u32 get_valid_double_write_mode(struct VP9Decoder_s *pbi)
 {
-	return ((double_write_mode & 0x80000000) == 0) ?
+	u32 dw = ((double_write_mode & 0x80000000) == 0) ?
 		pbi->double_write_mode :
 		(double_write_mode & 0x7fffffff);
-}
-
-static int v4l_parser_get_double_write_mode(struct VP9Decoder_s *pbi)
-{
-	u32 valid_dw_mode = get_valid_double_write_mode(pbi);
-	u32 dw;
-	int w, h;
-
-	/* mask for supporting double write value bigger than 0x100 */
-	if (valid_dw_mode & 0xffffff00) {
-		w = pbi->frame_width;
-		h = pbi->frame_height;
-
-		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:
-			break;
+	if (dw & 0x20) {
+		if ((get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_T3)
+			&& ((dw & 0xf) == 2 || (dw & 0xf) == 3)) {
+			pr_info("MMU doueble write 1:4 not supported !!!\n");
+			dw = 0;
 		}
-		return dw;
 	}
-
-	return valid_dw_mode;
+	return dw;
 }
 
-
 static int get_double_write_mode(struct VP9Decoder_s *pbi)
 {
 	u32 valid_dw_mode = get_valid_double_write_mode(pbi);
@@ -1692,6 +1777,14 @@
 	struct VP9_Common_s *cm = &pbi->common;
 	struct PIC_BUFFER_CONFIG_s *cur_pic_config;
 
+	if (pbi->is_used_v4l) {
+		unsigned int out;
+
+		vdec_v4l_get_dw_mode(pbi->v4l2_ctx, &out);
+		dw = out;
+		return dw;
+	}
+
 	/* mask for supporting double write value bigger than 0x100 */
 	if (valid_dw_mode & 0xffffff00) {
 		if (!cm->cur_frame)
@@ -1753,19 +1846,52 @@
 }
 #endif
 
-static int get_double_write_ratio(struct VP9Decoder_s *pbi,
-	int dw_mode)
+//#define	MAX_4K_NUM		0x1200
+
+/* return page number */
+static int vp9_mmu_page_num(struct VP9Decoder_s *pbi,
+		int w, int h, int save_mode)
 {
-	int ratio = 1;
-	if ((dw_mode == 2) ||
-			(dw_mode == 3))
-		ratio = 4;
-	else if (dw_mode == 4)
-		ratio = 2;
-	return ratio;
+	int picture_size;
+	int cur_mmu_4k_number, max_frame_num;
+
+	picture_size = compute_losless_comp_body_size(w, h, save_mode);
+	cur_mmu_4k_number = ((picture_size + (PAGE_SIZE - 1)) >> PAGE_SHIFT);
+
+	max_frame_num = (vvp9_frame_mmu_map_size(pbi) >> 2);
+
+	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, w, h);
+		return -1;
+	}
+
+	return cur_mmu_4k_number;
 }
 
-//#define	MAX_4K_NUM		0x1200
+static struct internal_comp_buf* v4lfb_to_icomp_buf(
+		struct VP9Decoder_s *pbi,
+		struct vdec_v4l2_buffer *fb)
+{
+	struct aml_video_dec_buf *aml_fb = NULL;
+	struct aml_vcodec_ctx * v4l2_ctx = pbi->v4l2_ctx;
+
+	aml_fb = container_of(fb, struct aml_video_dec_buf, frame_buffer);
+	return &v4l2_ctx->comp_bufs[aml_fb->internal_index];
+}
+
+static struct internal_comp_buf* index_to_icomp_buf(
+		struct VP9Decoder_s *pbi, int index)
+{
+	struct aml_video_dec_buf *aml_fb = NULL;
+	struct aml_vcodec_ctx * v4l2_ctx = pbi->v4l2_ctx;
+	struct vdec_v4l2_buffer *fb = NULL;
+
+	fb = (struct vdec_v4l2_buffer *)
+		pbi->m_BUF[index].v4l_ref_buf_addr;
+	aml_fb = container_of(fb, struct aml_video_dec_buf, frame_buffer);
+	return &v4l2_ctx->comp_bufs[aml_fb->internal_index];
+}
 
 int vp9_alloc_mmu(
 	struct VP9Decoder_s *pbi,
@@ -1775,42 +1901,90 @@
 	unsigned short bit_depth,
 	unsigned int *mmu_index_adr)
 {
+	int ret;
 	int bit_depth_10 = (bit_depth == VPX_BITS_10);
-	int picture_size;
-	int cur_mmu_4k_number, max_frame_num;
-	if (!pbi->mmu_box) {
-		pr_err("error no mmu box!\n");
-		return -1;
-	}
+	int cur_mmu_4k_number;
+
 	if (get_double_write_mode(pbi) == 0x10)
 		return 0;
+
 	if (bit_depth >= VPX_BITS_12) {
 		pbi->fatal_error = DECODER_FATAL_ERROR_SIZE_OVERFLOW;
 		pr_err("fatal_error, un support bit depth 12!\n\n");
 		return -1;
 	}
-	picture_size = compute_losless_comp_body_size(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;
+	cur_mmu_4k_number = vp9_mmu_page_num(pbi,
+				pic_width,
+				pic_height,
+				bit_depth_10);
+	if (cur_mmu_4k_number < 0)
+		return -1;
 
-	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);
+	if (pbi->is_used_v4l) {
+		struct internal_comp_buf *ibuf =
+			index_to_icomp_buf(pbi, cur_buf_idx);
+
+		ret = decoder_mmu_box_alloc_idx(
+				ibuf->mmu_box,
+				ibuf->index,
+				ibuf->frame_buffer_size,
+				mmu_index_adr);
+	} else {
+		ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_START);
+		ret = decoder_mmu_box_alloc_idx(
+				pbi->mmu_box,
+				cur_buf_idx,
+				cur_mmu_4k_number,
+				mmu_index_adr);
+		ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_END);
+	}
+
+	return ret;
+}
+
+#ifdef VP9_10B_MMU_DW
+int vp9_alloc_mmu_dw(
+	struct VP9Decoder_s *pbi,
+	int cur_buf_idx,
+	int pic_width,
+	int pic_height,
+	unsigned short bit_depth,
+	unsigned int *mmu_index_adr)
+{
+	int ret;
+	int bit_depth_10 = (bit_depth == VPX_BITS_10);
+	int cur_mmu_4k_number;
+
+	if (pbi->is_used_v4l)
+		return -1;
+
+	if (get_double_write_mode(pbi) == 0x10)
+		return 0;
+
+	if (bit_depth >= VPX_BITS_12) {
+		pbi->fatal_error = DECODER_FATAL_ERROR_SIZE_OVERFLOW;
+		pr_err("fatal_error, un support bit depth 12!\n\n");
 		return -1;
 	}
 
-	return decoder_mmu_box_alloc_idx(
-		pbi->mmu_box,
-		cur_buf_idx,
-		cur_mmu_4k_number,
-		mmu_index_adr);
+	cur_mmu_4k_number = vp9_mmu_page_num(pbi,
+				pic_width,
+				pic_height,
+				bit_depth_10);
+	if (cur_mmu_4k_number < 0)
+		return -1;
+
+	ret = decoder_mmu_box_alloc_idx(
+			pbi->mmu_box_dw,
+			cur_buf_idx,
+			cur_mmu_4k_number,
+			mmu_index_adr);
+
+	return ret;
 }
 
+#endif
 
 #ifndef MV_USE_FIXED_BUF
 static void dealloc_mv_bufs(struct VP9Decoder_s *pbi)
@@ -1858,7 +2032,7 @@
 		ret = 0;
 		if (debug) {
 			pr_info(
-			"MV Buffer %d: start_adr %p size %x\n",
+			"MV Buffer %d: start_adr %px size %x\n",
 			i,
 			(void *)pbi->m_mv_BUF[i].start_adr,
 			pbi->m_mv_BUF[i].size);
@@ -1982,7 +2156,7 @@
 		pic_config->mv_size = pbi->m_mv_BUF[ret].size;
 		if (debug & VP9_DEBUG_BUFMGR_MORE)
 			pr_info(
-			"%s => %d (%ld) size 0x%x\n",
+			"%s => %d (%lx) size 0x%x\n",
 			__func__, ret,
 			pic_config->mpred_mv_wr_start_addr,
 			pic_config->mv_size);
@@ -2042,10 +2216,18 @@
 	struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
 	int i;
 	for (i = 0; i < pbi->used_buf_num; ++i) {
+#if 0
 		if ((frame_bufs[i].ref_count == 0) &&
 			(frame_bufs[i].buf.index != -1) &&
 			(frame_bufs[i].buf.mv_buf_index >= 0)
 			)
+#else
+		if ((&frame_bufs[i] != cm->prev_frame) &&
+			(frame_bufs[i].buf.index != -1) &&
+			(frame_bufs[i].buf.mv_buf_index >= 0)
+			)
+#endif
+
 			put_mv_buf(pbi, &frame_bufs[i].buf.mv_buf_index);
 	}
 }
@@ -2326,7 +2508,8 @@
 	for (i = 0; i < pbi->used_buf_num; ++i) {
 		if ((frame_bufs[i].ref_count == 0) &&
 			(frame_bufs[i].buf.vf_ref == 0) &&
-			(frame_bufs[i].buf.index != -1)
+			(frame_bufs[i].buf.index != -1) &&
+			(cm->cur_frame != &frame_bufs[i])
 			)
 			break;
 	}
@@ -2344,6 +2527,39 @@
 	return i;
 }
 
+static void update_hide_frame_timestamp(struct VP9Decoder_s *pbi)
+{
+	struct RefCntBuffer_s *const frame_bufs =
+		pbi->common.buffer_pool->frame_bufs;
+	int i;
+
+	for (i = 0; i < pbi->used_buf_num; ++i) {
+		if ((!frame_bufs[i].show_frame) &&
+			(!frame_bufs[i].buf.vf_ref) &&
+			(frame_bufs[i].buf.BUF_index != -1)) {
+			frame_bufs[i].buf.timestamp = pbi->chunk->timestamp;
+			vp9_print(pbi, VP9_DEBUG_OUT_PTS,
+				"%s, update %d hide frame ts: %lld\n",
+				__func__, i, frame_bufs[i].buf.timestamp);
+		}
+	}
+}
+
+static int get_free_fb_idx(struct VP9Decoder_s *pbi)
+{
+	int i;
+	struct VP9_Common_s *const cm = &pbi->common;
+	struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
+
+	for (i = 0; i < pbi->used_buf_num; ++i) {
+		if ((frame_bufs[i].ref_count == 0) &&
+			(frame_bufs[i].buf.vf_ref == 0))
+			break;
+	}
+
+	return i;
+}
+
 static int v4l_get_free_fb(struct VP9Decoder_s *pbi)
 {
 	struct VP9_Common_s *const cm = &pbi->common;
@@ -2351,8 +2567,9 @@
 	struct aml_vcodec_ctx * v4l = pbi->v4l2_ctx;
 	struct v4l_buff_pool *pool = &v4l->cap_pool;
 	struct PIC_BUFFER_CONFIG_s *pic = NULL;
-	int i, idx = INVALID_IDX;
+	struct PIC_BUFFER_CONFIG_s *free_pic = NULL;
 	ulong flags;
+	int idx, i;
 
 	lock_buffer_pool(cm->buffer_pool, flags);
 
@@ -2367,47 +2584,92 @@
 				(pic->vf_ref == 0) &&
 				(pic->index != -1) &&
 				pic->cma_alloc_addr) {
-				idx = i;
+				free_pic = pic;
 			}
 			break;
 		case V4L_CAP_BUFF_IN_M2M:
-			pic = &frame_bufs[index].buf;
+			idx = get_free_fb_idx(pbi);
+			pic = &frame_bufs[idx].buf;
 			pic->y_crop_width = pbi->frame_width;
 			pic->y_crop_height = pbi->frame_height;
+			pbi->buffer_wrap[idx] = index;
 			if (!v4l_alloc_and_config_pic(pbi, pic)) {
 				set_canvas(pbi, pic);
 				init_pic_list_hw(pbi);
-				idx = index;
+				free_pic = pic;
 			}
 			break;
 		default:
-			pr_err("v4l buffer state err %d.\n", state);
 			break;
 		}
 
-		if (idx != INVALID_IDX) {
-			frame_bufs[idx].ref_count = 1;
+		if (free_pic) {
+			frame_bufs[i].ref_count = 1;
 			break;
 		}
 	}
 
+	if (free_pic && pbi->chunk) {
+		free_pic->timestamp = pbi->chunk->timestamp;
+		update_hide_frame_timestamp(pbi);
+	}
+
 	unlock_buffer_pool(cm->buffer_pool, flags);
 
-	return idx;
+	if (free_pic) {
+		struct vdec_v4l2_buffer *fb =
+			(struct vdec_v4l2_buffer *)
+			pbi->m_BUF[i].v4l_ref_buf_addr;
+
+		fb->status = FB_ST_DECODER;
+	}
+
+	if (debug & VP9_DEBUG_OUT_PTS) {
+		if (free_pic) {
+			pr_debug("%s, idx: %d, ts: %lld\n",
+				__func__, free_pic->index, free_pic->timestamp);
+		} else {
+			pr_debug("%s, vp9 get free pic null\n", __func__);
+		}
+	}
+
+	return free_pic ? free_pic->index : INVALID_IDX;
 }
 
 static int get_free_buf_count(struct VP9Decoder_s *pbi)
 {
 	struct VP9_Common_s *const cm = &pbi->common;
 	struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
-	int i;
-	int free_buf_count = 0;
-	for (i = 0; i < pbi->used_buf_num; ++i)
-		if ((frame_bufs[i].ref_count == 0) &&
-			(frame_bufs[i].buf.vf_ref == 0) &&
-			(frame_bufs[i].buf.index != -1)
-			)
-			free_buf_count++;
+	struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(pbi->v4l2_ctx);
+	int i, free_buf_count = 0;
+
+	if (pbi->is_used_v4l) {
+		for (i = 0; i < pbi->used_buf_num; ++i) {
+			if ((frame_bufs[i].ref_count == 0) &&
+				(frame_bufs[i].buf.vf_ref == 0) &&
+				frame_bufs[i].buf.cma_alloc_addr) {
+				free_buf_count++;
+			}
+		}
+
+		if (ctx->cap_pool.dec < pbi->used_buf_num) {
+			free_buf_count +=
+				v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx);
+		}
+
+		/* trigger to parse head data. */
+		if (!pbi->v4l_params_parsed) {
+			free_buf_count = pbi->run_ready_min_buf_num;
+		}
+	} else {
+		for (i = 0; i < pbi->used_buf_num; ++i) {
+			if ((frame_bufs[i].ref_count == 0) &&
+				(frame_bufs[i].buf.vf_ref == 0) &&
+				(frame_bufs[i].buf.index != -1))
+				free_buf_count++;
+		}
+	}
+
 	return free_buf_count;
 }
 
@@ -2528,9 +2790,11 @@
 
 	pbi->ready_for_new_data = 0;
 
-	if (pbi->has_keyframe == 0 &&
-		params->p.frame_type != KEY_FRAME){
+	if ((pbi->has_keyframe == 0) &&
+		(params->p.frame_type != KEY_FRAME) &&
+		(!params->p.intra_only)){
 		on_no_keyframe_skiped++;
+		pr_info("vp9_bufmgr_process no key frame return\n");
 		return -2;
 	}
 	pbi->has_keyframe = 1;
@@ -2631,6 +2895,7 @@
 		pbi->refresh_frame_flags = 0;
 		/*cm->lf.filter_level = 0;*/
 		cm->show_frame = 1;
+		cm->cur_frame->show_frame = 1;
 
 		/*
 		 *if (pbi->frame_parallel_decode) {
@@ -2646,7 +2911,7 @@
 	cm->show_frame = params->p.show_frame;
 	cm->bit_depth = params->p.bit_depth;
 	cm->error_resilient_mode = params->p.error_resilient_mode;
-
+	cm->cur_frame->show_frame = cm->show_frame;
 
 	if (cm->frame_type == KEY_FRAME) {
 		pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1;
@@ -2655,10 +2920,19 @@
 			cm->frame_refs[i].idx = INVALID_IDX;
 			cm->frame_refs[i].buf = NULL;
 		}
-
+#ifdef VP9_10B_MMU_DW
 		ret = setup_frame_size(pbi,
-			cm, params,  pbi->frame_mmu_map_addr,
-				print_header_info);
+			cm, params,
+			pbi->frame_mmu_map_addr,
+			pbi->frame_mmu_dw_map_addr,
+			print_header_info);
+#else
+		ret = setup_frame_size(pbi,
+			cm, params,
+			pbi->frame_mmu_map_addr,
+			NULL,
+			print_header_info);
+#endif
 		if (ret)
 			return -1;
 		if (pbi->need_resync) {
@@ -2717,11 +2991,21 @@
 			 *	pr_info("*%d-bits refresh_frame read:0x%x\n",
 			 *	REF_FRAMES, pbi->refresh_frame_flags);
 			 */
+#ifdef VP9_10B_MMU_DW
 			ret = setup_frame_size(pbi,
 				cm,
 				params,
 				pbi->frame_mmu_map_addr,
+				pbi->frame_mmu_dw_map_addr,
 				print_header_info);
+#else
+			ret = setup_frame_size(pbi,
+				cm,
+				params,
+				pbi->frame_mmu_map_addr,
+				NULL,
+				print_header_info);
+#endif
 			if (ret)
 				return -1;
 			if (pbi->need_resync) {
@@ -2767,13 +3051,23 @@
 				 */
 
 			}
-
+#ifdef VP9_10B_MMU_DW
 			ret = setup_frame_size_with_refs(
 				pbi,
 				cm,
 				params,
 				pbi->frame_mmu_map_addr,
+				pbi->frame_mmu_dw_map_addr,
 				print_header_info);
+#else
+			ret = setup_frame_size_with_refs(
+				pbi,
+				cm,
+				params,
+				pbi->frame_mmu_map_addr,
+				NULL,
+				print_header_info);
+#endif
 			if (ret)
 				return -1;
 			for (i = 0; i < REFS_PER_FRAME; ++i) {
@@ -2841,11 +3135,11 @@
 		struct vdec_s *vdec = hw_to_vdec(pbi);
 
 		/* create fence for each buffers. */
-		ret = vdec_timeline_create_fence(&vdec->sync);
+		ret = vdec_timeline_create_fence(vdec->sync);
 		if (ret < 0)
 			return ret;
 
-		pic->fence		= vdec->sync.fence;
+		pic->fence		= vdec->sync->fence;
 		pic->bit_depth		= cm->bit_depth;
 		pic->slice_type		= cm->frame_type;
 		pic->stream_offset	= pbi->pre_stream_offset;
@@ -3007,6 +3301,9 @@
 	}
 	cm->last_width = cm->width;
 	cm->last_height = cm->height;
+	pbi->last_width = cm->width;
+	pbi->last_height = cm->height;
+
 	if (cm->show_frame)
 		cm->current_video_frame++;
 
@@ -3015,8 +3312,32 @@
 		sd.stream_offset = pbi->pre_stream_offset;
 
 		if (pbi->enable_fence) {
+			int i, j, used_size, ret;
+			int signed_count = 0;
+			struct vframe_s *signed_fence[VF_POOL_SIZE];
 			/* notify signal to wake up wq of fence. */
-			vdec_timeline_increase(&vdec->sync, 1);
+			vdec_timeline_increase(vdec->sync, 1);
+			mutex_lock(&pbi->fence_mutex);
+			used_size = pbi->fence_vf_s.used_size;
+			if (used_size) {
+				for (i = 0, j = 0; i < VF_POOL_SIZE && j < used_size; i++) {
+					if (pbi->fence_vf_s.fence_vf[i] != NULL) {
+						ret = dma_fence_get_status(pbi->fence_vf_s.fence_vf[i]->fence);
+						if (ret == 1) {
+							signed_fence[signed_count] = pbi->fence_vf_s.fence_vf[i];
+							pbi->fence_vf_s.fence_vf[i] = NULL;
+							pbi->fence_vf_s.used_size--;
+							signed_count++;
+						}
+						j++;
+					}
+				}
+			}
+			mutex_unlock(&pbi->fence_mutex);
+			if (signed_count != 0) {
+				for (i = 0; i < signed_count; i++)
+					vvp9_vf_put(signed_fence[i], vdec);
+			}
 		} else {
 			prepare_display_buf(pbi, &sd);
 		}
@@ -3045,6 +3366,9 @@
 #define HEVC_CM_HEADER_LENGTH                      0x3629
 #define HEVC_CM_HEADER_OFFSET                      0x362b
 
+#define HEVC_CM_BODY_LENGTH2                       0x3663
+#define HEVC_CM_HEADER_OFFSET2                     0x3664
+#define HEVC_CM_HEADER_LENGTH2                     0x3665
 #define LOSLESS_COMPRESS_MODE
 
 /*#define DECOMP_HEADR_SURGENT*/
@@ -3066,7 +3390,15 @@
 static u32 pop_shorts;
 static u32 dbg_cmd;
 static u32 dbg_skip_decode_index;
-static u32 endian = 0xff0;
+
+/*
+ * 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 */
@@ -3076,18 +3408,10 @@
 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 vp9_max_pic_w = 4096;
-static u32 vp9_max_pic_h = 2304;
-
+static u32 vp9_max_pic_w;
+static u32 vp9_max_pic_h;
 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
+
 static u32 buf_alloc_depth = 10;
 static u32 buf_alloc_size;
 /*
@@ -3233,7 +3557,10 @@
 #define DW_VBH_BUF_SIZE_8K (VBH_BUF_SIZE_8K * 2)
 #define DW_VBH_BUF_SIZE(bufspec) (bufspec->mmu_vbh_dw.buf_size / 4)
 
-#define WORK_BUF_SPEC_NUM 3
+/* 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 amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = {
 	{
 		/* 8M bytes */
@@ -3243,6 +3570,292 @@
 			/* 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 = {
+			/* DBLK -> Max 256(4096/16) LCU,
+			 *each para 1024bytes(total:0x40000),
+			 *data 1024bytes(total:0x40000)
+			 */
+			.buf_size = 0x80000,
+		},
+		.dblk_data = {
+			.buf_size = 0x80000,
+		},
+		.seg_map = {
+		/*4096x2304/64/64 *24 = 0xd800 Bytes*/
+			.buf_size = 0xd800,
+		},
+		.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
+		.mpred_above = {
+			.buf_size = 0x10000, /* 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,
+		},
+		.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 1024bytes(total:0x40000),
+			 *data 1024bytes(total:0x40000)
+			 */
+			.buf_size = 0x80000,
+		},
+		.dblk_data = {
+			.buf_size = 0x80000,
+		},
+		.seg_map = {
+			/*4096x2304/64/64 *24 = 0xd800 Bytes*/
+			.buf_size = 0xd800,
+		},
+		.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
+		.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,
+		},
+		.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 = {
+			// DBLK -> Max 256(4096/16) LCU, each para 1024bytes(total:0x40000), data 1024bytes(total:0x40000)
+			.buf_size = 0x80000*2,
+		},
+		.dblk_data = {
+			.buf_size = 0x80000*2,
+		},
+		.seg_map = {
+			/*4096x2304/64/64 *24 = 0xd800 Bytes*/
+			.buf_size = 0xd800*4,
+		},
+		.mmu_vbh = {
+			.buf_size = 0x5000*2, //2*16*(more than 2304)/4, 4K
+		},
+#if 0
+		.cm_header = {
+			//.buf_size = MMU_COMPRESS_HEADER_SIZE*8, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
+			.buf_size = MMU_COMPRESS_HEADER_SIZE*16, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
+		},
+#endif
+		.mpred_above = {
+			.buf_size = 0x10000*2, /* 2 * size of hevc*/
+		},
+#ifdef MV_USE_FIXED_BUF
+		.mpred_mv = {
+			//4k2k , 0x100000 per buffer */
+			/* 4096x2304 , 0x120000 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 = {
@@ -3321,6 +3934,16 @@
 			/* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */
 		},
 #endif
+#ifdef VP9_10B_MMU_DW
+		.mmu_vbh_dw = {
+			.buf_size = DW_VBH_BUF_SIZE_1080P, //VBH_BUF_SIZE * VBH_BUF_COUNT, //2*16*(more than 2304)/4, 4K
+		},
+#if 0
+		.cm_header_dw = {
+			.buf_size = MMU_COMPRESS_HEADER_SIZE_DW * 16, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
+		},
+#endif
+#endif
 		.mpred_above = {
 			.buf_size = 0x2200, //0x21c0, /* 2 * size of hevc*/
 		},
@@ -3421,6 +4044,16 @@
 			/* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */
 		},
 #endif
+#ifdef VP9_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
+		},
+#if 0
+		.cm_header_dw = {
+			.buf_size = MMU_COMPRESS_HEADER_SIZE_DW * 16, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
+		},
+#endif
+#endif
 		.mpred_above = {
 			.buf_size = 0x4800, /* 2 * size of hevc*/
 		},
@@ -3504,6 +4137,16 @@
 			.buf_size = MMU_COMPRESS_HEADER_SIZE*16, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
 		},
 #endif
+#ifdef VP9_10B_MMU_DW
+		.mmu_vbh_dw = {
+			.buf_size = DW_VBH_BUF_SIZE_8K, //VBH_BUF_SIZE * VBH_BUF_COUNT, //2*16*(more than 2304)/4, 4K
+		},
+#if 0
+		.cm_header_dw = {
+			.buf_size = MMU_COMPRESS_HEADER_SIZE_DW * 16, // 0x44000 = ((1088*2*1024*4)/32/4)*(32/8)
+		},
+#endif
+#endif
 		.mpred_above = {
 			.buf_size = 0x9000,
 		},
@@ -3525,7 +4168,7 @@
 
 
 /*Losless compression body buffer size 4K per 64x32 (jt)*/
-int  compute_losless_comp_body_size(int width, int height,
+static int compute_losless_comp_body_size(int width, int height,
 				uint8_t is_bit_depth_10)
 {
 	int     width_x64;
@@ -3546,7 +4189,7 @@
 }
 
 /* Losless compression header buffer size 32bytes per 128x64 (jt)*/
-static  int  compute_losless_comp_header_size(int width, int height)
+static int compute_losless_comp_header_size(int width, int height)
 {
 	int     width_x128;
 	int     height_x64;
@@ -3571,66 +4214,69 @@
 {
 	void *mem_start_virt;
 
-	buf_spec->ipp.buf_start = buf_spec->start_adr;
+	buf_spec->ipp.buf_start =
+		WORKBUF_ALIGN(buf_spec->start_adr);
 	buf_spec->sao_abv.buf_start =
-		buf_spec->ipp.buf_start + buf_spec->ipp.buf_size;
-
+		WORKBUF_ALIGN(buf_spec->ipp.buf_start + buf_spec->ipp.buf_size);
 	buf_spec->sao_vb.buf_start =
-		buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size;
+		WORKBUF_ALIGN(buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size);
 	buf_spec->short_term_rps.buf_start =
-		buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size;
+		WORKBUF_ALIGN(buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size);
 	buf_spec->vps.buf_start =
-		buf_spec->short_term_rps.buf_start +
-		buf_spec->short_term_rps.buf_size;
+		WORKBUF_ALIGN(buf_spec->short_term_rps.buf_start + buf_spec->short_term_rps.buf_size);
 	buf_spec->sps.buf_start =
-		buf_spec->vps.buf_start + buf_spec->vps.buf_size;
+		WORKBUF_ALIGN(buf_spec->vps.buf_start + buf_spec->vps.buf_size);
 	buf_spec->pps.buf_start =
-		buf_spec->sps.buf_start + buf_spec->sps.buf_size;
+		WORKBUF_ALIGN(buf_spec->sps.buf_start + buf_spec->sps.buf_size);
 	buf_spec->sao_up.buf_start =
-		buf_spec->pps.buf_start + buf_spec->pps.buf_size;
+		WORKBUF_ALIGN(buf_spec->pps.buf_start + buf_spec->pps.buf_size);
 	buf_spec->swap_buf.buf_start =
-		buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size;
+		WORKBUF_ALIGN(buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size);
 	buf_spec->swap_buf2.buf_start =
-		buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size;
+		WORKBUF_ALIGN(buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size);
 	buf_spec->scalelut.buf_start =
-		buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size;
+		WORKBUF_ALIGN(buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size);
 	buf_spec->dblk_para.buf_start =
-		buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size;
+		WORKBUF_ALIGN(buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size);
 	buf_spec->dblk_data.buf_start =
-		buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size;
+		WORKBUF_ALIGN(buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size);
 	buf_spec->seg_map.buf_start =
-	buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size;
+		WORKBUF_ALIGN(buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size);
 	if (pbi == NULL || pbi->mmu_enable) {
 		buf_spec->mmu_vbh.buf_start  =
-			buf_spec->seg_map.buf_start +
-			buf_spec->seg_map.buf_size;
+			WORKBUF_ALIGN(buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size);
+#ifdef VP9_10B_MMU_DW
+		if (pbi == NULL || pbi->dw_mmu_enable) {
+			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);
+		}
+#else
 		buf_spec->mpred_above.buf_start =
-			buf_spec->mmu_vbh.buf_start +
-			buf_spec->mmu_vbh.buf_size;
+			WORKBUF_ALIGN(buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size);
+#endif
 	} else {
 		buf_spec->mpred_above.buf_start =
-		buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size;
+			WORKBUF_ALIGN(buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size);
 	}
 #ifdef MV_USE_FIXED_BUF
 	buf_spec->mpred_mv.buf_start =
-		buf_spec->mpred_above.buf_start +
-		buf_spec->mpred_above.buf_size;
+		WORKBUF_ALIGN(buf_spec->mpred_above.buf_start + buf_spec->mpred_above.buf_size);
 
 	buf_spec->rpm.buf_start =
-		buf_spec->mpred_mv.buf_start +
-		buf_spec->mpred_mv.buf_size;
+		WORKBUF_ALIGN(buf_spec->mpred_mv.buf_start + buf_spec->mpred_mv.buf_size);
 #else
 	buf_spec->rpm.buf_start =
-		buf_spec->mpred_above.buf_start +
-		buf_spec->mpred_above.buf_size;
-
+		WORKBUF_ALIGN(buf_spec->mpred_above.buf_start + buf_spec->mpred_above.buf_size);
 #endif
 	buf_spec->lmem.buf_start =
-		buf_spec->rpm.buf_start +
-		buf_spec->rpm.buf_size;
+		WORKBUF_ALIGN(buf_spec->rpm.buf_start + buf_spec->rpm.buf_size);
 	buf_spec->end_adr =
-		buf_spec->lmem.buf_start +
-		buf_spec->lmem.buf_size;
+		WORKBUF_ALIGN(buf_spec->lmem.buf_start + buf_spec->lmem.buf_size);
 
 	if (!pbi)
 		return;
@@ -3701,6 +4347,16 @@
 	if (pbi->mmu_enable) {
 		pr_info("mmu_vbh.buf_start     :%x\n",
 			buf_spec->mmu_vbh.buf_start);
+#ifdef VP9_10B_MMU_DW
+		if (pbi->dw_mmu_enable) {
+			pr_info("mmu_vbh_dw.buf_start     :%x",
+				buf_spec->mmu_vbh_dw.buf_start);
+#if 0
+			pr_info("cm_header_dw.buf_start     :%x",
+				buf_spec->mmu_vbh_dw.buf_start);
+#endif
+		}
+#endif
 	}
 		pr_info("mpred_above.buf_start     :%x\n",
 			   buf_spec->mpred_above.buf_start);
@@ -4898,71 +5554,25 @@
 
 }
 
-static bool v4l_is_there_vframe_bound(struct VP9Decoder_s *pbi)
-{
-	int i;
-	struct VP9_Common_s *const cm = &pbi->common;
-	struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs;
-
-	for (i = 0; i < pbi->used_buf_num; ++i) {
-		if (frame_bufs[i].buf.vframe_bound)
-			return true;
-	}
-
-	return false;
-}
-
-static void v4l_mmu_buffer_release(struct VP9Decoder_s *pbi)
-{
-	struct VP9_Common_s *const cm = &pbi->common;
-	struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs;
-	int i;
-
-	/* release workspace */
-	if (pbi->bmmu_box)
-		decoder_bmmu_box_free_idx(pbi->bmmu_box,
-			WORK_SPACE_BUF_ID);
-	/*
-	 * it's only when vframe get back to driver, right now we can be sure
-	 * that vframe and fd are related. if the playback exits, the capture
-	 * requires the upper app to release when the fd is closed, and others
-	 * buffers drivers are released by driver.
-	 */
-	for (i = 0; i < pbi->used_buf_num; ++i) {
-		if (!frame_bufs[i].buf.vframe_bound) {
-			if (pbi->bmmu_box)
-				decoder_bmmu_box_free_idx(pbi->bmmu_box,
-					HEADER_BUFFER_IDX(i));
-			if (pbi->mmu_box)
-				decoder_mmu_box_free_idx(pbi->mmu_box, i);
-
-			vp9_print(pbi, PRINT_FLAG_V4L_DETAIL,
-				"%s free buffer[%d], bmmu_box: %p, mmu_box: %p\n",
-				__func__, i, pbi->bmmu_box, pbi->mmu_box);
-		}
-	}
-}
-
 static void uninit_mmu_buffers(struct VP9Decoder_s *pbi)
 {
 #ifndef MV_USE_FIXED_BUF
 	dealloc_mv_bufs(pbi);
 #endif
-	if (pbi->is_used_v4l &&
-		v4l_is_there_vframe_bound(pbi)) {
-		if (get_double_write_mode(pbi) != 0x10) {
-			v4l_mmu_buffer_release(pbi);
-			return;
-		}
-	}
-
-	if (pbi->mmu_box)
+	if (pbi->mmu_box) {
 		decoder_mmu_box_free(pbi->mmu_box);
-	pbi->mmu_box = NULL;
-
-	if (pbi->bmmu_box)
+		pbi->mmu_box = NULL;
+	}
+#ifdef VP9_10B_MMU_DW
+	if (pbi->mmu_box_dw) {
+		decoder_mmu_box_free(pbi->mmu_box_dw);
+		pbi->mmu_box_dw = NULL;
+	}
+#endif
+	if (pbi->bmmu_box) {
 		decoder_bmmu_box_free(pbi->bmmu_box);
-	pbi->bmmu_box = NULL;
+		pbi->bmmu_box = NULL;
+	}
 }
 
 static int calc_luc_quantity(u32 w, u32 h)
@@ -4978,6 +5588,22 @@
 	return pic_width_lcu * pic_height_lcu;
 }
 
+/* return in MB */
+static int vp9_max_mmu_buf_size(int max_w, int max_h)
+{
+	int buf_size = 48;
+
+	if ((max_w * max_h > 1280*736) &&
+		(max_w * max_h <= 1920*1088)) {
+		buf_size = 12;
+	} else if ((max_w * max_h > 0) &&
+		(max_w * max_h <= 1280*736)) {
+		buf_size = 4;
+	}
+
+	return buf_size;
+}
+
 static int v4l_alloc_and_config_pic(struct VP9Decoder_s *pbi,
 	struct PIC_BUFFER_CONFIG_s *pic)
 {
@@ -4990,21 +5616,25 @@
 		pbi->work_space_buf->mpred_mv.buf_size;
 	int mv_size = cal_mv_buf_size(pbi, pbi->frame_width, pbi->frame_height);
 #endif
+	struct aml_vcodec_ctx * ctx = (struct aml_vcodec_ctx *)pbi->v4l2_ctx;
 	struct vdec_v4l2_buffer *fb = NULL;
 
 	if (i < 0)
 		return ret;
 
-	ret = vdec_v4l_get_buffer(pbi->v4l2_ctx, &fb);
+	ret = ctx->fb_ops.alloc(&ctx->fb_ops, pbi->fb_token, &fb, AML_FB_REQ_DEC);
 	if (ret < 0) {
 		vp9_print(pbi, 0, "[%d] VP9 get buffer fail.\n",
 			((struct aml_vcodec_ctx *) (pbi->v4l2_ctx))->id);
 		return ret;
 	}
 
+	fb->status	= FB_ST_DECODER;
+
 	if (pbi->mmu_enable) {
-		pbi->m_BUF[i].header_addr = decoder_bmmu_box_get_phy_addr(
-			pbi->bmmu_box, HEADER_BUFFER_IDX(i));
+		struct internal_comp_buf *ibuf = v4lfb_to_icomp_buf(pbi, fb);
+
+		pbi->m_BUF[i].header_addr = ibuf->header_addr;
 		if (debug & VP9_DEBUG_BUFMGR_MORE) {
 			pr_info("MMU header_adr %d: %ld\n",
 				i, pbi->m_BUF[i].header_addr);
@@ -5025,6 +5655,8 @@
 		fb->m.mem[0].bytes_used = fb->m.mem[0].size;
 		pic->dw_y_adr = pbi->m_BUF[i].start_adr;
 		pic->dw_u_v_adr = pic->dw_y_adr + pbi->m_BUF[i].luma_size;
+		pic->luma_size = fb->m.mem[0].offset;
+		pic->chroma_size = fb->m.mem[0].size - fb->m.mem[0].offset;
 	} else if (fb->num_planes == 2) {
 		pbi->m_BUF[i].start_adr = fb->m.mem[0].addr;
 		pbi->m_BUF[i].size = fb->m.mem[0].size;
@@ -5034,6 +5666,8 @@
 		fb->m.mem[1].bytes_used = fb->m.mem[1].size;
 		pic->dw_y_adr = pbi->m_BUF[i].start_adr;
 		pic->dw_u_v_adr = pbi->m_BUF[i].chroma_addr;
+		pic->luma_size = fb->m.mem[0].size;
+		pic->chroma_size = fb->m.mem[1].size;
 	}
 
 	/* config frame buffer */
@@ -5110,14 +5744,15 @@
 	int mc_buffer_size_u_v = 0;
 	int mc_buffer_size_u_v_h = 0;
 	int dw_mode = get_double_write_mode_init(pbi);
+	struct vdec_s *vdec = hw_to_vdec(pbi);
 
 	pbi->lcu_total = lcu_total;
 
-	if (dw_mode) {
+	if (dw_mode && (dw_mode & 0x20) == 0) {
 		int pic_width_dw = pic_width /
-			get_double_write_ratio(pbi, dw_mode);
+			get_double_write_ratio(dw_mode & 0xf);
 		int pic_height_dw = pic_height /
-			get_double_write_ratio(pbi, dw_mode);
+			get_double_write_ratio(dw_mode & 0xf);
 
 		int pic_width_64_dw = (pic_width_dw + 63) & (~0x3f);
 		int pic_height_32_dw = (pic_height_dw + 31) & (~0x1f);
@@ -5148,8 +5783,19 @@
 			pr_info("MMU header_adr %d: %ld\n",
 				pic_config->index, pic_config->header_adr);
 		}
-	}
+#ifdef VP9_10B_MMU_DW
+		if (pbi->dw_mmu_enable) {
+			pic_config->header_dw_adr = pic_config->header_adr +
+				vvp9_mmu_compress_header_size(pbi->init_pic_w, pbi->init_pic_h);
 
+			if (debug & VP9_DEBUG_BUFMGR_MORE) {
+				pr_info("MMU header_dw_adr %d: %ld size 0x%x\n",
+					pic_config->index, pic_config->header_dw_adr,
+					vvp9_mmu_compress_header_size(pbi->init_pic_w, pbi->init_pic_h));
+			}
+		}
+#endif
+	}
 	i = pic_config->index;
 #ifdef MV_USE_FIXED_BUF
 	if ((pbi->work_space_buf->mpred_mv.buf_start +
@@ -5171,6 +5817,13 @@
 				return ret;
 			}
 
+			if (pbi->enable_fence) {
+				//mm->fence_ref_release = vdec_fence_buffer_count_decrease;
+				vdec_fence_buffer_count_increase((ulong)vdec->sync);
+				INIT_LIST_HEAD(&vdec->sync->release_callback[VF_BUFFER_IDX(i)].node);
+				decoder_bmmu_box_add_callback_func(pbi->bmmu_box, VF_BUFFER_IDX(i), (void *)&vdec->sync->release_callback[VF_BUFFER_IDX(i)]);
+			}
+
 			if (pic_config->cma_alloc_addr)
 				y_adr = pic_config->cma_alloc_addr;
 			else {
@@ -5202,7 +5855,7 @@
 					(pic_config->index << 1);
 				pic_config->mc_canvas_u_v =
 					(pic_config->index << 1) + 1;
-			} else if (dw_mode) {
+			} else if (dw_mode && ((dw_mode & 0x20) == 0)) {
 				pic_config->dw_y_adr = y_adr;
 				pic_config->dw_u_v_adr = pic_config->dw_y_adr +
 				((mc_buffer_size_u_v_h << 16) << 1);
@@ -5237,24 +5890,6 @@
 	return ret;
 }
 
-static int vvp9_mmu_compress_header_size(struct VP9Decoder_s *pbi)
-{
-	if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
-		IS_8K_SIZE(pbi->max_pic_w, pbi->max_pic_h))
-		return (MMU_COMPRESS_8K_HEADER_SIZE);
-
-	return (MMU_COMPRESS_HEADER_SIZE);
-}
-
-/*#define FRAME_MMU_MAP_SIZE  (MAX_FRAME_4K_NUM * 4)*/
-static int vvp9_frame_mmu_map_size(struct VP9Decoder_s *pbi)
-{
-	if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
-		IS_8K_SIZE(pbi->max_pic_w, pbi->max_pic_h))
-		return (MAX_FRAME_8K_NUM * 4);
-
-	return (MAX_FRAME_4K_NUM * 4);
-}
 
 static void init_pic_list(struct VP9Decoder_s *pbi)
 {
@@ -5264,8 +5899,13 @@
 	u32 header_size;
 	struct vdec_s *vdec = hw_to_vdec(pbi);
 
-	if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) {
-		header_size = vvp9_mmu_compress_header_size(pbi);
+	if (!pbi->is_used_v4l && pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) {
+		header_size = vvp9_mmu_compress_header_size(
+			pbi->max_pic_w, pbi->max_pic_h);
+#ifdef VP9_10B_MMU_DW
+		if (pbi->dw_mmu_enable)
+			header_size <<= 1;
+#endif
 		/*alloc VP9 compress header first*/
 		for (i = 0; i < pbi->used_buf_num; i++) {
 			unsigned long buf_addr;
@@ -5279,6 +5919,12 @@
 				pbi->fatal_error |= DECODER_FATAL_ERROR_NO_MEM;
 				return;
 			}
+			if (pbi->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(pbi->bmmu_box, HEADER_BUFFER_IDX(i), (void *)&vdec->sync->release_callback[HEADER_BUFFER_IDX(i)]);
+				//mm->fence_ref_release = vdec_fence_buffer_count_decrease;
+			}
 		}
 	}
 	for (i = 0; i < pbi->used_buf_num; i++) {
@@ -5303,7 +5949,8 @@
 				break;
 			}
 
-			if (pic_config->double_write_mode) {
+			if (pic_config->double_write_mode &&
+			(pic_config->double_write_mode & 0x20) == 0) {
 				set_canvas(pbi, pic_config);
 			}
 		}
@@ -5331,14 +5978,12 @@
 	WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
 		(0x1 << 1) | (0x1 << 2));
 
-
 	for (i = 0; i < pbi->used_buf_num; i++) {
 		pic_config = &cm->buffer_pool->frame_bufs[i].buf;
 		if (pic_config->index < 0)
 			break;
 
 		if (pbi->mmu_enable && ((pic_config->double_write_mode & 0x10) == 0)) {
-
 			WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA,
 				pic_config->header_adr >> 5);
 		} else {
@@ -5372,7 +6017,6 @@
 		WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
 }
 
-
 static void dump_pic_list(struct VP9Decoder_s *pbi)
 {
 	struct VP9_Common_s *const cm = &pbi->common;
@@ -5381,7 +6025,7 @@
 	for (i = 0; i < FRAME_BUFFERS; i++) {
 		pic_config = &cm->buffer_pool->frame_bufs[i].buf;
 		vp9_print(pbi, 0,
-			"Buf(%d) index %d mv_buf_index %d ref_count %d vf_ref %d dec_idx %d slice_type %d w/h %d/%d adr%ld\n",
+			"Buf(%d) index %d mv_buf_index %d ref_count %d vf_ref %d dec_idx %d slice_type %d w/h %d/%d adr: %x\n",
 			i,
 			pic_config->index,
 #ifndef MV_USE_FIXED_BUF
@@ -5452,6 +6096,14 @@
 #else
 	WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
 #endif
+#ifdef VP9_10B_MMU_DW
+	if (pbi->dw_mmu_enable) {
+		/*losless_comp_header_size_dw same as losless_comp_header_size*/
+		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);
+	}
+#endif
 	return 0;
 }
 
@@ -5596,26 +6248,45 @@
 		(mc_buffer_size_u_v + 0xffff) >> 16;/*64k alignment*/
 	struct aml_vcodec_ctx * v4l2_ctx = pbi->v4l2_ctx;
 
-	if (get_double_write_mode(pbi)) {
+	if (get_double_write_mode(pbi) &&
+		(get_double_write_mode(pbi) & 0x20) == 0) {
 		WRITE_VREG(HEVC_SAO_Y_START_ADDR, pic_config->dw_y_adr);
 		WRITE_VREG(HEVC_SAO_C_START_ADDR, pic_config->dw_u_v_adr);
 		WRITE_VREG(HEVC_SAO_Y_WPTR, pic_config->dw_y_adr);
 		WRITE_VREG(HEVC_SAO_C_WPTR, pic_config->dw_u_v_adr);
 	} else {
-		WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff);
-		WRITE_VREG(HEVC_SAO_C_START_ADDR, 0xffffffff);
+		if (!pbi->dw_mmu_enable) {
+			WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff);
+			WRITE_VREG(HEVC_SAO_C_START_ADDR, 0xffffffff);
+		}
 	}
 	if (pbi->mmu_enable)
 		WRITE_VREG(HEVC_CM_HEADER_START_ADDR, pic_config->header_adr);
 
-	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, pic_config->lcu_total);
-	 */
-	WRITE_VREG(HEVC_SAO_Y_LENGTH, data32);
+	if (pbi->is_used_v4l) {
+		WRITE_VREG(HEVC_SAO_Y_LENGTH, pic_config->luma_size);
+		WRITE_VREG(HEVC_SAO_C_LENGTH, pic_config->chroma_size);
+		if (debug & PRINT_FLAG_V4L_DETAIL) {
+			pr_info("[%d] config pic, id: %d, Y:(%x, %d) C:(%x, %d).\n",
+				v4l2_ctx->id, pic_config->index,
+				pic_config->dw_y_adr, pic_config->luma_size,
+				pic_config->dw_u_v_adr, pic_config->chroma_size);
+		}
+	} else {
+#ifdef VP9_10B_MMU_DW
+		if (pbi->dw_mmu_enable) {
+			WRITE_VREG(HEVC_CM_HEADER_START_ADDR2, pic_config->header_dw_adr);
+		}
+#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, pic_config->lcu_total);*/
 
-	data32 = (mc_buffer_size_u_v_h << 16);
-	WRITE_VREG(HEVC_SAO_C_LENGTH, data32);
+		WRITE_VREG(HEVC_SAO_Y_LENGTH, data32);
+
+		data32 = (mc_buffer_size_u_v_h << 16);
+		WRITE_VREG(HEVC_SAO_C_LENGTH, data32);
+	}
 
 #ifdef VP9_10B_NV21
 #ifdef DOS_PROJECT
@@ -5668,17 +6339,21 @@
 #endif
 #else
 	data32 = READ_VREG(HEVC_SAO_CTRL1);
-	data32 &= (~0x3000);
-	data32 |= (pbi->mem_map_mode <<
-			   12);
+	data32 &= (~(3 << 14));
+	data32 |= (2 << 14);	/* line align with 64*/
 
-/*  [13:12] axi_aformat, 0-Linear,
- *				   1-32x32, 2-64x32
- */
+	data32 &= (~0x3000);
+	/* [13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32 */
+	data32 |= (pbi->mem_map_mode << 12);
+
 	data32 &= (~0xff0);
-	/* data32 |= 0x670;  // Big-Endian per 64-bit */
-	data32 |= endian;	/* Big-Endian per 64-bit */
-	data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/
+#ifdef VP9_10B_MMU_DW
+	if (pbi->dw_mmu_enable == 0)
+		data32 |= ((pbi->endian >> 8) & 0xfff);	/* Big-Endian per 64-bit */
+#else
+	data32 |= ((pbi->endian >> 8) & 0xfff);
+#endif
+	data32 &= (~0x3); 		/*[1]:dw_disable [0]:cm_disable*/
 	if (get_double_write_mode(pbi) == 0)
 		data32 |= 0x2; /*disable double write*/
 	else if (get_double_write_mode(pbi) & 0x10)
@@ -5730,24 +6405,29 @@
 		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(pbi) == 2 ||
-			get_double_write_mode(pbi) == 3)
-			data32 |= (0xff<<16);
-		else if (get_double_write_mode(pbi) == 4)
-			data32 |= (0x33<<16);
+		if ((get_double_write_mode(pbi) & 0xf) == 8 ||
+			(get_double_write_mode(pbi) & 0xf) == 9) {
+			data32 |= (0xff << 16);
+			WRITE_VREG(HEVC_SAO_CTRL26, 0xf);
+		} else if ((get_double_write_mode(pbi) & 0xf) == 2 ||
+			(get_double_write_mode(pbi) & 0xf) == 3)
+			data32 |= (0xff << 16);
+		else if ((get_double_write_mode(pbi) & 0xf) == 4)
+			data32 |= (0x33 << 16);
 		WRITE_VREG(HEVC_SAO_CTRL5, data32);
 	}
 
 	data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
 	data32 &= (~0x30);
 	/* [5:4]    -- address_format 00:linear 01:32x32 10:64x32 */
-	data32 |= (pbi->mem_map_mode <<
-			   4);
-	data32 &= (~0xF);
-	data32 |= 0xf;  /* valid only when double write only */
-		/*data32 |= 0x8;*/		/* Big-Endian per 64-bit */
+	data32 |= (pbi->mem_map_mode << 4);
+	data32 &= (~0xf);
+	data32 |= (pbi->endian & 0xf);  /* valid only when double write only */
 
 	/* swap uv */
 	if (pbi->is_used_v4l) {
@@ -5757,7 +6437,8 @@
 		else
 			data32 &= ~(1 << 12); /* NV12 */
 	}
-
+	data32 &= (~(3 << 8));
+	data32 |= (2 << 8);		/* line align with 64 for dw only */
 	/*
 	* [3:0]   little_endian
 	* [5:4]   address_format 00:linear 01:32x32 10:64x32
@@ -5774,7 +6455,7 @@
 static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi, u32 mask)
 {
 	struct BuffInfo_s *buf_spec = pbi->work_space_buf;
-	unsigned int data32;
+	unsigned int data32, data_tmp;
 	int losless_comp_header_size, losless_comp_body_size;
 
 	if (debug && pbi->init_flag == 0)
@@ -5812,29 +6493,32 @@
 
 	}
 
-	if (mask & HW_MASK_BACK) {
+	if ((mask & HW_MASK_BACK) == 0)
+		return;
+
 #ifdef LOSLESS_COMPRESS_MODE
-		losless_comp_header_size =
-			compute_losless_comp_header_size(pbi->init_pic_w,
-			pbi->init_pic_h);
-		losless_comp_body_size =
-			compute_losless_comp_body_size(pbi->init_pic_w,
-			pbi->init_pic_h, buf_alloc_depth == 10);
+	losless_comp_header_size =
+		compute_losless_comp_header_size(pbi->init_pic_w,
+		pbi->init_pic_h);
+	losless_comp_body_size =
+		compute_losless_comp_body_size(pbi->init_pic_w,
+		pbi->init_pic_h, buf_alloc_depth == 10);
 #endif
-		WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE,
-			buf_spec->ipp.buf_start);
-		//WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start);
-		//WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start);
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
-			/* cfg_addr_adp*/
-			WRITE_VREG(HEVC_DBLK_CFGE, buf_spec->dblk_para.buf_start);
-			if (debug & VP9_DEBUG_BUFMGR_MORE)
-				pr_info("Write HEVC_DBLK_CFGE\n");
-		}
-		/* 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(HEVCD_IPP_LINEBUFF_BASE,
+		buf_spec->ipp.buf_start);
+	//WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start);
+	//WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start);
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
+		/* cfg_addr_adp*/
+		WRITE_VREG(HEVC_DBLK_CFGE, buf_spec->dblk_para.buf_start);
+		if (debug & VP9_DEBUG_BUFMGR_MORE)
+			pr_info("Write HEVC_DBLK_CFGE\n");
+	}
+	/* 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);
 
 	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
 		 /*
@@ -5874,6 +6558,7 @@
 	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);
+
 	if (get_double_write_mode(pbi) & 0x10)
 		WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
 #else
@@ -5893,20 +6578,76 @@
 		data32 |= (1<<10);
 		WRITE_VREG(HEVC_SAO_CTRL5, data32);
 	}
+#ifdef VP9_10B_MMU_DW
+	if (pbi->dw_mmu_enable) {
+		data_tmp = READ_VREG(HEVC_SAO_CTRL9);
+		data_tmp |= (1<<10);
+		WRITE_VREG(HEVC_SAO_CTRL9, data_tmp);
 
-		WRITE_VREG(VP9_SEG_MAP_BUFFER, buf_spec->seg_map.buf_start);
+		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));
+
+		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T5D) {
+			if (get_double_write_mode(pbi) & 0x20) {
+				WRITE_VREG(HEVC_DW_VH0_ADDDR,
+					buf_spec->mmu_vbh_dw.buf_start + DW_VBH_BUF_SIZE(buf_spec) * 2);
+				WRITE_VREG(HEVC_DW_VH1_ADDDR,
+					buf_spec->mmu_vbh_dw.buf_start + DW_VBH_BUF_SIZE(buf_spec) * 3);
+			}
+		}
+		data32 = READ_VREG(HEVC_SAO_CTRL5);
+		/* use HEVC_CM_HEADER_START_ADDR */
+		data32 |= (1<<15);
+		WRITE_VREG(HEVC_SAO_CTRL5, data32);
+	}
+#endif
+
+	/* config mpred axi burst threshold */
+	WRITE_VREG(HEVC_MPRED_CTRL3, 0x24122412);
+
+#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
+
+	WRITE_VREG(VP9_SEG_MAP_BUFFER, buf_spec->seg_map.buf_start);
 
 	WRITE_VREG(LMEM_DUMP_ADR, (u32)pbi->lmem_phy_addr);
-		 /**/
-		WRITE_VREG(VP9_PROB_SWAP_BUFFER, pbi->prob_buffer_phy_addr);
-		WRITE_VREG(VP9_COUNT_SWAP_BUFFER, pbi->count_buffer_phy_addr);
-		if (pbi->mmu_enable) {
-			if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
-				WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, pbi->frame_mmu_map_phy_addr);
-			else
-				WRITE_VREG(VP9_MMU_MAP_BUFFER, pbi->frame_mmu_map_phy_addr);
-		}
+
+	WRITE_VREG(VP9_PROB_SWAP_BUFFER, pbi->prob_buffer_phy_addr);
+	WRITE_VREG(VP9_COUNT_SWAP_BUFFER, pbi->count_buffer_phy_addr);
+	if (pbi->mmu_enable) {
+		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
+			WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, pbi->frame_mmu_map_phy_addr);
+		else
+			WRITE_VREG(VP9_MMU_MAP_BUFFER, pbi->frame_mmu_map_phy_addr);
 	}
+#ifdef VP9_10B_MMU_DW
+	if (pbi->dw_mmu_enable) {
+		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T5D) {
+			WRITE_VREG(HEVC_SAO_MMU_DMA_CTRL2, pbi->frame_mmu_dw_map_phy_addr);
+			//WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR2, pbi->frame_mmu_dw_map_phy_addr);
+		} else {
+			WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR2, pbi->frame_mmu_dw_map_phy_addr);
+		}
+		WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0);
+		WRITE_VREG(HEVC_SAO_C_START_ADDR, 0);
+#ifdef VP9_10B_HED_FB
+		WRITE_VREG(HEVC_ASSIST_FB_MMU_MAP_ADDR2, FB_FRAME_MMU_MAP_ADDR);
+	#ifdef VP9_10B_HED_SAME_FB
+		WRITE_VREG(HEVC_ASSIST_FBD_MMU_MAP_ADDR2, FB_FRAME_MMU_MAP_ADDR);
+	#endif
+#endif
+	}
+#endif
 }
 
 
@@ -6277,10 +7018,13 @@
 	if (mask & HW_MASK_BACK) {
 		/*Initial IQIT_SCALELUT memory
 		-- just to avoid X in simulation*/
-
-		WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);/*cfg_p_addr*/
-		for (i = 0; i < 1024; i++)
-			WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0);
+		if (is_rdma_enable())
+			rdma_back_end_work(pbi->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);
+		}
 	}
 
 	if (mask & HW_MASK_FRONT) {
@@ -6668,21 +7412,30 @@
 				pbi->lmem_phy_addr);
 		pbi->lmem_addr = NULL;
 	}
-	if (pbi->prob_buffer_addr) {
-		if (pbi->prob_buffer_phy_addr)
-			dma_free_coherent(amports_get_dma_device(),
-				PROB_BUF_SIZE, pbi->prob_buffer_addr,
-				pbi->prob_buffer_phy_addr);
-
+	if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) &&
+		(vdec_secure(hw_to_vdec(pbi)))) {
+		tee_vp9_prob_free((u32)pbi->prob_buffer_phy_addr);
+		pbi->prob_buffer_phy_addr = 0;
+		pbi->count_buffer_phy_addr = 0;
 		pbi->prob_buffer_addr = NULL;
-	}
-	if (pbi->count_buffer_addr) {
-		if (pbi->count_buffer_phy_addr)
-			dma_free_coherent(amports_get_dma_device(),
-				COUNT_BUF_SIZE, pbi->count_buffer_addr,
-				pbi->count_buffer_phy_addr);
-
 		pbi->count_buffer_addr = NULL;
+	} else {
+		if (pbi->prob_buffer_addr) {
+			if (pbi->prob_buffer_phy_addr)
+				dma_free_coherent(amports_get_dma_device(),
+					PROB_BUF_SIZE, pbi->prob_buffer_addr,
+					pbi->prob_buffer_phy_addr);
+
+			pbi->prob_buffer_addr = NULL;
+		}
+		if (pbi->count_buffer_addr) {
+			if (pbi->count_buffer_phy_addr)
+				dma_free_coherent(amports_get_dma_device(),
+					COUNT_BUF_SIZE, pbi->count_buffer_addr,
+					pbi->count_buffer_phy_addr);
+
+			pbi->count_buffer_addr = NULL;
+		}
 	}
 	if (pbi->mmu_enable) {
 		u32 mmu_map_size = vvp9_frame_mmu_map_size(pbi);
@@ -6695,6 +7448,21 @@
 			pbi->frame_mmu_map_addr = NULL;
 		}
 	}
+
+#ifdef VP9_10B_MMU_DW
+	if (pbi->dw_mmu_enable) {
+		u32 dw_mmu_map_size = vvp9_frame_mmu_map_size(pbi);
+		if (pbi->frame_mmu_dw_map_addr) {
+			if (pbi->frame_mmu_dw_map_phy_addr)
+				dma_free_coherent(amports_get_dma_device(),
+					dw_mmu_map_size,
+					pbi->frame_mmu_dw_map_addr,
+					pbi->frame_mmu_dw_map_phy_addr);
+			pbi->frame_mmu_dw_map_addr = NULL;
+		}
+	}
+#endif
+
 #ifdef SUPPORT_FB_DECODING
 	if (pbi->stage_mmu_map_addr) {
 		if (pbi->stage_mmu_map_phy_addr)
@@ -6731,58 +7499,41 @@
 		memcpy(cur_buf_info, &amvvp9_workbuff_spec[force_bufspec & 0xf],
 		sizeof(struct BuffInfo_s));
 		pr_info("force buffer spec %d\n", force_bufspec & 0xf);
-	} else if (vdec_is_support_4k()) {
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
-			memcpy(cur_buf_info, &amvvp9_workbuff_spec[2],	/* 8k */
-			sizeof(struct BuffInfo_s));
-		} else
-			memcpy(cur_buf_info, &amvvp9_workbuff_spec[1],	/* 4k */
-			sizeof(struct BuffInfo_s));
-	} else
-		memcpy(cur_buf_info, &amvvp9_workbuff_spec[0],/* 1080p */
-		sizeof(struct BuffInfo_s));
+	} 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, &amvvp9_workbuff_spec[2],	/* 8k */
+					sizeof(struct BuffInfo_s));
+				} else
+					memcpy(cur_buf_info, &amvvp9_workbuff_spec[1],	/* 4k */
+					sizeof(struct BuffInfo_s));
+			} else
+				memcpy(cur_buf_info, &amvvp9_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, &amvvp9_workbuff_spec[5],	/* 8k */
+				sizeof(struct BuffInfo_s));
+			} else
+				memcpy(cur_buf_info, &amvvp9_workbuff_spec[3],/* 1080p */
+				sizeof(struct BuffInfo_s));
+		}
+	}
 
 	cur_buf_info->start_adr = pbi->buf_start;
 	if (!pbi->mmu_enable)
 		pbi->mc_buf_spec.buf_end = pbi->buf_start + pbi->buf_size;
-
-#else
-/*! MULTI_INSTANCE_SUPPORT*/
-	if (vdec_is_support_4k()) {
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)
-			cur_buf_info = &amvvp9_workbuff_spec[2];/* 8k work space */
-		else
-			cur_buf_info = &amvvp9_workbuff_spec[1];/* 4k2k work space */
-	} else
-		cur_buf_info = &amvvp9_workbuff_spec[0];/* 1080p work space */
-
 #endif
 
 	init_buff_spec(pbi, cur_buf_info);
 	vp9_bufmgr_init(pbi, cur_buf_info, NULL);
 
-	if (!vdec_is_support_4k()
-		&& (buf_alloc_width > 1920 &&  buf_alloc_height > 1088)) {
-		buf_alloc_width = 1920;
-		buf_alloc_height = 1088;
-		if (pbi->max_pic_w > 1920 && pbi->max_pic_h > 1088) {
-			pbi->max_pic_w = 1920;
-			pbi->max_pic_h = 1088;
-		}
-	} else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
-		buf_alloc_width = 8192;
-		buf_alloc_height = 4608;
-	}
-	pbi->init_pic_w = pbi->max_pic_w ? pbi->max_pic_w :
-		(buf_alloc_width ? buf_alloc_width :
-		(pbi->vvp9_amstream_dec_info.width ?
-		pbi->vvp9_amstream_dec_info.width :
-		pbi->work_space_buf->max_width));
-	pbi->init_pic_h = pbi->max_pic_h ? pbi->max_pic_h :
-		(buf_alloc_height ? buf_alloc_height :
-		(pbi->vvp9_amstream_dec_info.height ?
-		pbi->vvp9_amstream_dec_info.height :
-		pbi->work_space_buf->max_height));
+	/* vp9_max_pic_w/h for debug */
+	pbi->init_pic_w = (vp9_max_pic_w) ? vp9_max_pic_w:
+		((pbi->max_pic_w) ? pbi->max_pic_w : pbi->work_space_buf->max_width);
+	pbi->init_pic_h = (vp9_max_pic_h) ? vp9_max_pic_h:
+		((pbi->max_pic_h) ? pbi->max_pic_h : pbi->work_space_buf->max_height);
 
 	/* video is not support unaligned with 64 in tl1
 	** vdec canvas mode will be linear when dump yuv is set
@@ -6801,9 +7552,11 @@
 	}
 
 #ifndef MV_USE_FIXED_BUF
-	if (init_mv_buf_list(pbi) < 0) {
-		pr_err("%s: init_mv_buf_list fail\n", __func__);
-		return -1;
+	if (!pbi->is_used_v4l) {
+		if (init_mv_buf_list(pbi) < 0) {
+			pr_err("%s: init_mv_buf_list fail\n", __func__);
+			return -1;
+		}
 	}
 #endif
 	if (pbi->save_buffer_mode)
@@ -6842,24 +7595,38 @@
 		pr_err("%s: failed to alloc lmem buffer\n", __func__);
 		return -1;
 	}
-		pbi->lmem_ptr = pbi->lmem_addr;
+	pbi->lmem_ptr = pbi->lmem_addr;
 
-	pbi->prob_buffer_addr = dma_alloc_coherent(amports_get_dma_device(),
-				PROB_BUF_SIZE,
-				&pbi->prob_buffer_phy_addr, GFP_KERNEL);
-	if (pbi->prob_buffer_addr == NULL) {
-		pr_err("%s: failed to alloc prob_buffer\n", __func__);
-		return -1;
+	if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) &&
+		(vdec_secure(hw_to_vdec(pbi)))) {
+		u32 prob_addr, id;
+		id = tee_vp9_prob_malloc(&prob_addr);
+		if (prob_addr <= 0)
+			pr_err("%s, tee[%d] malloc prob buf failed\n", __func__, id);
+		else {
+			pbi->prob_buffer_phy_addr = prob_addr;
+			pbi->count_buffer_phy_addr = pbi->prob_buffer_phy_addr + PROB_BUF_SIZE;
+		}
+		pbi->prob_buffer_addr = NULL;
+		pbi->count_buffer_addr = NULL;
+	} else {
+		pbi->prob_buffer_addr = dma_alloc_coherent(amports_get_dma_device(),
+					PROB_BUF_SIZE,
+					&pbi->prob_buffer_phy_addr, GFP_KERNEL);
+		if (pbi->prob_buffer_addr == NULL) {
+			pr_err("%s: failed to alloc prob_buffer\n", __func__);
+			return -1;
+		}
+		memset(pbi->prob_buffer_addr, 0, PROB_BUF_SIZE);
+		pbi->count_buffer_addr = dma_alloc_coherent(amports_get_dma_device(),
+					COUNT_BUF_SIZE,
+					&pbi->count_buffer_phy_addr, GFP_KERNEL);
+		if (pbi->count_buffer_addr == NULL) {
+			pr_err("%s: failed to alloc count_buffer\n", __func__);
+			return -1;
+		}
+		memset(pbi->count_buffer_addr, 0, COUNT_BUF_SIZE);
 	}
-	memset(pbi->prob_buffer_addr, 0, PROB_BUF_SIZE);
-	pbi->count_buffer_addr = dma_alloc_coherent(amports_get_dma_device(),
-				COUNT_BUF_SIZE,
-				&pbi->count_buffer_phy_addr, GFP_KERNEL);
-	if (pbi->count_buffer_addr == NULL) {
-		pr_err("%s: failed to alloc count_buffer\n", __func__);
-		return -1;
-	}
-	memset(pbi->count_buffer_addr, 0, COUNT_BUF_SIZE);
 
 	if (pbi->mmu_enable) {
 		u32 mmu_map_size = vvp9_frame_mmu_map_size(pbi);
@@ -6873,6 +7640,20 @@
 		}
 		memset(pbi->frame_mmu_map_addr, 0, COUNT_BUF_SIZE);
 	}
+#ifdef VP9_10B_MMU_DW
+	if (pbi->dw_mmu_enable) {
+		u32 dw_mmu_map_size = vvp9_frame_mmu_map_size(pbi);
+		pbi->frame_mmu_dw_map_addr =
+			dma_alloc_coherent(amports_get_dma_device(),
+				dw_mmu_map_size,
+				&pbi->frame_mmu_dw_map_phy_addr, GFP_KERNEL);
+		if (pbi->frame_mmu_dw_map_addr == NULL) {
+			pr_err("%s: failed to alloc count_buffer mmu dw\n", __func__);
+			return -1;
+		}
+		memset(pbi->frame_mmu_dw_map_addr, 0, COUNT_BUF_SIZE);
+	}
+#endif
 #ifdef SUPPORT_FB_DECODING
 	if (pbi->m_ins_flag && stage_buf_num > 0) {
 		pbi->stage_mmu_map_addr =
@@ -6925,16 +7706,14 @@
 	/*CANVAS_BLKMODE_64X32*/
 	if	(pic_config->double_write_mode) {
 		canvas_w = pic_config->y_crop_width	/
-				get_double_write_ratio(pbi,
-					pic_config->double_write_mode);
+				get_double_write_ratio(
+					pic_config->double_write_mode & 0xf);
 		canvas_h = pic_config->y_crop_height /
-				get_double_write_ratio(pbi,
-					pic_config->double_write_mode);
+				get_double_write_ratio(
+					pic_config->double_write_mode & 0xf);
 
-		if (pbi->mem_map_mode == 0)
-			canvas_w = ALIGN(canvas_w, 32);
-		else
-			canvas_w = ALIGN(canvas_w, 64);
+		/* sao ctrl1 reg alignline with 64, align with 64 */
+		canvas_w = ALIGN(canvas_w, 64);
 		canvas_h = ALIGN(canvas_h, 32);
 
 		if (vdec->parallel_dec == 1) {
@@ -6949,12 +7728,12 @@
 			pic_config->uv_canvas_index = 128 + pic_config->index * 2 + 1;
 		}
 
-		canvas_config_ex(pic_config->y_canvas_index,
+		config_cav_lut_ex(pic_config->y_canvas_index,
 			pic_config->dw_y_adr, canvas_w, canvas_h,
-			CANVAS_ADDR_NOWRAP, blkmode, pbi->is_used_v4l ? 0 : 7);
-		canvas_config_ex(pic_config->uv_canvas_index,
+			CANVAS_ADDR_NOWRAP, blkmode, pbi->is_used_v4l ? 0 : 7, VDEC_HEVC);
+		config_cav_lut_ex(pic_config->uv_canvas_index,
 			pic_config->dw_u_v_adr,	canvas_w, canvas_h,
-			CANVAS_ADDR_NOWRAP, blkmode, pbi->is_used_v4l ? 0 : 7);
+			CANVAS_ADDR_NOWRAP, blkmode, pbi->is_used_v4l ? 0 : 7, VDEC_HEVC);
 
 #ifdef MULTI_INSTANCE_SUPPORT
 		pic_config->canvas_config[0].phy_addr =
@@ -7004,37 +7783,42 @@
 		memset(&hdr, 0, sizeof(hdr));
 		hdr.signal_type = vf->signal_type;
 		hdr.color_parms = pbi->vf_dp;
+
+		hdr.color_parms.luminance[0] = hdr.color_parms.luminance[0] / 10000;
+
 		vdec_v4l_set_hdr_infos(ctx, &hdr);
 	}
 
 	if ((pbi->chunk != NULL) && (pbi->chunk->hdr10p_data_buf != NULL)
 		&& (pbi->chunk->hdr10p_data_size != 0)) {
-		char *new_buf;
-		int i = 0;
-		new_buf = vzalloc(pbi->chunk->hdr10p_data_size);
+		if (pbi->chunk->hdr10p_data_size <= 128) {
+			char *new_buf;
+			int i = 0;
+			new_buf = kzalloc(pbi->chunk->hdr10p_data_size, GFP_ATOMIC);
 
-		if (new_buf) {
-			memcpy(new_buf, pbi->chunk->hdr10p_data_buf, pbi->chunk->hdr10p_data_size);
-			if (debug & VP9_DEBUG_BUFMGR_MORE) {
-				vp9_print(pbi, VP9_DEBUG_BUFMGR_MORE,
-					"hdr10p data: (size %d)\n",
-					pbi->chunk->hdr10p_data_size);
-				for (i = 0; i < pbi->chunk->hdr10p_data_size; i++) {
+			if (new_buf) {
+				memcpy(new_buf, pbi->chunk->hdr10p_data_buf, pbi->chunk->hdr10p_data_size);
+				if (debug & VP9_DEBUG_BUFMGR_MORE) {
 					vp9_print(pbi, VP9_DEBUG_BUFMGR_MORE,
-						"%02x ", pbi->chunk->hdr10p_data_buf[i]);
-					if (((i + 1) & 0xf) == 0)
-						vp9_print(pbi, VP9_DEBUG_BUFMGR_MORE, "\n");
+						"hdr10p data: (size %d)\n",
+						pbi->chunk->hdr10p_data_size);
+					for (i = 0; i < pbi->chunk->hdr10p_data_size; i++) {
+						vp9_print(pbi, VP9_DEBUG_BUFMGR_MORE,
+							"%02x ", pbi->chunk->hdr10p_data_buf[i]);
+						if (((i + 1) & 0xf) == 0)
+							vp9_print(pbi, VP9_DEBUG_BUFMGR_MORE, "\n");
+					}
+					vp9_print(pbi, VP9_DEBUG_BUFMGR_MORE, "\n");
 				}
-				vp9_print(pbi, VP9_DEBUG_BUFMGR_MORE, "\n");
-			}
 
-			vf->hdr10p_data_size = pbi->chunk->hdr10p_data_size;
-			vf->hdr10p_data_buf = new_buf;
-		} else {
-			vp9_print(pbi, 0, "%s:hdr10p data vzalloc size(%d) fail\n",
-				__func__, pbi->chunk->hdr10p_data_size);
-			vf->hdr10p_data_size = pbi->chunk->hdr10p_data_size;
-			vf->hdr10p_data_buf = new_buf;
+				vf->hdr10p_data_size = pbi->chunk->hdr10p_data_size;
+				vf->hdr10p_data_buf = new_buf;
+			} else {
+				vp9_print(pbi, 0, "%s:hdr10p data vzalloc size(%d) fail\n",
+					__func__, pbi->chunk->hdr10p_data_size);
+				vf->hdr10p_data_size = pbi->chunk->hdr10p_data_size;
+				vf->hdr10p_data_buf = new_buf;
+			}
 		}
 
 		vfree(pbi->chunk->hdr10p_data_buf);
@@ -7099,17 +7883,18 @@
 	if (kfifo_get(&pbi->display_q, &vf)) {
 		struct vframe_s *next_vf = NULL;
 		uint8_t index = vf->index & 0xff;
-		ATRACE_COUNTER(pbi->disp_q_name, kfifo_len(&pbi->display_q));
+		ATRACE_COUNTER(pbi->trace.disp_q_name, kfifo_len(&pbi->display_q));
 		if (index < pbi->used_buf_num ||
 			(vf->type & VIDTYPE_V4L_EOS)) {
 			vf->index_disp = pbi->vf_get_count;
 			pbi->vf_get_count++;
 			if (debug & VP9_DEBUG_BUFMGR)
-				pr_info("%s type 0x%x w/h %d/%d, pts %d, %lld\n",
-					__func__, vf->type,
+				pr_info("%s idx: %d, type 0x%x w/h %d/%d, pts %d, %lld, ts: %lld\n",
+					__func__, index, vf->type,
 					vf->width, vf->height,
 					vf->pts,
-					vf->pts_us64);
+					vf->pts_us64,
+					vf->timestamp);
 
 			if (kfifo_peek(&pbi->display_q, &next_vf) && next_vf) {
 				vf->next_vf_pts_valid = true;
@@ -7120,6 +7905,7 @@
 			return vf;
 		}
 	}
+
 	return NULL;
 }
 
@@ -7134,6 +7920,24 @@
 	if (!vf)
 		return;
 
+	if (pbi->enable_fence && vf->fence) {
+		int ret, i;
+
+		mutex_lock(&pbi->fence_mutex);
+		ret = dma_fence_get_status(vf->fence);
+		if (ret == 0) {
+			for (i = 0; i < VF_POOL_SIZE; i++) {
+				if (pbi->fence_vf_s.fence_vf[i] == NULL) {
+					pbi->fence_vf_s.fence_vf[i] = vf;
+					pbi->fence_vf_s.used_size++;
+					mutex_unlock(&pbi->fence_mutex);
+					return;
+				}
+			}
+		}
+		mutex_unlock(&pbi->fence_mutex);
+	}
+
 	index = vf->index & 0xff;
 
 	if (pbi->enable_fence && vf->fence) {
@@ -7142,14 +7946,23 @@
 	}
 
 	if (vf->hdr10p_data_buf) {
-		vfree(vf->hdr10p_data_buf);
+		kfree(vf->hdr10p_data_buf);
 		vf->hdr10p_data_buf = NULL;
 		vf->hdr10p_data_size = 0;
 	}
 
 	kfifo_put(&pbi->newframe_q, (const struct vframe_s *)vf);
-	ATRACE_COUNTER(pbi->new_q_name, kfifo_len(&pbi->newframe_q));
+	ATRACE_COUNTER(pbi->trace.new_q_name, kfifo_len(&pbi->newframe_q));
 	pbi->vf_put_count++;
+
+	if (debug & VP9_DEBUG_BUFMGR)
+		pr_info("%s idx: %d, type 0x%x w/h %d/%d, pts %d, %lld, ts: %lld\n",
+			__func__, index, vf->type,
+			vf->width, vf->height,
+			vf->pts,
+			vf->pts_us64,
+			vf->timestamp);
+
 	if (index < pbi->used_buf_num) {
 		struct VP9_Common_s *cm = &pbi->common;
 		struct BufferPool_s *pool = cm->buffer_pool;
@@ -7159,9 +7972,6 @@
 		if (pool->frame_bufs[index].buf.vf_ref > 0)
 			pool->frame_bufs[index].buf.vf_ref--;
 
-		if (pbi->is_used_v4l)
-			pool->frame_bufs[index].buf.vframe_bound = true;
-
 		if (pbi->wait_buf)
 			WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG,
 						0x1);
@@ -7290,11 +8100,29 @@
 static void update_vf_memhandle(struct VP9Decoder_s *pbi,
 	struct vframe_s *vf, struct PIC_BUFFER_CONFIG_s *pic)
 {
-	if (pic->index < 0) {
-		vf->mem_handle = NULL;
-		vf->mem_head_handle = NULL;
-		vf->mem_dw_handle = NULL;
-	} else if (vf->type & VIDTYPE_SCATTER) {
+	vf->mem_handle = NULL;
+	vf->mem_head_handle = NULL;
+	vf->mem_dw_handle = NULL;
+
+	/* keeper not needed for v4l solution */
+	if (pbi->is_used_v4l)
+		return;
+
+	if (vf->type & VIDTYPE_SCATTER) {
+
+#ifdef VP9_10B_MMU_DW
+		if (pic->double_write_mode & 0x20) {
+			vf->mem_handle =
+				decoder_mmu_box_get_mem_handle(
+					pbi->mmu_box_dw, pic->index);
+			vf->mem_head_handle =
+				decoder_bmmu_box_get_mem_handle(
+					pbi->bmmu_box,
+					HEADER_BUFFER_IDX(pic->BUF_index));
+			vf->mem_dw_handle = NULL;
+		} else
+#endif
+		{
 		vf->mem_handle =
 			decoder_mmu_box_get_mem_handle(
 				pbi->mmu_box, pic->index);
@@ -7309,6 +8137,7 @@
 					VF_BUFFER_IDX(pic->BUF_index));
 		else
 			vf->mem_dw_handle = NULL;
+		}
 	} else {
 		vf->mem_handle =
 			decoder_bmmu_box_get_mem_handle(
@@ -7322,11 +8151,12 @@
 	}
 }
 
-static inline void pbi_update_gvs(struct VP9Decoder_s *pbi)
+static inline void pbi_update_gvs(struct VP9Decoder_s *pbi,
+				  struct PIC_BUFFER_CONFIG_s *pic_config)
 {
-	if (pbi->gvs->frame_height != frame_height) {
-		pbi->gvs->frame_width = frame_width;
-		pbi->gvs->frame_height = frame_height;
+	if (pbi->gvs->frame_height != pic_config->y_crop_height) {
+		pbi->gvs->frame_width = pic_config->y_crop_width;
+		pbi->gvs->frame_height = pic_config->y_crop_height;
 	}
 	if (pbi->gvs->frame_dur != pbi->frame_dur) {
 		pbi->gvs->frame_dur = pbi->frame_dur;
@@ -7347,6 +8177,7 @@
 	int stream_offset = pic_config->stream_offset;
 	unsigned short slice_type = pic_config->slice_type;
 	struct aml_vcodec_ctx * v4l2_ctx = pbi->v4l2_ctx;
+	struct vdec_v4l2_buffer *fb = NULL;
 	ulong nv_order = VIDTYPE_VIU_NV21;
 	u32 pts_valid = 0, pts_us64_valid = 0;
 	u32 pts_save;
@@ -7361,6 +8192,7 @@
 		pr_info("fatal error, no available buffer slot.");
 		return -1;
 	}
+
 	/* swap uv */
 	if (pbi->is_used_v4l) {
 		if ((v4l2_ctx->cap_pix_fmt == V4L2_PIX_FMT_NV12) ||
@@ -7368,7 +8200,8 @@
 			nv_order = VIDTYPE_VIU_NV12;
 	}
 
-	if (pic_config->double_write_mode)
+	if (pic_config->double_write_mode &&
+		(pic_config->double_write_mode & 0x20) == 0)
 		set_canvas(pbi, pic_config);
 
 	display_frame_count[pbi->index]++;
@@ -7376,20 +8209,20 @@
 		if (!force_pts_unstable) {
 			if ((pic_config->pts == 0) || ((pic_config->pts <= pbi->last_pts) &&
 				(pic_config->pts64 <= pbi->last_pts_us64))) {
-					for (i = (FRAME_BUFFERS - 1); i > 0; i--) {
-						if ((pbi->last_pts == pbi->frame_mode_pts_save[i]) ||
-								(pbi->last_pts_us64 == pbi->frame_mode_pts64_save[i])) {
-								pic_config->pts = pbi->frame_mode_pts_save[i - 1];
-								pic_config->pts64 = pbi->frame_mode_pts64_save[i - 1];
-								break;
-						}
+				for (i = (FRAME_BUFFERS - 1); i > 0; i--) {
+					if ((pbi->last_pts == pbi->frame_mode_pts_save[i]) ||
+						(pbi->last_pts_us64 == pbi->frame_mode_pts64_save[i])) {
+						pic_config->pts = pbi->frame_mode_pts_save[i - 1];
+						pic_config->pts64 = pbi->frame_mode_pts64_save[i - 1];
+						break;
+					}
 				}
 				if ((i == 0) || (pic_config->pts <= pbi->last_pts)) {
-						vp9_print(pbi, VP9_DEBUG_OUT_PTS,
-							"no found pts %d, set 0. %d, %d\n",
-								i, pic_config->pts, pbi->last_pts);
-						pic_config->pts = 0;
-						pic_config->pts64 = 0;
+					vp9_print(pbi, VP9_DEBUG_OUT_PTS,
+						"no found pts %d, set 0. %d, %d\n",
+						i, pic_config->pts, pbi->last_pts);
+					pic_config->pts = 0;
+					pic_config->pts64 = 0;
 				}
 			}
 		}
@@ -7397,11 +8230,12 @@
 		if (pbi->is_used_v4l) {
 			vf->v4l_mem_handle
 				= pbi->m_BUF[pic_config->BUF_index].v4l_ref_buf_addr;
+			fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
 			if (pbi->mmu_enable) {
 				vf->mm_box.bmmu_box	= pbi->bmmu_box;
-				vf->mm_box.bmmu_idx	= HEADER_BUFFER_IDX(pic_config->BUF_index);
+				vf->mm_box.bmmu_idx	= HEADER_BUFFER_IDX(pbi->buffer_wrap[pic_config->BUF_index]);
 				vf->mm_box.mmu_box	= pbi->mmu_box;
-				vf->mm_box.mmu_idx	= pic_config->index;
+				vf->mm_box.mmu_idx	= pbi->buffer_wrap[pic_config->index];
 			}
 		}
 
@@ -7415,7 +8249,12 @@
 		if (vdec_frame_based(pvdec)) {
 			vf->pts = pic_config->pts;
 			vf->pts_us64 = pic_config->pts64;
-			vf->timestamp = pic_config->timestamp;
+
+			if (pbi->is_used_v4l && v4l_bitstream_id_enable)
+				vf->timestamp = pic_config->timestamp;
+			else
+				vf->timestamp = pic_config->pts64;
+
 			if (vf->pts != 0 || vf->pts_us64 != 0) {
 				pts_valid = 1;
 				pts_us64_valid = 1;
@@ -7453,7 +8292,7 @@
 
 		pts_save = vf->pts;
 		pts_us64_save = vf->pts_us64;
-		if (pbi->pts_unstable) {
+		if (pbi->is_used_v4l || pbi->pts_unstable) {
 			frame_duration_adapt(pbi, vf, pts_valid);
 			if (pbi->duration_from_pts_done) {
 				pbi->pts_mode = PTS_NONE_REF_USE_DURATION;
@@ -7525,10 +8364,28 @@
 			/* double write only */
 			vf->compBodyAddr = 0;
 			vf->compHeadAddr = 0;
+#ifdef VP9_10B_MMU_DW
+			vf->dwBodyAddr = 0;
+			vf->dwHeadAddr = 0;
+#endif
 		} else {
 			if (pbi->mmu_enable) {
 				vf->compBodyAddr = 0;
 				vf->compHeadAddr = pic_config->header_adr;
+#ifdef VP9_10B_MMU_DW
+				vf->dwBodyAddr = 0;
+				vf->dwHeadAddr = 0;
+				if (pic_config->double_write_mode & 0x20) {
+					u32 mode = pic_config->double_write_mode & 0xf;
+					if (mode == 5 || mode == 3)
+						vf->dwHeadAddr = pic_config->header_dw_adr;
+					else if ((mode == 1 || mode == 2 || mode == 4)
+					&& (debug & VP9_DEBUG_OUT_PTS) == 0) {
+						vf->compHeadAddr = pic_config->header_dw_adr;
+						pr_debug("Use dw mmu for display\n");
+					}
+				}
+#endif
 			} else {
 				/*vf->compBodyAddr = pic_config->mc_y_adr;
 				 *vf->compHeadAddr = pic_config->mc_y_adr +
@@ -7537,11 +8394,13 @@
 			}
 			vf->canvas0Addr = vf->canvas1Addr = 0;
 		}
-		if (pic_config->double_write_mode) {
+		if (pic_config->double_write_mode &&
+			(pic_config->double_write_mode & 0x20) == 0) {
 			vf->type = VIDTYPE_PROGRESSIVE |
 				VIDTYPE_VIU_FIELD;
 			vf->type |= nv_order;
-			if ((pic_config->double_write_mode == 3) &&
+			if ((pic_config->double_write_mode == 3 ||
+				pic_config->double_write_mode == 5) &&
 				(!IS_8K_SIZE(pic_config->y_crop_width,
 				pic_config->y_crop_height))) {
 				vf->type |= VIDTYPE_COMPRESS;
@@ -7593,24 +8452,29 @@
 		if (pic_config->bit_depth == VPX_BITS_8)
 			vf->bitdepth |= BITDEPTH_SAVING_MODE;
 
-		/* if((vf->width!=pic_config->width)|
-		 *	(vf->height!=pic_config->height))
-		 */
-		/* pr_info("aaa: %d/%d, %d/%d\n",
-		   vf->width,vf->height, pic_config->width,
-			pic_config->height); */
 		vf->width = pic_config->y_crop_width /
-			get_double_write_ratio(pbi,
-				pic_config->double_write_mode);
+			get_double_write_ratio(
+				pic_config->double_write_mode & 0xf);
 		vf->height = pic_config->y_crop_height /
-			get_double_write_ratio(pbi,
-				pic_config->double_write_mode);
+			get_double_write_ratio(
+				pic_config->double_write_mode & 0xf);
 		if (force_w_h != 0) {
 			vf->width = (force_w_h >> 16) & 0xffff;
 			vf->height = force_w_h & 0xffff;
 		}
-		vf->compWidth = pic_config->y_crop_width;
-		vf->compHeight = pic_config->y_crop_height;
+		if ((pic_config->double_write_mode & 0x20) &&
+			((pic_config->double_write_mode & 0xf) == 2 ||
+			(pic_config->double_write_mode & 0xf) == 4)) {
+			vf->compWidth = pic_config->y_crop_width /
+				get_double_write_ratio(
+					pic_config->double_write_mode & 0xf);
+			vf->compHeight = pic_config->y_crop_height /
+				get_double_write_ratio(
+					pic_config->double_write_mode & 0xf);
+		} else {
+			vf->compWidth = pic_config->y_crop_width;
+			vf->compHeight = pic_config->y_crop_height;
+		}
 		set_frame_info(pbi, vf);
 		if (force_fps & 0x100) {
 			u32 rate = force_fps & 0xff;
@@ -7627,9 +8491,10 @@
 		}
 		if ((debug & VP9_DEBUG_OUT_PTS) != 0) {
 			pr_info
-			("VP9 dec out pts: pts_mode=%d,dur=%d,pts(%d,%lld)(%d,%lld)\n",
+			("VP9 dec out pts: pts_mode=%d,dur=%d,pts(%d,%lld,%lld)(%d,%lld)\n",
 			pbi->pts_mode, pbi->frame_dur, vf->pts,
-			vf->pts_us64, pts_save, pts_us64_save);
+			vf->pts_us64, vf->timestamp, pts_save,
+			pts_us64_save);
 		}
 		if (!(pic_config->y_crop_width == 196
 		&& pic_config->y_crop_height == 196
@@ -7641,11 +8506,11 @@
 			decoder_do_frame_check(pvdec, vf);
 			vdec_vframe_ready(pvdec, vf);
 			kfifo_put(&pbi->display_q, (const struct vframe_s *)vf);
-			ATRACE_COUNTER(pbi->pts_name, vf->pts);
-			ATRACE_COUNTER(pbi->new_q_name, kfifo_len(&pbi->newframe_q));
-			ATRACE_COUNTER(pbi->disp_q_name, kfifo_len(&pbi->display_q));
+			ATRACE_COUNTER(pbi->trace.pts_name, vf->pts);
+			ATRACE_COUNTER(pbi->trace.new_q_name, kfifo_len(&pbi->newframe_q));
+			ATRACE_COUNTER(pbi->trace.disp_q_name, kfifo_len(&pbi->display_q));
 			pbi->vf_pre_count++;
-			pbi_update_gvs(pbi);
+			pbi_update_gvs(pbi, pic_config);
 			/*count info*/
 			vdec_count_info(pbi->gvs, 0, stream_offset);
 			if (stream_offset) {
@@ -7660,13 +8525,21 @@
 			memcpy(&tmp4x, pbi->gvs, sizeof(struct vdec_info));
 			tmp4x.bit_depth_luma = pbi->vp9_param.p.bit_depth;
 			tmp4x.bit_depth_chroma = pbi->vp9_param.p.bit_depth;
-			tmp4x.double_write_mode = get_double_write_mode(pbi);
+			tmp4x.double_write_mode = pic_config->double_write_mode;
 			vdec_fill_vdec_frame(pvdec, &pbi->vframe_qos, &tmp4x,
 				vf, pic_config->hw_decode_time);
 			pvdec->vdec_fps_detec(pvdec->id);
 			if (without_display_mode == 0) {
-				vf_notify_receiver(pbi->provider_name,
+				if (pbi->is_used_v4l) {
+					if (v4l2_ctx->is_stream_off) {
+						vvp9_vf_put(vvp9_vf_get(pbi), pbi);
+					} else {
+						fb->task->submit(fb->task, TASK_TYPE_DEC);
+					}
+				} else {
+					vf_notify_receiver(pbi->provider_name,
 						VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+				}
 			} else
 				vvp9_vf_put(vvp9_vf_get(pbi), pbi);
 		} else {
@@ -7700,7 +8573,8 @@
 			}
 
 			if (index == INVALID_IDX) {
-				if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb) < 0) {
+				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;
 				}
@@ -7712,11 +8586,16 @@
 		vf->flag		= VFRAME_FLAG_EMPTY_FRAME_V4L;
 		vf->v4l_mem_handle	= (index == INVALID_IDX) ? (ulong)fb :
 					hw->m_BUF[index].v4l_ref_buf_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);
-		vf_notify_receiver(vdec->vf_provider_name,
-			VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+
+		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] VP9 EOS notify.\n", (hw->is_used_v4l)?ctx->id:vdec->id);
 	}
@@ -7814,6 +8693,43 @@
 
 }
 
+static int recycle_mmu_buf_tail(struct VP9Decoder_s *pbi,
+		bool check_dma)
+{
+	struct VP9_Common_s *const cm = &pbi->common;
+
+	if (pbi->used_4k_num == -1) {
+		pbi->used_4k_num =
+			READ_VREG(HEVC_SAO_MMU_STATUS) >> 16;
+	}
+	vp9_print(pbi, VP9_DEBUG_BUFMGR_MORE,
+		"pic index %d page_start %d\n",
+		cm->cur_fb_idx_mmu, pbi->used_4k_num);
+
+	if (check_dma)
+		hevc_mmu_dma_check(hw_to_vdec(pbi));
+
+	if (pbi->is_used_v4l) {
+		int index = cm->cur_fb_idx_mmu;
+		struct internal_comp_buf *ibuf =
+			index_to_icomp_buf(pbi, index);
+
+		decoder_mmu_box_free_idx_tail(
+				ibuf->mmu_box,
+				ibuf->index,
+				pbi->used_4k_num);
+	} else {
+		decoder_mmu_box_free_idx_tail(
+				pbi->mmu_box,
+				cm->cur_fb_idx_mmu,
+				pbi->used_4k_num);
+	}
+
+	cm->cur_fb_idx_mmu = INVALID_IDX;
+	pbi->used_4k_num = -1;
+
+	return 0;
+}
 
 static void vp9_recycle_mmu_buf_tail(struct VP9Decoder_s *pbi)
 {
@@ -7821,16 +8737,9 @@
 	if (pbi->double_write_mode & 0x10)
 		return;
 	if (cm->cur_fb_idx_mmu != INVALID_IDX) {
-		if (pbi->used_4k_num == -1) {
-			pbi->used_4k_num =
-			(READ_VREG(HEVC_SAO_MMU_STATUS) >> 16);
-			if (pbi->m_ins_flag)
-				hevc_mmu_dma_check(hw_to_vdec(pbi));
-		}
-		decoder_mmu_box_free_idx_tail(pbi->mmu_box,
-			cm->cur_fb_idx_mmu, pbi->used_4k_num);
-		cm->cur_fb_idx_mmu = INVALID_IDX;
-		pbi->used_4k_num = -1;
+		recycle_mmu_buf_tail(pbi,
+			((pbi->used_4k_num == -1) &&
+			pbi->m_ins_flag) ? 1 : 0);
 	}
 }
 
@@ -7838,6 +8747,10 @@
 static void vp9_recycle_mmu_buf(struct VP9Decoder_s *pbi)
 {
 	struct VP9_Common_s *const cm = &pbi->common;
+
+	if (pbi->is_used_v4l)
+		return;
+
 	if (pbi->double_write_mode & 0x10)
 		return;
 	if (cm->cur_fb_idx_mmu != INVALID_IDX) {
@@ -7890,7 +8803,6 @@
 
 	if (pbi->is_used_v4l && ctx->param_sets_from_ucode)
 		pbi->res_ch_flag = 0;
-
 	bit_depth_luma = pbi->vp9_param.p.bit_depth;
 	bit_depth_chroma = pbi->vp9_param.p.bit_depth;
 
@@ -7921,6 +8833,22 @@
 				pr_err("can't alloc need mmu1,idx %d ret =%d\n",
 					cm->new_fb_idx,
 					ret);
+
+#ifdef VP9_10B_MMU_DW
+			if (pbi->dw_mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) {
+				ret = vp9_alloc_mmu_dw(pbi,
+					cm->new_fb_idx,
+					params->p.width,
+					params->p.height,
+					params->p.bit_depth,
+					pbi->frame_mmu_dw_map_addr);
+				if (ret < 0)
+					pr_err("can't alloc need dw mmu1,idx %d ret =%d\n",
+						cm->new_fb_idx,
+						ret);
+			}
+#endif
+
 		} else {
 			ret = 0;
 		}
@@ -7932,8 +8860,11 @@
 		 ret);
 		WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DISCARD_NAL);
 		cm->show_frame = 0;
-		if (pbi->mmu_enable)
+		if (pbi->mmu_enable) {
+			ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_START);
 			vp9_recycle_mmu_buf(pbi);
+			ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_END);
+		}
 #ifdef MULTI_INSTANCE_SUPPORT
 		if (pbi->m_ins_flag) {
 			pbi->dec_result = DEC_RESULT_DONE;
@@ -7960,11 +8891,14 @@
 			if (pbi->chunk) {
 				cur_pic_config->pts = pbi->chunk->pts;
 				cur_pic_config->pts64 = pbi->chunk->pts64;
-				cur_pic_config->timestamp = pbi->chunk->timestamp;
+
+				if (pbi->is_used_v4l && !v4l_bitstream_id_enable)
+					cur_pic_config->pts64 = pbi->chunk->timestamp;
 			}
 #endif
 		}
 		/*pr_info("Decode Frame Data %d\n", pbi->frame_count);*/
+		ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_REGISTER_START);
 		config_pic_size(pbi, pbi->vp9_param.p.bit_depth);
 
 		if ((pbi->common.frame_type != KEY_FRAME)
@@ -7980,6 +8914,7 @@
 #endif
 				clear_mpred_hw(pbi);
 		}
+
 #ifdef MCRCC_ENABLE
 		if (mcrcc_cache_alg_flag)
 			config_mcrcc_axi_hw_new(pbi);
@@ -8045,11 +8980,28 @@
 			if ((frame_bufs[i].ref_count == 0) &&
 				(frame_bufs[i].buf.vf_ref == 0) &&
 				(frame_bufs[i].buf.index != -1)) {
-				decoder_mmu_box_free_idx(pbi->mmu_box, i);
+				if (pbi->is_used_v4l) {
+					struct internal_comp_buf *ibuf =
+						index_to_icomp_buf(pbi, i);
+					ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_START);
+					decoder_mmu_box_free_idx(ibuf->mmu_box, ibuf->index);
+					ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_END);
+				} else {
+					ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_START);
+					decoder_mmu_box_free_idx(pbi->mmu_box, i);
+					ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_END);
+
+#ifdef VP9_10B_MMU_DW
+					if (pbi->dw_mmu_enable)
+						decoder_mmu_box_free_idx(pbi->mmu_box_dw, i);
+#endif
+
+				}
 			}
 			pbi->last_put_idx = -1;
 		}
 	}
+	ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_REGISTER_END);
 	return ret;
 }
 
@@ -8151,7 +9103,7 @@
 		frame->min_mv = a[0];
 
 		vp9_print(pbi, VP9_DEBUG_QOS_INFO,
-			"mv data %lx  a[0]= %x a[1]= %x a[2]= %x\n",
+			"mv data %x  a[0]= %x a[1]= %x a[2]= %x\n",
 			data, a[0], a[1], a[2]);
 
 		data = READ_VREG(HEVC_QP_INFO);
@@ -8178,7 +9130,7 @@
 		frame->min_qp = a[0];
 
 		vp9_print(pbi, VP9_DEBUG_QOS_INFO,
-			"qp data %lx  a[0]= %x a[1]= %x a[2]= %x\n",
+			"qp data %x  a[0]= %x a[1]= %x a[2]= %x\n",
 			data, a[0], a[1], a[2]);
 
 		data = READ_VREG(HEVC_SKIP_INFO);
@@ -8205,7 +9157,7 @@
 		frame->min_skip = a[0];
 
 		vp9_print(pbi, VP9_DEBUG_QOS_INFO,
-			"skip data %lx  a[0]= %x a[1]= %x a[2]= %x\n",
+			"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;
@@ -8524,14 +9476,29 @@
 	}
 }
 
+static void vvp9_get_comp_buf_info(struct VP9Decoder_s *pbi,
+					struct vdec_comp_buf_info *info)
+{
+	u16 bit_depth = pbi->param.p.bit_depth;
+
+	info->max_size = vp9_max_mmu_buf_size(
+			pbi->max_pic_w,
+			pbi->max_pic_h);
+	info->header_size = vvp9_mmu_compress_header_size(
+			pbi->frame_width,
+			pbi->frame_height);
+	info->frame_buffer_size = vp9_mmu_page_num(
+			pbi, pbi->frame_width,
+			pbi->frame_height,
+			bit_depth == 0);
+}
+
 static int vvp9_get_ps_info(struct VP9Decoder_s *pbi, struct aml_vdec_ps_infos *ps)
 {
-	int dw_mode = v4l_parser_get_double_write_mode(pbi);
-
-	ps->visible_width 	= pbi->frame_width / get_double_write_ratio(pbi, dw_mode);
-	ps->visible_height 	= pbi->frame_height / get_double_write_ratio(pbi, dw_mode);
-	ps->coded_width 	= ALIGN(pbi->frame_width, 32) / get_double_write_ratio(pbi, dw_mode);
-	ps->coded_height 	= ALIGN(pbi->frame_height, 32) / get_double_write_ratio(pbi, dw_mode);
+	ps->visible_width 	= pbi->frame_width;
+	ps->visible_height 	= pbi->frame_height;
+	ps->coded_width 	= ALIGN(pbi->frame_width, 64);
+	ps->coded_height 	= ALIGN(pbi->frame_height, 64);
 	ps->dpb_size 		= pbi->used_buf_num;
 
 	return 0;
@@ -8542,22 +9509,34 @@
 {
 	struct aml_vcodec_ctx *ctx =
 		(struct aml_vcodec_ctx *)(pbi->v4l2_ctx);
-	struct VP9_Common_s *const cm = &pbi->common;
 	int ret = 0;
 
 	if (ctx->param_sets_from_ucode &&
 		pbi->res_ch_flag == 0) {
 		struct aml_vdec_ps_infos ps;
-		if ((cm->width != 0 &&
-			cm->height != 0) &&
-			(pbi->frame_width != cm->width ||
-			pbi->frame_height != cm->height)) {
+		struct vdec_comp_buf_info comp;
 
-			vp9_print(pbi, 0, "%s (%d,%d)=>(%d,%d)\r\n", __func__, cm->width,
-				cm->height, pbi->frame_width, pbi->frame_height);
+		if ((pbi->last_width != 0 &&
+			pbi->last_height != 0) &&
+			(pbi->frame_width != pbi->last_width ||
+			pbi->frame_height != pbi->last_height)) {
+
+			vp9_print(pbi, 0, "%s (%d,%d)=>(%d,%d)\r\n", __func__, pbi->last_width,
+				pbi->last_height, pbi->frame_width, pbi->frame_height);
+
+			if (get_valid_double_write_mode(pbi) != 16) {
+				vvp9_get_comp_buf_info(pbi, &comp);
+				vdec_v4l_set_comp_buf_info(ctx, &comp);
+			}
+
 			vvp9_get_ps_info(pbi, &ps);
 			vdec_v4l_set_ps_infos(ctx, &ps);
 			vdec_v4l_res_ch_event(ctx);
+
+			pbi->init_pic_w = pbi->frame_width;
+			pbi->init_pic_h = pbi->frame_height;
+			init_mv_buf_list(pbi);
+
 			pbi->v4l_params_parsed = false;
 			pbi->res_ch_flag = 1;
 			ctx->v4l_resolution_change = 1;
@@ -8582,6 +9561,14 @@
 	/*if (pbi->wait_buf)
 	 *	pr_info("set wait_buf to 0\r\n");
 	 */
+
+	if (dec_status == VP9_HEAD_PARSER_DONE) {
+		ATRACE_COUNTER(pbi->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_START);
+	}
+	else if (dec_status == HEVC_DECPIC_DATA_DONE) {
+		ATRACE_COUNTER(pbi->trace.decode_time_name, DECODER_ISR_THREAD_PIC_DONE_START);
+	}
+
 	if (pbi->eos)
 		return IRQ_HANDLED;
 	pbi->wait_buf = 0;
@@ -8617,8 +9604,15 @@
 			if (!vdec_frame_based(hw_to_vdec(pbi)))
 				dec_again_process(pbi);
 			else {
-				pbi->dec_result = DEC_RESULT_GET_DATA;
-				vdec_schedule_work(&pbi->work);
+				if (pbi->common.show_existing_frame) {
+					pbi->dec_result = DEC_RESULT_DONE;

+					amhevc_stop();

+					vdec_schedule_work(&pbi->work);

+				}

+				else {

+					pbi->dec_result = DEC_RESULT_GET_DATA;

+					vdec_schedule_work(&pbi->work);

+				}

 			}
 		}
 		pbi->process_busy = 0;
@@ -8649,6 +9643,7 @@
 				amhevc_stop();
 				if (mcrcc_cache_alg_flag)
 					dump_hit_rate(pbi);
+				ATRACE_COUNTER(pbi->trace.decode_time_name, DECODER_ISR_THREAD_EDN);
 				vdec_schedule_work(&pbi->work);
 			}
 		} else {
@@ -8733,9 +9728,11 @@
 		&& pbi->used_stage_buf_num == 0
 #endif
 		) {
-		if (pbi->mmu_enable)
+		if (pbi->mmu_enable) {
+			ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_START);
 			vp9_recycle_mmu_buf_tail(pbi);
-
+			ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_MEMORY_END);
+		}
 
 		if (pbi->frame_count > 0)
 			vp9_bufmgr_postproc(pbi);
@@ -8794,12 +9791,14 @@
 		} else
 #endif
 		{
+			ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_RPM_START);
 			for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) {
 				int ii;
 				for (ii = 0; ii < 4; ii++)
 					pbi->vp9_param.l.data[i + ii] =
 						pbi->rpm_ptr[i + 3 - ii];
 			}
+			ATRACE_COUNTER(pbi->trace.decode_header_memory_time_name, TRACE_HEADER_RPM_END);
 		}
 	}
 
@@ -8822,11 +9821,22 @@
 		if (!v4l_res_change(pbi)) {
 			if (ctx->param_sets_from_ucode && !pbi->v4l_params_parsed) {
 				struct aml_vdec_ps_infos ps;
+				struct vdec_comp_buf_info comp;
 
 				pr_debug("set ucode parse\n");
+				if (get_valid_double_write_mode(pbi) != 16) {
+					vvp9_get_comp_buf_info(pbi, &comp);
+					vdec_v4l_set_comp_buf_info(ctx, &comp);
+				}
+
 				vvp9_get_ps_info(pbi, &ps);
 				/*notice the v4l2 codec.*/
 				vdec_v4l_set_ps_infos(ctx, &ps);
+
+				pbi->init_pic_w = pbi->frame_width;
+				pbi->init_pic_h = pbi->frame_height;
+				init_mv_buf_list(pbi);
+
 				pbi->v4l_params_parsed	= true;
 				pbi->postproc_done = 0;
 				pbi->process_busy = 0;
@@ -8849,7 +9859,7 @@
 	if (pbi->m_ins_flag)
 		start_process_time(pbi);
 #endif
-
+	ATRACE_COUNTER(pbi->trace.decode_time_name, DECODER_ISR_THREAD_HEAD_END);
 	return IRQ_HANDLED;
 }
 
@@ -8859,22 +9869,25 @@
 	unsigned int dec_status;
 	struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)data;
 	unsigned int adapt_prob_status;
-	struct VP9_Common_s *const cm = &pbi->common;
 	uint debug_tag;
 
 	WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1);
 
 	dec_status = READ_VREG(HEVC_DEC_STATUS_REG);
+	if (dec_status == VP9_HEAD_PARSER_DONE) {
+		ATRACE_COUNTER(pbi->trace.decode_time_name, DECODER_ISR_HEAD_DONE);
+	}
+	else if (dec_status == HEVC_DECPIC_DATA_DONE) {
+		ATRACE_COUNTER(pbi->trace.decode_time_name, DECODER_ISR_PIC_DONE);
+	}
+
 	adapt_prob_status = READ_VREG(VP9_ADAPT_PROB_REG);
 	if (!pbi)
 		return IRQ_HANDLED;
 	if (pbi->init_flag == 0)
 		return IRQ_HANDLED;
-	if (pbi->process_busy) {/*on process.*/
-		vp9_print(pbi, PRINT_FLAG_VDEC_STATUS,
-			"%s: process_busy isr return\n", __func__);
+	if (pbi->process_busy)/*on process.*/
 		return IRQ_HANDLED;
-	}
 	pbi->dec_status = dec_status;
 	pbi->process_busy = 1;
 	if (debug & VP9_DEBUG_BUFMGR)
@@ -8964,34 +9977,44 @@
 	}
 #endif
 	if ((adapt_prob_status & 0xff) == 0xfd) {
-		/*VP9_REQ_ADAPT_PROB*/
-		int pre_fc = (cm->frame_type == KEY_FRAME) ? 1 : 0;
-		uint8_t *prev_prob_b =
-		((uint8_t *)pbi->prob_buffer_addr) +
-		((adapt_prob_status >> 8) * 0x1000);
-		uint8_t *cur_prob_b =
-		((uint8_t *)pbi->prob_buffer_addr) + 0x4000;
-		uint8_t *count_b = (uint8_t *)pbi->count_buffer_addr;
-#ifdef MULTI_INSTANCE_SUPPORT
-		if (pbi->m_ins_flag)
-			reset_process_time(pbi);
-#endif
-		adapt_coef_probs(pbi->pic_count,
-			(cm->last_frame_type == KEY_FRAME),
-			pre_fc, (adapt_prob_status >> 8),
-			(unsigned int *)prev_prob_b,
-			(unsigned int *)cur_prob_b, (unsigned int *)count_b);
+		struct VP9_Common_s *const cm = &pbi->common;
+		int pre_fc = 0;
 
-		memcpy(prev_prob_b, cur_prob_b, PROB_SIZE);
+		if (pbi->m_ins_flag)
+				reset_process_time(pbi);
+
+		if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) &&
+			(vdec_secure(hw_to_vdec(pbi)))) {
+			pre_fc = ((cm->frame_type == KEY_FRAME) || (cm->intra_only)) ? 0 : 1;
+			tee_vp9_prob_process(pre_fc, cm->last_frame_type,
+				adapt_prob_status, (unsigned int)pbi->prob_buffer_phy_addr);
+		} else {
+			uint8_t *prev_prob_b, *cur_prob_b, *count_b;
+
+			/*VP9_REQ_ADAPT_PROB*/
+			pre_fc = ((cm->frame_type == KEY_FRAME) || (cm->intra_only));
+			prev_prob_b = ((uint8_t *)pbi->prob_buffer_addr) +
+				((adapt_prob_status >> 8) * 0x1000);
+			cur_prob_b = ((uint8_t *)pbi->prob_buffer_addr) + 0x4000;
+			count_b = (uint8_t *)pbi->count_buffer_addr;
+
+			adapt_coef_probs(pbi->pic_count,
+				(cm->last_frame_type == KEY_FRAME),
+				pre_fc, (adapt_prob_status >> 8),
+				(unsigned int *)prev_prob_b,
+				(unsigned int *)cur_prob_b, (unsigned int *)count_b);
+
+			memcpy(prev_prob_b, cur_prob_b, PROB_SIZE);
+		}
+
 		WRITE_VREG(VP9_ADAPT_PROB_REG, 0);
 		pbi->pic_count += 1;
 #ifdef MULTI_INSTANCE_SUPPORT
 		if (pbi->m_ins_flag)
 			start_process_time(pbi);
 #endif
-
-		/*return IRQ_HANDLED;*/
 	}
+	ATRACE_COUNTER(pbi->trace.decode_time_name, DECODER_ISR_END);
 	return IRQ_WAKE_THREAD;
 }
 
@@ -9007,15 +10030,14 @@
 		frame_height * fps;
 }
 
-static void vvp9_put_timer_func(unsigned long arg)
+static void vvp9_put_timer_func(struct timer_list *timer)
 {
-	struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)arg;
-	struct timer_list *timer = &pbi->timer;
+	struct VP9Decoder_s *pbi = container_of(timer,
+		struct VP9Decoder_s, timer);
+	enum receviver_start_e state = RECEIVER_INACTIVE;
 	uint8_t empty_flag;
 	unsigned int buf_level;
 
-	enum receviver_start_e state = RECEIVER_INACTIVE;
-
 	if (pbi->m_ins_flag) {
 		if (hw_to_vdec(pbi)->next_status
 			== VDEC_STATUS_DISCONNECTED &&
@@ -9517,12 +10539,10 @@
 	fw->len = fw_size;
 
 	INIT_WORK(&pbi->set_clk_work, vp9_set_clk);
-	init_timer(&pbi->timer);
+	timer_setup(&pbi->timer, vvp9_put_timer_func, 0);
 
 #ifdef MULTI_INSTANCE_SUPPORT
 	if (pbi->m_ins_flag) {
-		pbi->timer.data = (ulong) pbi;
-		pbi->timer.function = vvp9_put_timer_func;
 		pbi->timer.expires = jiffies + PUT_INTERVAL;
 
 		/*add_timer(&pbi->timer);
@@ -9579,16 +10599,18 @@
 
 	pbi->provider_name = PROVIDER_NAME;
 #ifdef MULTI_INSTANCE_SUPPORT
-	vf_provider_init(&vvp9_vf_prov, PROVIDER_NAME,
-				&vvp9_vf_provider, pbi);
-	vf_reg_provider(&vvp9_vf_prov);
-	vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL);
-	if (pbi->frame_dur != 0) {
-		if (!is_reset)
-			vf_notify_receiver(pbi->provider_name,
-					VFRAME_EVENT_PROVIDER_FR_HINT,
-					(void *)
-					((unsigned long)pbi->frame_dur));
+	if (!pbi->is_used_v4l) {
+		vf_provider_init(&vvp9_vf_prov, PROVIDER_NAME,
+					&vvp9_vf_provider, pbi);
+		vf_reg_provider(&vvp9_vf_prov);
+		vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL);
+		if (pbi->frame_dur != 0) {
+			if (!is_reset)
+				vf_notify_receiver(pbi->provider_name,
+						VFRAME_EVENT_PROVIDER_FR_HINT,
+						(void *)
+						((unsigned long)pbi->frame_dur));
+		}
 	}
 #else
 	vf_provider_init(&vvp9_vf_prov, PROVIDER_NAME, &vvp9_vf_provider,
@@ -9601,14 +10623,11 @@
 #endif
 	pbi->stat |= STAT_VF_HOOK;
 
-	pbi->timer.data = (ulong)pbi;
-	pbi->timer.function = vvp9_put_timer_func;
 	pbi->timer.expires = jiffies + PUT_INTERVAL;
+	add_timer(&pbi->timer);
 
 	pbi->stat |= STAT_VDEC_RUN;
 
-	add_timer(&pbi->timer);
-
 	pbi->stat |= STAT_TIMER_ARM;
 
 	amhevc_start();
@@ -9637,7 +10656,7 @@
 		pbi->stat &= ~STAT_TIMER_ARM;
 	}
 
-	if (pbi->stat & STAT_VF_HOOK) {
+	if (!pbi->is_used_v4l && (pbi->stat & STAT_VF_HOOK)) {
 		if (!is_reset)
 			vf_notify_receiver(pbi->provider_name,
 					VFRAME_EVENT_PROVIDER_FR_END_HINT,
@@ -9686,7 +10705,7 @@
 		pbi->stat &= ~STAT_TIMER_ARM;
 	}
 
-	if (pbi->stat & STAT_VF_HOOK) {
+	if (!pbi->is_used_v4l && (pbi->stat & STAT_VF_HOOK)) {
 		if (!is_reset)
 			vf_notify_receiver(pbi->provider_name,
 					VFRAME_EVENT_PROVIDER_FR_END_HINT,
@@ -9717,22 +10736,16 @@
 	pbi->fw = NULL;
 	return 0;
 }
+
 static int amvdec_vp9_mmu_init(struct VP9Decoder_s *pbi)
 {
 	int tvp_flag = vdec_secure(hw_to_vdec(pbi)) ?
 		CODEC_MM_FLAGS_TVP : 0;
-	int buf_size = 48;
+	int buf_size = vp9_max_mmu_buf_size(pbi->max_pic_w, pbi->max_pic_h);
 
-	if ((pbi->max_pic_w * pbi->max_pic_h > 1280*736) &&
-		(pbi->max_pic_w * pbi->max_pic_h <= 1920*1088)) {
-		buf_size = 12;
-	} else if ((pbi->max_pic_w * pbi->max_pic_h > 0) &&
-		(pbi->max_pic_w * pbi->max_pic_h <= 1280*736)) {
-		buf_size = 4;
-	}
 	pbi->need_cache_size = buf_size * SZ_1M;
 	pbi->sc_start_time = get_jiffies_64();
-	if (pbi->mmu_enable && ((pbi->double_write_mode & 0x10) == 0)) {
+	if (pbi->mmu_enable && !pbi->is_used_v4l) {
 		pbi->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME,
 			pbi->index, FRAME_BUFFERS,
 			pbi->need_cache_size,
@@ -9743,6 +10756,18 @@
 			return -1;
 		}
 	}
+#ifdef VP9_10B_MMU_DW
+	if (pbi->dw_mmu_enable && !pbi->is_used_v4l) {
+		pbi->mmu_box_dw = decoder_mmu_box_alloc_box(DRIVER_NAME,
+			pbi->index, FRAME_BUFFERS,
+			pbi->need_cache_size,
+			tvp_flag
+			);
+		if (!pbi->mmu_box_dw) {
+			pr_err("vp9 alloc mmu dw box failed!!\n");
+		}
+	}
+#endif
 	pbi->bmmu_box = decoder_bmmu_box_alloc_box(
 			DRIVER_NAME,
 			pbi->index,
@@ -9769,10 +10794,16 @@
 #ifndef MULTI_INSTANCE_SUPPORT
 	int i;
 #endif
+	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL ||
+		get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_TXL ||
+		get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5) {
+		pr_info("vp9 unsupported on cpu 0x%x\n", get_cpu_major_id());
+		return -EINVAL;
+	}
 	pr_debug("%s\n", __func__);
 
 	mutex_lock(&vvp9_mutex);
-	pbi = vmalloc(sizeof(struct VP9Decoder_s));
+	pbi = vzalloc(sizeof(struct VP9Decoder_s));
 	if (pbi == NULL) {
 		pr_info("\namvdec_vp9 device data allocation failed\n");
 		mutex_unlock(&vvp9_mutex);
@@ -9786,12 +10817,29 @@
 
 	pbi->init_flag = 0;
 	pbi->first_sc_checked= 0;
-	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
-		vp9_max_pic_w = 8192;
-		vp9_max_pic_h = 4608;
+
+	if (!vdec_is_support_4k()) {
+		pbi->max_pic_w = 1920;
+		pbi->max_pic_h = 1088;
+	} else if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SM1) {
+		pbi->max_pic_w = 4096;
+		pbi->max_pic_h = 2304;
+	} else {
+		pbi->max_pic_w = 8192;
+		pbi->max_pic_h = 4608;
 	}
-	pbi->max_pic_w = vp9_max_pic_w;
-	pbi->max_pic_h = vp9_max_pic_h;
+	if (pdata->sys_info) {
+		pbi->vvp9_amstream_dec_info = *pdata->sys_info;
+		if ((pbi->vvp9_amstream_dec_info.width != 0) &&
+			(pbi->vvp9_amstream_dec_info.height != 0)) {
+			pbi->max_pic_w = pbi->vvp9_amstream_dec_info.width;
+			pbi->max_pic_h = pbi->vvp9_amstream_dec_info.height;
+		}
+	} else {
+		pbi->vvp9_amstream_dec_info.width = 0;
+		pbi->vvp9_amstream_dec_info.height = 0;
+		pbi->vvp9_amstream_dec_info.rate = 30;
+	}
 
 #ifdef MULTI_INSTANCE_SUPPORT
 	pbi->eos = 0;
@@ -9813,6 +10861,14 @@
 #endif
 	pbi->double_write_mode = double_write_mode;
 	pbi->mmu_enable = 1;
+#ifdef VP9_10B_MMU_DW
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T5D) {
+		pbi->dw_mmu_enable =
+			(get_double_write_mode(pbi) & 0x20) ? 1 : 0;
+	} else {
+		pbi->dw_mmu_enable = 0;
+	}
+#endif
 	if (amvdec_vp9_mmu_init(pbi) < 0) {
 		vfree(pbi);
 		mutex_unlock(&vvp9_mutex);
@@ -9845,20 +10901,18 @@
 		pr_info("===VP9 decoder mem resource 0x%lx size 0x%x\n",
 			   pdata->mem_start, pbi->buf_size);
 	}
-
-	if (pdata->sys_info)
-		pbi->vvp9_amstream_dec_info = *pdata->sys_info;
-	else {
-		pbi->vvp9_amstream_dec_info.width = 0;
-		pbi->vvp9_amstream_dec_info.height = 0;
-		pbi->vvp9_amstream_dec_info.rate = 30;
-	}
 	pbi->no_head = no_head;
 #ifdef MULTI_INSTANCE_SUPPORT
 	pbi->cma_dev = pdata->cma_dev;
 #else
 	cma_dev = pdata->cma_dev;
 #endif
+	/* config endian */
+	pbi->endian = HEVC_CONFIG_LITTLE_ENDIAN;
+	if (is_support_vdec_canvas())
+		pbi->endian = HEVC_CONFIG_BIG_ENDIAN;
+	if (endian)
+		pbi->endian = endian;
 
 #ifdef MULTI_INSTANCE_SUPPORT
 	pdata->private = pbi;
@@ -9889,7 +10943,6 @@
 			       struct vdec_sync *sync)
 {
 	ulong expires;
-	int i;
 
 	/* notify signal to wake up all fences. */
 	vdec_timeline_increase(sync, VF_POOL_SIZE);
@@ -9902,15 +10955,6 @@
 		}
 	}
 
-	for (i = 0; i < VF_POOL_SIZE; i++) {
-		struct vframe_s *vf = &pbi->vfpool[i];
-
-		if (vf->fence) {
-			vdec_fence_put(vf->fence);
-			vf->fence = NULL;
-		}
-	}
-
 	/* decreases refcnt of timeline. */
 	vdec_timeline_put(sync);
 }
@@ -9946,7 +10990,7 @@
 	mem_map_mode = 0;
 
 	if (pbi->enable_fence)
-		vdec_fence_release(pbi, &vdec->sync);
+		vdec_fence_release(pbi, vdec->sync);
 
 	vfree(pbi);
 	mutex_unlock(&vvp9_mutex);
@@ -9955,32 +10999,16 @@
 }
 
 /****************************************/
-#ifdef CONFIG_PM
-static int vp9_suspend(struct device *dev)
-{
-	amhevc_suspend(to_platform_device(dev), dev->power.power_state);
-	return 0;
-}
-
-static int vp9_resume(struct device *dev)
-{
-	amhevc_resume(to_platform_device(dev));
-	return 0;
-}
-
-static const struct dev_pm_ops vp9_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(vp9_suspend, vp9_resume)
-};
-#endif
 
 static struct platform_driver amvdec_vp9_driver = {
 	.probe = amvdec_vp9_probe,
 	.remove = amvdec_vp9_remove,
+#ifdef CONFIG_PM
+	.suspend = amhevc_suspend,
+	.resume = amhevc_resume,
+#endif
 	.driver = {
 		.name = DRIVER_NAME,
-#ifdef CONFIG_PM
-		.pm = &vp9_pm_ops,
-#endif
 	}
 };
 
@@ -9998,6 +11026,9 @@
 	int sum = 0;
 	u8 *data = NULL;
 
+	if (vdec_secure(hw_to_vdec(pbi)))
+		return 0;
+
 	if (!pbi->chunk->block->is_mapped)
 		data = codec_mm_vmap(pbi->chunk->block->start +
 			pbi->chunk->offset, size);
@@ -10008,6 +11039,20 @@
 	for (jj = 0; jj < size; jj++)
 		sum += data[jj];
 
+	vp9_print(pbi, PRINT_FLAG_VDEC_STATUS,
+		"%s: size 0x%x sum 0x%x %02x %02x %02x %02x %02x %02x .. %02x %02x %02x %02x\n",
+		__func__, size, sum,
+		(size < 1) ? 0 : data[0],
+		(size < 2) ? 0 : data[1],
+		(size < 3) ? 0 : data[2],
+		(size < 4) ? 0 : data[3],
+		(size < 5) ? 0 : data[4],
+		(size < 6) ? 0 : data[5],
+		(size < 4) ? 0 : data[size - 4],
+		(size < 3) ? 0 : data[size - 3],
+		(size < 2) ? 0 : data[size - 2],
+		(size < 1) ? 0 : data[size - 1]);
+
 	if (!pbi->chunk->block->is_mapped)
 		codec_mm_unmap_phyaddr(data);
 	return sum;
@@ -10064,6 +11109,9 @@
 	/* finished decoding one frame or error,
 	 * notify vdec core to switch context
 	 */
+	ATRACE_COUNTER(pbi->trace.decode_time_name, DECODER_WORKER_START);
+	if (pbi->dec_result == DEC_RESULT_AGAIN)
+		ATRACE_COUNTER(pbi->trace.decode_time_name, DECODER_WORKER_AGAIN);
 	vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL,
 		"%s dec_result %d %x %x %x\n",
 		__func__,
@@ -10081,7 +11129,6 @@
 	if (pbi->dec_result == DEC_RESULT_NEED_MORE_BUFFER) {
 		reset_process_time(pbi);
 		if (!get_free_buf_count(pbi)) {
-			pbi->process_busy = 0;
 			pbi->dec_result = DEC_RESULT_NEED_MORE_BUFFER;
 			vdec_schedule_work(&pbi->work);
 		} else {
@@ -10262,6 +11309,7 @@
 		pbi->stat &= ~STAT_TIMER_ARM;
 	}
 	/* mark itself has all HW resource released and input released */
+	ATRACE_COUNTER(pbi->trace.decode_time_name, DECODER_WORKER_END);
 #ifdef SUPPORT_FB_DECODING
 	if (pbi->used_stage_buf_num > 0)
 		vdec_core_finish_run(hw_to_vdec(pbi), CORE_MASK_HEVC_BACK);
@@ -10296,6 +11344,34 @@
 #endif
 	return 0;
 }
+
+static bool is_avaliable_buffer(struct VP9Decoder_s *pbi)
+{
+	struct VP9_Common_s *const cm = &pbi->common;
+	struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
+	struct aml_vcodec_ctx *ctx =
+		(struct aml_vcodec_ctx *)(pbi->v4l2_ctx);
+	int i, free_count = 0;
+
+	if (ctx->cap_pool.dec < pbi->used_buf_num) {
+		free_count = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx);
+		if (free_count &&
+			!ctx->fb_ops.query(&ctx->fb_ops, &pbi->fb_token)) {
+			return false;
+		}
+	}
+
+	for (i = 0; i < pbi->used_buf_num; ++i) {
+		if ((frame_bufs[i].ref_count == 0) &&
+			(frame_bufs[i].buf.vf_ref == 0) &&
+			frame_bufs[i].buf.cma_alloc_addr) {
+			free_count++;
+		}
+	}
+
+	return free_count < pbi->run_ready_min_buf_num ? 0 : 1;
+}
+
 static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
 {
 	struct VP9Decoder_s *pbi =
@@ -10307,7 +11383,17 @@
 	if (!(pbi->pic_list_init_done && pbi->pic_list_init_done2) || pbi->eos)
 		return ret;
 	if (!pbi->first_sc_checked && pbi->mmu_enable) {
-		int size = decoder_mmu_box_sc_check(pbi->mmu_box, tvp);
+		int size;
+		void * mmu_box;
+
+		if (pbi->is_used_v4l) {
+			struct aml_vcodec_ctx *ctx =
+				(struct aml_vcodec_ctx *)(pbi->v4l2_ctx);
+			mmu_box = ctx->mmu_box;
+		} else
+			mmu_box = pbi->mmu_box;
+
+		size = decoder_mmu_box_sc_check(mmu_box, tvp);
 		pbi->first_sc_checked = 1;
 		vp9_print(pbi, 0, "vp9 cached=%d  need_size=%d speed= %d ms\n",
 			size, (pbi->need_cache_size >> PAGE_SHIFT),
@@ -10377,10 +11463,12 @@
 
 		if (ctx->param_sets_from_ucode) {
 			if (pbi->v4l_params_parsed) {
-				if ((ctx->cap_pool.in < pbi->used_buf_num) &&
-				v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) <
-				pbi->run_ready_min_buf_num)
-					ret = 0;
+				if (ctx->cap_pool.dec < pbi->used_buf_num) {
+					if (is_avaliable_buffer(pbi))
+						ret = CORE_MASK_HEVC;
+					else
+						ret = 0;
+				}
 			} else {
 				if (ctx->v4l_resolution_change)
 					ret = 0;
@@ -10411,13 +11499,17 @@
 	if (pbi->chunk == NULL)
 	       return;
 	vp9_print(pbi, VP9_DEBUG_OUT_PTS,
-	       "run front: pts %d, pts64 %lld\n", pbi->chunk->pts, pbi->chunk->pts64);
+	       "run front: pts %d, pts64 %lld, ts: %lld\n",
+	       pbi->chunk->pts, pbi->chunk->pts64, pbi->chunk->timestamp);
 	for (i = (FRAME_BUFFERS - 1); i > 0; i--) {
-	       pbi->frame_mode_pts_save[i] = pbi->frame_mode_pts_save[i - 1];
-	       pbi->frame_mode_pts64_save[i] = pbi->frame_mode_pts64_save[i - 1];
+		pbi->frame_mode_pts_save[i] = pbi->frame_mode_pts_save[i - 1];
+		pbi->frame_mode_pts64_save[i] = pbi->frame_mode_pts64_save[i - 1];
 	}
 	pbi->frame_mode_pts_save[0] = pbi->chunk->pts;
 	pbi->frame_mode_pts64_save[0] = pbi->chunk->pts64;
+
+	if (pbi->is_used_v4l && !v4l_bitstream_id_enable)
+		pbi->frame_mode_pts64_save[0] = pbi->chunk->timestamp;
 }
 
 static void run_front(struct vdec_s *vdec)
@@ -10475,7 +11567,9 @@
 		READ_VREG(HEVC_STREAM_WR_PTR),
 		READ_VREG(HEVC_STREAM_RD_PTR),
 		pbi->start_shift_bytes);
-		if (vdec_frame_based(vdec) && pbi->chunk) {
+
+		if (!vdec_secure(hw_to_vdec(pbi)) &&
+			vdec_frame_based(vdec) && pbi->chunk) {
 			u8 *data = NULL;
 
 			if (!pbi->chunk->block->is_mapped)
@@ -10496,6 +11590,7 @@
 		}
 		vp9_print_cont(pbi, 0, "\r\n");
 	}
+	ATRACE_COUNTER(pbi->trace.decode_run_time_name, TRACE_RUN_LOADING_FW_START);
 	if (vdec->mc_loaded) {
 	/*firmware have load before,
 	  and not changes to another.
@@ -10515,12 +11610,14 @@
 		vdec->mc_loaded = 1;
 		vdec->mc_type = VFORMAT_VP9;
 	}
+	ATRACE_COUNTER(pbi->trace.decode_run_time_name, TRACE_RUN_LOADING_FW_END);
 
+	ATRACE_COUNTER(pbi->trace.decode_run_time_name, TRACE_RUN_LOADING_RESTORE_START);
 	if (vp9_hw_ctx_restore(pbi) < 0) {
 		vdec_schedule_work(&pbi->work);
 		return;
 	}
-
+	ATRACE_COUNTER(pbi->trace.decode_run_time_name, TRACE_RUN_LOADING_RESTORE_END);
 	vdec_enable_input(vdec);
 
 	WRITE_VREG(HEVC_DEC_STATUS_REG, HEVC_ACTION_DONE);
@@ -10694,7 +11791,7 @@
 {
 	struct VP9Decoder_s *pbi =
 		(struct VP9Decoder_s *)vdec->private;
-
+	ATRACE_COUNTER(pbi->trace.decode_time_name, DECODER_RUN_START);
 	vp9_print(pbi,
 		PRINT_FLAG_VDEC_DETAIL, "%s mask %lx\r\n",
 		__func__, mask);
@@ -10716,23 +11813,36 @@
 #else
 	run_front(vdec);
 #endif
+	ATRACE_COUNTER(pbi->trace.decode_time_name, DECODER_RUN_END);
 
 }
 
-static void  init_frame_bufs(struct VP9Decoder_s *pbi)
+static void  vp9_decoder_ctx_reset(struct VP9Decoder_s *pbi)
 {
 	struct vdec_s *vdec = hw_to_vdec(pbi);
 	struct VP9_Common_s *const cm = &pbi->common;
 	struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
+	struct BufferPool_s *buffer_pool = cm->buffer_pool;
 	int i;
 
-	for (i = 0; i < pbi->used_buf_num; ++i) {
-		frame_bufs[i].ref_count = 0;
-		frame_bufs[i].buf.vf_ref = 0;
-		frame_bufs[i].buf.decode_idx = 0;
+	cm->buffer_pool = buffer_pool;
+
+	for (i = 0; i < FRAME_BUFFERS; ++i) {
+		frame_bufs[i].buf.index		= i;
+		frame_bufs[i].ref_count		= 0;
+		frame_bufs[i].buf.vf_ref	= 0;
+		frame_bufs[i].buf.decode_idx	= 0;
 		frame_bufs[i].buf.cma_alloc_addr = 0;
-		frame_bufs[i].buf.index = i;
-		frame_bufs[i].buf.vframe_bound = 0;
+		frame_bufs[i].buf.BUF_index	= -1;
+		frame_bufs[i].buf.slice_type	= 0;
+	}
+
+	for (i = 0; i < MV_BUFFER_NUM; ++i) {
+		pbi->m_mv_BUF[i].used_flag = 0;
+	}
+
+	for (i = 0; i < FRAME_BUFFERS; i++) {
+		pbi->buffer_wrap[i] = i;
 	}
 
 	if (vdec->parallel_dec == 1) {
@@ -10745,6 +11855,12 @@
 				vdec->id);
 		}
 	}
+
+	pbi->init_flag		= 0;
+	pbi->first_sc_checked	= 0;
+	pbi->fatal_error	= 0;
+	pbi->show_frame_num	= 0;
+	pbi->eos		= 0;
 }
 
 static void reset(struct vdec_s *vdec)
@@ -10752,6 +11868,7 @@
 	struct VP9Decoder_s *pbi =
 		(struct VP9Decoder_s *)vdec->private;
 
+	cancel_work_sync(&pbi->set_clk_work);
 	cancel_work_sync(&pbi->work);
 	if (pbi->stat & STAT_VDEC_RUN) {
 		amhevc_stop();
@@ -10762,16 +11879,16 @@
 		del_timer_sync(&pbi->timer);
 		pbi->stat &= ~STAT_TIMER_ARM;
 	}
-	pbi->dec_result = DEC_RESULT_NONE;
+
 	reset_process_time(pbi);
+
 	vp9_local_uninit(pbi);
 	if (vvp9_local_init(pbi) < 0)
-		vp9_print(pbi, 0, "%s	local_init failed \r\n", __func__);
-	init_frame_bufs(pbi);
+		vp9_print(pbi, 0, "%s local_init failed \r\n", __func__);
 
-	pbi->eos = 0;
+	vp9_decoder_ctx_reset(pbi);
 
-	vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__);
+	vp9_print(pbi, 0, "%s\r\n", __func__);
 }
 
 static irqreturn_t vp9_irq_cb(struct vdec_s *vdec, int irq)
@@ -10818,7 +11935,7 @@
 		pbi->no_head
 		);
 
-	if (vf_get_receiver(vdec->vf_provider_name)) {
+	if (!pbi->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,
@@ -10847,7 +11964,7 @@
 
 	for (i = 0; i < MAX_BUF_NUM; i++) {
 		vp9_print(pbi, 0,
-			"mv_Buf(%d) start_adr 0x%lx size 0x%x used %d\n",
+			"mv_Buf(%d) start_adr 0x%x size 0x%x used %d\n",
 			i,
 			pbi->m_mv_BUF[i].start_adr,
 			pbi->m_mv_BUF[i].size,
@@ -10942,9 +12059,15 @@
 	int transfer_val;
 	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 VP9Decoder_s *pbi = NULL;
+	int i;
+
+	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL ||
+		get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_TXL ||
+		get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5) {
+		pr_info("vp9 unsupported on cpu 0x%x\n", get_cpu_major_id());
+		return -EINVAL;
+	}
 	pr_debug("%s\n", __func__);
 
 	if (pdata == NULL) {
@@ -10974,19 +12097,35 @@
 	pdata->threaded_irq_handler = vp9_threaded_irq_cb;
 	pdata->dump_state = vp9_dump_state;
 
-	memcpy(&BUF[0], &pbi->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
-	memcpy(&pbi->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
-
 	pbi->index = pdev->id;
 
-	snprintf(pbi->vdec_name, sizeof(pbi->vdec_name),
+	if (is_rdma_enable()) {
+		pbi->rdma_adr = dma_alloc_coherent(amports_get_dma_device(), RDMA_SIZE, &pbi->rdma_phy_adr, GFP_KERNEL);
+		for (i = 0; i < SCALELUT_DATA_WRITE_NUM; i++) {
+			pbi->rdma_adr[i * 4] = HEVC_IQIT_SCALELUT_WR_ADDR & 0xfff;
+			pbi->rdma_adr[i * 4 + 1] = i;
+			pbi->rdma_adr[i * 4 + 2] = HEVC_IQIT_SCALELUT_DATA & 0xfff;
+			pbi->rdma_adr[i * 4 + 3] = 0;
+			if (i == SCALELUT_DATA_WRITE_NUM - 1) {
+				pbi->rdma_adr[i * 4 + 2] = (HEVC_IQIT_SCALELUT_DATA & 0xfff) | 0x20000;
+			}
+		}
+	}
+
+	snprintf(pbi->trace.vdec_name, sizeof(pbi->trace.vdec_name),
 		"vp9-%d", pbi->index);
-	snprintf(pbi->pts_name, sizeof(pbi->pts_name),
-		"%s-pts", pbi->vdec_name);
-	snprintf(pbi->new_q_name, sizeof(pbi->new_q_name),
-		"%s-newframe_q", pbi->vdec_name);
-	snprintf(pbi->disp_q_name, sizeof(pbi->disp_q_name),
-		"%s-dispframe_q", pbi->vdec_name);
+	snprintf(pbi->trace.pts_name, sizeof(pbi->trace.pts_name),
+		"%s-pts", pbi->trace.vdec_name);
+	snprintf(pbi->trace.new_q_name, sizeof(pbi->trace.new_q_name),
+		"%s-newframe_q", pbi->trace.vdec_name);
+	snprintf(pbi->trace.disp_q_name, sizeof(pbi->trace.disp_q_name),
+		"%s-dispframe_q", pbi->trace.vdec_name);
+	snprintf(pbi->trace.decode_time_name, sizeof(pbi->trace.decode_time_name),
+		"decoder_time%d", pdev->id);
+	snprintf(pbi->trace.decode_run_time_name, sizeof(pbi->trace.decode_run_time_name),
+		"decoder_run_time%d", pdev->id);
+	snprintf(pbi->trace.decode_header_memory_time_name, sizeof(pbi->trace.decode_header_memory_time_name),
+			"decoder_header_time%d", pdev->id);
 
 	if (pdata->use_vfm_path)
 		snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
@@ -10995,26 +12134,23 @@
 		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,
-		&vvp9_vf_provider, pbi);
-
 	pbi->provider_name = pdata->vf_provider_name;
 	platform_set_drvdata(pdev, pdata);
 
 	pbi->platform_dev = pdev;
 	pbi->video_signal_type = 0;
 	pbi->m_ins_flag = 1;
-	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_TXLX)
-		pbi->stat |= VP9_TRIGGER_FRAME_ENABLE;
-
-	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
-		pbi->max_pic_w = 8192;
-		pbi->max_pic_h = 4608;
-	} else {
+	if (!vdec_is_support_4k()) {
+		pbi->max_pic_w = 1920;
+		pbi->max_pic_h = 1088;
+	} else if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SM1) {
 		pbi->max_pic_w = 4096;
 		pbi->max_pic_h = 2304;
+	} else {
+		pbi->max_pic_w = 8192;
+		pbi->max_pic_h = 4608;
 	}
-#if 1
+
 	if ((debug & IGNORE_PARAM_FROM_CONFIG) == 0 &&
 			pdata->config_len) {
 #ifdef MULTI_INSTANCE_SUPPORT
@@ -11057,6 +12193,7 @@
 				&config_val) == 0) {
 				pbi->max_pic_h = config_val;
 		}
+
 		if ((pbi->max_pic_w * pbi->max_pic_h)
 			< (vp9_buf_width * vp9_buf_height)) {
 			pbi->max_pic_w = vp9_buf_width;
@@ -11105,6 +12242,8 @@
 		if (get_config_int(pdata->config, "HDRStaticInfo",
 				&vf_dp.present_flag) == 0
 				&& vf_dp.present_flag == 1) {
+			get_config_int(pdata->config, "signal_type",
+					&pbi->video_signal_type);
 			get_config_int(pdata->config, "mG.x",
 					&vf_dp.primaries[0][0]);
 			get_config_int(pdata->config, "mG.y",
@@ -11140,18 +12279,18 @@
 			vp9_print(pbi, 0, "transfer_val=%d\n",transfer_val);
 
 			vf_dp.content_light_level = content_light_level;
-			pbi->video_signal_type = (1 << 29)
+			if (!pbi->video_signal_type) {
+				pbi->video_signal_type = (1 << 29)
 					| (5 << 26)	/* unspecified */
 					| (0 << 25)	/* limit */
 					| (1 << 24)	/* color available */
 					| (9 << 16)	/* 2020 */
 					| (transfer_val << 8)	/* 2084 */
 					| (9 << 0);	/* 2020 */
+			}
 		}
 		pbi->vf_dp = vf_dp;
-	} else
-#endif
-	{
+	} else {
 		if (pdata->sys_info) {
 			pbi->vvp9_amstream_dec_info = *pdata->sys_info;
 			if ((pbi->vvp9_amstream_dec_info.width != 0) &&
@@ -11166,14 +12305,29 @@
 		pbi->double_write_mode = double_write_mode;
 	}
 
+	if (!pbi->is_used_v4l) {
+		vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
+			&vvp9_vf_provider, pbi);
+	}
+
 	if (no_head & 0x10) {
 		pbi->no_head = (no_head & 0xf);
 	}
 
+	pbi->endian = HEVC_CONFIG_LITTLE_ENDIAN;
 	if (!pbi->is_used_v4l) {
 		pbi->mem_map_mode = mem_map_mode;
+		if (is_support_vdec_canvas())
+			pbi->endian = HEVC_CONFIG_BIG_ENDIAN;
 	}
-	pbi->run_ready_min_buf_num = run_ready_min_buf_num;
+	if (endian)
+		pbi->endian = endian;
+
+	if (pbi->is_used_v4l)
+		pbi->run_ready_min_buf_num = run_ready_min_buf_num - 1 ;
+	else
+		pbi->run_ready_min_buf_num = run_ready_min_buf_num;
+
 	if (is_oversize(pbi->max_pic_w, pbi->max_pic_h)) {
 		pr_err("over size: %dx%d, probe failed\n",
 			pbi->max_pic_w, pbi->max_pic_h);
@@ -11190,10 +12344,20 @@
 			pbi->enable_fence, pbi->fence_usage);
 	}
 
-	if (pbi->enable_fence)
-		pdata->sync.usage = pbi->fence_usage;
+	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL ||
+		pbi->double_write_mode == 0x10)
+		pbi->mmu_enable = 0;
+	else
+		pbi->mmu_enable = 1;
 
-	pbi->mmu_enable = 1;
+#ifdef VP9_10B_MMU_DW
+	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T5D) {
+		pbi->dw_mmu_enable =
+			(get_double_write_mode(pbi) & 0x20) ? 1 : 0;
+	} else {
+		pbi->dw_mmu_enable = 0;
+	}
+#endif
 	video_signal_type = pbi->video_signal_type;
 
 	if (pdata->sys_info) {
@@ -11206,8 +12370,8 @@
 
 	pbi->low_latency_flag = 1;
 	vp9_print(pbi, 0,
-			"no_head %d  low_latency %d\n",
-			pbi->no_head, pbi->low_latency_flag);
+			"no_head %d  low_latency %d, signal_type 0x%x\n",
+			pbi->no_head, pbi->low_latency_flag, pbi->video_signal_type);
 #if 0
 	pbi->buf_start = pdata->mem_start;
 	pbi->buf_size = pdata->mem_end - pdata->mem_start + 1;
@@ -11247,8 +12411,27 @@
 	}
 
 	pbi->cma_dev = pdata->cma_dev;
+
+	mutex_init(&pbi->fence_mutex);
+
+	if (pbi->enable_fence) {
+		pdata->sync = vdec_sync_get();
+		if (!pdata->sync) {
+			vp9_print(pbi, 0, "alloc fence timeline error\n");
+			vp9_local_uninit(pbi);
+			uninit_mmu_buffers(pbi);
+			/* devm_kfree(&pdev->dev, (void *)pbi); */
+			vfree((void *)pbi);
+			pdata->dec_status = NULL;
+			return -1;
+		}
+		pdata->sync->usage = pbi->fence_usage;
+		vdec_timeline_create(pdata->sync, DRIVER_NAME);
+	}
+
 	if (vvp9_init(pdata) < 0) {
 		pr_info("\namvdec_vp9 init failed.\n");
+		vdec_timeline_put(pdata->sync);
 		vp9_local_uninit(pbi);
 		uninit_mmu_buffers(pbi);
 		/* devm_kfree(&pdev->dev, (void *)pbi); */
@@ -11276,11 +12459,6 @@
 #endif
 	pbi->pic_list_init_done2 = true;
 
-	if (pbi->enable_fence) {
-		/* creat timeline. */
-		vdec_timeline_create(&pdata->sync, DRIVER_NAME);
-	}
-
 	return 0;
 }
 
@@ -11319,7 +12497,7 @@
 	}
 
 	if (pbi->enable_fence)
-		vdec_fence_release(pbi, &vdec->sync);
+		vdec_fence_release(pbi, vdec->sync);
 
 #ifdef DEBUG_PTS
 	pr_info("pts missed %ld, pts hit %ld, duration %d\n",
@@ -11328,6 +12506,8 @@
 	mem_map_mode = 0;
 
 	/* devm_kfree(&pdev->dev, (void *)pbi); */
+	if (is_rdma_enable())
+		dma_free_coherent(amports_get_dma_device(), RDMA_SIZE, pbi->rdma_adr, pbi->rdma_phy_adr);
 	vfree((void *)pbi);
 	return 0;
 }
@@ -11335,11 +12515,12 @@
 static struct platform_driver ammvdec_vp9_driver = {
 	.probe = ammvdec_vp9_probe,
 	.remove = ammvdec_vp9_remove,
+#ifdef CONFIG_PM
+	.suspend = amhevc_suspend,
+	.resume = amhevc_resume,
+#endif
 	.driver = {
 		.name = MULTI_DRIVER_NAME,
-#ifdef CONFIG_PM
-		.pm = &vp9_pm_ops,
-#endif
 	}
 };
 #endif
@@ -11361,8 +12542,6 @@
 	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),
@@ -11388,13 +12567,20 @@
 
 	struct BuffInfo_s *p_buf_info;
 
-	if (vdec_is_support_4k()) {
-		if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)
-			p_buf_info = &amvvp9_workbuff_spec[2];
+	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 = &amvvp9_workbuff_spec[2];
+			else
+				p_buf_info = &amvvp9_workbuff_spec[1];
+		} else
+			p_buf_info = &amvvp9_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 = &amvvp9_workbuff_spec[5];
 		else
-			p_buf_info = &amvvp9_workbuff_spec[1];
-	} else
-		p_buf_info = &amvvp9_workbuff_spec[0];
+			p_buf_info = &amvvp9_workbuff_spec[4];
+	}
 
 	init_buff_spec(NULL, p_buf_info);
 	work_buf_size =
@@ -11424,20 +12610,21 @@
 		return -ENODEV;
 	}
 
-	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
-		amvdec_vp9_profile.profile =
-				"8k, 10bit, dwrite, compressed, fence";
-	} else if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL
-		/*&& get_cpu_major_id() != MESON_CPU_MAJOR_ID_GXLX*/
-		&& get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TXL) {
-			if (vdec_is_support_4k())
-				amvdec_vp9_profile.profile =
-					"4k, 10bit, dwrite, compressed, fence";
-			else
-				amvdec_vp9_profile.profile =
-					"10bit, dwrite, compressed, fence";
-	} else {
+	if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL ||
+		get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_TXL ||
+		get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5) {
 		amvdec_vp9_profile.name = "vp9_unsupport";
+	} else if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+		(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5D)) {
+		amvdec_vp9_profile.profile =
+			"8k, 10bit, dwrite, compressed, fence, v4l-uvm";
+	} else {
+		if (vdec_is_support_4k())
+			amvdec_vp9_profile.profile =
+				"4k, 10bit, dwrite, compressed, fence, v4l-uvm";
+		else
+			amvdec_vp9_profile.profile =
+				"10bit, dwrite, compressed, fence, v4l-uvm";
 	}
 
 	if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
@@ -11449,6 +12636,7 @@
 	vcodec_profile_register(&amvdec_vp9_profile_mult);
 	INIT_REG_NODE_CONFIGS("media.decoder", &vp9_node,
 		"vp9", vp9_configs, CONFIG_FOR_RW);
+	vcodec_feature_register(VFORMAT_VP9, 0);
 
 	return 0;
 }
@@ -11518,12 +12706,6 @@
 module_param(error_handle_policy, uint, 0664);
 MODULE_PARM_DESC(error_handle_policy, "\n amvdec_vp9 error_handle_policy\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");
 
@@ -11647,6 +12829,9 @@
 module_param(force_pts_unstable, uint, 0664);
 MODULE_PARM_DESC(force_pts_unstable, "\n force_pts_unstable\n");
 
+module_param(v4l_bitstream_id_enable, uint, 0664);
+MODULE_PARM_DESC(v4l_bitstream_id_enable, "\n v4l_bitstream_id_enable\n");
+
 module_init(amvdec_vp9_driver_init_module);
 module_exit(amvdec_vp9_driver_remove_module);
 
diff --git a/drivers/frame_provider/decoder_v4l/Makefile b/drivers/frame_provider/decoder_v4l/Makefile
new file mode 100644
index 0000000..43e94df
--- /dev/null
+++ b/drivers/frame_provider/decoder_v4l/Makefile
@@ -0,0 +1,9 @@
+obj-y	+=	mpeg12/
+obj-y	+=	mpeg4/
+obj-y	+=	h264_multi/
+obj-y	+=	h265/
+obj-y	+=	vp9/
+obj-y	+=	mjpeg/
+obj-y	+=	avs2/
+obj-y	+=	avs_multi/
+obj-y	+=	vav1/
diff --git a/drivers/frame_provider/decoder_v4l/avs2/Makefile b/drivers/frame_provider/decoder_v4l/avs2/Makefile
new file mode 100644
index 0000000..9995065
--- /dev/null
+++ b/drivers/frame_provider/decoder_v4l/avs2/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_AVS2) += amvdec_avs2_v4l.o
+amvdec_avs2_v4l-objs += vavs2.o avs2_bufmgr.o
diff --git a/drivers/frame_provider/decoder_v4l/avs2/avs2_bufmgr.c b/drivers/frame_provider/decoder_v4l/avs2/avs2_bufmgr.c
new file mode 100644
index 0000000..91c3132
--- /dev/null
+++ b/drivers/frame_provider/decoder_v4l/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 "../../decoder/utils/decoder_mmu_box.h"
+#include "../../decoder/utils/decoder_bmmu_box.h"
+#include "avs2_global.h"
+
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../../decoder/utils/vdec.h"
+#include "../../decoder/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_v4l/avs2/avs2_global.h b/drivers/frame_provider/decoder_v4l/avs2/avs2_global.h
new file mode 100644
index 0000000..d9f85bd
--- /dev/null
+++ b/drivers/frame_provider/decoder_v4l/avs2/avs2_global.h
@@ -0,0 +1,1687 @@
+/* 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;
+	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_v4l/avs2/vavs2.c b/drivers/frame_provider/decoder_v4l/avs2/vavs2.c
new file mode 100644
index 0000000..ce5ffde
--- /dev/null
+++ b/drivers/frame_provider/decoder_v4l/avs2/vavs2.c
@@ -0,0 +1,8375 @@
+ /*
+ * 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 "../../decoder/utils/decoder_mmu_box.h"
+#include "../../decoder/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 "../../decoder/utils/vdec.h"
+#include "../../decoder/utils/amvdec.h"
+
+#include <linux/amlogic/media/video_sink/video.h>
+#include <linux/amlogic/media/codec_mm/configs.h>
+#include "../../decoder/utils/config_parser.h"
+#include "../../decoder/utils/firmware.h"
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+#include "../../decoder/utils/vdec_feature.h"
+
+
+#define I_ONLY_SUPPORT
+#define MIX_STREAM_SUPPORT
+#define G12A_BRINGUP_DEBUG
+#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
+
+
+/*
+ * 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_v4l"
+
+#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];
+
+#ifdef G12A_BRINGUP_DEBUG
+static u32 decode_timeout_val = 200;
+#else
+static u32 decode_timeout_val = 200;
+#endif
+static int start_decode_buf_level = 0x8000;
+#ifdef AVS2_10B_MMU
+static u32 work_buf_size; /* = 24 * 1024 * 1024*/;
+#else
+static u32 work_buf_size = 32 * 1024 * 1024;
+#endif
+
+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_v4l"
+#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 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
+
+
+//#ifdef AVS2_10B_MMU
+//#define MMU_COMPRESS_HEADER_SIZE  0x48000
+//#define MMU_COMPRESS_8K_HEADER_SIZE  0x48000*4
+//#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*/
+#undef MV_USE_FIXED_BUF
+#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)
+#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
+	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;
+	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;
+
+	u32 cuva_size;
+	void *cuva_addr;
+	dma_addr_t cuva_phy_addr;
+
+#if 1
+	/*AVS2_10B_MMU*/
+	void *frame_mmu_map_addr;
+	dma_addr_t 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];
+	atomic_t vf_pre_count;
+	atomic_t vf_get_count;
+	atomic_t 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)
+{
+	return (dec->m_ins_flag &&
+		((double_write_mode & 0x80000000) == 0)) ?
+		dec->double_write_mode :
+		(double_write_mode & 0x7fffffff);
+}
+
+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;
+#ifdef DYNAMIC_ALLOC_HEAD
+	unsigned long buf_addr;
+	struct avs2_frame_s *pic = dec->avs2_dec.hc.cur_pic;
+	if (pic->header_adr == 0) {
+		if (decoder_bmmu_box_alloc_buf_phy
+				(dec->bmmu_box,
+				HEADER_BUFFER_IDX(cur_buf_idx),
+				get_compress_header_size(dec),
+				DRIVER_HEADER_NAME,
+				&buf_addr) < 0){
+			avs2_print(dec, 0,
+				"%s malloc compress header failed %d\n",
+				DRIVER_HEADER_NAME, cur_buf_idx);
+			dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM;
+			return -1;
+		} else
+			pic->header_adr = buf_addr;
+	}
+#endif
+
+	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
+
+#if 0
+/*ndef MV_USE_FIXED_BUF*/
+static void dealloc_mv_bufs(struct AVS2Decoder_s *dec)
+{
+	int i;
+	for (i = 0; i < FRAME_BUFFERS; i++) {
+		if (dec->m_mv_BUF[i].start_adr) {
+			if (debug)
+				pr_info(
+				"dealloc mv buf(%d) adr %ld size 0x%x used_flag %d\n",
+				i, dec->m_mv_BUF[i].start_adr,
+				dec->m_mv_BUF[i].size,
+				dec->m_mv_BUF[i].used_flag);
+			decoder_bmmu_box_free_idx(
+				dec->bmmu_box,
+				MV_BUFFER_IDX(i));
+			dec->m_mv_BUF[i].start_adr = 0;
+			dec->m_mv_BUF[i].size = 0;
+			dec->m_mv_BUF[i].used_flag = 0;
+		}
+	}
+}
+
+static int alloc_mv_buf(struct AVS2Decoder_s *dec,
+	int i, int size)
+{
+	int ret = 0;
+	if (decoder_bmmu_box_alloc_buf_phy
+		(dec->bmmu_box,
+		MV_BUFFER_IDX(i), size,
+		DRIVER_NAME,
+		&dec->m_mv_BUF[i].start_adr) < 0) {
+		dec->m_mv_BUF[i].start_adr = 0;
+		ret = -1;
+	} else {
+		dec->m_mv_BUF[i].size = size;
+		dec->m_mv_BUF[i].used_flag = 0;
+		ret = 0;
+		if (debug) {
+			pr_info(
+			"MV Buffer %d: start_adr %p size %x\n",
+			i,
+			(void *)dec->m_mv_BUF[i].start_adr,
+			dec->m_mv_BUF[i].size);
+		}
+	}
+	return ret;
+}
+
+static int init_mv_buf_list(struct AVS2Decoder_s *dec)
+{
+	int i;
+	int ret = 0;
+	int count = FRAME_BUFFERS;
+	int pic_width = dec->init_pic_w;
+	int pic_height = dec->init_pic_h;
+	int lcu_size = 64; /*fixed 64*/
+	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;
+	int size = ((lcu_total * MV_MEM_UNIT) + 0xffff) &
+		(~0xffff);
+	if (mv_buf_margin > 0)
+		count = dec->avs2_dec.ref_maxbuffer + mv_buf_margin;
+	for (i = 0; i < count; i++) {
+		if (alloc_mv_buf(dec, i, size) < 0) {
+			ret = -1;
+			break;
+		}
+	}
+	return ret;
+}
+#if 0
+
+static int get_mv_buf(struct AVS2Decoder_s *dec,
+				struct avs2_frame_s *pic)
+{
+	int i;
+	int ret = -1;
+	for (i = 0; i < FRAME_BUFFERS; i++) {
+		if (dec->m_mv_BUF[i].start_adr &&
+			dec->m_mv_BUF[i].used_flag == 0) {
+			dec->m_mv_BUF[i].used_flag = 1;
+			ret = i;
+			break;
+		}
+	}
+
+	if (ret >= 0) {
+		pic->mv_buf_index = ret;
+		pic->mpred_mv_wr_start_addr =
+			(dec->m_mv_BUF[ret].start_adr + 0xffff) &
+			(~0xffff);
+		if (debug & AVS2_DBG_BUFMGR_MORE)
+			pr_info(
+			"%s => %d (%d) size 0x%x\n",
+			__func__, ret,
+			pic->mpred_mv_wr_start_addr,
+			dec->m_mv_BUF[ret].size);
+	} else {
+		pr_info(
+		"%s: Error, mv buf is not enough\n",
+		__func__);
+	}
+	return ret;
+}
+
+static void put_mv_buf(struct AVS2Decoder_s *dec,
+				struct avs2_frame_s *pic)
+{
+	int i = pic->mv_buf_index;
+	if (i >= FRAME_BUFFERS) {
+		if (debug & AVS2_DBG_BUFMGR_MORE)
+			pr_info(
+			"%s: index %d beyond range\n",
+			__func__, i);
+		return;
+	}
+	if (debug & AVS2_DBG_BUFMGR_MORE)
+		pr_info(
+		"%s(%d): used_flag(%d)\n",
+		__func__, i,
+		dec->m_mv_BUF[i].used_flag);
+
+	pic->mv_buf_index = -1;
+	if (dec->m_mv_BUF[i].start_adr &&
+		dec->m_mv_BUF[i].used_flag)
+		dec->m_mv_BUF[i].used_flag = 0;
+}
+
+static void	put_un_used_mv_bufs(struct AVS2Decoder_s *dec)
+{
+	struct VP9_Common_s *const cm = &dec->common;
+	struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
+	int i;
+	for (i = 0; i < dec->used_buf_num; ++i) {
+		if ((frame_bufs[i].ref_count == 0) &&
+			(frame_bufs[i].buf.index != -1) &&
+			(frame_bufs[i].buf.mv_buf_index >= 0)
+			)
+			put_mv_buf(dec, &frame_bufs[i].buf);
+	}
+}
+#endif
+
+#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 debug;
+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 HEVC_SCALELUT             HEVC_ASSIST_SCRATCH_D
+#define AVS2_CUVA_ADR             HEVC_ASSIST_SCRATCH_A
+#define AVS2_CUVA_DATA_SIZE       HEVC_ASSIST_SCRATCH_B
+
+#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 = 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 = 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
+		.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
+		.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
+		.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);
+	buf_spec->mpred_above.buf_start =
+		WORKBUF_ALIGN(buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size);
+#else
+	buf_spec->mpred_above.buf_start =
+		WORKBUF_ALIGN(buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size);
+#endif
+#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
+			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)
+{
+#if 0
+/*ndef MV_USE_FIXED_BUF*/
+	dealloc_mv_bufs(dec);
+#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;
+#ifndef AVS2_10B_MMU
+		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);
+#endif
+	}
+	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;
+#if 0
+	int32_t MV_MEM_UNIT =
+		(lcu_size_log2 == 6) ? 0x200 :
+		((lcu_size_log2 == 5) ? 0x80 : 0x20);
+#endif
+#ifdef MV_USE_FIXED_BUF
+	u32 mpred_mv_end = dec->work_space_buf->mpred_mv.buf_start +
+			dec->work_space_buf->mpred_mv.buf_size;
+#endif
+	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) {
+		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;
+#ifndef AVS2_10B_MMU
+	if ((dw_mode & 0x10) == 0)
+		buf_size += (mc_buffer_size_h << 16);
+#endif
+
+#ifdef AVS2_10B_MMU
+#ifndef DYNAMIC_ALLOC_HEAD
+	pic->header_adr = decoder_bmmu_box_get_phy_addr(
+			dec->bmmu_box, HEADER_BUFFER_IDX(pic->index));
+
+	avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+		"buf_size %d, MMU header_adr %d: %ld\n",
+		buf_size, pic->index, pic->header_adr);
+#endif
+#endif
+
+	i = pic->index;
+#ifdef MV_USE_FIXED_BUF
+#ifdef G12A_BRINGUP_DEBUG
+	if (1) {
+#else
+	if ((dec->work_space_buf->mpred_mv.buf_start +
+		(((i + 1) * lcu_total) * MV_MEM_UNIT))
+		<= mpred_mv_end
+	) {
+#endif
+#endif
+#ifndef AVS2_10B_MMU
+		if (debug) {
+			pr_err("start %x  .size=%d\n",
+				dec->mc_buf_spec.buf_start + i * buf_size,
+				buf_size);
+		}
+#endif
+#ifndef AVS2_10B_MMU
+		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;
+#ifndef AVS2_10B_MMU
+			pic->mc_y_adr = y_adr;
+#endif
+			pic->mc_canvas_y = pic->index;
+			pic->mc_canvas_u_v = pic->index;
+#ifndef AVS2_10B_MMU
+			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) {
+				pic->dw_y_adr = y_adr
+#ifndef AVS2_10B_MMU
+				+ (mc_buffer_size_h << 16)
+#endif
+				;
+				pic->dw_u_v_adr = pic->dw_y_adr +
+					((mc_buffer_size_u_v_h << 16) << 1);
+#ifdef AVS2_10B_MMU
+				pic->mc_y_adr = pic->dw_y_adr;
+				pic->mc_u_v_adr = pic->dw_u_v_adr;
+#endif
+			}
+#ifdef MV_USE_FIXED_BUF
+#ifdef G12A_BRINGUP_DEBUG
+			if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) {
+				pic->mpred_mv_wr_start_addr =
+				dec->work_space_buf->mpred_mv.buf_start +
+					(pic->index * 0x120000 * 4);
+			} else {
+				pic->mpred_mv_wr_start_addr =
+				dec->work_space_buf->mpred_mv.buf_start +
+					(pic->index * 0x120000);
+			}
+#else
+			pic->mpred_mv_wr_start_addr =
+			dec->work_space_buf->mpred_mv.buf_start +
+					((pic->index * lcu_total)
+					* MV_MEM_UNIT);
+#endif
+#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;
+		}
+#ifdef MV_USE_FIXED_BUF
+	} else {
+		avs2_print(dec, 0,
+			"mv buffer alloc fail %x > %x\n",
+		dec->work_space_buf->mpred_mv.buf_start +
+		(((i + 1) * lcu_total) * MV_MEM_UNIT),
+		mpred_mv_end);
+	}
+#endif
+	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
+	unsigned long buf_addr1;
+	/*alloc AVS2 compress header first*/
+		if (decoder_bmmu_box_alloc_buf_phy
+				(dec->bmmu_box,
+				HEADER_BUFFER_IDX(-1), get_compress_header_size(dec),
+				DRIVER_HEADER_NAME,
+				&buf_addr1) < 0){
+			avs2_print(dec, 0,
+				"%s malloc compress header failed %d\n",
+				DRIVER_HEADER_NAME, -1);
+			dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM;
+			return;
+		}
+#ifndef DYNAMIC_ALLOC_HEAD
+	for (i = 0; i < dec->used_buf_num; i++) {
+		unsigned long buf_addr;
+		if (decoder_bmmu_box_alloc_buf_phy
+				(dec->bmmu_box,
+				HEADER_BUFFER_IDX(i), get_compress_header_size(dec),
+				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
+#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)) {
+		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
+	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);
+	data32 |= ((dec->endian >> 8) & 0xfff);	/* data32 |= 0x670; Big-Endian per 64-bit */
+	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) == 8 ||
+			get_double_write_mode(dec) == 9) {
+			data32 |= (0xff<<16);
+			WRITE_VREG(HEVC_SAO_CTRL26, 0xf);
+		} else if (get_double_write_mode(dec) == 2 ||
+			get_double_write_mode(dec) == 3)
+			data32 |= (0xff<<16);
+		else if (get_double_write_mode(dec) == 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
+}
+
+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
+	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
+
+	WRITE_VREG(LMEM_DUMP_ADR, (u32)dec->lmem_phy_addr);
+#if 1
+/*MULTI_INSTANCE_SUPPORT*/
+	/*new added in simulation???*/
+	WRITE_VREG(HEVC_MPRED_ABV_START_ADDR, buf_spec->mpred_above.buf_start);
+#endif
+#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 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
+	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 (!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 = 8192;
+		buf_alloc_height = 4608;
+	}
+	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);
+#if 0
+/*ndef MV_USE_FIXED_BUF*/
+	if (init_mv_buf_list(dec) < 0) {
+		pr_err("%s: init_mv_buf_list fail\n", __func__);
+		return -1;
+	}
+#endif
+
+#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_phy_addr = dma_map_single(amports_get_dma_device(),
+		dec->lmem_addr, LMEM_BUF_SIZE, DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(amports_get_dma_device(),
+		dec->lmem_phy_addr)) {
+		pr_err("%s: failed to map lmem buffer\n", __func__);
+		kfree(dec->lmem_addr);
+		dec->lmem_addr = NULL;
+		return -1;
+	}
+*/
+	dec->lmem_ptr = dec->lmem_addr;
+
+
+#ifdef AVS2_10B_MMU
+	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));
+/*	dec->frame_mmu_map_phy_addr = dma_map_single(amports_get_dma_device(),
+	dec->frame_mmu_map_addr, FRAME_MMU_MAP_SIZE, DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(amports_get_dma_device(),
+	dec->frame_mmu_map_phy_addr)) {
+		pr_err("%s: failed to map count_buffer\n", __func__);
+		kfree(dec->frame_mmu_map_addr);
+		dec->frame_mmu_map_addr = NULL;
+		return -1;
+	}*/
+#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;
+
+	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);
+
+	ar = min_t(u32, dec->frame_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_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;
+		}
+		vf->index_disp = atomic_read(&dec->vf_get_count);
+		atomic_add(1, &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));
+	atomic_add(1, &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 = atomic_read(&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)
+		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 1
+		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);
+#endif
+		dec->last_pts = vf->pts;
+
+		if (vf->pts_us64 != 0)
+			dec->last_lookup_pts_us64 = vf->pts_us64;
+
+#if 1
+		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);
+		}
+#endif
+		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;
+#else
+		vf->compBodyAddr = pic->mc_y_adr; /*body adr*/
+		vf->compHeadAddr = pic->mc_y_adr +
+					pic->comp_body_size;
+		/*head adr*/
+#endif
+		}
+		if (pic->double_write_mode) {
+			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;
+		}
+		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) {
+			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);
+	}
+	atomic_add(1, &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->timestamp);
+			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);
+#ifdef DYNAMIC_ALLOC_HEAD
+						decoder_bmmu_box_free_idx(
+							dec->bmmu_box,
+							HEADER_BUFFER_IDX(pic->index));
+						pic->header_adr = 0;
+#endif
+#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
+					}
+					/*
+					decoder_bmmu_box_free_idx(
+						dec->bmmu_box,
+						VF_BUFFER_IDX(pic->index));
+					dec->cma_alloc_addr = 0;*/
+				}
+			}
+		}
+	}
+
+	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
+#ifdef AVS2_10B_MMU
+		if (ret >= 0) {
+			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
+
+#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
+			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->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 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;
+
+#ifdef AVS2_10B_MMU
+	dec->need_cache_size = buf_size * SZ_1M;
+	dec->sc_start_time = get_jiffies_64();
+	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
+	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 struct codec_profile_t amvdec_avs2_profile = {
+	.name = "AVS2-V4L",
+	.profile = ""
+};
+
+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
+		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;
+
+	atomic_set(&dec->vf_pre_count, 0);
+	atomic_set(&dec->vf_get_count, 0);
+	atomic_set(&dec->vf_put_count, 0);
+
+	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 = vmalloc(sizeof(struct AVS2Decoder_s));
+	memset(dec, 0, 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-timestamp", 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 1
+	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
+#endif
+	{
+		/*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 0
+	dec->buf_start = pdata->mem_start;
+	dec->buf_size = pdata->mem_end - pdata->mem_start + 1;
+#else
+	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;
+#endif
+	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 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7)
+		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");
+		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);
+
+	INIT_REG_NODE_CONFIGS("media.decoder", &avs2_node,
+		"avs2-v4l", avs2_configs, CONFIG_FOR_RW);
+	vcodec_feature_register(VFORMAT_AVS2, 1);
+
+	return 0;
+}
+
+static void __exit amvdec_avs2_driver_remove_module(void)
+{
+	pr_debug("amvdec_avs2 module remove.\n");
+	platform_driver_unregister(&ammvdec_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/real/vreal.h b/drivers/frame_provider/decoder_v4l/avs2/vavs2.h
similarity index 68%
copy from drivers/frame_provider/decoder/real/vreal.h
copy to drivers/frame_provider/decoder_v4l/avs2/vavs2.h
index 734cc6f..6b51f61 100644
--- a/drivers/frame_provider/decoder/real/vreal.h
+++ b/drivers/frame_provider/decoder_v4l/avs2/vavs2.h
@@ -1,5 +1,5 @@
 /*
- * drivers/amlogic/amports/vreal.h
+ * drivers/amlogic/amports/vavs2.h
  *
  * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
  *
@@ -13,14 +13,14 @@
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  *
- */
+*/
 
-#ifndef VREAL_H
-#define VREAL_H
+#ifndef VAVS2_H
+#define VAVS2_H
 
-#if 1				/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
-/* TODO: move to register headers */
-#define VPP_VD1_POSTBLEND           (1 << 10)
+#define AVS2_10B_MMU
+#define MV_USE_FIXED_BUF
+
+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
-
-#endif				/* VREAL_H */
diff --git a/drivers/frame_provider/decoder_v4l/avs_multi/Makefile b/drivers/frame_provider/decoder_v4l/avs_multi/Makefile
new file mode 100644
index 0000000..10da3ab
--- /dev/null
+++ b/drivers/frame_provider/decoder_v4l/avs_multi/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_AVS_MULTI) += amvdec_mavs_v4l.o
+amvdec_mavs_v4l-objs += avs_multi.o
diff --git a/drivers/frame_provider/decoder_v4l/avs_multi/avs_multi.c b/drivers/frame_provider/decoder_v4l/avs_multi/avs_multi.c
new file mode 100644
index 0000000..3ad9385
--- /dev/null
+++ b/drivers/frame_provider/decoder_v4l/avs_multi/avs_multi.c
@@ -0,0 +1,5016 @@
+/*
+ * 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 "../../decoder/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 "../../decoder/utils/decoder_mmu_box.h"
+#include "../../decoder/utils/decoder_bmmu_box.h"
+#include "../../decoder/utils/firmware.h"
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+#include <linux/amlogic/tee.h>
+#include "../../decoder/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
+
+#define DRIVER_NAME "ammvdec_avs_v4l"
+
+
+#define MULTI_DRIVER_NAME "ammvdec_avs_v4l"
+
+#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;
+	atomic_t prepare_num;
+	atomic_t put_num;
+	atomic_t peek_num;
+	atomic_t 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);
+	atomic_add(1, &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;
+	atomic_add(1, &hw->peek_num);
+	if (step == 2)
+		return NULL;
+	if (hw->recover_flag)
+		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) {
+			vf->index_disp = atomic_read(&hw->get_num);
+			atomic_add(1, &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) {
+		atomic_add(1, &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
+	SET_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
+	/* V4L2_PIX_FMT_NV21  V4L2_PIX_FMT_NV21M */
+	SET_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->timestamp);
+				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->timestamp);
+				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->timestamp);
+				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-timestamp", 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
+	/* V4L2_PIX_FMT_NV21  V4L2_PIX_FMT_NV21M */
+	SET_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 = "AVS-V4L",
+	.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");
+		return -ENODEV;
+	}
+
+	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-v4l", mavs_configs, CONFIG_FOR_RW);
+	vcodec_feature_register(VFORMAT_AVS, 1);
+	return 0;
+}
+
+
+
+static void __exit ammvdec_avs_driver_remove_module(void)
+{
+	pr_debug("ammvdec_avs module remove.\n");
+
+	platform_driver_unregister(&ammvdec_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(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_v4l/avs_multi/avs_multi.h b/drivers/frame_provider/decoder_v4l/avs_multi/avs_multi.h
new file mode 100644
index 0000000..8922b40
--- /dev/null
+++ b/drivers/frame_provider/decoder_v4l/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_v4l/h264_multi/Makefile b/drivers/frame_provider/decoder_v4l/h264_multi/Makefile
new file mode 100644
index 0000000..48f2c5a
--- /dev/null
+++ b/drivers/frame_provider/decoder_v4l/h264_multi/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_H264_MULTI) += amvdec_mh264_v4l.o
+amvdec_mh264_v4l-objs += vmh264.o h264_dpb.o
diff --git a/drivers/frame_provider/decoder_v4l/h264_multi/h264_dpb.c b/drivers/frame_provider/decoder_v4l/h264_multi/h264_dpb.c
new file mode 100644
index 0000000..8ab097e
--- /dev/null
+++ b/drivers/frame_provider/decoder_v4l/h264_multi/h264_dpb.c
@@ -0,0 +1,6036 @@
+/*
+* 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 "../../decoder/utils/vdec.h"
+#include "../../decoder/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;
+	}
+	if ((fs->frame != NULL) &&
+		((fs->bottom_field != NULL) || (fs->top_field != NULL))) {
+		fs->last_field_timestamp = fs->timestamp;
+		fs->timestamp = p->timestamp;
+	} else {
+		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;
+
+	/*
+	 * When the sei data(dv data) after the PIC done and no flush,
+	 * it is necessary to output a frame of data until
+	 * the number of frames not displayed is greater than the reorder.
+	 */
+	if ((p_H264_Dpb->wait_aux_data_flag) && (!flush_flag)) {
+		int no_output_num = 0;
+
+		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)))
+				no_output_num++;
+		}
+
+		if (no_output_num <= p_H264_Dpb->reorder_output)
+			return 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->buf_alloc_fail)
+		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_v4l/h264_multi/h264_dpb.h b/drivers/frame_provider/decoder_v4l/h264_multi/h264_dpb.h
new file mode 100644
index 0000000..e1d1ab4
--- /dev/null
+++ b/drivers/frame_provider/decoder_v4l/h264_multi/h264_dpb.h
@@ -0,0 +1,1008 @@
+/*
+* 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;
+	u64 last_field_timestamp;
+};
+
+/* #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;
+	/* need wait aux data when there is data after pic done in dv stream */
+	bool wait_aux_data_flag;
+	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/real/vreal.h b/drivers/frame_provider/decoder_v4l/h264_multi/vh264.h
similarity index 63%
copy from drivers/frame_provider/decoder/real/vreal.h
copy to drivers/frame_provider/decoder_v4l/h264_multi/vh264.h
index 734cc6f..6c8e4ad 100644
--- a/drivers/frame_provider/decoder/real/vreal.h
+++ b/drivers/frame_provider/decoder_v4l/h264_multi/vh264.h
@@ -1,7 +1,7 @@
 /*
- * drivers/amlogic/amports/vreal.h
+ * drivers/amlogic/media/frame_provider/decoder/h264/vh264.h
  *
- * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * 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
@@ -15,12 +15,13 @@
  *
  */
 
-#ifndef VREAL_H
-#define VREAL_H
+#ifndef VH264_H
+#define VH264_H
 
-#if 1				/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
-/* TODO: move to register headers */
-#define VPP_VD1_POSTBLEND           (1 << 10)
-#endif
+extern int query_video_status(int type, int *value);
 
-#endif				/* VREAL_H */
+/* extern s32 vh264_init(void); */
+
+extern s32 vh264_release(void);
+
+#endif /* VMPEG4_H */
diff --git a/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c b/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c
new file mode 100644
index 0000000..e513272
--- /dev/null
+++ b/drivers/frame_provider/decoder_v4l/h264_multi/vmh264.c
@@ -0,0 +1,11466 @@
+/*
+ * 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 "../../decoder/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 "../../decoder/utils/vdec.h"
+#include "../../decoder/utils/amvdec.h"
+#include "vh264.h"
+#include "../../../stream_input/amports/streambuf.h"
+#include <linux/delay.h>
+#include <linux/amlogic/media/codec_mm/configs.h>
+#include "../../decoder/utils/decoder_mmu_box.h"
+#include "../../decoder/utils/decoder_bmmu_box.h"
+#include "../../decoder/utils/firmware.h"
+#include <linux/uaccess.h>
+#include "../../decoder/utils/config_parser.h"
+#include "../../../common/chips/decoder_cpu_ver_info.h"
+#include "../../decoder/utils/vdec_v4l2_buffer_ops.h"
+#include <linux/crc32.h>
+#include <media/v4l2-mem2mem.h>
+#include "../../decoder/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_v4l"
+#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 RATE_5994_FPS  1601   /* 59.94 */
+#define RATE_11990_FPS  800   /* 119.90 */
+#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 unsigned int colocate_old_cal;
+
+#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 = 0x3fCfb6; /*0x1f14*/
+
+static unsigned int v4l_error_policy = 0x8017C3B5; //default
+
+/*
+	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;
+
+static u32 adjust_dpb_size = 13;
+
+#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;
+	int ctx_buf_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
+#define DEC_RESULT_NEED_MORE_BUFFER 10
+
+
+/*
+ *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 7-14,level_idc
+	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);
+static DEFINE_MUTEX(reset_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 seq_info3;
+	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;
+	atomic_t 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;
+	u32 cfg_bitstream_restriction_flag;
+	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;
+	struct mh264_fence_vf_t fence_vf_s;
+	struct mutex fence_mutex;
+	u32 no_decoder_buffer_flag;
+	u32 video_signal_type;
+	bool need_free_aux_data;
+	u32 error_proc_policy;
+	struct trace_decoder_name trace;
+	bool high_bandwidth_flag;
+	bool hevc_enable_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_v4l(struct vdec_s *vdec, int flush_flag);
+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;
+
+	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;
+			}
+		} 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 {
+			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 void vh264_put_video_frame(void *vdec_ctx, struct vframe_s *vf)
+{
+	vh264_vf_put(vf, vdec_ctx);
+}
+
+static void vh264_get_video_frame(void *vdec_ctx, struct vframe_s **vf)
+{
+	*vf = vh264_vf_get(vdec_ctx);
+}
+
+static struct task_ops_s task_dec_ops = {
+	.type		= TASK_TYPE_DEC,
+	.get_vframe	= vh264_get_video_frame,
+	.put_vframe	= vh264_put_video_frame,
+};
+
+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->task->attach(fb->task, &task_dec_ops, hw_to_vdec(hw));
+	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;
+
+		v4l->aux_infos.bind_sei_buffer(v4l, &pic->aux_data_buf,
+			&pic->aux_data_size, &pic->ctx_buf_idx);
+	}
+
+	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;
+		int free_count = 0;
+		int used_count = 0;
+
+		/* trigger to parse head data. */
+		if (!hw->v4l_params_parsed)
+			return 1;
+
+		if (dpb->mDPB.used_size >= dpb->mDPB.size - 1)
+			return 0;
+
+		if (ctx->cap_pool.dec < hw->dpb.mDPB.size) {
+			if (ctx->fb_ops.query(&ctx->fb_ops, &hw->fb_token)) {
+				free_count =
+					v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) + 1;
+			}
+		}
+
+		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) {
+				free_count++;
+			} else if (hw->buffer_spec[i].cma_alloc_addr)
+				used_count++;
+		}
+
+		ATRACE_COUNTER("V_ST_DEC-free_buff_count", free_count);
+		ATRACE_COUNTER("V_ST_DEC-used_buff_count", used_count);
+
+		return free_count >= run_ready_min_buf_num ? 1 : 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->is_used_v4l)
+		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;
+	}
+	if (hw->is_used_v4l && (bForceInterlace == 0) && frame->frame) {
+		bForceInterlace = (frame->frame->mb_aff_frame_flag)?1:0;
+	}
+	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 (hw->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 hw error_proc_policy %x\n",
+		__func__, buffer_index,
+		frame->data_flag & ERROR_FLAG,
+		frame->poc, hw->data_flag & ERROR_FLAG,
+		hw->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 && (atomic_read(&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) || (!v4l2_ctx->vpp_is_need)))
+		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 {
+			if ((i == 0) && (vf_count == 2))
+				vf->timestamp = frame->last_field_timestamp;
+			else
+				vf->timestamp = frame->timestamp;
+			vf->pts = frame->pts;
+			vf->pts_us64 = frame->pts64;
+			if ((i > 0) && v4l2_ctx->second_field_pts_mode) {
+				vf->timestamp = 0;
+			}
+			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
+
+		}
+		if (frame->data_flag & ERROR_FLAG) {
+			vf->frame_type |= V4L2_BUF_FLAG_ERROR;
+		}
+
+		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;
+			}
+		}
+		atomic_add(1, &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->timestamp);
+		ATRACE_COUNTER(hw->trace.disp_q_name, kfifo_len(&hw->display_q));
+		ATRACE_COUNTER(hw->trace.new_q_name, kfifo_len(&hw->newframe_q));
+		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) {
+			if ((hw->buffer_spec[buffer_index].aux_data_size == 0) &&
+				(frame->slice_type == I_SLICE) &&
+				(atomic_read(&hw->vf_pre_count) == 1)) {
+				hw->need_free_aux_data = true;
+			}
+
+			if (hw->need_free_aux_data) {
+				v4l2_ctx->aux_infos.free_one_sei_buffer(v4l2_ctx,
+					&hw->buffer_spec[buffer_index].aux_data_buf,
+					&hw->buffer_spec[buffer_index].aux_data_size,
+					hw->buffer_spec[buffer_index].ctx_buf_idx);
+			} else {
+				if (!hw->discard_dv_data)
+					v4l2_ctx->aux_infos.bind_dv_buffer(v4l2_ctx,
+						&vf->src_fmt.comp_buf,
+						&vf->src_fmt.md_buf);
+				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 {
+					set_meta_data_to_vf(vf, UVM_META_DATA_VF_BASE_INFOS, hw->v4l2_ctx);
+					ATRACE_COUNTER("VC_OUT_DEC-submit", fb->buf_idx);
+					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) {
+		expires = jiffies + msecs_to_jiffies(2000);
+		while (!have_free_buf_spec(vdec)) {
+			if (time_after(jiffies, expires)) {
+				pr_err("[%d] H264 isn't enough buff for notify eos.\n", ctx->id);
+				return 0;
+			}
+		}
+
+		index = v4l_get_free_buf_idx(vdec);
+		if (INVALID_IDX == index) {
+			pr_err("[%d] H264 EOS get free buff fail.\n", ctx->id);
+			return 0;
+		}
+
+		fb = (struct vdec_v4l2_buffer *)
+			hw->buffer_spec[index].cma_alloc_addr;
+
+		vf->type		|= VIDTYPE_V4L_EOS;
+		vf->timestamp		= ULONG_MAX;
+		vf->flag		= VFRAME_FLAG_EMPTY_FRAME_V4L;
+		vf->v4l_mem_handle	= (ulong)fb;
+
+		vdec_vframe_ready(vdec, vf);
+		kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
+
+		ATRACE_COUNTER(hw->trace.pts_name, vf->timestamp);
+
+		ATRACE_COUNTER("VC_OUT_DEC-submit", fb->buf_idx);
+		fb->task->submit(fb->task, TASK_TYPE_DEC);
+
+		pr_info("[%d] H264 EOS notify.\n", ctx->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;
+
+		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;
+			}
+		}
+
+		if (AUX_DATA_BUF(pic)) {
+			unsigned char valid_tag = 0;
+			unsigned char *h =
+				AUX_DATA_BUF(pic) +
+				AUX_DATA_SIZE(pic);
+			unsigned char *p = h + 8;
+			int len = 0;
+			int padding_len = 0;
+			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)
+{
+#if 0
+	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;
+#endif
+}
+
+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, 0);
+	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 && !(hw->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 (hw->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_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;
+	}
+
+	if (vf->meta_data_buf) {
+		vf->meta_data_buf = NULL;
+		vf->meta_data_size = 0;
+	}
+
+	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) {
+			dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
+				"H264 update fb handle, old:%llx, new:%llx\n",
+				pic->cma_alloc_addr, vf->v4l_mem_handle);
+
+				pic->cma_alloc_addr = vf->v4l_mem_handle;
+		}
+	}
+
+	if (vf && (vf_valid_check(vf, hw) == true)) {
+		atomic_add(1, &hw->vf_put_count);
+		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)
+{
+	int endian_tmp;
+	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];
+	vf->canvas1_config[0] = p_canvas_config[0];
+	vf->canvas1_config[1] = p_canvas_config[1];
+#ifndef NV21
+	vf->canvas0_config[2] = p_canvas_config[2];
+	vf->canvas1_config[2] = p_canvas_config[2];
+#endif
+	if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) {
+		endian_tmp = (hw->canvas_mode == CANVAS_BLKMODE_LINEAR) ? 7 : 0;
+	} else {
+		endian_tmp = (hw->canvas_mode == CANVAS_BLKMODE_LINEAR) ? 0 : 7;
+	}
+	vf->canvas0_config[0].endian = endian_tmp;
+	vf->canvas0_config[1].endian = endian_tmp;
+	vf->canvas1_config[0].endian = endian_tmp;
+	vf->canvas1_config[1].endian = endian_tmp;
+#ifndef NV21
+	vf->canvas0_config[2].endian = endian_tmp;
+	vf->canvas1_config[2].endian = endian_tmp;
+#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, int level_idc)
+{
+	struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+	int pic_size = mb_width * mb_height * 384;
+	int size = 0, size_vui;
+
+	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 */
+
+	if (!hw->discard_dv_data)  {
+		size += 1;
+		dpb_print(DECODE_ID(hw), 0, "dv stream need one more buffer.\n");
+	}
+
+	return size;
+}
+
+static int get_dec_dpb_size_active(struct vdec_h264_hw_s *hw, u32 param1, u32 param4)
+{
+	int mb_width, mb_total;
+	int mb_height = 0;
+	int dec_dpb_size;
+	int level_idc = param4 & 0xff;
+
+	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, level_idc);
+
+	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;
+	u32 seq_info3;
+	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;
+	seq_info3 = param4;
+	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->dpb.dec_dpb_size != get_dec_dpb_size_active(hw, param1, param4);
+
+	if (((seq_info2 != 0 &&
+		(hw->seq_info2 & 0x80ffffff) != (param1 & 0x80ffffff)) || dec_dpb_size_change) &&
+		hw->seq_info2 != 0
+		) { /*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;
+			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->cfg_param1 = param1;
+			hw->cfg_bitstream_restriction_flag = hw->bitstream_restriction_flag;
+
+			hw->seq_info2 = seq_info2;
+			hw->seq_info3 = seq_info3;
+
+			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;
+			}
+
+			hw->max_reference_size =
+				max_reference_size + reference_buf_margin;
+
+			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->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->cfg_bitstream_restriction_flag = hw->bitstream_restriction_flag;
+
+		hw->seq_info2 = seq_info2;
+		hw->seq_info3 = seq_info3;
+		dpb_print(DECODE_ID(hw), 0,
+			"AV_SCRATCH_1 = %x, AV_SCRATCH_2 = %x, AV_SCRATCH_B: = %x\n",
+			seq_info2, hw->seq_info, seq_info3);
+
+		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, level_idc);
+		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);
+		}
+
+		if (hw->is_used_v4l) {
+			struct aml_vcodec_ctx *ctx =
+				(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+			struct vdec_pic_info pic;
+
+			vdec_v4l_get_pic_info(ctx, &pic);
+
+			active_buffer_spec_num = pic.dpb_frames +
+				pic.dpb_margin;
+		}
+
+		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)
+				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->is_used_v4l && (p_H264_Dpb->dpb_param.l.data[SLICE_TYPE] == I_Slice) &&
+			(hw->num_units_in_tick != 0)) {
+			if (hw->num_units_in_tick % 1001 == 0) {
+				int multiple = hw->num_units_in_tick / 1001;
+
+				if (hw->time_scale / multiple == 120000) {
+					hw->frame_dur = RATE_11990_FPS;
+					if (hw->fixed_frame_rate_flag == 1)
+						hw->frame_dur = RATE_5994_FPS;
+				} else if (hw->time_scale / multiple ==  60000) {
+					hw->frame_dur = RATE_5994_FPS;
+					if (hw->fixed_frame_rate_flag == 1)
+						hw->frame_dur = RATE_2997_FPS;
+				} else if ((hw->time_scale / multiple  == 48000) &&
+					(hw->fixed_frame_rate_flag == 1)) {
+					hw->frame_dur = RATE_2397_FPS;
+				} else if (hw->time_scale / multiple  == 30000) {
+					hw->frame_dur = RATE_2997_FPS;
+				} else if (hw->time_scale / multiple  == 24000) {
+					hw->frame_dur = RATE_2397_FPS;
+				}
+			} else {
+				u32 frame_rate = hw->time_scale / hw->num_units_in_tick;
+
+				if (hw->fixed_frame_rate_flag == 1) {
+					frame_rate = frame_rate / 2;
+				}
+				hw->frame_dur = 96000 / frame_rate;
+			}
+		}
+
+		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 (hw->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 ((hw->error_proc_policy & 0x4) &&
+			(hw->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 ((hw->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))) &&
+			(hw->discard_dv_data)) {
+			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 ((hw->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 ((hw->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 ((hw->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)
+				&& (hw->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 (hw->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;
+				}
+			}
+			p_H264_Dpb->wait_aux_data_flag = ((!hw->discard_dv_data) && (hw->frmbase_cont_flag));
+				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));
+		}
+		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 ((hw->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 ((hw->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 (slice_header_process_status == -1) {
+			amvdec_stop();
+			hw->dec_result = DEC_RESULT_DONE;
+			vdec_schedule_work(&hw->work);
+			return IRQ_HANDLED;
+		}
+
+		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 (hw->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 (!(hw->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 (hw->error_proc_policy & 0x400) {
+				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 (((hw->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 ((hw->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 ((hw->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 (hw->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) {
+			bufmgr_h264_remove_unused_frame(p_H264_Dpb, 0);
+			if (!have_free_buf_spec(vdec)) {
+				hw->dec_result = DEC_RESULT_NEED_MORE_BUFFER;
+				vdec_schedule_work(&hw->work);
+				return IRQ_HANDLED;
+			}
+			/*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 ((hw->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 (hw->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 (hw->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));
+
+	ATRACE_COUNTER("V_ST_DEC-decode_state", p_H264_Dpb->dec_dpb_status);
+
+	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 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 (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) {
+		if ((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))
+			CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
+		else
+			SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
+	} else {
+		if ((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->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 (hw->error_proc_policy & 0x80000000)
+		hw->send_error_frame_flag = hw->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
+	struct aml_vcodec_ctx *ctx =
+		(struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+	struct vdec_pic_info pic;
+	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;
+	hw->dpb.mSPS.level_idc = level_idc;
+
+#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, level_idc);
+
+	dpb_print(DECODE_ID(hw), 0,
+		"v4l restriction:%d, max buffering:%d, DPB size:%d, reorder frames:%d, 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_margin		= used_reorder_dpb_size_margin;
+	ps->dpb_size		= active_buffer_spec_num;
+	ps->field = frame_mbs_only_flag ?
+		V4L2_FIELD_NONE : V4L2_FIELD_INTERLACED;
+
+	/* update reoder and margin num. */
+	if (hw->res_ch_flag) {
+		vdec_v4l_get_pic_info(ctx, &pic);
+		ps->dpb_frames = pic.dpb_frames;
+		ps->dpb_margin = pic.dpb_margin;
+	}
+
+	if ((ps->dpb_frames >= 16) && (ps->coded_width > 1280) &&
+		(ps->coded_height > 768)) {
+		if (ps->field == V4L2_FIELD_NONE) {
+			ps->dpb_frames = adjust_dpb_size;
+		} else {
+			ps->dpb_frames = adjust_dpb_size - 2;
+		}
+	}
+
+	dpb_print(DECODE_ID(hw), 0,
+		"Res:%dx%d, DPB size:%d, margin:%d, scan:%s\n",
+		ps->visible_width, ps->visible_height,
+		ps->dpb_frames, ps->dpb_margin,
+		(ps->field == V4L2_FIELD_NONE) ? "P" : "I");
+
+	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->dpb.dec_dpb_size != get_dec_dpb_size_active(hw, param1, param4);
+
+	if (ctx->param_sets_from_ucode &&
+			hw->res_ch_flag == 0) {
+		if (((param1 != 0 &&
+		(hw->seq_info2 & 0x80ffffff) != (param1 & 0x80ffffff)) || dec_dpb_size_change)  &&
+			hw->seq_info2 != 0) { /*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;
+				hw->bitstream_restriction_flag = hw->cfg_bitstream_restriction_flag; // restore the old value when v4l res change
+				amvdec_stop();
+				if (hw->mmu_enable)
+					amhevc_stop();
+				hw->eos = 1;
+				flush_dpb(p_H264_Dpb);
+				//del_timer_sync(&hw->check_timer);
+				ATRACE_COUNTER("V_ST_DEC-submit_eos", __LINE__);
+				notify_v4l_eos(hw_to_vdec(hw));
+				ATRACE_COUNTER("V_ST_DEC-submit_eos", 0);
+				ret = 1;
+		}
+	}
+
+	return ret;
+
+}
+
+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));
+
+	ATRACE_COUNTER("V_ST_DEC-work_state", hw->dec_result);
+
+	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();
+					ATRACE_COUNTER(hw->trace.decode_time_name, DECODER_WORKER_START);
+				} 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; */
+		if ((hw->dec_result == DEC_RESULT_TIMEOUT) &&
+				!hw->i_only && (hw->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 (hw->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;
+		}
+		amvdec_stop();
+		if (hw->mmu_enable)
+			amhevc_stop();
+		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);
+		if (hw->is_used_v4l) {
+			ATRACE_COUNTER("V_ST_DEC-submit_eos", __LINE__);
+			notify_v4l_eos(hw_to_vdec(hw));
+			ATRACE_COUNTER("V_ST_DEC-submit_eos", 0);
+		}
+		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;
+		}
+	} else if (hw->dec_result == DEC_RESULT_NEED_MORE_BUFFER) {
+		struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
+		bufmgr_h264_remove_unused_frame(p_H264_Dpb, 0);
+		if (!have_free_buf_spec(vdec)) {
+			if (vdec->next_status == VDEC_STATUS_DISCONNECTED)
+				hw->dec_result = DEC_RESULT_AGAIN;
+			else
+				hw->dec_result = DEC_RESULT_NEED_MORE_BUFFER;
+			vdec_schedule_work(&hw->work);
+		} else {
+			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;
+	}
+
+	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 (vd