Project import generated by Copybara.
GitOrigin-RevId: a13be63c5ff99e1fd1c223991f26f4265e6fef3e
diff --git a/Makefile b/Makefile
old mode 100755
new mode 100644
index 7481eee..6640ff9
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,3 @@
-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 \
@@ -18,25 +15,21 @@
CONFIG_AMLOGIC_MEDIA_VDEC_AVS=m \
CONFIG_AMLOGIC_MEDIA_VDEC_AVS_MULTI=m \
CONFIG_AMLOGIC_MEDIA_VDEC_AVS2=m \
- CONFIG_AMLOGIC_MEDIA_VENC_H264=m \
- CONFIG_AMLOGIC_MEDIA_VENC_H265=m \
CONFIG_AMLOGIC_MEDIA_VDEC_AV1=m \
- CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y \
- CONFIG_AMLOGIC_MEDIA_GE2D=y \
- CONFIG_AMLOGIC_MEDIA_VENC_MULTI=m \
- CONFIG_AMLOGIC_MEDIA_VENC_JPEG=m
+ CONFIG_AMLOGIC_MEDIA_VENC_H264=m \
+ CONFIG_AMLOGIC_MEDIA_VENC_JPEG=m \
+ CONFIG_AMLOGIC_MEDIA_VENC_H265=m
+
EXTRA_INCLUDE := -I$(KERNEL_SRC)/$(M)/drivers/include
CONFIGS_BUILD := -Wno-parentheses-equality -Wno-pointer-bool-conversion \
-Wno-unused-const-variable -Wno-typedef-redefinition \
- -Wno-logical-not-parentheses -Wno-sometimes-uninitialized \
- -Wno-frame-larger-than=
+ -Wno-logical-not-parentheses -Wno-sometimes-uninitialized
-KBUILD_CFLAGS_MODULE += $(GKI_EXT_MODULE_PREDEFINE)
modules:
- $(MAKE) -C $(KERNEL_SRC) M=$(M)/drivers modules "EXTRA_CFLAGS+=-I$(INCLUDE) -Wno-error $(CONFIGS_BUILD) $(EXTRA_INCLUDE) $(KBUILD_CFLAGS_MODULE) ${VERSION_CONTROL_CFLAGS}" $(CONFIGS)
+ $(MAKE) -C $(KERNEL_SRC) M=$(M)/drivers modules "EXTRA_CFLAGS+=-I$(INCLUDE) -Wno-error $(CONFIGS_BUILD) $(EXTRA_INCLUDE)" $(CONFIGS)
all: modules
diff --git a/Media.mk b/Media.mk
index 58db63b..68b0778 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_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y \
- CONFIG_AMLOGIC_MEDIA_GE2D=y \
- CONFIG_AMLOGIC_MEDIA_VENC_MULTI=m \
- CONFIG_AMLOGIC_MEDIA_VENC_JPEG=m
+ CONFIG_FRAME_WARN=4096
define copy-media-modules
$(foreach m, $(shell find $(strip $(1)) -name "*.ko"),\
@@ -63,10 +63,11 @@
$(shell cp $(MEDIA_DRIVERS)/* $(MEDIA_MODULES) -rfa)
define media-modules
- PATH=$(KERNEL_TOOLPATHS):$$PATH \
- $(MAKE) -C $(KDIR) M=$(MEDIA_MODULES) $(KERNEL_ARGS) $(CONFIGS) \
- "EXTRA_CFLAGS+=-I$(INCLUDE) -Wno-error" modules; \
- find $(MEDIA_MODULES) -name "*.ko" | PATH=$$(cd ./$(TARGET_HOST_TOOL_PATH); pwd):$$PATH xargs -i cp {} $(MODS_OUT)
+ 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)
endef
else
@@ -90,10 +91,18 @@
$(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=$(KERNEL_TOOLPATHS):$$PATH \
- $(MAKE) -C $(KDIR) M=$(MEDIA_DRIVERS) ARCH=$(KERNEL_ARCH) $(KERNEL_ARGS) $(CONFIGS) \
- EXTRA_CFLAGS+=-I$(INCLUDE) -j64
+ 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
copy-modules:
@echo "start copying media modules."
@@ -102,9 +111,8 @@
all: modules copy-modules
-
clean:
- PATH=$(KERNEL_TOOLPATHS):$$PATH \
- $(MAKE) -C $(KDIR) M=$(MEDIA_DRIVERS) $(KERNEL_ARGS) clean
+ PATH=$$(cd ./$(TARGET_HOST_TOOL_PATH); pwd):$$PATH \
+ $(MAKE) -C $(KDIR) M=$(MEDIA_DRIVERS) ARCH=$(KERNEL_ARCH) clean
endif
diff --git a/VERSION b/VERSION
deleted file mode 100644
index 4b1504d..0000000
--- a/VERSION
+++ /dev/null
@@ -1,76 +0,0 @@
-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
new file mode 100755
index 0000000..63eaf1a
--- /dev/null
+++ b/build_media.sh
@@ -0,0 +1,105 @@
+#!/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 e96ba44..3e487db 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 2e7cff4..6395adf 100644
--- a/drivers/amvdec_ports/Makefile
+++ b/drivers/amvdec_ports/Makefile
@@ -3,10 +3,8 @@
amvdec_ports-objs += aml_vcodec_dec.o
amvdec_ports-objs += aml_vcodec_util.o
amvdec_ports-objs += aml_vcodec_adapt.o
-amvdec_ports-objs += aml_vcodec_vpp.o
-amvdec_ports-objs += aml_vcodec_ge2d.o
+amvdec_ports-objs += aml_vcodec_vfm.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
deleted file mode 100644
index 8dfe014..0000000
--- a/drivers/amvdec_ports/aml_task_chain.c
+++ /dev/null
@@ -1,365 +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/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
deleted file mode 100644
index fdbe2fb..0000000
--- a/drivers/amvdec_ports/aml_task_chain.h
+++ /dev/null
@@ -1,125 +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_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 7e08371..95ee48a 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.c
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.c
@@ -56,11 +56,17 @@
//#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,
@@ -167,6 +173,60 @@
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];
@@ -177,14 +237,41 @@
pubuf->buf_rp = 0;
}
-static void video_component_release(struct stream_port_s *port)
+static void video_component_release(struct stream_port_s *port,
+struct stream_buf_s *pbuf, int release_num)
{
struct aml_vdec_adapt *ada_ctx
= container_of(port, struct aml_vdec_adapt, port);
struct vdec_s *vdec = ada_ctx->vdec;
- vdec_release(vdec);
+ struct vdec_s *slave = NULL;
+ 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,
@@ -204,21 +291,69 @@
|| 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 ||
- (port->type & PORT_TYPE_ES)) {
- ret = vdec_init(vdec, port->is_4k, true);
+ if (port->type & PORT_TYPE_FRAME) {
+ ret = vdec_init(vdec, port->is_4k);
if (ret < 0) {
v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "failed\n");
- video_component_release(port);
+ 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);
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;
}
@@ -227,8 +362,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];
}
@@ -241,7 +376,7 @@
psparser_release();
if (port->type & PORT_TYPE_VIDEO)
- video_component_release(port);
+ video_component_release(port, pvbuf, 0);
port->pcr_inited = 0;
port->flag = 0;
@@ -256,6 +391,7 @@
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;
@@ -289,6 +425,7 @@
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;
@@ -308,7 +445,6 @@
if (IS_ERR_OR_NULL(vdec))
return -1;
- vdec->disable_vfm = true;
set_vdec_properity(vdec, ada_ctx);
/* init hw and gate*/
@@ -325,8 +461,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];
}
@@ -390,11 +526,9 @@
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)
{
@@ -445,11 +579,11 @@
{
struct vdec_s *vdec = ada_ctx->vdec;
- return (vdec->input.have_frame_num > 60) ? true : false;
+ return (vdec->input.have_frame_num > 600) ? true : false;
}
int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx,
- const char *buf, unsigned int count, u64 timestamp, ulong meta_ptr)
+ const char *buf, unsigned int count, u64 timestamp)
{
int ret = -1;
struct vdec_s *vdec = ada_ctx->vdec;
@@ -457,9 +591,6 @@
/* 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) {
@@ -468,12 +599,9 @@
msleep(30);
}
- if (dump_output_frame > 0 &&
- (!dump_output_start_position ||
- (dump_output_start_position == crc32_le(0, buf, count)))) {
+ if (dump_output_frame > 0) {
dump("/data/es.data", buf, count);
dump_output_frame--;
- dump_output_start_position = 0;
}
v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_INPUT,
@@ -530,14 +658,23 @@
int ret = 0;
if (vdec) {
- if (ada_ctx->ctx->v4l_resolution_change)
- *mode = V4L_RESET_MODE_LIGHT;
- else
+ if (!ada_ctx->ctx->q_data[AML_Q_DATA_SRC].resolution_changed)
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, es frames buffering: %d\n",
- *mode, vdec_frame_number(ada_ctx));
+ "reset mode: %d\n", *mode);
ret = vdec_v4l2_reset(vdec, *mode);
*mode = V4L_RESET_MODE_NORMAL;
@@ -572,11 +709,6 @@
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;
@@ -584,8 +716,3 @@
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 c8641ce..b86cbff 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.h
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.h
@@ -27,12 +27,13 @@
#include "aml_vcodec_drv.h"
struct aml_vdec_adapt {
- int format;
+ enum vformat_e 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;
@@ -40,7 +41,8 @@
struct dec_sysinfo dec_prop;
struct v4l2_config_parm config;
int video_type;
- char *frm_name;
+ char *recv_name;
+ int vfm_path;
};
int video_decoder_init(struct aml_vdec_adapt *ada_ctx);
@@ -51,7 +53,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, ulong meta_ptr);
+ const char *buf, unsigned int count, u64 timestamp);
void vdec_vframe_input_free(void *priv, u32 handle);
@@ -71,9 +73,5 @@
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 2bbfb6e..afebb7a 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec.c
@@ -20,41 +20,27 @@
#include <media/v4l2-event.h>
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-dma-contig.h>
-#include <media/videobuf2-dma-sg.h>
-
-#include <linux/delay.h>
-#include <linux/atomic.h>
-#include <linux/crc32.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/amlogic/meson_uvm_core.h>
-#include <linux/scatterlist.h>
-#include <linux/sched/clock.h>
-#include <linux/highmem.h>
-#include <uapi/linux/sched/types.h>
#include "aml_vcodec_drv.h"
#include "aml_vcodec_dec.h"
+//#include "aml_vcodec_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 "aml_vcodec_vpp.h"
-#include "aml_vcodec_ge2d.h"
+#include <linux/spinlock.h>
+#include "aml_vcodec_vfm.h"
#include "../frame_provider/decoder/utils/decoder_bmmu_box.h"
#include "../frame_provider/decoder/utils/decoder_mmu_box.h"
-#include "../common/chips/decoder_cpu_ver_info.h"
-#include "utils/common.h"
-#include "../frame_provider/decoder/utils/vdec_sync.h"
-
#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2
#include <trace/events/meson_atrace.h>
-
-#define OUT_FMT_IDX (0) //default h264
-#define CAP_FMT_IDX (9) //capture nv21
-#define CAP_FMT_I420_IDX (12) //use for mjpeg
+#define OUT_FMT_IDX 0 //default h264
+#define CAP_FMT_IDX 8 //capture nv21
#define AML_VDEC_MIN_W 64U
#define AML_VDEC_MIN_H 64U
@@ -63,12 +49,8 @@
#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
@@ -80,89 +62,70 @@
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[] = {
@@ -202,11 +165,6 @@
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},
@@ -226,44 +184,16 @@
.stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
},
- {
- .fourcc = V4L2_PIX_FMT_YUV420,
- .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
- AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
- },
- {
- .fourcc = V4L2_PIX_FMT_YUV420M,
- .stepwise = { AML_VDEC_MIN_W, AML_VDEC_MAX_W, 2,
- AML_VDEC_MIN_H, AML_VDEC_MAX_H, 2},
- },
};
#define NUM_SUPPORTED_FRAMESIZE ARRAY_SIZE(aml_vdec_framesizes)
#define NUM_FORMATS ARRAY_SIZE(aml_video_formats)
extern bool multiplanar;
-extern int dump_capture_frame;
-extern int bypass_vpp;
-extern int bypass_ge2d;
-extern bool support_format_I420;
-extern bool support_mjpeg;
-extern int bypass_progressive;
-extern int force_enable_nr;
-extern int force_enable_di_local_buffer;
-extern int max_di_instance;
-extern int bypass_nr_flag;
+extern bool dump_capture_frame;
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)
{
@@ -279,23 +209,6 @@
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;
@@ -323,6 +236,16 @@
{
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:
@@ -354,176 +277,11 @@
aml_decoder_flush(ctx->ada_ctx);
}
-/* Conditions:
- * Always connect VPP for mpeg2 and h264 when the stream size is under 2K.
- * Always connect VPP for hevc/av1/vp9 when color space is not SDR and
- * stream size is under 2K.
- * For DV, need application to notify V4L2 driver to enforce the color space
- * conversion. Plan to do it through a system node.
- * Do not connect VPP in other cases.
- */
-static bool vpp_needed(struct aml_vcodec_ctx *ctx, u32* mode)
+static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx)
{
- int width = ctx->picinfo.coded_width;
- int height = ctx->picinfo.coded_height;
- int size = 1920 * 1088;
+ unsigned int dpbsize = 0;
+ int ret;
- 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");
@@ -551,277 +309,287 @@
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;
+}
- if (ctx->vpp_is_need)
- ctx->vpp_cfg.is_vpp_reset = true;
+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;
- v4l_buf_size_decision(ctx);
+ if (dev == NULL)
+ return false;
- 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));
+ 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;
}
void vdec_frame_buffer_release(void *data)
{
struct file_private_data *priv_data =
(struct file_private_data *) data;
- struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)
- priv_data->v4l_dec_ctx;
- struct aml_video_dec_buf *vb = (struct aml_video_dec_buf *)
+ struct aml_vcodec_dev *dev = (struct aml_vcodec_dev *)
priv_data->vb_handle;
- struct uvm_hook_mod_info *uvm = NULL;
+ struct aml_vcodec_ctx *inst = (struct aml_vcodec_ctx *)
+ priv_data->v4l_dec_ctx;
+ u32 id = priv_data->v4l_inst_id;
- if (ctx && ctx->uvm_proxy) {
- uvm = &ctx->uvm_proxy[vb->internal_index];
- uvm->free(uvm->arg);
+ 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);
+ }
+
}
memset(data, 0, sizeof(struct file_private_data));
kfree(data);
}
-static void v4l2_buff_done(struct vb2_v4l2_buffer *buf, enum vb2_buffer_state state)
+int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_fb)
{
- 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);
- 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;
+ if (ctx->state == AML_STATE_ABORT) {
+ aml_vcodec_ctx_unlock(ctx, flags);
+ return -1;
}
- aml_vcodec_ctx_unlock(ctx, flags);
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "%s done\n", __func__);
-}
-
-static void fb_map_table_hold(struct aml_vcodec_ctx *ctx,
- struct vb2_buffer *vb,
- struct vframe_s *vf,
- struct task_chain_s *task,
- u32 icomp)
-{
- int i;
- ulong addr, flags;
-
- flags = aml_vcodec_ctx_lock(ctx);
-
- addr = vb2_dma_contig_plane_dma_addr(vb, 0);
-
- for (i = 0; i < ARRAY_SIZE(ctx->fb_map); i++) {
- if (!ctx->fb_map[i].addr ||
- (addr == ctx->fb_map[i].addr)) {
- ctx->fb_map[i].task = task;
- ctx->fb_map[i].addr = addr;
- ctx->fb_map[i].vframe = vf;
- ctx->fb_map[i].icomp = icomp;
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
- "%s, task:%px, vf:%px, addr:%lx, icomp:%u\n",
- __func__, task, vf, addr, icomp);
- break;
- }
+ dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+ if (!dst_buf) {
+ aml_vcodec_ctx_unlock(ctx, flags);
+ return -1;
}
- aml_vcodec_ctx_unlock(ctx, flags);
+ 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));
- 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);
- }
-}
+ 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);
-static void fb_map_table_fetch(struct aml_vcodec_ctx *ctx,
- struct vb2_buffer *vb,
- struct vframe_s **vf,
- struct task_chain_s **task,
- u32 *icomp)
-{
- int i;
- ulong addr, flags;
-
- flags = aml_vcodec_ctx_lock(ctx);
-
- addr = vb2_dma_contig_plane_dma_addr(vb, 0);
-
- for (i = 0; i < ARRAY_SIZE(ctx->fb_map); i++) {
- if (addr == ctx->fb_map[i].addr) {
- *task = ctx->fb_map[i].task;
- *vf = ctx->fb_map[i].vframe;
- *icomp = ctx->fb_map[i].icomp;
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
- "%s, task:%px, vf:%px, addr:%lx, icomp:%u\n",
- __func__, task, vf, addr, *icomp);
-
- ctx->fb_map[i].task = NULL;
- ctx->fb_map[i].vframe = NULL;
- ctx->fb_map[i].addr = 0;
- ctx->fb_map[i].icomp = 0;
- break;
- }
- }
-
- aml_vcodec_ctx_unlock(ctx, flags);
-
- if (i >= ARRAY_SIZE(ctx->fb_map)) {
+ 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,
- "%s, there is new addr:%lx.\n",
- __func__, addr);
+ "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);
}
-}
-static bool is_fb_mapped(struct aml_vcodec_ctx *ctx, ulong addr)
-{
- int i;
- ulong flags;
+ dst_buf_info->used = true;
+ ctx->buf_used_count++;
- flags = aml_vcodec_ctx_lock(ctx);
+ *out_fb = pfb;
- for (i = 0; i < ARRAY_SIZE(ctx->fb_map); i++) {
- if (addr == ctx->fb_map[i].addr)
- break;
- }
+ 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);
- 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 0;
+}
+EXPORT_SYMBOL(get_fb_from_queue);
+
+int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *in_fb)
+{
+ struct aml_video_dec_buf *dstbuf;
+
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO, "%s\n", __func__);
+
+ if (in_fb == NULL) {
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "No free frame buffer\n");
+ return -1;
}
- return true;
+ dstbuf = container_of(in_fb, struct aml_video_dec_buf, frame_buffer);
+
+ 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;
+
}
+EXPORT_SYMBOL(put_fb_to_queue);
- static void post_frame_to_upper(struct aml_vcodec_ctx *ctx,
- struct vdec_v4l2_buffer *fb)
+void trans_vframe_to_user(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;
+ struct aml_video_dec_buf *dstbuf = NULL;
+ struct vb2_buffer *vb2_buf = NULL;
+ struct vframe_s *vf = (struct vframe_s *)fb->vf_handle;
v4l_dbg(ctx, V4L_DEBUG_CODEC_OUTPUT,
- "OUT_BUFF (%s, st:%d, seq:%d) vb:(%d, %px), vf:(%d, %px), ts:%lld, "
+ "FROM (%s %s) vf: %lx, ts: %llu, idx: %d, "
"Y:(%lx, %u) C/U:(%lx, %u) V:(%lx, %u)\n",
- ctx->ada_ctx->frm_name, fb->status, vf->index_disp,
- vb2_buf->index, vb2_buf,
- vf->index & 0xff, vf,
- vf->timestamp,
+ 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,
fb->m.mem[0].addr, fb->m.mem[0].size,
fb->m.mem[1].addr, fb->m.mem[1].size,
fb->m.mem[2].addr, fb->m.mem[2].size);
- vb2_v4l2 = container_of(vb2_buf, struct vb2_v4l2_buffer, vb2_buf);
+ dstbuf = container_of(fb, struct aml_video_dec_buf, frame_buffer);
+ vb2_buf = &dstbuf->vb.vb2_buf;
if (dstbuf->frame_buffer.num_planes == 1) {
- vb2_set_plane_payload(vb2_buf, 0, fb->m.mem[0].bytes_used);
+ vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, fb->m.mem[0].bytes_used);
} else if (dstbuf->frame_buffer.num_planes == 2) {
- vb2_set_plane_payload(vb2_buf, 0, fb->m.mem[0].bytes_used);
- vb2_set_plane_payload(vb2_buf, 1, fb->m.mem[1].bytes_used);
+ vb2_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_buf->timestamp = vf->timestamp;
- dstbuf->vb.flags |= vf->frame_type;
+ dstbuf->vb.vb2_buf.timestamp = vf->timestamp;
+ dstbuf->ready_to_display = true;
- 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;
+ if (dump_capture_frame) {
struct file *fp;
- char file_name[32] = {0};
-
- if (!dump_capture_frame || ctx->is_drm_mode)
- break;
- if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode))
- break;
- if (dw_mode == VDEC_DW_AFBC_ONLY)
- break;
-
- snprintf(file_name, 32, "/data/dec_dump_%ux%u.raw", vf->width, vf->height);
-
- fp = filp_open(file_name,
+ fp = filp_open("/data/dec_dump.raw",
O_CREAT | O_RDWR | O_LARGEFILE | O_APPEND, 0600);
-
if (!IS_ERR(fp)) {
- struct vb2_buffer *vb = vb2_buf;
-
- kernel_write(fp,vb2_plane_vaddr(vb, 0),vb->planes[0].length, 0);
+ struct vb2_buffer *vb = &dstbuf->vb.vb2_buf;
+ kernel_write(fp,vb2_plane_vaddr(vb, 0),vb->planes[0].bytesused, 0);
if (dstbuf->frame_buffer.num_planes == 2)
kernel_write(fp,vb2_plane_vaddr(vb, 1),
- vb->planes[1].length, 0);
+ vb->planes[1].bytesused, 0);
pr_info("dump idx: %d %dx%d\n", dump_capture_frame, vf->width, vf->height);
- dump_capture_frame--;
+ dump_capture_frame = false;
filp_close(fp, NULL);
}
- } while(0);
-
- ATRACE_COUNTER("VC_OUT_VSINK-1.submit", vb2_buf->index);
- ATRACE_COUNTER("V_ST_VSINK-input_buffering", vdec_frame_number(ctx->ada_ctx));
+ }
if (vf->flag & VFRAME_FLAG_EMPTY_FRAME_V4L) {
dstbuf->vb.flags = V4L2_BUF_FLAG_LAST;
if (dstbuf->frame_buffer.num_planes == 1) {
- vb2_set_plane_payload(vb2_buf, 0, 0);
+ vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, 0);
} else if (dstbuf->frame_buffer.num_planes == 2) {
- vb2_set_plane_payload(vb2_buf, 0, 0);
- vb2_set_plane_payload(vb2_buf, 1, 0);
+ vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0, 0);
+ vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1, 0);
}
ctx->has_receive_eos = true;
v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
"recevie a empty frame. idx: %d, state: %d\n",
- vb2_buf->index, vb2_buf->state);
+ dstbuf->vb.vb2_buf.index,
+ dstbuf->vb.vb2_buf.state);
+ ATRACE_COUNTER("v4l2_eos", 0);
}
v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
"receive vbuf idx: %d, state: %d\n",
- vb2_buf->index, vb2_buf->state);
+ dstbuf->vb.vb2_buf.index,
+ dstbuf->vb.vb2_buf.state);
if (vf->flag & VFRAME_FLAG_EMPTY_FRAME_V4L) {
- if (ctx->v4l_resolution_change) {
+ if (ctx->q_data[AML_Q_DATA_SRC].resolution_changed) {
/* 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
@@ -838,449 +606,50 @@
if (dstbuf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE) {
/* binding vframe handle. */
- if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T7) {
- if (vf->canvas0_config[0].block_mode == CANVAS_BLKMODE_LINEAR) {
- if ((ctx->output_pix_fmt != V4L2_PIX_FMT_H264) &&
- (ctx->output_pix_fmt != V4L2_PIX_FMT_MPEG1) &&
- (ctx->output_pix_fmt != V4L2_PIX_FMT_MPEG2) &&
- (ctx->output_pix_fmt != V4L2_PIX_FMT_MPEG4) &&
- (ctx->output_pix_fmt != V4L2_PIX_FMT_MJPEG)) {
- vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
- }
- else {
- if (fb->status == FB_ST_GE2D)
- vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
- }
- }
- } else {
- if (vf->canvas0_config[0].block_mode == CANVAS_BLKMODE_LINEAR)
- vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
- }
-
- vf->omx_index = vf->index_disp;
+ 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 (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;
+ v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE);
}
mutex_lock(&ctx->state_lock);
if (ctx->state == AML_STATE_FLUSHING &&
ctx->has_receive_eos) {
ctx->state = AML_STATE_FLUSHED;
- ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+ ATRACE_COUNTER("v4l2_state", ctx->state);
v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
"vcodec state (AML_STATE_FLUSHED)\n");
}
mutex_unlock(&ctx->state_lock);
- if (ctx->post_to_upper_done == false) {
- ctx->post_to_upper_done = true;
- wake_up_interruptible(&ctx->post_done_wq);
- }
-
ctx->decoded_frame_cnt++;
}
-static void fill_capture_done_cb(void *v4l_ctx, void *fb_ctx)
+static int get_display_buffer(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out)
{
- 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;
+ int ret = -1;
- if (ctx->is_stream_off) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT,
- "ignore buff idx: %d streamoff\n", fb->buf_idx);
- return;
- }
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO, "%s\n", __func__);
- 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)) {
+ ret = vdec_if_get_param(ctx, GET_PARAM_DISP_FRAME_BUFFER, out);
+ if (ret) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "%s, table is full. token:%lx\n",
- __func__, vb_handle);
- return false;
+ "Cannot get param : GET_PARAM_DISP_FRAME_BUFFER\n");
+ return -1;
}
- *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)) {
+ if (!*out) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "%s, remove token err, token:%lx.\n",
- __func__, token);
+ "No display frame buffer\n");
+ return -1;
}
-}
-
-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) {
@@ -1291,26 +660,12 @@
ctx->v4l_codec_dpb_ready = true;
v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
- "dpb: %d, vpp: %d, ready: %d, used: %d, dpb is ready: %s\n",
- ctx->dpb_size, ctx->vpp_size,
- v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx),
+ "dpb: %d, ready: %d, used: %d, dpb is ready: %s\n",
+ ctx->dpb_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;
@@ -1326,7 +681,7 @@
mutex_lock(&ctx->state_lock);
if (ctx->state == AML_STATE_PROBE) {
ctx->state = AML_STATE_READY;
- ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+ ATRACE_COUNTER("v4l2_state", ctx->state);
v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
"vcodec state (AML_STATE_READY)\n");
}
@@ -1338,7 +693,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("V_ST_VSINK-state", ctx->state);
+ ATRACE_COUNTER("v4l2_state", ctx->state);
v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
"vcodec state (AML_STATE_ACTIVE)\n");
}
@@ -1363,7 +718,7 @@
return true;
}
-static void aml_wait_buf_ready(struct aml_vcodec_ctx *ctx)
+static void aml_wait_dpb_ready(struct aml_vcodec_ctx *ctx)
{
ulong expires;
@@ -1378,75 +733,34 @@
}
ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx);
- if ((ready_num + ctx->buf_used_count) >= CTX_BUF_TOTAL(ctx))
+ if ((ready_num + ctx->buf_used_count) >= ctx->dpb_size)
ctx->v4l_codec_dpb_ready = true;
}
}
-void dmabuff_recycle_worker(struct work_struct *work)
-{
- struct aml_vcodec_ctx *ctx =
- container_of(work, struct aml_vcodec_ctx, dmabuff_recycle_work);
- struct vb2_v4l2_buffer *vb = NULL;
- struct aml_video_dec_buf *buf = NULL;
- unsigned long flags;
-
- for (;;) {
- spin_lock_irqsave(&ctx->dmabuff_recycle_lock, flags);
- if (!kfifo_get(&ctx->dmabuff_recycle, &vb)) {
- spin_unlock_irqrestore(&ctx->dmabuff_recycle_lock, flags);
- break;
- }
- spin_unlock_irqrestore(&ctx->dmabuff_recycle_lock, flags);
-
- buf = container_of(vb, struct aml_video_dec_buf, vb);
-
- if (ctx->is_out_stream_off)
- continue;
-
- if (wait_event_interruptible_timeout
- (ctx->wq, buf->used == false,
- msecs_to_jiffies(200)) == 0) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "wait recycle dma buff timeout.\n");
- }
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_INPUT,
- "recycle buff idx: %d, vbuf: %lx\n", vb->vb2_buf.index,
- (ulong)sg_dma_address(buf->out_sgt->sgl));
-
- ATRACE_COUNTER("VO_OUT_VSINK-2.write_secure_end", vb->vb2_buf.index);
-
- if (vb->vb2_buf.state != VB2_BUF_STATE_ERROR)
- v4l2_buff_done(vb, buf->error ? VB2_BUF_STATE_ERROR :
- VB2_BUF_STATE_DONE);
- }
-}
-
void aml_recycle_dma_buffers(struct aml_vcodec_ctx *ctx, u32 handle)
{
- struct aml_vcodec_dev *dev = ctx->dev;
- struct vb2_v4l2_buffer *vb = NULL;
- struct vb2_queue *q = NULL;
+ struct vb2_v4l2_buffer *vb;
+ struct aml_video_dec_buf *buf;
+ struct vb2_queue *q;
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);
- 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);
+ 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));
}
static void aml_vdec_worker(struct work_struct *work)
@@ -1454,12 +768,12 @@
struct aml_vcodec_ctx *ctx =
container_of(work, struct aml_vcodec_ctx, decode_work);
struct aml_vcodec_dev *dev = ctx->dev;
- struct aml_video_dec_buf *aml_buf;
- struct vb2_v4l2_buffer *vb2_v4l2;
- struct vb2_buffer *vb;
+ struct vb2_buffer *src_buf;
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) {
@@ -1473,23 +787,21 @@
goto out;
}
- vb2_v4l2 = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
- if (vb2_v4l2 == NULL) {
+ src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+ if (src_buf == NULL) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
"src_buf empty.\n");
goto out;
}
- vb = (struct vb2_buffer *)vb2_v4l2;
-
/*this case for google, but some frames are droped on ffmpeg, so disabled temp.*/
if (0 && !is_enough_work_items(ctx))
goto out;
- aml_buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
- if (aml_buf->lastframe) {
- ulong expires;
+ 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);
+ 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");
@@ -1497,34 +809,22 @@
/*
* when inputs a small amount of src buff, then soon to
* switch state FLUSHING, must to wait the DBP to be ready.
- * (!ctx->v4l_codec_dpb_ready) change to only need one buf
- * for run ready in new version.
*/
- expires = jiffies + msecs_to_jiffies(5000);
- while ((vdec_frame_number(ctx->ada_ctx) > 0) &&
- (ctx->cap_pool.in < 1)) {
- if (time_after(jiffies, expires)) {
- aml_vdec_flush_decoder(ctx);
- v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
- v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
- aml_vdec_dispatch_event(ctx, V4L2_EVENT_REQUEST_EXIT);
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "capture buffer waiting timeout.\n");
- goto out;
- }
- usleep_range(5000, 5500);
+ if (!ctx->v4l_codec_dpb_ready) {
+ v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+ goto out;
}
mutex_lock(&ctx->state_lock);
if (ctx->state == AML_STATE_ACTIVE) {
ctx->state = AML_STATE_FLUSHING;// prepare flushing
- ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+ ATRACE_COUNTER("v4l2_state", ctx->state);
v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
"vcodec state (AML_STATE_FLUSHING-LASTFRM)\n");
}
mutex_unlock(&ctx->state_lock);
- v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+ src_buf = 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. */
@@ -1533,22 +833,21 @@
goto out;
}
- buf.index = vb->index;
- buf.vaddr = vb2_plane_vaddr(vb, 0);
- buf.addr = sg_dma_address(aml_buf->out_sgt->sgl);
- buf.size = vb->planes[0].bytesused;
- buf.model = vb->memory;
- buf.timestamp = vb->timestamp;
- buf.meta_ptr = (ulong)aml_buf->meta_data;
+ 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;
if (!buf.vaddr && !buf.addr) {
v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "id=%d src_addr is NULL.\n", vb->index);
+ "id=%d src_addr is NULL.\n", src_buf->index);
goto out;
}
- aml_buf->used = true;
+ src_buf_info->used = true;
/* v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
"size: 0x%zx, crc: 0x%x\n",
@@ -1558,52 +857,29 @@
/*v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
"timestamp: 0x%llx\n", src_buf->timestamp);*/
- if (ctx->is_drm_mode &&
- (buf.model == VB2_MEMORY_DMABUF)) {
- ATRACE_COUNTER("VO_IN_VSINK-2.write_secure", buf.size);
- } else {
- ATRACE_COUNTER("VO_IN_VSINK-2.write", buf.size);
- }
-
- ATRACE_COUNTER("V_ST_VSINK-input_buffering", vdec_frame_number(ctx->ada_ctx));
-
ret = vdec_if_decode(ctx, &buf, &res_chg);
if (ret > 0) {
/*
* we only return src buffer with VB2_BUF_STATE_DONE
* when decode success without resolution change.
*/
- aml_buf->used = false;
v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
-
- if (ctx->is_drm_mode &&
- (buf.model == VB2_MEMORY_DMABUF)) {
- wake_up_interruptible(&ctx->wq);
- } else {
- ATRACE_COUNTER("VO_OUT_VSINK-0.wrtie_end", buf.size);
- v4l2_buff_done(&aml_buf->vb,
- VB2_BUF_STATE_DONE);
- }
+ 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) {
- aml_buf->used = false;
+ src_buf_info->error = (ret == -EIO ? true : 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);
- }
+ if (!(ctx->is_drm_mode && buf.model == VB2_MEMORY_DMABUF))
+ v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR);
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
"error processing src data. %d.\n", ret);
} else if (res_chg) {
/* wait the DPB state to be ready. */
- aml_wait_buf_ready(ctx);
+ aml_wait_dpb_ready(ctx);
- aml_buf->used = false;
+ src_buf_info->used = false;
aml_vdec_pic_info_update(ctx);
/*
* On encountering a resolution change in the stream.
@@ -1614,13 +890,13 @@
mutex_lock(&ctx->state_lock);
if (ctx->state == AML_STATE_ACTIVE) {
ctx->state = AML_STATE_FLUSHING;// prepare flushing
- ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+ ATRACE_COUNTER("v4l2_state", ctx->state);
v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
"vcodec state (AML_STATE_FLUSHING-RESCHG)\n");
}
mutex_unlock(&ctx->state_lock);
- ctx->v4l_resolution_change = true;
+ ctx->q_data[AML_Q_DATA_SRC].resolution_changed = true;
while (ctx->m2m_ctx->job_flags & TRANS_RUNNING) {
v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
}
@@ -1629,10 +905,8 @@
goto out;
} else {
- ATRACE_COUNTER("VO_OUT_VSINK-1.write_again", buf.size);
/* decoder is lack of resource, retry after short delay */
- if (vdec_get_instance_num() < 2)
- usleep_range(2000, 4000);
+ usleep_range(50000, 55000);
}
v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
@@ -1650,10 +924,28 @@
if (aml_codec_reset(ctx->ada_ctx, &ctx->reset_flag)) {
ctx->state = AML_STATE_ABORT;
- ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+ ATRACE_COUNTER("v4l2_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;
@@ -1661,13 +953,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. */
- cancel_work_sync(&ctx->decode_work);
- cancel_work_sync(&ctx->dmabuff_recycle_work);
+ flush_workqueue(dev->decode_workqueue);
/* clean output cache and decoder status . */
if (ctx->state > AML_STATE_INIT)
@@ -1681,38 +973,33 @@
ctx->v4l_codec_dpb_ready = false;
}
-void aml_thread_capture_worker(struct aml_vcodec_ctx *ctx)
+void try_to_capture(struct aml_vcodec_ctx *ctx)
{
- struct vb2_v4l2_buffer *vb = NULL;
- struct aml_video_dec_buf *aml_buff = NULL;
+ int ret = 0;
struct vdec_v4l2_buffer *fb = NULL;
- for (;;) {
- mutex_lock(&ctx->capture_buffer_lock);
- if (!kfifo_get(&ctx->capture_buffer, &vb)) {
- mutex_unlock(&ctx->capture_buffer_lock);
- break;
- }
- mutex_unlock(&ctx->capture_buffer_lock);
-
- aml_buff = container_of(vb, struct aml_video_dec_buf, vb);
- fb = &aml_buff->frame_buffer;
-
- if (ctx->is_stream_off)
- continue;
-
- post_frame_to_upper(ctx, fb);
+ 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;
}
-}
-EXPORT_SYMBOL_GPL(aml_thread_capture_worker);
-static int vdec_capture_thread(void *data)
+ trans_vframe_to_user(ctx, fb);
+}
+EXPORT_SYMBOL_GPL(try_to_capture);
+
+static int vdec_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, ¶m);
+
for (;;) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
"%s, state: %d\n", __func__, ctx->state);
@@ -1728,19 +1015,19 @@
}
while (!kthread_should_stop()) {
- usleep_range(1000, 2000);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
}
return 0;
}
-void aml_thread_post_task(struct aml_vcodec_ctx *ctx,
+void aml_thread_notify(struct aml_vcodec_ctx *ctx,
enum aml_thread_type type)
{
struct aml_vdec_thread *thread = NULL;
- ulong flags;
- spin_lock_irqsave(&ctx->tsplock, flags);
+ mutex_lock(&ctx->lock);
list_for_each_entry(thread, &ctx->vdec_thread_list, node) {
if (thread->task == NULL)
continue;
@@ -1748,9 +1035,9 @@
if (thread->type == type)
up(&thread->sem);
}
- spin_unlock_irqrestore(&ctx->tsplock, flags);
+ mutex_unlock(&ctx->lock);
}
-EXPORT_SYMBOL_GPL(aml_thread_post_task);
+EXPORT_SYMBOL_GPL(aml_thread_notify);
int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func,
enum aml_thread_type type, const char *thread_name)
@@ -1768,7 +1055,7 @@
thread->priv = ctx;
sema_init(&thread->sem, 0);
- thread->task = kthread_run(vdec_capture_thread, thread, "aml-%s-%d", thread_name, ctx->id);
+ thread->task = kthread_run(vdec_thread, thread, "aml-%s", thread_name);
if (IS_ERR(thread->task)) {
ret = PTR_ERR(thread->task);
thread->task = NULL;
@@ -1776,10 +1063,6 @@
}
sched_setscheduler_nocheck(thread->task, SCHED_FIFO, ¶m);
- 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;
@@ -1794,14 +1077,13 @@
void aml_thread_stop(struct aml_vcodec_ctx *ctx)
{
struct aml_vdec_thread *thread = NULL;
- ulong flags;
while (!list_empty(&ctx->vdec_thread_list)) {
thread = list_entry(ctx->vdec_thread_list.next,
struct aml_vdec_thread, node);
- spin_lock_irqsave(&ctx->tsplock, flags);
+ mutex_lock(&ctx->lock);
list_del(&thread->node);
- spin_unlock_irqrestore(&ctx->tsplock, flags);
+ mutex_unlock(&ctx->lock);
thread->stop = true;
up(&thread->sem);
@@ -1823,17 +1105,7 @@
switch (cmd->cmd) {
case V4L2_DEC_CMD_STOP:
case V4L2_DEC_CMD_START:
- if (cmd->cmd == V4L2_DEC_CMD_START) {
- if (cmd->start.speed == ~0)
- cmd->start.speed = 0;
- if (cmd->start.format == ~0)
- cmd->start.format = 0;
- }
-
- if (cmd->flags == ~0)
- cmd->flags = 0;
-
- if ((cmd->flags != 0) && (cmd->flags != ~0)) {
+ if (cmd->flags != 0) {
v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
"cmd->flags=%u\n", cmd->flags);
return -EINVAL;
@@ -1862,6 +1134,19 @@
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)) {
@@ -1870,32 +1155,18 @@
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:
@@ -1905,20 +1176,6 @@
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)
{
@@ -1927,80 +1184,26 @@
struct vb2_queue *q;
q = v4l2_m2m_get_vq(fh->m2m_ctx, i);
- if (!V4L2_TYPE_IS_OUTPUT(q->type) &&
- ctx->is_stream_off) {
- if (ctx->vpp_is_need) {
- int ret;
+ if (!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 (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;
+ v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
+ "vcodec state (AML_STATE_RESET)\n");
+ aml_vdec_reset(ctx);
}
- 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;
- }
+ mutex_unlock(&ctx->state_lock);
+
+ ctx->is_stream_off = false;
+ ctx->v4l_resolution_change = false;
}
-
- 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;
@@ -2016,26 +1219,12 @@
struct v4l2_fh *fh = file->private_data;
struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
struct vb2_queue *q;
- ulong flags;
q = v4l2_m2m_get_vq(fh->m2m_ctx, i);
-
- flags = aml_vcodec_ctx_lock(ctx);
-
- if (V4L2_TYPE_IS_OUTPUT(q->type))
- ctx->is_out_stream_off = true;
- else
+ if (!V4L2_TYPE_IS_OUTPUT(q->type))
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;
- }
+ else
+ ctx->is_out_stream_off = true;
v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
"%s, type: %d\n", __func__, q->type);
@@ -2052,38 +1241,19 @@
q = v4l2_m2m_get_vq(fh->m2m_ctx, rb->type);
- if (!rb->count) {
- if (!V4L2_TYPE_IS_OUTPUT(rb->type)) {
- if (wait_event_interruptible_timeout
- (ctx->post_done_wq, ctx->post_to_upper_done == true,
- msecs_to_jiffies(200)) == 0) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "wait post frame to upper finish timeout.\n");
- }
- }
+ if (!rb->count)
vb2_queue_release(q);
- }
v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
"%s, type: %d, count: %d\n",
__func__, q->type, rb->count);
if (!V4L2_TYPE_IS_OUTPUT(rb->type)) {
- /* driver needs match v4l buffer number with total size*/
- if (rb->count > CTX_BUF_TOTAL(ctx)) {
+ /* driver needs match v4l buffer number with dpb_size */
+ if (rb->count > ctx->dpb_size) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
"reqbufs (st:%d) %d -> %d\n",
- ctx->state, rb->count, CTX_BUF_TOTAL(ctx));
- ctx->picinfo.dpb_margin += (rb->count - CTX_BUF_TOTAL(ctx));
- ctx->dpb_size = ctx->picinfo.dpb_frames + ctx->picinfo.dpb_margin;
- vdec_if_set_param(ctx, SET_PARAM_PIC_INFO, &ctx->picinfo);
- v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
- "%s buf updated, dec: %d (%d + %d), vpp %d\n",
- __func__,
- ctx->dpb_size,
- ctx->picinfo.dpb_frames,
- ctx->picinfo.dpb_margin,
- ctx->vpp_size);
+ ctx->state, rb->count, ctx->dpb_size);
//rb->count = ctx->dpb_size;
}
} else {
@@ -2123,12 +1293,9 @@
{
ulong flags;
- if (kref_read(&ctx->box_ref))
- kref_put(&ctx->box_ref, box_release);
-
flags = aml_vcodec_ctx_lock(ctx);
ctx->state = AML_STATE_ABORT;
- ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+ ATRACE_COUNTER("v4l2_state", ctx->state);
v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
"vcodec state (AML_STATE_ABORT)\n");
aml_vcodec_ctx_unlock(ctx, flags);
@@ -2154,8 +1321,6 @@
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;
@@ -2169,9 +1334,6 @@
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,
@@ -2187,11 +1349,8 @@
q_data->bytesperline[1] = q_data->coded_width;
ctx->reset_flag = V4L_RESET_MODE_NORMAL;
- ctx->fb_ops.query = fb_buff_query;
- ctx->fb_ops.alloc = fb_buff_from_queue;
-
ctx->state = AML_STATE_IDLE;
- ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+ ATRACE_COUNTER("v4l2_state", ctx->state);
v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
"vcodec state (AML_STATE_IDLE)\n");
}
@@ -2215,24 +1374,11 @@
ret = v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
if (V4L2_TYPE_IS_OUTPUT(buf->type)) {
- if (V4L2_TYPE_IS_MULTIPLANAR(buf->type)) {
- if (ret == -EAGAIN)
- ATRACE_COUNTER("VO_IN_VSINK-1.que_again", buf->m.planes[0].bytesused);
- else
- ATRACE_COUNTER("VO_IN_VSINK-0.que", buf->m.planes[0].bytesused);
- } else {
- if (ret == -EAGAIN)
- ATRACE_COUNTER("VO_IN_VSINK-1.que_again", buf->length);
- else
- ATRACE_COUNTER("VO_IN_VSINK-0.que", buf->length);
- }
- } else {
if (ret == -EAGAIN)
- ATRACE_COUNTER("VC_IN_VSINK-1.que_again", buf->index);
+ ATRACE_COUNTER("v4l2_qbuf_eagain", 0);
else
- ATRACE_COUNTER("VC_IN_VSINK-0.que", buf->index);
+ ATRACE_COUNTER("v4l2_qbuf_ok", 0);
}
-
return ret;
}
@@ -2254,47 +1400,39 @@
}
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) aml_buf;
+ aml_buf->privdata.vb_handle = (ulong) ctx->dev;
aml_buf->privdata.v4l_dec_ctx = (ulong) ctx;
+ aml_buf->privdata.v4l_inst_id = ctx->id;
file = fget(vb2_v4l2->private);
- if (file && is_v4l2_buf_file(file)) {
+ if (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);
}
- }
-
- 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);
+ fput(file);
}
return ret;
@@ -2304,12 +1442,10 @@
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);
@@ -2347,154 +1483,115 @@
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 (V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
- if (V4L2_TYPE_IS_OUTPUT(f->type)) {
- pix_mp->num_planes = 1;
- pix_mp->plane_fmt[0].bytesperline = 0;
+ if (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 ((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;
+ 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);
- 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);
+ /*
+ * 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);
- pix_mp->num_planes = fmt->num_planes;
+ 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->plane_fmt[0].bytesperline = pix_mp->width;
- pix_mp->plane_fmt[0].sizeimage =
- pix_mp->width * pix_mp->height;
+ 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[1].bytesperline = pix_mp->width;
- pix_mp->plane_fmt[1].sizeimage =
- pix_mp->width * pix_mp->height / 2;
+ 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;
}
-
- 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_out(struct file *file, void *priv,
+static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct aml_q_data *q_data = NULL;
struct aml_video_fmt *fmt = NULL;
struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
- struct vb2_queue *dst_vq;
v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
- "%s, type: %u, planes: %u, fmt: %x\n",
- __func__, f->type,
- V4L2_TYPE_IS_MULTIPLANAR(f->type) ?
- f->fmt.pix_mp.num_planes : 1,
+ "%s, type: %u, planes: %u, fmt: %u\n",
+ __func__, f->type, f->fmt.pix_mp.num_planes,
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);
+ fmt = aml_vdec_find_format(f);
+ if (!fmt)
return -EINVAL;
- }
- if (!V4L2_TYPE_IS_MULTIPLANAR(f->type) && dst_vq->is_multiplanar)
- 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) {
- 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)
+ if (!fmt)
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;
- }
+ if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) {
+ v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+ "sizeimage of output format must be given\n");
+ return -EINVAL;
}
- return 0;
+ return vidioc_try_fmt(f, fmt);
}
static int vidioc_vdec_g_selection(struct file *file, void *priv,
@@ -2502,36 +1599,29 @@
{
struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
struct aml_q_data *q_data;
- int ratio = 1;
if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
(s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE))
return -EINVAL;
- if (ctx->internal_dw_scale) {
- if (ctx->state >= AML_STATE_PROBE) {
- unsigned int dw_mode = VDEC_DW_NO_AFBC;
- if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode))
- return -EBUSY;
- ratio = get_double_write_ratio(dw_mode);
- }
- }
-
q_data = &ctx->q_data[AML_Q_DATA_DST];
switch (s->target) {
case V4L2_SEL_TGT_COMPOSE_DEFAULT:
case V4L2_SEL_TGT_COMPOSE:
- s->r.left = 0;
- s->r.top = 0;
- s->r.width = ctx->picinfo.visible_width / ratio;
- s->r.height = ctx->picinfo.visible_height / ratio;
+ 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;
+ }
break;
case V4L2_SEL_TGT_COMPOSE_BOUNDS:
s->r.left = 0;
s->r.top = 0;
- s->r.width = ctx->picinfo.coded_width / ratio;
- s->r.height = ctx->picinfo.coded_height / ratio;
+ s->r.width = ctx->picinfo.coded_width;
+ s->r.height = ctx->picinfo.coded_height;
break;
default:
return -EINVAL;
@@ -2555,7 +1645,6 @@
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);
@@ -2563,21 +1652,12 @@
if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
- if (ctx->internal_dw_scale) {
- if (ctx->state >= AML_STATE_PROBE) {
- unsigned int dw_mode = VDEC_DW_NO_AFBC;
- if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode))
- return -EBUSY;
- ratio = get_double_write_ratio(dw_mode);
- }
- }
-
switch (s->target) {
case V4L2_SEL_TGT_COMPOSE:
s->r.left = 0;
s->r.top = 0;
- s->r.width = ctx->picinfo.visible_width / ratio;
- s->r.height = ctx->picinfo.visible_height / ratio;
+ s->r.width = ctx->picinfo.visible_width;
+ s->r.height = ctx->picinfo.visible_height;
break;
default:
return -EINVAL;
@@ -2586,127 +1666,89 @@
return 0;
}
-/* called when it is beyong AML_STATE_PROBE */
-static void update_ctx_dimension(struct aml_vcodec_ctx *ctx, u32 type)
-{
- struct aml_q_data *q_data;
- unsigned int dw_mode = VDEC_DW_NO_AFBC;
- int ratio = 1;
-
- q_data = aml_vdec_get_q_data(ctx, type);
-
- if (ctx->internal_dw_scale) {
- if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode))
- return;
- ratio = get_double_write_ratio(dw_mode);
- }
-
- if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
- q_data->sizeimage[0] = ctx->picinfo.y_len_sz;
- q_data->sizeimage[1] = ctx->picinfo.c_len_sz;
-
- q_data->coded_width = ALIGN(ctx->picinfo.coded_width / ratio, 64);
- q_data->coded_height = ALIGN(ctx->picinfo.coded_height / ratio, 64);
-
- q_data->bytesperline[0] = ALIGN(ctx->picinfo.coded_width / ratio, 64);
- q_data->bytesperline[1] = ALIGN(ctx->picinfo.coded_width / ratio, 64);
- } else {
- q_data->coded_width = ALIGN(ctx->picinfo.coded_width / ratio, 64);
- q_data->coded_height = ALIGN(ctx->picinfo.coded_height / ratio, 64);
- q_data->sizeimage[0] = ctx->picinfo.y_len_sz;
- q_data->sizeimage[0] += ctx->picinfo.c_len_sz;
- q_data->bytesperline[0] = ALIGN(ctx->picinfo.coded_width / ratio, 64);
- }
-}
-
static void copy_v4l2_format_dimention(struct v4l2_pix_format_mplane *pix_mp,
- struct v4l2_pix_format *pix,
- struct aml_q_data *q_data,
- u32 type)
+ struct aml_q_data *q_data, u32 type)
{
- int i;
-
- if (!pix || !pix_mp || !q_data)
+ if (!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];
- }
+ if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ pix_mp->width = q_data->visible_width;
+ pix_mp->height = q_data->visible_height;
} 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];
+ /*
+ * 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;
+ }
+
+ /*
+ * 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];
}
}
static int vidioc_vdec_s_fmt(struct file *file, void *priv,
struct v4l2_format *f)
{
- int ret = 0;
struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
- struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct aml_q_data *q_data = NULL;
+ struct v4l2_pix_format_mplane *pix_mp;
+ struct aml_q_data *q_data;
+ int ret = 0;
struct aml_video_fmt *fmt;
- struct vb2_queue *dst_vq;
v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT,
- "%s, type: %u, planes: %u, fmt: %x\n",
- __func__, f->type,
- V4L2_TYPE_IS_MULTIPLANAR(f->type) ?
- f->fmt.pix_mp.num_planes : 1,
+ "%s, type: %u, planes: %u, fmt: %u\n",
+ __func__, f->type, f->fmt.pix_mp.num_planes,
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 (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;
+ 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);
+ }
}
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;
@@ -2716,7 +1758,6 @@
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;
@@ -2732,38 +1773,7 @@
return -EINVAL;
}
ctx->state = AML_STATE_INIT;
- ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
- v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
- "vcodec state (AML_STATE_INIT)\n");
- }
- mutex_unlock(&ctx->state_lock);
- } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
- q_data->sizeimage[0] = pix->sizeimage;
- q_data->coded_width = pix->width;
- q_data->coded_height = pix->height;
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
- "w: %d, h: %d, size: %d\n",
- pix->width, pix->height,
- pix->sizeimage);
-
- ctx->output_pix_fmt = pix->pixelformat;
- ctx->colorspace = f->fmt.pix.colorspace;
- ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
- ctx->quantization = f->fmt.pix.quantization;
- ctx->xfer_func = f->fmt.pix.xfer_func;
-
- mutex_lock(&ctx->state_lock);
- if (ctx->state == AML_STATE_IDLE) {
- ret = vdec_if_init(ctx, q_data->fmt->fourcc);
- if (ret) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "vdec_if_init() fail ret=%d\n", ret);
- mutex_unlock(&ctx->state_lock);
- return -EINVAL;
- }
- ctx->state = AML_STATE_INIT;
- ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+ ATRACE_COUNTER("v4l2_state", ctx->state);
v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
"vcodec state (AML_STATE_INIT)\n");
}
@@ -2771,13 +1781,9 @@
}
if (!V4L2_TYPE_IS_OUTPUT(f->type)) {
- ctx->cap_pix_fmt = V4L2_TYPE_IS_MULTIPLANAR(f->type) ?
- pix_mp->pixelformat : pix->pixelformat;
- if (ctx->state >= AML_STATE_PROBE) {
- update_ctx_dimension(ctx, f->type);
- copy_v4l2_format_dimention(pix_mp, pix, q_data, f->type);
- v4l_buf_size_decision(ctx);
- }
+ ctx->cap_pix_fmt = pix_mp->pixelformat;
+ if (ctx->state >= AML_STATE_PROBE)
+ copy_v4l2_format_dimention(pix_mp, q_data, f->type);
}
return 0;
@@ -2827,31 +1833,16 @@
static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue)
{
struct aml_video_fmt *fmt;
- int i = 0, j = 0;
+ int i, j = 0;
- /* I420 only used for mjpeg. */
- if (!output_queue && support_mjpeg && support_format_I420) {
- for (i = 0; i < NUM_FORMATS; i++) {
- fmt = &aml_video_formats[i];
- if ((fmt->fourcc == V4L2_PIX_FMT_YUV420) ||
- (fmt->fourcc == V4L2_PIX_FMT_YUV420M)) {
- break;
- }
- }
- }
-
- for (; i < NUM_FORMATS; i++) {
- fmt = &aml_video_formats[i];
- if (output_queue && (fmt->type != AML_FMT_DEC))
+ for (i = 0; i < NUM_FORMATS; i++) {
+ if (output_queue && (aml_video_formats[i].type != AML_FMT_DEC))
continue;
- if (!output_queue && (fmt->type != AML_FMT_FRAME))
- continue;
- if (support_mjpeg && !support_format_I420 &&
- ((fmt->fourcc == V4L2_PIX_FMT_YUV420) ||
- (fmt->fourcc == V4L2_PIX_FMT_YUV420M)))
+ if (!output_queue && (aml_video_formats[i].type != AML_FMT_FRAME))
continue;
if (j == f->index) {
+ fmt = &aml_video_formats[i];
f->pixelformat = fmt->fourcc;
return 0;
}
@@ -2888,7 +1879,6 @@
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;
@@ -2899,29 +1889,12 @@
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)) {
@@ -2940,8 +1913,24 @@
if ((!V4L2_TYPE_IS_OUTPUT(f->type)) &&
(ctx->state >= AML_STATE_PROBE)) {
- update_ctx_dimension(ctx, f->type);
- copy_v4l2_format_dimention(pix_mp, pix, q_data, f->type);
+ /* 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);
} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
/*
* This is run on OUTPUT
@@ -2949,21 +1938,20 @@
* so width and height have no meaning.
* Assign value here to pass v4l2-compliance test
*/
- copy_v4l2_format_dimention(pix_mp, pix, q_data, f->type);
+ copy_v4l2_format_dimention(pix_mp, q_data, f->type);
} else {
- copy_v4l2_format_dimention(pix_mp, pix, q_data, f->type);
+ copy_v4l2_format_dimention(pix_mp, 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: %x\n",
- __func__, f->type,
- V4L2_TYPE_IS_MULTIPLANAR(f->type) ?
- q_data->fmt->num_planes : 1,
- q_data->fmt->fourcc);
+ "%s, type: %u, planes: %u, fmt: %u\n",
+ __func__, f->type, f->fmt.pix_mp.num_planes,
+ f->fmt.pix_mp.pixelformat);
return 0;
}
@@ -3019,32 +2007,21 @@
for (i = 0; i < *nplanes; i++) {
if (sizes[i] < q_data->sizeimage[i])
return -EINVAL;
- alloc_devs[i] = &ctx->dev->plat_dev->dev;
-
- if (!V4L2_TYPE_IS_OUTPUT(vq->type))
- alloc_devs[i] = v4l_get_dev_from_codec_mm();
+ //alloc_devs[i] = &ctx->dev->plat_dev->dev;
+ alloc_devs[i] = v4l_get_dev_from_codec_mm();//alloc mm from the codec mm
}
} else {
- int dw_mode = VDEC_DW_NO_AFBC;
-
if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
*nplanes = 2;
else
*nplanes = 1;
- if (!vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode)) {
- if (dw_mode == VDEC_DW_AFBC_ONLY)
- *nplanes = 1;
- }
-
for (i = 0; i < *nplanes; i++) {
sizes[i] = q_data->sizeimage[i];
if (V4L2_TYPE_IS_OUTPUT(vq->type) && ctx->output_dma_mode)
- sizes[i] = 1;
- alloc_devs[i] = &ctx->dev->plat_dev->dev;
-
- if (!V4L2_TYPE_IS_OUTPUT(vq->type))
- alloc_devs[i] = v4l_get_dev_from_codec_mm();
+ 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
}
}
@@ -3059,8 +2036,6 @@
{
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,
@@ -3082,710 +2057,65 @@
}
}
- vb2_v4l2 = to_vb2_v4l2_buffer(vb);
- buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
-
- if (vb2_v4l2->meta_ptr && (copy_from_user(buf->meta_data,
- (void *)vb2_v4l2->meta_ptr, META_DATA_SIZE + 4))) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "%s:copy meta data error. ptr: %lx\n", __func__, vb2_v4l2->meta_ptr);
- }
-
return 0;
}
-static int init_mmu_bmmu_box(struct aml_vcodec_ctx *ctx)
-{
- int i;
- int mmu_flag = ctx->is_drm_mode? CODEC_MM_FLAGS_TVP:0;
- int bmmu_flag = mmu_flag;
- u32 dw_mode = VDEC_DW_NO_AFBC;
-
- ctx->comp_bufs = vzalloc(sizeof(*ctx->comp_bufs) * V4L_CAP_BUFF_MAX);
- if (!ctx->comp_bufs)
- return -ENOMEM;
-
- if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode)) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "invalid dw_mode\n");
- goto free_comp_bufs;
- }
-
- /* init mmu box */
- ctx->mmu_box = decoder_mmu_box_alloc_box("v4l2_dec",
- ctx->id, V4L_CAP_BUFF_MAX,
- ctx->comp_info.max_size * SZ_1M, mmu_flag);
- if (!ctx->mmu_box) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to create mmu box\n");
- goto free_comp_bufs;
- }
-
- /* init bmmu box */
- bmmu_flag |= CODEC_MM_FLAGS_CMA_CLEAR | CODEC_MM_FLAGS_FOR_VDECODER;
- ctx->bmmu_box = decoder_bmmu_box_alloc_box("v4l2_dec",
- ctx->id, V4L_CAP_BUFF_MAX,
- 4 + PAGE_SHIFT, bmmu_flag);
- if (!ctx->bmmu_box) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to create bmmu box\n");
- goto free_mmubox;
- }
-
- if (dw_mode & 0x20) {
- /* init mmu box dw*/
- ctx->mmu_box_dw = decoder_mmu_box_alloc_box("v4l2_dec",
- ctx->id, V4L_CAP_BUFF_MAX,
- ctx->comp_info.max_size * SZ_1M, mmu_flag);
- if (!ctx->mmu_box_dw) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to create mmu box dw\n");
- goto free_bmmubox;
- }
-
- /* init bmmu box dw*/
- bmmu_flag |= CODEC_MM_FLAGS_CMA_CLEAR | CODEC_MM_FLAGS_FOR_VDECODER;
- ctx->bmmu_box_dw = decoder_bmmu_box_alloc_box("v4l2_dec",
- ctx->id, V4L_CAP_BUFF_MAX,
- 4 + PAGE_SHIFT, bmmu_flag);
- if (!ctx->bmmu_box_dw) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to create bmmu box dw\n");
- goto free_mmubox_dw;
- }
- }
-
- kref_init(&ctx->box_ref);
- for (i = 0; i < V4L_CAP_BUFF_MAX; i++) {
- struct internal_comp_buf *buf;
- buf = &ctx->comp_bufs[i];
- buf->index = i;
- buf->ref = 0;
- buf->box_ref = &ctx->box_ref;
- buf->mmu_box = ctx->mmu_box;
- buf->bmmu_box = ctx->bmmu_box;
- buf->mmu_box_dw = ctx->mmu_box_dw;
- buf->bmmu_box_dw = ctx->bmmu_box_dw;
- }
- kref_get(&ctx->ctx_ref);
-
- ctx->uvm_proxy = vzalloc(sizeof(*ctx->uvm_proxy) * V4L_CAP_BUFF_MAX);
- if (!ctx->uvm_proxy)
- goto free_mmubox;
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
- "box init, bmmu: %px, mmu: %px, mmu_dw: %px bmmu_dw: %px\n",
- ctx->bmmu_box, ctx->mmu_box, ctx->mmu_box_dw, ctx->bmmu_box_dw);
-
- return 0;
-free_mmubox_dw:
- decoder_mmu_box_free(ctx->mmu_box_dw);
- ctx->mmu_box_dw = NULL;
-
-free_bmmubox:
- decoder_bmmu_box_free(ctx->bmmu_box);
- ctx->bmmu_box = NULL;
-
-free_mmubox:
- decoder_mmu_box_free(ctx->mmu_box);
- ctx->mmu_box = NULL;
-
-free_comp_bufs:
- vfree(ctx->comp_bufs);
- ctx->comp_bufs = NULL;
-
- return -1;
-}
-
-void aml_alloc_buffer(struct aml_vcodec_ctx *ctx, int flag)
-{
- int i = 0;
-
- if (flag & DV_TYPE) {
- for (i = 0; i < V4L_CAP_BUFF_MAX; i++) {
- ctx->aux_infos.bufs[i].md_buf = vzalloc(MD_BUF_SIZE);
- if (ctx->aux_infos.bufs[i].md_buf == NULL) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "v4l2 alloc %dth dv md buffer fail\n", i);
- }
-
- ctx->aux_infos.bufs[i].comp_buf = vzalloc(COMP_BUF_SIZE);
- if (ctx->aux_infos.bufs[i].comp_buf == NULL) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "v4l2 alloc %dth dv comp buffer fail\n", i);
- }
- }
- }
-
- if (flag & SEI_TYPE) {
- for (i = 0; i < V4L_CAP_BUFF_MAX; i++) {
- ctx->aux_infos.bufs[i].sei_buf = vzalloc(SEI_BUF_SIZE);
- if (ctx->aux_infos.bufs[i].sei_buf) {
- ctx->aux_infos.bufs[i].sei_size = 0;
- ctx->aux_infos.bufs[i].sei_state = 1;
- ctx->aux_infos.sei_need_free = false;
- v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
- "v4l2 alloc %dth aux buffer:%px\n",
- i, ctx->aux_infos.bufs[i].sei_buf);
- } else {
- ctx->aux_infos.bufs[i].sei_buf = NULL;
- ctx->aux_infos.bufs[i].sei_state = 0;
- ctx->aux_infos.bufs[i].sei_size = 0;
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "v4l2 alloc %dth aux buffer fail\n", i);
- }
- }
- }
-}
-
-void aml_free_buffer(struct aml_vcodec_ctx *ctx, int flag)
-{
- int i = 0;
-
- if (flag & DV_TYPE) {
- for (i = 0; i < V4L_CAP_BUFF_MAX; i++) {
- if (ctx->aux_infos.bufs[i].md_buf != NULL) {
- vfree(ctx->aux_infos.bufs[i].md_buf);
- ctx->aux_infos.bufs[i].md_buf = NULL;
- }
-
- if (ctx->aux_infos.bufs[i].comp_buf != NULL) {
- vfree(ctx->aux_infos.bufs[i].comp_buf);
- ctx->aux_infos.bufs[i].comp_buf = NULL;
- }
- }
- }
-
- if (flag & SEI_TYPE) {
- for (i = 0; i < V4L_CAP_BUFF_MAX; i++) {
- if (ctx->aux_infos.bufs[i].sei_buf != NULL) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
- "v4l2 free %dth aux buffer:%px\n",
- i, ctx->aux_infos.bufs[i].sei_buf);
- vfree(ctx->aux_infos.bufs[i].sei_buf);
- ctx->aux_infos.bufs[i].sei_state = 0;
- ctx->aux_infos.bufs[i].sei_size = 0;
- ctx->aux_infos.bufs[i].sei_buf = NULL;
- }
- }
- }
-}
-
-void aml_free_one_sei_buffer(struct aml_vcodec_ctx *ctx, char **addr, int *size, int idx)
-{
- if (ctx->aux_infos.bufs[idx].sei_buf != NULL) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
- "v4l2 free %dth aux buffer:%px\n",
- idx, ctx->aux_infos.bufs[idx].sei_buf);
-
- vfree(ctx->aux_infos.bufs[idx].sei_buf);
- ctx->aux_infos.bufs[idx].sei_state = 0;
- ctx->aux_infos.bufs[idx].sei_size = 0;
- ctx->aux_infos.bufs[idx].sei_buf = NULL;
- *addr = NULL;
- *size = 0;
- ctx->aux_infos.sei_need_free = true;
- }
-}
-
-void aml_bind_sei_buffer(struct aml_vcodec_ctx *ctx, char **addr, int *size, int *idx)
-{
- int index = ctx->aux_infos.sei_index;
- int count = 0;
-
- if (ctx->aux_infos.sei_need_free) {
- for (count = 0; count < V4L_CAP_BUFF_MAX; count++) {
- if ((ctx->aux_infos.bufs[index].sei_buf != NULL) &&
- (ctx->aux_infos.bufs[index].sei_state == 1)) {
- break;
- }
- index = (index + 1) % V4L_CAP_BUFF_MAX;
- }
- } else {
- for (count = 0; count < V4L_CAP_BUFF_MAX; count++) {
- if ((ctx->aux_infos.bufs[index].sei_buf != NULL) &&
- ((ctx->aux_infos.bufs[index].sei_state == 1) ||
- (ctx->aux_infos.bufs[index].sei_state == 2))) {
- memset(ctx->aux_infos.bufs[index].sei_buf, 0, SEI_BUF_SIZE);
- ctx->aux_infos.bufs[index].sei_size = 0;
- break;
- }
- index = (index + 1) % V4L_CAP_BUFF_MAX;
- }
- }
-
- if (count == V4L_CAP_BUFF_MAX) {
- *addr = NULL;
- *size = 0;
- } else {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
- "v4l2 bind %dth aux buffer:%px, count = %d\n",
- index, ctx->aux_infos.bufs[index].sei_buf, count);
- *addr = ctx->aux_infos.bufs[index].sei_buf;
- *size = ctx->aux_infos.bufs[index].sei_size;
- *idx = index;
- ctx->aux_infos.bufs[index].sei_state = 2;
- ctx->aux_infos.sei_index = (index + 1) % V4L_CAP_BUFF_MAX;
- }
-}
-
-void aml_bind_dv_buffer(struct aml_vcodec_ctx *ctx, char **comp_buf, char **md_buf)
-{
- int index = ctx->aux_infos.dv_index;
-
- if ((ctx->aux_infos.bufs[index].comp_buf != NULL) &&
- (ctx->aux_infos.bufs[index].md_buf != NULL)) {
- *comp_buf = ctx->aux_infos.bufs[index].comp_buf;
- *md_buf = ctx->aux_infos.bufs[index].md_buf;
- ctx->aux_infos.dv_index = (index + 1) % V4L_CAP_BUFF_MAX;
- }
-}
-
-void aml_v4l_ctx_release(struct kref *kref)
-{
- struct aml_vcodec_ctx * ctx;
-
- ctx = container_of(kref, struct aml_vcodec_ctx, ctx_ref);
-
- if (ctx->vpp) {
- atomic_dec(&ctx->dev->vpp_count);
- aml_v4l2_vpp_destroy(ctx->vpp);
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
- "vpp destory inst count:%d.\n",
- atomic_read(&ctx->dev->vpp_count));
- }
-
- if (ctx->ge2d) {
- aml_v4l2_ge2d_destroy(ctx->ge2d);
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
- "ge2d destory.\n");
- }
-
- v4l2_m2m_ctx_release(ctx->m2m_ctx);
- aml_task_chain_remove(ctx);
-
- vfree(ctx->meta_infos.meta_bufs);
- ctx->aux_infos.free_buffer(ctx, SEI_TYPE | DV_TYPE);
- ctx->aux_infos.free_buffer(ctx, 1);
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
- "v4ldec has been destroyed.\n");
-
- if (ctx->sync) {
- vdec_clean_all_fence(ctx->sync);
- }
-
- kfree(ctx);
-}
-
-static void box_release(struct kref *kref)
-{
- struct aml_vcodec_ctx * ctx
- = container_of(kref, struct aml_vcodec_ctx, box_ref);
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
- "%s, bmmu: %px, mmu: %px mmu_dw: %pu\n",
- __func__, ctx->bmmu_box, ctx->mmu_box,ctx->mmu_box_dw);
-
- decoder_bmmu_box_free(ctx->bmmu_box);
- decoder_mmu_box_free(ctx->mmu_box);
-
- if (ctx->config.parm.dec.cfg.double_write_mode & 0x20) {
- decoder_mmu_box_free(ctx->mmu_box_dw);
- decoder_bmmu_box_free(ctx->bmmu_box_dw);
- }
- vfree(ctx->comp_bufs);
- vfree(ctx->uvm_proxy);
- kref_put(&ctx->ctx_ref, aml_v4l_ctx_release);
-}
-
-static void internal_buf_free(void *arg)
-{
- struct internal_comp_buf* ibuf =
- (struct internal_comp_buf*)arg;
- struct aml_vcodec_ctx * ctx
- = container_of(ibuf->box_ref,struct aml_vcodec_ctx, box_ref);
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
- "%s, idx:%d\n", __func__, ibuf->index);
-
- mutex_lock(&ctx->comp_lock);
-
- if (!(ibuf->ref & 0xff00)) {
- decoder_mmu_box_free_idx(ibuf->mmu_box, ibuf->index);
- decoder_bmmu_box_free_idx(ibuf->bmmu_box, ibuf->index);
-
- if (ctx->config.parm.dec.cfg.double_write_mode & 0x20) {
- decoder_mmu_box_free_idx(ibuf->mmu_box_dw, ibuf->index);
- decoder_bmmu_box_free_idx(ibuf->bmmu_box_dw, ibuf->index);
- }
- }
- ibuf->ref = 0;
-
- mutex_unlock(&ctx->comp_lock);
-
- kref_put(ibuf->box_ref, box_release);
-}
-
-static void internal_buf_free2(void *arg)
-{
- struct internal_comp_buf *ibuf =
- container_of(arg, struct internal_comp_buf, priv_data);
- struct aml_vcodec_ctx * ctx
- = container_of(ibuf->box_ref, struct aml_vcodec_ctx, box_ref);
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
- "%s, idx: %d\n", __func__, ibuf->index);
-
- mutex_lock(&ctx->comp_lock);
-
- if (!(ibuf->ref & 0xff00)) {
- decoder_mmu_box_free_idx(ibuf->mmu_box, ibuf->index);
- decoder_bmmu_box_free_idx(ibuf->bmmu_box, ibuf->index);
-
- if (ctx->config.parm.dec.cfg.double_write_mode & 0x20) {
- decoder_mmu_box_free_idx(ibuf->mmu_box_dw, ibuf->index);
- decoder_bmmu_box_free_idx(ibuf->bmmu_box_dw, ibuf->index);
- }
- }
- ibuf->ref = 0;
-
- mutex_unlock(&ctx->comp_lock);
-
- kref_put(ibuf->box_ref, box_release);
-}
-
-static void aml_uvm_buf_free(void *arg)
-{
- struct aml_uvm_buff_ref * ubuf =
- (struct aml_uvm_buff_ref*)arg;
- struct aml_vcodec_ctx * ctx
- = container_of(ubuf->ref, struct aml_vcodec_ctx, ctx_ref);
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
- "%s, vb:%d, dbuf:%px, ino:%lu\n",
- __func__, ubuf->index, ubuf->dbuf,
- file_inode(ubuf->dbuf->file)->i_ino);
-
- kref_put(ubuf->ref, aml_v4l_ctx_release);
- vfree(ubuf);
-}
-
-static int uvm_attach_hook_mod_local(struct aml_vcodec_ctx *ctx,
- struct uvm_hook_mod_info *uvm)
-{
- struct internal_comp_buf* ibuf = uvm->arg;
-
- ctx->uvm_proxy[ibuf->index] = *uvm;
-
- return 0;
-}
-
-static int update_comp_buffer_to_reuse(struct aml_vcodec_ctx *ctx,
- struct aml_video_dec_buf *buf)
-{
- struct internal_comp_buf* ibuf = NULL;
-
- mutex_lock(&ctx->comp_lock);
-
- ibuf = vb_to_comp(ctx, &buf->vb.vb2_buf);
- if (!ibuf) {
- mutex_unlock(&ctx->comp_lock);
- return 0;
- }
-
- if (ibuf->ref & 0xff) {
- buf->internal_index = ibuf->index;
- ibuf->frame_buffer_size = ctx->comp_info.frame_buffer_size;
-
- if (ctx->comp_info.header_size != ibuf->header_size) {
- decoder_bmmu_box_free_idx(ctx->bmmu_box, ibuf->index);
- if (decoder_bmmu_box_alloc_buf_phy(ctx->bmmu_box,
- ibuf->index, ctx->comp_info.header_size,
- "v4l2_dec", &ibuf->header_addr) < 0) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "fail to alloc %dth bmmu\n",
- ibuf->index);
- mutex_unlock(&ctx->comp_lock);
- return -ENOMEM;
- }
- ibuf->header_size = ctx->comp_info.header_size;
- }
-
- ibuf->ref |= (1 << 8);
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
- "%s, reuse comp buffer vb2:%d <--> internal: %d, header_addr 0x%lx, size: %u\n",
- __func__, buf->vb.vb2_buf.index,
- buf->internal_index,
- ibuf->header_addr,
- ibuf->header_size);
- }
-
- mutex_unlock(&ctx->comp_lock);
-
- return (ibuf->ref & 0xff00) ? 1 : 0;
-}
-
-static int bind_comp_buffer_to_uvm(struct aml_vcodec_ctx *ctx,
- struct aml_video_dec_buf *buf)
-{
- int ret, i;
- struct dma_buf * dma = buf->vb.vb2_buf.planes[0].dbuf;
- struct aml_dec_params *parms = &ctx->config.parm.dec;
- struct uvm_hook_mod_info u_info;
- struct internal_comp_buf* ibuf;
- u32 dw_mode = VDEC_DW_NO_AFBC;
-
- /* get header and page size */
- if (vdec_if_get_param(ctx, GET_PARAM_COMP_BUF_INFO, &ctx->comp_info)) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to get comp info\n");
- return -EINVAL;
- }
-
- if (!ctx->bmmu_box || !ctx->mmu_box)
- if (init_mmu_bmmu_box(ctx))
- return -EINVAL;
-
- ret = update_comp_buffer_to_reuse(ctx, buf);
- if (ret < 0)
- return ret;
-
- if (ret == 1 /*reused*/)
- return 0;
-
- for (i = 0; i < V4L_CAP_BUFF_MAX; i++) {
- if (!ctx->comp_bufs[i].ref)
- break;
- }
-
- if (i == V4L_CAP_BUFF_MAX) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "out of internal buf\n");
- return -EINVAL;
- }
-
- if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode)) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "invalid dw_mode\n");
- return -EINVAL;
- }
-
- buf->internal_index = i;
- ibuf = &ctx->comp_bufs[i];
- ibuf->frame_buffer_size = ctx->comp_info.frame_buffer_size;
- ibuf->header_size = ctx->comp_info.header_size;
-
- /* allocate header */
- ret = decoder_bmmu_box_alloc_buf_phy(ctx->bmmu_box,
- ibuf->index, ctx->comp_info.header_size,
- "v4l2_dec", &ibuf->header_addr);
- if (ret < 0) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to alloc %dth bmmu\n", i);
- return -ENOMEM;
- }
-
- if (dw_mode & 0x20) {
- ret = decoder_bmmu_box_alloc_buf_phy(ctx->bmmu_box_dw,
- ibuf->index, ctx->comp_info.header_size,
- "v4l2_dec", &ibuf->header_dw_addr);
- if (ret < 0) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to alloc %dth bmmu dw\n", i);
- return -ENOMEM;
- }
- }
-
- kref_get(&ctx->box_ref);
- ibuf->ref = 1;
-
- /* frame SG buffer need to be realloc inside decoder,
- * just before slice decoding to save memory
- */
- u_info.type = VF_SRC_DECODER;
- u_info.arg = ibuf;
- u_info.free = internal_buf_free;
-
- if (parms->cfg.uvm_hook_type == VF_PROCESS_V4LVIDEO) {
- /* adapted video composer to use for hwc. */
- ibuf->priv_data.v4l_inst_id = ctx->id;
- u_info.type = VF_PROCESS_V4LVIDEO;
- u_info.arg = &ibuf->priv_data;
- u_info.free = internal_buf_free2;
- }
-
- ret = dmabuf_is_uvm(dma) ?
- uvm_attach_hook_mod(dma, &u_info) :
- uvm_attach_hook_mod_local(ctx, &u_info);
- if (ret < 0) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to set dmabuf priv buf\n");
- goto bmmu_box_free;
- }
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
- "%s, bind vb2:(%d, %px) <--> internal: (%d, %px) header_addr 0x%lx, size: %u\n",
- __func__, buf->vb.vb2_buf.index,
- dma, i, ibuf, ibuf->header_addr,
- ctx->comp_info.header_size);
-
- return 0;
-
-bmmu_box_free:
- if (dw_mode & 0x20) {
- decoder_bmmu_box_free_idx(ibuf->bmmu_box_dw, ibuf->index);
- }
- decoder_bmmu_box_free_idx(ibuf->bmmu_box, ibuf->index);
- kref_put(&ctx->box_ref, box_release);
- ibuf->ref = 0;
- return -EINVAL;
-}
-
-static int aml_uvm_buff_attach(struct vb2_buffer * vb)
-{
- int ret = 0;
- struct dma_buf *dbuf = vb->planes[0].dbuf;
- struct uvm_hook_mod_info u_info;
- struct aml_vcodec_ctx *ctx =
- vb2_get_drv_priv(vb->vb2_queue);
- struct aml_uvm_buff_ref *ubuf = NULL;
-
- if (vb->memory != VB2_MEMORY_DMABUF || !dmabuf_is_uvm(dbuf))
- return 0;
-
- ubuf = vzalloc(sizeof(struct aml_uvm_buff_ref));
- if (ubuf == NULL)
- return -ENOMEM;
-
- ubuf->index = vb->index;
- ubuf->addr = vb2_dma_contig_plane_dma_addr(vb, 0);
- ubuf->dbuf = dbuf;
- ubuf->ref = &ctx->ctx_ref;
-
- u_info.type = VF_PROCESS_DECODER;
- u_info.arg = (void *)ubuf;
- u_info.free = aml_uvm_buf_free;
- ret = uvm_attach_hook_mod(dbuf, &u_info);
- if (ret < 0) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "aml uvm buffer %d attach fail.\n",
- ubuf->index);
- return ret;
- }
-
- kref_get(ubuf->ref);
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
- "%s, vb:%d, dbuf:%px, ino:%lu\n",
- __func__, ubuf->index, ubuf->dbuf,
- file_inode(ubuf->dbuf->file)->i_ino);
-
- return ret;
-}
-
-static struct internal_comp_buf* vb_to_comp(struct aml_vcodec_ctx *ctx,
- struct vb2_buffer *vb)
-{
- struct aml_dec_params *parms = &ctx->config.parm.dec;
- bool is_v4lvideo = (parms->cfg.uvm_hook_type == VF_PROCESS_V4LVIDEO);
- enum uvm_hook_mod_type u_type =
- is_v4lvideo ? VF_PROCESS_V4LVIDEO : VF_SRC_DECODER;
- struct dma_buf *dbuf = vb->planes[0].dbuf;
- struct internal_comp_buf *ibuf = NULL;
- struct uvm_hook_mod *uhmod = NULL;
-
- uhmod = uvm_get_hook_mod(dbuf, u_type);
- if (IS_ERR_OR_NULL(uhmod))
- return NULL;
-
- ibuf = !is_v4lvideo ? (struct internal_comp_buf *) uhmod->arg :
- container_of(uhmod->arg, struct internal_comp_buf, priv_data);
-
- uvm_put_hook_mod(dbuf, u_type);
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
- "%s, vb2: (%d, %px) --> comp: (%d, %px)\n",
- __func__, vb->index, dbuf, ibuf->index, ibuf);
-
- return ibuf;
-}
-
static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb)
{
struct aml_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- struct vb2_v4l2_buffer *vb2_v4l2 = to_vb2_v4l2_buffer(vb);
- struct aml_video_dec_buf *buf =
- container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
- struct vdec_v4l2_buffer *fb = &buf->frame_buffer;
+ struct vb2_v4l2_buffer *vb2_v4l2 = NULL;
+ struct aml_video_dec_buf *buf = NULL;
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)) {
- u32 dw_mode = VDEC_DW_NO_AFBC;
-
- if (vdec_if_get_param(ctx, GET_PARAM_DW_MODE, &dw_mode)) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "invalid dw_mode\n");
+ 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;
-
}
+ 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 (!buf->que_in_m2m) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
"enque capture buf idx %d, vf: %lx\n",
vb->index, (ulong) v4l_get_vf_handle(vb2_v4l2->private));
- /* bind compressed buffer to uvm */
- if ((dw_mode != VDEC_DW_NO_AFBC) &&
- vb->memory == VB2_MEMORY_DMABUF &&
- bind_comp_buffer_to_uvm(ctx, buf)) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR, "fail to bind comp buffer\n");
- return;
- }
-
- /* DI hook must be detached if the dmabuff be reused. */
- if (ctx->vpp_cfg.enable_local_buf) {
- struct dma_buf *dma = vb->planes[0].dbuf;
-
- if (dmabuf_is_uvm(dma) &&
- uvm_detach_hook_mod(dma, VF_PROCESS_DI) < 0) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_EXINFO,
- "dmabuf without attach DI hook.\n");
- }
- }
-
- task_chain_clean(fb->task);
-
- ctx->cap_pool.seq[ctx->cap_pool.in++] =
- (V4L_CAP_BUFF_IN_M2M << 16 | vb->index);
v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2);
buf->que_in_m2m = true;
-
- fb->status = FB_ST_INIT;
- ATRACE_COUNTER("VC_IN_VSINK-2.storage", vb->index);
+ buf->queued_in_vb2 = true;
+ buf->queued_in_v4l2 = true;
+ buf->ready_to_display = false;
+ ctx->cap_pool.seq[ctx->cap_pool.in++] =
+ (V4L_CAP_BUFF_IN_M2M << 16 | vb->index);
/* check dpb ready */
aml_check_dpb_ready(ctx);
- } else {
- struct vframe_s *vf = fb->vframe;
- struct task_chain_s *task = fb->task;
+ } else if (buf->frame_buffer.status == FB_ST_DISPLAY) {
+ buf->queued_in_vb2 = false;
+ buf->queued_in_v4l2 = true;
+ buf->ready_to_display = false;
- 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);
+ /* recycle vf */
+ video_vf_put(ctx->ada_ctx->recv_name,
+ &buf->frame_buffer, ctx->id);
}
-
- wake_up_interruptible(&ctx->cap_wq);
return;
}
@@ -3795,41 +2125,28 @@
return;
}
- buf->used = true;
vb2_v4l2 = to_vb2_v4l2_buffer(vb);
buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
if (buf->lastframe) {
/* This shouldn't happen. Just in case. */
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
"Invalid flush buffer.\n");
- buf->used = false;
v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
- if (ctx->is_drm_mode && (vb->memory == VB2_MEMORY_DMABUF))
- wake_up_interruptible(&ctx->wq);
-
return;
}
src_mem.index = vb->index;
src_mem.vaddr = vb2_plane_vaddr(vb, 0);
- src_mem.addr = sg_dma_address(buf->out_sgt->sgl);
+ src_mem.addr = vb2_dma_contig_plane_dma_addr(vb, 0);
src_mem.size = vb->planes[0].bytesused;
src_mem.model = vb->memory;
src_mem.timestamp = vb->timestamp;
- src_mem.meta_ptr = (ulong)buf->meta_data;
if (vdec_if_probe(ctx, &src_mem, NULL)) {
- buf->used = false;
v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
- if (ctx->is_drm_mode &&
- (src_mem.model == VB2_MEMORY_DMABUF)) {
- wake_up_interruptible(&ctx->wq);
- } else {
- v4l2_buff_done(to_vb2_v4l2_buffer(vb),
- VB2_BUF_STATE_DONE);
- }
-
+ if (!(ctx->is_drm_mode && src_mem.model == VB2_MEMORY_DMABUF))
+ v4l2_m2m_buf_done(to_vb2_v4l2_buffer(vb), VB2_BUF_STATE_DONE);
return;
}
@@ -3837,14 +2154,11 @@
* If on model dmabuf must remove the buffer
* because this data has been consumed by hw.
*/
- buf->used = false;
- v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
-
- if (ctx->is_drm_mode &&
- (src_mem.model == VB2_MEMORY_DMABUF)) {
- wake_up_interruptible(&ctx->wq);
+ if (ctx->is_drm_mode && src_mem.model == VB2_MEMORY_DMABUF) {
+ v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
} else if (ctx->param_sets_from_ucode) {
- v4l2_buff_done(to_vb2_v4l2_buffer(vb),
+ v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+ v4l2_m2m_buf_done(to_vb2_v4l2_buffer(vb),
VB2_BUF_STATE_DONE);
}
@@ -3854,24 +2168,23 @@
return;
}
- if (!ctx->picinfo.dpb_frames)
+ 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)
return;
- v4l_buf_size_decision(ctx);
+ ctx->dpb_size = dpb;
ctx->last_decoded_picinfo = ctx->picinfo;
-
- v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
- "Picture buffer count: dec:%u, vpp:%u, ge2d:%u, margin:%u, total:%u\n",
- ctx->picinfo.dpb_frames, ctx->vpp_size, ctx->ge2d_size,
- ctx->picinfo.dpb_margin,
- CTX_BUF_TOTAL(ctx));
-
aml_vdec_dispatch_event(ctx, V4L2_EVENT_SRC_CH_RESOLUTION);
mutex_lock(&ctx->state_lock);
if (ctx->state == AML_STATE_INIT) {
ctx->state = AML_STATE_PROBE;
- ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+ ATRACE_COUNTER("v4l2_state", ctx->state);
v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
"vcodec state (AML_STATE_PROBE)\n");
}
@@ -3883,19 +2196,26 @@
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 = to_vb2_v4l2_buffer(vb);
+ vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
- if (buf->error) {
+ 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) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
"Unrecoverable error on buffer.\n");
ctx->state = AML_STATE_ABORT;
- ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
+ ATRACE_COUNTER("v4l2_state", ctx->state);
v4l_dbg(ctx, V4L_DEBUG_CODEC_STATE,
"vcodec state (AML_STATE_ABORT)\n");
}
@@ -3908,145 +2228,108 @@
struct vb2_v4l2_buffer, vb2_buf);
struct aml_video_dec_buf *buf = container_of(vb2_v4l2,
struct aml_video_dec_buf, vb);
- struct vdec_v4l2_buffer *fb = &buf->frame_buffer;
- u32 size, phy_addr = 0;
- int i;
+ unsigned int size, phy_addr = 0;
+ char *owner = __getname();
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)) {
+ 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 {
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) {
- char *owner = __getname();
-
- snprintf(owner, PATH_MAX, "%s-%d", "v4l-output", ctx->id);
+ 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);
strncpy(buf->mem_onwer, owner, sizeof(buf->mem_onwer));
buf->mem_onwer[sizeof(buf->mem_onwer) - 1] = '\0';
- __putname(owner);
- for (i = 0; i < vb->num_planes; i++) {
- size = vb->planes[i].length;
- phy_addr = vb2_dma_contig_plane_dma_addr(vb, i);
- buf->mem[i] = v4l_reqbufs_from_codec_mm(buf->mem_onwer,
- phy_addr, size, vb->index);
- v4l_dbg(ctx, V4L_DEBUG_CODEC_BUFMGR,
- "OUT %c alloc, addr: %x, size: %u, idx: %u\n",
- (i == 0? 'Y':'C'), phy_addr, size, vb->index);
- }
- } else if (vb->memory == VB2_MEMORY_DMABUF) {
- unsigned int dw_mode = VDEC_DW_NO_AFBC;
+ 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++) {
- struct dma_buf * dma;
+ 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);
- 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");
- }
+ 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 (!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;
- }
- }
+ __putname(owner);
return 0;
}
-static void vb2ops_vdec_buf_cleanup(struct vb2_buffer *vb)
+static void codec_mm_bufs_cnt_clean(struct vb2_queue *q)
{
- 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;;
+ 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;
- v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s, type: %d, idx: %d\n",
- __func__, vb->vb2_queue->type, vb->index);
+ 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;
- if (!V4L2_TYPE_IS_OUTPUT(vb->type)) {
- if (vb->memory == VB2_MEMORY_MMAP) {
- int i;
+ if (V4L2_TYPE_IS_OUTPUT(q->bufs[i]->type)) {
+ v4l_freebufs_back_to_codec_mm(buf->mem_onwer, buf->mem[0]);
- 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;
- }
+ 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;
}
- 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);
- }
+
+ 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;
}
}
}
@@ -4056,10 +2339,6 @@
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);
@@ -4080,81 +2359,40 @@
"%s, type: %d, state: %x, frame_cnt: %d\n",
__func__, q->type, ctx->state, ctx->decoded_frame_cnt);
- if (V4L2_TYPE_IS_OUTPUT(q->type))
- ctx->is_out_stream_off = true;
- else
- ctx->is_stream_off = true;
+ codec_mm_bufs_cnt_clean(q);
if (V4L2_TYPE_IS_OUTPUT(q->type)) {
- struct vb2_queue * que = v4l2_m2m_get_dst_vq(ctx->m2m_ctx);
- unsigned long flags;
-
- cancel_work_sync(&ctx->dmabuff_recycle_work);
- spin_lock_irqsave(&ctx->dmabuff_recycle_lock, flags);
- INIT_KFIFO(ctx->dmabuff_recycle);
- spin_unlock_irqrestore(&ctx->dmabuff_recycle_lock, flags);
-
while ((vb2_v4l2 = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
- v4l2_buff_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
+ v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
for (i = 0; i < q->num_buffers; ++i) {
vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]);
if (vb2_v4l2->vb2_buf.state == VB2_BUF_STATE_ACTIVE)
- v4l2_buff_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
- }
-
- /*
- * drop es frame was stored in the vdec_input
- * if the capture queue have not start streaming.
- */
- if (!que->streaming &&
- (vdec_frame_number(ctx->ada_ctx) > 0) &&
- (ctx->state < AML_STATE_ACTIVE)) {
- ctx->state = AML_STATE_INIT;
- ATRACE_COUNTER("V_ST_VSINK-state", ctx->state);
- ctx->v4l_resolution_change = false;
- ctx->reset_flag = V4L_RESET_MODE_NORMAL;
- v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO,
- "force reset to drop es frames.\n");
- wake_up_interruptible(&ctx->cap_wq);
- aml_vdec_reset(ctx);
+ v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
}
} else {
/* clean output cache and decoder status . */
- if (ctx->state > AML_STATE_INIT) {
- wake_up_interruptible(&ctx->cap_wq);
+ if (ctx->state > AML_STATE_INIT)
aml_vdec_reset(ctx);
- }
-
- cancel_work_sync(&ctx->decode_work);
- mutex_lock(&ctx->capture_buffer_lock);
- INIT_KFIFO(ctx->capture_buffer);
- mutex_unlock(&ctx->capture_buffer_lock);
while ((vb2_v4l2 = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)))
- v4l2_buff_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
+ v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
for (i = 0; i < q->num_buffers; ++i) {
vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]);
buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
- buf->frame_buffer.status = FB_ST_FREE;
- buf->frame_buffer.vframe = NULL;
- buf->que_in_m2m = false;
- buf->used = false;
- buf->vb.flags = 0;
- ctx->cap_pool.seq[i] = 0;
+ buf->frame_buffer.status = FB_ST_NORMAL;
+ buf->que_in_m2m = false;
+ buf->vb.flags = 0;
+ ctx->cap_pool.seq[i] = 0;
if (vb2_v4l2->vb2_buf.state == VB2_BUF_STATE_ACTIVE)
- v4l2_buff_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
+ v4l2_m2m_buf_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;
@@ -4172,6 +2410,15 @@
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;
@@ -4201,23 +2448,17 @@
switch (ctrl->id) {
case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
if (ctx->state >= AML_STATE_PROBE) {
- ctrl->val = CTX_BUF_TOTAL(ctx);
+ ctrl->val = ctx->dpb_size;
} 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;
}
@@ -4235,10 +2476,6 @@
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;
@@ -4261,42 +2498,6 @@
.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;
@@ -4307,42 +2508,24 @@
&aml_vcodec_dec_ctrl_ops,
V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
0, 32, 1, 2);
- if ((ctrl == NULL) || (ctx->ctrl_hdl.error)) {
+ ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+ if (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)) {
+ ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+ if (ctx->ctrl_hdl.error) {
ret = ctx->ctrl_hdl.error;
goto err;
}
- ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
ctrl = v4l2_ctrl_new_custom(&ctx->ctrl_hdl, &ctrl_st_mode, NULL);
- if ((ctrl == NULL) || (ctx->ctrl_hdl.error)) {
- ret = ctx->ctrl_hdl.error;
- goto err;
- }
-
- ctrl = v4l2_ctrl_new_custom(&ctx->ctrl_hdl, &ctrl_gt_input_buffer_number, NULL);
- if ((ctrl == NULL) || (ctx->ctrl_hdl.error)) {
- ret = ctx->ctrl_hdl.error;
- goto err;
- }
-
- ctrl = v4l2_ctrl_new_custom(&ctx->ctrl_hdl, &ctrl_st_duration, NULL);
- if ((ctrl == NULL) || (ctx->ctrl_hdl.error)) {
- ret = ctx->ctrl_hdl.error;
- goto err;
- }
-
- ctrl = v4l2_ctrl_new_custom(&ctx->ctrl_hdl, &ctrl_gt_filmgrain_info, NULL);
- if ((ctrl == NULL) || (ctx->ctrl_hdl.error)) {
+ if (ctx->ctrl_hdl.error) {
ret = ctx->ctrl_hdl.error;
goto err;
}
@@ -4362,25 +2545,16 @@
struct v4l2_streamparm *a)
{
struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
- struct vb2_queue *dst_vq;
- dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
- if (!dst_vq) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "no vb2 queue for type=%d\n", V4L2_BUF_TYPE_VIDEO_CAPTURE);
- return -EINVAL;
- }
-
- if (!V4L2_TYPE_IS_MULTIPLANAR(a->type) && dst_vq->is_multiplanar)
- return -EINVAL;
-
- if ((a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) || (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) {
- if (vdec_if_get_param(ctx, GET_PARAM_CONFIG_INFO, &ctx->config.parm.dec))
+ if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ if (vdec_if_get_param(ctx, GET_PARAM_CONFIG_INFO,
+ &ctx->config.parm.dec)) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
"GET_PARAM_CONFIG_INFO err\n");
- else
- memcpy(a->parm.raw_data, ctx->config.parm.data,
- sizeof(a->parm.raw_data));
+ return -1;
+ }
+ memcpy(a->parm.raw_data, ctx->config.parm.data,
+ sizeof(a->parm.raw_data));
}
v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s\n", __func__);
@@ -4388,65 +2562,22 @@
return 0;
}
-static int check_dec_cfginfo(struct aml_vdec_cfg_infos *cfg)
-{
- if (cfg->double_write_mode != 0 &&
- cfg->double_write_mode != 1 &&
- cfg->double_write_mode != 2 &&
- cfg->double_write_mode != 3 &&
- cfg->double_write_mode != 4 &&
- cfg->double_write_mode != 16 &&
- cfg->double_write_mode != 0x21 &&
- cfg->double_write_mode != 0x100 &&
- cfg->double_write_mode != 0x200) {
- pr_err("invalid double write mode %d\n", cfg->double_write_mode);
- return -1;
- }
- if (cfg->ref_buf_margin > 20) {
- pr_err("invalid margin %d\n", cfg->ref_buf_margin);
- return -1;
- }
-
- if (mandatory_dw_mmu) {
- cfg->double_write_mode = 0x21;
- }
-
- pr_info("double write mode %d margin %d\n",
- cfg->double_write_mode, cfg->ref_buf_margin);
- return 0;
-}
-
static int vidioc_vdec_s_parm(struct file *file, void *fh,
struct v4l2_streamparm *a)
{
struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
- struct vb2_queue *dst_vq;
v4l_dbg(ctx, V4L_DEBUG_CODEC_PROT, "%s\n", __func__);
- dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
- if (!dst_vq) {
- v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
- "no vb2 queue for type=%d\n", V4L2_BUF_TYPE_VIDEO_CAPTURE);
- return -EINVAL;
- }
-
- if (!V4L2_TYPE_IS_MULTIPLANAR(a->type) && dst_vq->is_multiplanar)
- return -EINVAL;
-
- if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT ||
- a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
struct aml_dec_params *in =
(struct aml_dec_params *) a->parm.raw_data;
struct aml_dec_params *dec = &ctx->config.parm.dec;
ctx->config.type = V4L2_CONFIG_PARM_DECODE;
- if (in->parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO) {
- if (check_dec_cfginfo(&in->cfg))
- return -EINVAL;
+ if (in->parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO)
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)
@@ -4455,37 +2586,31 @@
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 = {
@@ -4495,7 +2620,6 @@
.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,
@@ -4512,10 +2636,10 @@
.vidioc_qbuf = vidioc_vdec_qbuf,
.vidioc_dqbuf = vidioc_vdec_dqbuf,
- .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_vid_cap_out,
- .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap_out,
- .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_vid_cap_out,
- .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_cap_out,
+ .vidioc_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_s_fmt_vid_cap_mplane = vidioc_vdec_s_fmt,
.vidioc_s_fmt_vid_cap = vidioc_vdec_s_fmt,
@@ -4528,18 +2652,17 @@
.vidioc_create_bufs = vidioc_vdec_create_bufs,
- //fixme
- //.vidioc_enum_fmt_vid_cap_mplane = vidioc_vdec_enum_fmt_vid_cap_mplane,
- //.vidioc_enum_fmt_vid_out_mplane = vidioc_vdec_enum_fmt_vid_out_mplane,
+ .vidioc_enum_fmt_vid_cap_mplane = vidioc_vdec_enum_fmt_vid_cap_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,
@@ -4557,11 +2680,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 | VB2_USERPTR;
+ src_vq->io_modes = VB2_DMABUF | VB2_MMAP;
src_vq->drv_priv = ctx;
src_vq->buf_struct_size = sizeof(struct aml_video_dec_buf);
src_vq->ops = &aml_vdec_vb2_ops;
- src_vq->mem_ops = &vb2_dma_sg_memops;
+ src_vq->mem_ops = &vb2_dma_contig_memops;
src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
src_vq->lock = &ctx->dev->dev_mutex;
ret = vb2_queue_init(src_vq);
@@ -4580,7 +2703,6 @@
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 a23522c..3653ff0 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.h
+++ b/drivers/amvdec_ports/aml_vcodec_dec.h
@@ -20,14 +20,11 @@
#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
@@ -41,25 +38,15 @@
#define VDEC_GATHER_MEMORY_TYPE 0
#define VDEC_SCATTER_MEMORY_TYPE 1
-#define META_DATA_SIZE (256)
-#define MD_BUF_SIZE (1024)
-#define COMP_BUF_SIZE (8196)
-#define SEI_BUF_SIZE (2 * 12 * 1024)
-#define SEI_TYPE (1)
-#define DV_TYPE (2)
-
-
-/*
- * struct vdec_v4l2_buffer - decoder frame buffer
+/**
+ * struct vdec_fb - 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 {
@@ -69,19 +56,22 @@
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.
* @b: VB2 buffer
* @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
@@ -97,21 +87,12 @@
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;
@@ -130,19 +111,16 @@
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 18f0254..1ed0b97 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_vpp.h"
+#include "aml_vcodec_vfm.h"
#include <linux/file.h>
#include <linux/anon_inodes.h>
@@ -50,7 +50,6 @@
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)
{
@@ -63,21 +62,12 @@
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++;
@@ -86,26 +76,14 @@
v4l2_fh_add(&ctx->fh);
INIT_LIST_HEAD(&ctx->list);
INIT_LIST_HEAD(&ctx->vdec_thread_list);
- INIT_LIST_HEAD(&ctx->task_chain_pool);
dev->filp = file;
ctx->dev = dev;
init_waitqueue_head(&ctx->queue);
- mutex_init(&ctx->capture_buffer_lock);
- mutex_init(&ctx->buff_done_lock);
mutex_init(&ctx->state_lock);
- mutex_init(&ctx->comp_lock);
+ mutex_init(&ctx->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) {
@@ -133,19 +111,9 @@
ctx->output_thread_ready = true;
ctx->empty_flush_buf->vb.vb2_buf.vb2_queue = src_vq;
ctx->empty_flush_buf->lastframe = true;
- ctx->vdec_pic_info_update = aml_vdec_pic_info_update;
aml_vcodec_dec_set_default_params(ctx);
- ctx->is_stream_off = true;
- ctx->aux_infos.dv_index = 0;
- ctx->aux_infos.sei_index = 0;
- ctx->aux_infos.alloc_buffer = aml_alloc_buffer;
- ctx->aux_infos.free_buffer = aml_free_buffer;
- ctx->aux_infos.bind_sei_buffer = aml_bind_sei_buffer;
- ctx->aux_infos.bind_dv_buffer = aml_bind_dv_buffer;
- ctx->aux_infos.free_one_sei_buffer = aml_free_one_sei_buffer;
-
- ret = aml_thread_start(ctx, aml_thread_capture_worker, AML_THREAD_CAPTURE, "cap");
+ ret = aml_thread_start(ctx, try_to_capture, AML_THREAD_CAPTURE, "cap");
if (ret) {
v4l_dbg(ctx, V4L_DEBUG_CODEC_ERROR,
"Failed to creat capture thread.\n");
@@ -158,7 +126,7 @@
v4l_dbg(ctx, V4L_DEBUG_CODEC_PRINFO, "%s decoder %lx\n",
dev_name(&dev->plat_dev->dev), (ulong)ctx);
- return 0;
+ return ret;
/* Deinit when failure occurred */
err_creat_thread:
@@ -168,7 +136,6 @@
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);
@@ -184,20 +151,24 @@
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);
- vb2_queue_release(&ctx->m2m_ctx->cap_q_ctx.q);
- vb2_queue_release(&ctx->m2m_ctx->out_q_ctx.q);
-
+ v4l2_m2m_ctx_release(ctx->m2m_ctx);
aml_vcodec_dec_release(ctx);
+
v4l2_fh_del(&ctx->fh);
v4l2_fh_exit(&ctx->fh);
v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
list_del_init(&ctx->list);
-
kfree(ctx->empty_flush_buf);
- kref_put(&ctx->ctx_ref, aml_v4l_ctx_release);
+ kfree(ctx);
mutex_unlock(&dev->dev_mutex);
return 0;
}
@@ -331,10 +302,8 @@
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;
}
@@ -446,43 +415,6 @@
.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;
@@ -495,7 +427,6 @@
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);
@@ -506,7 +437,8 @@
ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
if (ret) {
- dev_err(&pdev->dev, "v4l2_device_register err=%d\n", ret);
+ v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+ "v4l2_device_register err=%d\n", ret);
goto err_res;
}
@@ -514,7 +446,8 @@
vfd_dec = video_device_alloc();
if (!vfd_dec) {
- dev_err(&pdev->dev, "Failed to allocate video device\n");
+ v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+ "Failed to allocate video device\n");
ret = -ENOMEM;
goto err_dec_alloc;
}
@@ -526,7 +459,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);
@@ -536,16 +469,18 @@
dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops);
if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
- dev_err(&pdev->dev, "Failed to init mem2mem dec device\n");
+ v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+ "Failed to init mem2mem dec device\n");
ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
goto err_dec_mem_init;
}
dev->decode_workqueue =
- alloc_ordered_workqueue("output-worker",
- __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_HIGHPRI);
+ alloc_ordered_workqueue(AML_VCODEC_DEC_NAME,
+ WQ_MEM_RECLAIM | WQ_FREEZABLE);
if (!dev->decode_workqueue) {
- dev_err(&pdev->dev, "Failed to create decode workqueue\n");
+ v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+ "Failed to create decode workqueue\n");
ret = -EINVAL;
goto err_event_workq;
}
@@ -554,26 +489,16 @@
ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, 26);
if (ret) {
- dev_err(&pdev->dev, "Failed to register video device\n");
+ v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
+ "Failed to register video device\n");
goto err_dec_reg;
}
- /*init class*/
- dev->v4ldec_class.name = "v4ldec";
- dev->v4ldec_class.owner = THIS_MODULE;
- dev->v4ldec_class.class_groups = v4ldec_class_groups;
- ret = class_register(&dev->v4ldec_class);
- if (ret) {
- dev_err(&pdev->dev, "v4l dec class create fail.\n");
- goto err_reg_class;
- }
-
- dev_info(&pdev->dev, "v4ldec registered as /dev/video%d\n", vfd_dec->num);
+ v4l_dbg(0, V4L_DEBUG_CODEC_PRINFO,
+ "decoder 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:
@@ -587,6 +512,13 @@
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);
@@ -594,8 +526,6 @@
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);
@@ -604,17 +534,12 @@
v4l2_device_unregister(&dev->v4l2_dev);
- dev_info(&pdev->dev, "v4ldec removed.\n");
-
return 0;
}
-static const struct of_device_id aml_vcodec_match[] = {
- {.compatible = "amlogic, vcodec-dec",},
- {},
-};
-
-MODULE_DEVICE_TABLE(of, aml_vcodec_match);
+/*static void aml_vcodec_dev_release(struct device *dev)
+{
+}*/
static struct platform_driver aml_vcodec_dec_driver = {
.probe = aml_vcodec_probe,
@@ -625,36 +550,44 @@
},
};
+/*
+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)
{
- pr_info("v4l dec module init\n");
+ int ret;
- if (platform_driver_register(&aml_vcodec_dec_driver)) {
- pr_err("failed to register v4l dec driver\n");
- return -ENODEV;
- }
+ ret = platform_device_register(&aml_vcodec_dec_device);
+ if (ret)
+ return ret;
- return 0;
+ ret = platform_driver_register(&aml_vcodec_dec_driver);
+ if (ret)
+ platform_device_unregister(&aml_vcodec_dec_device);
+
+ return ret;
}
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);
@@ -683,72 +616,20 @@
EXPORT_SYMBOL(multiplanar);
module_param(multiplanar, bool, 0644);
-int dump_capture_frame;
+bool dump_capture_frame;
EXPORT_SYMBOL(dump_capture_frame);
-module_param(dump_capture_frame, int, 0644);
-
-int dump_vpp_input;
-EXPORT_SYMBOL(dump_vpp_input);
-module_param(dump_vpp_input, int, 0644);
-
-int dump_ge2d_input;
-EXPORT_SYMBOL(dump_ge2d_input);
-module_param(dump_ge2d_input, int, 0644);
+module_param(dump_capture_frame, bool, 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 522fe67..2e9e576 100644
--- a/drivers/amvdec_ports/aml_vcodec_drv.h
+++ b/drivers/amvdec_ports/aml_vcodec_drv.h
@@ -20,19 +20,14 @@
#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"
@@ -71,8 +66,6 @@
#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. */
@@ -86,7 +79,6 @@
/* 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
*/
@@ -127,6 +119,7 @@
* @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 {
@@ -137,6 +130,7 @@
AML_STATE_ACTIVE,
AML_STATE_FLUSHING,
AML_STATE_FLUSHED,
+ AML_STATE_RESET,
AML_STATE_ABORT,
};
@@ -162,10 +156,9 @@
* 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;
- const u8 *name;
+ u32 num_planes;
};
/**
@@ -190,13 +183,13 @@
* struct aml_q_data - Structure used to store information about queue
*/
struct aml_q_data {
- u32 visible_width;
- u32 visible_height;
- u32 coded_width;
- u32 coded_height;
+ unsigned int visible_width;
+ unsigned int visible_height;
+ unsigned int coded_width;
+ unsigned int coded_height;
enum v4l2_field field;
- u32 bytesperline[AML_VCODEC_MAX_PLANES];
- u32 sizeimage[AML_VCODEC_MAX_PLANES];
+ unsigned int bytesperline[AML_VCODEC_MAX_PLANES];
+ unsigned int sizeimage[AML_VCODEC_MAX_PLANES];
struct aml_video_fmt *fmt;
bool resolution_changed;
};
@@ -221,19 +214,42 @@
* @force_intra: force/insert intra frame
*/
struct aml_enc_params {
- u32 bitrate;
- u32 num_b_frame;
- u32 rc_frame;
- u32 rc_mb;
- u32 seq_hdr_mode;
- u32 intra_period;
- u32 gop_size;
- u32 framerate_num;
- u32 framerate_denom;
- u32 h264_max_qp;
- u32 h264_profile;
- u32 h264_level;
- u32 force_intra;
+ 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;
};
/**
@@ -250,38 +266,20 @@
* plane
* E.g. suppose picture size is 176x144,
* buffer size will be aligned to 176x160.
- * @profile_idc: source profile level
* @field: frame/field information.
- * @dpb_frames: used for DPB size of calculation.
- * @dpb_margin: extra buffers for decoder.
- * @vpp_margin: extra buffers for vpp.
*/
struct vdec_pic_info {
- u32 visible_width;
- u32 visible_height;
- u32 coded_width;
- u32 coded_height;
- u32 y_bs_sz;
- u32 c_bs_sz;
- u32 y_len_sz;
- u32 c_len_sz;
+ 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;
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 {
@@ -292,20 +290,6 @@
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 {
@@ -339,10 +323,8 @@
u32 mb_height;
u32 dpb_size;
u32 ref_frames;
- u32 dpb_frames;
- u32 dpb_margin;
+ u32 reorder_frames;
u32 field;
- u32 data[3];
};
struct aml_vdec_cnt_infos {
@@ -379,7 +361,7 @@
*/
u32 seq[V4L_CAP_BUFF_MAX];
u32 in, out;
- u32 dec, vpp, ge2d;
+ u32 dec, vpp;
};
enum aml_thread_type {
@@ -390,203 +372,35 @@
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.
@@ -594,7 +408,6 @@
* @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.
@@ -617,46 +430,24 @@
* @reset_flag: reset mode includes lightly and normal mode.
* @decoded_frame_cnt: the capture buffer deque number to be count.
* @buf_used_count: means that decode allocate how many buffs from v4l.
- * @wq: wait recycle dma buffer finish.
- * @cap_wq: the wq used for wait capture buffer.
- * @dmabuff_recycle_lock: protect the lock dmabuff free.
- * @dmabuff_recycle_work: used for recycle dmabuff.
- * @dmabuff_recycle: kfifo used for store vb buff.
- * @capture_buffer: kfifo used for store capture vb buff.
- * @mmu_box: mmu_box of context.
- * @bmmu_box: bmmu_box of context.
- * @box_ref: box_ref of context.
- * @comp_info: compress buffer information.
- * @comp_bufs: compress buffer describe.
- * @comp_lock: used for lock ibuf free cb.
- * @fb_ops: frame buffer ops interface.
- * @dv_infos: dv data information.
- * @vpp_cfg: vpp init parms of configuration.
- * @vdec_pic_info_update: update pic info cb.
- * @vpp_is_need: the instance is need vpp.
- * @task_chain_pool: used to store task chain inst.
- * @index_disp: the number of frames output.
*/
struct aml_vcodec_ctx {
int id;
- struct kref ctx_ref;
enum aml_instance_type type;
struct aml_vcodec_dev *dev;
struct v4l2_m2m_ctx *m2m_ctx;
struct aml_vdec_adapt *ada_ctx;
- struct aml_v4l2_vpp *vpp;
const struct vdec_common_if *dec_if;
ulong drv_handle;
struct v4l2_fh fh;
struct v4l2_ctrl_handler ctrl_hdl;
spinlock_t slock;
- spinlock_t tsplock;
struct aml_video_dec_buf *empty_flush_buf;
struct list_head list;
struct aml_q_data q_data[2];
wait_queue_head_t queue;
- struct mutex state_lock;
+ struct mutex lock, state_lock;
enum aml_instance_state state;
struct work_struct decode_work;
bool output_thread_ready;
@@ -664,8 +455,6 @@
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;
@@ -678,7 +467,6 @@
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;
@@ -689,84 +477,81 @@
int reset_flag;
int decoded_frame_cnt;
int buf_used_count;
- wait_queue_head_t wq, cap_wq, post_done_wq;
- struct mutex capture_buffer_lock;
- spinlock_t dmabuff_recycle_lock;
- struct mutex buff_done_lock;
- struct work_struct dmabuff_recycle_work;
- DECLARE_KFIFO(dmabuff_recycle, struct vb2_v4l2_buffer *, 32);
- DECLARE_KFIFO(capture_buffer, struct vb2_v4l2_buffer *, 32);
-
- /* compressed buffer support */
- void *bmmu_box;
- void *mmu_box;
- struct kref box_ref;
- struct vdec_comp_buf_info comp_info;
- struct internal_comp_buf *comp_bufs;
- struct uvm_hook_mod_info *uvm_proxy;
- struct mutex comp_lock;
-
- struct aml_fb_ops fb_ops;
- ulong token_table[32];
-
- struct aml_fb_map_table fb_map[32];
- struct aml_vpp_cfg_infos vpp_cfg;
- void (*vdec_pic_info_update)(struct aml_vcodec_ctx *ctx);
- bool vpp_is_need;
- struct list_head task_chain_pool;
- struct meta_info meta_infos;
- struct vdec_sync *sync;
- u32 internal_dw_scale;
-
- /* ge2d field. */
- struct aml_v4l2_ge2d *ge2d;
- struct aml_ge2d_cfg_infos ge2d_cfg;
- bool ge2d_is_need;
-
- bool second_field_pts_mode;
- struct aux_info aux_infos;
- u32 index_disp;
- bool post_to_upper_done;
- bool film_grain_present;
- void *bmmu_box_dw;
- void *mmu_box_dw;
};
/**
- * struct aml_vcodec_dev - driver data.
- * @v4l2_dev : V4L2 device to register video devices for.
- * @vfd_dec : Video device for decoder.
- * @plat_dev : platform device.
- * @m2m_dev_dec : m2m device for decoder.
- * @curr_ctx : The context that is waiting for codec hardware.
- * @id_counter : used to identify current opened instance.
- * @dec_capability : used to identify decode capability, ex: 4k
- * @decode_workqueue : the worker used to output buffer schedule.
- * @ctx_list : list of struct aml_vcodec_ctx.
- * @irqlock : protect data access by irq handler and work thread.
- * @dev_mutex : video_device lock.
- * @dec_mutex : decoder hardware lock.
- * @queue : waitqueue for waiting for completion of device commands.
- * @vpp_count : count the number of open vpp.
- * @v4ldec_class : creat class sysfs uesd to show some information.
+ * struct aml_vcodec_dev - 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 {
- 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;
+ 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;
};
static inline struct aml_vcodec_ctx *fh_to_ctx(struct v4l2_fh *fh)
@@ -779,10 +564,4 @@
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
deleted file mode 100644
index 2d331ed..0000000
--- a/drivers/amvdec_ports/aml_vcodec_ge2d.c
+++ /dev/null
@@ -1,968 +0,0 @@
-/*
-* 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, ¶m);
-
- *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
deleted file mode 100644
index a12931d..0000000
--- a/drivers/amvdec_ports/aml_vcodec_ge2d.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-* 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 54b0d06..509a42a 100644
--- a/drivers/amvdec_ports/aml_vcodec_util.c
+++ b/drivers/amvdec_ports/aml_vcodec_util.c
@@ -22,6 +22,72 @@
#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 96c5453..312ee40 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,16 +45,14 @@
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
@@ -71,11 +69,6 @@
#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 { \
@@ -99,6 +92,12 @@
} \
} 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
new file mode 100644
index 0000000..62896ea
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_vfm.c
@@ -0,0 +1,245 @@
+/*
+* 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
new file mode 100644
index 0000000..141e9a7
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_vfm.h
@@ -0,0 +1,60 @@
+/*
+* 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
new file mode 100644
index 0000000..e19c53c
--- /dev/null
+++ b/drivers/amvdec_ports/aml_vcodec_vfq.h
@@ -0,0 +1,112 @@
+/*
+* 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
deleted file mode 100644
index 9f4e960..0000000
--- a/drivers/amvdec_ports/aml_vcodec_vpp.c
+++ /dev/null
@@ -1,1102 +0,0 @@
-/*
-* 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, ¶m);
-
- 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, ¶m);
-
- 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
deleted file mode 100644
index 7a5771d..0000000
--- a/drivers/amvdec_ports/aml_vcodec_vpp.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
-* 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 d0d0198..c9da299 100644
--- a/drivers/amvdec_ports/decoder/aml_h264_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_h264_parser.c
@@ -1,3 +1,22 @@
+/*
+* 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 24977a8..4ea76b9 100644
--- a/drivers/amvdec_ports/decoder/aml_hevc_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_hevc_parser.c
@@ -1,3 +1,22 @@
+/*
+* 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 9223639..0c81cb5 100644
--- a/drivers/amvdec_ports/decoder/aml_hevc_parser.h
+++ b/drivers/amvdec_ports/decoder/aml_hevc_parser.h
@@ -22,6 +22,7 @@
#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 c582ab0..fd56755 100644
--- a/drivers/amvdec_ports/decoder/aml_mjpeg_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.c
@@ -1,3 +1,22 @@
+/*
+* 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 4704ba0..bbc9282 100644
--- a/drivers/amvdec_ports/decoder/aml_mjpeg_parser.h
+++ b/drivers/amvdec_ports/decoder/aml_mjpeg_parser.h
@@ -1,3 +1,19 @@
+/*
+ * 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 748a83f..2720446 100644
--- a/drivers/amvdec_ports/decoder/aml_mpeg12_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.c
@@ -1,3 +1,22 @@
+/*
+* 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 c06d632..8abbc78 100644
--- a/drivers/amvdec_ports/decoder/aml_mpeg12_parser.h
+++ b/drivers/amvdec_ports/decoder/aml_mpeg12_parser.h
@@ -1,3 +1,19 @@
+/*
+ * 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
@@ -7,6 +23,7 @@
#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 9c47c08..f680b12 100644
--- a/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.c
@@ -1,3 +1,22 @@
+/*
+* 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 f9b71cf..3e5bf62 100644
--- a/drivers/amvdec_ports/decoder/aml_mpeg4_parser.h
+++ b/drivers/amvdec_ports/decoder/aml_mpeg4_parser.h
@@ -1,3 +1,19 @@
+/*
+ * 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 21d5283..b027b8a 100644
--- a/drivers/amvdec_ports/decoder/aml_vp9_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_vp9_parser.c
@@ -1,3 +1,22 @@
+/*
+* 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 c28ca10..e8693d4 100644
--- a/drivers/amvdec_ports/decoder/vdec_av1_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_av1_if.c
@@ -29,6 +29,7 @@
#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
@@ -117,9 +118,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. */
@@ -206,7 +207,6 @@
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:7;");
- pbuf += sprintf(pbuf, "av1_double_write_mode:1;");
+ pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:11;");
+ pbuf += sprintf(pbuf, "av1_double_write_mode:3;");
pbuf += sprintf(pbuf, "av1_buf_width:1920;");
pbuf += sprintf(pbuf, "av1_buf_height:1088;");
- pbuf += sprintf(pbuf, "av1_max_pic_w:4096;");
- pbuf += sprintf(pbuf, "av1_max_pic_h:2304;");
+ pbuf += sprintf(pbuf, "av1_max_pic_w:8192;");
+ pbuf += sprintf(pbuf, "av1_max_pic_h:4608;");
pbuf += sprintf(pbuf, "save_buffer_mode:0;");
pbuf += sprintf(pbuf, "no_head:0;");
pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
@@ -264,10 +264,6 @@
{
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;
@@ -277,8 +273,10 @@
ctx->config.parm.dec.cfg.ref_buf_margin);
pbuf += sprintf(pbuf, "av1_double_write_mode:%d;",
ctx->config.parm.dec.cfg.double_write_mode);
- pbuf += sprintf(pbuf, "av1_buf_width:1920;");
- pbuf += sprintf(pbuf, "av1_buf_height:1088;");
+ pbuf += sprintf(pbuf, "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, "save_buffer_mode:0;");
pbuf += sprintf(pbuf, "no_head:0;");
pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
@@ -287,23 +285,19 @@
ctx->config.parm.dec.cfg.canvas_mem_endian);
pbuf += sprintf(pbuf, "parm_v4l_low_latency_mode:%d;",
ctx->config.parm.dec.cfg.low_latency_mode);
- pbuf += sprintf(pbuf, "parm_v4l_duration:%d;",
- ctx->config.parm.dec.cfg.duration);
ctx->config.length = pbuf - ctx->config.buf;
} else {
- ctx->config.parm.dec.cfg.double_write_mode = 1;
+ ctx->config.parm.dec.cfg.double_write_mode = 16;
ctx->config.parm.dec.cfg.ref_buf_margin = 7;
ctx->config.length = vdec_config_default_parms(ctx->config.buf);
}
if ((ctx->config.parm.dec.parms_status &
V4L2_CONFIG_PARM_DECODE_HDRINFO) &&
- ctx->config.parm.dec.hdr.color_parms.present_flag) {
+ inst->parms.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;",
@@ -332,8 +326,6 @@
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;
@@ -349,7 +341,6 @@
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;
@@ -364,6 +355,16 @@
/* 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) {
@@ -372,7 +373,7 @@
}
/* alloc the header buffer to be used cache sps or spp etc.*/
- inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
+ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
if (!inst->vsi->header_buf) {
ret = -ENOMEM;
goto err;
@@ -380,6 +381,9 @@
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;
@@ -391,13 +395,14 @@
goto err;
}
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
- "av1 Instance >> %lx\n", (ulong) inst);
+ //dump_init();
return 0;
err:
+ if (inst)
+ vcodec_vfm_release(&inst->vfm);
if (inst && inst->vsi && inst->vsi->header_buf)
- vfree(inst->vsi->header_buf);
+ kfree(inst->vsi->header_buf);
if (inst && inst->vsi)
kfree(inst->vsi);
if (inst)
@@ -423,7 +428,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_ucode_dma(struct vdec_av1_inst *inst,
@@ -444,7 +449,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_cpu(struct vdec_av1_inst *inst, u8 *buf, u32 size)
@@ -499,13 +504,19 @@
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)
- vfree(inst->vsi->header_buf);
+ kfree(inst->vsi->header_buf);
if (inst->vsi)
kfree(inst->vsi);
@@ -513,6 +524,42 @@
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.
@@ -589,7 +636,7 @@
int i;
const size_t leb_size = uleb_size_in_bytes(value);
- if (value > kMaximumLeb128Value || leb_size > kMaximumLeb128Size ||
+ if (leb_size > kMaximumLeb128Size ||
leb_size > available || !coded_value || !coded_size) {
return -1;
}
@@ -657,12 +704,13 @@
static int read_obu_header(struct read_bit_buffer *rb,
int is_annexb, struct ObuHeader *header)
{
- const int bit_buffer_byte_length =
- rb->bit_buffer_end - rb->bit_buffer;
+ int bit_buffer_byte_length;
if (!rb || !header)
return -1;
+ bit_buffer_byte_length = rb->bit_buffer_end - rb->bit_buffer;
+
if (bit_buffer_byte_length < 1)
return -1;
@@ -1000,13 +1048,13 @@
parser_frame(0, src, src + size, data, &length, meta_buffer, &meta_size);
if (length)
- ret = vdec_vframe_write(vdec, data, length, ts, 0);
+ ret = vdec_vframe_write(vdec, data, length, ts);
else
ret = -1;
vfree(data);
} else {
- ret = vdec_vframe_write(vdec, buf, size, ts, 0);
+ ret = vdec_vframe_write(vdec, buf, size, ts);
}
return ret;
@@ -1040,14 +1088,18 @@
{
struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec;
struct aml_vdec_adapt *vdec = &inst->vdec;
- u8 *buf = (u8 *) bs->vaddr;
- u32 size = bs->size;
+ u8 *buf;
+ u32 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;
}
@@ -1069,8 +1121,7 @@
ret = vdec_vframe_write(vdec,
s->data,
s->len,
- bs->timestamp,
- 0);
+ bs->timestamp);
} else if (bs->model == VB2_MEMORY_DMABUF ||
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
@@ -1086,6 +1137,7 @@
ret = vdec_write_nalu(inst, buf, size, bs->timestamp);
}
+ ATRACE_COUNTER("v4l2_decode_write", ret);
return ret;
}
@@ -1093,12 +1145,8 @@
static void get_param_config_info(struct vdec_av1_inst *inst,
struct aml_dec_params *parms)
{
- if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO) {
- /* dw use v4l cfg */
- inst->parms.cfg.double_write_mode =
- inst->ctx->config.parm.dec.cfg.double_write_mode;
- parms->cfg = inst->parms.cfg;
- }
+ if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO)
+ parms->cfg = inst->parms.cfg;
if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO)
parms->ps = inst->parms.ps;
if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO)
@@ -1108,16 +1156,10 @@
parms->parms_status |= inst->parms.parms_status;
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
"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)
{
@@ -1125,12 +1167,20 @@
struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, 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;
@@ -1147,20 +1197,6 @@
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);
@@ -1175,69 +1211,12 @@
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;
@@ -1253,16 +1232,11 @@
pic->coded_width = ps->coded_width;
pic->coded_height = ps->coded_height;
- pic->y_len_sz = ALIGN(vdec_pic_scale(inst, pic->coded_width, dw), 64) *
- ALIGN(vdec_pic_scale(inst, pic->coded_height, dw), 64);
+ pic->y_len_sz = pic->coded_width * pic->coded_height;
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 |=
@@ -1272,27 +1246,23 @@
complete(&inst->comp);
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
- "Parse from ucode, visible(%d x %d), coded(%d x %d)\n",
+ "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);
-}
-
-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));
+ ps->coded_width, ps->coded_height,
+ ps->dpb_size);
}
static void set_param_hdr_info(struct vdec_av1_inst *inst,
struct aml_vdec_hdr_infos *hdr)
{
- if (hdr->signal_type != 0) {
+ if ((inst->parms.parms_status &
+ V4L2_CONFIG_PARM_DECODE_HDRINFO)) {
inst->parms.hdr = *hdr;
inst->parms.parms_status |=
V4L2_CONFIG_PARM_DECODE_HDRINFO;
aml_vdec_dispatch_event(inst->ctx,
V4L2_EVENT_SRC_CH_HDRINFO);
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
+ v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
"av1 set HDR infos\n");
}
}
@@ -1304,12 +1274,6 @@
"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)
{
@@ -1317,7 +1281,7 @@
struct vdec_av1_inst *inst = (struct vdec_av1_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
"the av1 inst of dec is invalid.\n");
return -1;
}
@@ -1331,10 +1295,6 @@
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;
@@ -1342,11 +1302,6 @@
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 911c91d..d13fc34 100644
--- a/drivers/amvdec_ports/decoder/vdec_h264_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_h264_if.c
@@ -30,6 +30,7 @@
#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"
@@ -149,6 +150,7 @@
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;
};
@@ -279,10 +281,6 @@
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;
@@ -299,13 +297,14 @@
{
struct vdec_h264_inst *inst = NULL;
int ret = -1;
+ bool dec_init = false;
- inst = vzalloc(sizeof(*inst));
+ inst = kzalloc(sizeof(*inst), GFP_KERNEL);
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;
@@ -316,43 +315,60 @@
if (ctx->is_drm_mode)
inst->vdec.port.flag |= PORT_FLAG_DRM;
- /* probe info from the stream */
- inst->vsi = vzalloc(sizeof(struct vdec_h264_vsi));
- if (!inst->vsi) {
- ret = -ENOMEM;
+ /* 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;
}
- /* alloc the header buffer to be used cache sps or spp etc.*/
- inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
- if (!inst->vsi->header_buf) {
- ret = -ENOMEM;
- goto err;
- }
-
- init_completion(&inst->comp);
-
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
-
ret = video_decoder_init(&inst->vdec);
if (ret) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"vdec_h264 init err=%d\n", ret);
goto err;
}
+ dec_init = true;
+
+ /* probe info from the stream */
+ inst->vsi = kzalloc(sizeof(struct vdec_h264_vsi), GFP_KERNEL);
+ if (!inst->vsi) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* alloc the header buffer to be used cache sps or spp etc.*/
+ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
+ if (!inst->vsi->header_buf) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ 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();
+
return 0;
err:
- if (inst && inst->vsi && inst->vsi->header_buf)
- vfree(inst->vsi->header_buf);
- if (inst && inst->vsi)
- vfree(inst->vsi);
+ if (dec_init)
+ video_decoder_release(&inst->vdec);
if (inst)
- vfree(inst);
+ vcodec_vfm_release(&inst->vfm);
+ if (inst && inst->vsi && inst->vsi->header_buf)
+ kfree(inst->vsi->header_buf);
+ if (inst && inst->vsi)
+ kfree(inst->vsi);
+ if (inst)
+ kfree(inst);
*h_vdec = 0;
return ret;
@@ -481,6 +497,7 @@
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;
@@ -492,7 +509,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.dpb_frames = sps->num_reorder_frames;
+ inst->parms.ps.reorder_frames = sps->num_reorder_frames;
inst->parms.ps.dpb_size = dec->dpb_sz;
inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO;
@@ -554,7 +571,7 @@
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- ret = vdec_vframe_write(vdec, buf, size, timestamp, 0);
+ ret = vdec_vframe_write(vdec, buf, size, timestamp);
if (ret < 0) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"write frame data failed. err: %d\n", ret);
@@ -565,7 +582,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_ucode_dma(struct vdec_h264_inst *inst,
@@ -586,7 +603,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_cpu(struct vdec_h264_inst *inst, u8 *buf, u32 size)
@@ -671,20 +688,71 @@
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)
- vfree(inst->vsi->header_buf);
+ kfree(inst->vsi->header_buf);
if (inst->vsi)
- vfree(inst->vsi);
+ kfree(inst->vsi);
- vfree(inst);
+ kfree(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,
@@ -734,7 +802,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, 0);
+ ret = vdec_vframe_write(vdec, buf, size, ts);
} else {
char *write_buf = vmalloc(inst->vsi->head_offset + size);
if (!write_buf) {
@@ -746,7 +814,7 @@
memcpy(write_buf + inst->vsi->head_offset, buf, size);
ret = vdec_vframe_write(vdec, write_buf,
- inst->vsi->head_offset + size, ts, 0);
+ inst->vsi->head_offset + size, ts);
memset(inst->vsi->header_buf, 0, HEADER_BUFFER_SIZE);
inst->vsi->head_offset = 0;
@@ -794,7 +862,9 @@
inst->vsi->cur_pic.coded_height !=
inst->vsi->pic.coded_height) ||
(inst->vsi->pic.profile_idc !=
- inst->vsi->cur_pic.profile_idc))) {
+ inst->vsi->cur_pic.profile_idc) ||
+ (inst->vsi->pic.ref_frame_count !=
+ inst->vsi->cur_pic.ref_frame_count))) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "res change\n");
inst->vsi->cur_pic = inst->vsi->pic;
return true;
@@ -808,13 +878,16 @@
{
struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
struct aml_vdec_adapt *vdec = &inst->vdec;
- u8 *buf = (u8 *) bs->vaddr;
- u32 size = bs->size;
+ u8 *buf;
+ u32 size;
int ret = -1;
if (bs == NULL)
return -1;
+ buf = (u8 *) bs->vaddr;
+ size = bs->size;
+
if (vdec_input_full(vdec))
return -EAGAIN;
@@ -836,8 +909,7 @@
ret = vdec_vframe_write(vdec,
s->data,
s->len,
- bs->timestamp,
- 0);
+ bs->timestamp);
} else if (bs->model == VB2_MEMORY_DMABUF ||
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
@@ -889,12 +961,20 @@
struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, 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;
@@ -910,14 +990,6 @@
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);
@@ -956,10 +1028,8 @@
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;
@@ -972,9 +1042,10 @@
complete(&inst->comp);
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
- "Parse from ucode, visible(%d x %d), coded(%d x %d), scan:%s\n",
+ "Parse from ucode, visible(%d x %d), coded(%d x %d) dpb: %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");
}
@@ -994,12 +1065,6 @@
}
}
-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);
@@ -1014,7 +1079,7 @@
struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
"the h264 inst of dec is invalid.\n");
return -1;
}
@@ -1035,11 +1100,6 @@
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 56d492a..2a41276 100644
--- a/drivers/amvdec_ports/decoder/vdec_hevc_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
@@ -29,6 +29,7 @@
#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)
@@ -111,9 +112,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,
@@ -154,7 +155,7 @@
pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
- pbuf += sprintf(pbuf, "hevc_double_write_mode:1;");
+ pbuf += sprintf(pbuf, "hevc_double_write_mode:16;");
pbuf += sprintf(pbuf, "hevc_buf_width:4096;");
pbuf += sprintf(pbuf, "hevc_buf_height:2304;");
pbuf += sprintf(pbuf, "save_buffer_mode:0;");
@@ -186,13 +187,9 @@
ctx->config.parm.dec.cfg.canvas_mem_endian);
pbuf += sprintf(pbuf, "parm_v4l_low_latency_mode:%d;",
ctx->config.parm.dec.cfg.low_latency_mode);
- pbuf += sprintf(pbuf, "parm_v4l_metadata_config_flag:%d;",
- ctx->config.parm.dec.cfg.metadata_config_flag);
- pbuf += sprintf(pbuf, "parm_v4l_duration:%d;",
- ctx->config.parm.dec.cfg.duration);
ctx->config.length = pbuf - ctx->config.buf;
} else {
- ctx->config.parm.dec.cfg.double_write_mode = 1;
+ ctx->config.parm.dec.cfg.double_write_mode = 16;
ctx->config.parm.dec.cfg.ref_buf_margin = 7;
ctx->config.length = vdec_config_default_parms(ctx->config.buf);
}
@@ -206,13 +203,14 @@
{
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;
@@ -226,6 +224,24 @@
/* 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) {
@@ -234,7 +250,7 @@
}
/* alloc the header buffer to be used cache sps or spp etc.*/
- inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
+ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
if (!inst->vsi->header_buf) {
ret = -ENOMEM;
goto err;
@@ -242,23 +258,22 @@
init_completion(&inst->comp);
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
-
- ret = video_decoder_init(&inst->vdec);
- if (ret) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
- "vdec_hevc init err=%d\n", ret);
- goto err;
- }
-
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
"hevc Instance >> %lx\n", (ulong) inst);
+ 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)
- vfree(inst->vsi->header_buf);
+ kfree(inst->vsi->header_buf);
if (inst && inst->vsi)
kfree(inst->vsi);
if (inst)
@@ -302,8 +317,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->vsi->pic.coded_width;
- int h = inst->vsi->pic.coded_height;
+ int w = inst->parms.cfg.init_width;
+ int h = inst->parms.cfg.init_height;
u32 dw = 0x1; /*1:1*/
switch (valid_dw_mode) {
@@ -406,7 +421,7 @@
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- ret = vdec_vframe_write(vdec, buf, size, timestamp, 0);
+ ret = vdec_vframe_write(vdec, buf, size, timestamp);
if (ret < 0) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"write frame data failed. err: %d\n", ret);
@@ -417,7 +432,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_ucode_dma(struct vdec_hevc_inst *inst,
@@ -438,7 +453,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_cpu(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
@@ -511,13 +526,19 @@
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)
- vfree(inst->vsi->header_buf);
+ kfree(inst->vsi->header_buf);
if (inst->vsi)
kfree(inst->vsi);
@@ -525,6 +546,49 @@
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,
@@ -533,7 +597,7 @@
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- ret = vdec_vframe_write(vdec, buf, size, ts, 0);
+ ret = vdec_vframe_write(vdec, buf, size, ts);
return ret;
}
@@ -580,13 +644,16 @@
{
struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
struct aml_vdec_adapt *vdec = &inst->vdec;
- u8 *buf = (u8 *) bs->vaddr;
- u32 size = bs->size;
+ u8 *buf;
+ u32 size;
int ret = -1;
if (bs == NULL)
return -1;
+ buf = (u8 *) bs->vaddr;
+ size = bs->size;
+
if (vdec_input_full(vdec))
return -EAGAIN;
@@ -608,8 +675,7 @@
ret = vdec_vframe_write(vdec,
s->data,
s->len,
- bs->timestamp,
- 0);
+ bs->timestamp);
} else if (bs->model == VB2_MEMORY_DMABUF ||
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
@@ -647,12 +713,6 @@
"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)
{
@@ -660,12 +720,20 @@
struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, 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;
@@ -681,21 +749,6 @@
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);
@@ -716,7 +769,6 @@
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;
@@ -732,14 +784,9 @@
pic->coded_width = ps->coded_width;
pic->coded_height = ps->coded_height;
-
- pic->y_len_sz = ALIGN(vdec_pic_scale(inst, pic->coded_width, dw), 64) *
- ALIGN(vdec_pic_scale(inst, pic->coded_height, dw), 64);
+ pic->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;
@@ -751,27 +798,13 @@
complete(&inst->comp);
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
- "Parse from ucode, visible(%d x %d), coded(%d x %d), scan:%s\n",
+ "Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %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)
{
@@ -794,12 +827,6 @@
"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)
{
@@ -807,7 +834,7 @@
struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
"the hevc inst of dec is invalid.\n");
return -1;
}
@@ -817,18 +844,10 @@
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;
@@ -836,10 +855,6 @@
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 8332956..f9816cc 100644
--- a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
@@ -28,6 +28,7 @@
#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>
@@ -111,6 +112,7 @@
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;
};
@@ -156,7 +158,6 @@
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;
}
@@ -176,8 +177,6 @@
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);
@@ -193,13 +192,14 @@
{
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,6 +213,24 @@
/* 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) {
@@ -221,31 +239,30 @@
}
/* alloc the header buffer to be used cache sps or spp etc.*/
- inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
+ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
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)
- vfree(inst->vsi->header_buf);
+ kfree(inst->vsi->header_buf);
if (inst && inst->vsi)
kfree(inst->vsi);
if (inst)
@@ -291,9 +308,9 @@
dec->dpb_sz = 8;
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
- "The stream infos, coded:(%d x %d), visible:(%d x %d)\n",
+ "The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
pic->coded_width, pic->coded_height,
- pic->visible_width, pic->visible_height);
+ pic->visible_width, pic->visible_height, dec->dpb_sz);
}
static int parse_stream_ucode(struct vdec_mjpeg_inst *inst,
@@ -302,7 +319,7 @@
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- ret = vdec_vframe_write(vdec, buf, size, timestamp, 0);
+ ret = vdec_vframe_write(vdec, buf, size, timestamp);
if (ret < 0) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"write frame data failed. err: %d\n", ret);
@@ -313,7 +330,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_ucode_dma(struct vdec_mjpeg_inst *inst,
@@ -334,7 +351,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_cpu(struct vdec_mjpeg_inst *inst, u8 *buf, u32 size)
@@ -414,8 +431,12 @@
video_decoder_release(&inst->vdec);
+ vcodec_vfm_release(&inst->vfm);
+
+ //dump_deinit();
+
if (inst->vsi && inst->vsi->header_buf)
- vfree(inst->vsi->header_buf);
+ kfree(inst->vsi->header_buf);
if (inst->vsi)
kfree(inst->vsi);
@@ -423,13 +444,55 @@
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, 0);
+ ret = vdec_vframe_write(vdec, buf, size, ts);
return ret;
}
@@ -457,8 +520,7 @@
ret = vdec_vframe_write(vdec,
s->data,
s->len,
- bs->timestamp,
- 0);
+ bs->timestamp);
} else if (bs->model == VB2_MEMORY_DMABUF ||
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
@@ -480,12 +542,20 @@
struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, 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;
@@ -498,13 +568,6 @@
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);
@@ -536,13 +599,9 @@
pic->coded_width = ps->coded_width;
pic->coded_height = ps->coded_height;
pic->y_len_sz = pic->coded_width * pic->coded_height;
- pic->c_len_sz = pic->y_len_sz >> 1;
+ pic->c_len_sz = pic->y_len_sz;
- 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 |=
@@ -552,10 +611,10 @@
complete(&inst->comp);
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
- "Parse from ucode, visible(%d x %d), coded(%d x %d), scan:%s\n",
+ "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,
- pic->field == V4L2_FIELD_NONE ? "P" : "I");
+ dec->dpb_sz);
}
static void set_param_write_sync(struct vdec_mjpeg_inst *inst)
@@ -563,12 +622,6 @@
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)
{
@@ -576,7 +629,7 @@
struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
"the mjpeg inst of dec is invalid.\n");
return -1;
}
@@ -585,15 +638,10 @@
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 2472ac1..9a38e71 100644
--- a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
@@ -28,6 +28,7 @@
#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)
@@ -110,6 +111,7 @@
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;
};
@@ -171,10 +173,6 @@
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);
@@ -189,13 +187,14 @@
{
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;
@@ -210,6 +209,24 @@
/* 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) {
@@ -218,31 +235,29 @@
}
/* alloc the header buffer to be used cache sps or spp etc.*/
- inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
+ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
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;
- 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);
+ //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)
- vfree(inst->vsi->header_buf);
+ kfree(inst->vsi->header_buf);
if (inst && inst->vsi)
kfree(inst->vsi);
if (inst)
@@ -291,7 +306,7 @@
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- ret = vdec_vframe_write(vdec, buf, size, timestamp, 0);
+ ret = vdec_vframe_write(vdec, buf, size, timestamp);
if (ret < 0) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"write frame data failed. err: %d\n", ret);
@@ -302,7 +317,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_ucode_dma(struct vdec_mpeg12_inst *inst,
@@ -323,7 +338,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_cpu(struct vdec_mpeg12_inst *inst, u8 *buf, u32 size)
@@ -403,8 +418,12 @@
video_decoder_release(&inst->vdec);
+ vcodec_vfm_release(&inst->vfm);
+
+ //dump_deinit();
+
if (inst->vsi && inst->vsi->header_buf)
- vfree(inst->vsi->header_buf);
+ kfree(inst->vsi->header_buf);
if (inst->vsi)
kfree(inst->vsi);
@@ -412,13 +431,55 @@
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, 0);
+ ret = vdec_vframe_write(vdec, buf, size, ts);
return ret;
}
@@ -446,8 +507,7 @@
ret = vdec_vframe_write(vdec,
s->data,
s->len,
- bs->timestamp,
- 0);
+ bs->timestamp);
} else if (bs->model == VB2_MEMORY_DMABUF ||
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
@@ -462,19 +522,6 @@
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)
{
@@ -482,12 +529,20 @@
struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, 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;
@@ -500,17 +555,6 @@
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);
@@ -525,12 +569,6 @@
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)
{
@@ -554,9 +592,6 @@
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;
@@ -568,28 +603,13 @@
complete(&inst->comp);
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
- "Parse from ucode, visible(%d x %d), coded(%d x %d), scan:%s\n",
+ "Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %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)
{
@@ -597,7 +617,7 @@
struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
"the mpeg12 inst of dec is invalid.\n");
return -1;
}
@@ -606,19 +626,10 @@
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 bc0af24..c47bafc 100644
--- a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
@@ -28,6 +28,7 @@
#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)
@@ -110,6 +111,7 @@
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;
};
@@ -171,8 +173,6 @@
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,14 +188,15 @@
{
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;
@@ -209,23 +210,16 @@
/* to eable mpeg4 hw.*/
inst->vdec.port.type = PORT_TYPE_VIDEO;
- /* probe info from the stream */
- inst->vsi = kzalloc(sizeof(struct vdec_mpeg4_vsi), GFP_KERNEL);
- if (!inst->vsi) {
- ret = -ENOMEM;
+ /* 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;
}
-
- /* alloc the header buffer to be used cache sps or spp etc.*/
- inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
- if (!inst->vsi->header_buf) {
- ret = -ENOMEM;
- goto err;
- }
-
- init_completion(&inst->comp);
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
+ dec_init = true;
ret = video_decoder_init(&inst->vdec);
if (ret) {
@@ -234,14 +228,38 @@
goto err;
}
+ /* probe info from the stream */
+ inst->vsi = kzalloc(sizeof(struct vdec_mpeg4_vsi), GFP_KERNEL);
+ if (!inst->vsi) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ /* alloc the header buffer to be used cache sps or spp etc.*/
+ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
+ if (!inst->vsi->header_buf) {
+ ret = -ENOMEM;
+ 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)
- vfree(inst->vsi->header_buf);
+ kfree(inst->vsi->header_buf);
if (inst && inst->vsi)
kfree(inst->vsi);
if (inst)
@@ -298,7 +316,7 @@
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- ret = vdec_vframe_write(vdec, buf, size, timestamp, 0);
+ ret = vdec_vframe_write(vdec, buf, size, timestamp);
if (ret < 0) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"write frame data failed. err: %d\n", ret);
@@ -309,7 +327,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_ucode_dma(struct vdec_mpeg4_inst *inst,
@@ -330,7 +348,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_cpu(struct vdec_mpeg4_inst *inst, u8 *buf, u32 size)
@@ -410,8 +428,12 @@
video_decoder_release(&inst->vdec);
+ vcodec_vfm_release(&inst->vfm);
+
+ //dump_deinit();
+
if (inst->vsi && inst->vsi->header_buf)
- vfree(inst->vsi->header_buf);
+ kfree(inst->vsi->header_buf);
if (inst->vsi)
kfree(inst->vsi);
@@ -419,13 +441,55 @@
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, 0);
+ ret = vdec_vframe_write(vdec, buf, size, ts);
return ret;
}
@@ -453,8 +517,7 @@
ret = vdec_vframe_write(vdec,
s->data,
s->len,
- bs->timestamp,
- 0);
+ bs->timestamp);
} else if (bs->model == VB2_MEMORY_DMABUF ||
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
@@ -476,12 +539,20 @@
struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, 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;
@@ -493,12 +564,6 @@
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,
@@ -533,9 +598,6 @@
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;
@@ -547,9 +609,10 @@
complete(&inst->comp);
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
- "Parse from ucode, visible(%d x %d), coded(%d x %d), scan:%s\n",
+ "Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %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");
}
@@ -558,12 +621,6 @@
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)
{
@@ -571,7 +628,7 @@
struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
"the mpeg4 inst of dec is invalid.\n");
return -1;
}
@@ -580,15 +637,10 @@
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 fe81ddd..6704350 100644
--- a/drivers/amvdec_ports/decoder/vdec_vp9_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_vp9_if.c
@@ -29,6 +29,7 @@
#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"
@@ -122,13 +123,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, ulong meta_ptr);
+ u8 *buf, u32 size, u64 ts);
static void get_pic_info(struct vdec_vp9_inst *inst,
struct vdec_pic_info *pic)
@@ -169,7 +170,7 @@
pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
- pbuf += sprintf(pbuf, "vp9_double_write_mode:1;");
+ pbuf += sprintf(pbuf, "vp9_double_write_mode:16;");
pbuf += sprintf(pbuf, "vp9_buf_width:1920;");
pbuf += sprintf(pbuf, "vp9_buf_height:1088;");
pbuf += sprintf(pbuf, "vp9_max_pic_w:4096;");
@@ -186,10 +187,6 @@
{
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;
@@ -211,11 +208,9 @@
ctx->config.parm.dec.cfg.canvas_mem_endian);
pbuf += sprintf(pbuf, "parm_v4l_low_latency_mode:%d;",
ctx->config.parm.dec.cfg.low_latency_mode);
- pbuf += sprintf(pbuf, "parm_v4l_duration:%d;",
- ctx->config.parm.dec.cfg.duration);
ctx->config.length = pbuf - ctx->config.buf;
} else {
- ctx->config.parm.dec.cfg.double_write_mode = 1;
+ ctx->config.parm.dec.cfg.double_write_mode = 16;
ctx->config.parm.dec.cfg.ref_buf_margin = 7;
ctx->config.length = vdec_config_default_parms(ctx->config.buf);
}
@@ -226,8 +221,6 @@
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;",
@@ -256,8 +249,6 @@
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;
@@ -273,8 +264,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;
@@ -288,6 +279,16 @@
/* 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) {
@@ -296,7 +297,7 @@
}
/* alloc the header buffer to be used cache sps or spp etc.*/
- inst->vsi->header_buf = vzalloc(HEADER_BUFFER_SIZE);
+ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
if (!inst->vsi->header_buf) {
ret = -ENOMEM;
goto err;
@@ -318,10 +319,14 @@
goto err;
}
+ //dump_init();
+
return 0;
err:
+ if (inst)
+ vcodec_vfm_release(&inst->vfm);
if (inst && inst->vsi && inst->vsi->header_buf)
- vfree(inst->vsi->header_buf);
+ kfree(inst->vsi->header_buf);
if (inst && inst->vsi)
kfree(inst->vsi);
if (inst)
@@ -342,8 +347,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->vsi->pic.coded_width;
- int h = inst->vsi->pic.coded_height;
+ int w = inst->parms.cfg.init_width;
+ int h = inst->parms.cfg.init_height;
u32 dw = 0x1; /*1:1*/
switch (valid_dw_mode) {
@@ -438,11 +443,11 @@
}
static int parse_stream_ucode(struct vdec_vp9_inst *inst,
- u8 *buf, u32 size, u64 timestamp, ulong meta_ptr)
+ u8 *buf, u32 size, u64 timestamp)
{
int ret = 0;
- ret = vdec_write_nalu(inst, buf, size, timestamp, meta_ptr);
+ ret = vdec_write_nalu(inst, buf, size, timestamp);
if (ret < 0) {
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
"write frame data failed. err: %d\n", ret);
@@ -453,7 +458,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_ucode_dma(struct vdec_vp9_inst *inst,
@@ -474,7 +479,7 @@
wait_for_completion_timeout(&inst->comp,
msecs_to_jiffies(1000));
- return inst->vsi->pic.dpb_frames ? 0 : -1;
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int parse_stream_cpu(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
@@ -523,7 +528,7 @@
if (inst->ctx->param_sets_from_ucode) {
ret = parse_stream_ucode(inst, s->data,
- s->len, bs->timestamp, 0);
+ s->len, bs->timestamp);
} else {
ret = parse_stream_cpu(inst, s->data, s->len);
}
@@ -534,7 +539,7 @@
}
} else {
if (inst->ctx->param_sets_from_ucode) {
- ret = parse_stream_ucode(inst, buf, size, bs->timestamp, bs->meta_ptr);
+ ret = parse_stream_ucode(inst, buf, size, bs->timestamp);
} else {
ret = parse_stream_cpu(inst, buf, size);
}
@@ -547,13 +552,19 @@
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)
- vfree(inst->vsi->header_buf);
+ kfree(inst->vsi->header_buf);
if (inst->vsi)
kfree(inst->vsi);
@@ -561,11 +572,54 @@
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)
{
@@ -716,7 +770,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, 0);
+ frame_size, 0);
v4l_dbg(vdec->ctx, V4L_DEBUG_CODEC_ERROR,
"write trigger frame %d\n", ret);
p += frame_size;
@@ -724,7 +778,7 @@
}
static int vdec_write_nalu(struct vdec_vp9_inst *inst,
- u8 *buf, u32 size, u64 ts, ulong meta_ptr)
+ u8 *buf, u32 size, u64 ts)
{
int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
@@ -754,10 +808,10 @@
/*add headers.*/
add_prefix_data(&s, &data, &length);
- ret = vdec_vframe_write(vdec, data, length, ts, 0);
+ ret = vdec_vframe_write(vdec, data, length, ts);
vfree(data);
} else {
- ret = vdec_vframe_write(vdec, buf, size, ts, meta_ptr);
+ ret = vdec_vframe_write(vdec, buf, size, ts);
}
return ret;
@@ -791,14 +845,18 @@
{
struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
struct aml_vdec_adapt *vdec = &inst->vdec;
- u8 *buf = (u8 *) bs->vaddr;
- u32 size = bs->size;
+ u8 *buf;
+ u32 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;
}
@@ -820,8 +878,7 @@
ret = vdec_vframe_write(vdec,
s->data,
s->len,
- bs->timestamp,
- 0);
+ bs->timestamp);
} else if (bs->model == VB2_MEMORY_DMABUF ||
bs->model == VB2_MEMORY_USERPTR) {
ret = vdec_vframe_write_with_dma(vdec,
@@ -834,8 +891,10 @@
if ((!inst->ctx->param_sets_from_ucode) &&
(*res_chg = monitor_res_change(inst, buf, size)))
return 0;
- ret = vdec_write_nalu(inst, buf, size, bs->timestamp, bs->meta_ptr);
+
+ ret = vdec_write_nalu(inst, buf, size, bs->timestamp);
}
+ ATRACE_COUNTER("v4l2_decode_write", ret);
return ret;
}
@@ -858,12 +917,6 @@
"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)
{
@@ -871,12 +924,20 @@
struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, 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;
@@ -892,21 +953,6 @@
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);
@@ -927,7 +973,6 @@
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;
@@ -943,16 +988,11 @@
pic->coded_width = ps->coded_width;
pic->coded_height = ps->coded_height;
- pic->y_len_sz = ALIGN(vdec_pic_scale(inst, pic->coded_width, dw), 64) *
- ALIGN(vdec_pic_scale(inst, pic->coded_height, dw), 64);
+ pic->y_len_sz = pic->coded_width * pic->coded_height;
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 |=
@@ -962,15 +1002,10 @@
complete(&inst->comp);
v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
- "Parse from ucode, visible(%d x %d), coded(%d x %d)\n",
- pic->visible_width, pic->visible_height,
- pic->coded_width, pic->coded_height);
-}
-
-static void set_param_comp_buf_info(struct vdec_vp9_inst *inst,
- struct vdec_comp_buf_info *info)
-{
- memcpy(&inst->comp_info, info, sizeof(*info));
+ "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);
}
static void set_param_hdr_info(struct vdec_vp9_inst *inst,
@@ -995,12 +1030,6 @@
"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)
{
@@ -1008,7 +1037,7 @@
struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
if (!inst) {
- v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
+ v4l_dbg(0, V4L_DEBUG_CODEC_ERROR,
"the vp9 inst of dec is invalid.\n");
return -1;
}
@@ -1022,10 +1051,6 @@
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;
@@ -1033,11 +1058,6 @@
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 67cf93b..1d621da 100644
--- a/drivers/amvdec_ports/utils/common.c
+++ b/drivers/amvdec_ports/utils/common.c
@@ -1,3 +1,22 @@
+/*
+* 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>
@@ -221,12 +240,3 @@
_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 89ae50b..dd4c51f 100644
--- a/drivers/amvdec_ports/utils/common.h
+++ b/drivers/amvdec_ports/utils/common.h
@@ -1,3 +1,22 @@
+/*
+* 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
@@ -58,7 +77,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)
@@ -82,7 +101,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,
@@ -106,7 +125,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,
@@ -132,8 +151,8 @@
AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma"
AVCOL_TRC_NB ///< Not part of ABI
};
-#endif
+#endif
//fmt
const char *av_color_space_name(enum AVColorSpace space);
const char *av_color_primaries_name(enum AVColorPrimaries primaries);
@@ -150,6 +169,4 @@
//debug
void print_hex_debug(u8 *data, u32 len, int max);
-bool is_over_size(int w, int h, int size);
-
-#endif
\ No newline at end of file
+#endif
diff --git a/drivers/amvdec_ports/vdec_drv_if.c b/drivers/amvdec_ports/vdec_drv_if.c
index 01510c5..ed9f053 100644
--- a/drivers/amvdec_ports/vdec_drv_if.c
+++ b/drivers/amvdec_ports/vdec_drv_if.c
@@ -116,19 +116,6 @@
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 29911f8..a04d832 100644
--- a/drivers/amvdec_ports/vdec_drv_if.h
+++ b/drivers/amvdec_ports/vdec_drv_if.h
@@ -50,48 +50,33 @@
/**
* struct vdec_fb_status - decoder frame buffer status
- * @FB_ST_INIT : initial state
- * @FB_ST_DECODER : frame buffer be allocted by decoder.
- * @FB_ST_VPP : frame buffer be allocate by vpp.
- * @FB_ST_DISPLAY : frame buffer is ready to be displayed.
+ * @FB_ST_NORMAL : initial state
+ * @FB_ST_DISPLAY : frmae buffer is ready to be displayed
* @FB_ST_FREE : frame buffer is not used by decoder any more
*/
enum vdec_fb_status {
- FB_ST_INIT,
- FB_ST_DECODER,
- FB_ST_VPP,
- FB_ST_GE2D,
+ FB_ST_NORMAL,
FB_ST_DISPLAY,
FB_ST_FREE
};
-enum vdec_dw_mode {
- VDEC_DW_AFBC_ONLY = 0,
- VDEC_DW_AFBC_1_1_DW = 1,
- VDEC_DW_AFBC_1_4_DW = 2,
- VDEC_DW_AFBC_x2_1_4_DW = 3,
- VDEC_DW_AFBC_1_2_DW = 4,
- VDEC_DW_NO_AFBC = 16,
- VDEC_DW_AFBC_AUTO_1_2 = 0x100,
- VDEC_DW_AFBC_AUTO_1_4 = 0x200,
-};
-
-/*
+/* For GET_PARAM_DISP_FRAME_BUFFER and GET_PARAM_FREE_FRAME_BUFFER,
* 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_DW_MODE,
- GET_PARAM_COMP_BUF_INFO
+ GET_PARAM_CONFIG_INFO
};
/*
@@ -100,11 +85,8 @@
enum vdec_set_param_type {
SET_PARAM_WRITE_FRAME_SYNC,
SET_PARAM_PS_INFO,
- SET_PARAM_COMP_BUF_INFO,
SET_PARAM_HDR_INFO,
- SET_PARAM_POST_EVENT,
- SET_PARAM_PIC_INFO,
- SET_PARAM_CFG_INFO
+ SET_PARAM_POST_EVENT
};
/**
@@ -156,10 +138,7 @@
* @type : [in] input parameter type
* @out : [out] buffer to store query result
*/
-int vdec_if_get_param(struct aml_vcodec_ctx *ctx,
- enum vdec_get_param_type type, void *out);
-
-int vdec_if_set_param(struct aml_vcodec_ctx *ctx,
- enum vdec_set_param_type type, void *in);
+int vdec_if_get_param(struct aml_vcodec_ctx *ctx, enum vdec_get_param_type type,
+ void *out);
#endif
diff --git a/drivers/common/chips/chips.c b/drivers/common/chips/chips.c
index 158e32c..d692ca8 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/media/registers/cpu_version.h>
+#include <linux/amlogic/cpu_version.h>
#include "../../stream_input/amports/amports_priv.h"
#include "../../frame_provider/decoder/utils/vdec.h"
#include "chips.h"
@@ -78,14 +78,6 @@
{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 af162b8..d74728c 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/media/registers/cpu_version.h>
+#include <linux/amlogic/cpu_version.h>
#include "decoder_cpu_ver_info.h"
#define DECODE_CPU_VER_ID_NODE_NAME "cpu_ver_name"
@@ -32,7 +32,6 @@
#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]=
{
@@ -58,22 +57,13 @@
AM_MESON_CPU_MAJOR_ID_G12B,
AM_MESON_CPU_MAJOR_ID_GXLX2,
AM_MESON_CPU_MAJOR_ID_SM1,
- AM_MESON_CPU_MAJOR_ID_A1,
+ AM_MESON_CPU_MAJOR_ID_RES_0x2c,
AM_MESON_CPU_MAJOR_ID_RES_0x2d,
AM_MESON_CPU_MAJOR_ID_TL1,
AM_MESON_CPU_MAJOR_ID_TM2,
- AM_MESON_CPU_MAJOR_ID_C1,
+ AM_MESON_CPU_MAJOR_ID_RES_0x30,
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[] = {
@@ -124,90 +114,32 @@
.compatible = "amlogic, cpu-major-id-sc2",
.data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_SC2 - MAJOR_ID_START],
},
- {
- .compatible = "amlogic, cpu-major-id-t5",
- .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_T5 - MAJOR_ID_START],
- },
- {
- .compatible = "amlogic, cpu-major-id-t5d",
- .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_T5D - MAJOR_ID_START],
- },
- {
- .compatible = "amlogic, cpu-major-id-t7",
- .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_T7 - MAJOR_ID_START],
- },
- {
- .compatible = "amlogic, cpu-major-id-s4",
- .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_S4 - MAJOR_ID_START],
- },
- {
- .compatible = "amlogic, cpu-major-id-t3",
- .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_T3 - MAJOR_ID_START],
- },
- {
- .compatible = "amlogic, cpu-major-id-p1",
- .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_P1 - MAJOR_ID_START],
- },
- {
- .compatible = "amlogic, cpu-major-id-s4d",
- .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_S4D - MAJOR_ID_START],
- },
- {
- .compatible = "amlogic, cpu-major-id-t5w",
- .data = &cpu_ver_info[AM_MESON_CPU_MAJOR_ID_T5W - MAJOR_ID_START],
- },
{},
};
-static const int cpu_sub_info[] = {
- AM_MESON_CPU_MINOR_ID_REVB_G12B,
- AM_MESON_CPU_MINOR_ID_REVB_TM2,
- AM_MESON_CPU_MINOR_ID_S4_S805X2,
-};
-
-static const struct of_device_id cpu_sub_id_of_match[] = {
- {
- .compatible = "amlogic, cpu-major-id-g12b-b",
- .data = &cpu_sub_info[0],
- },
- {
- .compatible = "amlogic, cpu-major-id-tm2-b",
- .data = &cpu_sub_info[1],
- },
- {
- .compatible = "amlogic, cpu-major-id-s4-805x2",
- .data = &cpu_sub_info[2],
- },
-};
-
-static bool get_cpu_id_from_dtb(enum AM_MESON_CPU_MAJOR_ID *pid_type, int *sub_id)
+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;
+ 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) {
+ 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) {
- pmatch = of_match_device(cpu_sub_id_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) {
+ pr_err("No find of_match_device\n");
+ return -EINVAL;
}
- *pid_type = (enum AM_MESON_CPU_MAJOR_ID)(*(int *)pmatch->data) & (MAJOY_ID_MASK);
-
- *sub_id = ((*(int *)pmatch->data) & (SUB_ID_MASK)) >> 8;
+ *pidType = *(enum AM_MESON_CPU_MAJOR_ID *)pMatch->data;
return AM_SUCESS;
}
@@ -215,20 +147,15 @@
static void initial_cpu_id(void)
{
enum AM_MESON_CPU_MAJOR_ID id_type = AM_MESON_CPU_MAJOR_ID_MAX;
- int sub_id = 0;
- if (AM_SUCESS == get_cpu_id_from_dtb(&id_type, &sub_id)) {
+ if (AM_SUCESS == get_cpu_id_from_dtb(&id_type))
cpu_ver_id = id_type;
- cpu_sub_id = sub_id;
- } else {
+ else
cpu_ver_id = (enum AM_MESON_CPU_MAJOR_ID)get_cpu_type();
- cpu_sub_id = (is_meson_rev_b()) ? CHIP_REVB : CHIP_REVA;
- }
- if ((AM_MESON_CPU_MAJOR_ID_G12B == cpu_ver_id) && (CHIP_REVB == cpu_sub_id))
- cpu_ver_id = AM_MESON_CPU_MAJOR_ID_TL1;
-
- pr_info("vdec init cpu id: 0x%x(%d)", cpu_ver_id, cpu_sub_id);
+ if (AM_MESON_CPU_MAJOR_ID_G12B == cpu_ver_id)
+ if (is_meson_rev_b())
+ cpu_ver_id = AM_MESON_CPU_MAJOR_ID_TL1;
}
enum AM_MESON_CPU_MAJOR_ID get_cpu_major_id(void)
@@ -240,32 +167,10 @@
}
EXPORT_SYMBOL(get_cpu_major_id);
-int get_cpu_sub_id(void)
-{
- return cpu_sub_id;
-}
-EXPORT_SYMBOL(get_cpu_sub_id);
-
-bool is_cpu_meson_revb(void)
-{
- if (AM_MESON_CPU_MAJOR_ID_MAX == cpu_ver_id)
- initial_cpu_id();
-
- return (cpu_sub_id == CHIP_REVB);
-}
-EXPORT_SYMBOL(is_cpu_meson_revb);
-
bool is_cpu_tm2_revb(void)
{
- return ((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_TM2)
- && (is_cpu_meson_revb()));
+ return ((get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_TM2) &&
+ (is_meson_rev_b()));
}
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 6129244..673b001 100644
--- a/drivers/common/chips/decoder_cpu_ver_info.h
+++ b/drivers/common/chips/decoder_cpu_ver_info.h
@@ -19,11 +19,9 @@
*/
#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,
@@ -46,50 +44,18 @@
AM_MESON_CPU_MAJOR_ID_G12B = 0x29,
AM_MESON_CPU_MAJOR_ID_GXLX2 = 0x2a,
AM_MESON_CPU_MAJOR_ID_SM1 = 0x2b,
- AM_MESON_CPU_MAJOR_ID_A1 = 0x2c,
+ AM_MESON_CPU_MAJOR_ID_RES_0x2c,
AM_MESON_CPU_MAJOR_ID_RES_0x2d,
AM_MESON_CPU_MAJOR_ID_TL1 = 0x2e,
AM_MESON_CPU_MAJOR_ID_TM2 = 0x2f,
- AM_MESON_CPU_MAJOR_ID_C1 = 0x30,
+ AM_MESON_CPU_MAJOR_ID_RES_0x30,
AM_MESON_CPU_MAJOR_ID_RES_0x31,
AM_MESON_CPU_MAJOR_ID_SC2 = 0x32,
- AM_MESON_CPU_MAJOR_ID_C2 = 0x33,
- AM_MESON_CPU_MAJOR_ID_T5 = 0x34,
- AM_MESON_CPU_MAJOR_ID_T5D = 0x35,
- AM_MESON_CPU_MAJOR_ID_T7 = 0x36,
- AM_MESON_CPU_MAJOR_ID_S4 = 0x37,
- AM_MESON_CPU_MAJOR_ID_T3 = 0x38,
- AM_MESON_CPU_MAJOR_ID_P1 = 0x39,
- AM_MESON_CPU_MAJOR_ID_S4D = 0x3a,
- AM_MESON_CPU_MAJOR_ID_T5W = 0x3b,
+ AM_MESON_CPU_MAJOR_ID_RES_0x33,
+ AM_MESON_CPU_MAJOR_ID_T5,
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 9422198..85a81e6 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/media/registers/cpu_version.h>
+#include <linux/amlogic/cpu_version.h>
#include "../../stream_input/amports/amports_priv.h"
#include "../../frame_provider/decoder/utils/vdec.h"
#include "firmware_priv.h"
@@ -34,14 +34,13 @@
#include <linux/amlogic/media/utils/log.h>
#include <linux/firmware.h>
#include <linux/amlogic/tee.h>
-//#include <linux/amlogic/major.h> //if kernel is 4.9 then use this one
-#include <uapi/linux/major.h>
+#include <linux/amlogic/major.h>
#include <linux/cdev.h>
#include <linux/crc32.h>
#include "../chips/decoder_cpu_ver_info.h"
/* major.minor */
-#define PACK_VERS "v0.3"
+#define PACK_VERS "v0.2"
#define CLASS_NAME "firmware_codec"
#define DEV_NAME "firmware_vdec"
@@ -76,7 +75,6 @@
struct fw_mgr_s *g_mgr;
struct fw_dev_s *g_dev;
-struct package_head_s package_head;
static u32 debug;
static u32 detail;
@@ -87,7 +85,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));
@@ -111,7 +109,6 @@
break;
}
-
out:
mutex_unlock(&mutex);
@@ -344,8 +341,6 @@
struct fw_info_s *info;
unsigned int secs = 0;
struct tm tm;
- char history_change_id[7] = {0};
- int i;
mutex_lock(&mutex);
@@ -355,21 +350,7 @@
}
/* shows version of driver. */
- pr_info("The ucode driver version is %s\n", PACK_VERS);
-
- pr_info("The firmware version is %d.%d.%d-g%s\n",
- (package_head.version >> 16) & 0xff,
- package_head.version & 0xff,
- package_head.submit_count,
- package_head.commit);
-
- pr_info("change id history:\n");
- for (i = 0; i < 5; i++) {
- memset(history_change_id, 0, sizeof(history_change_id));
- strncpy(history_change_id, &(package_head.history_change_id[i * 6]), 6);
- pr_info("\t%s\n", history_change_id);
-
- }
+ pr_info("The driver version is %s\n", PACK_VERS);
list_for_each_entry(info, &mgr->fw_head, node) {
if (IS_ERR_OR_NULL(info->data))
@@ -394,8 +375,7 @@
secs = info->data->head.time
- sys_tz.tz_minuteswest * 60;
- //time_to_tm(secs, 0, &tm);//kernel4.9
- time64_to_tm(secs, 0, &tm);
+ time_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,
@@ -597,7 +577,6 @@
if (ret != 2)
return -1;
- package_head = pack->head;
major_fw = (pack->head.version >> 16) & 0xff;
minor_fw = pack->head.version & 0xff;
@@ -616,7 +595,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.%d\n", major_fw, minor_fw, pack->head.submit_count);
+ pr_info("The firmware ver is v%d.%d\n", major_fw, minor_fw);
}
return 0;
@@ -931,7 +910,6 @@
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),
@@ -943,26 +921,7 @@
.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 d901f9d..410745b 100644
--- a/drivers/common/firmware/firmware_priv.h
+++ b/drivers/common/firmware/firmware_priv.h
@@ -85,11 +85,7 @@
int checksum;
int total;
int version;
- int submit_count;
- char change_id[16];
- char commit[16];
- char history_change_id[30];
- char reserved[62];
+ char reserved[128];
};
struct package_s {
diff --git a/drivers/common/firmware/firmware_type.c b/drivers/common/firmware/firmware_type.c
index 8d95c12..c232020 100644
--- a/drivers/common/firmware/firmware_type.c
+++ b/drivers/common/firmware/firmware_type.c
@@ -76,13 +76,6 @@
{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 4615baf..e997057 100644
--- a/drivers/common/firmware/firmware_type.h
+++ b/drivers/common/firmware/firmware_type.h
@@ -80,7 +80,6 @@
#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 6340c1a..972bcc1 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/media/registers/cpu_version.h>
+#include <linux/amlogic/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(667);
+ hcodec_clock_set(1);
}
EXPORT_SYMBOL(hcodec_clock_enable);
@@ -311,21 +311,6 @@
}
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);
@@ -353,8 +338,7 @@
|| format == VFORMAT_AV1) {
ret_clk = hevc_clock_set(clk);
clock_source_wxhxfps_saved[VDEC_HEVC] = width * height * fps;
- if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A &&
- !is_hevc_front_back_clk_combined()) {
+ if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
ret_clk = hevc_back_clock_set(clk);
clock_source_wxhxfps_saved[VDEC_HEVCB] = width * height * fps;
}
@@ -388,7 +372,7 @@
*/
return 0; /* ignore don't needed firmare. */
}
- mgr = kmalloc(sizeof(struct chip_vdec_clk_s), GFP_KERNEL);
+ mgr = vzalloc(sizeof(struct chip_vdec_clk_s));
if (!mgr)
return -ENOMEM;
*mgr = *t_mgr;
@@ -397,7 +381,7 @@
*/
if (mgr->clock_init) {
if (mgr->clock_init()) {
- kfree(mgr);
+ vfree(mgr);
return -ENOMEM;
}
}
@@ -420,7 +404,7 @@
int unregister_vdec_clk_mgr(enum vdec_type_e vdec_type)
{
- kfree(get_current_vdec_chip()->clk_mgr[vdec_type]);
+ vfree(get_current_vdec_chip()->clk_mgr[vdec_type]);
return 0;
}
@@ -439,7 +423,7 @@
*/
return 0; /* ignore don't needed this setting . */
}
- p_setting = kmalloc(size, GFP_KERNEL);
+ p_setting = vzalloc(size);
if (!p_setting)
return -ENOMEM;
memcpy(p_setting, setting, size);
@@ -465,7 +449,7 @@
int unregister_vdec_clk_setting(void)
{
- kfree(get_current_vdec_chip()->clk_setting_array);
+ vfree(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 bbc3bee..82eec1d 100644
--- a/drivers/common/media_clock/clk/clk.h
+++ b/drivers/common/media_clock/clk/clk.h
@@ -52,8 +52,6 @@
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);
@@ -132,7 +130,7 @@
#endif
#ifdef VDEC_HAS_HEVC
register_vdec_clk_mgr(cpus, VDEC_HEVC, &vdec_hevc_clk_mgr);
- if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
+ if (get_cpu_major_id() >= 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 c49d150..be2401c 100644
--- a/drivers/common/media_clock/clk/clkg12.c
+++ b/drivers/common/media_clock/clk/clkg12.c
@@ -114,6 +114,11 @@
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;
@@ -125,14 +130,19 @@
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)
- clk_set_rate(clk, 1296000000UL);
- else
- clk_set_rate(clk, 648000000UL);
+ if (is_gp0_div2) {
+ ret = clk_set_rate(clk, 1296000000UL);
+ CHECK_RET(ret);
+ } else {
+ ret = clk_set_rate(clk, 648000000UL);
+ CHECK_RET(ret);
+ }
VDEC1_SAFE_CLOCK();
VDEC1_CLOCK_OFF();
if (is_gp0_div2)
@@ -416,9 +426,7 @@
struct gate_switch_node *node = NULL;
char *hevc_mux_str = NULL;
- if ((get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SC2) ||
- (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5) ||
- (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_T5D))
+ if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_SC2)
hevc_mux_str = "clk_hevc_mux";
else
hevc_mux_str = "clk_hevcf_mux";
@@ -458,6 +466,7 @@
static int vdec_set_clk(int dec, int rate)
{
struct clk *clk = NULL;
+ int ret;
switch (dec) {
case VDEC_1:
@@ -497,7 +506,8 @@
return -1;
}
- clk_set_rate(clk, rate);
+ ret = clk_set_rate(clk, rate);
+ CHECK_RET(ret);
return 0;
}
@@ -513,12 +523,12 @@
{
gp_pll_user_vdec = gp_pll_user_register("vdec", 0,
gp_pll_user_cb_vdec);
- if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL)
+ if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_GXL)
is_gp0_div2 = false;
else
is_gp0_div2 = true;
- if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_GXL) {
+ if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_GXL) {
pr_info("used fix clk for vdec clk source!\n");
//update_vdec_clk_config_settings(1);
}
@@ -733,14 +743,9 @@
}
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1 &&
- get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1 &&
- get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5 &&
- get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5D)
+ get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1)
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;
@@ -836,15 +841,10 @@
if ((clk > 500 && clk != 667)) {
if (clock_real_clk[VDEC_HEVC] == 648)
return 648;
- if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
- (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5) &&
- (get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_T5D))
+ if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1)
clk = TL1_HEVC_MAX_CLK;
else
clk = 667;
-
- if (is_cpu_s4_s805x2())
- clk = 500;
}
if (set_frq_enable && hevc_frq) {
@@ -1042,14 +1042,6 @@
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 58a0289..9d5f7b4 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 %px\n",
+ pr_info("get gate %s control failed %p\n",
gates[i].name,
gates[i].clk);
} else {
- pr_info("get gate %s control ok %px\n",
+ pr_info("get gate %s control ok %p\n",
gates[i].name,
gates[i].clk);
}
diff --git a/drivers/fake_video_out/Makefile b/drivers/fake_video_out/Makefile
new file mode 100644
index 0000000..1dd937c
--- /dev/null
+++ b/drivers/fake_video_out/Makefile
@@ -0,0 +1 @@
+obj-m += fake_video.o
diff --git a/drivers/fake_video_out/fake_video.c b/drivers/fake_video_out/fake_video.c
new file mode 100644
index 0000000..e0e9b16
--- /dev/null
+++ b/drivers/fake_video_out/fake_video.c
@@ -0,0 +1,309 @@
+/*
+* 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 f30c4f1..371e088 100644
--- a/drivers/frame_provider/Makefile
+++ b/drivers/frame_provider/Makefile
@@ -1,2 +1 @@
obj-y += decoder/
-obj-y += decoder_v4l/
diff --git a/drivers/frame_provider/decoder/Makefile b/drivers/frame_provider/decoder/Makefile
index bb0079e..349d381 100644
--- a/drivers/frame_provider/decoder/Makefile
+++ b/drivers/frame_provider/decoder/Makefile
@@ -7,6 +7,7 @@
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 5869eac..6314f9d 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 <uapi/linux/tee.h>
+#include <linux/amlogic/tee.h>
+
#define DRIVER_NAME "amvdec_avs"
#define MODULE_NAME "amvdec_avs"
@@ -162,6 +162,7 @@
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;
@@ -412,7 +413,6 @@
}
}
-
#ifdef HANDLE_AVS_IRQ
static irqreturn_t vavs_isr(int irq, void *dev_id)
#else
@@ -654,7 +654,6 @@
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);
@@ -741,6 +740,7 @@
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
- config_cav_lut_ex(canvas_base + canvas_num * i + 0,
+ canvas_config_ex(canvas_base + canvas_num * i + 0,
buf_start,
canvas_width, canvas_height,
CANVAS_ADDR_NOWRAP,
- vdec->canvas_mode, endian, VDEC_1);
- config_cav_lut_ex(canvas_base + canvas_num * i + 1,
+ vdec->canvas_mode, endian);
+ canvas_config_ex(canvas_base + canvas_num * i + 1,
buf_start +
decbuf_y_size, canvas_width,
canvas_height / 2,
CANVAS_ADDR_NOWRAP,
- vdec->canvas_mode, endian, VDEC_1);
+ vdec->canvas_mode, endian);
#else
- config_cav_lut_ex(canvas_num * i + 0,
+ canvas_config_ex(canvas_num * i + 0,
buf_start,
canvas_width, canvas_height,
CANVAS_ADDR_NOWRAP,
- vdec->canvas_mode, endian, VDEC_1);
- config_cav_lut_ex(canvas_num * i + 1,
+ vdec->canvas_mode, endian);
+ canvas_config_ex(canvas_num * i + 1,
buf_start +
decbuf_y_size, canvas_width / 2,
canvas_height / 2,
CANVAS_ADDR_NOWRAP,
- vdec->canvas_mode, endian, VDEC_1);
- config_cav_lut_ex(canvas_num * i + 2,
+ vdec->canvas_mode, endian);
+ canvas_config_ex(canvas_num * i + 2,
buf_start +
decbuf_y_size + decbuf_uv_size,
canvas_width / 2, canvas_height / 2,
CANVAS_ADDR_NOWRAP,
- vdec->canvas_mode, endian, VDEC_1);
+ vdec->canvas_mode, endian);
#endif
if (debug_flag & AVS_DEBUG_PRINT) {
pr_info("canvas config %d, addr %p\n", i,
@@ -1353,8 +1353,10 @@
}
}
-static void vavs_put_timer_func(struct timer_list *timer)
+static void vavs_put_timer_func(unsigned long arg)
{
+ struct timer_list *timer = (struct timer_list *)arg;
+
#ifndef HANDLE_AVS_IRQ
vavs_isr();
#endif
@@ -1571,6 +1573,7 @@
return -ENOMEM;
pr_info("vavs_init\n");
+ init_timer(&recycle_timer);
stat |= STAT_TIMER_INIT;
@@ -1654,8 +1657,10 @@
stat |= STAT_VF_HOOK;
- timer_setup(&recycle_timer, vavs_put_timer_func, 0);
+ recycle_timer.data = (ulong)(&recycle_timer);
+ recycle_timer.function = vavs_put_timer_func;
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 de9a3d2..3da87e4 100644
--- a/drivers/frame_provider/decoder/avs2/avs2_bufmgr.c
+++ b/drivers/frame_provider/decoder/avs2/avs2_bufmgr.c
@@ -39,9 +39,7 @@
#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 <linux/amlogic/tee.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 be35a5e..3e7fcb8 100644
--- a/drivers/frame_provider/decoder/avs2/avs2_global.h
+++ b/drivers/frame_provider/decoder/avs2/avs2_global.h
@@ -772,9 +772,6 @@
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;
@@ -817,9 +814,6 @@
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 e21dc55..a5d550f 100644
--- a/drivers/frame_provider/decoder/avs2/vavs2.c
+++ b/drivers/frame_provider/decoder/avs2/vavs2.c
@@ -37,9 +37,7 @@
#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 <linux/amlogic/tee.h>
#include "../../../stream_input/amports/amports_priv.h"
#include <linux/amlogic/media/codec_mm/codec_mm.h>
#include "../utils/decoder_mmu_box.h"
@@ -57,46 +55,26 @@
#include "../utils/config_parser.h"
#include "../utils/firmware.h"
#include "../../../common/chips/decoder_cpu_ver_info.h"
-#include "../utils/vdec_feature.h"
+#include <linux/amlogic/tee.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
@@ -249,9 +227,6 @@
#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];
@@ -261,11 +236,17 @@
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;
-
-static u32 work_buf_size;
+#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;
@@ -279,7 +260,6 @@
* 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;
@@ -318,7 +298,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(struct timer_list *timer);
+static void vavs2_put_timer_func(unsigned long arg);
static void dump_data(struct AVS2Decoder_s *dec, int size);
static unsigned char get_data_check_sum
(struct AVS2Decoder_s *dec, int size);
@@ -350,8 +330,6 @@
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",
@@ -427,6 +405,11 @@
#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
@@ -442,7 +425,6 @@
#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
@@ -515,9 +497,6 @@
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)
@@ -532,6 +511,11 @@
#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
@@ -546,7 +530,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)
@@ -558,7 +542,6 @@
#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
@@ -601,10 +584,6 @@
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;
@@ -689,22 +668,11 @@
unsigned short *lmem_ptr;
unsigned short *debug_ptr;
-#ifdef AVS2_10B_MMU
- bool mmu_enable;
-
- u32 cuva_size;
- void *cuva_addr;
- dma_addr_t cuva_phy_addr;
-
+#if 1
+ /*AVS2_10B_MMU*/
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];
@@ -807,14 +775,10 @@
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(
@@ -924,19 +888,10 @@
static u32 get_valid_double_write_mode(struct AVS2Decoder_s *dec)
{
- u32 dw_mode;
-
- dw_mode = (dec->m_ins_flag &&
+ return (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)
@@ -994,6 +949,18 @@
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(
@@ -1007,6 +974,25 @@
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,
@@ -1029,38 +1015,157 @@
}
#endif
-#ifdef AVS2_10B_MMU_DW
-int avs2_alloc_dw_mmu(
- struct AVS2Decoder_s *dec,
- int cur_buf_idx,
- int pic_width,
- int pic_height,
- unsigned short bit_depth,
- unsigned int *mmu_index_adr)
+#if 0
+/*ndef MV_USE_FIXED_BUF*/
+static void dealloc_mv_bufs(struct AVS2Decoder_s *dec)
{
- 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;
+ 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;
+ }
}
- 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)
@@ -1203,19 +1308,13 @@
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)
-
+static u32 endian = 0xff0;
#ifdef ERROR_HANDLE_DEBUG
static u32 dbg_nal_skip_flag;
/* bit[0], skip vps; bit[1], skip sps; bit[2], skip pps */
@@ -1319,9 +1418,6 @@
#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
@@ -1380,10 +1476,7 @@
#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
+#define WORK_BUF_SPEC_NUM 3
static struct BuffInfo_s amvavs2_workbuff_spec[WORK_BUF_SPEC_NUM] = {
{
/* 8M bytes */
@@ -1392,283 +1485,6 @@
.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 = {
@@ -1740,16 +1556,6 @@
},
#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*/
},
@@ -1845,16 +1651,6 @@
},
#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*/
},
@@ -1943,16 +1739,6 @@
},
#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,
},
@@ -2054,70 +1840,64 @@
struct BuffInfo_s *buf_spec)
{
void *mem_start_virt;
- buf_spec->ipp.buf_start =
- WORKBUF_ALIGN(buf_spec->start_adr);
+ buf_spec->ipp.buf_start = buf_spec->start_adr;
buf_spec->sao_abv.buf_start =
- WORKBUF_ALIGN(buf_spec->ipp.buf_start + buf_spec->ipp.buf_size);
+ 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->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->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->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->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->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->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->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->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->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->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_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);
+ buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size;
#ifdef AVS2_10B_MMU
buf_spec->mmu_vbh.buf_start =
- WORKBUF_ALIGN(buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size);
- #ifdef AVS2_10B_MMU_DW
- buf_spec->mmu_vbh_dw.buf_start =
- WORKBUF_ALIGN(buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size);
+ buf_spec->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->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size;
+#else
buf_spec->mpred_above.buf_start =
- WORKBUF_ALIGN(buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size);
- #endif
-#else /* AVS2_10B_MMU */
- #ifdef AVS2_10B_MMU_DW
- buf_spec->mmu_vbh_dw.buf_start =
- WORKBUF_ALIGN(buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size);
- buf_spec->mpred_above.buf_start =
- WORKBUF_ALIGN(buf_spec->mmu_vbh_dw.buf_start + buf_spec->mmu_vbh_dw.buf_size);
- #else
- buf_spec->mpred_above.buf_start =
- WORKBUF_ALIGN(buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size);
- #endif
-#endif /* AVS2_10B_MMU */
+ 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->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);
+ 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);
+ 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->rpm.buf_start +
+ buf_spec->rpm.buf_size;
buf_spec->end_adr =
- WORKBUF_ALIGN(buf_spec->lmem.buf_start + buf_spec->lmem.buf_size);
+ buf_spec->lmem.buf_start +
+ buf_spec->lmem.buf_size;
if (dec) {
mem_start_virt =
@@ -2170,10 +1950,6 @@
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
@@ -2191,11 +1967,9 @@
static void uninit_mmu_buffers(struct AVS2Decoder_s *dec)
{
-#ifdef AVS2_10B_MMU_DW
- if (dec->dw_mmu_enable && dec->dw_mmu_box) {
- decoder_mmu_box_free(dec->dw_mmu_box);
- dec->dw_mmu_box = NULL;
- }
+#if 0
+/*ndef MV_USE_FIXED_BUF*/
+ dealloc_mv_bufs(dec);
#endif
decoder_mmu_box_free(dec->mmu_box);
dec->mmu_box = NULL;
@@ -2236,9 +2010,9 @@
if (dw_mode) {
int pic_width_dw = pic_width /
- get_double_write_ratio(dw_mode);
+ get_double_write_ratio(dec, dw_mode);
int pic_height_dw = pic_height /
- get_double_write_ratio(dw_mode);
+ get_double_write_ratio(dec, 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);
@@ -2269,7 +2043,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;
@@ -2310,6 +2084,7 @@
"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;
}
@@ -2334,7 +2109,15 @@
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;
@@ -2350,11 +2133,11 @@
int mc_buffer_size_u_v_h = 0;
int dw_mode = get_double_write_mode_init(dec);
- if (dw_mode && ((dw_mode & 0x20) == 0)) {
+ if (dw_mode) {
int pic_width_dw = pic_width /
- get_double_write_ratio(dw_mode);
+ get_double_write_ratio(dec, dw_mode);
int pic_height_dw = pic_height /
- get_double_write_ratio(dw_mode);
+ get_double_write_ratio(dec, 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) ?
@@ -2373,150 +2156,171 @@
}
if (mc_buffer_size & 0xffff) /*64k alignment*/
mc_buffer_size_h += 1;
-
-
-#ifdef AVS2_10B_MMU
- if (dec->mmu_enable) {
- pic->header_adr = decoder_bmmu_box_get_phy_addr(
- dec->bmmu_box, HEADER_BUFFER_IDX(pic->index));
-
-#ifdef AVS2_10B_MMU_DW
- if (dec->dw_mmu_enable) {
- pic->dw_header_adr = pic->header_adr
- + get_compress_header_size(dec);
- }
-#endif
- avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
- "buf_size %d, MMU header_adr %d: %ld\n",
- buf_size, pic->index, pic->header_adr);
- }
-#else
+#ifndef AVS2_10B_MMU
if ((dw_mode & 0x10) == 0)
buf_size += (mc_buffer_size_h << 16);
#endif
- i = pic->index;
-
-#ifndef AVS2_10B_MMU
- if (debug) {
- pr_err("start %x .size=%d\n",
- dec->mc_buf_spec.buf_start + i * buf_size, buf_size);
- }
- for (i = 0; i < dec->buf_num; i++) {
- y_adr = ((dec->m_BUF[i].free_start_adr
- + 0xffff) >> 16) << 16;
- /*64k alignment*/
- if ((y_adr+buf_size) <= (dec->m_BUF[i].start_adr+
- dec->m_BUF[i].size)) {
- dec->m_BUF[i].free_start_adr =
- y_adr + buf_size;
- break;
- }
- }
- if (i < dec->buf_num)
-#else
- /*if ((dec->mc_buf->buf_start + (i + 1) * buf_size) <
- dec->mc_buf->buf_end)
- y_adr = dec->mc_buf->buf_start + i * buf_size;
- else {*/
- if (buf_size > 0 && pic->cma_alloc_addr == 0) {
- ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box,
- VF_BUFFER_IDX(i),
- buf_size, DRIVER_NAME,
- &pic->cma_alloc_addr);
- if (ret < 0) {
- avs2_print(dec, 0,
- "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n",
- VF_BUFFER_IDX(i),
- buf_size
- );
- return ret;
- }
-
- if (pic->cma_alloc_addr)
- y_adr = pic->cma_alloc_addr;
- else {
- avs2_print(dec, 0,
- "decoder_bmmu_box_alloc_buf_phy idx %d size %d return null\n",
- VF_BUFFER_IDX(i),
- buf_size
- );
- return -1;
- }
- }
-#endif
- {
- /*ensure get_pic_by_POC()
- not get the buffer not decoded*/
- pic->BUF_index = i;
- pic->lcu_total = lcu_total;
-
- pic->comp_body_size = losless_comp_body_size;
- pic->buf_size = buf_size;
- pic->mc_canvas_y = pic->index;
- pic->mc_canvas_u_v = pic->index;
-#ifndef AVS2_10B_MMU
- pic->mc_y_adr = y_adr;
- if (dw_mode & 0x10) {
- pic->mc_u_v_adr = y_adr +
- ((mc_buffer_size_u_v_h << 16) << 1);
-
- pic->mc_canvas_y =
- (pic->index << 1);
- pic->mc_canvas_u_v =
- (pic->index << 1) + 1;
-
- pic->dw_y_adr = y_adr;
- pic->dw_u_v_adr = pic->mc_u_v_adr;
- } else
-#endif
- if (dw_mode) {
#ifdef AVS2_10B_MMU
- pic->dw_y_adr = y_adr;
- pic->dw_u_v_adr = pic->dw_y_adr +
- ((mc_buffer_size_u_v_h << 16) << 1);
- pic->mc_y_adr = pic->dw_y_adr;
- pic->mc_u_v_adr = pic->dw_u_v_adr;
-#else
- pic->dw_y_adr = y_adr + (mc_buffer_size_h << 16);
- pic->dw_u_v_adr = pic->dw_y_adr +
- ((mc_buffer_size_u_v_h << 16) << 1);
+#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
- 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;
+ } 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;
}
@@ -2527,28 +2331,36 @@
struct avs2_decoder *avs2_dec = &dec->avs2_dec;
struct avs2_frame_s *pic;
#ifdef AVS2_10B_MMU
- if (dec->mmu_enable) {
- for (i = 0; i < dec->used_buf_num; i++) {
- unsigned long buf_addr;
- u32 header_size = get_compress_header_size(dec);
-#ifdef AVS2_10B_MMU_DW
- if (dec->dw_mmu_enable)
- header_size <<= 1;
-#endif
- if (decoder_bmmu_box_alloc_buf_phy
- (dec->bmmu_box,
- HEADER_BUFFER_IDX(i), header_size,
- DRIVER_HEADER_NAME,
- &buf_addr) < 0){
- avs2_print(dec, 0,
- "%s malloc compress header failed %d\n",
- DRIVER_HEADER_NAME, i);
- dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM;
- return;
- }
+ 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;
@@ -3261,7 +3073,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) & 0x20) == 0) {
+ 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);
@@ -3273,14 +3085,6 @@
#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);*/
@@ -3297,22 +3101,6 @@
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*/
@@ -3344,41 +3132,23 @@
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);
-#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 |= 0x670; // Big-Endian per 64-bit */
+ data32 |= endian; /* 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) {
@@ -3396,18 +3166,6 @@
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) {
@@ -3421,55 +3179,26 @@
data32 &= ~(0xff << 16);
WRITE_VREG(HEVC_SAO_CTRL5, data32);
} else {
- if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_T7)
- WRITE_VREG(HEVC_SAO_CTRL26, 0);
-
data32 = READ_VREG(HEVC_SAO_CTRL5);
data32 &= (~(0xff << 16));
- if ((get_double_write_mode(dec) & 0xf) == 8 ||
- (get_double_write_mode(dec) & 0xf) == 9) {
+ if (get_double_write_mode(dec) == 2 ||
+ get_double_write_mode(dec) == 3)
data32 |= (0xff<<16);
- WRITE_VREG(HEVC_SAO_CTRL26, 0xf);
- } else if ((get_double_write_mode(dec) & 0xf) == 2 ||
- (get_double_write_mode(dec) & 0xf) == 3)
- data32 |= (0xff<<16);
- else if ((get_double_write_mode(dec) & 0xf) == 4)
+ else if (get_double_write_mode(dec) == 4)
data32 |= (0x33<<16);
WRITE_VREG(HEVC_SAO_CTRL5, data32);