summaryrefslogtreecommitdiff
authorNanxin Qin <nanxin.qin@amlogic.com>2018-03-06 11:30:03 (GMT)
committer Nanxin Qin <nanxin.qin@amlogic.com>2018-03-07 13:54:24 (GMT)
commita6c89e9657159ba7a49d503e99246ebd647e974a (patch)
tree3e5219aa77267d9ee7259027ac4f7e6629eb8e09
parentd1ad76720316ef17f6582a1d8b770733567da7b3 (diff)
downloadmedia_modules-a6c89e9657159ba7a49d503e99246ebd647e974a.zip
media_modules-a6c89e9657159ba7a49d503e99246ebd647e974a.tar.gz
media_modules-a6c89e9657159ba7a49d503e99246ebd647e974a.tar.bz2
decoder: merges code from the branch of the bringup g12a
PD#161606: notes 1. fix avs2 bringup bug: config dblk_data2 and config HEVC_SAO_CTRL0 with lcu_size_log2 2. vdec: merge debug code from kernel 3.14, support step and schedule profile (multi-instance only) echo 0x100 > /sys/module/decoder_common/parameters/step_mode 3. decoder: fixed a bug of the vdec_profile event. the ISA register base has changeed to 0x3c00 on the txlx, g12a platforms 4. decoder: modify the value of the hevc reg HEVC_DBLK_STS1 G12A changes #define HEVC_DBLK_STS0 0x350f #define HEVC_DBLK_STS1 0x3510 5. stream_input: add a feature of check efuse status [2/2]. 6. media_clock: adds media clk nodes echo 1 > /sys/module/media_clock/parameters/set_frq_enable echo 667 > /sys/module/media_clock/parameters/vdec_frq echo 667 > /sys/module/media_clock/parameters/hevc_frq echo 667 > /sys/module/media_clock/parameters/hevcb_frq 7. media_modules: revised dolby vision macro control for g12a 8. ucode: update the video_ucode.bin Change-Id: Icf781a1e5f8095bd1b14a2b21e525683ad0cc22d Signed-off-by: Nanxin Qin <nanxin.qin@amlogic.com>
Diffstat
-rw-r--r--Media.mk1
-rw-r--r--drivers/common/chips/chips.c23
-rw-r--r--drivers/common/chips/chips.h2
-rw-r--r--drivers/common/firmware/firmware_cfg.h1
-rw-r--r--drivers/common/firmware/firmware_drv.c2
-rw-r--r--drivers/common/firmware/firmware_type.c4
-rw-r--r--drivers/common/firmware/firmware_type.h4
-rw-r--r--drivers/common/media_clock/Makefile2
-rw-r--r--drivers/common/media_clock/clk/clk.c46
-rw-r--r--drivers/common/media_clock/clk/clk.h13
-rw-r--r--drivers/common/media_clock/clk/clkg12.c1005
-rw-r--r--drivers/common/media_clock/clk/clkgx.c609
-rw-r--r--drivers/common/media_clock/switch/amports_gate.c7
-rw-r--r--drivers/frame_provider/decoder/Makefile1
-rw-r--r--drivers/frame_provider/decoder/avs/avsp_trans.c3
-rw-r--r--drivers/frame_provider/decoder/avs2/Makefile2
-rw-r--r--drivers/frame_provider/decoder/avs2/avs2_bufmgr.c1980
-rw-r--r--drivers/frame_provider/decoder/avs2/avs2_global.h1648
-rw-r--r--drivers/frame_provider/decoder/avs2/vavs2.c6057
-rw-r--r--drivers/frame_provider/decoder/avs2/vavs2.h26
-rw-r--r--drivers/frame_provider/decoder/h264_multi/vmh264.c24
-rw-r--r--drivers/frame_provider/decoder/h265/vh265.c266
-rw-r--r--drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c14
-rw-r--r--drivers/frame_provider/decoder/mpeg12/vmpeg12.c754
-rw-r--r--drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c20
-rw-r--r--drivers/frame_provider/decoder/real/vreal.c3
-rw-r--r--drivers/frame_provider/decoder/utils/amvdec.c22
-rw-r--r--drivers/frame_provider/decoder/utils/vdec.c721
-rw-r--r--drivers/frame_provider/decoder/utils/vdec.h62
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_profile.c28
-rw-r--r--drivers/frame_provider/decoder/vp9/vvp9.c2585
-rw-r--r--drivers/frame_provider/decoder/vp9/vvp9.h2
-rw-r--r--drivers/stream_input/amports/amstream.c44
-rwxr-xr-x[-rw-r--r--]firmware/video_ucode.bin3875
34 files changed, 17443 insertions, 2413 deletions
diff --git a/Media.mk b/Media.mk
index 494d003..37cb40a 100644
--- a/Media.mk
+++ b/Media.mk
@@ -14,6 +14,7 @@ CONFIGS := CONFIG_AMLOGIC_MEDIA_VDEC_MPEG12=m \
CONFIG_AMLOGIC_MEDIA_VDEC_MJPEG_MULTI=m \
CONFIG_AMLOGIC_MEDIA_VDEC_REAL=m \
CONFIG_AMLOGIC_MEDIA_VDEC_AVS=m \
+ CONFIG_AMLOGIC_MEDIA_VDEC_AVS2=m \
CONFIG_AMLOGIC_MEDIA_VENC_H264=m \
CONFIG_AMLOGIC_MEDIA_VECN_H265=m \
CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION=y
diff --git a/drivers/common/chips/chips.c b/drivers/common/chips/chips.c
index d5bfa0e..5ca9094 100644
--- a/drivers/common/chips/chips.c
+++ b/drivers/common/chips/chips.c
@@ -30,6 +30,7 @@
#include "../../frame_provider/decoder/utils/vdec.h"
#include "chips.h"
#include <linux/amlogic/media/utils/log.h>
+#include <linux/amlogic/media/utils/vdec_reg.h>
#define VIDEO_FIRMWARE_FATHER_NAME "video"
@@ -69,6 +70,7 @@ static const struct type_name cpu_type_name[] = {
{MESON_CPU_MAJOR_ID_GXM, "gxm"},
{MESON_CPU_MAJOR_ID_TXL, "txl"},
{MESON_CPU_MAJOR_ID_TXLX, "txlx"},
+ {MESON_CPU_MAJOR_ID_TXLX, "g12a"},
{0, NULL},
};
@@ -117,6 +119,7 @@ EXPORT_SYMBOL(get_cpu_type_name);
* VFORMAT_H264_ENC,
* VFORMAT_JPEG_ENC,
* VFORMAT_VP9,
+* VFORMAT_AVS2,
* VFORMAT_MAX
*};
*/
@@ -136,6 +139,7 @@ static const struct type_name vformat_type_name[] = {
{VFORMAT_H264_ENC, "h264_enc"},
{VFORMAT_JPEG_ENC, "jpeg_enc"},
{VFORMAT_VP9, "vp9"},
+ {VFORMAT_AVS2, "avs2"},
{VFORMAT_YUV, "yuv"},
{0, NULL},
};
@@ -157,3 +161,22 @@ struct chip_vdec_info_s *get_current_vdec_chip(void)
}
EXPORT_SYMBOL(get_current_vdec_chip);
+bool check_efuse_chip(int vformat)
+{
+ unsigned int status, i = 0;
+ int type[] = {15, 14, 11, 2}; /* avs2, vp9, h265, h264 */
+
+ status = (READ_EFUSE_REG(EFUSE_LIC2) >> 8 & 0xf);
+ if (!status)
+ return false;
+
+ do {
+ if ((status & 1) && (type[i] == vformat))
+ return true;
+ i++;
+ } while (status >>= 1);
+
+ return false;
+}
+EXPORT_SYMBOL(check_efuse_chip);
+
diff --git a/drivers/common/chips/chips.h b/drivers/common/chips/chips.h
index c52a83f..003e9d2 100644
--- a/drivers/common/chips/chips.h
+++ b/drivers/common/chips/chips.h
@@ -35,4 +35,6 @@ const char *get_video_format_name(enum vformat_e type);
struct chip_vdec_info_s *get_current_vdec_chip(void);
+bool check_efuse_chip(int vformat);
+
#endif
diff --git a/drivers/common/firmware/firmware_cfg.h b/drivers/common/firmware/firmware_cfg.h
index 8283de8..ae34ef1 100644
--- a/drivers/common/firmware/firmware_cfg.h
+++ b/drivers/common/firmware/firmware_cfg.h
@@ -22,6 +22,7 @@
{MESON_CPU_MAJOR_ID_GXM, VIDEO_PACKAGE, "video_ucode.bin"},
{MESON_CPU_MAJOR_ID_TXL, VIDEO_PACKAGE, "video_ucode.bin"},
{MESON_CPU_MAJOR_ID_TXLX, VIDEO_PACKAGE, "video_ucode.bin"},
+{MESON_CPU_MAJOR_ID_G12A, VIDEO_PACKAGE, "video_ucode.bin"},
/*firmware for a special format, to replace the format in the package.*/
{MESON_CPU_MAJOR_ID_GXL, VIDEO_DEC_HEVC, "h265.bin"},
diff --git a/drivers/common/firmware/firmware_drv.c b/drivers/common/firmware/firmware_drv.c
index a077aef..eb00d3f 100644
--- a/drivers/common/firmware/firmware_drv.c
+++ b/drivers/common/firmware/firmware_drv.c
@@ -43,7 +43,7 @@
#define DEV_NAME "firmware_vdec"
#define DIR "video"
#define FRIMWARE_SIZE (128 * 1024) /*128k*/
-#define BUFF_SIZE (1024 * 1024)
+#define BUFF_SIZE (1024 * 1024 * 2)
#define FW_LOAD_FORCE (0x1)
#define FW_LOAD_TRY (0X2)
diff --git a/drivers/common/firmware/firmware_type.c b/drivers/common/firmware/firmware_type.c
index 40a21ec..a6be5ad 100644
--- a/drivers/common/firmware/firmware_type.c
+++ b/drivers/common/firmware/firmware_type.c
@@ -20,8 +20,12 @@ static const struct type_name_s type_name[] = {
{VIDEO_DEC_H264_MULTI_MMU, "h264_multi_mmu"},
{VIDEO_DEC_HEVC, "hevc"},
{VIDEO_DEC_HEVC_MMU, "hevc_mmu"},
+ {VIDEO_DEC_HEVC_G12A, "hevc_g12a"},
{VIDEO_DEC_VP9, "vp9"},
{VIDEO_DEC_VP9_MMU, "vp9_mmu"},
+ {VIDEO_DEC_VP9_G12A, "vp9_g12a"},
+ {VIDEO_DEC_AVS2, "avs2"},
+ {VIDEO_DEC_AVS2_MMU, "avs2_mmu"},
{VIDEO_ENC_H264, "h264_enc"},
{VIDEO_ENC_JPEG, "jpeg_enc"},
{FIRMWARE_MAX, "unknown"},
diff --git a/drivers/common/firmware/firmware_type.h b/drivers/common/firmware/firmware_type.h
index 0bd842e..3ddd94b 100644
--- a/drivers/common/firmware/firmware_type.h
+++ b/drivers/common/firmware/firmware_type.h
@@ -28,6 +28,10 @@ enum firmware_type_e {
VIDEO_ENC_JPEG,
VIDEO_PACKAGE,
VIDEO_DEC_H264_MULTI_MMU,
+ VIDEO_DEC_HEVC_G12A,
+ VIDEO_DEC_VP9_G12A,
+ VIDEO_DEC_AVS2,
+ VIDEO_DEC_AVS2_MMU,
FIRMWARE_MAX
};
diff --git a/drivers/common/media_clock/Makefile b/drivers/common/media_clock/Makefile
index 25c9a10..994857a 100644
--- a/drivers/common/media_clock/Makefile
+++ b/drivers/common/media_clock/Makefile
@@ -1,5 +1,5 @@
obj-m += media_clock.o
media_clock-objs += ../chips/chips.o
-media_clock-objs += clk/clkgx.o
+media_clock-objs += clk/clkg12.o
media_clock-objs += clk/clk.o
media_clock-objs += switch/amports_gate.o
diff --git a/drivers/common/media_clock/clk/clk.c b/drivers/common/media_clock/clk/clk.c
index 05451c2..4102184 100644
--- a/drivers/common/media_clock/clk/clk.c
+++ b/drivers/common/media_clock/clk/clk.c
@@ -38,6 +38,7 @@
#define p_vdec2() (get_current_vdec_chip()->clk_mgr[VDEC_2])
#define p_vdec_hcodec() (get_current_vdec_chip()->clk_mgr[VDEC_HCODEC])
#define p_vdec_hevc() (get_current_vdec_chip()->clk_mgr[VDEC_HEVC])
+#define p_vdec_hevc_back() (get_current_vdec_chip()->clk_mgr[VDEC_HEVCB])
static int clock_source_wxhxfps_saved[VDEC_MAX + 1];
@@ -186,6 +187,31 @@ void hcodec_clock_off(void)
}
EXPORT_SYMBOL(hcodec_clock_off);
+int hevc_back_clock_init(void)
+{
+ if (p_vdec_hevc_back() && p_vdec_hevc_back()->clock_init)
+ return p_vdec_hevc_back()->clock_init();
+ else
+ return 0;
+}
+EXPORT_SYMBOL(hevc_back_clock_init);
+
+int hevc_back_clock_set(int clk)
+{
+ pr_debug("%s-----%d\n", __func__, clk);
+ if (p_vdec_hevc_back() && p_vdec_hevc_back()->clock_set)
+ return p_vdec_hevc_back()->clock_set(clk);
+ else
+ return -1;
+}
+EXPORT_SYMBOL(hevc_back_clock_set);
+
+void hevc_back_clock_enable(void)
+{
+ hevc_back_clock_set(1);
+}
+EXPORT_SYMBOL(hevc_back_clock_enable);
+
int hevc_clock_init(void)
{
if (p_vdec_hevc() && p_vdec_hevc()->clock_init)
@@ -217,6 +243,19 @@ void hevc_clock_hi_enable(void)
}
EXPORT_SYMBOL(hevc_clock_hi_enable);
+void hevc_back_clock_on(void)
+{
+ IF_HAVE_RUN(p_vdec_hevc_back(), clock_on);
+}
+EXPORT_SYMBOL(hevc_back_clock_on);
+
+void hevc_back_clock_off(void)
+{
+ IF_HAVE_RUN(p_vdec_hevc_back(), clock_off);
+ clock_source_wxhxfps_saved[VDEC_HEVCB] = 0;
+}
+EXPORT_SYMBOL(hevc_back_clock_off);
+
void hevc_clock_on(void)
{
IF_HAVE_RUN(p_vdec_hevc(), clock_on);
@@ -287,9 +326,14 @@ int vdec_source_changed_for_clk_set(int format, int width, int height, int fps)
*changed to default min clk.
*/
- if (format == VFORMAT_HEVC || format == VFORMAT_VP9) {
+ if (format == VFORMAT_HEVC || format == VFORMAT_VP9
+ || format == VFORMAT_AVS2) {
ret_clk = hevc_clock_set(clk);
clock_source_wxhxfps_saved[VDEC_HEVC] = width * height * fps;
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
+ ret_clk = hevc_back_clock_set(clk);
+ clock_source_wxhxfps_saved[VDEC_HEVCB] = width * height * fps;
+ }
} else if (format == VFORMAT_H264_ENC || format == VFORMAT_JPEG_ENC) {
ret_clk = hcodec_clock_set(clk);
clock_source_wxhxfps_saved[VDEC_HCODEC] = width * height * fps;
diff --git a/drivers/common/media_clock/clk/clk.h b/drivers/common/media_clock/clk/clk.h
index cc1bdd2..e1fa3f1 100644
--- a/drivers/common/media_clock/clk/clk.h
+++ b/drivers/common/media_clock/clk/clk.h
@@ -42,6 +42,11 @@ void hcodec_clock_off(void);
void hevc_clock_on(void);
void hevc_clock_off(void);
+int hevc_back_clock_init(void);
+void hevc_back_clock_on(void);
+void hevc_back_clock_off(void);
+int hevc_back_clock_set(int clk);
+
int vdec_source_get(enum vdec_type_e core);
int vdec_clk_get(enum vdec_type_e core);
@@ -95,6 +100,13 @@ static struct chip_vdec_clk_s vdec_hevc_clk_mgr __initdata = {
.clock_off = hevc_clock_off,
.clock_get = vdec_clock_get,
};
+static struct chip_vdec_clk_s vdec_hevc_back_clk_mgr __initdata = {
+ .clock_init = hevc_back_clock_init,
+ .clock_set = hevc_back_clock_set,
+ .clock_on = hevc_back_clock_on,
+ .clock_off = hevc_back_clock_off,
+ .clock_get = vdec_clock_get,
+};
#endif
#ifdef VDEC_HAS_VDEC_HCODEC
@@ -116,6 +128,7 @@ static int __init vdec_init_clk(void)
#endif
#ifdef VDEC_HAS_HEVC
register_vdec_clk_mgr(cpus, VDEC_HEVC, &vdec_hevc_clk_mgr);
+ register_vdec_clk_mgr(cpus, VDEC_HEVCB, &vdec_hevc_back_clk_mgr);
#endif
#ifdef VDEC_HAS_VDEC_HCODEC
register_vdec_clk_mgr(cpus, VDEC_HCODEC, &vdec_hcodec_clk_mgr);
diff --git a/drivers/common/media_clock/clk/clkg12.c b/drivers/common/media_clock/clk/clkg12.c
new file mode 100644
index 0000000..08f7be2
--- a/dev/null
+++ b/drivers/common/media_clock/clk/clkg12.c
@@ -0,0 +1,1005 @@
+/*
+ * drivers/amlogic/media/common/arch/clk/clkgx.c
+ *
+ * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+#define DEBUG
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/amlogic/media/clk/gp_pll.h>
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include <linux/amlogic/media/utils/amports_config.h>
+#include "../../../frame_provider/decoder/utils/vdec.h"
+#include <linux/amlogic/media/registers/register.h>
+#include "clk_priv.h"
+#include <linux/amlogic/media/utils/log.h>
+
+#include <linux/amlogic/media/registers/register_ops.h>
+#include "../switch/amports_gate.h"
+#define MHz (1000000)
+#define debug_print pr_info
+
+//#define NO_CLKTREE
+
+/* set gp0 648M vdec use gp0 clk*/
+#define VDEC1_648M() \
+ WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (6 << 9) | (0), 0, 16)
+
+#define HEVC_648M() \
+ WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (0), 16, 16)
+
+/*set gp0 1296M vdec use gp0 clk div2*/
+#define VDEC1_648M_DIV() \
+ WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (6 << 9) | (1), 0, 16)
+
+#define HEVC_648M_DIV() \
+ WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (1), 16, 16)
+
+#define VDEC1_WITH_GP_PLL() \
+ ((READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0xe00) == 0xc00)
+#define HEVC_WITH_GP_PLL() \
+ ((READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0xe000000) == 0xc000000)
+
+#define VDEC1_CLOCK_ON() \
+ do { if (is_meson_m8_cpu()) { \
+ WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \
+ WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \
+ } else { \
+ WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \
+ WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 15, 1); \
+ WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 8, 1); \
+ WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \
+ } \
+ } while (0)
+
+#define VDEC2_CLOCK_ON() do {\
+ WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 8, 1); \
+ WRITE_VREG(DOS_GCLK_EN1, 0x3ff);\
+ } while (0)
+
+#define HCODEC_CLOCK_ON() do {\
+ WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 24, 1); \
+ WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15);\
+ } while (0)
+#define HEVC_CLOCK_ON() do {\
+ WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 24, 1); \
+ WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 8, 1); \
+ WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 31, 1); \
+ WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 15, 1); \
+ WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 24, 1); \
+ WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);\
+ } while (0)
+#define VDEC1_SAFE_CLOCK() do {\
+ WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, \
+ READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x7f, 0, 7); \
+ WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 8, 1); \
+ WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 15, 1);\
+ } while (0)
+
+#define VDEC1_CLOCK_OFF() \
+ WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 8, 1)
+#define VDEC2_CLOCK_OFF() \
+ WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 8, 1)
+#define HCODEC_CLOCK_OFF() \
+ WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 24, 1)
+#define HEVC_SAFE_CLOCK() do { \
+ WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \
+ (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 16) & 0x7f, 16, 7);\
+ WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \
+ (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 25) & 0x7f, 25, 7);\
+ WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 24, 1); \
+ WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 31, 1);\
+ WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 15, 1);\
+ } while (0)
+
+#define HEVC_CLOCK_OFF() do {\
+ WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 24, 1);\
+ WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 8, 1);\
+}while(0)
+
+static int clock_real_clk[VDEC_MAX + 1];
+
+static unsigned int set_frq_enable, vdec_frq, hevc_frq, hevcb_frq;
+
+#ifdef NO_CLKTREE
+static struct gp_pll_user_handle_s *gp_pll_user_vdec, *gp_pll_user_hevc;
+static bool is_gp0_div2 = true;
+
+static int gp_pll_user_cb_vdec(struct gp_pll_user_handle_s *user,
+ int event)
+{
+ debug_print("gp_pll_user_cb_vdec call\n");
+ if (event == GP_PLL_USER_EVENT_GRANT) {
+ struct clk *clk = clk_get(NULL, "gp0_pll");
+ if (!IS_ERR(clk)) {
+ if (is_gp0_div2)
+ clk_set_rate(clk, 1296000000UL);
+ else
+ clk_set_rate(clk, 648000000UL);
+ VDEC1_SAFE_CLOCK();
+ VDEC1_CLOCK_OFF();
+ if (is_gp0_div2)
+ VDEC1_648M_DIV();
+ else
+ VDEC1_648M();
+
+ VDEC1_CLOCK_ON();
+ debug_print("gp_pll_user_cb_vdec call set\n");
+ }
+ }
+ return 0;
+}
+
+static int gp_pll_user_cb_hevc(struct gp_pll_user_handle_s *user,
+ int event)
+{
+ debug_print("gp_pll_user_cb_hevc callback\n");
+ if (event == GP_PLL_USER_EVENT_GRANT) {
+ struct clk *clk = clk_get(NULL, "gp0_pll");
+ if (!IS_ERR(clk)) {
+ if (is_gp0_div2)
+ clk_set_rate(clk, 1296000000UL);
+ else
+ clk_set_rate(clk, 648000000UL);
+// HEVC_SAFE_CLOCK();
+ HEVC_CLOCK_OFF();
+ if (is_gp0_div2)
+ HEVC_648M_DIV();
+ else
+ HEVC_648M();
+ HEVC_CLOCK_ON();
+ debug_print("gp_pll_user_cb_hevc callback2\n");
+ }
+ }
+
+ return 0;
+}
+
+
+#endif
+
+struct clk_mux_s {
+ struct gate_switch_node *vdec_mux_node;
+ struct gate_switch_node *hcodec_mux_node;
+ struct gate_switch_node *hevc_mux_node;
+ struct gate_switch_node *hevc_back_mux_node;
+};
+
+struct clk_mux_s gclk;
+
+void vdec1_set_clk(int source, int div)
+{
+ pr_debug("vdec1_set_clk %d, %d\n", source, div);
+ WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (source << 9) | (div - 1), 0, 16);
+}
+EXPORT_SYMBOL(vdec1_set_clk);
+
+void hcodec_set_clk(int source, int div)
+{
+ WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL,
+ (source << 9) | (div - 1), 16, 16);
+}
+EXPORT_SYMBOL(hcodec_set_clk);
+
+void vdec2_set_clk(int source, int div)
+{
+ WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL,
+ (source << 9) | (div - 1), 0, 16);
+}
+EXPORT_SYMBOL(vdec2_set_clk);
+
+//extern uint force_hevc_clock_cntl;
+uint force_hevc_clock_cntl = 0;
+void hevc_set_clk(int source, int div)
+{
+ if (force_hevc_clock_cntl) {
+ pr_info("%s, write force clock cntl %x\n", __func__, force_hevc_clock_cntl);
+ WRITE_HHI_REG(HHI_VDEC2_CLK_CNTL, force_hevc_clock_cntl);
+ } else {
+ pr_debug("hevc_set_clk %d, %d\n", source, div);
+ WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL,
+ (source << 9) | (div - 1), 16, 16);
+ WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (source << 9) | (div - 1), 0, 16);
+ }
+}
+EXPORT_SYMBOL(hevc_set_clk);
+
+void vdec_get_clk_source(int clk, int *source, int *div, int *rclk)
+{
+#define source_div4 (0)
+#define source_div3 (1)
+#define source_div5 (2)
+#define source_div7 (3)
+ if (clk > 500) {
+ *source = source_div3;
+ *div = 1;
+ *rclk = 667;
+ } else if (clk >= 500) {
+ *source = source_div4;
+ *div = 1;
+ *rclk = 500;
+ } else if (clk >= 400) {
+ *source = source_div5;
+ *div = 1;
+ *rclk = 400;
+ } else if (clk >= 333) {
+ *source = source_div3;
+ *div = 2;
+ *rclk = 333;
+ } else if (clk >= 200) {
+ *source = source_div5;
+ *div = 2;
+ *rclk = 200;
+ } else if (clk >= 166) {
+ *source = source_div4;
+ *div = 3;
+ *rclk = 166;
+ } else if (clk >= 133) {
+ *source = source_div5;
+ *div = 3;
+ *rclk = 133;
+ } else if (clk >= 100) {
+ *source = source_div5;
+ *div = 4;
+ *rclk = 100;
+ } else if (clk >= 50) {
+ *source = source_div5;
+ *div = 8;
+ *rclk = 50;
+ } else {
+ *source = source_div5;
+ *div = 20;
+ *rclk = 10;
+ }
+}
+EXPORT_SYMBOL(vdec_get_clk_source);
+
+
+/*
+ *enum vformat_e {
+ * VFORMAT_MPEG12 = 0,
+ * VFORMAT_MPEG4,
+ * VFORMAT_H264,
+ * VFORMAT_MJPEG,
+ * VFORMAT_REAL,
+ * VFORMAT_JPEG,
+ * VFORMAT_VC1,
+ * VFORMAT_AVS,
+ * VFORMAT_YUV,
+ * VFORMAT_H264MVC,
+ * VFORMAT_H264_4K2K,
+ * VFORMAT_HEVC,
+ * VFORMAT_H264_ENC,
+ * VFORMAT_JPEG_ENC,
+ * VFORMAT_VP9,
+ * VFORMAT_MAX
+ *};
+ *sample:
+ *{{1280*720*30, 100}, {1920*1080*30, 166}, {1920*1080*60, 333},
+ * {4096*2048*30, 600}, {4096*2048*60, 600}, {INT_MAX, 600},}
+ *mean:
+ *width * height * fps
+ *<720p30fps clk=100MHZ
+ *>=720p30fps & < 1080p30fps clk=166MHZ
+ *>=1080p 30fps & < 1080p60fps clk=333MHZ
+ */
+static struct clk_set_setting clks_for_formats[] = {
+ { /*[VFORMAT_MPEG12] */
+ {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
+ {1920 * 1080 * 60, 333},
+ {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+ 600}, {INT_MAX, 600},
+ }
+ },
+ { /*[VFORMAT_MPEG4] */
+ {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
+ {1920 * 1080 * 60, 333},
+ {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+ 600}, {INT_MAX, 600},
+ }
+ },
+ { /*[VFORMAT_H264] */
+ {{1280 * 720 * 30, 100}, {1920 * 1080 * 21, 166},
+ {1920 * 1080 * 30, 333},
+ {1920 * 1080 * 60, 600}, {4096 * 2048 * 60,
+ 600}, {INT_MAX, 600},
+ }
+ },
+ { /*[VFORMAT_MJPEG] */
+ {{1280 * 720 * 30, 200}, {1920 * 1080 * 30, 200},
+ {1920 * 1080 * 60, 333},
+ {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+ 600}, {INT_MAX, 600},
+ }
+ },
+ { /*[VFORMAT_REAL] */
+ {{1280 * 720 * 20, 200}, {1920 * 1080 * 30, 500},
+ {1920 * 1080 * 60, 500},
+ {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+ 600}, {INT_MAX, 600},
+ }
+ },
+ { /*[VFORMAT_JPEG] */
+ {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
+ {1920 * 1080 * 60, 333},
+ {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+ 600}, {INT_MAX, 600},
+ }
+ },
+ { /*[VFORMAT_VC1] */
+ {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
+ {1920 * 1080 * 60, 333},
+ {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+ 600}, {INT_MAX, 600},
+ }
+ },
+ { /*[VFORMAT_AVS] */
+ {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
+ {1920 * 1080 * 60, 333},
+ {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
+ 600}, {INT_MAX, 600},
+ }
+ },
+ { /*[VFORMAT_YUV] */
+ {{1280 * 720 * 30, 100}, {INT_MAX, 100},
+ {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ }
+ },
+ { /*VFORMAT_H264MVC */
+ {{1280 * 720 * 30, 333}, {1920 * 1080 * 30, 333},
+ {4096 * 2048 * 60, 600},
+ {INT_MAX, 630}, {0, 0}, {0, 0},
+ }
+ },
+ { /*VFORMAT_H264_4K2K */
+ {{1280 * 720 * 30, 600}, {4096 * 2048 * 60, 630},
+ {INT_MAX, 630},
+ {0, 0}, {0, 0}, {0, 0},
+ }
+ },
+ { /*VFORMAT_HEVC */
+ {{1280 * 720 * 30, 100}, {1920 * 1080 * 60, 600},
+ {4096 * 2048 * 25, 630},
+ {4096 * 2048 * 30, 630}, {4096 * 2048 * 60,
+ 630}, {INT_MAX, 630},
+ }
+ },
+ { /*VFORMAT_H264_ENC */
+ {{1280 * 720 * 30, 0}, {INT_MAX, 0},
+ {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ }
+ },
+ { /*VFORMAT_JPEG_ENC */
+ {{1280 * 720 * 30, 0}, {INT_MAX, 0},
+ {0, 0}, {0, 0}, {0, 0}, {0, 0},
+ }
+ },
+ { /*VFORMAT_VP9 */
+ {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 100},
+ {1920 * 1080 * 60, 166},
+ {4096 * 2048 * 30, 333}, {4096 * 2048 * 60,
+ 630}, {INT_MAX, 630},
+ }
+ },
+
+};
+
+void set_clock_gate(struct gate_switch_node *nodes, int num)
+{
+ struct gate_switch_node *node = NULL;
+
+ do {
+ node = &nodes[num - 1];
+ if (IS_ERR_OR_NULL(node))
+ pr_info("get mux clk err.\n");
+
+ if (!strcmp(node->name, "clk_vdec_mux"))
+ gclk.vdec_mux_node = node;
+ else if (!strcmp(node->name, "clk_hcodec_mux"))
+ gclk.hcodec_mux_node = node;
+ else if (!strcmp(node->name, "clk_hevc_mux"))
+ gclk.hevc_mux_node = node;
+ else if (!strcmp(node->name, "clk_hevcb_mux"))
+ gclk.hevc_back_mux_node = node;
+ } while(--num);
+}
+EXPORT_SYMBOL(set_clock_gate);
+#ifdef NO_CLKTREE
+int vdec_set_clk(int dec, int source, int div)
+{
+
+ if (dec == VDEC_1)
+ vdec1_set_clk(source, div);
+ else if (dec == VDEC_2)
+ vdec2_set_clk(source, div);
+ else if (dec == VDEC_HEVC)
+ hevc_set_clk(source, div);
+ else if (dec == VDEC_HCODEC)
+ hcodec_set_clk(source, div);
+ return 0;
+}
+
+#else
+static int vdec_set_clk(int dec, int rate)
+{
+ struct clk *clk = NULL;
+
+ switch (dec) {
+ case VDEC_1:
+ clk = gclk.vdec_mux_node->clk;
+ WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10);
+ break;
+
+ case VDEC_HCODEC:
+ clk = gclk.hcodec_mux_node->clk;
+ WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15);
+ break;
+
+ case VDEC_2:
+ clk = gclk.vdec_mux_node->clk;
+ WRITE_VREG(DOS_GCLK_EN1, 0x3ff);
+ break;
+
+ case VDEC_HEVC:
+ clk = gclk.hevc_mux_node->clk;
+ WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);
+ break;
+
+ case VDEC_HEVCB:
+ clk = gclk.hevc_back_mux_node->clk;
+ WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);
+ break;
+
+ case VDEC_MAX:
+ break;
+
+ default:
+ pr_info("invaild vdec type.\n");
+ }
+
+ if (IS_ERR_OR_NULL(clk)) {
+ pr_info("the mux clk err.\n");
+ return -1;
+ }
+
+ clk_set_rate(clk, rate);
+
+ return 0;
+}
+
+static int vdec_clock_init(void)
+{
+ return 0;
+}
+
+#endif
+#ifdef NO_CLKTREE
+static int vdec_clock_init(void)
+{
+ gp_pll_user_vdec = gp_pll_user_register("vdec", 0,
+ gp_pll_user_cb_vdec);
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL)
+ is_gp0_div2 = false;
+ else
+ is_gp0_div2 = true;
+
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) {
+ pr_info("used fix clk for vdec clk source!\n");
+ //update_vdec_clk_config_settings(1);
+ }
+ return (gp_pll_user_vdec) ? 0 : -ENOMEM;
+}
+
+
+
+static void update_clk_with_clk_configs(
+ int clk, int *source, int *div, int *rclk)
+{
+ unsigned int config = 0;//get_vdec_clk_config_settings();
+
+ if (!config)
+ return;
+ if (config >= 10) {
+ int wantclk;
+ wantclk = config;
+ vdec_get_clk_source(wantclk, source, div, rclk);
+ }
+ return;
+}
+#define NO_GP0_PLL 0//(get_vdec_clk_config_settings() == 1)
+#define ALWAYS_GP0_PLL 0//(get_vdec_clk_config_settings() == 2)
+
+#define NO_GP0_PLL 0//(get_vdec_clk_config_settings() == 1)
+#define ALWAYS_GP0_PLL 0//(get_vdec_clk_config_settings() == 2)
+
+static int vdec_clock_set(int clk)
+{
+ int use_gpll = 0;
+ int source, div, rclk;
+ int clk_seted = 0;
+ int gp_pll_wait = 0;
+ if (clk == 1)
+ clk = 200;
+ else if (clk == 2) {
+ if (clock_real_clk[VDEC_1] != 648)
+ clk = 500;
+ else
+ clk = 648;
+ } else if (clk == 0) {
+ /*used for release gp pull.
+ if used, release it.
+ if not used gp pll
+ do nothing.
+ */
+ if (clock_real_clk[VDEC_1] == 667 ||
+ (clock_real_clk[VDEC_1] == 648) ||
+ clock_real_clk[VDEC_1] <= 0)
+ clk = 200;
+ else
+ clk = clock_real_clk[VDEC_1];
+ }
+ vdec_get_clk_source(clk, &source, &div, &rclk);
+ update_clk_with_clk_configs(clk, &source, &div, &rclk);
+
+ if (clock_real_clk[VDEC_1] == rclk)
+ return rclk;
+ if (NO_GP0_PLL) {
+ use_gpll = 0;
+ clk_seted = 0;
+ } else if ((rclk > 500 && clk != 667) || ALWAYS_GP0_PLL) {
+ if (clock_real_clk[VDEC_1] == 648)
+ return 648;
+ use_gpll = 1;
+ gp_pll_request(gp_pll_user_vdec);
+ while (!VDEC1_WITH_GP_PLL() && gp_pll_wait++ < 1000000)
+ udelay(1);
+ if (VDEC1_WITH_GP_PLL()) {
+ clk_seted = 1;
+ rclk = 648;
+ } else {
+ use_gpll = 0;
+ rclk = 667;
+ /*gp_pull request failed,used default 500Mhz*/
+ pr_info("get gp pll failed used fix pull\n");
+ }
+ }
+ if (!clk_seted) {/*if 648 not set,*/
+ VDEC1_SAFE_CLOCK();
+ VDEC1_CLOCK_OFF();
+ vdec_set_clk(VDEC_1, source, div);
+ VDEC1_CLOCK_ON();
+ }
+
+ if (!use_gpll)
+ gp_pll_release(gp_pll_user_vdec);
+ clock_real_clk[VDEC_1] = rclk;
+ debug_print("vdec_clock_set 2 to %d\n", rclk);
+ return rclk;
+}
+static int hevc_clock_init(void)
+{
+ gp_pll_user_hevc = gp_pll_user_register("hevc", 0,
+ gp_pll_user_cb_hevc);
+
+ return (gp_pll_user_hevc) ? 0 : -ENOMEM;
+}
+static int hevc_clock_set(int clk)
+{
+ int use_gpll = 0;
+ int source, div, rclk;
+ int gp_pll_wait = 0;
+ int clk_seted = 0;
+
+ debug_print("hevc_clock_set 1 to clk %d\n", clk);
+ if (clk == 1)
+ clk = 200;
+ else if (clk == 2) {
+ if (clock_real_clk[VDEC_HEVC] != 648)
+ clk = 500;
+ else
+ clk = 648;
+ } else if (clk == 0) {
+ /*used for release gp pull.
+ if used, release it.
+ if not used gp pll
+ do nothing.
+ */
+ if ((clock_real_clk[VDEC_HEVC] == 667) ||
+ (clock_real_clk[VDEC_HEVC] == 648) ||
+ (clock_real_clk[VDEC_HEVC] <= 0))
+ clk = 200;
+ else
+ clk = clock_real_clk[VDEC_HEVC];
+ }
+ vdec_get_clk_source(clk, &source, &div, &rclk);
+ update_clk_with_clk_configs(clk, &source, &div, &rclk);
+
+ if (rclk == clock_real_clk[VDEC_HEVC])
+ return rclk;/*clk not changed,*/
+ if (NO_GP0_PLL) {
+ use_gpll = 0;
+ clk_seted = 0;
+ } else if ((rclk > 500 && clk != 667) || ALWAYS_GP0_PLL) {
+ if (clock_real_clk[VDEC_HEVC] == 648)
+ return 648;
+ use_gpll = 1;
+ gp_pll_request(gp_pll_user_hevc);
+ while (!HEVC_WITH_GP_PLL() && gp_pll_wait++ < 1000000)
+ udelay(1);
+ if (HEVC_WITH_GP_PLL()) {
+ clk_seted = 1;
+ rclk = 648;
+ } else {
+ rclk = 667;
+ /*gp_pull request failed,used default 500Mhz*/
+ pr_info("get gp pll failed used fix pull\n");
+ }
+ }
+ if (!clk_seted) {/*if 648 not set,*/
+// HEVC_SAFE_CLOCK();
+ HEVC_CLOCK_OFF();
+ vdec_set_clk(VDEC_HEVC, source, div);
+ HEVC_CLOCK_ON();
+ }
+ if (!use_gpll)
+ gp_pll_release(gp_pll_user_hevc);
+ clock_real_clk[VDEC_HEVC] = rclk;
+ /*debug_print("hevc_clock_set 2 to rclk=%d, configs=%d\n",
+ rclk,
+ get_vdec_clk_config_settings());*/ //DEBUG_TMP
+ return rclk;
+}
+
+static int hcodec_clock_set(int clk)
+{
+ int source, div, rclk;
+ HCODEC_CLOCK_OFF();
+ vdec_get_clk_source(200, &source, &div, &rclk);
+ vdec_set_clk(VDEC_HCODEC, source, div);
+ HCODEC_CLOCK_ON();
+ clock_real_clk[VDEC_HCODEC] = rclk;
+ return rclk;
+}
+
+
+#else
+static int vdec_clock_set(int clk)
+{
+ if (clk == 1)
+ clk = 200;
+ else if (clk == 2) {
+ if (clock_real_clk[VDEC_1] != 648)
+ clk = 500;
+ else
+ clk = 648;
+ } else if (clk == 0) {
+ if (clock_real_clk[VDEC_1] == 667 ||
+ (clock_real_clk[VDEC_1] == 648) ||
+ clock_real_clk[VDEC_1] <= 0)
+ clk = 200;
+ else
+ clk = clock_real_clk[VDEC_1];
+ }
+
+ if ((clk > 500 && clk != 667)) {
+ if (clock_real_clk[VDEC_1] == 648)
+ return 648;
+ clk = 667;
+ }
+
+ if (set_frq_enable && vdec_frq) {
+ pr_info("Set the vdec frq is %u MHz\n", vdec_frq);
+ clk = vdec_frq;
+ }
+
+ vdec_set_clk(VDEC_1, clk * MHz);
+
+ clock_real_clk[VDEC_1] = clk;
+
+ pr_debug("vdec mux clock is %lu Hz\n",
+ clk_get_rate(gclk.vdec_mux_node->clk));
+
+ return clk;
+}
+
+static int hevc_clock_init(void)
+{
+ return 0;
+}
+
+static int hevc_back_clock_init(void)
+{
+ return 0;
+}
+
+static int hevc_back_clock_set(int clk)
+{
+ if (clk == 1)
+ clk = 200;
+ else if (clk == 2) {
+ if (clock_real_clk[VDEC_HEVCB] != 648)
+ clk = 500;
+ else
+ clk = 648;
+ } else if (clk == 0) {
+ if (clock_real_clk[VDEC_HEVCB] == 667 ||
+ (clock_real_clk[VDEC_HEVCB] == 648) ||
+ clock_real_clk[VDEC_HEVCB] <= 0)
+ clk = 200;
+ else
+ clk = clock_real_clk[VDEC_HEVCB];
+ }
+
+ if ((clk > 500 && clk != 667)) {
+ if (clock_real_clk[VDEC_HEVCB] == 648)
+ return 648;
+ clk = 667;
+ }
+
+ if (set_frq_enable && hevcb_frq) {
+ pr_info("Set the hevcb frq is %u MHz\n", hevcb_frq);
+ clk = hevcb_frq;
+ }
+
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX) {
+ if ((READ_EFUSE_REG(EFUSE_LIC1) >> 28 & 0x1) && clk > 333) {
+ pr_info("The hevcb clock limit to 333MHz.\n");
+ clk = 333;
+ }
+ }
+
+ vdec_set_clk(VDEC_HEVCB, clk * MHz);
+
+ clock_real_clk[VDEC_HEVCB] = clk;
+ pr_debug("hevc back mux clock is %lu Hz\n",
+ clk_get_rate(gclk.hevc_back_mux_node->clk));
+
+ return clk;
+}
+
+static int hevc_clock_set(int clk)
+{
+ if (clk == 1)
+ clk = 200;
+ else if (clk == 2) {
+ if (clock_real_clk[VDEC_HEVC] != 648)
+ clk = 500;
+ else
+ clk = 648;
+ } else if (clk == 0) {
+ if (clock_real_clk[VDEC_HEVC] == 667 ||
+ (clock_real_clk[VDEC_HEVC] == 648) ||
+ clock_real_clk[VDEC_HEVC] <= 0)
+ clk = 200;
+ else
+ clk = clock_real_clk[VDEC_HEVC];
+ }
+
+ if ((clk > 500 && clk != 667)) {
+ if (clock_real_clk[VDEC_HEVC] == 648)
+ return 648;
+ clk = 667;
+ }
+
+ if (set_frq_enable && hevc_frq) {
+ pr_info("Set the hevc frq is %u MHz\n", hevc_frq);
+ clk = hevc_frq;
+ }
+
+ vdec_set_clk(VDEC_HEVC, clk * MHz);
+
+ clock_real_clk[VDEC_HEVC] = clk;
+
+ pr_debug("hevc mux clock is %lu Hz\n",
+ clk_get_rate(gclk.hevc_mux_node->clk));
+
+ return clk;
+}
+
+static int hcodec_clock_set(int clk)
+{
+ if (clk == 1)
+ clk = 200;
+ else if (clk == 2) {
+ if (clock_real_clk[VDEC_HCODEC] != 648)
+ clk = 500;
+ else
+ clk = 648;
+ } else if (clk == 0) {
+ if (clock_real_clk[VDEC_HCODEC] == 667 ||
+ (clock_real_clk[VDEC_HCODEC] == 648) ||
+ clock_real_clk[VDEC_HCODEC] <= 0)
+ clk = 200;
+ else
+ clk = clock_real_clk[VDEC_HCODEC];
+ }
+
+ if ((clk > 500 && clk != 667)) {
+ if (clock_real_clk[VDEC_HCODEC] == 648)
+ return 648;
+ clk = 667;
+ }
+
+ vdec_set_clk(VDEC_HCODEC, clk * MHz);
+
+ clock_real_clk[VDEC_HCODEC] = clk;
+
+ pr_debug("hcodec mux clock is %lu Hz\n",
+ clk_get_rate(gclk.hcodec_mux_node->clk));
+
+ return clk;
+}
+#endif
+
+static void vdec_clock_on(void)
+{
+ mutex_lock(&gclk.vdec_mux_node->mutex);
+ if (!gclk.vdec_mux_node->ref_count)
+ clk_prepare_enable(gclk.vdec_mux_node->clk);
+
+ gclk.vdec_mux_node->ref_count++;
+ mutex_unlock(&gclk.vdec_mux_node->mutex);
+
+ pr_debug("the %-15s clock on, ref cnt: %d\n",
+ gclk.vdec_mux_node->name,
+ gclk.vdec_mux_node->ref_count);
+}
+
+static void vdec_clock_off(void)
+{
+ mutex_lock(&gclk.vdec_mux_node->mutex);
+ gclk.vdec_mux_node->ref_count--;
+ if (!gclk.vdec_mux_node->ref_count)
+ clk_disable_unprepare(gclk.vdec_mux_node->clk);
+
+ clock_real_clk[VDEC_1] = 0;
+ mutex_unlock(&gclk.vdec_mux_node->mutex);
+
+ pr_debug("the %-15s clock off, ref cnt: %d\n",
+ gclk.vdec_mux_node->name,
+ gclk.vdec_mux_node->ref_count);
+}
+
+static void hcodec_clock_on(void)
+{
+ mutex_lock(&gclk.hcodec_mux_node->mutex);
+ if (!gclk.hcodec_mux_node->ref_count)
+ clk_prepare_enable(gclk.hcodec_mux_node->clk);
+
+ gclk.hcodec_mux_node->ref_count++;
+ mutex_unlock(&gclk.hcodec_mux_node->mutex);
+
+ pr_debug("the %-15s clock on, ref cnt: %d\n",
+ gclk.hcodec_mux_node->name,
+ gclk.hcodec_mux_node->ref_count);
+}
+
+static void hcodec_clock_off(void)
+{
+ mutex_lock(&gclk.hcodec_mux_node->mutex);
+ gclk.hcodec_mux_node->ref_count--;
+ if (!gclk.hcodec_mux_node->ref_count)
+ clk_disable_unprepare(gclk.hcodec_mux_node->clk);
+
+ mutex_unlock(&gclk.hcodec_mux_node->mutex);
+
+ pr_debug("the %-15s clock off, ref cnt: %d\n",
+ gclk.hcodec_mux_node->name,
+ gclk.hcodec_mux_node->ref_count);
+}
+
+static void hevc_clock_on(void)
+{
+ mutex_lock(&gclk.hevc_mux_node->mutex);
+ if (!gclk.hevc_mux_node->ref_count)
+ clk_prepare_enable(gclk.hevc_mux_node->clk);
+
+ gclk.hevc_mux_node->ref_count++;
+ WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);
+ mutex_unlock(&gclk.hevc_mux_node->mutex);
+
+ pr_debug("the %-15s clock on, ref cnt: %d\n",
+ gclk.hevc_mux_node->name,
+ gclk.hevc_mux_node->ref_count);
+}
+
+static void hevc_clock_off(void)
+{
+ mutex_lock(&gclk.hevc_mux_node->mutex);
+ gclk.hevc_mux_node->ref_count--;
+ if (!gclk.hevc_mux_node->ref_count)
+ clk_disable_unprepare(gclk.hevc_mux_node->clk);
+
+ clock_real_clk[VDEC_HEVC] = 0;
+ mutex_unlock(&gclk.hevc_mux_node->mutex);
+
+ pr_debug("the %-15s clock off, ref cnt: %d\n",
+ gclk.hevc_mux_node->name,
+ gclk.hevc_mux_node->ref_count);
+}
+
+static void hevc_back_clock_on(void)
+{
+ mutex_lock(&gclk.hevc_back_mux_node->mutex);
+ if (!gclk.hevc_back_mux_node->ref_count)
+ clk_prepare_enable(gclk.hevc_back_mux_node->clk);
+
+ gclk.hevc_back_mux_node->ref_count++;
+ WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);
+ mutex_unlock(&gclk.hevc_back_mux_node->mutex);
+
+ pr_debug("the %-15s clock on, ref cnt: %d\n",
+ gclk.hevc_back_mux_node->name,
+ gclk.hevc_back_mux_node->ref_count);
+}
+
+static void hevc_back_clock_off(void)
+{
+ mutex_lock(&gclk.hevc_back_mux_node->mutex);
+ gclk.hevc_back_mux_node->ref_count--;
+ if (!gclk.hevc_back_mux_node->ref_count)
+ clk_disable_unprepare(gclk.hevc_back_mux_node->clk);
+
+ clock_real_clk[VDEC_HEVC] = 0;
+ mutex_unlock(&gclk.hevc_back_mux_node->mutex);
+
+ pr_debug("the %-15s clock off, ref cnt: %d\n",
+ gclk.hevc_back_mux_node->name,
+ gclk.hevc_back_mux_node->ref_count);
+}
+
+static int vdec_clock_get(enum vdec_type_e core)
+{
+ if (core >= VDEC_MAX)
+ return 0;
+
+ return clock_real_clk[core];
+}
+
+#define INCLUDE_FROM_ARCH_CLK_MGR
+
+/*#define VDEC_HAS_VDEC2*/
+#define VDEC_HAS_HEVC
+#define VDEC_HAS_VDEC_HCODEC
+#define VDEC_HAS_CLK_SETTINGS
+#define CLK_FOR_CPU {\
+ MESON_CPU_MAJOR_ID_GXBB,\
+ MESON_CPU_MAJOR_ID_GXTVBB,\
+ MESON_CPU_MAJOR_ID_GXL,\
+ MESON_CPU_MAJOR_ID_GXM,\
+ MESON_CPU_MAJOR_ID_TXL,\
+ MESON_CPU_MAJOR_ID_TXLX,\
+ MESON_CPU_MAJOR_ID_G12A,\
+ 0}
+#include "clk.h"
+
+module_param(set_frq_enable, uint, 0664);
+MODULE_PARM_DESC(set_frq_enable, "\n set frequency enable\n");
+
+module_param(vdec_frq, uint, 0664);
+MODULE_PARM_DESC(vdec_frq, "\n set vdec frequency\n");
+
+module_param(hevc_frq, uint, 0664);
+MODULE_PARM_DESC(hevc_frq, "\n set hevc frequency\n");
+
+module_param(hevcb_frq, uint, 0664);
+MODULE_PARM_DESC(hevcb_frq, "\n set hevcb frequency\n");
+
+ARCH_VDEC_CLK_INIT();
+ARCH_VDEC_CLK_EXIT();
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/common/media_clock/clk/clkgx.c b/drivers/common/media_clock/clk/clkgx.c
deleted file mode 100644
index 1212d4f..0000000
--- a/drivers/common/media_clock/clk/clkgx.c
+++ b/dev/null
@@ -1,609 +0,0 @@
-/*
- * drivers/amlogic/media/common/arch/clk/clkgx.c
- *
- * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- */
-#define DEBUG
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/amlogic/media/clk/gp_pll.h>
-#include <linux/amlogic/media/utils/vdec_reg.h>
-#include <linux/amlogic/media/utils/amports_config.h>
-#include "../../../frame_provider/decoder/utils/vdec.h"
-#include <linux/amlogic/media/registers/register.h>
-#include "clk_priv.h"
-#include <linux/amlogic/media/utils/log.h>
-
-#include <linux/amlogic/media/registers/register_ops.h>
-#include "../switch/amports_gate.h"
-#define MHz (1000000)
-
-struct clk_mux_s {
- struct gate_switch_node *vdec_mux_node;
- struct gate_switch_node *hcodec_mux_node;
- struct gate_switch_node *hevc_mux_node;
-};
-
-struct clk_mux_s gclk;
-
-void vdec1_set_clk(int source, int div)
-{
- pr_debug("vdec1_set_clk %d, %d\n", source, div);
- WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (source << 9) | (div - 1), 0, 16);
-}
-EXPORT_SYMBOL(vdec1_set_clk);
-
-void hcodec_set_clk(int source, int div)
-{
- WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL,
- (source << 9) | (div - 1), 16, 16);
-}
-EXPORT_SYMBOL(hcodec_set_clk);
-
-void vdec2_set_clk(int source, int div)
-{
- WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL,
- (source << 9) | (div - 1), 0, 16);
-}
-EXPORT_SYMBOL(vdec2_set_clk);
-
-void hevc_set_clk(int source, int div)
-{
- pr_debug("hevc_set_clk %d, %d\n", source, div);
- WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL,
- (source << 9) | (div - 1), 16, 16);
-}
-EXPORT_SYMBOL(hevc_set_clk);
-
-void vdec_get_clk_source(int clk, int *source, int *div, int *rclk)
-{
-#define source_div4 (0)
-#define source_div3 (1)
-#define source_div5 (2)
-#define source_div7 (3)
- if (clk > 500) {
- *source = source_div3;
- *div = 1;
- *rclk = 667;
- } else if (clk >= 500) {
- *source = source_div4;
- *div = 1;
- *rclk = 500;
- } else if (clk >= 400) {
- *source = source_div5;
- *div = 1;
- *rclk = 400;
- } else if (clk >= 333) {
- *source = source_div3;
- *div = 2;
- *rclk = 333;
- } else if (clk >= 200) {
- *source = source_div5;
- *div = 2;
- *rclk = 200;
- } else if (clk >= 166) {
- *source = source_div4;
- *div = 3;
- *rclk = 166;
- } else if (clk >= 133) {
- *source = source_div5;
- *div = 3;
- *rclk = 133;
- } else if (clk >= 100) {
- *source = source_div5;
- *div = 4;
- *rclk = 100;
- } else if (clk >= 50) {
- *source = source_div5;
- *div = 8;
- *rclk = 50;
- } else {
- *source = source_div5;
- *div = 20;
- *rclk = 10;
- }
-}
-EXPORT_SYMBOL(vdec_get_clk_source);
-
-/* set gp0 648M vdec use gp0 clk*/
-#define VDEC1_648M() \
- WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (6 << 9) | (0), 0, 16)
-
-#define HEVC_648M() \
- WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (0), 16, 16)
-
-/*set gp0 1296M vdec use gp0 clk div2*/
-#define VDEC1_648M_DIV() \
- WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (6 << 9) | (1), 0, 16)
-
-#define HEVC_648M_DIV() \
- WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (1), 16, 16)
-
-#define VDEC1_WITH_GP_PLL() \
- ((READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0xe00) == 0xc00)
-#define HEVC_WITH_GP_PLL() \
- ((READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0xe000000) == 0xc000000)
-
-#define VDEC1_CLOCK_ON() \
- do { if (is_meson_m8_cpu()) { \
- WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \
- WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \
- } else { \
- WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \
- WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 15, 1); \
- WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 8, 1); \
- WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \
- } \
- } while (0)
-
-#define VDEC2_CLOCK_ON() do {\
- WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 8, 1); \
- WRITE_VREG(DOS_GCLK_EN1, 0x3ff);\
- } while (0)
-
-#define HCODEC_CLOCK_ON() do {\
- WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 24, 1); \
- WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15);\
- } while (0)
-#define HEVC_CLOCK_ON() do {\
- WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 24, 1); \
- WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 31, 1); \
- WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 24, 1); \
- WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);\
- } while (0)
-#define VDEC1_SAFE_CLOCK() do {\
- WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, \
- READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x7f, 0, 7); \
- WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 8, 1); \
- WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 15, 1);\
- } while (0)
-
-#define VDEC1_CLOCK_OFF() \
- WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 8, 1)
-#define VDEC2_CLOCK_OFF() \
- WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 8, 1)
-#define HCODEC_CLOCK_OFF() \
- WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 24, 1)
-#define HEVC_SAFE_CLOCK() do { \
- WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \
- (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 16) & 0x7f, 16, 7);\
- WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \
- (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 25) & 0x7f, 25, 7);\
- WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 24, 1); \
- WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 31, 1);\
- } while (0)
-
-#define HEVC_CLOCK_OFF() WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 24, 1)
-
-static int clock_real_clk[VDEC_MAX + 1];
-
-/*
- *enum vformat_e {
- * VFORMAT_MPEG12 = 0,
- * VFORMAT_MPEG4,
- * VFORMAT_H264,
- * VFORMAT_MJPEG,
- * VFORMAT_REAL,
- * VFORMAT_JPEG,
- * VFORMAT_VC1,
- * VFORMAT_AVS,
- * VFORMAT_YUV,
- * VFORMAT_H264MVC,
- * VFORMAT_H264_4K2K,
- * VFORMAT_HEVC,
- * VFORMAT_H264_ENC,
- * VFORMAT_JPEG_ENC,
- * VFORMAT_VP9,
- * VFORMAT_MAX
- *};
- *sample:
- *{{1280*720*30, 100}, {1920*1080*30, 166}, {1920*1080*60, 333},
- * {4096*2048*30, 600}, {4096*2048*60, 600}, {INT_MAX, 600},}
- *mean:
- *width * height * fps
- *<720p30fps clk=100MHZ
- *>=720p30fps & < 1080p30fps clk=166MHZ
- *>=1080p 30fps & < 1080p60fps clk=333MHZ
- */
-static struct clk_set_setting clks_for_formats[] = {
- { /*[VFORMAT_MPEG12] */
- {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
- {1920 * 1080 * 60, 333},
- {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
- 600}, {INT_MAX, 600},
- }
- },
- { /*[VFORMAT_MPEG4] */
- {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
- {1920 * 1080 * 60, 333},
- {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
- 600}, {INT_MAX, 600},
- }
- },
- { /*[VFORMAT_H264] */
- {{1280 * 720 * 30, 100}, {1920 * 1080 * 21, 166},
- {1920 * 1080 * 30, 333},
- {1920 * 1080 * 60, 600}, {4096 * 2048 * 60,
- 600}, {INT_MAX, 600},
- }
- },
- { /*[VFORMAT_MJPEG] */
- {{1280 * 720 * 30, 200}, {1920 * 1080 * 30, 200},
- {1920 * 1080 * 60, 333},
- {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
- 600}, {INT_MAX, 600},
- }
- },
- { /*[VFORMAT_REAL] */
- {{1280 * 720 * 20, 200}, {1920 * 1080 * 30, 500},
- {1920 * 1080 * 60, 500},
- {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
- 600}, {INT_MAX, 600},
- }
- },
- { /*[VFORMAT_JPEG] */
- {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
- {1920 * 1080 * 60, 333},
- {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
- 600}, {INT_MAX, 600},
- }
- },
- { /*[VFORMAT_VC1] */
- {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
- {1920 * 1080 * 60, 333},
- {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
- 600}, {INT_MAX, 600},
- }
- },
- { /*[VFORMAT_AVS] */
- {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166},
- {1920 * 1080 * 60, 333},
- {4096 * 2048 * 30, 600}, {4096 * 2048 * 60,
- 600}, {INT_MAX, 600},
- }
- },
- { /*[VFORMAT_YUV] */
- {{1280 * 720 * 30, 100}, {INT_MAX, 100},
- {0, 0}, {0, 0}, {0, 0}, {0, 0},
- }
- },
- { /*VFORMAT_H264MVC */
- {{1280 * 720 * 30, 333}, {1920 * 1080 * 30, 333},
- {4096 * 2048 * 60, 600},
- {INT_MAX, 630}, {0, 0}, {0, 0},
- }
- },
- { /*VFORMAT_H264_4K2K */
- {{1280 * 720 * 30, 600}, {4096 * 2048 * 60, 630},
- {INT_MAX, 630},
- {0, 0}, {0, 0}, {0, 0},
- }
- },
- { /*VFORMAT_HEVC */
- {{1280 * 720 * 30, 100}, {1920 * 1080 * 60, 600},
- {4096 * 2048 * 25, 630},
- {4096 * 2048 * 30, 630}, {4096 * 2048 * 60,
- 630}, {INT_MAX, 630},
- }
- },
- { /*VFORMAT_H264_ENC */
- {{1280 * 720 * 30, 0}, {INT_MAX, 0},
- {0, 0}, {0, 0}, {0, 0}, {0, 0},
- }
- },
- { /*VFORMAT_JPEG_ENC */
- {{1280 * 720 * 30, 0}, {INT_MAX, 0},
- {0, 0}, {0, 0}, {0, 0}, {0, 0},
- }
- },
- { /*VFORMAT_VP9 */
- {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 100},
- {1920 * 1080 * 60, 166},
- {4096 * 2048 * 30, 333}, {4096 * 2048 * 60,
- 630}, {INT_MAX, 630},
- }
- },
-
-};
-
-void set_clock_gate(struct gate_switch_node *nodes, int num)
-{
- struct gate_switch_node *node = NULL;
-
- do {
- node = &nodes[num - 1];
- if (IS_ERR_OR_NULL(node))
- pr_info("get mux clk err.\n");
-
- if (!strcmp(node->name, "clk_vdec_mux"))
- gclk.vdec_mux_node = node;
- else if (!strcmp(node->name, "clk_hcodec_mux"))
- gclk.hcodec_mux_node = node;
- else if (!strcmp(node->name, "clk_hevc_mux"))
- gclk.hevc_mux_node = node;
- } while (--num);
-}
-EXPORT_SYMBOL(set_clock_gate);
-
-static int vdec_set_clk(int dec, int rate)
-{
- struct clk *clk = NULL;
-
- switch (dec) {
- case VDEC_1:
- clk = gclk.vdec_mux_node->clk;
- WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10);
- break;
-
- case VDEC_HCODEC:
- clk = gclk.hcodec_mux_node->clk;
- WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15);
- break;
-
- case VDEC_2:
- clk = gclk.vdec_mux_node->clk;
- WRITE_VREG(DOS_GCLK_EN1, 0x3ff);
- break;
-
- case VDEC_HEVC:
- clk = gclk.hevc_mux_node->clk;
- WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);
- break;
-
- case VDEC_MAX:
- break;
-
- default:
- pr_info("invaild vdec type.\n");
- }
-
- if (IS_ERR_OR_NULL(clk)) {
- pr_info("the mux clk err.\n");
- return -1;
- }
-
- clk_set_rate(clk, rate);
-
- return 0;
-}
-
-static int vdec_clock_init(void)
-{
- return 0;
-}
-
-static int vdec_clock_set(int clk)
-{
- if (clk == 1)
- clk = 200;
- else if (clk == 2) {
- if (clock_real_clk[VDEC_1] != 648)
- clk = 500;
- else
- clk = 648;
- } else if (clk == 0) {
- if (clock_real_clk[VDEC_1] == 667 ||
- (clock_real_clk[VDEC_1] == 648) ||
- clock_real_clk[VDEC_1] <= 0)
- clk = 200;
- else
- clk = clock_real_clk[VDEC_1];
- }
-
- if ((clk > 500 && clk != 667)) {
- if (clock_real_clk[VDEC_1] == 648)
- return 648;
- clk = 667;
- }
-
- vdec_set_clk(VDEC_1, clk * MHz);
-
- clock_real_clk[VDEC_1] = clk;
-
- pr_debug("vdec mux clock is %lu Hz\n",
- clk_get_rate(gclk.vdec_mux_node->clk));
-
- return clk;
-}
-
-static int hevc_clock_init(void)
-{
- return 0;
-}
-
-static int hevc_clock_set(int clk)
-{
- if (clk == 1)
- clk = 200;
- else if (clk == 2) {
- if (clock_real_clk[VDEC_HEVC] != 648)
- clk = 500;
- else
- clk = 648;
- } else if (clk == 0) {
- if (clock_real_clk[VDEC_HEVC] == 667 ||
- (clock_real_clk[VDEC_HEVC] == 648) ||
- clock_real_clk[VDEC_HEVC] <= 0)
- clk = 200;
- else
- clk = clock_real_clk[VDEC_HEVC];
- }
-
- if ((clk > 500 && clk != 667)) {
- if (clock_real_clk[VDEC_HEVC] == 648)
- return 648;
- clk = 667;
- }
-
- vdec_set_clk(VDEC_HEVC, clk * MHz);
-
- clock_real_clk[VDEC_HEVC] = clk;
-
- pr_debug("hevc mux clock is %lu Hz\n",
- clk_get_rate(gclk.hevc_mux_node->clk));
-
- return clk;
-}
-
-static int hcodec_clock_set(int clk)
-{
- if (clk == 1)
- clk = 200;
- else if (clk == 2) {
- if (clock_real_clk[VDEC_HCODEC] != 648)
- clk = 500;
- else
- clk = 648;
- } else if (clk == 0) {
- if (clock_real_clk[VDEC_HCODEC] == 667 ||
- (clock_real_clk[VDEC_HCODEC] == 648) ||
- clock_real_clk[VDEC_HCODEC] <= 0)
- clk = 200;
- else
- clk = clock_real_clk[VDEC_HCODEC];
- }
-
- if ((clk > 500 && clk != 667)) {
- if (clock_real_clk[VDEC_HCODEC] == 648)
- return 648;
- clk = 667;
- }
-
- vdec_set_clk(VDEC_HCODEC, clk * MHz);
-
- clock_real_clk[VDEC_HCODEC] = clk;
-
- pr_debug("hcodec mux clock is %lu Hz\n",
- clk_get_rate(gclk.hcodec_mux_node->clk));
-
- return clk;
-}
-
-static void vdec_clock_on(void)
-{
- mutex_lock(&gclk.vdec_mux_node->mutex);
- if (!gclk.vdec_mux_node->ref_count)
- clk_prepare_enable(gclk.vdec_mux_node->clk);
-
- gclk.vdec_mux_node->ref_count++;
- mutex_unlock(&gclk.vdec_mux_node->mutex);
-
- pr_debug("the %-15s clock on, ref cnt: %d\n",
- gclk.vdec_mux_node->name,
- gclk.vdec_mux_node->ref_count);
-}
-
-static void vdec_clock_off(void)
-{
- mutex_lock(&gclk.vdec_mux_node->mutex);
- gclk.vdec_mux_node->ref_count--;
- if (!gclk.vdec_mux_node->ref_count)
- clk_disable_unprepare(gclk.vdec_mux_node->clk);
-
- clock_real_clk[VDEC_1] = 0;
- mutex_unlock(&gclk.vdec_mux_node->mutex);
-
- pr_debug("the %-15s clock off, ref cnt: %d\n",
- gclk.vdec_mux_node->name,
- gclk.vdec_mux_node->ref_count);
-}
-
-static void hcodec_clock_on(void)
-{
- mutex_lock(&gclk.hcodec_mux_node->mutex);
- if (!gclk.hcodec_mux_node->ref_count)
- clk_prepare_enable(gclk.hcodec_mux_node->clk);
-
- gclk.hcodec_mux_node->ref_count++;
- mutex_unlock(&gclk.hcodec_mux_node->mutex);
-
- pr_debug("the %-15s clock on, ref cnt: %d\n",
- gclk.hcodec_mux_node->name,
- gclk.hcodec_mux_node->ref_count);
-}
-
-static void hcodec_clock_off(void)
-{
- mutex_lock(&gclk.hcodec_mux_node->mutex);
- gclk.hcodec_mux_node->ref_count--;
- if (!gclk.hcodec_mux_node->ref_count)
- clk_disable_unprepare(gclk.hcodec_mux_node->clk);
-
- mutex_unlock(&gclk.hcodec_mux_node->mutex);
-
- pr_debug("the %-15s clock off, ref cnt: %d\n",
- gclk.hcodec_mux_node->name,
- gclk.hcodec_mux_node->ref_count);
-}
-
-static void hevc_clock_on(void)
-{
- mutex_lock(&gclk.hevc_mux_node->mutex);
- if (!gclk.hevc_mux_node->ref_count)
- clk_prepare_enable(gclk.hevc_mux_node->clk);
-
- gclk.hevc_mux_node->ref_count++;
- WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);
- mutex_unlock(&gclk.hevc_mux_node->mutex);
-
- pr_debug("the %-15s clock on, ref cnt: %d\n",
- gclk.hevc_mux_node->name,
- gclk.hevc_mux_node->ref_count);
-}
-
-static void hevc_clock_off(void)
-{
- mutex_lock(&gclk.hevc_mux_node->mutex);
- gclk.hevc_mux_node->ref_count--;
- if (!gclk.hevc_mux_node->ref_count)
- clk_disable_unprepare(gclk.hevc_mux_node->clk);
-
- clock_real_clk[VDEC_HEVC] = 0;
- mutex_unlock(&gclk.hevc_mux_node->mutex);
-
- pr_debug("the %-15s clock off, ref cnt: %d\n",
- gclk.hevc_mux_node->name,
- gclk.hevc_mux_node->ref_count);
-}
-
-static int vdec_clock_get(enum vdec_type_e core)
-{
- if (core >= VDEC_MAX)
- return 0;
-
- return clock_real_clk[core];
-}
-
-#define INCLUDE_FROM_ARCH_CLK_MGR
-
-/*#define VDEC_HAS_VDEC2*/
-#define VDEC_HAS_HEVC
-#define VDEC_HAS_VDEC_HCODEC
-#define VDEC_HAS_CLK_SETTINGS
-#define CLK_FOR_CPU {\
- MESON_CPU_MAJOR_ID_GXBB,\
- MESON_CPU_MAJOR_ID_GXTVBB,\
- MESON_CPU_MAJOR_ID_GXL,\
- MESON_CPU_MAJOR_ID_GXM,\
- MESON_CPU_MAJOR_ID_TXL,\
- MESON_CPU_MAJOR_ID_TXLX,\
- 0}
-#include "clk.h"
-ARCH_VDEC_CLK_INIT();
-ARCH_VDEC_CLK_EXIT();
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/common/media_clock/switch/amports_gate.c b/drivers/common/media_clock/switch/amports_gate.c
index 8bc18dd..c2119f2 100644
--- a/drivers/common/media_clock/switch/amports_gate.c
+++ b/drivers/common/media_clock/switch/amports_gate.c
@@ -52,6 +52,9 @@ struct gate_switch_node gates[] = {
{
.name = "clk_hevc_mux",
},
+ {
+ .name = "clk_hevcb_mux",
+ },
};
/*
@@ -64,13 +67,15 @@ struct gate_switch_node gates[] = {
* &clkc CLKID_DOS
* &clkc CLKID_VDEC_MUX
* &clkc CLKID_HCODEC_MUX
+ * &clkc CLKID_HEVCF_MUX
* &clkc CLKID_HEVC_MUX>;
* clock-names = "parser_top",
* "demux",
* "vdec",
* "clk_vdec_mux",
* "clk_hcodec_mux",
- * "clk_hevc_mux";
+ * "clk_hevc_mux",
+ * "clk_hevcb_mux";
*};
*/
diff --git a/drivers/frame_provider/decoder/Makefile b/drivers/frame_provider/decoder/Makefile
index 11d66b3..12121b4 100644
--- a/drivers/frame_provider/decoder/Makefile
+++ b/drivers/frame_provider/decoder/Makefile
@@ -9,3 +9,4 @@ obj-y += vp9/
obj-y += mjpeg/
obj-y += real/
obj-y += avs/
+obj-y += avs2/
diff --git a/drivers/frame_provider/decoder/avs/avsp_trans.c b/drivers/frame_provider/decoder/avs/avsp_trans.c
index 2895a7c..be45bdd 100644
--- a/drivers/frame_provider/decoder/avs/avsp_trans.c
+++ b/drivers/frame_provider/decoder/avs/avsp_trans.c
@@ -2868,8 +2868,7 @@ int header(void)
temp_slice_buf = &tmp_buf[0];
return SOP;
- }
- {
+ } else {
io_printf("Can't find start code");
return -EOS;
}
diff --git a/drivers/frame_provider/decoder/avs2/Makefile b/drivers/frame_provider/decoder/avs2/Makefile
new file mode 100644
index 0000000..5fe8566
--- a/dev/null
+++ b/drivers/frame_provider/decoder/avs2/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_AMLOGIC_MEDIA_VDEC_AVS2) += amvdec_avs2.o
+amvdec_avs2-objs += vavs2.o avs2_bufmgr.o
diff --git a/drivers/frame_provider/decoder/avs2/avs2_bufmgr.c b/drivers/frame_provider/decoder/avs2/avs2_bufmgr.c
new file mode 100644
index 0000000..5309669
--- a/dev/null
+++ b/drivers/frame_provider/decoder/avs2/avs2_bufmgr.c
@@ -0,0 +1,1980 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/semaphore.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/kfifo.h>
+#include <linux/kthread.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
+#include <linux/slab.h>
+#include <linux/amlogic/tee.h>
+#include "../../../stream_input/amports/amports_priv.h"
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include "../utils/decoder_mmu_box.h"
+#include "../utils/decoder_bmmu_box.h"
+#include "avs2_global.h"
+
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../utils/vdec.h"
+#include "../utils/amvdec.h"
+
+#undef pr_info
+#define pr_info printk
+
+#define assert(chk_cond) {\
+ if (!(chk_cond))\
+ pr_info("error line %d\n", __LINE__);\
+ while (!(chk_cond))\
+ ;\
+}
+
+int16_t get_param(uint16_t value, int8_t *print_info)
+{
+ if (is_avs2_print_param())
+ pr_info("%s = %x\n", print_info, value);
+ return (int16_t)value;
+}
+
+void readAlfCoeff(struct avs2_decoder *avs2_dec, struct ALFParam_s *Alfp)
+{
+ int32_t pos;
+ union param_u *rpm_param = &avs2_dec->param;
+
+ int32_t f = 0, symbol, pre_symbole;
+ const int32_t numCoeff = (int32_t)ALF_MAX_NUM_COEF;
+
+ switch (Alfp->componentID) {
+ case ALF_Cb:
+ case ALF_Cr: {
+ for (pos = 0; pos < numCoeff; pos++) {
+ if (Alfp->componentID == ALF_Cb)
+ Alfp->coeffmulti[0][pos] =
+ get_param(
+ rpm_param->alf.alf_cb_coeffmulti[pos],
+ "Chroma ALF coefficients");
+ else
+ Alfp->coeffmulti[0][pos] =
+ get_param(
+ rpm_param->alf.alf_cr_coeffmulti[pos],
+ "Chroma ALF coefficients");
+#if Check_Bitstream
+ if (pos <= 7)
+ assert(Alfp->coeffmulti[0][pos] >= -64
+ && Alfp->coeffmulti[0][pos] <= 63);
+ if (pos == 8)
+ assert(Alfp->coeffmulti[0][pos] >= -1088
+ && Alfp->coeffmulti[0][pos] <= 1071);
+#endif
+ }
+ }
+ break;
+ case ALF_Y: {
+ int32_t region_distance_idx = 0;
+ Alfp->filters_per_group =
+ get_param(rpm_param->alf.alf_filters_num_m_1,
+ "ALF_filter_number_minus_1");
+#if Check_Bitstream
+ assert(Alfp->filters_per_group >= 0
+ && Alfp->filters_per_group <= 15);
+#endif
+ Alfp->filters_per_group = Alfp->filters_per_group + 1;
+
+ memset(Alfp->filterPattern, 0, NO_VAR_BINS * sizeof(int32_t));
+ pre_symbole = 0;
+ symbol = 0;
+ for (f = 0; f < Alfp->filters_per_group; f++) {
+ if (f > 0) {
+ if (Alfp->filters_per_group != 16) {
+ symbol =
+ get_param(rpm_param->alf.region_distance
+ [region_distance_idx++],
+ "Region distance");
+ } else {
+ symbol = 1;
+ }
+ Alfp->filterPattern[symbol + pre_symbole] = 1;
+ pre_symbole = symbol + pre_symbole;
+ }
+
+ for (pos = 0; pos < numCoeff; pos++) {
+ Alfp->coeffmulti[f][pos] =
+ get_param(
+ rpm_param->alf.alf_y_coeffmulti[f][pos],
+ "Luma ALF coefficients");
+#if Check_Bitstream
+ if (pos <= 7)
+ assert(
+ Alfp->coeffmulti[f][pos]
+ >= -64 &&
+ Alfp->coeffmulti[f][pos]
+ <= 63);
+ if (pos == 8)
+ assert(
+ Alfp->coeffmulti[f][pos]
+ >= -1088 &&
+ Alfp->coeffmulti[f][pos]
+ <= 1071);
+#endif
+
+ }
+ }
+
+#if Check_Bitstream
+ assert(pre_symbole >= 0 && pre_symbole <= 15);
+
+#endif
+ }
+ break;
+ default: {
+ pr_info("Not a legal component ID\n");
+ assert(0);
+ return; /* exit(-1);*/
+ }
+ }
+}
+
+void Read_ALF_param(struct avs2_decoder *avs2_dec)
+{
+ struct inp_par *input = &avs2_dec->input;
+ struct ImageParameters_s *img = &avs2_dec->img;
+ union param_u *rpm_param = &avs2_dec->param;
+ int32_t compIdx;
+ if (input->alf_enable) {
+ img->pic_alf_on[0] =
+ get_param(
+ rpm_param->alf.picture_alf_enable_Y,
+ "alf_pic_flag_Y");
+ img->pic_alf_on[1] =
+ get_param(
+ rpm_param->alf.picture_alf_enable_Cb,
+ "alf_pic_flag_Cb");
+ img->pic_alf_on[2] =
+ get_param(
+ rpm_param->alf.picture_alf_enable_Cr,
+ "alf_pic_flag_Cr");
+
+ avs2_dec->m_alfPictureParam[ALF_Y].alf_flag
+ = img->pic_alf_on[ALF_Y];
+ avs2_dec->m_alfPictureParam[ALF_Cb].alf_flag
+ = img->pic_alf_on[ALF_Cb];
+ avs2_dec->m_alfPictureParam[ALF_Cr].alf_flag
+ = img->pic_alf_on[ALF_Cr];
+ if (img->pic_alf_on[0]
+ || img->pic_alf_on[1]
+ || img->pic_alf_on[2]) {
+ for (compIdx = 0;
+ compIdx < NUM_ALF_COMPONENT;
+ compIdx++) {
+ if (img->pic_alf_on[compIdx]) {
+ readAlfCoeff(
+ avs2_dec,
+ &avs2_dec->m_alfPictureParam[compIdx]);
+ }
+ }
+ }
+ }
+
+}
+
+void Get_SequenceHeader(struct avs2_decoder *avs2_dec)
+{
+ struct inp_par *input = &avs2_dec->input;
+ struct ImageParameters_s *img = &avs2_dec->img;
+ struct Video_Com_data_s *hc = &avs2_dec->hc;
+ struct Video_Dec_data_s *hd = &avs2_dec->hd;
+ union param_u *rpm_param = &avs2_dec->param;
+ /*int32_t i, j;*/
+
+ /*fpr_info(stdout, "Sequence Header\n");*/
+ /*memcpy(currStream->streamBuffer, buf, length);*/
+ /*currStream->code_len = currStream->bitstream_length = length;*/
+ /*currStream->read_len = currStream->frame_bitoffset = (startcodepos +
+ 1) * 8;*/
+
+ input->profile_id =
+ get_param(rpm_param->p.profile_id, "profile_id");
+ input->level_id =
+ get_param(rpm_param->p.level_id, "level_id");
+ hd->progressive_sequence =
+ get_param(
+ rpm_param->p.progressive_sequence,
+ "progressive_sequence");
+#if INTERLACE_CODING
+ hd->is_field_sequence =
+ get_param(
+ rpm_param->p.is_field_sequence,
+ "field_coded_sequence");
+#endif
+#if HALF_PIXEL_COMPENSATION || HALF_PIXEL_CHROMA
+ img->is_field_sequence = hd->is_field_sequence;
+#endif
+ hd->horizontal_size =
+ get_param(rpm_param->p.horizontal_size, "horizontal_size");
+ hd->vertical_size =
+ get_param(rpm_param->p.vertical_size, "vertical_size");
+ input->chroma_format =
+ get_param(rpm_param->p.chroma_format, "chroma_format");
+ input->output_bit_depth = 8;
+ input->sample_bit_depth = 8;
+ hd->sample_precision = 1;
+ if (input->profile_id == BASELINE10_PROFILE) { /* 10bit profile (0x52)*/
+ input->output_bit_depth =
+ get_param(rpm_param->p.sample_precision,
+ "sample_precision");
+ input->output_bit_depth =
+ 6 + (input->output_bit_depth) * 2;
+ input->sample_bit_depth =
+ get_param(rpm_param->p.encoding_precision,
+ "encoding_precision");
+ input->sample_bit_depth =
+ 6 + (input->sample_bit_depth) * 2;
+ } else { /* other profile*/
+ hd->sample_precision =
+ get_param(rpm_param->p.sample_precision,
+ "sample_precision");
+ }
+ hd->aspect_ratio_information =
+ get_param(rpm_param->p.aspect_ratio_information,
+ "aspect_ratio_information");
+ hd->frame_rate_code =
+ get_param(rpm_param->p.frame_rate_code, "frame_rate_code");
+
+ hd->bit_rate_lower =
+ get_param(rpm_param->p.bit_rate_lower, "bit_rate_lower");
+ /*hd->marker_bit = get_param(rpm_param->p.marker_bit,
+ * "marker bit");*/
+ /*CHECKMARKERBIT*/
+ hd->bit_rate_upper =
+ get_param(rpm_param->p.bit_rate_upper, "bit_rate_upper");
+ hd->low_delay =
+ get_param(rpm_param->p.low_delay, "low_delay");
+ /*hd->marker_bit =
+ get_param(rpm_param->p.marker_bit2,
+ "marker bit");*/
+ /*CHECKMARKERBIT*/
+#if M3480_TEMPORAL_SCALABLE
+ hd->temporal_id_exist_flag =
+ get_param(rpm_param->p.temporal_id_exist_flag,
+ "temporal_id exist flag"); /*get
+ Extention Flag*/
+#endif
+ /*u_v(18, "bbv buffer size");*/
+ input->g_uiMaxSizeInBit =
+ get_param(rpm_param->p.g_uiMaxSizeInBit,
+ "Largest Coding Block Size");
+
+
+ /*hd->background_picture_enable = 0x01 ^
+ (get_param(rpm_param->p.avs2_seq_flags,
+ "background_picture_disable")
+ >> BACKGROUND_PICTURE_DISABLE_BIT) & 0x1;*/
+ /*rain???*/
+ hd->background_picture_enable = 0x01 ^
+ ((get_param(rpm_param->p.avs2_seq_flags,
+ "background_picture_disable")
+ >> BACKGROUND_PICTURE_DISABLE_BIT) & 0x1);
+
+
+ hd->b_dmh_enabled = 1;
+
+ hd->b_mhpskip_enabled =
+ get_param(rpm_param->p.avs2_seq_flags >> B_MHPSKIP_ENABLED_BIT,
+ "mhpskip enabled") & 0x1;
+ hd->dhp_enabled =
+ get_param(rpm_param->p.avs2_seq_flags >> DHP_ENABLED_BIT,
+ "dhp enabled") & 0x1;
+ hd->wsm_enabled =
+ get_param(rpm_param->p.avs2_seq_flags >> WSM_ENABLED_BIT,
+ "wsm enabled") & 0x1;
+
+ img->inter_amp_enable =
+ get_param(rpm_param->p.avs2_seq_flags >> INTER_AMP_ENABLE_BIT,
+ "Asymmetric Motion Partitions") & 0x1;
+ input->useNSQT =
+ get_param(rpm_param->p.avs2_seq_flags >> USENSQT_BIT,
+ "useNSQT") & 0x1;
+ input->useSDIP =
+ get_param(rpm_param->p.avs2_seq_flags >> USESDIP_BIT,
+ "useNSIP") & 0x1;
+
+ hd->b_secT_enabled =
+ get_param(rpm_param->p.avs2_seq_flags >> B_SECT_ENABLED_BIT,
+ "secT enabled") & 0x1;
+
+ input->sao_enable =
+ get_param(rpm_param->p.avs2_seq_flags >> SAO_ENABLE_BIT,
+ "SAO Enable Flag") & 0x1;
+ input->alf_enable =
+ get_param(rpm_param->p.avs2_seq_flags >> ALF_ENABLE_BIT,
+ "ALF Enable Flag") & 0x1;
+ hd->b_pmvr_enabled =
+ get_param(rpm_param->p.avs2_seq_flags >> B_PMVR_ENABLED_BIT,
+ "pmvr enabled") & 0x1;
+
+
+ hd->gop_size = get_param(rpm_param->p.num_of_RPS,
+ "num_of_RPS");
+#if Check_Bitstream
+ /*assert(hd->gop_size<=32);*/
+#endif
+
+ if (hd->low_delay == 0) {
+ hd->picture_reorder_delay =
+ get_param(rpm_param->p.picture_reorder_delay,
+ "picture_reorder_delay");
+ }
+
+ input->crossSliceLoopFilter =
+ get_param(rpm_param->p.avs2_seq_flags
+ >> CROSSSLICELOOPFILTER_BIT,
+ "Cross Loop Filter Flag") & 0x1;
+
+#if BCBR
+ if ((input->profile_id == SCENE_PROFILE ||
+ input->profile_id == SCENE10_PROFILE) &&
+ hd->background_picture_enable) {
+ hd->bcbr_enable = u_v(1,
+ "block_composed_background_picture_enable");
+ u_v(1, "reserved bits");
+ } else {
+ hd->bcbr_enable = 0;
+ u_v(2, "reserved bits");
+ }
+#else
+ /*u_v(2, "reserved bits");*/
+#endif
+
+ img->width = hd->horizontal_size;
+ img->height = hd->vertical_size;
+ img->width_cr = (img->width >> 1);
+
+ if (input->chroma_format == 1) {
+ img->height_cr
+ = (img->height >> 1);
+ }
+
+ img->PicWidthInMbs = img->width / MIN_CU_SIZE;
+ img->PicHeightInMbs = img->height / MIN_CU_SIZE;
+ img->PicSizeInMbs = img->PicWidthInMbs * img->PicHeightInMbs;
+ img->buf_cycle = input->buf_cycle + 1;
+ img->max_mb_nr = (img->width * img->height)
+ / (MIN_CU_SIZE * MIN_CU_SIZE);
+
+#ifdef AML
+avs2_dec->lcu_size =
+ get_param(rpm_param->p.lcu_size, "lcu_size");
+avs2_dec->lcu_size = 1<<(avs2_dec->lcu_size);
+#endif
+hc->seq_header++;
+}
+
+
+void Get_I_Picture_Header(struct avs2_decoder *avs2_dec)
+{
+ struct ImageParameters_s *img = &avs2_dec->img;
+ struct Video_Dec_data_s *hd = &avs2_dec->hd;
+ union param_u *rpm_param = &avs2_dec->param;
+
+#if RD1501_FIX_BG /*//Longfei.Wang@mediatek.com*/
+ hd->background_picture_flag = 0;
+ hd->background_picture_output_flag = 0;
+ img->typeb = 0;
+#endif
+
+ hd->time_code_flag =
+ get_param(rpm_param->p.time_code_flag,
+ "time_code_flag");
+
+ if (hd->time_code_flag) {
+ hd->time_code =
+ get_param(rpm_param->p.time_code,
+ "time_code");
+ }
+ if (hd->background_picture_enable) {
+ hd->background_picture_flag =
+ get_param(rpm_param->p.background_picture_flag,
+ "background_picture_flag");
+
+ if (hd->background_picture_flag) {
+ img->typeb =
+ BACKGROUND_IMG;
+ } else {
+ img->typeb = 0;
+ }
+
+ if (img->typeb == BACKGROUND_IMG) {
+ hd->background_picture_output_flag =
+ get_param(
+ rpm_param->p.background_picture_output_flag,
+ "background_picture_output_flag");
+ }
+ }
+
+
+ {
+ img->coding_order =
+ get_param(rpm_param->p.coding_order,
+ "coding_order");
+
+
+
+#if M3480_TEMPORAL_SCALABLE
+ if (hd->temporal_id_exist_flag == 1) {
+ hd->cur_layer =
+ get_param(rpm_param->p.cur_layer,
+ "temporal_id");
+ }
+#endif
+#if RD1501_FIX_BG /*Longfei.Wang@mediatek.com*/
+ if (hd->low_delay == 0
+ && !(hd->background_picture_flag &&
+ !hd->background_picture_output_flag)) { /*cdp*/
+#else
+ if (hd->low_delay == 0 &&
+ !(hd->background_picture_enable &&
+ !hd->background_picture_output_flag)) { /*cdp*/
+#endif
+ hd->displaydelay =
+ get_param(rpm_param->p.displaydelay,
+ "picture_output_delay");
+ }
+
+ }
+ {
+ int32_t RPS_idx;/* = (img->coding_order-1) % gop_size;*/
+ int32_t predict;
+ int32_t j;
+ predict =
+ get_param(rpm_param->p.predict,
+ "use RCS in SPS");
+ /*if (predict) {*/
+ RPS_idx =
+ get_param(rpm_param->p.RPS_idx,
+ "predict for RCS");
+ /* hd->curr_RPS = hd->decod_RPS[RPS_idx];*/
+ /*} else {*/
+ /*gop size16*/
+ hd->curr_RPS.referd_by_others =
+ get_param(rpm_param->p.referd_by_others_cur,
+ "refered by others");
+ hd->curr_RPS.num_of_ref =
+ get_param(rpm_param->p.num_of_ref_cur,
+ "num of reference picture");
+ for (j = 0; j < hd->curr_RPS.num_of_ref; j++) {
+ hd->curr_RPS.ref_pic[j] =
+ get_param(rpm_param->p.ref_pic_cur[j],
+ "delta COI of ref pic");
+ }
+ hd->curr_RPS.num_to_remove =
+ get_param(rpm_param->p.num_to_remove_cur,
+ "num of removed picture");
+ for (j = 0; j < hd->curr_RPS.num_to_remove; j++) {
+ hd->curr_RPS.remove_pic[j] =
+ get_param(
+ rpm_param->p.remove_pic_cur[j],
+ "delta COI of removed pic");
+ }
+ /*u_v(1, "marker bit");*/
+
+ /*}*/
+ }
+ /*xyji 12.23*/
+ if (hd->low_delay) {
+ /*ue_v(
+ "bbv check times");*/
+ }
+
+ hd->progressive_frame =
+ get_param(rpm_param->p.progressive_frame,
+ "progressive_frame");
+
+ if (!hd->progressive_frame) {
+ img->picture_structure =
+ get_param(rpm_param->p.picture_structure,
+ "picture_structure");
+ } else {
+ img->picture_structure
+ = 1;
+ }
+
+ hd->top_field_first =
+ get_param(rpm_param->p.top_field_first,
+ "top_field_first");
+ hd->repeat_first_field =
+ get_param(rpm_param->p.repeat_first_field,
+ "repeat_first_field");
+#if INTERLACE_CODING
+ if (hd->is_field_sequence) {
+ hd->is_top_field =
+ get_param(rpm_param->p.is_top_field,
+ "is_top_field");
+#if HALF_PIXEL_COMPENSATION || HALF_PIXEL_CHROMA
+ img->is_top_field = hd->is_top_field;
+#endif
+ }
+#endif
+
+
+ img->qp = hd->picture_qp;
+
+ img->type = I_IMG;
+
+}
+
+/*
+ * Function:pb picture header
+ * Input:
+ * Output:
+ * Return:
+ * Attention:
+ */
+
+void Get_PB_Picture_Header(struct avs2_decoder *avs2_dec)
+{
+ struct ImageParameters_s *img = &avs2_dec->img;
+ struct Video_Dec_data_s *hd = &avs2_dec->hd;
+ union param_u *rpm_param = &avs2_dec->param;
+
+
+ /*u_v(32, "bbv delay");*/
+
+ hd->picture_coding_type =
+ get_param(rpm_param->p.picture_coding_type,
+ "picture_coding_type");
+
+ if (hd->background_picture_enable &&
+ (hd->picture_coding_type == 1 ||
+ hd->picture_coding_type == 3)) {
+ if (hd->picture_coding_type == 1) {
+ hd->background_pred_flag =
+ get_param(
+ rpm_param->p.background_pred_flag,
+ "background_pred_flag");
+ } else {
+ hd->background_pred_flag = 0;
+ }
+ if (hd->background_pred_flag == 0) {
+
+ hd->background_reference_enable =
+ get_param(
+ rpm_param->
+ p.background_reference_enable,
+ "background_reference_enable");
+
+ } else {
+#if RD170_FIX_BG
+ hd->background_reference_enable = 1;
+#else
+ hd->background_reference_enable = 0;
+#endif
+ }
+
+ } else {
+ hd->background_pred_flag = 0;
+ hd->background_reference_enable = 0;
+ }
+
+
+
+ if (hd->picture_coding_type == 1) {
+ img->type =
+ P_IMG;
+ } else if (hd->picture_coding_type == 3) {
+ img->type =
+ F_IMG;
+ } else {
+ img->type =
+ B_IMG;
+ }
+
+
+ if (hd->picture_coding_type == 1 &&
+ hd->background_pred_flag) {
+ img->typeb = BP_IMG;
+ } else {
+ img->typeb = 0;
+ }
+
+
+ {
+ img->coding_order =
+ get_param(
+ rpm_param->p.coding_order,
+ "coding_order");
+
+
+#if M3480_TEMPORAL_SCALABLE
+ if (hd->temporal_id_exist_flag == 1) {
+ hd->cur_layer =
+ get_param(rpm_param->p.cur_layer,
+ "temporal_id");
+ }
+#endif
+
+ if (hd->low_delay == 0) {
+ hd->displaydelay =
+ get_param(rpm_param->p.displaydelay,
+ "displaydelay");
+ }
+ }
+ {
+ int32_t RPS_idx;/* = (img->coding_order-1) % gop_size;*/
+ int32_t predict;
+ predict =
+ get_param(rpm_param->p.predict,
+ "use RPS in SPS");
+ if (predict) {
+ RPS_idx =
+ get_param(rpm_param->p.RPS_idx,
+ "predict for RPS");
+ hd->curr_RPS = hd->decod_RPS[RPS_idx];
+ } /*else*/
+ {
+ /*gop size16*/
+ int32_t j;
+ hd->curr_RPS.referd_by_others =
+ get_param(
+ rpm_param->p.referd_by_others_cur,
+ "refered by others");
+ hd->curr_RPS.num_of_ref =
+ get_param(
+ rpm_param->p.num_of_ref_cur,
+ "num of reference picture");
+ for (j = 0; j < hd->curr_RPS.num_of_ref; j++) {
+ hd->curr_RPS.ref_pic[j] =
+ get_param(
+ rpm_param->p.ref_pic_cur[j],
+ "delta COI of ref pic");
+ }
+ hd->curr_RPS.num_to_remove =
+ get_param(
+ rpm_param->p.num_to_remove_cur,
+ "num of removed picture");
+ for (j = 0;
+ j < hd->curr_RPS.num_to_remove; j++) {
+ hd->curr_RPS.remove_pic[j] =
+ get_param(
+ rpm_param->p.remove_pic_cur[j],
+ "delta COI of removed pic");
+ }
+ /*u_v(1, "marker bit");*/
+
+ }
+ }
+ /*xyji 12.23*/
+ if (hd->low_delay) {
+ /*ue_v(
+ "bbv check times");*/
+ }
+
+ hd->progressive_frame =
+ get_param(rpm_param->p.progressive_frame,
+ "progressive_frame");
+
+ if (!hd->progressive_frame) {
+ img->picture_structure =
+ get_param(rpm_param->p.picture_structure,
+ "picture_structure");
+ } else {
+ img->picture_structure = 1;
+ }
+
+ hd->top_field_first =
+ get_param(rpm_param->p.top_field_first,
+ "top_field_first");
+ hd->repeat_first_field =
+ get_param(rpm_param->p.repeat_first_field,
+ "repeat_first_field");
+#if INTERLACE_CODING
+ if (hd->is_field_sequence) {
+ hd->is_top_field =
+ get_param(rpm_param->p.is_top_field,
+ "is_top_field");
+#if HALF_PIXEL_COMPENSATION || HALF_PIXEL_CHROMA
+ img->is_top_field = hd->is_top_field;
+#endif
+ /*u_v(1, "reserved bit for interlace coding");*/
+ }
+#endif
+
+#if Check_Bitstream
+ /*assert(hd->picture_qp>=0&&hd->picture_qp<=(63 + 8 *
+ (input->sample_bit_depth - 8)));*/
+#endif
+
+ img->random_access_decodable_flag =
+ get_param(rpm_param->p.random_access_decodable_flag,
+ "random_access_decodable_flag");
+
+ img->qp = hd->picture_qp;
+}
+
+
+
+
+void calc_picture_distance(struct avs2_decoder *avs2_dec)
+{
+ struct ImageParameters_s *img = &avs2_dec->img;
+ struct Video_Com_data_s *hc = &avs2_dec->hc;
+ struct Video_Dec_data_s *hd = &avs2_dec->hd;
+ /*
+ union param_u *rpm_param = &avs2_dec->param;
+
+ for POC mode 0:
+ uint32_t MaxPicDistanceLsb = (1 << 8);
+ */
+ if (img->coding_order < img->PrevPicDistanceLsb)
+
+ {
+ int32_t i, j;
+
+ hc->total_frames++;
+ for (i = 0; i < avs2_dec->ref_maxbuffer; i++) {
+ if (
+ avs2_dec->fref[i]->imgtr_fwRefDistance
+ >= 0) {
+ avs2_dec->fref[i]->
+ imgtr_fwRefDistance -= 256;
+ avs2_dec->fref[i]->
+ imgcoi_ref -= 256;
+ }
+#if RD170_FIX_BG
+ for (j = 0; j < MAXREF; j++) {
+#else
+ for (j = 0; j < 4; j++) {
+#endif
+ avs2_dec->fref[i]->ref_poc[j] -= 256;
+ }
+ }
+ for (i = 0; i < avs2_dec->outprint.buffer_num; i++) {
+ avs2_dec->outprint.stdoutdata[i].framenum -= 256;
+ avs2_dec->outprint.stdoutdata[i].tr -= 256;
+ }
+
+ hd->last_output -= 256;
+ hd->curr_IDRtr -= 256;
+ hd->curr_IDRcoi -= 256;
+ hd->next_IDRtr -= 256;
+ hd->next_IDRcoi -= 256;
+ }
+ if (hd->low_delay == 0) {
+ img->tr = img->coding_order +
+ hd->displaydelay - hd->picture_reorder_delay;
+ } else {
+ img->tr =
+ img->coding_order;
+ }
+
+#if REMOVE_UNUSED
+ img->pic_distance = img->tr;
+#else
+ img->pic_distance = img->tr % 256;
+#endif
+ hc->picture_distance = img->pic_distance;
+
+}
+
+int32_t avs2_init_global_buffers(struct avs2_decoder *avs2_dec)
+{
+ struct inp_par *input = &avs2_dec->input;
+ struct ImageParameters_s *img = &avs2_dec->img;
+ struct Video_Com_data_s *hc = &avs2_dec->hc;
+
+ int32_t refnum;
+
+ int32_t memory_size = 0;
+ /*
+int32_t img_height = (hd->vertical_size + img->auto_crop_bottom);
+ */
+ img->buf_cycle = input->buf_cycle + 1;
+
+ img->buf_cycle *= 2;
+
+ hc->background_ref = hc->backgroundReferenceFrame;
+
+ for (refnum = 0; refnum < REF_MAXBUFFER; refnum++) {
+ avs2_dec->fref[refnum] = &avs2_dec->frm_pool[refnum];
+
+ /*//avs2_dec->fref[i] memory allocation*/
+ if (is_avs2_print_bufmgr_detail())
+ pr_info("[t] avs2_dec->fref[%d]@0x%p\n",
+ refnum, avs2_dec->fref[refnum]);
+ avs2_dec->fref[refnum]->imgcoi_ref = -257;
+ avs2_dec->fref[refnum]->is_output = -1;
+ avs2_dec->fref[refnum]->refered_by_others = -1;
+ avs2_dec->fref[refnum]->
+ imgtr_fwRefDistance = -256;
+ init_frame_t(avs2_dec->fref[refnum]);
+#ifdef AML
+ avs2_dec->fref[refnum]->index = refnum;
+#endif
+ }
+#ifdef AML
+ avs2_dec->f_bg = NULL;
+
+ avs2_dec->m_bg = &avs2_dec->frm_pool[REF_MAXBUFFER];
+ /*///avs2_dec->fref[i] memory allocation*/
+ if (is_avs2_print_bufmgr_detail())
+ pr_info("[t] avs2_dec->m_bg@0x%p\n",
+ avs2_dec->m_bg);
+ avs2_dec->m_bg->imgcoi_ref = -257;
+ avs2_dec->m_bg->is_output = -1;
+ avs2_dec->m_bg->refered_by_others = -1;
+ avs2_dec->m_bg->imgtr_fwRefDistance = -256;
+ init_frame_t(avs2_dec->m_bg);
+ avs2_dec->m_bg->index = refnum;
+#endif
+
+#if BCBR
+ /*init BCBR related*/
+ img->iNumCUsInFrame =
+ ((img->width + MAX_CU_SIZE - 1) / MAX_CU_SIZE)
+ * ((img->height + MAX_CU_SIZE - 1)
+ / MAX_CU_SIZE);
+ /*img->BLCUidx = (int32_t*) calloc(
+ img->iNumCUsInFrame, sizeof(int32_t));*/
+ /*memset( img->BLCUidx, 0, img->iNumCUsInFrame);*/
+#endif
+ return memory_size;
+}
+
+void init_frame_t(struct avs2_frame_s *currfref)
+{
+ memset(currfref, 0, sizeof(struct avs2_frame_s));
+ currfref->imgcoi_ref = -257;
+ currfref->is_output = -1;
+ currfref->refered_by_others = -1;
+ currfref->imgtr_fwRefDistance = -256;
+ memset(currfref->ref_poc, 0, sizeof(currfref->ref_poc));
+}
+
+void get_reference_list_info(struct avs2_decoder *avs2_dec, int8_t *str)
+{
+ struct ImageParameters_s *img = &avs2_dec->img;
+ struct Video_Com_data_s *hc = &avs2_dec->hc;
+
+ int8_t str_tmp[16];
+ int32_t i;
+ /* int32_t poc = hc->f_rec->imgtr_fwRefDistance;
+ fred.chiu@mediatek.com*/
+
+ if (img->num_of_references > 0) {
+ strcpy(str, "[");
+ for (i = 0; i < img->num_of_references; i++) {
+#if RD1510_FIX_BG
+ if (img->type == B_IMG) {
+ sprintf(str_tmp, "%4d ",
+ hc->f_rec->
+ ref_poc[
+ img->num_of_references - 1 - i]);
+ } else {
+ sprintf(str_tmp, "%4d ",
+ hc->f_rec->ref_poc[i]);
+ }
+#else
+ sprintf(str_tmp, "%4d ",
+ avs2_dec->fref[i]->imgtr_fwRefDistance);
+#endif
+
+ str_tmp[5] = '\0';
+ strcat(str, str_tmp);
+ }
+ strcat(str, "]");
+ } else {
+ str[0] = '\0';
+ }
+}
+
+void prepare_RefInfo(struct avs2_decoder *avs2_dec)
+{
+ struct ImageParameters_s *img = &avs2_dec->img;
+ struct Video_Com_data_s *hc = &avs2_dec->hc;
+ struct Video_Dec_data_s *hd = &avs2_dec->hd;
+
+ int32_t i, j;
+ int32_t ii;
+ struct avs2_frame_s *tmp_fref;
+
+ /*update IDR frame*/
+ if (img->tr > hd->next_IDRtr && hd->curr_IDRtr != hd->next_IDRtr) {
+ hd->curr_IDRtr = hd->next_IDRtr;
+ hd->curr_IDRcoi = hd->next_IDRcoi;
+ }
+ /* re-order the ref buffer according to RPS*/
+ img->num_of_references = hd->curr_RPS.num_of_ref;
+
+#if 1
+ /*rain*/
+ if (is_avs2_print_bufmgr_detail()) {
+ pr_info("%s: coding_order is %d, curr_IDRcoi is %d\n",
+ __func__, img->coding_order, hd->curr_IDRcoi);
+ for (ii = 0; ii < MAXREF; ii++) {
+ pr_info("ref_pic(%d)=%d\n",
+ ii, hd->curr_RPS.ref_pic[ii]);
+ }
+ for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) {
+ pr_info(
+ "fref[%d]: index %d imgcoi_ref %d imgtr_fwRefDistance %d\n",
+ ii, avs2_dec->fref[ii]->index,
+ avs2_dec->fref[ii]->imgcoi_ref,
+ avs2_dec->fref[ii]->imgtr_fwRefDistance);
+ }
+ }
+#endif
+
+ for (i = 0; i < hd->curr_RPS.num_of_ref; i++) {
+ /*int32_t accumulate = 0;*/
+ /* copy tmp_fref from avs2_dec->fref[i] */
+ tmp_fref = avs2_dec->fref[i];
+
+#if REMOVE_UNUSED
+ for (j = i; j < avs2_dec->ref_maxbuffer; j++) {
+ /*/////////////to be modified IDR*/
+ if (avs2_dec->fref[j]->imgcoi_ref ==
+ img->coding_order -
+ hd->curr_RPS.ref_pic[i]) {
+ break;
+ }
+ }
+#else
+
+ for (j = i; j < avs2_dec->ref_maxbuffer; j++) {
+ /*/////////////to be modified IDR*/
+ int32_t k , tmp_tr;
+ for (k = 0; k < avs2_dec->ref_maxbuffer; k++) {
+ if (((int32_t)img->coding_order -
+ (int32_t)hd->curr_RPS.ref_pic[i]) ==
+ avs2_dec->fref[k]->imgcoi_ref &&
+ avs2_dec->fref[k]->imgcoi_ref >= -256) {
+ break;
+ }
+ }
+ if (k == avs2_dec->ref_maxbuffer) {
+ tmp_tr =
+ -1-1;
+ } else {
+ tmp_tr =
+ avs2_dec->fref[k]->imgtr_fwRefDistance;
+ }
+ if (tmp_tr < hd->curr_IDRtr) {
+ hd->curr_RPS.ref_pic[i] =
+ img->coding_order - hd->curr_IDRcoi;
+
+ for (k = 0; k < i; k++) {
+ if (hd->curr_RPS.ref_pic[k] ==
+ hd->curr_RPS.ref_pic[i]) {
+ accumulate++;
+ break;
+ }
+ }
+ }
+ if (avs2_dec->fref[j]->imgcoi_ref ==
+ img->coding_order - hd->curr_RPS.ref_pic[i]) {
+ break;
+ }
+ }
+ if (j == avs2_dec->ref_maxbuffer || accumulate)
+ img->num_of_references--;
+#endif
+ if (j != avs2_dec->ref_maxbuffer) {
+ /* copy avs2_dec->fref[i] from avs2_dec->fref[j] */
+ avs2_dec->fref[i] = avs2_dec->fref[j];
+ /* copy avs2_dec->fref[j] from ferf[tmp] */
+ avs2_dec->fref[j] = tmp_fref;
+ if (is_avs2_print_bufmgr_detail()) {
+ pr_info("%s, switch %d %d: ", __func__, i, j);
+ for (ii = 0; ii < hd->curr_RPS.num_of_ref
+ || ii <= j; ii++)
+ pr_info("%d ",
+ avs2_dec->fref[ii]->index);
+ pr_info("\n");
+ }
+ }
+ }
+ if (img->type == B_IMG &&
+ (avs2_dec->fref[0]->imgtr_fwRefDistance <= img->tr
+ || avs2_dec->fref[1]->imgtr_fwRefDistance >= img->tr)) {
+
+ pr_info("wrong reference configuration for B frame");
+ pr_info(
+ "fref0 imgtr_fwRefDistance %d, fref1 imgtr_fwRefDistance %d, img->tr %d\n",
+ avs2_dec->fref[0]->imgtr_fwRefDistance,
+ avs2_dec->fref[1]->imgtr_fwRefDistance,
+ img->tr);
+ return; /* exit(-1);*/
+ /*******************************************/
+ }
+
+#if !FIX_PROFILE_LEVEL_DPB_RPS_1
+ /* delete the frame that will never be used*/
+ for (i = 0; i < hd->curr_RPS.num_to_remove; i++) {
+ for (j = 0; j < avs2_dec->ref_maxbuffer; j++) {
+ if (avs2_dec->fref[j]->imgcoi_ref >= -256
+ && avs2_dec->fref[j]->imgcoi_ref
+ == img->coding_order -
+ hd->curr_RPS.remove_pic[i]) {
+ break;
+ }
+ }
+ if (j < avs2_dec->ref_maxbuffer &&
+ j >= img->num_of_references) {
+ avs2_dec->fref[j]->imgcoi_ref = -257;
+#if M3480_TEMPORAL_SCALABLE
+ avs2_dec->fref[j]->temporal_id = -1;
+#endif
+ if (avs2_dec->fref[j]->is_output == -1) {
+ avs2_dec->fref[j]->
+ imgtr_fwRefDistance = -256;
+ }
+ }
+ }
+#endif
+
+ /* add inter-view reference picture*/
+
+ /* add current frame to ref buffer*/
+ for (i = 0; i < avs2_dec->ref_maxbuffer; i++) {
+ if ((avs2_dec->fref[i]->imgcoi_ref < -256
+ || abs(avs2_dec->fref[i]->
+ imgtr_fwRefDistance - img->tr) >= 128)
+ && avs2_dec->fref[i]->is_output == -1
+ && avs2_dec->fref[i]->bg_flag == 0
+#ifndef NO_DISPLAY
+ && avs2_dec->fref[i]->vf_ref == 0
+#endif
+ ) {
+ break;
+ }
+ }
+ if (i == avs2_dec->ref_maxbuffer)
+ i--;
+
+ hc->f_rec = avs2_dec->fref[i];
+ hc->currentFrame = hc->f_rec->ref;
+ hc->f_rec->imgtr_fwRefDistance = img->tr;
+ hc->f_rec->imgcoi_ref = img->coding_order;
+#if M3480_TEMPORAL_SCALABLE
+ hc->f_rec->temporal_id = hd->cur_layer;
+#endif
+ hc->f_rec->is_output = 1;
+ hc->f_rec->refered_by_others = hd->curr_RPS.referd_by_others;
+ if (is_avs2_print_bufmgr_detail())
+ pr_info(
+ "%s, set f_rec (cur_pic) <= fref[%d] img->tr %d coding_order %d\n",
+ __func__, i, img->tr, img->coding_order);
+
+ if (img->type != B_IMG) {
+ for (j = 0;
+ j < img->num_of_references; j++) {
+ hc->f_rec->ref_poc[j] =
+ avs2_dec->fref[j]->imgtr_fwRefDistance;
+ }
+ } else {
+ hc->f_rec->ref_poc[0] =
+ avs2_dec->fref[1]->imgtr_fwRefDistance;
+ hc->f_rec->ref_poc[1] =
+ avs2_dec->fref[0]->imgtr_fwRefDistance;
+ }
+
+#if M3480_TEMPORAL_SCALABLE
+
+ for (j = img->num_of_references;
+ j < 4; j++) {
+ /**/
+ hc->f_rec->ref_poc[j] = 0;
+ }
+
+ if (img->type == INTRA_IMG) {
+ int32_t l;
+ for (l = 0; l < 4; l++) {
+ hc->f_rec->ref_poc[l]
+ = img->tr;
+ }
+ }
+
+#endif
+
+/*////////////////////////////////////////////////////////////////////////*/
+ /* updata ref pointer*/
+
+ if (img->type != I_IMG) {
+
+ img->imgtr_next_P = img->type == B_IMG ?
+ avs2_dec->fref[0]->imgtr_fwRefDistance : img->tr;
+ if (img->type == B_IMG) {
+ hd->trtmp = avs2_dec->fref[0]->imgtr_fwRefDistance;
+ avs2_dec->fref[0]->imgtr_fwRefDistance =
+ avs2_dec->fref[1]->imgtr_fwRefDistance;
+ }
+ }
+#if 1
+ /*rain*/
+ if (is_avs2_print_bufmgr_detail()) {
+ for (ii = 0; ii < avs2_dec->ref_maxbuffer; ii++) {
+ pr_info(
+ "fref[%d]: index %d imgcoi_ref %d imgtr_fwRefDistance %d refered %d, is_out %d, bg %d, vf_ref %d ref_pos(%d,%d,%d,%d,%d,%d,%d)\n",
+ ii, avs2_dec->fref[ii]->index,
+ avs2_dec->fref[ii]->imgcoi_ref,
+ avs2_dec->fref[ii]->imgtr_fwRefDistance,
+ avs2_dec->fref[ii]->refered_by_others,
+ avs2_dec->fref[ii]->is_output,
+ avs2_dec->fref[ii]->bg_flag,
+ avs2_dec->fref[ii]->vf_ref,
+ avs2_dec->fref[ii]->ref_poc[0],
+ avs2_dec->fref[ii]->ref_poc[1],
+ avs2_dec->fref[ii]->ref_poc[2],
+ avs2_dec->fref[ii]->ref_poc[3],
+ avs2_dec->fref[ii]->ref_poc[4],
+ avs2_dec->fref[ii]->ref_poc[5],
+ avs2_dec->fref[ii]->ref_poc[6]
+ );
+ }
+ }
+#endif
+}
+
+int32_t init_frame(struct avs2_decoder *avs2_dec)
+{
+ struct ImageParameters_s *img = &avs2_dec->img;
+ struct Video_Com_data_s *hc = &avs2_dec->hc;
+ struct Video_Dec_data_s *hd = &avs2_dec->hd;
+
+
+#if RD1510_FIX_BG
+ if (img->type == I_IMG &&
+ img->typeb == BACKGROUND_IMG) { /*G/GB frame*/
+ img->num_of_references = 0;
+ } else if (img->type == P_IMG && img->typeb == BP_IMG) {
+ /* only one reference frame(G\GB) for S frame*/
+ img->num_of_references = 1;
+ }
+#endif
+
+ if (img->typeb == BACKGROUND_IMG &&
+ hd->background_picture_output_flag == 0) {
+ hc->currentFrame = hc->background_ref;
+#ifdef AML
+ hc->cur_pic = avs2_dec->m_bg;
+#endif
+ } else {
+ prepare_RefInfo(avs2_dec);
+#ifdef AML
+ hc->cur_pic = hc->f_rec;
+#endif
+ }
+
+
+#ifdef FIX_CHROMA_FIELD_MV_BK_DIST
+ if (img->typeb == BACKGROUND_IMG
+ && img->is_field_sequence) {
+ avs2_dec->bk_img_is_top_field
+ = img->is_top_field;
+ }
+#endif
+ return 0;
+}
+
+void delete_trbuffer(struct outdata_s *data, int32_t pos)
+{
+ int32_t i;
+ for (i = pos;
+ i < data->buffer_num - 1; i++) {
+ data->stdoutdata[i] =
+ data->stdoutdata[i + 1];
+ }
+ data->buffer_num--;
+}
+
+static int frame_postprocessing(struct avs2_decoder *avs2_dec)
+{
+ struct ImageParameters_s *img = &avs2_dec->img;
+ struct Video_Com_data_s *hc = &avs2_dec->hc;
+ struct Video_Dec_data_s *hd = &avs2_dec->hd;
+
+ int32_t pointer_tmp = avs2_dec->outprint.buffer_num;
+ int32_t i;
+ struct STDOUT_DATA_s *p_outdata;
+#if RD160_FIX_BG
+ int32_t j, tmp_min, output_cur_dec_pic, pos = -1;
+ int32_t search_times = avs2_dec->outprint.buffer_num;
+#endif
+ /*pic dist by Grandview Semi. @ [06-07-20 15:25]*/
+ img->PrevPicDistanceLsb = (img->coding_order % 256);
+
+ pointer_tmp = avs2_dec->outprint.buffer_num;
+ p_outdata = &avs2_dec->outprint.stdoutdata[pointer_tmp];
+
+ p_outdata->type = img->type;
+ p_outdata->typeb = img->typeb;
+ p_outdata->framenum = img->tr;
+ p_outdata->tr = img->tr;
+#if 0 /*def ORI*/
+ p_outdata->qp = img->qp;
+#else
+ p_outdata->qp = 0;
+#endif
+ /*p_outdata->snr_y = snr->snr_y;*/
+ /*p_outdata->snr_u = snr->snr_u;*/
+ /*p_outdata->snr_v = snr->snr_v;*/
+ p_outdata->tmp_time = hd->tmp_time;
+ p_outdata->picture_structure = img->picture_structure;
+ /*p_outdata->curr_frame_bits =
+ StatBitsPtr->curr_frame_bits;*/
+ /*p_outdata->emulate_bits = StatBitsPtr->emulate_bits;*/
+#if RD1501_FIX_BG
+ p_outdata->background_picture_output_flag
+ = hd->background_picture_output_flag;
+ /*Longfei.Wang@mediatek.com*/
+#endif
+
+#if RD160_FIX_BG
+ p_outdata->picture_reorder_delay = hd->picture_reorder_delay;
+#endif
+ avs2_dec->outprint.buffer_num++;
+
+#if RD170_FIX_BG
+ search_times = avs2_dec->outprint.buffer_num;
+#endif
+ /* record the reference list*/
+ strcpy(p_outdata->str_reference_list, hc->str_list_reference);
+
+#if !REF_OUTPUT
+ #error "!!!REF_OUTPUT should be 1"
+ for (i = 0; i < avs2_dec->outprint.buffer_num; i++) {
+ min_tr(avs2_dec->outprint, &pos);
+ if (avs2_dec->outprint.stdoutdata[pos].tr < img->tr
+ || avs2_dec->outprint.stdoutdata[pos].tr
+ == (hd->last_output + 1)) {
+ hd->last_output = avs2_dec->outprint.stdoutdata[pos].tr;
+ report_frame(avs2_dec, &avs2_dec->outprint, pos);
+#if 0 /*def ORI*/
+ write_frame(hd->p_out,
+ avs2_dec->outprint.stdoutdata[pos].tr);
+#endif
+ delete_trbuffer(&avs2_dec->outprint, pos);
+ i--;
+ } else {
+ break;
+ }
+ }
+#else
+#if RD160_FIX_BG /*Longfei.Wang@mediatek.com*/
+ tmp_min = 1 << 20;
+ i = 0, j = 0;
+ output_cur_dec_pic = 0;
+ pos = -1;
+ for (j = 0; j < search_times; j++) {
+ pos = -1;
+ tmp_min = (1 << 20);
+ /*search for min poi picture to display*/
+ for (i = 0; i < avs2_dec->outprint.buffer_num; i++) {
+ if ((avs2_dec->outprint.stdoutdata[i].tr < tmp_min) &&
+ ((avs2_dec->outprint.stdoutdata[i].tr
+ + avs2_dec->outprint.stdoutdata[i].
+ picture_reorder_delay)
+ <= (int32_t)img->coding_order)) {
+ pos = i;
+ tmp_min = avs2_dec->outprint.stdoutdata[i].tr;
+ }
+ }
+
+ if ((0 == hd->displaydelay) && (0 == output_cur_dec_pic)) {
+ if (img->tr <= tmp_min) {/*fred.chiu@mediatek.com*/
+ /*output current decode picture
+ right now*/
+ pos = avs2_dec->outprint.buffer_num - 1;
+ output_cur_dec_pic = 1;
+ }
+ }
+ if (pos != -1) {
+ hd->last_output = avs2_dec->outprint.stdoutdata[pos].tr;
+ report_frame(avs2_dec, &avs2_dec->outprint, pos);
+#if 1 /*def ORI*/
+ if (avs2_dec->outprint.stdoutdata[pos].typeb
+ == BACKGROUND_IMG &&
+ avs2_dec->outprint.stdoutdata[pos].
+ background_picture_output_flag == 0) {
+ /**/
+ /**/
+ } else {
+ write_frame(avs2_dec,
+ avs2_dec->outprint.stdoutdata[pos].tr);
+ }
+#endif
+ delete_trbuffer(&avs2_dec->outprint, pos);
+ }
+
+ }
+
+#else
+ #error "!!!RD160_FIX_BG should be defined"
+ if (img->coding_order +
+ (uint32_t)hc->total_frames * 256 >=
+ (uint32_t)hd->picture_reorder_delay) {
+ int32_t tmp_min, pos = -1;
+ tmp_min = 1 << 20;
+
+ for (i = 0; i <
+ avs2_dec->outprint.buffer_num; i++) {
+ if (avs2_dec->outprint.stdoutdata[i].tr
+ < tmp_min &&
+ avs2_dec->outprint.stdoutdata[i].tr
+ >= hd->last_output) {
+ /*GB has the same "tr" with "last_output"*/
+ pos = i;
+ tmp_min =
+ avs2_dec->outprint.stdoutdata[i].tr;
+ }
+ }
+
+ if (pos != -1) {
+ hd->last_output = avs2_dec->outprint.stdoutdata[pos].tr;
+ report_frame(avs2_dec, &avs2_dec->outprint, pos);
+#if RD1501_FIX_BG
+ if (avs2_dec->outprint.stdoutdata[pos].typeb
+ == BACKGROUND_IMG && avs2_dec->
+ outprint.stdoutdata[pos].
+ background_picture_output_flag == 0) {
+#else
+ if (avs2_dec->outprint.stdoutdata[pos].typeb
+ == BACKGROUND_IMG &&
+ hd->background_picture_output_flag
+ == 0) {
+#endif
+ write_GB_frame(
+ hd->p_out_background);
+ } else {
+ write_frame(avs2_dec,
+ avs2_dec->outprint.stdoutdata[pos].tr);
+ }
+ delete_trbuffer(&avs2_dec->outprint, pos);
+
+ }
+
+ }
+#endif
+#endif
+ return pos;
+
+ }
+
+void write_frame(struct avs2_decoder *avs2_dec, int32_t pos)
+{
+ int32_t j;
+ for (j = 0; j < avs2_dec->ref_maxbuffer; j++) {
+ if (avs2_dec->fref[j]->imgtr_fwRefDistance == pos) {
+ avs2_dec->fref[j]->is_output = -1;
+ avs2_dec->fref[j]->to_prepare_disp = 1;
+ if (avs2_dec->fref[j]->refered_by_others == 0
+ || avs2_dec->fref[j]->imgcoi_ref
+ == -257) {
+ avs2_dec->fref[j]->imgtr_fwRefDistance
+ = -256;
+ avs2_dec->fref[j]->imgcoi_ref = -257;
+#if M3480_TEMPORAL_SCALABLE
+ avs2_dec->fref[j]->temporal_id = -1;
+#endif
+ }
+ break;
+ }
+ }
+}
+
+/*rain???, outdata *data*/
+void report_frame(struct avs2_decoder *avs2_dec,
+ struct outdata_s *data, int32_t pos)
+{
+ struct ImageParameters_s *img = &avs2_dec->img;
+ struct Video_Com_data_s *hc = &avs2_dec->hc;
+ struct Video_Dec_data_s *hd = &avs2_dec->hd;
+
+ int8_t *Frmfld;
+ int8_t Frm[] = "FRM";
+ int8_t Fld[] = "FLD";
+ struct STDOUT_DATA_s *p_stdoutdata
+ = &data->stdoutdata[pos];
+ const int8_t *typ;
+
+#if 0
+ if (input->MD5Enable & 0x02) {
+ sprintf(MD5str, "%08X%08X%08X%08X\0",
+ p_stdoutdata->DecMD5Value[0],
+ p_stdoutdata->DecMD5Value[1],
+ p_stdoutdata->DecMD5Value[2],
+ p_stdoutdata->DecMD5Value[3]);
+ } else {
+ memset(MD5val, 0, 16);
+ memset(MD5str, 0, 33);
+ }
+#endif
+
+ if (p_stdoutdata->
+ picture_structure) {
+ Frmfld = Frm;
+ } else {
+ Frmfld = Fld;
+ }
+#if INTERLACE_CODING
+ if (img->is_field_sequence) { /*rcs??*/
+ Frmfld = Fld;
+ }
+#endif
+ if ((p_stdoutdata->tr + hc->total_frames * 256)
+ == hd->end_SeqTr) { /* I picture*/
+ /*if ( img->new_sequence_flag == 1 )*/
+ {
+ img->sequence_end_flag = 0;
+ /*fprintf(stdout, "Sequence
+ End\n\n");*/
+ }
+ }
+ if ((p_stdoutdata->tr + hc->total_frames * 256)
+ == hd->next_IDRtr) {
+#if !RD170_FIX_BG
+ if (hd->vec_flag) /**/
+#endif
+ {
+ hd->vec_flag = 0;
+ /*fprintf(stdout, "Video Edit
+ Code\n");*/
+ }
+ }
+
+ if (p_stdoutdata->typeb == BACKGROUND_IMG) {
+ typ = (hd->background_picture_output_flag != 0) ? "G" : "GB";
+ } else {
+#if REMOVE_UNUSED
+ typ = (p_stdoutdata->type == INTRA_IMG)
+ ? "I" : (p_stdoutdata->type == INTER_IMG) ?
+ ((p_stdoutdata->typeb == BP_IMG) ? "S" : "P")
+ : (p_stdoutdata->type == F_IMG ? "F" : "B");
+#else
+ typ = (p_stdoutdata->type == INTRA_IMG) ? "I" :
+ (p_stdoutdata->type == INTER_IMG) ?
+ ((p_stdoutdata->type == BP_IMG) ? "S" : "P")
+ : (p_stdoutdata->type == F_IMG ? "F" : "B");
+#endif
+ }
+
+#if 0
+ /*rain???*/
+ pr_info("%3d(%s) %3d %5d %7.4f %7.4f %7.4f %5d\t\t%s %8d %6d\t%s",
+ p_stdoutdata->framenum + hc->total_frames * 256,
+ typ, p_stdoutdata->tr + hc->total_frames * 256,
+ p_stdoutdata->qp, p_stdoutdata->snr_y,
+ p_stdoutdata->snr_u, p_stdoutdata->snr_v,
+ p_stdoutdata->tmp_time, Frmfld,
+ p_stdoutdata->curr_frame_bits,
+ p_stdoutdata->emulate_bits,
+ "");
+#endif
+ if (is_avs2_print_bufmgr_detail())
+ pr_info(" %s\n", p_stdoutdata->str_reference_list);
+
+ /*fflush(stdout);*/
+ hd->FrameNum++;
+}
+
+void avs2_prepare_header(struct avs2_decoder *avs2_dec, int32_t start_code)
+{
+ struct ImageParameters_s *img = &avs2_dec->img;
+
+ switch (start_code) {
+ case SEQUENCE_HEADER_CODE:
+ img->new_sequence_flag = 1;
+ if (is_avs2_print_bufmgr_detail())
+ pr_info("SEQUENCE\n");
+#ifdef TO_CHECK
+#if SEQ_CHANGE_CHECKER
+ if (seq_checker_buf == NULL) {
+ seq_checker_buf = malloc(length);
+ seq_checker_length = length;
+ memcpy(seq_checker_buf, Buf, length);
+ } else {
+ if ((seq_checker_length != length) ||
+ (memcmp(seq_checker_buf, Buf, length) != 0)) {
+ free(seq_checker_buf);
+ /*fprintf(stdout,
+ "Non-conformance
+ stream: sequence
+ header cannot change
+ !!\n");*/
+#if RD170_FIX_BG
+ seq_checker_buf = NULL;
+ seq_checker_length = 0;
+ seq_checker_buf = malloc(length);
+ seq_checker_length = length;
+ memcpy(seq_checker_buf, Buf, length);
+#endif
+ }
+
+
+ }
+#endif
+#if RD170_FIX_BG
+ if (input->alf_enable
+ && alfParAllcoated == 1) {
+ ReleaseAlfGlobalBuffer();
+ alfParAllcoated = 0;
+ }
+#endif
+#if FIX_FLUSH_DPB_BY_LF
+ if (hd->vec_flag) {
+ int32_t k;
+ flushDPB();
+ for (k = 0; k < avs2_dec->ref_maxbuffer; k++)
+ cleanRefMVBufRef(k);
+
+ hd->vec_flag = 0;
+ free_global_buffers();
+ img->number = 0;
+ img->PrevPicDistanceLsb = 0;
+ }
+#endif
+
+#if FIX_SEQ_END_FLUSH_DPB_BY_LF
+ if (img->new_sequence_flag
+ && img->sequence_end_flag) {
+ int32_t k;
+ flushDPB();
+ for (k = 0; k < avs2_dec->ref_maxbuffer; k++)
+ cleanRefMVBufRef(k);
+
+ free_global_buffers();
+ img->number = 0;
+ img->PrevPicDistanceLsb = 0;
+ }
+#endif
+#endif
+ img->seq_header_indicate = 1;
+ break;
+ case I_PICTURE_START_CODE:
+ if (is_avs2_print_bufmgr_detail())
+ pr_info("PIC-I\n");
+ Get_SequenceHeader(avs2_dec);
+ Get_I_Picture_Header(avs2_dec);
+ calc_picture_distance(avs2_dec);
+ Read_ALF_param(avs2_dec);
+ if (!img->seq_header_indicate) {
+ img->B_discard_flag = 1;
+ /*fprintf(stdout, " I
+ %3d\t\tDIDSCARD!!\n",
+ img->tr);*/
+ break;
+ }
+ break;
+ case PB_PICTURE_START_CODE:
+ if (is_avs2_print_bufmgr_detail())
+ pr_info("PIC-PB\n");
+ Get_SequenceHeader(avs2_dec);
+ Get_PB_Picture_Header(avs2_dec);
+ calc_picture_distance(avs2_dec);
+ Read_ALF_param(avs2_dec);
+ /* xiaozhen zheng, 20071009*/
+ if (!img->seq_header_indicate) {
+ img->B_discard_flag = 1;
+
+ if (img->type == P_IMG) {
+ /*fprintf(stdout, " P
+ %3d\t\tDIDSCARD!!\n",
+ img->tr);*/
+ }
+ if (img->type == F_IMG) {
+ /*fprintf(stdout, " F
+ %3d\t\tDIDSCARD!!\n",
+ img->tr);*/
+ } else {
+ /*fprintf(stdout, " B
+ %3d\t\tDIDSCARD!!\n",
+ img->tr);*/
+ }
+
+ break;
+ }
+
+ if (img->seq_header_indicate == 1
+ && img->type != B_IMG) {
+ img->B_discard_flag = 0;
+ }
+ if (img->type == B_IMG && img->B_discard_flag == 1
+ && !img->random_access_decodable_flag) {
+ /*fprintf(stdout, " B
+ %3d\t\tDIDSCARD!!\n",
+ img->tr);*/
+ break;
+ }
+
+ break;
+ case SEQUENCE_END_CODE:
+#ifdef TO_CHECK
+#if SEQ_CHANGE_CHECKER
+ if (seq_checker_buf != NULL) {
+ free(seq_checker_buf);
+ seq_checker_buf = NULL;
+ seq_checker_length = 0;
+ }
+#endif
+#endif
+img->new_sequence_flag = 1;
+img->sequence_end_flag = 1;
+break;
+#ifdef TO_CHECK
+ case VIDEO_EDIT_CODE:
+ video_edit_code_data(Buf, startcodepos, length);
+#if SEQ_CHANGE_CHECKER
+ if (seq_checker_buf != NULL) {
+ free(seq_checker_buf);
+ seq_checker_buf = NULL;
+ seq_checker_length = 0;
+ }
+#endif
+
+break;
+#endif
+ }
+}
+
+#ifdef AML
+static uint32_t log2i(uint32_t val)
+{
+ uint32_t ret = -1;
+ while (val != 0) {
+ val >>= 1;
+ ret++;
+ }
+ return ret;
+}
+#endif
+
+int32_t avs2_process_header(struct avs2_decoder *avs2_dec)
+{
+ struct inp_par *input = &avs2_dec->input;
+ struct ImageParameters_s *img = &avs2_dec->img;
+ struct Video_Dec_data_s *hd = &avs2_dec->hd;
+ int32_t lcu_x_num_div;
+ int32_t lcu_y_num_div;
+
+ int32_t N8_SizeScale;
+ /*pr_info("%s\n", __func__);*/
+ {
+ N8_SizeScale = 1;
+
+ if (hd->horizontal_size %
+ (MIN_CU_SIZE * N8_SizeScale) != 0) {
+ img->auto_crop_right =
+ (MIN_CU_SIZE * N8_SizeScale) -
+ (hd->horizontal_size %
+ (MIN_CU_SIZE * N8_SizeScale));
+ } else
+ img->auto_crop_right = 0;
+
+#if !INTERLACE_CODING
+ if (hd->progressive_sequence) /**/
+#endif
+ {
+ if (hd->vertical_size %
+ (MIN_CU_SIZE * N8_SizeScale) != 0) {
+ img->auto_crop_bottom =
+ (MIN_CU_SIZE * N8_SizeScale) -
+ (hd->vertical_size %
+ (MIN_CU_SIZE * N8_SizeScale));
+ } else
+ img->auto_crop_bottom = 0;
+ }
+
+ /* Reinit parameters (NOTE: need to do
+ before init_frame //*/
+ img->width =
+ (hd->horizontal_size + img->auto_crop_right);
+ img->height =
+ (hd->vertical_size + img->auto_crop_bottom);
+ img->width_cr = (img->width >> 1);
+
+ if (input->chroma_format == 1)
+ img->height_cr = (img->height >> 1);
+
+ img->PicWidthInMbs = img->width / MIN_CU_SIZE;
+ img->PicHeightInMbs = img->height / MIN_CU_SIZE;
+ img->PicSizeInMbs = img->PicWidthInMbs * img->PicHeightInMbs;
+ img->max_mb_nr = (img->width * img->height) /
+ (MIN_CU_SIZE * MIN_CU_SIZE);
+ }
+
+ if (img->new_sequence_flag && img->sequence_end_flag) {
+#if 0/*RD170_FIX_BG //*/
+ int32_t k;
+ flushDPB();
+ for (k = 0; k < avs2_dec->ref_maxbuffer; k++)
+ cleanRefMVBufRef(k);
+
+ free_global_buffers();
+ img->number = 0;
+#endif
+ hd->end_SeqTr = img->tr;
+ img->sequence_end_flag = 0;
+ }
+ if (img->new_sequence_flag) {
+ hd->next_IDRtr = img->tr;
+ hd->next_IDRcoi = img->coding_order;
+ img->new_sequence_flag = 0;
+ }
+#if 0/*RD170_FIX_BG*/
+ if (hd->vec_flag) {
+ int32_t k;
+ flushDPB();
+ for (k = 0; k < avs2_dec->ref_maxbuffer; k++)
+ cleanRefMVBufRef(k);
+
+ hd->vec_flag = 0;
+ free_global_buffers();
+ img->number = 0;
+ }
+#endif
+/* allocate memory for frame buffers*/
+#if 0
+/* called in vavs2.c*/
+ if (img->number == 0)
+ avs2_init_global_buffers(avs2_dec);
+#endif
+ img->current_mb_nr = 0;
+
+ init_frame(avs2_dec);
+
+ img->types = img->type; /* jlzheng 7.15*/
+
+ if (img->type != B_IMG) {
+ hd->pre_img_type = img->type;
+ hd->pre_img_types = img->types;
+ }
+
+#ifdef AML
+ avs2_dec->lcu_size_log2 = log2i(avs2_dec->lcu_size);
+ lcu_x_num_div = (img->width/avs2_dec->lcu_size);
+ lcu_y_num_div = (img->height/avs2_dec->lcu_size);
+ avs2_dec->lcu_x_num = ((img->width % avs2_dec->lcu_size) == 0) ?
+ lcu_x_num_div : lcu_x_num_div+1;
+ avs2_dec->lcu_y_num = ((img->height % avs2_dec->lcu_size) == 0) ?
+ lcu_y_num_div : lcu_y_num_div+1;
+ avs2_dec->lcu_total = avs2_dec->lcu_x_num*avs2_dec->lcu_y_num;
+#endif
+ return SOP;
+}
+
+int avs2_post_process(struct avs2_decoder *avs2_dec)
+{
+ struct ImageParameters_s *img = &avs2_dec->img;
+ struct Video_Com_data_s *hc = &avs2_dec->hc;
+ struct Video_Dec_data_s *hd = &avs2_dec->hd;
+ int32_t i;
+ int ret;
+ if (img->typeb == BACKGROUND_IMG && hd->background_picture_enable) {
+#ifdef AML
+ for (i = 0; i < avs2_dec->ref_maxbuffer; i++) {
+ if (avs2_dec->fref[i]->bg_flag != 0) {
+ avs2_dec->fref[i]->bg_flag = 0;
+ if (is_avs2_print_bufmgr_detail())
+ pr_info(
+ "clear old BACKGROUND_IMG for index %d\r\n",
+ avs2_dec->fref[i]->index);
+ }
+ }
+ if (is_avs2_print_bufmgr_detail())
+ pr_info(
+ "post_process: set BACKGROUND_IMG flag for %d\r\n",
+ hc->cur_pic->index);
+ avs2_dec->f_bg = hc->cur_pic;
+ hc->cur_pic->bg_flag = 1;
+#endif
+ }
+
+#if BCBR
+ if (hd->background_picture_enable
+ && hd->bcbr_enable && img->number > 0)
+ updateBgReference();
+#endif
+
+ if (img->typeb == BACKGROUND_IMG &&
+ hd->background_picture_output_flag == 0)
+ hd->background_number++;
+
+ if (img->type == B_IMG) {
+ avs2_dec->fref[0]->imgtr_fwRefDistance
+ = hd->trtmp;
+ }
+
+ /* record the reference list information*/
+ get_reference_list_info(avs2_dec, avs2_dec->hc.str_list_reference);
+
+ /*pr_info("%s\n", __func__);*/
+ ret = frame_postprocessing(avs2_dec);
+
+#if FIX_PROFILE_LEVEL_DPB_RPS_1
+ /* delete the frame that will never be used*/
+ {
+ int32_t i, j;
+ for (i = 0; i < hd->curr_RPS.num_to_remove; i++) {
+ for (j = 0; j < avs2_dec->ref_maxbuffer; j++) {
+
+ if (avs2_dec->fref[j]->imgcoi_ref >= -256
+ && avs2_dec->fref[j]->imgcoi_ref ==
+ img->coding_order -
+ hd->curr_RPS.remove_pic[i])
+ break;
+ }
+ if (j < avs2_dec->ref_maxbuffer) { /**/
+#if FIX_RPS_PICTURE_REMOVE
+/* Label new frames as "un-referenced" */
+ avs2_dec->fref[j]->refered_by_others = 0;
+
+ /* remove frames which have been outputted */
+ if (avs2_dec->fref[j]->is_output == -1) {
+ avs2_dec->fref[j]->
+ imgtr_fwRefDistance = -256;
+ avs2_dec->fref[j]->imgcoi_ref = -257;
+ avs2_dec->fref[j]->temporal_id = -1;
+
+ }
+#else
+ avs2_dec->fref[j]->imgcoi_ref = -257;
+#if M3480_TEMPORAL_SCALABLE
+ avs2_dec->fref[j]->temporal_id = -1;
+#endif
+ if (avs2_dec->fref[j]->is_output == -1) {
+ avs2_dec->fref[j]->imgtr_fwRefDistance
+ = -256;
+ }
+#endif
+ }
+ }
+ }
+#endif
+
+
+ /*! TO 19.11.2001 Known Problem: for init_frame
+ * we have to know the picture type of the
+ * actual frame*/
+ /*! in case the first slice of the P-Frame
+ * following the I-Frame was lost we decode this
+ * P-Frame but! do not write it because it
+ * was
+ * assumed to be an I-Frame in init_frame.So we
+ * force the decoder to*/
+ /*! guess the right picture type. This is a hack
+ * a should be removed by the time there is a
+ * clean*/
+ /*! solution where we do not have to know the
+ * picture type for the function init_frame.*/
+ /*! End TO 19.11.2001//Lou*/
+
+ {
+ if (img->type == I_IMG ||
+ img->type == P_IMG ||
+ img->type == F_IMG)
+ img->number++;
+ else {
+ hc->Bframe_ctr++; /* B
+ pictures*/
+ }
+ }
+ return ret;
+}
+
+void init_avs2_decoder(struct avs2_decoder *avs2_dec)
+{
+ int32_t i, j, k;
+
+ struct inp_par *input = &avs2_dec->input;
+ struct ImageParameters_s *img = &avs2_dec->img;
+ struct Video_Com_data_s *hc = &avs2_dec->hc;
+ struct Video_Dec_data_s *hd = &avs2_dec->hd;
+ if (is_avs2_print_bufmgr_detail())
+ pr_info("[t] struct avs2_dec @0x%p\n", avs2_dec);
+ memset(avs2_dec, 0, sizeof(struct avs2_decoder));
+
+ /*
+ * ALFParam init
+ */
+ for (i = 0; i < 3; i++) {
+ avs2_dec->m_alfPictureParam[i].alf_flag = 0; /*1*/
+ avs2_dec->m_alfPictureParam[i].num_coeff = 9; /*1*/
+ avs2_dec->m_alfPictureParam[i].filters_per_group = 3; /*1*/
+ avs2_dec->m_alfPictureParam[i].componentID = i; /*1*/
+ for (j = 0; j < 16; j++) {
+ avs2_dec->m_alfPictureParam[i].filterPattern[j] = 0;
+ /*16*/
+ }
+ for (j = 0; j < 16; j++) {
+ for (k = 0; k < 9; k++) {
+ avs2_dec->
+ m_alfPictureParam[i].coeffmulti[j][k] = 0;
+ /*16*9*/
+ }
+ }
+ }
+
+ img->seq_header_indicate = 0;
+ img->B_discard_flag = 0;
+
+ hd->eos = 0;
+
+ if (input->ref_pic_order) { /*ref order*/
+ hd->dec_ref_num = 0;
+ }
+
+ /*
+ memset(g_log2size, -1, MAX_CU_SIZE + 1);
+ c = 2;
+ for (k = 4; k <= MAX_CU_SIZE; k *= 2) {
+ g_log2size[k] = c;
+ c++;
+ }
+ */
+
+ avs2_dec->outprint.buffer_num = 0;
+
+ hd->last_output = -1;
+ hd->end_SeqTr = -1;
+ hd->curr_IDRtr = 0;
+ hd->curr_IDRcoi = 0;
+ hd->next_IDRtr = 0;
+ hd->next_IDRcoi = 0;
+ /* Allocate Slice data struct*/
+ img->number = 0;
+ img->type = I_IMG;
+
+ img->imgtr_next_P = 0;
+
+ img->imgcoi_next_ref = 0;
+
+
+ img->num_of_references = 0;
+ hc->seq_header = 0;
+
+ img->new_sequence_flag = 1;
+
+ hd->vec_flag = 0;
+
+ hd->FrameNum = 0;
+
+ /* B pictures*/
+ hc->Bframe_ctr = 0;
+ hc->total_frames = 0;
+
+ /* time for total decoding session*/
+ hc->tot_time = 0;
+
+}
+
diff --git a/drivers/frame_provider/decoder/avs2/avs2_global.h b/drivers/frame_provider/decoder/avs2/avs2_global.h
new file mode 100644
index 0000000..81182b8
--- a/dev/null
+++ b/drivers/frame_provider/decoder/avs2/avs2_global.h
@@ -0,0 +1,1648 @@
+/* The copyright in this software is being made available under the BSD
+ * License, included below. This software may be subject to other third party
+ * and contributor rights, including patent rights, and no such rights are
+ * granted under this license.
+ *
+ * Copyright (c) 2002-2016, Audio Video coding Standard Workgroup of China
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Audio Video coding Standard Workgroup of China
+ * nor the names of its contributors maybe
+ * used to endorse or promote products
+ * derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+
+/*
+ * File name: global.h
+ * Function: global definitions for for AVS decoder.
+ *
+ */
+
+#ifndef _GLOBAL_H_
+#define _GLOBAL_H_
+
+/* #include <stdio.h> //!< for FILE */
+/* #include <stdlib.h> */
+
+#define AML
+#undef NO_DISPLAY
+
+/* #include "define.h" */
+#define RD "19.2"
+#define VERSION "19.2"
+
+#define RESERVED_PROFILE_ID 0x24
+#define BASELINE_PICTURE_PROFILE 18
+#define BASELINE_PROFILE 32 /* 0x20 */
+#define BASELINE10_PROFILE 34 /* 0x22 */
+
+
+#define SCENE_PROFILE 48 /* 0x21 */
+#define SCENE10_PROFILE 50 /* 0x23 */
+
+#define TRACE 0 /* !< 0:Trace off 1:Trace on */
+
+
+/* Type definitions and file operation for Windows/Linux
+ * All file operations for windows are replaced with native (FILE *) operations
+ * Falei LUO (falei.luo@vipl.ict.ac.cn)
+ * */
+
+#define _FILE_OFFSET_BITS 64 /* for 64 bit fseeko */
+#define fseek fseeko
+
+#define int16 int16_t
+#define int64 int64_t
+
+/* ////////////////// bug fix ///////////////////////////// */
+#define ALFSliceFix 1
+#define WRITENBIT_FIX 1
+#define FIX_PROFILE_LEVEL_DPB_RPS_1 1
+#define FIX_PROFILE_LEVEL_DPB_RPS_2 1
+#define FIX_RPS_PICTURE_REMOVE 1 /* flluo@pku.edu.cn */
+#define Mv_Clip 1 /* yuquanhe@hisilicon.com */
+#define REMOVE_UNUSED 1 /* yuquanhe@hisilicon.com */
+#define SAO_Height_Fix 1 /* yuquanhe@hisilicon.com */
+#define B_BACKGROUND_Fix 1 /* yuquanhe@hisilicon.com */
+#define Check_Bitstream 1 /* yuquanhe@hisilicon.com */
+#define Wq_param_Clip 1 /* yuquanhe@hisilicon.com */
+ /* luofalei flluo@pku.edu.cn , wlq15@mails.tsinghua.edu.cn ,
+ Longfei.Wang@mediatek.com */
+#define RD1501_FIX_BG 1
+ /* yuquanhe@hisilicon.com ; he-yuan.lin@mstarsemi.com */
+#define Mv_Rang 1
+ /* Longfei.Wang@mediatek.com ;fred.chiu@mediatek.com
+ jie1222.chen@samsung.com */
+#define RD160_FIX_BG 1
+ /* Y_K_Tu@novatek.com.tw, he-yuan.lin@mstarsemi.com,
+ victor.huang@montage-tech.com M4041 */
+#define RD1601_FIX_BG 1
+#define SEQ_CHANGE_CHECKER 1 /* he-yuan.lin@mstarsemi.com */
+#define M4140_END_OF_SLICE_CHECKER 1 /* he-yuan.lin@mstarsemi.com */
+ /* wlq15@mails.tsinghua.edu.cn */
+#define Mv_check_bug 1
+#define SAO_ASSERTION_FIX 1 /* fred.chiu@mediatek.com */
+#define FIELD_HORI_MV_NO_SCALE_FIX 1 /* fred.chiu@mediatek.com */
+#define RD170_FIX_BG 1
+#define FIX_CHROMA_FIELD_MV_BK_DIST 1
+#define FIX_LUMA_FIELD_MV_BK_DIST 1
+#define FIX_CHROMA_FIELD_MV_CLIP 1
+#define FIX_FLUSH_DPB_BY_LF 0 /* fred.chiu@mediatek.com */
+#define FIX_SEQ_END_FLUSH_DPB_BY_LF 0 /* fred.chiu@mediatek.com */
+#define RD191_FIX_BUG 1 /* yuquanhe@hsilicon.com */
+#define SYM_MV_SCALE_FIX 1/* peisong.chen@broadcom.com */
+#define BUG_10BIT_REFINEQP 0 /* wangzhenyu */
+
+
+
+#if RD191_FIX_BUG
+#endif
+
+/************************
+ * AVS2 macros start
+ **************************/
+
+#define INTERLACE_CODING 1
+#if INTERLACE_CODING /* M3531: MV scaling compensation */
+/* Luma component */
+#define HALF_PIXEL_COMPENSATION 1 /* common functions definition */
+#define HALF_PIXEL_COMPENSATION_PMV 1 /* spacial MV prediction */
+#define HALF_PIXEL_COMPENSATION_DIRECT 1 /* B direct mode */
+ /* MV derivation method 1, weighted P_skip mode */
+#define HALF_PIXEL_COMPENSATION_M1 1
+ /* M1 related with mv-scaling function */
+#define HALF_PIXEL_COMPENSATION_M1_FUCTION 1
+#define HALF_PIXEL_COMPENSATION_MVD 1 /* MV scaling from FW->BW */
+/* Chroma components */
+ /* chroma MV is scaled with luma MV for 4:2:0 format */
+#define HALF_PIXEL_CHROMA 1
+ /* half pixel compensation for p skip/direct */
+#define HALF_PIXEL_PSKIP 1
+#define INTERLACE_CODING_FIX 1 /* HLS fix */
+#define OUTPUT_INTERLACE_MERGED_PIC 1
+
+#endif
+/*
+ *******************************
+AVS2 10bit/12bit profile
+ ********************************
+ */
+
+#define DBFIX_10bit 1
+
+#define BUG_10bit 1
+
+/*
+ ***************************************
+AVS2 HIGH LEVEL SYNTAX
+ ***************************************
+ */
+#define AVS2_HDR_HLS 1
+ /* AVS2 HDR technology //yuquanhe@hisilicon.com */
+#define AVS2_HDR_Tec 1
+#if AVS2_HDR_Tec
+#define HDR_CHROMA_DELTA_QP 1 /* M3905 */
+#define HDR_ADPTIVE_UV_DELTA 1
+#endif
+/*
+ *************************************
+AVS2 S2
+ *************************************
+ */
+#define AVS2_S2_FASTMODEDECISION 1
+#define RD1510_FIX_BG 1 /* 20160714, flluo@pku.edu.cn */
+
+
+/* ////////////////// prediction techniques ///////////////////////////// */
+#define LAM_2Level_TU 0.8
+
+
+#define DIRECTION 4
+#define DS_FORWARD 4
+#define DS_BACKWARD 2
+#define DS_SYM 3
+#define DS_BID 1
+
+#define MH_PSKIP_NUM 4
+#define NUM_OFFSET 0
+#define BID_P_FST 1
+#define BID_P_SND 2
+#define FW_P_FST 3
+#define FW_P_SND 4
+#define WPM_NUM 3
+ /* M3330 changes it to 2, the original value is 3 */
+#define MAX_MVP_CAND_NUM 2
+
+#define DMH_MODE_NUM 5 /* Number of DMH mode */
+#define TH_ME 0 /* Threshold of ME */
+
+#define MV_SCALE 1
+
+/* ///// reference picture management // */
+#define FIX_MAX_REF 1 /* Falei LUO, flluo@pku.edu.cn */
+#if FIX_MAX_REF
+ /* maximum number of reference frame for each frame */
+#define MAXREF 7
+#define MAXGOP 32
+#endif
+
+/* #define REF_MAXBUFFER 7 */
+/* more bufferes for displaying and background */
+/* #define REF_MAXBUFFER 15 */
+#if 1
+#define REF_MAXBUFFER 23
+#define REF_BUFFER 16
+#else
+#if RD170_FIX_BG
+#define REF_MAXBUFFER 16
+#else
+#define REF_MAXBUFFER 7
+#endif
+#endif
+
+#ifdef TO_PORTING
+ /* block-composed background reference, fangdong@mail.ustc.edu.cn */
+#define BCBR 1
+#else
+#define BCBR 0
+#endif
+/* one more buffer for background when background_picture_output_flag is 0*/
+#define AVS2_MAX_BUFFER_NUM (REF_MAXBUFFER + 1)
+
+/* /////////////////Adaptive Loop Filter////////////////////////// */
+#define NUM_ALF_COEFF_CTX 1
+#define NUM_ALF_LCU_CTX 4
+
+#define LAMBDA_SCALE_LUMA (1.0)
+#define LAMBDA_SCALE_CHROMA (1.0)
+
+
+
+/* ////////////////// entropy coding ///////////////////////////// */
+ /* M3090: Make sure rs1 will not overflow for 8-bit unsign char */
+#define NUN_VALUE_BOUND 254
+#define Encoder_BYPASS_Final 1 /* M3484 */
+#define Decoder_Bypass_Annex 0 /* M3484 */
+#define Decoder_Final_Annex 0 /* M3540 */
+
+
+/* ////////////////// coefficient coding ///// */
+ /* M3035 size of an coefficient group, 4x4 */
+#define CG_SIZE 16
+
+#define SWAP(x, y) {\
+ (y) = (y) ^ (x);\
+ (x) = (y) ^ (x);\
+ (y) = (x) ^ (y);\
+}
+
+/* ////////////////// encoder optimization /////// */
+#define TH 2
+
+#define M3624MDLOG /* reserved */
+
+#define TDRDO 1 /* M3528 */
+/* #define FIX_TDRDO_BG 1 // flluo@pku.edu.cn, 20160318// */
+#define RATECONTROL 1 /* M3580 M3627 M3689 */
+#define AQPO 1 /* M3623 */
+#define AQPOM3694 0
+#define AQPOM4063 1
+#define AQPOM3762 1
+#define BGQPO 1 /* M4061 */
+#if BGQPO
+#define LONGREFERENCE 32
+#endif
+
+/* #define REPORT */
+/* ////////////////// Quantization /////////////////////////////////////// */
+ /* Adaptive frequency weighting quantization */
+#define FREQUENCY_WEIGHTING_QUANTIZATION 1
+#if FREQUENCY_WEIGHTING_QUANTIZATION
+#define CHROMA_DELTA_QP 1
+#define AWQ_WEIGHTING 1
+#define AWQ_LARGE_BLOCK_ENABLE 1
+#define COUNT_BIT_OVERHEAD 0
+#define AWQ_LARGE_BLOCK_EXT_MAPPING 1
+#endif
+
+#define QuantClip 1
+#define QuantMatrixClipFix 1 /* 20160418, fllu@pku.edu.cn */
+
+#define WQ_MATRIX_FCD 1
+#if !WQ_MATRIX_FCD
+#define WQ_FLATBASE_INBIT 7
+#else
+#define WQ_FLATBASE_INBIT 6
+#endif
+
+
+#define REFINED_QP 1
+
+
+/* ////////////////// delta QP ///// */
+ /* M3122: the minimum dQP unit is Macro block */
+#define MB_DQP 1
+ /* M3122: 1 represents left prediction
+ and 0 represents previous prediction */
+#define LEFT_PREDICTION 1
+
+
+/* //////////////////////SAO///////// */
+#define NUM_BO_OFFSET 32
+#define MAX_NUM_SAO_CLASSES 32
+#define NUM_SAO_BO_CLASSES_LOG2 5
+#define NUM_SAO_BO_CLASSES_IN_BIT 5
+#define MAX_DOUBLE (1.7e + 308)
+#define NUM_SAO_EO_TYPES_LOG2 2
+#define NUM_SAO_BO_CLASSES (1<<NUM_SAO_BO_CLASSES_LOG2)
+#define SAO_RATE_THR 0.75
+#define SAO_RATE_CHROMA_THR 1
+#define SAO_SHIFT_PIX_NUM 4
+
+#define SAO_PARA_CROSS_SLICE 1
+#define SAO_MULSLICE_FTR_FIX 1
+
+/* /////////////////// Transform ///////////////////// */
+#define SEC_TR_SIZE 4
+ /* apply secT to greater than or equal to 8x8 block, */
+#define SEC_TR_MIN_BITSIZE 3
+
+#define BUGFIXED_COMBINED_ST_BD 1
+
+/* /////////////////// Scalable ///////////////////// */
+#define M3480_TEMPORAL_SCALABLE 1
+#define TEMPORAL_MAXLEVEL 8
+#define TEMPORAL_MAXLEVEL_BIT 3
+
+
+
+
+/*
+ *************************************
+ * AVS2 macros end
+ *
+ *************************************
+ */
+
+#define CHROMA 1
+#define LUMA_8x8 2
+#define NUM_BLOCK_TYPES 8
+
+#if (!defined clamp)
+ /* !< clamp a to the range of [b;c] */
+#define clamp(a, b, c) ((a) < (b) ? (b) : ((a) > (c) ? (c) : (a)))
+#endif
+
+ /* POC200301 moved from defines.h */
+#define LOG2_MAX_FRAME_NUM_MINUS4 4
+ /* !< bytes for one frame */
+#define MAX_CODED_FRAME_SIZE 15000000
+
+/* ----------------------- */
+/* FLAGS and DEFINES for new chroma intra prediction, Dzung Hoang */
+/* Threshold values to zero out quantized transform coefficients. */
+/* Recommend that _CHROMA_COEFF_COST_ be low to improve chroma quality */
+#define _LUMA_COEFF_COST_ 4 /* !< threshold for luma coeffs */
+ /* !< Number of pixels padded around the reference frame (>=4) */
+#define IMG_PAD_SIZE 64
+
+#define OUTSTRING_SIZE 255
+
+ /* !< abs macro, faster than procedure */
+#define absm(A) ((A) < (0) ? (-(A)) : (A))
+ /* !< used for start value for some variables */
+#define MAX_VALUE 999999
+
+#define Clip1(a) ((a) > 255 ? 255:((a) < 0 ? 0 : (a)))
+#define Clip3(min, max, val) (((val) < (min)) ?\
+ (min) : (((val) > (max)) ? (max) : (val)))
+
+/* --------------------------------------------- */
+
+/* block size of block transformed by AVS */
+#define PSKIPDIRECT 0
+#define P2NX2N 1
+#define P2NXN 2
+#define PNX2N 3
+#define PHOR_UP 4
+#define PHOR_DOWN 5
+#define PVER_LEFT 6
+#define PVER_RIGHT 7
+#define PNXN 8
+#define I8MB 9
+#define I16MB 10
+#define IBLOCK 11
+#define InNxNMB 12
+#define INxnNMB 13
+#define MAXMODE 14 /* add yuqh 20130824 */
+#define LAMBDA_ACCURACY_BITS 16
+#define LAMBDA_FACTOR(lambda) ((int)((double)(1 << LAMBDA_ACCURACY_BITS)\
+ * lambda + 0.5))
+#define WEIGHTED_COST(factor, bits) (((factor) * (bits))\
+ >> LAMBDA_ACCURACY_BITS)
+#define MV_COST(f, s, cx, cy, px, py) (WEIGHTED_COST(f, mvbits[((cx) << (s))\
+ - px] + mvbits[((cy) << (s)) - py]))
+#define REF_COST(f, ref) (WEIGHTED_COST(f, refbits[(ref)]))
+
+#define BWD_IDX(ref) (((ref) < 2) ? 1 - (ref) : (ref))
+#define REF_COST_FWD(f, ref) (WEIGHTED_COST(f,\
+ ((img->num_ref_pic_active_fwd_minus1 == 0) ?\
+ 0 : refbits[(ref)])))
+#define REF_COST_BWD(f, ef) (WEIGHTED_COST(f,\
+ ((img->num_ref_pic_active_bwd_minus1 == 0) ?\
+ 0 : BWD_IDX(refbits[ref]))))
+
+#define IS_INTRA(MB) ((MB)->cuType == I8MB ||\
+ (MB)->cuType == I16MB ||\
+ (MB)->cuType == InNxNMB || (MB)->cuType == INxnNMB)
+#define IS_INTER(MB) ((MB)->cuType != I8MB &&\
+ (MB)->cuType != I16MB && (MB)->cuType != InNxNMB\
+ && (MB)->cuType != INxnNMB)
+#define IS_INTERMV(MB) ((MB)->cuType != I8MB &&\
+ (MB)->cuType != I16MB && (MB)->cuType != InNxNMB &&\
+ (MB)->cuType != INxnNMB && (MB)->cuType != 0)
+
+
+#define IS_DIRECT(MB) ((MB)->cuType == PSKIPDIRECT && (img->type == B_IMG))
+#define IS_P_SKIP(MB) ((MB)->cuType == PSKIPDIRECT &&\
+ (((img->type == F_IMG)) || ((img->type == P_IMG))))
+#define IS_P8x8(MB) ((MB)->cuType == PNXN)
+
+/* Quantization parameter range */
+#define MIN_QP 0
+#define MAX_QP 63
+#define SHIFT_QP 11
+
+/* Picture types */
+#define INTRA_IMG 0 /* !< I frame */
+#define INTER_IMG 1 /* !< P frame */
+#define B_IMG 2 /* !< B frame */
+#define I_IMG 0 /* !< I frame */
+#define P_IMG 1 /* !< P frame */
+#define F_IMG 4 /* !< F frame */
+
+#define BACKGROUND_IMG 3
+
+#define BP_IMG 5
+
+
+/* Direct Mode types */
+#define MIN_CU_SIZE 8
+#define MIN_BLOCK_SIZE 4
+#define MIN_CU_SIZE_IN_BIT 3
+#define MIN_BLOCK_SIZE_IN_BIT 2
+#define BLOCK_MULTIPLE (MIN_CU_SIZE/(MIN_BLOCK_SIZE))
+#define MAX_CU_SIZE 64
+#define MAX_CU_SIZE_IN_BIT 6
+#define B4X4_IN_BIT 2
+#define B8X8_IN_BIT 3
+#define B16X16_IN_BIT 4
+#define B32X32_IN_BIT 5
+#define B64X64_IN_BIT 6
+ /* !< # luma intra prediction modes */
+#define NUM_INTRA_PMODE 33
+ /* number of luma modes for full RD search */
+#define NUM_MODE_FULL_RD 9
+ /* !< #chroma intra prediction modes */
+#define NUM_INTRA_PMODE_CHROMA 5
+
+/* luma intra prediction modes */
+
+#define DC_PRED 0
+#define PLANE_PRED 1
+#define BI_PRED 2
+#define VERT_PRED 12
+#define HOR_PRED 24
+
+
+/* chroma intra prediction modes */
+#define DM_PRED_C 0
+#define DC_PRED_C 1
+#define HOR_PRED_C 2
+#define VERT_PRED_C 3
+#define BI_PRED_C 4
+
+#define EOS 1 /* !< End Of Sequence */
+ /* !< Start Of Picture */
+#define SOP 2
+
+#define DECODING_OK 0
+#define SEARCH_SYNC 1
+#define DECODE_MB 1
+
+#ifndef max
+ /* !< Macro returning max value */
+#define max(a, b) ((a) > (b) ? (a) : (b))
+ /* !< Macro returning min value */
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+
+#define XY_MIN_PMV 1
+#if XY_MIN_PMV
+#define MVPRED_xy_MIN 0
+#else
+#define MVPRED_MEDIAN 0
+#endif
+#define MVPRED_L 1
+#define MVPRED_U 2
+#define MVPRED_UR 3
+
+#define DUAL 4
+#define FORWARD 0
+#define BACKWARD 1
+#define SYM 2
+#define BID 3
+#define INTRA -1
+
+#define BUF_CYCLE 5
+
+#define ROI_M3264 1 /* ROI Information Encoding */
+
+#define PicExtensionData 1
+
+
+#define REF_OUTPUT 1 /* M3337 */
+
+
+/* MV scaling 14 bit */
+#define MULTI 16384
+#define HALF_MULTI 8192
+#define OFFSET 14
+/* end of MV scaling */
+ /* store the middle pixel's mv in a motion information unit */
+#define MV_DECIMATION_FACTOR 4
+
+/* BUGFIX_AVAILABILITY_INTRA */
+#define NEIGHBOR_INTRA_LEFT 0
+#define NEIGHBOR_INTRA_UP 1
+#define NEIGHBOR_INTRA_UP_RIGHT 2
+#define NEIGHBOR_INTRA_UP_LEFT 3
+#define NEIGHBOR_INTRA_LEFT_DOWN 4
+/* end of BUGFIX_AVAILABILITY_INTRA */
+
+/* end #include "define.h" */
+
+/*#include "commonStructures.h"*/
+
+/*typedef uint16_t byte;*/ /* !< byte type definition */
+#define byte uint16_t
+#define pel_t byte
+
+enum BitCountType_e {
+ BITS_HEADER,
+ BITS_TOTAL_MB,
+ BITS_MB_MODE,
+ BITS_INTER_MB,
+ BITS_CBP_MB,
+ BITS_CBP01_MB,
+ BITS_COEFF_Y_MB,
+ BITS_COEFF_UV_MB,
+ BITS_DELTA_QUANT_MB,
+ BITS_SAO_MB,
+ MAX_BITCOUNTER_MB
+};
+
+
+enum SAOEOClasses {
+/* EO Groups, the assignments depended on
+how you implement the edgeType calculation */
+ SAO_CLASS_EO_FULL_VALLEY = 0,
+ SAO_CLASS_EO_HALF_VALLEY = 1,
+ SAO_CLASS_EO_PLAIN = 2,
+ SAO_CLASS_EO_HALF_PEAK = 3,
+ SAO_CLASS_EO_FULL_PEAK = 4,
+ SAO_CLASS_BO = 5,
+ NUM_SAO_EO_CLASSES = SAO_CLASS_BO,
+ NUM_SAO_OFFSET
+};
+
+struct SAOstatdata {
+ int32_t diff[MAX_NUM_SAO_CLASSES];
+ int32_t count[MAX_NUM_SAO_CLASSES];
+};
+
+struct CopyRight_s {
+ int32_t extension_id;
+ int32_t copyright_flag;
+ int32_t copyright_id;
+ int32_t original_or_copy;
+ int32_t reserved;
+ int32_t copyright_number;
+};
+
+struct CameraParamters_s {
+ int32_t reserved;
+ int32_t camera_id;
+ int32_t height_of_image_device;
+ int32_t focal_length;
+ int32_t f_number;
+ int32_t vertical_angle_of_view;
+ int32_t camera_position_x;
+ int32_t camera_position_y;
+ int32_t camera_position_z;
+ int32_t camera_direction_x;
+ int32_t camera_direction_y;
+ int32_t camera_direction_z;
+ int32_t image_plane_vertical_x;
+ int32_t image_plane_vertical_y;
+ int32_t image_plane_vertical_z;
+};
+
+/* ! SNRParameters */
+struct SNRParameters_s {
+ double snr_y; /* !< current Y SNR */
+ double snr_u; /* !< current U SNR */
+ double snr_v; /* !< current V SNR */
+ double snr_y1; /* !< SNR Y(dB) first frame */
+ double snr_u1; /* !< SNR U(dB) first frame */
+ double snr_v1; /* !< SNR V(dB) first frame */
+ double snr_ya; /* !< Average SNR Y(dB) remaining frames */
+ double snr_ua; /* !< Average SNR U(dB) remaining frames */
+ double snr_va; /* !< Average SNR V(dB) remaining frames */
+#if INTERLACE_CODING
+ double i_snr_ya; /* !< current Y SNR */
+ double i_snr_ua; /* !< current U SNR */
+ double i_snr_va; /* !< current V SNR */
+#endif
+};
+
+/* signal to noise ratio parameters */
+
+/* ! codingUnit */
+struct codingUnit {
+ uint32_t ui_MbBitSize;
+ int32_t uiBitSize; /* size of MB */
+ /* !< number of current syntax element */
+ int32_t currSEnr;
+ int32_t slice_nr;
+ int32_t delta_quant; /* !< for rate control */
+ int32_t delta_qp;
+ int32_t qp;
+ int32_t bitcounter[MAX_BITCOUNTER_MB];
+ struct codingUnit
+ *mb_available[3][3]; /*!< pointer to neighboring MBs
+ in a 3x3 window of current MB, which is located at [1][1] \n
+ NULL pointer identifies neighboring MBs which are unavailable */
+ /* some storage of codingUnit syntax elements for global access */
+ int32_t cuType;
+ int32_t weighted_skipmode;
+
+ int32_t md_directskip_mode;
+
+ int32_t trans_size;
+ int
+ /* !< indices correspond to [forw,backw][block_y][block_x][x,y, dmh] */
+ mvd[2][BLOCK_MULTIPLE][BLOCK_MULTIPLE][3];
+
+ int32_t intra_pred_modes[BLOCK_MULTIPLE * BLOCK_MULTIPLE];
+ int32_t real_intra_pred_modes[BLOCK_MULTIPLE * BLOCK_MULTIPLE];
+ int32_t l_ipred_mode;
+ int32_t cbp, cbp_blk;
+ uint32_t cbp_bits;
+
+ int32_t b8mode[4];
+ int32_t b8pdir[4];
+ /* !< chroma intra prediction mode */
+ int32_t c_ipred_mode;
+
+ /* !< pointer to neighboring MB (AEC) */
+ struct codingUnit *mb_available_up;
+ /* !< pointer to neighboring MB (AEC) */
+ struct codingUnit *mb_available_left;
+ int32_t mbAddrA, mbAddrB, mbAddrC, mbAddrD;
+ /* !<added by mz, 2008.04 */
+ int32_t slice_set_index;
+ /* added by mz, 2008.04 */
+ int32_t slice_header_flag;
+ int32_t sliceqp; /* added by mz, 2008.04 */
+#if MB_DQP
+ int32_t previouse_qp;
+ int32_t left_cu_qp;
+#endif
+ int32_t block_available_up;
+ int32_t block_available_left;
+
+};
+
+
+/* image parameters */
+struct syntaxelement;
+struct slice;
+struct alfdatapart;
+struct SAOBlkParam_s {
+ int32_t modeIdc; /* NEW, MERGE, OFF */
+ /* NEW: EO_0, EO_90, EO_135, EO_45, BO. MERGE: left, above */
+ int32_t typeIdc;
+ int32_t startBand; /* BO: starting band index */
+ int32_t startBand2;
+ int32_t deltaband;
+ int32_t offset[MAX_NUM_SAO_CLASSES];
+};
+struct ALFParam_s {
+ int32_t alf_flag;
+ int32_t num_coeff;
+ int32_t filters_per_group;
+ int32_t componentID;
+ int32_t filterPattern[16]; /* *filterPattern; */
+ int32_t coeffmulti[16][9]; /* **coeffmulti; */
+};
+
+enum ALFComponentID {
+ ALF_Y = 0,
+ ALF_Cb,
+ ALF_Cr,
+ NUM_ALF_COMPONENT
+};
+struct ALF_APS_s {
+ int32_t usedflag;
+ int32_t cur_number;
+ int32_t max_number;
+ struct ALFParam_s alf_par[NUM_ALF_COMPONENT];
+};
+
+
+/* ------------------------------------------------------
+ * frame data
+ */
+struct avs2_frame_s {
+ int32_t imgcoi_ref;
+ byte * *referenceFrame[3];
+ int32_t **refbuf;
+ int32_t ***mvbuf;
+#if 0
+ double saorate[NUM_SAO_COMPONENTS];
+#endif
+ byte ***ref;
+
+ int32_t imgtr_fwRefDistance;
+ int32_t refered_by_others;
+ int32_t is_output;
+ int32_t to_prepare_disp;
+#if M3480_TEMPORAL_SCALABLE
+ /* temporal level setted in configure file */
+ int32_t temporal_id;
+#endif
+ byte **oneForthRefY;
+#if FIX_MAX_REF
+ int32_t ref_poc[MAXREF];
+#else
+ int32_t ref_poc[4];
+#endif
+#ifdef AML
+ int32_t index;
+ int32_t mmu_alloc_flag;
+ int32_t lcu_size_log2;
+ /*uint32_t header_adr;*/
+ uint32_t mc_y_adr;
+ uint32_t mc_u_v_adr;
+ uint32_t mc_canvas_y;
+ uint32_t mc_canvas_u_v;
+ uint32_t mpred_mv_wr_start_addr;
+ uint8_t bg_flag;
+ /**/
+ unsigned long header_adr;
+ int buf_size;
+ int lcu_total;
+ int comp_body_size;
+ uint32_t dw_y_adr;
+ uint32_t dw_u_v_adr;
+ int y_canvas_index;
+ int uv_canvas_index;
+ struct canvas_config_s canvas_config[2];
+ int double_write_mode;
+ int bit_depth;
+ unsigned long cma_alloc_addr;
+ int BUF_index;
+ int pic_w;
+ int pic_h;
+ int stream_offset;
+ u32 pts;
+ u64 pts64;
+ /**/
+ int vf_ref;
+ int decode_idx;
+ int slice_type;
+#endif
+#ifndef MV_USE_FIXED_BUF
+ int mv_buf_index;
+#endif
+};
+
+
+struct ImageParameters_s {
+ struct codingUnit *mb_data;
+ int32_t number; /* <! frame number */
+ int32_t numIPFrames;
+
+ int32_t type;
+ int32_t typeb;
+ int32_t typeb_before;
+
+ int32_t qp; /* <! quant for the current frame */
+ int32_t current_mb_nr; /* bitstream order */
+ int32_t current_slice_nr;
+ int32_t tr; /* <! temporal reference, 8 bit, */
+
+ int32_t width; /* !< Number of pels */
+ int32_t width_cr; /* !< Number of pels chroma */
+ int32_t height; /* !< Number of lines */
+ int32_t height_cr; /* !< Number of lines chroma */
+ int32_t PicWidthInMbs;
+ int32_t PicSizeInMbs;
+ int32_t block8_x, block8_y;
+ int32_t subblock_x;
+ int32_t subblock_y;
+
+ int32_t num_of_references;
+ /* <! Bug Fix: correct picture size for outputted reconstructed pictures */
+ int32_t auto_crop_right;
+ int32_t auto_crop_bottom;
+ int32_t buf_cycle;
+ int32_t picture_structure;
+ /* <! pointer to current Slice data struct */
+ struct slice *currentSlice;
+
+ int32_t **predBlock; /* !< current best prediction mode */
+ int32_t **predBlockTmp;
+ /* !< the diff pixel values between orginal image and prediction */
+ int32_t **resiY;
+ /* !< Array containing square values,used for snr computation */
+ int32_t *quad;
+
+ /* //location of current MB////// */
+ int32_t mb_y; /* !< current MB vertical */
+ int32_t mb_x; /* !< current MB horizontal */
+ int32_t pix_y; /* !< current pixel vertical */
+ int32_t pix_x; /* !< current pixel horizontal */
+ int32_t pix_c_y; /* !< current pixel chroma vertical */
+ int32_t pix_c_x; /* !< current pixel chroma horizontal */
+
+ int32_t imgtr_next_P;
+
+ int32_t imgcoi_next_ref;
+
+ /* !< GH ipredmode[90][74];prediction mode for inter frames */
+ /* fix from ver 4.1 */
+ int32_t **ipredmode;
+ int32_t **rec_ipredmode;
+
+
+ /* //////////////decoder////////////////////////// */
+ int32_t max_mb_nr;
+ int32_t **intra_block;
+
+ int32_t block_y;
+ int32_t block_x;
+ /* <! final 4x4 block. Extended to 16x16 for AVS */
+ int32_t resiUV[2][MAX_CU_SIZE][MAX_CU_SIZE];
+
+ int32_t **fw_refFrArr; /* <! [72][88]; */
+ int32_t **bw_refFrArr; /* <! [72][88]; */
+
+ int32_t random_access_decodable_flag;
+
+ int32_t seq_header_indicate;
+ int32_t B_discard_flag;
+
+ /* B pictures */
+ uint32_t pic_distance;
+
+ uint32_t coding_order;
+
+ uint32_t PrevPicDistanceLsb;
+ int32_t CurrPicDistanceMsb;
+
+ int32_t PicHeightInMbs;
+
+ int32_t types;
+
+ int32_t new_sequence_flag;
+ int32_t sequence_end_flag; /* <! rm52k_r2 */
+
+ int32_t current_slice_set_index; /* <! added by mz, 2008.04 */
+ int32_t current_slice_header_flag; /* <! added by mz, 2008.04 */
+ int32_t slice_set_qp[64]; /* <! added by mz, 2008.04 */
+
+
+ int32_t inter_amp_enable;
+
+ /* ////////////////////////encoder////////////////////////// */
+
+ /* int32_t nb_references; //!< replaced by "num_of_references" */
+
+ int32_t framerate;
+
+ int32_t ***predBlockY; /* !< all 9 prediction modes */
+ /* !< new chroma 8x8 intra prediction modes */
+ int32_t ****predBlockUV;
+
+ int32_t **Coeff_all;/* qyu 0821 */
+
+ struct syntaxelement *MB_SyntaxElements; /* !< by oliver 0612 */
+
+ /* B pictures */
+
+ int32_t b_frame_to_code;
+ int32_t num_ref_pic_active_fwd_minus1;
+ int32_t num_ref_pic_active_bwd_minus1;
+ int32_t mv_range_flag;
+
+ uint32_t frame_num; /* frame_num for this frame */
+ int32_t slice_offset;
+ /* the following are sent in the slice header */
+ int32_t NoResidueDirect;
+ int32_t coded_mb_nr;
+ int32_t progressive_frame;
+ int32_t tc_reserve_bit;
+ /* the last MB no in current slice. Yulj 2004.07.15 */
+ int32_t mb_no_currSliceLastMB;
+ int32_t Seqheader_flag; /* Added by cjw, 20070327 */
+ int32_t EncodeEnd_flag; /* Carmen, 2007/12/19 */
+
+ uint16_t bbv_delay;
+
+ int32_t tmp_fwBSkipMv[DIRECTION + 1][2];
+ int32_t tmp_bwBSkipMv[DIRECTION + 1][2];
+
+ int32_t tmp_pref_fst[MH_PSKIP_NUM + NUM_OFFSET + 1];
+ int32_t tmp_pref_snd[MH_PSKIP_NUM + NUM_OFFSET + 1];
+ int32_t tmp_fstPSkipMv[MH_PSKIP_NUM + NUM_OFFSET + 1][3];
+ int32_t tmp_sndPSkipMv[MH_PSKIP_NUM + NUM_OFFSET + 1][3];
+#if BCBR
+byte *org_ref_y;
+byte *org_ref_u;
+byte *org_ref_v;
+int32_t *BLCUidx;
+int32_t *DQPList;
+int32_t iNumCUsInFrame;
+
+byte *org_ref2_y;
+byte *org_ref2_u;
+byte *org_ref2_v;
+int32_t ref2Num;
+#endif
+/* //////////////SAO parameter////////////////// */
+double *cur_saorate;
+#if 0
+int32_t slice_sao_on[NUM_SAO_COMPONENTS];
+#endif
+int32_t pic_alf_on[NUM_ALF_COMPONENT];
+struct alfdatapart *dp_ALF;
+
+#if INTERLACE_CODING
+int32_t is_field_sequence;
+int32_t is_top_field;
+#endif
+
+
+};
+
+
+
+/* ! struct for context management */
+struct BiContextType_s {
+ uint8_t MPS; /* 1 bit */
+ uint32_t LG_PMPS; /* 10 bits */
+ uint8_t cycno; /* 2 bits */
+};
+
+/***********************************************************************
+ * D a t a t y p e s f o r A E C
+ ************************************************************************/
+
+
+
+struct pix_pos {
+ int32_t available; /* ABCD */
+ int32_t mb_addr; /* MB position */
+ int32_t x;
+ int32_t y;
+ int32_t pos_x; /* 4x4 x-pos */
+ int32_t pos_y;
+};
+
+
+
+struct STDOUT_DATA_s {
+ int32_t type;
+ int32_t typeb;
+
+ int32_t framenum;
+ int32_t tr;
+ int32_t qp;
+ double snr_y;
+ double snr_u;
+ double snr_v;
+ int32_t tmp_time;
+ int32_t picture_structure;
+ int32_t curr_frame_bits;
+ int32_t emulate_bits;
+
+ uint32_t DecMD5Value[4];
+#if RD1501_FIX_BG
+int32_t background_picture_output_flag;/* Longfei.Wang@mediatek.com */
+#endif
+#if RD160_FIX_BG
+int32_t picture_reorder_delay;
+#endif
+int8_t str_reference_list[128]; /* reference list information */
+};
+
+/**********************************************************************
+ * C O N T E X T S F O R T M L S Y N T A X E L E M E N T S
+ **********************************************************************
+ */
+#define NUM_CuType_CTX (11 + 10)
+#define NUM_B8_TYPE_CTX 9
+#define NUM_MVD_CTX 15
+#define NUM_PMV_IDX_CTX 10
+#define NUM_REF_NO_CTX 6
+#define NUM_DELTA_QP_CTX 4
+#define NUM_INTER_DIR_CTX 18
+#define NUM_INTER_DIR_DHP_CTX 3
+#define NUM_B8_TYPE_DHP_CTX 1
+#define NUM_AMP_CTX 2
+#define NUM_C_INTRA_MODE_CTX 4
+#define NUM_CBP_CTX 4
+#define NUM_BCBP_CTX 4
+#define NUM_MAP_CTX 17
+#define NUM_LAST_CTX 17
+
+#define NUM_INTRA_MODE_CTX 7
+
+#define NUM_ABS_CTX 5
+#define NUM_TU_CTX 3
+#define NUM_SPLIT_CTX 8 /* CU depth */
+#if BCBR
+#define NUM_BGBLCOK_CTX 1
+#endif
+
+#define NUM_BRP_CTX 8
+
+
+#define NUM_LAST_CG_CTX_LUMA 12
+#define NUM_LAST_CG_CTX_CHROMA 6
+#define NUM_SIGCG_CTX_LUMA 2
+#define NUM_SIGCG_CTX_CHROMA 1
+#define NUM_LAST_POS_CTX_LUMA 56
+#define NUM_LAST_POS_CTX_CHROMA 16
+#define NUM_LAST_CG_CTX (NUM_LAST_CG_CTX_LUMA + NUM_LAST_CG_CTX_CHROMA)
+#define NUM_SIGCG_CTX (NUM_SIGCG_CTX_LUMA + NUM_SIGCG_CTX_CHROMA)
+#define NUM_LAST_POS_CTX (NUM_LAST_POS_CTX_LUMA + NUM_LAST_POS_CTX_CHROMA)
+#define NUM_SAO_MERGE_FLAG_CTX 3
+#define NUM_SAO_MODE_CTX 1
+#define NUM_SAO_OFFSET_CTX 2
+#define NUM_INTER_DIR_MIN_CTX 2
+
+/*end #include "commonStructures.h"*/
+
+/*#include "commonVariables.h"*/
+
+/*
+extern struct CameraParamters_s *camera;
+extern struct SNRParameters_s *snr;
+extern struct ImageParameters_s *img;
+ */
+
+/* avs2_frame_t *fref[REF_MAXBUFFER]; */
+
+
+#define ET_SIZE 300 /* !< size of error text buffer */
+
+
+/* ------------------------------------------------------
+ * common data
+ */
+struct Video_Com_data_s {
+ int32_t Bframe_ctr;
+
+ /* FILE *p_log; //!< SNR file */
+ /* FILE *p_trace; //!< Trace file */
+
+ int32_t tot_time;
+
+ /* Tsinghua for picture_distance 200701 */
+ int32_t picture_distance;
+
+ /* M3178 PKU Reference Manage */
+ int32_t coding_order;
+ /* !< current encoding/decoding frame pointer */
+ struct avs2_frame_s *f_rec;
+ int32_t seq_header;
+ /* !< Array for reference frames of each block */
+ int32_t **refFrArr;
+ int32_t **p_snd_refFrArr;
+
+ byte ***currentFrame; /* [yuv][height][width] */
+#ifdef AML
+ struct avs2_frame_s *cur_pic; /*either f_rec or m_bg*/
+#endif
+ byte **backgroundReferenceFrame[3];
+ byte ***background_ref;
+
+
+ int32_t total_frames;
+
+ /* mv_range, 20071009 */
+ int32_t Min_V_MV;
+ int32_t Max_V_MV;
+ int32_t Min_H_MV;
+ int32_t Max_H_MV;
+ /* !< buffer for error message for exit with error(void) */
+ int8_t errortext[ET_SIZE];
+ int8_t str_list_reference[128];
+
+
+};
+/* extern Video_Com_data *hc; */
+
+
+/*end #include "commonVariables.h"*/
+/* #define USE_PARAM_TXT */
+/*
+#if FIX_CHROMA_FIELD_MV_BK_DIST
+int8_t bk_img_is_top_field;
+#endif
+*/
+/* void write_GB_frame(FILE *p_dec); */
+
+#if !FIX_MAX_REF
+#define MAXREF 4
+#define MAXGOP 32
+#endif
+
+struct StatBits {
+ int32_t curr_frame_bits;
+ int32_t prev_frame_bits;
+ int32_t emulate_bits;
+ int32_t prev_emulate_bits;
+ int32_t last_unit_bits;
+ int32_t bitrate;
+ int32_t total_bitrate[1000];
+ int32_t coded_pic_num;
+ int32_t time_s;
+};
+
+struct reference_management {
+ int32_t poc;
+ int32_t qp_offset;
+ int32_t num_of_ref;
+ int32_t referd_by_others;
+ int32_t ref_pic[MAXREF];
+ int32_t predict;
+ int32_t deltaRPS;
+ int32_t num_to_remove;
+ int32_t remove_pic[MAXREF];
+};
+
+
+/* ------------------------------------------------------
+ * dec data
+ */
+struct Video_Dec_data_s {
+ byte **background_frame[3];
+ int32_t background_reference_enable;
+
+ int32_t background_picture_flag;
+ int32_t background_picture_output_flag;
+ int32_t background_picture_enable;
+
+ int32_t background_number;
+
+#if BCBR
+ int32_t bcbr_enable;
+#endif
+
+ int32_t demulate_enable;
+ int32_t currentbitoffset;
+
+ int32_t aspect_ratio_information;
+ int32_t frame_rate_code;
+ int32_t bit_rate_lower;
+ int32_t bit_rate_upper;
+ int32_t marker_bit;
+
+ int32_t video_format;
+ int32_t color_description;
+ int32_t color_primaries;
+ int32_t transfer_characteristics;
+ int32_t matrix_coefficients;
+
+ int32_t progressive_sequence;
+#if INTERLACE_CODING
+int32_t is_field_sequence;
+#endif
+int32_t low_delay;
+int32_t horizontal_size;
+int32_t vertical_size;
+int32_t sample_precision;
+int32_t video_range;
+
+int32_t display_horizontal_size;
+int32_t display_vertical_size;
+int32_t TD_mode;
+int32_t view_packing_mode;
+int32_t view_reverse;
+
+int32_t b_pmvr_enabled;
+int32_t dhp_enabled;
+int32_t b_dmh_enabled;
+int32_t b_mhpskip_enabled;
+int32_t wsm_enabled;
+int32_t b_secT_enabled;
+
+int32_t tmp_time;
+int32_t FrameNum;
+int32_t eos;
+int32_t pre_img_type;
+int32_t pre_img_types;
+/* int32_t pre_str_vec; */
+int32_t pre_img_tr;
+int32_t pre_img_qp;
+int32_t pre_tmp_time;
+int32_t RefPicExist; /* 20071224 */
+int32_t BgRefPicExist;
+int32_t dec_ref_num; /* ref order */
+
+/* video edit code */ /* M1956 by Grandview 2006.12.12 */
+int32_t vec_flag;
+
+/* Copyright_extension(void) header */
+int32_t copyright_flag;
+int32_t copyright_identifier;
+int32_t original_or_copy;
+int64_t copyright_number_1;
+int64_t copyright_number_2;
+int64_t copyright_number_3;
+/* Camera_parameters_extension */
+int32_t camera_id;
+int32_t height_of_image_device;
+int32_t focal_length;
+int32_t f_number;
+int32_t vertical_angle_of_view;
+int32_t camera_position_x_upper;
+int32_t camera_position_x_lower;
+int32_t camera_position_y_upper;
+int32_t camera_position_y_lower;
+int32_t camera_position_z_upper;
+int32_t camera_position_z_lower;
+int32_t camera_direction_x;
+int32_t camera_direction_y;
+int32_t camera_direction_z;
+int32_t image_plane_vertical_x;
+int32_t image_plane_vertical_y;
+int32_t image_plane_vertical_z;
+
+#if AVS2_HDR_HLS
+/* mastering_display_and_content_metadata_extension(void) header */
+int32_t display_primaries_x0;
+int32_t display_primaries_y0;
+int32_t display_primaries_x1;
+int32_t display_primaries_y1;
+int32_t display_primaries_x2;
+int32_t display_primaries_y2;
+int32_t white_point_x;
+int32_t white_point_y;
+int32_t max_display_mastering_luminance;
+int32_t min_display_mastering_luminance;
+int32_t maximum_content_light_level;
+int32_t maximum_frame_average_light_level;
+#endif
+
+/* I_pictures_header(void) */
+int32_t top_field_first;
+int32_t repeat_first_field;
+int32_t progressive_frame;
+#if INTERLACE_CODING
+int32_t is_top_field;
+#endif
+/* int32_t fixed_picture_qp; //qyu 0927 */
+int32_t picture_qp;
+int32_t fixed_picture_qp;
+int32_t time_code_flag;
+int32_t time_code;
+int32_t loop_filter_disable;
+int32_t loop_filter_parameter_flag;
+/* int32_t alpha_offset; */
+/* int32_t beta_offset; */
+
+/* Pb_picture_header(void) */
+int32_t picture_coding_type;
+
+/*picture_display_extension(void)*/
+int32_t frame_centre_horizontal_offset[4];
+int32_t frame_centre_vertical_offset[4];
+
+/* slice_header(void) */
+int32_t img_width;
+int32_t slice_vertical_position;
+int32_t slice_vertical_position_extension;
+int32_t fixed_slice_qp;
+int32_t slice_qp;
+int32_t slice_horizontal_positon; /* added by mz, 2008.04 */
+int32_t slice_horizontal_positon_extension;
+
+int32_t StartCodePosition;
+int32_t background_pred_flag;
+
+
+/* Reference Manage */
+int32_t displaydelay;
+int32_t picture_reorder_delay;
+#if M3480_TEMPORAL_SCALABLE
+int32_t temporal_id_exist_flag;
+#endif
+
+int32_t gop_size;
+struct reference_management decod_RPS[MAXGOP];
+struct reference_management curr_RPS;
+int32_t last_output;
+int32_t trtmp;
+#if M3480_TEMPORAL_SCALABLE
+int32_t cur_layer;
+#endif
+
+/* Adaptive frequency weighting quantization */
+#if FREQUENCY_WEIGHTING_QUANTIZATION
+int32_t weight_quant_enable_flag;
+int32_t load_seq_weight_quant_data_flag;
+
+int32_t pic_weight_quant_enable_flag;
+int32_t pic_weight_quant_data_index;
+int32_t weighting_quant_param;
+int32_t weighting_quant_model;
+int16_t quant_param_undetail[6]; /* M2148 2007-09 */
+int16_t quant_param_detail[6]; /* M2148 2007-09 */
+int32_t WeightQuantEnable; /* M2148 2007-09 */
+int32_t mb_adapt_wq_disable; /* M2331 2008-04 */
+int32_t mb_wq_mode; /* M2331 2008-04 */
+#if CHROMA_DELTA_QP
+int32_t chroma_quant_param_disable;
+int32_t chroma_quant_param_delta_u;
+int32_t chroma_quant_param_delta_v;
+#endif
+
+int32_t b_pre_dec_intra_img;
+int32_t pre_dec_img_type;
+int32_t CurrentSceneModel;
+#endif
+
+int32_t curr_IDRcoi;
+int32_t curr_IDRtr;
+int32_t next_IDRtr;
+int32_t next_IDRcoi;
+int32_t end_SeqTr;
+
+#if MB_DQP
+int32_t lastQP;
+/* FILE * testQP; */
+#endif
+
+};
+/* extern Video_Dec_data *hd; */
+
+struct DecodingEnvironment_s {
+ uint32_t Dbuffer;
+ int32_t Dbits_to_go;
+ uint8_t *Dcodestrm;
+ int32_t *Dcodestrm_len;
+};
+
+/* added at rm52k version */
+
+struct inp_par;
+
+
+
+/* ! Slice */
+struct slice {
+ int32_t picture_id;
+ int32_t qp;
+ int32_t picture_type; /* !< picture type */
+ int32_t start_mb_nr;
+ /* !< number of different partitions */
+ int32_t max_part_nr;
+
+ /* added by lzhang */
+ /* !< pointer to struct of context models for use in AEC */
+ struct SyntaxInfoContexts_s *syn_ctx;
+};
+
+struct alfdatapart {
+ struct Bitstream_s *bitstream;
+ struct DecodingEnvironment_s de_AEC;
+ struct SyntaxInfoContexts_s *syn_ctx;
+};
+/* static int32_t alfParAllcoated = 0; */
+
+/* input parameters from configuration file */
+struct inp_par {
+ int32_t buf_cycle; /* <! Frame buffer size */
+ int32_t ref_pic_order; /* <! ref order */
+ int32_t output_dec_pic; /* <! output_dec_pic */
+ int32_t profile_id;
+ int32_t level_id;
+ int32_t chroma_format;
+ int32_t g_uiMaxSizeInBit;
+ int32_t alpha_c_offset;
+ int32_t beta_offset;
+ int32_t useNSQT;
+#if MB_DQP
+ int32_t useDQP;
+#endif
+ int32_t useSDIP;
+ int32_t sao_enable;
+#if M3480_TEMPORAL_SCALABLE
+ int32_t temporal_id_exist_flag;
+#endif
+ int32_t alf_enable;
+
+ int32_t crossSliceLoopFilter;
+
+ int32_t sample_bit_depth; /* sample bit depth */
+ /* decoded file bit depth (assuming output_bit_depth is
+ less or equal to sample_bit_depth) */
+ int32_t output_bit_depth;
+
+
+ int32_t MD5Enable;
+
+#if OUTPUT_INTERLACE_MERGED_PIC
+ int32_t output_interlace_merged_picture;
+#endif
+
+};
+
+/* extern struct inp_par *input; */
+
+struct outdata_s {
+#if RD170_FIX_BG
+ struct STDOUT_DATA_s stdoutdata[REF_MAXBUFFER];
+#else
+ struct STDOUT_DATA_s stdoutdata[8];
+#endif
+ int32_t buffer_num;
+};
+/* outdata outprint; */
+
+#define PAYLOAD_TYPE_IDERP 8
+
+struct Bitstream_s *AllocBitstream(void);
+void FreeBitstream(void);
+#if TRACE
+void tracebits2(const int8_t *trace_str, int32_t len, int32_t info);
+#endif
+
+/* int32_t direct_mv[45][80][4][4][3]; // only to verify result */
+
+#define I_PICTURE_START_CODE 0xB3
+#define PB_PICTURE_START_CODE 0xB6
+#define SLICE_START_CODE_MIN 0x00
+#define SLICE_START_CODE_MAX 0x8F
+#define USER_DATA_START_CODE 0xB2
+#define SEQUENCE_HEADER_CODE 0xB0
+#define EXTENSION_START_CODE 0xB5
+#define SEQUENCE_END_CODE 0xB1
+#define VIDEO_EDIT_CODE 0xB7
+
+
+#define SEQUENCE_DISPLAY_EXTENSION_ID 2
+#define COPYRIGHT_EXTENSION_ID 4
+#define CAMERAPARAMETERS_EXTENSION_ID 11
+#define PICTURE_DISPLAY_EXTENSION_ID 7
+#if M3480_TEMPORAL_SCALABLE
+#define TEMPORAL_SCALABLE_EXTENSION_ID 3
+#endif
+
+#if ROI_M3264
+#if RD1501_FIX_BG
+#define LOCATION_DATA_EXTENSION_ID 12
+#else
+#define LOCATION_DATA_EXTENSION_ID 15
+#endif
+#endif
+
+#if AVS2_HDR_HLS
+#define MASTERING_DISPLAY_AND_CONTENT_METADATA_EXTENSION 10
+#endif
+
+void malloc_slice(void);
+void free_slice(void);
+
+
+void read_ipred_modes(void);
+
+int32_t AEC_startcode_follows(int32_t eos_bit);
+
+/* extern uint32_t max_value_s; */
+
+/*ComAdaptiveLoopFilter.h*/
+#define ALF_MAX_NUM_COEF 9
+#define NO_VAR_BINS 16
+
+
+#define RPM_BEGIN 0x100
+#define ALF_BEGIN 0x180
+#define RPM_END 0x280
+
+union param_u {
+ struct {
+ uint16_t data[RPM_END - RPM_BEGIN];
+ } l;
+ struct {
+ /*sequence*/
+ uint16_t profile_id;
+ uint16_t level_id;
+ uint16_t progressive_sequence;
+ uint16_t is_field_sequence;
+ uint16_t horizontal_size;
+ uint16_t vertical_size;
+ uint16_t chroma_format;
+ uint16_t sample_precision;
+ uint16_t encoding_precision;
+ uint16_t aspect_ratio_information;
+ uint16_t frame_rate_code;
+ uint16_t bit_rate_lower;
+ uint16_t bit_rate_upper;
+ uint16_t low_delay;
+ uint16_t temporal_id_exist_flag;
+ uint16_t g_uiMaxSizeInBit;
+
+#define BACKGROUND_PICTURE_DISABLE_BIT 11
+#define B_MHPSKIP_ENABLED_BIT 10
+#define DHP_ENABLED_BIT 9
+#define WSM_ENABLED_BIT 8
+#define INTER_AMP_ENABLE_BIT 7
+#define USENSQT_BIT 6
+#define USESDIP_BIT 5
+#define B_SECT_ENABLED_BIT 4
+#define SAO_ENABLE_BIT 3
+#define ALF_ENABLE_BIT 2
+#define B_PMVR_ENABLED_BIT 1
+#define CROSSSLICELOOPFILTER_BIT 0
+ uint16_t avs2_seq_flags;
+
+ uint16_t num_of_RPS;
+ uint16_t picture_reorder_delay;
+ /*PIC*/
+ uint16_t time_code_flag;
+ uint16_t time_code;
+ uint16_t background_picture_flag;
+ uint16_t background_picture_output_flag;
+ uint16_t coding_order;
+ uint16_t cur_layer;
+ uint16_t displaydelay; /*???*/
+ uint16_t predict; /*???*/
+ uint16_t RPS_idx; /*???*/
+ uint16_t referd_by_others_cur;
+ uint16_t num_of_ref_cur;
+ uint16_t ref_pic_cur[8];
+ uint16_t num_to_remove_cur;
+ uint16_t remove_pic_cur[8];
+ uint16_t progressive_frame;
+ uint16_t picture_structure;
+ uint16_t top_field_first;
+ uint16_t repeat_first_field;
+ uint16_t is_top_field;
+
+ uint16_t picture_coding_type;
+ uint16_t background_pred_flag;
+ uint16_t background_reference_enable;
+ uint16_t random_access_decodable_flag;
+ uint16_t lcu_size;
+ uint16_t alpha_c_offset;
+ uint16_t beta_offset;
+ uint16_t chroma_quant_param_delta_cb;
+ uint16_t chroma_quant_param_delta_cr;
+ uint16_t loop_filter_disable;
+ } p;
+ struct {
+ uint16_t padding[ALF_BEGIN - RPM_BEGIN];
+ uint16_t picture_alf_enable_Y;
+ uint16_t picture_alf_enable_Cb;
+ uint16_t picture_alf_enable_Cr;
+ uint16_t alf_filters_num_m_1;
+ uint16_t region_distance[16];
+ uint16_t alf_cb_coeffmulti[9];
+ uint16_t alf_cr_coeffmulti[9];
+ uint16_t alf_y_coeffmulti[16][9];
+ } alf;
+};
+
+
+struct avs2_decoder {
+ uint8_t init_hw_flag;
+ struct inp_par input;
+ struct ImageParameters_s img;
+ struct Video_Com_data_s hc;
+ struct Video_Dec_data_s hd;
+ union param_u param;
+ struct avs2_frame_s frm_pool[AVS2_MAX_BUFFER_NUM];
+ struct avs2_frame_s *fref[REF_MAXBUFFER];
+#ifdef AML
+ /*used for background
+ when background_picture_output_flag is 0*/
+ struct avs2_frame_s *m_bg;
+ /*current background picture, ether m_bg or fref[..]*/
+ struct avs2_frame_s *f_bg;
+#endif
+ struct outdata_s outprint;
+ uint32_t cm_header_start;
+ struct ALFParam_s m_alfPictureParam[NUM_ALF_COMPONENT];
+#ifdef FIX_CHROMA_FIELD_MV_BK_DIST
+ int8_t bk_img_is_top_field;
+#endif
+#ifdef AML
+ int32_t lcu_size;
+ int32_t lcu_size_log2;
+ int32_t lcu_x_num;
+ int32_t lcu_y_num;
+ int32_t lcu_total;
+ int32_t ref_maxbuffer;
+#endif
+};
+
+
+extern void write_frame(struct avs2_decoder *avs2_dec, int32_t pos);
+extern void init_frame_t(struct avs2_frame_s *currfref);
+extern void report_frame(struct avs2_decoder *avs2_dec,
+ struct outdata_s *data, int32_t pos);
+
+extern int avs2_post_process(struct avs2_decoder *avs2_dec);
+extern void avs2_prepare_header(struct avs2_decoder *avs2_dec,
+ int32_t start_code);
+extern int32_t avs2_process_header(struct avs2_decoder *avs2_dec);
+
+extern void init_avs2_decoder(struct avs2_decoder *avs2_dec);
+
+extern int32_t avs2_init_global_buffers(struct avs2_decoder *avs2_dec);
+
+extern bool is_avs2_print_param(void);
+extern bool is_avs2_print_bufmgr_detail(void);
+#endif
+
diff --git a/drivers/frame_provider/decoder/avs2/vavs2.c b/drivers/frame_provider/decoder/avs2/vavs2.c
new file mode 100644
index 0000000..4a764ef
--- a/dev/null
+++ b/drivers/frame_provider/decoder/avs2/vavs2.c
@@ -0,0 +1,6057 @@
+ /*
+ * drivers/amlogic/amports/avs2.c
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+*/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/semaphore.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/kfifo.h>
+#include <linux/kthread.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/amlogic/media/vfm/vframe.h>
+#include <linux/amlogic/media/utils/amstream.h>
+#include <linux/amlogic/media/utils/vformat.h>
+#include <linux/amlogic/media/frame_sync/ptsserv.h>
+#include <linux/amlogic/media/canvas/canvas.h>
+#include <linux/amlogic/media/vfm/vframe_provider.h>
+#include <linux/amlogic/media/vfm/vframe_receiver.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
+#include <linux/slab.h>
+#include <linux/amlogic/tee.h>
+#include "../../../stream_input/amports/amports_priv.h"
+#include <linux/amlogic/media/codec_mm/codec_mm.h>
+#include "../utils/decoder_mmu_box.h"
+#include "../utils/decoder_bmmu_box.h"
+#include "avs2_global.h"
+
+#define MEM_NAME "codec_avs2"
+/* #include <mach/am_regs.h> */
+#include <linux/amlogic/media/utils/vdec_reg.h>
+#include "../utils/vdec.h"
+#include "../utils/amvdec.h"
+
+#include <linux/amlogic/media/video_sink/video.h>
+#include <linux/amlogic/media/codec_mm/configs.h>
+#include "../utils/config_parser.h"
+#include "../utils/firmware.h"
+
+#define MIX_STREAM_SUPPORT
+#define SUPPORT_4K2K
+
+#define G12A_BRINGUP_DEBUG
+
+#include "vavs2.h"
+#define HEVC_SHIFT_LENGTH_PROTECT 0x313a
+#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_SAO_MMU_STATUS 0x3639
+
+
+#define AVS2_10B_DISCARD_NAL 6
+#define AVS2_DUMP_LMEM 7
+#define HEVC_DECPIC_DATA_DONE 0xa
+#define HEVC_DECPIC_DATA_ERROR 0xb
+#define HEVC_NAL_DECODE_DONE 0xe
+
+#define AVS2_HEAD_SEQ_READY 0x21
+#define AVS2_HEAD_PIC_I_READY 0x22
+#define AVS2_HEAD_PIC_PB_READY 0x23
+#define AVS2_HEAD_SEQ_END_READY 0x24
+
+#define AVS2_DECODE_BUFEMPTY 0x30
+#define AVS2_DECODE_TIMEOUT 0x31
+#define AVS2_DECODE_OVER_SIZE 0x33
+
+#define AVS2_EOS 0xf2
+#define AVS2_DISCARD_NAL 0xf0
+#define AVS2_ACTION_ERROR 0xfe
+#define AVS2_ACTION_DONE 0xff
+
+#define VF_POOL_SIZE 32
+
+#undef pr_info
+#define pr_info printk
+
+#define DECODE_MODE_SINGLE (0 | (0x80 << 24))
+#define DECODE_MODE_MULTI_STREAMBASE (1 | (0x80 << 24))
+#define DECODE_MODE_MULTI_FRAMEBASE (2 | (0x80 << 24))
+
+
+#define VP9_TRIGGER_FRAME_DONE 0x100
+#define VP9_TRIGGER_FRAME_ENABLE 0x200
+
+/*#define MV_MEM_UNIT 0x240*/
+#define MV_MEM_UNIT 0x200
+/*---------------------------------------------------
+ Include "parser_cmd.h"
+---------------------------------------------------*/
+#define PARSER_CMD_SKIP_CFG_0 0x0000090b
+
+#define PARSER_CMD_SKIP_CFG_1 0x1b14140f
+
+#define PARSER_CMD_SKIP_CFG_2 0x001b1910
+
+
+#define PARSER_CMD_NUMBER 37
+
+static unsigned short parser_cmd[PARSER_CMD_NUMBER] = {
+0x0401,
+0x8401,
+0x0800,
+0x0402,
+0x9002,
+0x1423,
+0x8CC3,
+0x1423,
+0x8804,
+0x9825,
+0x0800,
+0x04FE,
+0x8406,
+0x8411,
+0x1800,
+0x8408,
+0x8409,
+0x8C2A,
+0x9C2B,
+0x1C00,
+0x840F,
+0x8407,
+0x8000,
+0x8408,
+0x2000,
+0xA800,
+0x8410,
+0x04DE,
+0x840C,
+0x840D,
+0xAC00,
+0xA000,
+0x08C0,
+0x08E0,
+0xA40E,
+0xFC00,
+0x7C00
+};
+
+static int32_t g_WqMDefault4x4[16] = {
+ 64, 64, 64, 68,
+ 64, 64, 68, 72,
+ 64, 68, 76, 80,
+ 72, 76, 84, 96
+};
+
+
+static int32_t g_WqMDefault8x8[64] = {
+ 64, 64, 64, 64, 68, 68, 72, 76,
+ 64, 64, 64, 68, 72, 76, 84, 92,
+ 64, 64, 68, 72, 76, 80, 88, 100,
+ 64, 68, 72, 80, 84, 92, 100, 112,
+ 68, 72, 80, 84, 92, 104, 112, 128,
+ 76, 80, 84, 92, 104, 116, 132, 152,
+ 96, 100, 104, 116, 124, 140, 164, 188,
+ 104, 108, 116, 128, 152, 172, 192, 216
+};
+/*#define HEVC_PIC_STRUCT_SUPPORT*/
+/* to remove, fix build error */
+
+/*#define CODEC_MM_FLAGS_FOR_VDECODER 0*/
+
+#define MULTI_INSTANCE_SUPPORT
+/* #define ERROR_HANDLE_DEBUG */
+#if 0 /* MESON_CPU_TYPE == MESON_CPU_TYPE_MESON8B*/
+#undef SUPPORT_4K2K
+#else
+#define SUPPORT_4K2K
+#endif
+
+#ifndef STAT_KTHREAD
+#define STAT_KTHREAD 0x40
+#endif
+
+#ifdef MULTI_INSTANCE_SUPPORT
+#define MAX_DECODE_INSTANCE_NUM 12
+#define MULTI_DRIVER_NAME "ammvdec_avs2"
+
+#define lock_buffer(dec, flags) \
+ spin_lock_irqsave(&dec->buffer_lock, flags)
+
+#define unlock_buffer(dec, flags) \
+ spin_unlock_irqrestore(&dec->buffer_lock, flags)
+
+static unsigned int max_decode_instance_num
+ = MAX_DECODE_INSTANCE_NUM;
+static unsigned int decode_frame_count[MAX_DECODE_INSTANCE_NUM];
+static unsigned int display_frame_count[MAX_DECODE_INSTANCE_NUM];
+static unsigned int max_process_time[MAX_DECODE_INSTANCE_NUM];
+static unsigned int run_count[MAX_DECODE_INSTANCE_NUM];
+static unsigned int input_empty[MAX_DECODE_INSTANCE_NUM];
+static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM];
+
+#ifdef G12A_BRINGUP_DEBUG
+static u32 decode_timeout_val;
+#else
+static u32 decode_timeout_val = 200;
+#endif
+static int start_decode_buf_level = 0x8000;
+#ifdef AVS2_10B_MMU
+static u32 work_buf_size; /* = 24 * 1024 * 1024*/;
+#else
+static u32 work_buf_size = 32 * 1024 * 1024;
+#endif
+
+static u32 mv_buf_margin;
+
+/* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */
+/* double_write_mode: 0, no double write
+ 1, 1:1 ratio
+ 2, (1/4):(1/4) ratio
+ 4, (1/2):(1/2) ratio
+ 0x10, double write only
+*/
+static u32 double_write_mode;
+
+#define DRIVER_NAME "amvdec_avs2"
+#define MODULE_NAME "amvdec_avs2"
+#define DRIVER_HEADER_NAME "amvdec_avs2_header"
+
+
+#define PUT_INTERVAL (HZ/100)
+#define ERROR_SYSTEM_RESET_COUNT 200
+
+#define PTS_NORMAL 0
+#define PTS_NONE_REF_USE_DURATION 1
+
+#define PTS_MODE_SWITCHING_THRESHOLD 3
+#define PTS_MODE_SWITCHING_RECOVERY_THREASHOLD 3
+
+#define DUR2PTS(x) ((x)*90/96)
+
+struct AVS2Decoder_s;
+static int vavs2_vf_states(struct vframe_states *states, void *);
+static struct vframe_s *vavs2_vf_peek(void *);
+static struct vframe_s *vavs2_vf_get(void *);
+static void vavs2_vf_put(struct vframe_s *, void *);
+static int vavs2_event_cb(int type, void *data, void *private_data);
+static void set_vframe(struct AVS2Decoder_s *dec,
+ struct vframe_s *vf, struct avs2_frame_s *pic, u8 dummy);
+
+static int vavs2_stop(struct AVS2Decoder_s *dec);
+static s32 vavs2_init(struct vdec_s *vdec);
+static void vavs2_prot_init(struct AVS2Decoder_s *dec);
+static int vavs2_local_init(struct AVS2Decoder_s *dec);
+static void vavs2_put_timer_func(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);
+static void dump_pic_list(struct AVS2Decoder_s *dec);
+
+static const char vavs2_dec_id[] = "vavs2-dev";
+
+#define PROVIDER_NAME "decoder.avs2"
+#define MULTI_INSTANCE_PROVIDER_NAME "vdec.avs2"
+
+static const struct vframe_operations_s vavs2_vf_provider = {
+ .peek = vavs2_vf_peek,
+ .get = vavs2_vf_get,
+ .put = vavs2_vf_put,
+ .event_cb = vavs2_event_cb,
+ .vf_states = vavs2_vf_states,
+};
+
+static struct vframe_provider_s vavs2_vf_prov;
+
+static u32 bit_depth_luma;
+static u32 bit_depth_chroma;
+static u32 frame_width;
+static u32 frame_height;
+static u32 video_signal_type;
+static u32 pts_unstable;
+static u32 on_no_keyframe_skiped;
+
+
+#define PROB_SIZE (496 * 2 * 4)
+#define PROB_BUF_SIZE (0x5000)
+#define COUNT_BUF_SIZE (0x300 * 4 * 4)
+/*compute_losless_comp_body_size(4096, 2304, 1) = 18874368(0x1200000)*/
+#define MAX_FRAME_4K_NUM 0x1200
+#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4)
+
+static inline int div_r32(int64_t m, int n)
+{
+/*
+return (int)(m/n)
+*/
+#ifndef CONFIG_ARM64
+ do_div(m, n);
+ return (int)m;
+#else
+ return (int)(m/n);
+#endif
+}
+
+enum vpx_bit_depth_t {
+ AVS2_BITS_8 = 8, /**< 8 bits */
+ AVS2_BITS_10 = 10, /**< 10 bits */
+ AVS2_BITS_12 = 12, /**< 12 bits */
+};
+
+/*USE_BUF_BLOCK*/
+struct BUF_s {
+ int index;
+ unsigned int alloc_flag;
+ /*buffer */
+ unsigned int cma_page_count;
+ unsigned long alloc_addr;
+ unsigned long start_adr;
+ unsigned int size;
+
+ unsigned int free_start_adr;
+} /*BUF_t */;
+
+struct MVBUF_s {
+ unsigned long start_adr;
+ unsigned int size;
+ int used_flag;
+} /*MVBUF_t */;
+
+ /* #undef BUFMGR_ONLY to enable hardware configuration */
+
+/*#define TEST_WR_PTR_INC*/
+#define WR_PTR_INC_NUM 128
+
+#define SIMULATION
+#define DOS_PROJECT
+#undef MEMORY_MAP_IN_REAL_CHIP
+
+/*#undef DOS_PROJECT*/
+/*#define MEMORY_MAP_IN_REAL_CHIP*/
+
+/*#define BUFFER_MGR_ONLY*/
+/*#define CONFIG_HEVC_CLK_FORCED_ON*/
+/*#define ENABLE_SWAP_TEST*/
+
+#ifdef AVS2_10B_NV21
+#define MEM_MAP_MODE 2 /* 0:linear 1:32x32 2:64x32*/
+#else
+#define MEM_MAP_MODE 0 /* 0:linear 1:32x32 2:64x32*/
+#endif
+
+#ifdef AVS2_10B_NV21
+#else
+#define LOSLESS_COMPRESS_MODE
+#endif
+
+#define DOUBLE_WRITE_YSTART_TEMP 0x02000000
+#define DOUBLE_WRITE_CSTART_TEMP 0x02900000
+
+
+
+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
+#define AVS2_DBG_IRQ_EVENT 0x08
+#define AVS2_DBG_OUT_PTS 0x10
+#define AVS2_DBG_PRINT_SOURCE_LINE 0x20
+#define AVS2_DBG_PRINT_PARAM 0x40
+#define AVS2_DBG_SEND_PARAM_WITH_REG 0x100
+#define AVS2_DBG_MERGE 0x200
+#define AVS2_DBG_DBG_LF_PRINT 0x400
+#define AVS2_DBG_REG 0x800
+#define AVS2_DBG_DIS_LOC_ERROR_PROC 0x10000
+#define AVS2_DBG_DIS_SYS_ERROR_PROC 0x20000
+#define AVS2_DBG_DUMP_PIC_LIST 0x40000
+#define AVS2_DBG_TRIG_SLICE_SEGMENT_PROC 0x80000
+#define AVS2_DBG_HW_RESET 0x100000
+#define AVS2_DBG_LOAD_UCODE_FROM_FILE 0x200000
+#define AVS2_DBG_FORCE_SEND_AGAIN 0x400000
+#define AVS2_DBG_DUMP_DATA 0x800000
+#define AVS2_DBG_CACHE 0x1000000
+#define AVS2_DBG_CACHE_HIT_RATE 0x2000000
+#define IGNORE_PARAM_FROM_CONFIG 0x8000000
+/*MULTI_INSTANCE_SUPPORT*/
+#define PRINT_FLAG_ERROR 0
+#define PRINT_FLAG_VDEC_STATUS 0x20000000
+#define PRINT_FLAG_VDEC_DETAIL 0x40000000
+#define PRINT_FLAG_VDEC_DATA 0x80000000
+
+#define PRINT_LINE() \
+ if (debug & AVS2_DBG_PRINT_SOURCE_LINE)\
+ pr_info("%s line %d\\n", __func__, __LINE__)
+
+static u32 debug;
+
+bool is_avs2_print_param(void)
+{
+ bool ret = false;
+ if (debug & AVS2_DBG_PRINT_PARAM)
+ ret = true;
+ return ret;
+}
+
+bool is_avs2_print_bufmgr_detail(void)
+{
+ bool ret = false;
+ if (debug & AVS2_DBG_BUFMGR_DETAIL)
+ ret = true;
+ return ret;
+}
+static bool is_reset;
+/*for debug*/
+/*
+ udebug_flag:
+ bit 0, enable ucode print
+ bit 1, enable ucode detail print
+ bit [31:16] not 0, pos to dump lmem
+ bit 2, pop bits to lmem
+ bit [11:8], pre-pop bits for alignment (when bit 2 is 1)
+*/
+static u32 udebug_flag;
+/*
+ when udebug_flag[1:0] is not 0
+ udebug_pause_pos not 0,
+ pause position
+*/
+static u32 udebug_pause_pos;
+/*
+ when udebug_flag[1:0] is not 0
+ and udebug_pause_pos is not 0,
+ pause only when DEBUG_REG2 is equal to this val
+*/
+static u32 udebug_pause_val;
+
+static u32 udebug_pause_decode_idx;
+
+static u32 force_disp_pic_index;
+
+#define DEBUG_REG
+#ifdef DEBUG_REG
+static void WRITE_VREG_DBG2(unsigned adr, unsigned val)
+{
+ if (debug & AVS2_DBG_REG)
+ pr_info("%s(%x, %x)\n", __func__, adr, val);
+ if (adr != 0)
+ WRITE_VREG(adr, val);
+}
+
+#undef WRITE_VREG
+#define WRITE_VREG WRITE_VREG_DBG2
+#endif
+
+
+#ifdef AVS2_10B_MMU
+#define MMU_COMPRESS_HEADER_SIZE 0x48000
+#endif
+
+#define INVALID_IDX -1 /* Invalid buffer index.*/
+
+
+#define FRAME_BUFFERS (AVS2_MAX_BUFFER_NUM)
+#define HEADER_FRAME_BUFFERS (FRAME_BUFFERS)
+#define MAX_BUF_NUM (FRAME_BUFFERS)
+
+#define FRAME_CONTEXTS_LOG2 2
+#define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2)
+/*buffer + header buffer + workspace*/
+#ifdef MV_USE_FIXED_BUF
+#define MAX_BMMU_BUFFER_NUM (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + 1)
+#define VF_BUFFER_IDX(n) (n)
+#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n)
+#define WORK_SPACE_BUF_ID (FRAME_BUFFERS + HEADER_FRAME_BUFFERS)
+#else
+#define MAX_BMMU_BUFFER_NUM ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS + 1)
+#define VF_BUFFER_IDX(n) (n)
+#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n)
+#define MV_BUFFER_IDX(n) ((FRAME_BUFFERS * 2) + n)
+#define WORK_SPACE_BUF_ID ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS)
+#endif
+/*
+static void set_canvas(struct AVS2Decoder_s *dec,
+ struct avs2_frame_s *pic);
+int avs2_prepare_display_buf(struct AVS2Decoder_s *dec,
+ int pos);
+*/
+
+
+struct buff_s {
+ u32 buf_start;
+ u32 buf_size;
+ u32 buf_end;
+};
+
+struct BuffInfo_s {
+ u32 max_width;
+ u32 max_height;
+ u32 start_adr;
+ u32 end_adr;
+ struct buff_s ipp;
+ struct buff_s sao_abv;
+ struct buff_s sao_vb;
+ struct buff_s short_term_rps;
+ struct buff_s rcs;
+ struct buff_s sps;
+ struct buff_s pps;
+ struct buff_s sao_up;
+ struct buff_s swap_buf;
+ struct buff_s swap_buf2;
+ struct buff_s scalelut;
+ struct buff_s dblk_para;
+ struct buff_s dblk_data;
+ struct buff_s dblk_data2;
+#ifdef AVS2_10B_MMU
+ struct buff_s mmu_vbh;
+ struct buff_s cm_header;
+#endif
+ struct buff_s mpred_above;
+#ifdef MV_USE_FIXED_BUF
+ struct buff_s mpred_mv;
+#endif
+ struct buff_s rpm;
+ struct buff_s lmem;
+};
+
+#define DEC_RESULT_NONE 0
+#define DEC_RESULT_DONE 1
+#define DEC_RESULT_AGAIN 2
+#define DEC_RESULT_CONFIG_PARAM 3
+#define DEC_RESULT_ERROR 4
+#define DEC_INIT_PICLIST 5
+#define DEC_UNINIT_PICLIST 6
+#define DEC_RESULT_GET_DATA 7
+#define DEC_RESULT_GET_DATA_RETRY 8
+#define DEC_RESULT_EOS 9
+#define DEC_RESULT_FORCE_EXIT 10
+
+static void avs2_work(struct work_struct *work);
+struct loop_filter_info_n;
+struct loopfilter;
+struct segmentation;
+
+struct AVS2Decoder_s {
+ int pic_list_init_flag;
+ unsigned char index;
+ spinlock_t buffer_lock;
+ struct device *cma_dev;
+ struct platform_device *platform_dev;
+ void (*vdec_cb)(struct vdec_s *, void *);
+ void *vdec_cb_arg;
+ struct vframe_chunk_s *chunk;
+ int dec_result;
+ struct work_struct work;
+ u32 start_shift_bytes;
+
+ struct BuffInfo_s work_space_buf_store;
+ unsigned long buf_start;
+ u32 buf_size;
+ u32 cma_alloc_count;
+ unsigned long cma_alloc_addr;
+ uint8_t eos;
+ unsigned long int start_process_time;
+ unsigned last_lcu_idx;
+ int decode_timeout_count;
+ unsigned timeout_num;
+
+ int double_write_mode;
+
+ unsigned char m_ins_flag;
+ char *provider_name;
+ int frame_count;
+ u32 stat;
+ struct timer_list timer;
+ u32 frame_dur;
+ u32 frame_ar;
+ int fatal_error;
+ uint8_t init_flag;
+ uint8_t process_busy;
+#define PROC_STATE_INIT 0
+#define PROC_STATE_DECODESLICE 1
+#define PROC_STATE_SENDAGAIN 2
+ uint8_t process_state;
+ u32 ucode_pause_pos;
+
+ int show_frame_num;
+#ifndef AVS2_10B_MMU
+ struct buff_s mc_buf_spec;
+#endif
+ struct dec_sysinfo vavs2_amstream_dec_info;
+ void *rpm_addr;
+ void *lmem_addr;
+ dma_addr_t rpm_phy_addr;
+ dma_addr_t lmem_phy_addr;
+ unsigned short *lmem_ptr;
+ unsigned short *debug_ptr;
+
+#if 1
+ /*AVS2_10B_MMU*/
+ void *frame_mmu_map_addr;
+ dma_addr_t frame_mmu_map_phy_addr;
+#endif
+ unsigned int use_cma_flag;
+
+ struct BUF_s m_BUF[MAX_BUF_NUM];
+ struct MVBUF_s m_mv_BUF[MAX_BUF_NUM];
+ u32 used_buf_num;
+ DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE);
+ DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE);
+ DECLARE_KFIFO(pending_q, struct vframe_s *, VF_POOL_SIZE);
+ struct vframe_s vfpool[VF_POOL_SIZE];
+ u32 vf_pre_count;
+ u32 vf_get_count;
+ u32 vf_put_count;
+ int buf_num;
+ unsigned int losless_comp_body_size;
+
+ u32 video_signal_type;
+
+ int pts_mode;
+ int last_lookup_pts;
+ int last_pts;
+ u64 last_lookup_pts_us64;
+ u64 last_pts_us64;
+ u64 shift_byte_count;
+ u32 shift_byte_count_lo;
+ u32 shift_byte_count_hi;
+ int pts_mode_switching_count;
+ int pts_mode_recovery_count;
+
+ bool get_frame_dur;
+ u32 saved_resolution;
+
+ /**/
+ int refresh_frame_flags;
+ uint8_t hold_ref_buf;
+ struct BuffInfo_s *work_space_buf;
+#ifndef AVS2_10B_MMU
+ struct buff_s *mc_buf;
+#endif
+ unsigned int frame_width;
+ unsigned int frame_height;
+
+ unsigned short *rpm_ptr;
+ int init_pic_w;
+ int init_pic_h;
+
+ int slice_type;
+
+ int decode_idx;
+ int slice_idx;
+ uint8_t wait_buf;
+ uint8_t error_flag;
+
+ /* bit 0, for decoding; bit 1, for displaying */
+ uint8_t ignore_bufmgr_error;
+ int PB_skip_mode;
+ int PB_skip_count_after_decoding;
+ /*hw*/
+
+ /**/
+ struct vdec_info *gvs;
+
+
+ unsigned int dec_status;
+ u32 last_put_idx;
+ int new_frame_displayed;
+ void *mmu_box;
+ void *bmmu_box;
+ struct vframe_master_display_colour_s vf_dp;
+ struct firmware_s *fw;
+#ifdef AVS2_10B_MMU
+ int cur_fb_idx_mmu;
+ long used_4k_num;
+#endif
+ struct avs2_decoder avs2_dec;
+#define ALF_NUM_BIT_SHIFT 6
+#define NO_VAR_BINS 16
+ int32_t m_filterCoeffSym[16][9];
+ int32_t m_varIndTab[NO_VAR_BINS];
+
+ struct vframe_s vframe_dummy;
+
+};
+
+static int compute_losless_comp_body_size(
+ struct AVS2Decoder_s *dec, int width, int height,
+ uint8_t is_bit_depth_10);
+
+static int avs2_print(struct AVS2Decoder_s *dec,
+ int flag, const char *fmt, ...)
+{
+#define HEVC_PRINT_BUF 256
+ unsigned char buf[HEVC_PRINT_BUF];
+ int len = 0;
+ if (dec == NULL ||
+ (flag == 0) ||
+ (debug & flag)) {
+ va_list args;
+ va_start(args, fmt);
+ if (dec)
+ len = sprintf(buf, "[%d]", dec->index);
+ vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args);
+ pr_info("%s", buf);
+ va_end(args);
+ }
+ return 0;
+}
+
+static int avs2_print_cont(struct AVS2Decoder_s *dec,
+ int flag, const char *fmt, ...)
+{
+ unsigned char buf[HEVC_PRINT_BUF];
+ int len = 0;
+ if (dec == NULL ||
+ (flag == 0) ||
+ (debug & flag)) {
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(buf + len, HEVC_PRINT_BUF - len, fmt, args);
+ pr_info("%s", buf);
+ va_end(args);
+ }
+ return 0;
+}
+
+static void reset_process_time(struct AVS2Decoder_s *dec)
+{
+ if (dec->start_process_time) {
+ unsigned process_time =
+ 1000 * (jiffies - dec->start_process_time) / HZ;
+ dec->start_process_time = 0;
+ if (process_time > max_process_time[dec->index])
+ max_process_time[dec->index] = process_time;
+ }
+}
+
+static void start_process_time(struct AVS2Decoder_s *dec)
+{
+ dec->start_process_time = jiffies;
+ dec->decode_timeout_count = 0;
+ dec->last_lcu_idx = 0;
+}
+
+static void timeout_process(struct AVS2Decoder_s *dec)
+{
+ dec->timeout_num++;
+ amhevc_stop();
+ avs2_print(dec,
+ 0, "%s decoder timeout\n", __func__);
+
+ dec->dec_result = DEC_RESULT_DONE;
+ reset_process_time(dec);
+ vdec_schedule_work(&dec->work);
+}
+
+static u32 get_valid_double_write_mode(struct AVS2Decoder_s *dec)
+{
+ return (dec->m_ins_flag &&
+ ((double_write_mode & 0x80000000) == 0)) ?
+ dec->double_write_mode :
+ (double_write_mode & 0x7fffffff);
+}
+
+static int get_double_write_mode(struct AVS2Decoder_s *dec)
+{
+ u32 valid_dw_mode = get_valid_double_write_mode(dec);
+ u32 dw;
+ if (valid_dw_mode == 0x100) {
+ int w = dec->avs2_dec.img.width;
+ int h = dec->avs2_dec.img.height;
+ if (w > 1920 && h > 1088)
+ dw = 0x4; /*1:2*/
+ else
+ dw = 0x1; /*1:1*/
+
+ return dw;
+ }
+
+ return valid_dw_mode;
+}
+
+/* for double write buf alloc */
+static int get_double_write_mode_init(struct AVS2Decoder_s *dec)
+{
+ u32 valid_dw_mode = get_valid_double_write_mode(dec);
+ if (valid_dw_mode == 0x100) {
+ u32 dw;
+ int w = dec->init_pic_w;
+ int h = dec->init_pic_h;
+ if (w > 1920 && h > 1088)
+ dw = 0x4; /*1:2*/
+ else
+ dw = 0x1; /*1:1*/
+
+ return dw;
+ }
+ return valid_dw_mode;
+}
+
+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(
+ struct AVS2Decoder_s *dec,
+ int cur_buf_idx,
+ int pic_width,
+ int pic_height,
+ unsigned short bit_depth,
+ unsigned int *mmu_index_adr)
+{
+ int bit_depth_10 = (bit_depth == AVS2_BITS_10);
+ int picture_size;
+ int cur_mmu_4k_number;
+
+ 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 (cur_mmu_4k_number > MAX_4K_NUM) {
+ pr_err("over max !! cur_mmu_4k_number 0x%x width %d height %d\n",
+ cur_mmu_4k_number, pic_width, pic_height);
+ return -1;
+ }
+ return decoder_mmu_box_alloc_idx(
+ dec->mmu_box,
+ cur_buf_idx,
+ cur_mmu_4k_number,
+ mmu_index_adr);
+}
+#endif
+
+#ifndef MV_USE_FIXED_BUF
+static void dealloc_mv_bufs(struct AVS2Decoder_s *dec)
+{
+ int i;
+ for (i = 0; i < FRAME_BUFFERS; i++) {
+ if (dec->m_mv_BUF[i].start_adr) {
+ if (debug)
+ pr_info(
+ "dealloc mv buf(%d) adr %ld size 0x%x used_flag %d\n",
+ i, dec->m_mv_BUF[i].start_adr,
+ dec->m_mv_BUF[i].size,
+ dec->m_mv_BUF[i].used_flag);
+ decoder_bmmu_box_free_idx(
+ dec->bmmu_box,
+ MV_BUFFER_IDX(i));
+ dec->m_mv_BUF[i].start_adr = 0;
+ dec->m_mv_BUF[i].size = 0;
+ dec->m_mv_BUF[i].used_flag = 0;
+ }
+ }
+}
+
+static int alloc_mv_buf(struct AVS2Decoder_s *dec,
+ int i, int size)
+{
+ int ret = 0;
+ if (decoder_bmmu_box_alloc_buf_phy
+ (dec->bmmu_box,
+ MV_BUFFER_IDX(i), size,
+ DRIVER_NAME,
+ &dec->m_mv_BUF[i].start_adr) < 0) {
+ dec->m_mv_BUF[i].start_adr = 0;
+ ret = -1;
+ } else {
+ dec->m_mv_BUF[i].size = size;
+ dec->m_mv_BUF[i].used_flag = 0;
+ ret = 0;
+ if (debug) {
+ pr_info(
+ "MV Buffer %d: start_adr %p size %x\n",
+ i,
+ (void *)dec->m_mv_BUF[i].start_adr,
+ dec->m_mv_BUF[i].size);
+ }
+ }
+ return ret;
+}
+
+static int init_mv_buf_list(struct AVS2Decoder_s *dec)
+{
+ int i;
+ int ret = 0;
+ int count = FRAME_BUFFERS;
+ int pic_width = dec->init_pic_w;
+ int pic_height = dec->init_pic_h;
+ int lcu_size = 64; /*fixed 64*/
+ int pic_width_64 = (pic_width + 63) & (~0x3f);
+ int pic_height_32 = (pic_height + 31) & (~0x1f);
+ int pic_width_lcu = (pic_width_64 % lcu_size) ?
+ pic_width_64 / lcu_size + 1
+ : pic_width_64 / lcu_size;
+ int pic_height_lcu = (pic_height_32 % lcu_size) ?
+ pic_height_32 / lcu_size + 1
+ : pic_height_32 / lcu_size;
+ int lcu_total = pic_width_lcu * pic_height_lcu;
+ int size = ((lcu_total * MV_MEM_UNIT) + 0xffff) &
+ (~0xffff);
+ if (mv_buf_margin > 0)
+ count = dec->avs2_dec.ref_maxbuffer + mv_buf_margin;
+ for (i = 0; i < count; i++) {
+ if (alloc_mv_buf(dec, i, size) < 0) {
+ ret = -1;
+ break;
+ }
+ }
+ return ret;
+}
+#if 0
+
+static int get_mv_buf(struct AVS2Decoder_s *dec,
+ struct avs2_frame_s *pic)
+{
+ int i;
+ int ret = -1;
+ for (i = 0; i < FRAME_BUFFERS; i++) {
+ if (dec->m_mv_BUF[i].start_adr &&
+ dec->m_mv_BUF[i].used_flag == 0) {
+ dec->m_mv_BUF[i].used_flag = 1;
+ ret = i;
+ break;
+ }
+ }
+
+ if (ret >= 0) {
+ pic->mv_buf_index = ret;
+ pic->mpred_mv_wr_start_addr =
+ (dec->m_mv_BUF[ret].start_adr + 0xffff) &
+ (~0xffff);
+ if (debug & AVS2_DBG_BUFMGR_MORE)
+ pr_info(
+ "%s => %d (%d) size 0x%x\n",
+ __func__, ret,
+ pic->mpred_mv_wr_start_addr,
+ dec->m_mv_BUF[ret].size);
+ } else {
+ pr_info(
+ "%s: Error, mv buf is not enough\n",
+ __func__);
+ }
+ return ret;
+}
+
+static void put_mv_buf(struct AVS2Decoder_s *dec,
+ struct avs2_frame_s *pic)
+{
+ int i = pic->mv_buf_index;
+ if (i >= FRAME_BUFFERS) {
+ if (debug & AVS2_DBG_BUFMGR_MORE)
+ pr_info(
+ "%s: index %d beyond range\n",
+ __func__, i);
+ return;
+ }
+ if (debug & AVS2_DBG_BUFMGR_MORE)
+ pr_info(
+ "%s(%d): used_flag(%d)\n",
+ __func__, i,
+ dec->m_mv_BUF[i].used_flag);
+
+ pic->mv_buf_index = -1;
+ if (dec->m_mv_BUF[i].start_adr &&
+ dec->m_mv_BUF[i].used_flag)
+ dec->m_mv_BUF[i].used_flag = 0;
+}
+
+static void put_un_used_mv_bufs(struct AVS2Decoder_s *dec)
+{
+ struct VP9_Common_s *const cm = &dec->common;
+ struct RefCntBuffer_s *const frame_bufs = cm->buffer_pool->frame_bufs;
+ int i;
+ for (i = 0; i < dec->used_buf_num; ++i) {
+ if ((frame_bufs[i].ref_count == 0) &&
+ (frame_bufs[i].buf.index != -1) &&
+ (frame_bufs[i].buf.mv_buf_index >= 0)
+ )
+ put_mv_buf(dec, &frame_bufs[i].buf);
+ }
+}
+#endif
+
+#endif
+
+static int get_free_buf_count(struct AVS2Decoder_s *dec)
+{
+ struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+ int i;
+ int count = 0;
+ for (i = 0; i < avs2_dec->ref_maxbuffer; i++) {
+ if ((avs2_dec->fref[i]->imgcoi_ref < -256
+#if 0
+ || abs(avs2_dec->fref[i]->
+ imgtr_fwRefDistance - img->tr) >= 128
+#endif
+ ) && avs2_dec->fref[i]->is_output == -1
+ && avs2_dec->fref[i]->bg_flag == 0
+#ifndef NO_DISPLAY
+ && avs2_dec->fref[i]->vf_ref == 0
+#endif
+ ) {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+
+int avs2_bufmgr_init(struct AVS2Decoder_s *dec, struct BuffInfo_s *buf_spec_i,
+ struct buff_s *mc_buf_i) {
+
+ dec->frame_count = 0;
+#ifdef AVS2_10B_MMU
+ dec->used_4k_num = -1;
+ dec->cur_fb_idx_mmu = INVALID_IDX;
+#endif
+
+
+ /* private init */
+ dec->work_space_buf = buf_spec_i;
+#ifndef AVS2_10B_MMU
+ dec->mc_buf = mc_buf_i;
+#endif
+ dec->rpm_addr = NULL;
+ dec->lmem_addr = NULL;
+
+ dec->use_cma_flag = 0;
+ dec->decode_idx = 0;
+ dec->slice_idx = 0;
+ /*int m_uiMaxCUWidth = 1<<7;*/
+ /*int m_uiMaxCUHeight = 1<<7;*/
+ dec->wait_buf = 0;
+ dec->error_flag = 0;
+
+ dec->pts_mode = PTS_NORMAL;
+ dec->last_pts = 0;
+ dec->last_lookup_pts = 0;
+ dec->last_pts_us64 = 0;
+ dec->last_lookup_pts_us64 = 0;
+ dec->shift_byte_count = 0;
+ dec->shift_byte_count_lo = 0;
+ dec->shift_byte_count_hi = 0;
+ dec->pts_mode_switching_count = 0;
+ dec->pts_mode_recovery_count = 0;
+
+ dec->buf_num = 0;
+
+ return 0;
+}
+
+
+
+#define HEVC_CM_BODY_START_ADDR 0x3626
+#define HEVC_CM_BODY_LENGTH 0x3627
+#define HEVC_CM_HEADER_LENGTH 0x3629
+#define HEVC_CM_HEADER_OFFSET 0x362b
+
+#define LOSLESS_COMPRESS_MODE
+
+/*#define DECOMP_HEADR_SURGENT*/
+
+static u32 mem_map_mode; /* 0:linear 1:32x32 2:64x32 ; m8baby test1902 */
+static u32 enable_mem_saving = 1;
+static u32 force_w_h;
+
+static u32 force_fps;
+
+
+const u32 avs2_version = 201602101;
+static u32 debug;
+static u32 radr;
+static u32 rval;
+static u32 pop_shorts;
+static u32 dbg_cmd;
+static u32 dbg_skip_decode_index;
+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 */
+static u32 dbg_nal_skip_count;
+#endif
+/*for debug*/
+static u32 decode_pic_begin;
+static uint slice_parse_begin;
+static u32 step;
+#ifdef MIX_STREAM_SUPPORT
+#ifdef SUPPORT_4K2K
+static u32 buf_alloc_width = 4096;
+static u32 buf_alloc_height = 2304;
+#else
+static u32 buf_alloc_width = 1920;
+static u32 buf_alloc_height = 1088;
+#endif
+static u32 dynamic_buf_num_margin;
+#else
+static u32 buf_alloc_width;
+static u32 buf_alloc_height;
+static u32 dynamic_buf_num_margin = 7;
+#endif
+static u32 buf_alloc_depth = 10;
+static u32 buf_alloc_size;
+/*
+bit[0]: 0,
+ bit[1]: 0, always release cma buffer when stop
+ bit[1]: 1, never release cma buffer when stop
+bit[0]: 1, when stop, release cma buffer if blackout is 1;
+do not release cma buffer is blackout is not 1
+
+bit[2]: 0, when start decoding, check current displayed buffer
+ (only for buffer decoded by vp9) if blackout is 0
+ 1, do not check current displayed buffer
+
+bit[3]: 1, if blackout is not 1, do not release current
+ displayed cma buffer always.
+*/
+/* set to 1 for fast play;
+ set to 8 for other case of "keep last frame"
+*/
+static u32 buffer_mode = 1;
+/* buffer_mode_dbg: debug only*/
+static u32 buffer_mode_dbg = 0xffff0000;
+/**/
+
+/*
+bit 0, 1: only display I picture;
+bit 1, 1: only decode I picture;
+*/
+static u32 i_only_flag;
+
+
+static u32 max_decoding_time;
+/*
+error handling
+*/
+/*error_handle_policy:
+bit 0: 0, auto skip error_skip_nal_count nals before error recovery;
+1, skip error_skip_nal_count nals before error recovery;
+bit 1 (valid only when bit0 == 1):
+1, wait vps/sps/pps after error recovery;
+bit 2 (valid only when bit0 == 0):
+0, auto search after error recovery (avs2_recover() called);
+1, manual search after error recovery
+(change to auto search after get IDR: WRITE_VREG(NAL_SEARCH_CTL, 0x2))
+
+bit 4: 0, set error_mark after reset/recover
+ 1, do not set error_mark after reset/recover
+bit 5: 0, check total lcu for every picture
+ 1, do not check total lcu
+
+*/
+
+static u32 error_handle_policy;
+/*static u32 parser_sei_enable = 1;*/
+
+static u32 max_buf_num = (REF_BUFFER + 1);
+
+static u32 run_ready_min_buf_num = 2;
+
+static DEFINE_MUTEX(vavs2_mutex);
+
+#define HEVC_DEC_STATUS_REG HEVC_ASSIST_SCRATCH_0
+#define HEVC_RPM_BUFFER HEVC_ASSIST_SCRATCH_1
+#define HEVC_SHORT_TERM_RPS HEVC_ASSIST_SCRATCH_2
+#define HEVC_RCS_BUFFER HEVC_ASSIST_SCRATCH_3
+#define HEVC_SPS_BUFFER HEVC_ASSIST_SCRATCH_4
+#define HEVC_PPS_BUFFER HEVC_ASSIST_SCRATCH_5
+#define HEVC_SAO_UP HEVC_ASSIST_SCRATCH_6
+#ifdef AVS2_10B_MMU
+#define AVS2_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_7
+#else
+#define HEVC_STREAM_SWAP_BUFFER HEVC_ASSIST_SCRATCH_7
+#endif
+#define HEVC_STREAM_SWAP_BUFFER2 HEVC_ASSIST_SCRATCH_8
+/*
+#define VP9_PROB_SWAP_BUFFER HEVC_ASSIST_SCRATCH_9
+#define VP9_COUNT_SWAP_BUFFER HEVC_ASSIST_SCRATCH_A
+#define VP9_SEG_MAP_BUFFER HEVC_ASSIST_SCRATCH_B
+*/
+#define HEVC_SCALELUT HEVC_ASSIST_SCRATCH_D
+#define HEVC_WAIT_FLAG HEVC_ASSIST_SCRATCH_E
+#define RPM_CMD_REG HEVC_ASSIST_SCRATCH_F
+#define LMEM_DUMP_ADR HEVC_ASSIST_SCRATCH_9
+#define HEVC_STREAM_SWAP_TEST HEVC_ASSIST_SCRATCH_L
+/*!!!*/
+#define HEVC_DECODE_COUNT HEVC_ASSIST_SCRATCH_M
+#define HEVC_DECODE_SIZE HEVC_ASSIST_SCRATCH_N
+#define DEBUG_REG1 HEVC_ASSIST_SCRATCH_G
+#define DEBUG_REG2 HEVC_ASSIST_SCRATCH_H
+
+
+/*
+ucode parser/search control
+bit 0: 0, header auto parse; 1, header manual parse
+bit 1: 0, auto skip for noneseamless stream; 1, no skip
+bit [3:2]: valid when bit1==0;
+0, auto skip nal before first vps/sps/pps/idr;
+1, auto skip nal before first vps/sps/pps
+2, auto skip nal before first vps/sps/pps,
+ and not decode until the first I slice (with slice address of 0)
+
+3, auto skip before first I slice (nal_type >=16 && nal_type<=21)
+bit [15:4] nal skip count (valid when bit0 == 1 (manual mode) )
+bit [16]: for NAL_UNIT_EOS when bit0 is 0:
+ 0, send SEARCH_DONE to arm ; 1, do not send SEARCH_DONE to arm
+bit [17]: for NAL_SEI when bit0 is 0:
+ 0, do not parse SEI in ucode; 1, parse SEI in ucode
+bit [31:20]: used by ucode for debug purpose
+*/
+#define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I
+#define DECODE_MODE HEVC_ASSIST_SCRATCH_J
+#define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K
+
+#define RPM_BUF_SIZE (0x400 * 2)
+#define LMEM_BUF_SIZE (0x400 * 2)
+
+#define WORK_BUF_SPEC_NUM 2
+static struct BuffInfo_s amvavs2_workbuff_spec[WORK_BUF_SPEC_NUM] = {
+ {
+ /* 8M bytes */
+ .max_width = 1920,
+ .max_height = 1088,
+ .ipp = {
+ /* IPP work space calculation :
+ 4096 * (Y+CbCr+Flags) = 12k, round to 16k */
+ .buf_size = 0x4000,
+ },
+ .sao_abv = {
+ .buf_size = 0x30000,
+ },
+ .sao_vb = {
+ .buf_size = 0x30000,
+ },
+ .short_term_rps = {
+ /* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
+ total 64x16x2 = 2048 bytes (0x800) */
+ .buf_size = 0x800,
+ },
+ .rcs = {
+ /* RCS STORE AREA - Max 32 RCS, each has 32 bytes,
+ total 0x0400 bytes */
+ .buf_size = 0x400,
+ },
+ .sps = {
+ /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
+ total 0x0800 bytes*/
+ .buf_size = 0x800,
+ },
+ .pps = {
+ /*PPS STORE AREA - Max 64 PPS, each has 0x80 bytes,
+ total 0x2000 bytes*/
+ .buf_size = 0x2000,
+ },
+ .sao_up = {
+ /* SAO UP STORE AREA - Max 640(10240/16) LCU,
+ each has 16 bytes total 0x2800 bytes */
+ .buf_size = 0x2800,
+ },
+ .swap_buf = {
+ /* 256cyclex64bit = 2K bytes 0x800
+ (only 144 cycles valid) */
+ .buf_size = 0x800,
+ },
+ .swap_buf2 = {
+ .buf_size = 0x800,
+ },
+ .scalelut = {
+ /* support up to 32 SCALELUT 1024x32 =
+ 32Kbytes (0x8000) */
+ .buf_size = 0x8000,
+ },
+ .dblk_para = {
+ /* DBLK -> Max 256(4096/16) LCU,
+ each para 1024bytes(total:0x40000),
+ data 1024bytes(total:0x40000)*/
+ .buf_size = 0x40000,
+ },
+ .dblk_data = {
+ .buf_size = 0x40000,
+ },
+ .dblk_data2 = {
+ .buf_size = 0x40000,
+ },
+#ifdef AVS2_10B_MMU
+ .mmu_vbh = {
+ .buf_size = 0x5000, /*2*16*(more than 2304)/4, 4K*/
+ },
+#if 0
+ .cm_header = {
+ /*add one for keeper.*/
+ .buf_size = MMU_COMPRESS_HEADER_SIZE *
+ (FRAME_BUFFERS + 1),
+ /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */
+ },
+#endif
+#endif
+ .mpred_above = {
+ .buf_size = 0x8000, /* 2 * size of hevc*/
+ },
+#ifdef MV_USE_FIXED_BUF
+ .mpred_mv = {/* 1080p, 0x40000 per buffer */
+ .buf_size = 0x40000 * FRAME_BUFFERS,
+ },
+#endif
+ .rpm = {
+ .buf_size = RPM_BUF_SIZE,
+ },
+ .lmem = {
+ .buf_size = 0x400 * 2,
+ }
+ },
+ {
+ .max_width = 4096,
+ .max_height = 2304,
+ .ipp = {
+ /* IPP work space calculation :
+ 4096 * (Y+CbCr+Flags) = 12k, round to 16k */
+ .buf_size = 0x4000,
+ },
+ .sao_abv = {
+ .buf_size = 0x30000,
+ },
+ .sao_vb = {
+ .buf_size = 0x30000,
+ },
+ .short_term_rps = {
+ /* SHORT_TERM_RPS - Max 64 set, 16 entry every set,
+ total 64x16x2 = 2048 bytes (0x800) */
+ .buf_size = 0x800,
+ },
+ .rcs = {
+ /* RCS STORE AREA - Max 16 RCS, each has 32 bytes,
+ total 0x0400 bytes */
+ .buf_size = 0x400,
+ },
+ .sps = {
+ /* SPS STORE AREA - Max 16 SPS, each has 0x80 bytes,
+ total 0x0800 bytes */
+ .buf_size = 0x800,
+ },
+ .pps = {
+ /* PPS STORE AREA - Max 64 PPS, each has 0x80 bytes,
+ total 0x2000 bytes */
+ .buf_size = 0x2000,
+ },
+ .sao_up = {
+ /* SAO UP STORE AREA - Max 640(10240/16) LCU,
+ each has 16 bytes total 0x2800 bytes */
+ .buf_size = 0x2800,
+ },
+ .swap_buf = {
+ /* 256cyclex64bit = 2K bytes 0x800
+ (only 144 cycles valid) */
+ .buf_size = 0x800,
+ },
+ .swap_buf2 = {
+ .buf_size = 0x800,
+ },
+ .scalelut = {
+ /* support up to 32 SCALELUT 1024x32 = 32Kbytes
+ (0x8000) */
+ .buf_size = 0x8000,
+ },
+ .dblk_para = {
+ /* DBLK -> Max 256(4096/16) LCU,
+ each para 1024bytes(total:0x40000),
+ data 1024bytes(total:0x40000)*/
+ .buf_size = 0x80000,
+ },
+ .dblk_data = {
+ /*DBLK -> Max 256(4096/16) LCU,
+ each para 1024bytes(total:0x40000),
+ data 1024bytes(total:0x40000)*/
+ .buf_size = 0x80000,
+ },
+ .dblk_data2 = {
+ .buf_size = 0x80000,
+ },
+#ifdef AVS2_10B_MMU
+ .mmu_vbh = {
+ .buf_size = 0x5000,/*2*16*(more than 2304)/4, 4K*/
+ },
+#if 0
+ .cm_header = {
+ /*add one for keeper.*/
+ .buf_size = MMU_COMPRESS_HEADER_SIZE *
+ (FRAME_BUFFERS + 1),
+ /* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */
+ },
+#endif
+#endif
+ .mpred_above = {
+ .buf_size = 0x10000, /* 2 * size of hevc*/
+ },
+#ifdef MV_USE_FIXED_BUF
+ .mpred_mv = {
+ /* .buf_size = 0x100000*16,
+ //4k2k , 0x100000 per buffer */
+ /* 4096x2304 , 0x120000 per buffer */
+ .buf_size = 0x120000 * FRAME_BUFFERS,
+ },
+#endif
+ .rpm = {
+ .buf_size = RPM_BUF_SIZE,
+ },
+ .lmem = {
+ .buf_size = 0x400 * 2,
+ }
+ }
+};
+
+
+/*Losless compression body buffer size 4K per 64x32 (jt)*/
+static int compute_losless_comp_body_size(struct AVS2Decoder_s *dec,
+ int width, int height,
+ uint8_t is_bit_depth_10)
+{
+ int width_x64;
+ int height_x32;
+ int bsize;
+ width_x64 = width + 63;
+ width_x64 >>= 6;
+ height_x32 = height + 31;
+ height_x32 >>= 5;
+#ifdef AVS2_10B_MMU
+ bsize = (is_bit_depth_10 ? 4096 : 3200)
+ * width_x64 * height_x32;
+#else
+ bsize = (is_bit_depth_10 ? 4096 : 3072)
+ * width_x64 * height_x32;
+#endif
+ avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+ "%s(%d,%d,%d)=>%d\n",
+ __func__, width, height,
+ is_bit_depth_10, bsize);
+
+ return bsize;
+}
+
+/* Losless compression header buffer size 32bytes per 128x64 (jt)*/
+static int compute_losless_comp_header_size(struct AVS2Decoder_s *dec,
+ int width, int height)
+{
+ int width_x128;
+ int height_x64;
+ int hsize;
+ width_x128 = width + 127;
+ width_x128 >>= 7;
+ height_x64 = height + 63;
+ height_x64 >>= 6;
+
+ hsize = 32 * width_x128 * height_x64;
+ avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+ "%s(%d,%d)=>%d\n",
+ __func__, width, height,
+ hsize);
+
+ return hsize;
+}
+
+static void init_buff_spec(struct AVS2Decoder_s *dec,
+ struct BuffInfo_s *buf_spec)
+{
+ void *mem_start_virt;
+ buf_spec->ipp.buf_start = buf_spec->start_adr;
+ buf_spec->sao_abv.buf_start =
+ buf_spec->ipp.buf_start + buf_spec->ipp.buf_size;
+
+ buf_spec->sao_vb.buf_start =
+ buf_spec->sao_abv.buf_start + buf_spec->sao_abv.buf_size;
+ buf_spec->short_term_rps.buf_start =
+ buf_spec->sao_vb.buf_start + buf_spec->sao_vb.buf_size;
+ buf_spec->rcs.buf_start =
+ buf_spec->short_term_rps.buf_start +
+ buf_spec->short_term_rps.buf_size;
+ buf_spec->sps.buf_start =
+ buf_spec->rcs.buf_start + buf_spec->rcs.buf_size;
+ buf_spec->pps.buf_start =
+ buf_spec->sps.buf_start + buf_spec->sps.buf_size;
+ buf_spec->sao_up.buf_start =
+ buf_spec->pps.buf_start + buf_spec->pps.buf_size;
+ buf_spec->swap_buf.buf_start =
+ buf_spec->sao_up.buf_start + buf_spec->sao_up.buf_size;
+ buf_spec->swap_buf2.buf_start =
+ buf_spec->swap_buf.buf_start + buf_spec->swap_buf.buf_size;
+ buf_spec->scalelut.buf_start =
+ buf_spec->swap_buf2.buf_start + buf_spec->swap_buf2.buf_size;
+ buf_spec->dblk_para.buf_start =
+ buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size;
+ buf_spec->dblk_data.buf_start =
+ buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size;
+ buf_spec->dblk_data2.buf_start =
+ buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size;
+#ifdef AVS2_10B_MMU
+ buf_spec->mmu_vbh.buf_start =
+ buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size;
+ buf_spec->mpred_above.buf_start =
+ buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size;
+#else
+ buf_spec->mpred_above.buf_start =
+ buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size;
+#endif
+#ifdef MV_USE_FIXED_BUF
+ buf_spec->mpred_mv.buf_start =
+ buf_spec->mpred_above.buf_start +
+ buf_spec->mpred_above.buf_size;
+
+ buf_spec->rpm.buf_start =
+ buf_spec->mpred_mv.buf_start +
+ buf_spec->mpred_mv.buf_size;
+#else
+ buf_spec->rpm.buf_start =
+ buf_spec->mpred_above.buf_start +
+ buf_spec->mpred_above.buf_size;
+
+#endif
+ buf_spec->lmem.buf_start =
+ buf_spec->rpm.buf_start +
+ buf_spec->rpm.buf_size;
+ buf_spec->end_adr =
+ buf_spec->lmem.buf_start +
+ buf_spec->lmem.buf_size;
+
+ if (dec) {
+ mem_start_virt =
+ codec_mm_phys_to_virt(buf_spec->dblk_para.buf_start);
+ if (mem_start_virt) {
+ memset(mem_start_virt, 0, buf_spec->dblk_para.buf_size);
+ codec_mm_dma_flush(mem_start_virt,
+ buf_spec->dblk_para.buf_size,
+ DMA_TO_DEVICE);
+ } else {
+ /*not virt for tvp playing,
+ may need clear on ucode.*/
+ pr_err("mem_start_virt failed\n");
+ }
+ if (debug) {
+ pr_info("%s workspace (%x %x) size = %x\n", __func__,
+ buf_spec->start_adr, buf_spec->end_adr,
+ buf_spec->end_adr - buf_spec->start_adr);
+ }
+ if (debug) {
+ pr_info("ipp.buf_start :%x\n",
+ buf_spec->ipp.buf_start);
+ pr_info("sao_abv.buf_start :%x\n",
+ buf_spec->sao_abv.buf_start);
+ pr_info("sao_vb.buf_start :%x\n",
+ buf_spec->sao_vb.buf_start);
+ pr_info("short_term_rps.buf_start :%x\n",
+ buf_spec->short_term_rps.buf_start);
+ pr_info("rcs.buf_start :%x\n",
+ buf_spec->rcs.buf_start);
+ pr_info("sps.buf_start :%x\n",
+ buf_spec->sps.buf_start);
+ pr_info("pps.buf_start :%x\n",
+ buf_spec->pps.buf_start);
+ pr_info("sao_up.buf_start :%x\n",
+ buf_spec->sao_up.buf_start);
+ pr_info("swap_buf.buf_start :%x\n",
+ buf_spec->swap_buf.buf_start);
+ pr_info("swap_buf2.buf_start :%x\n",
+ buf_spec->swap_buf2.buf_start);
+ pr_info("scalelut.buf_start :%x\n",
+ buf_spec->scalelut.buf_start);
+ pr_info("dblk_para.buf_start :%x\n",
+ buf_spec->dblk_para.buf_start);
+ pr_info("dblk_data.buf_start :%x\n",
+ buf_spec->dblk_data.buf_start);
+ pr_info("dblk_data2.buf_start :%x\n",
+ buf_spec->dblk_data2.buf_start);
+ #ifdef AVS2_10B_MMU
+ pr_info("mmu_vbh.buf_start :%x\n",
+ buf_spec->mmu_vbh.buf_start);
+ #endif
+ pr_info("mpred_above.buf_start :%x\n",
+ buf_spec->mpred_above.buf_start);
+#ifdef MV_USE_FIXED_BUF
+ pr_info("mpred_mv.buf_start :%x\n",
+ buf_spec->mpred_mv.buf_start);
+#endif
+ if ((debug & AVS2_DBG_SEND_PARAM_WITH_REG) == 0) {
+ pr_info("rpm.buf_start :%x\n",
+ buf_spec->rpm.buf_start);
+ }
+ }
+ }
+
+}
+
+static void uninit_mmu_buffers(struct AVS2Decoder_s *dec)
+{
+#ifndef MV_USE_FIXED_BUF
+ dealloc_mv_bufs(dec);
+#endif
+ decoder_mmu_box_free(dec->mmu_box);
+ dec->mmu_box = NULL;
+
+ if (dec->bmmu_box)
+ decoder_bmmu_box_free(dec->bmmu_box);
+ dec->bmmu_box = NULL;
+}
+
+#ifndef AVS2_10B_MMU
+static void init_buf_list(struct AVS2Decoder_s *dec)
+{
+ int i;
+ int buf_size;
+ int mc_buffer_end = dec->mc_buf->buf_start + dec->mc_buf->buf_size;
+ dec->used_buf_num = max_buf_num;
+
+ if (dec->used_buf_num > MAX_BUF_NUM)
+ dec->used_buf_num = MAX_BUF_NUM;
+ if (buf_alloc_size > 0) {
+ buf_size = buf_alloc_size;
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "[Buffer Management] init_buf_list:\n");
+ } else {
+ int pic_width = dec->init_pic_w;
+ int pic_height = dec->init_pic_h;
+
+ /*SUPPORT_10BIT*/
+ int losless_comp_header_size = compute_losless_comp_header_size
+ (dec, pic_width, pic_height);
+ int losless_comp_body_size = compute_losless_comp_body_size
+ (dec, pic_width, pic_height, buf_alloc_depth == 10);
+ int mc_buffer_size = losless_comp_header_size
+ + losless_comp_body_size;
+ int mc_buffer_size_h = (mc_buffer_size + 0xffff)>>16;
+
+ int dw_mode = get_double_write_mode_init(dec);
+
+ if (dw_mode) {
+ int pic_width_dw = pic_width /
+ get_double_write_ratio(dec, dw_mode);
+ int pic_height_dw = pic_height /
+ 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);
+ int pic_width_lcu =
+ (pic_width_64 % lcu_size) ? pic_width_64 / lcu_size
+ + 1 : pic_width_64 / lcu_size;
+ int pic_height_lcu =
+ (pic_height_32 % lcu_size) ? pic_height_32 / lcu_size
+ + 1 : pic_height_32 / lcu_size;
+ int lcu_total = pic_width_lcu * pic_height_lcu;
+ int mc_buffer_size_u_v = lcu_total * lcu_size * lcu_size / 2;
+ int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16;
+ /*64k alignment*/
+ buf_size = ((mc_buffer_size_u_v_h << 16) * 3);
+ } else
+ buf_size = 0;
+
+ if (mc_buffer_size & 0xffff) { /*64k alignment*/
+ mc_buffer_size_h += 1;
+ }
+ if ((dw_mode & 0x10) == 0)
+ buf_size += (mc_buffer_size_h << 16);
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "init_buf_list num %d (width %d height %d):\n",
+ dec->used_buf_num, pic_width, pic_height);
+ }
+
+ for (i = 0; i < dec->used_buf_num; i++) {
+ if (((i + 1) * buf_size) > dec->mc_buf->buf_size)
+ dec->use_cma_flag = 1;
+#ifndef AVS2_10B_MMU
+ dec->m_BUF[i].alloc_flag = 0;
+ dec->m_BUF[i].index = i;
+
+ dec->use_cma_flag = 1;
+ if (dec->use_cma_flag) {
+ dec->m_BUF[i].cma_page_count =
+ PAGE_ALIGN(buf_size) / PAGE_SIZE;
+ if (decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box,
+ VF_BUFFER_IDX(i), buf_size, DRIVER_NAME,
+ &dec->m_BUF[i].alloc_addr) < 0) {
+ dec->m_BUF[i].cma_page_count = 0;
+ if (i <= 5) {
+ dec->fatal_error |=
+ DECODER_FATAL_ERROR_NO_MEM;
+ }
+ break;
+ }
+ dec->m_BUF[i].start_adr = dec->m_BUF[i].alloc_addr;
+ } else {
+ dec->m_BUF[i].cma_page_count = 0;
+ dec->m_BUF[i].alloc_addr = 0;
+ dec->m_BUF[i].start_adr =
+ dec->mc_buf->buf_start + i * buf_size;
+ }
+ dec->m_BUF[i].size = buf_size;
+ dec->m_BUF[i].free_start_adr = dec->m_BUF[i].start_adr;
+
+ if (((dec->m_BUF[i].start_adr + buf_size) > mc_buffer_end)
+ && (dec->m_BUF[i].alloc_addr == 0)) {
+ if (debug) {
+ avs2_print(dec, 0,
+ "Max mc buffer or mpred_mv buffer is used\n");
+ }
+ break;
+ }
+
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "Buffer %d: start_adr %p size %x\n", i,
+ (void *)dec->m_BUF[i].start_adr,
+ dec->m_BUF[i].size);
+#endif
+ }
+ dec->buf_num = i;
+}
+#endif
+
+static int config_pic(struct AVS2Decoder_s *dec,
+ struct avs2_frame_s *pic, int32_t lcu_size_log2)
+{
+ int ret = -1;
+ int i;
+ int pic_width = dec->init_pic_w;
+ int pic_height = dec->init_pic_h;
+ /*struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+ int32_t lcu_size_log2 = avs2_dec->lcu_size_log2;*/
+ int32_t lcu_size = 1 << lcu_size_log2;
+ int pic_width_64 = (pic_width + 63) & (~0x3f);
+ int pic_height_32 = (pic_height + 31) & (~0x1f);
+ int pic_width_lcu = (pic_width_64 % lcu_size) ?
+ pic_width_64 / lcu_size + 1
+ : pic_width_64 / lcu_size;
+ int pic_height_lcu = (pic_height_32 % lcu_size) ?
+ pic_height_32 / lcu_size + 1
+ : pic_height_32 / lcu_size;
+ int lcu_total = pic_width_lcu * pic_height_lcu;
+#if 0
+ int32_t MV_MEM_UNIT =
+ (lcu_size_log2 == 6) ? 0x200 :
+ ((lcu_size_log2 == 5) ? 0x80 : 0x20);
+#endif
+#ifdef MV_USE_FIXED_BUF
+ u32 mpred_mv_end = dec->work_space_buf->mpred_mv.buf_start +
+ dec->work_space_buf->mpred_mv.buf_size;
+#endif
+ u32 y_adr = 0;
+ int buf_size = 0;
+
+ int losless_comp_header_size =
+ compute_losless_comp_header_size(
+ dec, pic_width, pic_height);
+ int losless_comp_body_size = compute_losless_comp_body_size(
+ dec, pic_width,
+ pic_height, buf_alloc_depth == 10);
+ int mc_buffer_size = losless_comp_header_size + losless_comp_body_size;
+ int mc_buffer_size_h = (mc_buffer_size + 0xffff) >> 16;
+ int mc_buffer_size_u_v = 0;
+ int mc_buffer_size_u_v_h = 0;
+ int dw_mode = get_double_write_mode_init(dec);
+
+ if (dw_mode) {
+ int pic_width_dw = pic_width /
+ get_double_write_ratio(dec, dw_mode);
+ int pic_height_dw = pic_height /
+ 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) ?
+ pic_width_64_dw / lcu_size + 1
+ : pic_width_64_dw / lcu_size;
+ int pic_height_lcu_dw = (pic_height_32_dw % lcu_size) ?
+ pic_height_32_dw / lcu_size + 1
+ : pic_height_32_dw / lcu_size;
+ int lcu_total_dw = pic_width_lcu_dw * pic_height_lcu_dw;
+
+ mc_buffer_size_u_v = lcu_total_dw * lcu_size * lcu_size / 2;
+ mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16;
+ /*64k alignment*/
+ buf_size = ((mc_buffer_size_u_v_h << 16) * 3);
+ buf_size = ((buf_size + 0xffff) >> 16) << 16;
+ }
+ if (mc_buffer_size & 0xffff) /*64k alignment*/
+ mc_buffer_size_h += 1;
+#ifndef AVS2_10B_MMU
+ if ((dw_mode & 0x10) == 0)
+ buf_size += (mc_buffer_size_h << 16);
+#endif
+
+#ifdef AVS2_10B_MMU
+ 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
+
+ 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) {
+ 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
+ pic->mpred_mv_wr_start_addr =
+ dec->work_space_buf->mpred_mv.buf_start +
+ (pic->index * 0x120000);
+#else
+ pic->mpred_mv_wr_start_addr =
+ dec->work_space_buf->mpred_mv.buf_start +
+ ((pic->index * lcu_total)
+ * MV_MEM_UNIT);
+#endif
+#endif
+ if (debug) {
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "%s index %d BUF_index %d mc_y_adr %x ",
+ __func__, pic->index,
+ pic->BUF_index,
+ pic->mc_y_adr);
+ avs2_print_cont(dec, AVS2_DBG_BUFMGR,
+ "comp_body_size %x comp_buf_size %x ",
+ pic->comp_body_size,
+ pic->buf_size);
+ avs2_print_cont(dec, AVS2_DBG_BUFMGR,
+ "mpred_mv_wr_start_adr %d\n",
+ pic->mpred_mv_wr_start_addr);
+ avs2_print_cont(dec, AVS2_DBG_BUFMGR,
+ "dw_y_adr %d, pic->dw_u_v_adr =%d\n",
+ pic->dw_y_adr,
+ pic->dw_u_v_adr);
+ }
+ ret = 0;
+ }
+#ifdef MV_USE_FIXED_BUF
+ } else {
+ avs2_print(dec, 0,
+ "mv buffer alloc fail %x > %x\n",
+ dec->work_space_buf->mpred_mv.buf_start +
+ (((i + 1) * lcu_total) * MV_MEM_UNIT),
+ mpred_mv_end);
+ }
+#endif
+ return ret;
+}
+
+static void init_pic_list(struct AVS2Decoder_s *dec,
+ int32_t lcu_size_log2)
+{
+ int i;
+ struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+ struct avs2_frame_s *pic;
+#ifdef AVS2_10B_MMU
+ /*alloc AVS2 compress header first*/
+ 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), MMU_COMPRESS_HEADER_SIZE,
+ DRIVER_HEADER_NAME,
+ &buf_addr) < 0){
+ avs2_print(dec, 0,
+ "%s malloc compress header failed %d\n",
+ DRIVER_HEADER_NAME, i);
+ dec->fatal_error |= DECODER_FATAL_ERROR_NO_MEM;
+ return;
+ }
+ }
+#endif
+ for (i = 0; i < dec->used_buf_num; i++) {
+ if (i == (dec->used_buf_num - 1))
+ pic = avs2_dec->m_bg;
+ else
+ pic = avs2_dec->fref[i];
+ pic->index = i;
+ pic->BUF_index = -1;
+ pic->mv_buf_index = -1;
+ if (config_pic(dec, pic, lcu_size_log2) < 0) {
+ if (debug)
+ avs2_print(dec, 0,
+ "Config_pic %d fail\n",
+ pic->index);
+ pic->index = -1;
+ break;
+ }
+ pic->pic_w = avs2_dec->img.width;
+ pic->pic_h = avs2_dec->img.height;
+ }
+ for (; i < dec->used_buf_num; i++) {
+ if (i == (dec->used_buf_num - 1))
+ pic = avs2_dec->m_bg;
+ else
+ pic = avs2_dec->fref[i];
+ pic->index = -1;
+ pic->BUF_index = -1;
+ pic->mv_buf_index = -1;
+ }
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "%s ok, used_buf_num = %d\n",
+ __func__, dec->used_buf_num);
+ dec->pic_list_init_flag = 1;
+}
+
+
+static void init_pic_list_hw(struct AVS2Decoder_s *dec)
+{
+ int i;
+ struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+ struct avs2_frame_s *pic;
+ /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x0);*/
+ WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
+ (0x1 << 1) | (0x1 << 2));
+
+#ifdef DUAL_CORE_64
+ WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
+ (0x1 << 1) | (0x1 << 2));
+#endif
+ for (i = 0; i < dec->used_buf_num; i++) {
+ if (i == (dec->used_buf_num - 1))
+ pic = avs2_dec->m_bg;
+ else
+ pic = avs2_dec->fref[i];
+ if (pic->index < 0)
+ break;
+
+#ifdef AVS2_10B_MMU
+ /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
+ pic->header_adr
+ | (pic->mc_canvas_y << 8)|0x1);*/
+ WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->header_adr >> 5);
+#else
+ /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
+ pic->mc_y_adr
+ | (pic->mc_canvas_y << 8) | 0x1);*/
+ WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->mc_y_adr >> 5);
+#endif
+#ifndef LOSLESS_COMPRESS_MODE
+ /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
+ pic->mc_u_v_adr
+ | (pic->mc_canvas_u_v << 8)| 0x1);*/
+ WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic->mc_u_v_adr >> 5);
+#endif
+#ifdef DUAL_CORE_64
+#ifdef AVS2_10B_MMU
+ WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA,
+ pic->header_adr >> 5);
+#else
+ WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA,
+ pic->mc_y_adr >> 5);
+#endif
+#ifndef LOSLESS_COMPRESS_MODE
+ WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_DATA,
+ pic->mc_u_v_adr >> 5);
+#endif
+/*DUAL_CORE_64*/
+#endif
+ }
+ WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR, 0x1);
+#ifdef DUAL_CORE_64
+ WRITE_VREG(HEVC2_HEVCD_MPP_ANC2AXI_TBL_CONF_ADDR,
+ 0x1);
+#endif
+ /*Zero out canvas registers in IPP -- avoid simulation X*/
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+ (0 << 8) | (0 << 1) | 1);
+ for (i = 0; i < 32; i++) {
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
+#ifdef DUAL_CORE_64
+ WRITE_VREG(HEVC2_HEVCD_MPP_ANC_CANVAS_DATA_ADDR, 0);
+#endif
+ }
+}
+
+
+static void dump_pic_list(struct AVS2Decoder_s *dec)
+{
+#if 0
+ struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+ int i;
+ for (i = 0; i < FRAME_BUFFERS; i++) {
+ struct avs2_frame_s *pic =
+ avs2_dec->fref[i];
+ if (pic == NULL)
+ continue;
+ avs2_print(dec,
+ 0,
+ "Buf(%d) index %d mv_buf_index %d vf_ref %d dec_idx %d slice_type %d w/h %d/%d adr%ld\n",
+ i,
+ pic->index,
+#ifndef MV_USE_FIXED_BUF
+ pic->mv_buf_index,
+#else
+ -1,
+#endif
+ pic->vf_ref,
+ pic->decode_idx,
+ pic->slice_type,
+ pic->pic_w,
+ pic->pic_h,
+ pic->cma_alloc_addr
+ );
+ }
+#endif
+ return;
+}
+
+static int config_mc_buffer(struct AVS2Decoder_s *dec)
+{
+ int32_t i;
+ struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+ struct avs2_frame_s *pic;
+ /*if (avs2_dec->img.type == I_IMG)
+ return 0;
+ */
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "Entered config_mc_buffer....\n");
+ if (avs2_dec->f_bg != NULL) {
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "config_mc_buffer for background (canvas_y %d, canvas_u_v %d)\n",
+ avs2_dec->f_bg->mc_canvas_y, avs2_dec->f_bg->mc_canvas_u_v);
+ /*WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+ (7 << 8) | (0<<1) | 1); L0:BG */
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+ (15 << 8) | (0<<1) | 1); /* L0:BG*/
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+ (avs2_dec->f_bg->mc_canvas_u_v << 16) |
+ (avs2_dec->f_bg->mc_canvas_u_v << 8) |
+ avs2_dec->f_bg->mc_canvas_y);
+ /*WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+ (23 << 8) | (0<<1) | 1); L1:BG*/
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+ (31 << 8) | (0<<1) | 1); /* L1:BG*/
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+ (avs2_dec->f_bg->mc_canvas_u_v << 16) |
+ (avs2_dec->f_bg->mc_canvas_u_v << 8) |
+ avs2_dec->f_bg->mc_canvas_y);
+ }
+
+ if (avs2_dec->img.type == I_IMG)
+ return 0;
+
+ if (avs2_dec->img.type == P_IMG) {
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "config_mc_buffer for P_IMG, img type %d\n",
+ avs2_dec->img.type);
+ /*refer to prepare_RefInfo()*/
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+ (0 << 8) | (0<<1) | 1);
+ for (i = 0; i < avs2_dec->img.num_of_references; i++) {
+ pic = avs2_dec->fref[i];
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+ (pic->mc_canvas_u_v << 16) |
+ (pic->mc_canvas_u_v << 8) |
+ pic->mc_canvas_y);
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "refid %x mc_canvas_u_v %x mc_canvas_y %x\n",
+ i, pic->mc_canvas_u_v, pic->mc_canvas_y);
+ }
+ } else if (avs2_dec->img.type == F_IMG) {
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "config_mc_buffer for F_IMG, img type %d\n",
+ avs2_dec->img.type);
+ /*refer to prepare_RefInfo()*/
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+ (0 << 8) | (0<<1) | 1);
+ for (i = 0; i < avs2_dec->img.num_of_references; i++) {
+ pic = avs2_dec->fref[i];
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+ (pic->mc_canvas_u_v << 16) |
+ (pic->mc_canvas_u_v << 8) |
+ pic->mc_canvas_y);
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "refid %x mc_canvas_u_v %x mc_canvas_y %x\n",
+ i, pic->mc_canvas_u_v, pic->mc_canvas_y);
+ }
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+ (16 << 8) | (0<<1) | 1);
+ for (i = 0; i < avs2_dec->img.num_of_references; i++) {
+ pic = avs2_dec->fref[i];
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+ (pic->mc_canvas_u_v << 16) |
+ (pic->mc_canvas_u_v << 8) |
+ pic->mc_canvas_y);
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "refid %x mc_canvas_u_v %x mc_canvas_y %x\n",
+ i, pic->mc_canvas_u_v, pic->mc_canvas_y);
+ }
+ } else {
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "config_mc_buffer for B_IMG\n");
+ /*refer to prepare_RefInfo()*/
+ pic = avs2_dec->fref[1];
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+ (0 << 8) | (0<<1) | 1);
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+ (pic->mc_canvas_u_v << 16) |
+ (pic->mc_canvas_u_v << 8) |
+ pic->mc_canvas_y);
+
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "refid %x mc_canvas_u_v %x mc_canvas_y %x\n",
+ 1, pic->mc_canvas_u_v, pic->mc_canvas_y);
+
+ pic = avs2_dec->fref[0];
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+ (16 << 8) | (0<<1) | 1);
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR,
+ (pic->mc_canvas_u_v<<16) |
+ (pic->mc_canvas_u_v<<8) |
+ pic->mc_canvas_y);
+
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "refid %x mc_canvas_u_v %x mc_canvas_y %x\n",
+ 0, pic->mc_canvas_u_v, pic->mc_canvas_y);
+ }
+ return 0;
+}
+
+
+static void config_mcrcc_axi_hw(struct AVS2Decoder_s *dec)
+{
+ uint32_t rdata32;
+ uint32_t rdata32_2;
+ struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+
+ WRITE_VREG(HEVCD_MCRCC_CTL1, 0x2); /* reset mcrcc*/
+
+ if (avs2_dec->img.type == I_IMG) { /* I-PIC*/
+ /* remove reset -- disables clock */
+ WRITE_VREG(HEVCD_MCRCC_CTL1, 0x0);
+ return;
+ }
+
+ #if 0
+ mcrcc_get_hitrate();
+ decomp_get_hitrate();
+ decomp_get_comprate();
+ #endif
+
+ if ((avs2_dec->img.type == B_IMG) ||
+ (avs2_dec->img.type == F_IMG)) { /*B-PIC or F_PIC*/
+ /*Programme canvas0 */
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+ (0 << 8) | (0 << 1) | 0);
+ rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+ rdata32 = rdata32 & 0xffff;
+ rdata32 = rdata32 | (rdata32 << 16);
+ WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32);
+
+ /*Programme canvas1 */
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+ (16 << 8) | (1 << 1) | 0);
+ rdata32_2 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+ rdata32_2 = rdata32_2 & 0xffff;
+ rdata32_2 = rdata32_2 | (rdata32_2 << 16);
+ if (rdata32 == rdata32_2) {
+ rdata32_2 =
+ READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+ rdata32_2 = rdata32_2 & 0xffff;
+ rdata32_2 = rdata32_2 | (rdata32_2 << 16);
+ }
+ WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32_2);
+ } else { /* P-PIC */
+ WRITE_VREG(HEVCD_MPP_ANC_CANVAS_ACCCONFIG_ADDR,
+ (0 << 8) | (1 << 1) | 0);
+ rdata32 = READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+ rdata32 = rdata32 & 0xffff;
+ rdata32 = rdata32 | (rdata32 << 16);
+ WRITE_VREG(HEVCD_MCRCC_CTL2, rdata32);
+
+ /*Programme canvas1*/
+ rdata32 =
+ READ_VREG(HEVCD_MPP_ANC_CANVAS_DATA_ADDR);
+ rdata32 = rdata32 & 0xffff;
+ rdata32 = rdata32 | (rdata32 << 16);
+ WRITE_VREG(HEVCD_MCRCC_CTL3, rdata32);
+ }
+ /*enable mcrcc progressive-mode */
+ WRITE_VREG(HEVCD_MCRCC_CTL1, 0xff0);
+ return;
+}
+
+static void config_mpred_hw(struct AVS2Decoder_s *dec)
+{
+ uint32_t data32;
+ struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+ struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic;
+ struct avs2_frame_s *col_pic = avs2_dec->fref[0];
+ int32_t mpred_mv_rd_start_addr;
+ int32_t mpred_curr_lcu_x;
+ int32_t mpred_curr_lcu_y;
+ int32_t mpred_mv_rd_end_addr;
+ int32_t above_en;
+ int32_t mv_wr_en;
+ int32_t mv_rd_en;
+ int32_t col_isIntra;
+ int mv_mem_unit;
+ if (avs2_dec->img.type != I_IMG) {
+ above_en = 1;
+ mv_wr_en = 1;
+ mv_rd_en = 1;
+ col_isIntra = 0;
+ } else {
+ above_en = 1;
+ mv_wr_en = 1;
+ mv_rd_en = 0;
+ col_isIntra = 0;
+ }
+
+ mpred_mv_rd_start_addr =
+ col_pic->mpred_mv_wr_start_addr;
+ data32 = READ_VREG(HEVC_MPRED_CURR_LCU);
+ mpred_curr_lcu_x = data32 & 0xffff;
+ mpred_curr_lcu_y = (data32 >> 16) & 0xffff;
+
+ mv_mem_unit = avs2_dec->lcu_size_log2 == 6 ?
+ 0x200 : (avs2_dec->lcu_size_log2 == 5 ?
+ 0x80 : 0x20);
+
+ mpred_mv_rd_end_addr =
+ mpred_mv_rd_start_addr +
+ ((avs2_dec->lcu_x_num *
+ avs2_dec->lcu_y_num) * mv_mem_unit);
+
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "cur pic index %d col pic index %d\n",
+ cur_pic->index, col_pic->index);
+
+
+ WRITE_VREG(HEVC_MPRED_MV_WR_START_ADDR,
+ cur_pic->mpred_mv_wr_start_addr);
+ WRITE_VREG(HEVC_MPRED_MV_RD_START_ADDR,
+ col_pic->mpred_mv_wr_start_addr);
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "[MPRED CO_MV] write 0x%x read 0x%x\n",
+ cur_pic->mpred_mv_wr_start_addr,
+ col_pic->mpred_mv_wr_start_addr);
+
+ data32 =
+ ((avs2_dec->bk_img_is_top_field) << 13) |
+ ((avs2_dec->hd.background_picture_enable & 1) << 12) |
+ ((avs2_dec->hd.curr_RPS.num_of_ref & 7) << 8) |
+ ((avs2_dec->hd.b_pmvr_enabled & 1) << 6) |
+ ((avs2_dec->img.is_top_field & 1) << 5) |
+ ((avs2_dec->img.is_field_sequence & 1) << 4) |
+ ((avs2_dec->img.typeb & 7) << 1) |
+ (avs2_dec->hd.background_reference_enable & 0x1);
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "HEVC_MPRED_CTRL9 <= 0x%x(num of ref %d)\n",
+ data32, avs2_dec->hd.curr_RPS.num_of_ref);
+ WRITE_VREG(HEVC_MPRED_CTRL9, data32);
+
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "%s: dis %d %d %d %d %d %d %d fref0_ref_poc %d %d %d %d %d %d %d\n",
+ __func__,
+ avs2_dec->fref[0]->imgtr_fwRefDistance,
+ avs2_dec->fref[1]->imgtr_fwRefDistance,
+ avs2_dec->fref[2]->imgtr_fwRefDistance,
+ avs2_dec->fref[3]->imgtr_fwRefDistance,
+ avs2_dec->fref[4]->imgtr_fwRefDistance,
+ avs2_dec->fref[5]->imgtr_fwRefDistance,
+ avs2_dec->fref[6]->imgtr_fwRefDistance,
+ avs2_dec->fref[0]->ref_poc[0],
+ avs2_dec->fref[0]->ref_poc[1],
+ avs2_dec->fref[0]->ref_poc[2],
+ avs2_dec->fref[0]->ref_poc[3],
+ avs2_dec->fref[0]->ref_poc[4],
+ avs2_dec->fref[0]->ref_poc[5],
+ avs2_dec->fref[0]->ref_poc[6]
+ );
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "pic_distance %d, imgtr_next_P %d\n",
+ avs2_dec->img.pic_distance, avs2_dec->img.imgtr_next_P);
+
+
+ WRITE_VREG(HEVC_MPRED_CUR_POC, avs2_dec->img.pic_distance);
+ WRITE_VREG(HEVC_MPRED_COL_POC, avs2_dec->img.imgtr_next_P);
+
+ /*below MPRED Ref_POC_xx_Lx registers
+ must follow Ref_POC_xx_L0 ->
+ Ref_POC_xx_L1 in pair write order!!!*/
+ WRITE_VREG(HEVC_MPRED_L0_REF00_POC,
+ avs2_dec->fref[0]->imgtr_fwRefDistance);
+ WRITE_VREG(HEVC_MPRED_L1_REF00_POC,
+ avs2_dec->fref[0]->ref_poc[0]);
+
+ WRITE_VREG(HEVC_MPRED_L0_REF01_POC,
+ avs2_dec->fref[1]->imgtr_fwRefDistance);
+ WRITE_VREG(HEVC_MPRED_L1_REF01_POC,
+ avs2_dec->fref[0]->ref_poc[1]);
+
+ WRITE_VREG(HEVC_MPRED_L0_REF02_POC,
+ avs2_dec->fref[2]->imgtr_fwRefDistance);
+ WRITE_VREG(HEVC_MPRED_L1_REF02_POC,
+ avs2_dec->fref[0]->ref_poc[2]);
+
+ WRITE_VREG(HEVC_MPRED_L0_REF03_POC,
+ avs2_dec->fref[3]->imgtr_fwRefDistance);
+ WRITE_VREG(HEVC_MPRED_L1_REF03_POC,
+ avs2_dec->fref[0]->ref_poc[3]);
+
+ WRITE_VREG(HEVC_MPRED_L0_REF04_POC,
+ avs2_dec->fref[4]->imgtr_fwRefDistance);
+ WRITE_VREG(HEVC_MPRED_L1_REF04_POC,
+ avs2_dec->fref[0]->ref_poc[4]);
+
+ WRITE_VREG(HEVC_MPRED_L0_REF05_POC,
+ avs2_dec->fref[5]->imgtr_fwRefDistance);
+ WRITE_VREG(HEVC_MPRED_L1_REF05_POC,
+ avs2_dec->fref[0]->ref_poc[5]);
+
+ WRITE_VREG(HEVC_MPRED_L0_REF06_POC,
+ avs2_dec->fref[6]->imgtr_fwRefDistance);
+ WRITE_VREG(HEVC_MPRED_L1_REF06_POC,
+ avs2_dec->fref[0]->ref_poc[6]);
+
+
+ WRITE_VREG(HEVC_MPRED_MV_RD_END_ADDR,
+ mpred_mv_rd_end_addr);
+}
+
+static void config_dblk_hw(struct AVS2Decoder_s *dec)
+{
+ /*
+ * Picture level de-block parameter configuration here
+ */
+ struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+ union param_u *rpm_param = &avs2_dec->param;
+ uint32_t data32;
+
+ data32 = READ_VREG(HEVC_DBLK_CFG1);
+ data32 = (((data32 >> 20) & 0xfff) << 20) |
+ (((avs2_dec->input.sample_bit_depth == 10)
+ ? 0xa : 0x0) << 16) | /*[16 +: 4]: {luma_bd[1:0],
+ chroma_bd[1:0]}*/
+ (((data32 >> 2) & 0x3fff) << 2) |
+ (((rpm_param->p.lcu_size == 6)
+ ? 0 : (rpm_param->p.lcu_size == 5)
+ ? 1 : 2) << 0);/*[ 0 +: 2]: lcu_size*/
+ WRITE_VREG(HEVC_DBLK_CFG1, data32);
+
+ data32 = (avs2_dec->img.height << 16) |
+ avs2_dec->img.width;
+ WRITE_VREG(HEVC_DBLK_CFG2, data32);
+ /*
+ [27 +: 1]: cross_slice_loopfilter_enable_flag
+ [26 +: 1]: loop_filter_disable
+ [25 +: 1]: useNSQT
+ [22 +: 3]: imgtype
+ [17 +: 5]: alpha_c_offset (-8~8)
+ [12 +: 5]: beta_offset (-8~8)
+ [ 6 +: 6]: chroma_quant_param_delta_u (-16~16)
+ [ 0 +: 6]: chroma_quant_param_delta_v (-16~16)
+ */
+ data32 = ((avs2_dec->input.crossSliceLoopFilter
+ & 0x1) << 27) |
+ ((rpm_param->p.loop_filter_disable & 0x1) << 26) |
+ ((avs2_dec->input.useNSQT & 0x1) << 25) |
+ ((avs2_dec->img.type & 0x7) << 22) |
+ ((rpm_param->p.alpha_c_offset & 0x1f) << 17) |
+ ((rpm_param->p.beta_offset & 0x1f) << 12) |
+ ((rpm_param->p.chroma_quant_param_delta_cb & 0x3f) << 6) |
+ ((rpm_param->p.chroma_quant_param_delta_cr & 0x3f) << 0);
+
+ WRITE_VREG(HEVC_DBLK_CFG9, data32);
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "[c] cfgDBLK: crossslice(%d),lfdisable(%d),bitDepth(%d),lcuSize(%d),NSQT(%d)\n",
+ avs2_dec->input.crossSliceLoopFilter,
+ rpm_param->p.loop_filter_disable,
+ avs2_dec->input.sample_bit_depth,
+ avs2_dec->lcu_size,
+ avs2_dec->input.useNSQT);
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "[c] cfgDBLK: alphaCOffset(%d),betaOffset(%d),quantDeltaCb(%d),quantDeltaCr(%d)\n",
+ rpm_param->p.alpha_c_offset,
+ rpm_param->p.beta_offset,
+ rpm_param->p.chroma_quant_param_delta_cb,
+ rpm_param->p.chroma_quant_param_delta_cr);
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "[c] cfgDBLK: .done.\n");
+}
+
+static void config_sao_hw(struct AVS2Decoder_s *dec)
+{
+ uint32_t data32;
+ struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+ struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic;
+
+ int lcu_size = 64;
+ int mc_buffer_size_u_v =
+ cur_pic->lcu_total * lcu_size*lcu_size/2;
+ int mc_buffer_size_u_v_h =
+ (mc_buffer_size_u_v + 0xffff) >> 16;/*64k alignment*/
+
+ data32 = READ_VREG(HEVC_SAO_CTRL0);
+ data32 &= (~0xf);
+ data32 |= avs2_dec->lcu_size_log2;
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "%s, lcu_size_log2 = %d, config HEVC_SAO_CTRL0 0x%x\n",
+ __func__,
+ avs2_dec->lcu_size_log2,
+ data32);
+
+ WRITE_VREG(HEVC_SAO_CTRL0, data32);
+
+#ifndef AVS2_10B_MMU
+ if ((get_double_write_mode(dec) & 0x10) == 0)
+ WRITE_VREG(HEVC_CM_BODY_START_ADDR, cur_pic->mc_y_adr);
+#endif
+ if (get_double_write_mode(dec)) {
+ WRITE_VREG(HEVC_SAO_Y_START_ADDR, cur_pic->dw_y_adr);
+ WRITE_VREG(HEVC_SAO_C_START_ADDR, cur_pic->dw_u_v_adr);
+ WRITE_VREG(HEVC_SAO_Y_WPTR, cur_pic->dw_y_adr);
+ WRITE_VREG(HEVC_SAO_C_WPTR, cur_pic->dw_u_v_adr);
+ } else {
+ WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff);
+ WRITE_VREG(HEVC_SAO_C_START_ADDR, 0xffffffff);
+ }
+#ifdef AVS2_10B_MMU
+ WRITE_VREG(HEVC_CM_HEADER_START_ADDR, cur_pic->header_adr);
+#endif
+ data32 = (mc_buffer_size_u_v_h << 16) << 1;
+ /*pr_info("data32=%x,mc_buffer_size_u_v_h=%x,lcu_total=%x\n",
+ data32, mc_buffer_size_u_v_h, cur_pic->lcu_total);*/
+ WRITE_VREG(HEVC_SAO_Y_LENGTH, data32);
+
+ data32 = (mc_buffer_size_u_v_h << 16);
+ WRITE_VREG(HEVC_SAO_C_LENGTH, data32);
+
+#ifdef AVS2_10B_NV21
+#ifdef DOS_PROJECT
+ data32 = READ_VREG(HEVC_SAO_CTRL1);
+ data32 &= (~0x3000);
+ /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/
+ data32 |= (MEM_MAP_MODE << 12);
+ data32 &= (~0x3);
+ data32 |= 0x1; /* [1]:dw_disable [0]:cm_disable*/
+ WRITE_VREG(HEVC_SAO_CTRL1, data32);
+ /*[23:22] dw_v1_ctrl [21:20] dw_v0_ctrl [19:18] dw_h1_ctrl
+ [17:16] dw_h0_ctrl*/
+ data32 = READ_VREG(HEVC_SAO_CTRL5);
+ /*set them all 0 for H265_NV21 (no down-scale)*/
+ data32 &= ~(0xff << 16);
+ WRITE_VREG(HEVC_SAO_CTRL5, data32);
+ ata32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
+ data32 &= (~0x30);
+ /*[5:4] address_format 00:linear 01:32x32 10:64x32*/
+ data32 |= (MEM_MAP_MODE << 4);
+ WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32);
+#else
+ /*m8baby test1902*/
+ data32 = READ_VREG(HEVC_SAO_CTRL1);
+ data32 &= (~0x3000);
+ /*[13:12] axi_aformat, 0-Linear, 1-32x32, 2-64x32*/
+ data32 |= (MEM_MAP_MODE << 12);
+ data32 &= (~0xff0);
+ /*data32 |= 0x670;*/ /*Big-Endian per 64-bit*/
+ data32 |= 0x880; /*.Big-Endian per 64-bit */
+ data32 &= (~0x3);
+ data32 |= 0x1; /*[1]:dw_disable [0]:cm_disable*/
+ WRITE_VREG(HEVC_SAO_CTRL1, data32);
+ /* [23:22] dw_v1_ctrl [21:20] dw_v0_ctrl
+ [19:18] dw_h1_ctrl [17:16] dw_h0_ctrl*/
+ data32 = READ_VREG(HEVC_SAO_CTRL5);
+ /* set them all 0 for H265_NV21 (no down-scale)*/
+ data32 &= ~(0xff << 16);
+ WRITE_VREG(HEVC_SAO_CTRL5, data32);
+
+ 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*/
+ WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32);
+#endif
+#else
+ data32 = READ_VREG(HEVC_SAO_CTRL1);
+ data32 &= (~0x3000);
+ data32 |= (MEM_MAP_MODE <<
+ 12); /* [13:12] axi_aformat, 0-Linear,
+ 1-32x32, 2-64x32 */
+ data32 &= (~0xff0);
+ /* data32 |= 0x670; // Big-Endian per 64-bit */
+ data32 |= endian; /* Big-Endian per 64-bit */
+ data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/
+#if 0
+ if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) {
+ if (get_double_write_mode(dec) == 0)
+ data32 |= 0x2; /*disable double write*/
+#ifndef AVS2_10B_MMU
+ else
+ if (get_double_write_mode(dec) & 0x10)
+ data32 |= 0x1; /*disable cm*/
+#endif
+ }
+#endif
+ WRITE_VREG(HEVC_SAO_CTRL1, data32);
+
+ if (get_double_write_mode(dec) & 0x10) {
+ /* [23:22] dw_v1_ctrl
+ [21:20] dw_v0_ctrl
+ [19:18] dw_h1_ctrl
+ [17:16] dw_h0_ctrl
+ */
+ data32 = READ_VREG(HEVC_SAO_CTRL5);
+ /*set them all 0 for H265_NV21 (no down-scale)*/
+ data32 &= ~(0xff << 16);
+ WRITE_VREG(HEVC_SAO_CTRL5, data32);
+ } else {
+ data32 = READ_VREG(HEVC_SAO_CTRL5);
+ data32 &= (~(0xff << 16));
+ if (get_double_write_mode(dec) == 2 ||
+ get_double_write_mode(dec) == 3)
+ data32 |= (0xff<<16);
+ else if (get_double_write_mode(dec) == 4)
+ data32 |= (0x33<<16);
+ WRITE_VREG(HEVC_SAO_CTRL5, data32);
+ }
+
+ data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
+ data32 &= (~0x30);
+ /* [5:4] -- address_format 00:linear 01:32x32 10:64x32 */
+ data32 |= (mem_map_mode <<
+ 4);
+ data32 &= (~0xF);
+ data32 |= 0xf; /* valid only when double write only */
+ /*data32 |= 0x8;*/ /* Big-Endian per 64-bit */
+ WRITE_VREG(HEVCD_IPP_AXIIF_CONFIG, data32);
+#endif
+}
+
+static void reconstructCoefficients(struct AVS2Decoder_s *dec,
+ struct ALFParam_s *alfParam)
+{
+ int32_t g, sum, i, coeffPred;
+ for (g = 0; g < alfParam->filters_per_group; g++) {
+ sum = 0;
+ for (i = 0; i < alfParam->num_coeff - 1; i++) {
+ sum += (2 * alfParam->coeffmulti[g][i]);
+ dec->m_filterCoeffSym[g][i] =
+ alfParam->coeffmulti[g][i];
+ /*pr_info("[t] dec->m_filterCoeffSym[%d][%d]=0x%x\n",
+ g, i, dec->m_filterCoeffSym[g][i]);*/
+ }
+ coeffPred = (1 << ALF_NUM_BIT_SHIFT) - sum;
+ dec->m_filterCoeffSym[g][alfParam->num_coeff - 1]
+ = coeffPred +
+ alfParam->coeffmulti[g][alfParam->num_coeff - 1];
+ /*pr_info("[t] dec->m_filterCoeffSym[%d][%d]=0x%x\n",
+ g, (alfParam->num_coeff - 1),
+ dec->m_filterCoeffSym[g][alfParam->num_coeff - 1]);*/
+ }
+}
+
+static void reconstructCoefInfo(struct AVS2Decoder_s *dec,
+ int32_t compIdx, struct ALFParam_s *alfParam)
+{
+ int32_t i;
+ if (compIdx == ALF_Y) {
+ if (alfParam->filters_per_group > 1) {
+ for (i = 1; i < NO_VAR_BINS; ++i) {
+ if (alfParam->filterPattern[i])
+ dec->m_varIndTab[i] =
+ dec->m_varIndTab[i - 1] + 1;
+ else
+ dec->m_varIndTab[i] =
+ dec->m_varIndTab[i - 1];
+ }
+ }
+ }
+ reconstructCoefficients(dec, alfParam);
+}
+
+static void config_alf_hw(struct AVS2Decoder_s *dec)
+{
+ /*
+ * Picture level ALF parameter configuration here
+ */
+ uint32_t data32;
+ int32_t i, j;
+ int32_t m_filters_per_group;
+ struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+ struct ALFParam_s *m_alfPictureParam_y =
+ &avs2_dec->m_alfPictureParam[0];
+ struct ALFParam_s *m_alfPictureParam_cb =
+ &avs2_dec->m_alfPictureParam[1];
+ struct ALFParam_s *m_alfPictureParam_cr =
+ &avs2_dec->m_alfPictureParam[2];
+
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "[t]alfy,cidx(%d),flag(%d),filters_per_group(%d),filterPattern[0]=0x%x,[15]=0x%x\n",
+ m_alfPictureParam_y->componentID,
+ m_alfPictureParam_y->alf_flag,
+ m_alfPictureParam_y->filters_per_group,
+ m_alfPictureParam_y->filterPattern[0],
+ m_alfPictureParam_y->filterPattern[15]);
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "[t]alfy,num_coeff(%d),coeffmulti[0][0]=0x%x,[0][1]=0x%x,[1][0]=0x%x,[1][1]=0x%x\n",
+ m_alfPictureParam_y->num_coeff,
+ m_alfPictureParam_y->coeffmulti[0][0],
+ m_alfPictureParam_y->coeffmulti[0][1],
+ m_alfPictureParam_y->coeffmulti[1][0],
+ m_alfPictureParam_y->coeffmulti[1][1]);
+
+ /*Cr*/
+ for (i = 0; i < 16; i++)
+ dec->m_varIndTab[i] = 0;
+ for (j = 0; j < 16; j++)
+ for (i = 0; i < 9; i++)
+ dec->m_filterCoeffSym[j][i] = 0;
+ reconstructCoefInfo(dec, 2, m_alfPictureParam_cr);
+ data32 =
+ ((dec->m_filterCoeffSym[0][4] & 0xf) << 28) |
+ ((dec->m_filterCoeffSym[0][3] & 0x7f) << 21) |
+ ((dec->m_filterCoeffSym[0][2] & 0x7f) << 14) |
+ ((dec->m_filterCoeffSym[0][1] & 0x7f) << 7) |
+ ((dec->m_filterCoeffSym[0][0] & 0x7f) << 0);
+ WRITE_VREG(HEVC_DBLK_CFGD, data32);
+ data32 =
+ ((dec->m_filterCoeffSym[0][8] & 0x7f) << 24) |
+ ((dec->m_filterCoeffSym[0][7] & 0x7f) << 17) |
+ ((dec->m_filterCoeffSym[0][6] & 0x7f) << 10) |
+ ((dec->m_filterCoeffSym[0][5] & 0x7f) << 3) |
+ (((dec->m_filterCoeffSym[0][4] >> 4) & 0x7) << 0);
+ WRITE_VREG(HEVC_DBLK_CFGD, data32);
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "[c] pic_alf_on_cr(%d), alf_cr_coef(%d %d %d %d %d %d %d %d %d)\n",
+ m_alfPictureParam_cr->alf_flag,
+ dec->m_filterCoeffSym[0][0],
+ dec->m_filterCoeffSym[0][1],
+ dec->m_filterCoeffSym[0][2],
+ dec->m_filterCoeffSym[0][3],
+ dec->m_filterCoeffSym[0][4],
+ dec->m_filterCoeffSym[0][5],
+ dec->m_filterCoeffSym[0][6],
+ dec->m_filterCoeffSym[0][7],
+ dec->m_filterCoeffSym[0][8]);
+
+ /* Cb*/
+ for (j = 0; j < 16; j++)
+ for (i = 0; i < 9; i++)
+ dec->m_filterCoeffSym[j][i] = 0;
+ reconstructCoefInfo(dec, 1, m_alfPictureParam_cb);
+ data32 =
+ ((dec->m_filterCoeffSym[0][4] & 0xf) << 28) |
+ ((dec->m_filterCoeffSym[0][3] & 0x7f) << 21) |
+ ((dec->m_filterCoeffSym[0][2] & 0x7f) << 14) |
+ ((dec->m_filterCoeffSym[0][1] & 0x7f) << 7) |
+ ((dec->m_filterCoeffSym[0][0] & 0x7f) << 0);
+ WRITE_VREG(HEVC_DBLK_CFGD, data32);
+ data32 =
+ ((dec->m_filterCoeffSym[0][8] & 0x7f) << 24) |
+ ((dec->m_filterCoeffSym[0][7] & 0x7f) << 17) |
+ ((dec->m_filterCoeffSym[0][6] & 0x7f) << 10) |
+ ((dec->m_filterCoeffSym[0][5] & 0x7f) << 3) |
+ (((dec->m_filterCoeffSym[0][4] >> 4) & 0x7) << 0);
+ WRITE_VREG(HEVC_DBLK_CFGD, data32);
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "[c] pic_alf_on_cb(%d), alf_cb_coef(%d %d %d %d %d %d %d %d %d)\n",
+ m_alfPictureParam_cb->alf_flag,
+ dec->m_filterCoeffSym[0][0],
+ dec->m_filterCoeffSym[0][1],
+ dec->m_filterCoeffSym[0][2],
+ dec->m_filterCoeffSym[0][3],
+ dec->m_filterCoeffSym[0][4],
+ dec->m_filterCoeffSym[0][5],
+ dec->m_filterCoeffSym[0][6],
+ dec->m_filterCoeffSym[0][7],
+ dec->m_filterCoeffSym[0][8]);
+
+ /* Y*/
+ for (j = 0; j < 16; j++)
+ for (i = 0; i < 9; i++)
+ dec->m_filterCoeffSym[j][i] = 0;
+ reconstructCoefInfo(dec, 0, m_alfPictureParam_y);
+ data32 =
+ ((dec->m_varIndTab[7] & 0xf) << 28) |
+ ((dec->m_varIndTab[6] & 0xf) << 24) |
+ ((dec->m_varIndTab[5] & 0xf) << 20) |
+ ((dec->m_varIndTab[4] & 0xf) << 16) |
+ ((dec->m_varIndTab[3] & 0xf) << 12) |
+ ((dec->m_varIndTab[2] & 0xf) << 8) |
+ ((dec->m_varIndTab[1] & 0xf) << 4) |
+ ((dec->m_varIndTab[0] & 0xf) << 0);
+ WRITE_VREG(HEVC_DBLK_CFGD, data32);
+ data32 = ((dec->m_varIndTab[15] & 0xf) << 28) |
+ ((dec->m_varIndTab[14] & 0xf) << 24) |
+ ((dec->m_varIndTab[13] & 0xf) << 20) |
+ ((dec->m_varIndTab[12] & 0xf) << 16) |
+ ((dec->m_varIndTab[11] & 0xf) << 12) |
+ ((dec->m_varIndTab[10] & 0xf) << 8) |
+ ((dec->m_varIndTab[9] & 0xf) << 4) |
+ ((dec->m_varIndTab[8] & 0xf) << 0);
+ WRITE_VREG(HEVC_DBLK_CFGD, data32);
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "[c] pic_alf_on_y(%d), alf_y_tab(%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)\n",
+ m_alfPictureParam_y->alf_flag,
+ dec->m_varIndTab[0],
+ dec->m_varIndTab[1],
+ dec->m_varIndTab[2],
+ dec->m_varIndTab[3],
+ dec->m_varIndTab[4],
+ dec->m_varIndTab[5],
+ dec->m_varIndTab[6],
+ dec->m_varIndTab[7],
+ dec->m_varIndTab[8],
+ dec->m_varIndTab[9],
+ dec->m_varIndTab[10],
+ dec->m_varIndTab[11],
+ dec->m_varIndTab[12],
+ dec->m_varIndTab[13],
+ dec->m_varIndTab[14],
+ dec->m_varIndTab[15]);
+
+ m_filters_per_group =
+ (m_alfPictureParam_y->alf_flag == 0) ?
+ 1 : m_alfPictureParam_y->filters_per_group;
+ for (i = 0; i < m_filters_per_group; i++) {
+ data32 =
+ ((dec->m_filterCoeffSym[i][4] & 0xf) << 28) |
+ ((dec->m_filterCoeffSym[i][3] & 0x7f) << 21) |
+ ((dec->m_filterCoeffSym[i][2] & 0x7f) << 14) |
+ ((dec->m_filterCoeffSym[i][1] & 0x7f) << 7) |
+ ((dec->m_filterCoeffSym[i][0] & 0x7f) << 0);
+ WRITE_VREG(HEVC_DBLK_CFGD, data32);
+ data32 =
+ /*[31] last indication*/
+ ((i == m_filters_per_group-1) << 31) |
+ ((dec->m_filterCoeffSym[i][8] & 0x7f) << 24) |
+ ((dec->m_filterCoeffSym[i][7] & 0x7f) << 17) |
+ ((dec->m_filterCoeffSym[i][6] & 0x7f) << 10) |
+ ((dec->m_filterCoeffSym[i][5] & 0x7f) << 3) |
+ (((dec->m_filterCoeffSym[i][4] >> 4) & 0x7) << 0);
+ WRITE_VREG(HEVC_DBLK_CFGD, data32);
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "[c] alf_y_coef[%d](%d %d %d %d %d %d %d %d %d)\n",
+ i, dec->m_filterCoeffSym[i][0],
+ dec->m_filterCoeffSym[i][1],
+ dec->m_filterCoeffSym[i][2],
+ dec->m_filterCoeffSym[i][3],
+ dec->m_filterCoeffSym[i][4],
+ dec->m_filterCoeffSym[i][5],
+ dec->m_filterCoeffSym[i][6],
+ dec->m_filterCoeffSym[i][7],
+ dec->m_filterCoeffSym[i][8]);
+ }
+ avs2_print(dec, AVS2_DBG_BUFMGR_DETAIL,
+ "[c] cfgALF .done.\n");
+}
+
+static void config_other_hw(struct AVS2Decoder_s *dec)
+{
+ uint32_t data32;
+ struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+ struct avs2_frame_s *cur_pic = avs2_dec->hc.cur_pic;
+ int bit_depth = cur_pic->bit_depth;
+ int losless_comp_header_size =
+ compute_losless_comp_header_size(
+ dec, cur_pic->pic_w,
+ cur_pic->pic_h);
+ int losless_comp_body_size =
+ compute_losless_comp_body_size(
+ dec, cur_pic->pic_w,
+ cur_pic->pic_h, (bit_depth == AVS2_BITS_10));
+ cur_pic->comp_body_size = losless_comp_body_size;
+
+#ifdef LOSLESS_COMPRESS_MODE
+ data32 = READ_VREG(HEVC_SAO_CTRL5);
+ if (bit_depth == AVS2_BITS_10)
+ data32 &= ~(1 << 9);
+ else
+ data32 |= (1 << 9);
+
+ WRITE_VREG(HEVC_SAO_CTRL5, data32);
+
+#ifdef AVS2_10B_MMU
+ /*bit[4] : paged_mem_mode*/
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4));
+#else
+ /*bit[3] smem mdoe*/
+ if (bit_depth == AVS2_BITS_10)
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0 << 3));
+ else
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (1 << 3));
+#endif
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5));
+ /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/
+ WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size);
+ WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size);
+ WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size);
+#else
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
+#endif
+}
+
+static void avs2_config_work_space_hw(struct AVS2Decoder_s *dec)
+{
+ struct BuffInfo_s *buf_spec = dec->work_space_buf;
+#ifdef LOSLESS_COMPRESS_MODE
+ int losless_comp_header_size =
+ compute_losless_comp_header_size(
+ dec, dec->init_pic_w,
+ dec->init_pic_h);
+ int losless_comp_body_size =
+ compute_losless_comp_body_size(dec,
+ dec->init_pic_w,
+ dec->init_pic_h, buf_alloc_depth == 10);
+#endif
+#ifdef AVS2_10B_MMU
+ unsigned int data32;
+#endif
+ if (debug && dec->init_flag == 0)
+ avs2_print(dec, 0,
+ "%s %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
+ __func__,
+ buf_spec->ipp.buf_start,
+ buf_spec->start_adr,
+ buf_spec->short_term_rps.buf_start,
+ buf_spec->rcs.buf_start,
+ buf_spec->sps.buf_start,
+ buf_spec->pps.buf_start,
+ buf_spec->sao_up.buf_start,
+ buf_spec->swap_buf.buf_start,
+ buf_spec->swap_buf2.buf_start,
+ buf_spec->scalelut.buf_start,
+ buf_spec->dblk_para.buf_start,
+ buf_spec->dblk_data.buf_start,
+ buf_spec->dblk_data2.buf_start);
+ WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, buf_spec->ipp.buf_start);
+ if ((debug & AVS2_DBG_SEND_PARAM_WITH_REG) == 0)
+ WRITE_VREG(HEVC_RPM_BUFFER, (u32)dec->rpm_phy_addr);
+ WRITE_VREG(HEVC_SHORT_TERM_RPS, buf_spec->short_term_rps.buf_start);
+ WRITE_VREG(HEVC_RCS_BUFFER, buf_spec->rcs.buf_start);
+ WRITE_VREG(HEVC_SPS_BUFFER, buf_spec->sps.buf_start);
+ WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start);
+ WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start);
+#ifdef AVS2_10B_MMU
+ WRITE_VREG(AVS2_MMU_MAP_BUFFER, dec->frame_mmu_map_phy_addr);
+#else
+ WRITE_VREG(HEVC_STREAM_SWAP_BUFFER, buf_spec->swap_buf.buf_start);
+#endif
+ WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, buf_spec->swap_buf2.buf_start);
+ WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start);
+
+ /* cfg_p_addr */
+ WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start);
+ /* cfg_d_addr */
+ WRITE_VREG(HEVC_DBLK_CFG5, buf_spec->dblk_data.buf_start);
+
+ WRITE_VREG(HEVC_DBLK_CFGE, buf_spec->dblk_data2.buf_start);
+
+#ifdef LOSLESS_COMPRESS_MODE
+ data32 = READ_VREG(HEVC_SAO_CTRL5);
+#if 1
+ data32 &= ~(1<<9);
+#else
+ if (params->p.bit_depth != 0x00)
+ data32 &= ~(1<<9);
+ else
+ data32 |= (1<<9);
+#endif
+ WRITE_VREG(HEVC_SAO_CTRL5, data32);
+#ifdef AVS2_10B_MMU
+ /*bit[4] : paged_mem_mode*/
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4));
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0);
+#else
+ /* bit[3] smem mode*/
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0<<3));
+
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5));
+#endif
+ /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL2,(losless_comp_body_size >> 5));*/
+ /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/
+/*8-bit mode */
+ WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size);
+ WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size);
+ WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size);
+#else
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
+#endif
+
+#ifdef AVS2_10B_MMU
+ WRITE_VREG(HEVC_SAO_MMU_VH0_ADDR, buf_spec->mmu_vbh.buf_start);
+ WRITE_VREG(HEVC_SAO_MMU_VH1_ADDR, buf_spec->mmu_vbh.buf_start
+ + buf_spec->mmu_vbh.buf_size/2);
+ /*data32 = READ_VREG(HEVC_SAO_CTRL9);*/
+ /*data32 |= 0x1;*/
+ /*WRITE_VREG(HEVC_SAO_CTRL9, data32);*/
+
+ /* use HEVC_CM_HEADER_START_ADDR */
+ data32 = READ_VREG(HEVC_SAO_CTRL5);
+ data32 |= (1<<10);
+ WRITE_VREG(HEVC_SAO_CTRL5, data32);
+
+#endif
+
+ WRITE_VREG(LMEM_DUMP_ADR, (u32)dec->lmem_phy_addr);
+
+}
+
+static void avs2_init_decoder_hw(struct AVS2Decoder_s *dec)
+{
+ unsigned int data32;
+ int i;
+
+ /*if (debug & AVS2_DBG_BUFMGR_MORE)
+ pr_info("%s\n", __func__);*/
+ data32 = READ_VREG(HEVC_PARSER_INT_CONTROL);
+#if 1
+ /* set bit 31~29 to 3 if HEVC_STREAM_FIFO_CTL[29] is 1 */
+ data32 &= ~(7 << 29);
+ data32 |= (3 << 29);
+#endif
+ data32 = data32 |
+ (1 << 24) |/*stream_buffer_empty_int_amrisc_enable*/
+ (1 << 22) |/*stream_fifo_empty_int_amrisc_enable*/
+ (1 << 7) |/*dec_done_int_cpu_enable*/
+ (1 << 4) |/*startcode_found_int_cpu_enable*/
+ (0 << 3) |/*startcode_found_int_amrisc_enable*/
+ (1 << 0) /*parser_int_enable*/
+ ;
+ WRITE_VREG(HEVC_PARSER_INT_CONTROL, data32);
+
+ data32 = READ_VREG(HEVC_SHIFT_STATUS);
+ data32 = data32 |
+ (0 << 1) |/*emulation_check_off VP9
+ do not have emulation*/
+ (1 << 0)/*startcode_check_on*/
+ ;
+ WRITE_VREG(HEVC_SHIFT_STATUS, data32);
+ WRITE_VREG(HEVC_SHIFT_CONTROL,
+ (6 << 20) | /* emu_push_bits (6-bits for AVS2)*/
+ (0 << 19) | /* emu_3_enable, maybe turned on in microcode*/
+ (0 << 18) | /* emu_2_enable, maybe turned on in microcode*/
+ (0 << 17) | /* emu_1_enable, maybe turned on in microcode*/
+ (0 << 16) | /* emu_0_enable, maybe turned on in microcode*/
+ (0 << 14) | /*disable_start_code_protect*/
+ (3 << 6) | /* sft_valid_wr_position*/
+ (2 << 4) | /* emulate_code_length_sub_1*/
+ (2 << 1) | /* start_code_length_sub_1*/
+ (1 << 0) /* stream_shift_enable*/
+ );
+
+ WRITE_VREG(HEVC_SHIFT_LENGTH_PROTECT,
+ (0 << 30) | /*data_protect_fill_00_enable*/
+ (1 << 29) /*data_protect_fill_ff_enable*/
+ );
+ WRITE_VREG(HEVC_CABAC_CONTROL,
+ (1 << 0)/*cabac_enable*/
+ );
+
+ WRITE_VREG(HEVC_PARSER_CORE_CONTROL,
+ (1 << 0)/* hevc_parser_core_clk_en*/
+ );
+
+
+ WRITE_VREG(HEVC_DEC_STATUS_REG, 0);
+
+ /*Initial IQIT_SCALELUT memory -- just to avoid X in simulation*/
+
+ WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);/*cfg_p_addr*/
+ for (i = 0; i < 1024; i++)
+ WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0);
+
+
+#ifdef ENABLE_SWAP_TEST
+ WRITE_VREG(HEVC_STREAM_SWAP_TEST, 100);
+#else
+ WRITE_VREG(HEVC_STREAM_SWAP_TEST, 0);
+#endif
+ if (!dec->m_ins_flag)
+ WRITE_VREG(DECODE_MODE, DECODE_MODE_SINGLE);
+ else if (vdec_frame_based(hw_to_vdec(dec)))
+ WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_FRAMEBASE);
+ else
+ WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_STREAMBASE);
+ WRITE_VREG(HEVC_DECODE_SIZE, 0);
+ WRITE_VREG(HEVC_DECODE_COUNT, 0);
+
+ /*Send parser_cmd*/
+ WRITE_VREG(HEVC_PARSER_CMD_WRITE, (1 << 16) | (0 << 0));
+ for (i = 0; i < PARSER_CMD_NUMBER; i++)
+ WRITE_VREG(HEVC_PARSER_CMD_WRITE, parser_cmd[i]);
+ WRITE_VREG(HEVC_PARSER_CMD_SKIP_0, PARSER_CMD_SKIP_CFG_0);
+ WRITE_VREG(HEVC_PARSER_CMD_SKIP_1, PARSER_CMD_SKIP_CFG_1);
+ WRITE_VREG(HEVC_PARSER_CMD_SKIP_2, PARSER_CMD_SKIP_CFG_2);
+
+
+ WRITE_VREG(HEVC_PARSER_IF_CONTROL,
+ (1 << 9) | /* parser_alf_if_en*/
+ /* (1 << 8) |*/ /*sao_sw_pred_enable*/
+ (1 << 5) | /*parser_sao_if_en*/
+ (1 << 2) | /*parser_mpred_if_en*/
+ (1 << 0) /*parser_scaler_if_en*/
+ );
+ /*Changed to Start MPRED in microcode*/
+ /*
+ pr_info("[test.c] Start MPRED\n");
+ WRITE_VREG(HEVC_MPRED_INT_STATUS,
+ (1<<31)
+ );
+ */
+
+ /*AVS2 default seq_wq_matrix config*/
+
+ avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+ "Config AVS2 default seq_wq_matrix ...\n");
+ /*4x4*/
+ /* default seq_wq_matrix_4x4 begin address*/
+ WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 64);
+ for (i = 0; i < 16; i++)
+ WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, g_WqMDefault4x4[i]);
+
+ /*8x8*/
+ /*default seq_wq_matrix_8x8 begin address*/
+ WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);
+ for (i = 0; i < 64; i++)
+ WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, g_WqMDefault8x8[i]);
+
+
+ WRITE_VREG(HEVCD_IPP_TOP_CNTL,
+ (0 << 1) | /*enable ipp*/
+ (1 << 0) /*software reset ipp and mpp*/
+ );
+ WRITE_VREG(HEVCD_IPP_TOP_CNTL,
+ (1 << 1) | /*enable ipp*/
+ (0 << 0) /*software reset ipp and mpp*/
+ );
+#if 0
+/*AVS2_10B_NV21*/
+ /*Enable NV21 reference read mode for MC*/
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
+#endif
+ /* Init dblk*/
+ data32 = READ_VREG(HEVC_DBLK_CFGB);
+ data32 |= (2 << 0);
+ /* [3:0] cfg_video_type -> AVS2*/
+
+ data32 &= (~0x300); /*[8]:first write enable (compress)
+ [9]:double write enable (uncompress)*/
+ if (get_double_write_mode(dec) == 0)
+ data32 |= (0x1 << 8); /*enable first write*/
+ else if (get_double_write_mode(dec) == 0x10)
+ data32 |= (0x1 << 9); /*double write only*/
+ else
+ data32 |= ((0x1 << 8) |(0x1 << 9));
+ WRITE_VREG(HEVC_DBLK_CFGB, data32);
+
+ WRITE_VREG(HEVC_DBLK_CFG0, (1 << 0)); /* [0] rst_sync*/
+ avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+ "Bitstream level Init for DBLK .Done.\n");
+
+ return;
+}
+
+
+#ifdef CONFIG_HEVC_CLK_FORCED_ON
+static void config_avs2_clk_forced_on(void)
+{
+ unsigned int rdata32;
+ /*IQIT*/
+ rdata32 = READ_VREG(HEVC_IQIT_CLK_RST_CTRL);
+ WRITE_VREG(HEVC_IQIT_CLK_RST_CTRL, rdata32 | (0x1 << 2));
+
+ /* DBLK*/
+ rdata32 = READ_VREG(HEVC_DBLK_CFG0);
+ WRITE_VREG(HEVC_DBLK_CFG0, rdata32 | (0x1 << 2));
+
+ /* SAO*/
+ rdata32 = READ_VREG(HEVC_SAO_CTRL1);
+ WRITE_VREG(HEVC_SAO_CTRL1, rdata32 | (0x1 << 2));
+
+ /*MPRED*/
+ rdata32 = READ_VREG(HEVC_MPRED_CTRL1);
+ WRITE_VREG(HEVC_MPRED_CTRL1, rdata32 | (0x1 << 24));
+
+ /* PARSER*/
+ rdata32 = READ_VREG(HEVC_STREAM_CONTROL);
+ WRITE_VREG(HEVC_STREAM_CONTROL, rdata32 | (0x1 << 15));
+ rdata32 = READ_VREG(HEVC_SHIFT_CONTROL);
+ WRITE_VREG(HEVC_SHIFT_CONTROL, rdata32 | (0x1 << 15));
+ rdata32 = READ_VREG(HEVC_CABAC_CONTROL);
+ WRITE_VREG(HEVC_CABAC_CONTROL, rdata32 | (0x1 << 13));
+ rdata32 = READ_VREG(HEVC_PARSER_CORE_CONTROL);
+ WRITE_VREG(HEVC_PARSER_CORE_CONTROL, rdata32 | (0x1 << 15));
+ rdata32 = READ_VREG(HEVC_PARSER_INT_CONTROL);
+ WRITE_VREG(HEVC_PARSER_INT_CONTROL, rdata32 | (0x1 << 15));
+ rdata32 = READ_VREG(HEVC_PARSER_IF_CONTROL);
+ WRITE_VREG(HEVC_PARSER_IF_CONTROL,
+ rdata32 | (0x1 << 6) | (0x1 << 3) | (0x1 << 1));
+
+ /*IPP*/
+ rdata32 = READ_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG);
+ WRITE_VREG(HEVCD_IPP_DYNCLKGATE_CONFIG, rdata32 | 0xffffffff);
+
+ /* MCRCC*/
+ rdata32 = READ_VREG(HEVCD_MCRCC_CTL1);
+ WRITE_VREG(HEVCD_MCRCC_CTL1, rdata32 | (0x1 << 3));
+}
+#endif
+
+
+
+
+
+static struct AVS2Decoder_s gHevc;
+
+static void avs2_local_uninit(struct AVS2Decoder_s *dec)
+{
+ dec->rpm_ptr = NULL;
+ dec->lmem_ptr = NULL;
+ if (dec->rpm_addr) {
+ dma_unmap_single(amports_get_dma_device(),
+ dec->rpm_phy_addr, RPM_BUF_SIZE,
+ DMA_FROM_DEVICE);
+ kfree(dec->rpm_addr);
+ dec->rpm_addr = NULL;
+ }
+ if (dec->lmem_addr) {
+ if (dec->lmem_phy_addr)
+ dma_free_coherent(amports_get_dma_device(),
+ LMEM_BUF_SIZE, dec->lmem_addr,
+ dec->lmem_phy_addr);
+ dec->lmem_addr = NULL;
+ }
+
+#ifdef AVS2_10B_MMU
+ if (dec->frame_mmu_map_addr) {
+ if (dec->frame_mmu_map_phy_addr)
+ dma_free_coherent(amports_get_dma_device(),
+ FRAME_MMU_MAP_SIZE, dec->frame_mmu_map_addr,
+ dec->frame_mmu_map_phy_addr);
+ dec->frame_mmu_map_addr = NULL;
+ }
+#endif
+ if (dec->gvs)
+ vfree(dec->gvs);
+ dec->gvs = NULL;
+}
+
+static int avs2_local_init(struct AVS2Decoder_s *dec)
+{
+ int ret = -1;
+ /*int losless_comp_header_size, losless_comp_body_size;*/
+
+ struct BuffInfo_s *cur_buf_info = NULL;
+
+ cur_buf_info = &dec->work_space_buf_store;
+#ifdef SUPPORT_4K2K
+ if (vdec_is_support_4k())
+ memcpy(cur_buf_info, &amvavs2_workbuff_spec[1], /* 4k */
+ sizeof(struct BuffInfo_s));
+ else
+ memcpy(cur_buf_info, &amvavs2_workbuff_spec[0],/* 1080p */
+ sizeof(struct BuffInfo_s));
+#else
+ memcpy(cur_buf_info, &amvavs2_workbuff_spec[0], /* 1080p work space */
+ sizeof(struct BuffInfo_s));
+#endif
+ cur_buf_info->start_adr = dec->buf_start;
+#ifndef AVS2_10B_MMU
+ dec->mc_buf_spec.buf_end = dec->buf_start + dec->buf_size;
+#endif
+
+ init_buff_spec(dec, cur_buf_info);
+
+ init_avs2_decoder(&dec->avs2_dec);
+
+#ifdef AVS2_10B_MMU
+ avs2_bufmgr_init(dec, cur_buf_info, NULL);
+#else
+ dec->mc_buf_spec.buf_start = (cur_buf_info->end_adr + 0xffff)
+ & (~0xffff);
+ dec->mc_buf_spec.buf_size = (dec->mc_buf_spec.buf_end
+ - dec->mc_buf_spec.buf_start);
+ if (debug) {
+ pr_err("dec->mc_buf_spec.buf_start %x-%x\n",
+ dec->mc_buf_spec.buf_start,
+ dec->mc_buf_spec.buf_start +
+ dec->mc_buf_spec.buf_size);
+ }
+ avs2_bufmgr_init(dec, cur_buf_info, &dec->mc_buf_spec);
+#endif
+
+ if (!vdec_is_support_4k()
+ && (buf_alloc_width > 1920 && buf_alloc_height > 1088)) {
+ buf_alloc_width = 1920;
+ buf_alloc_height = 1088;
+ }
+ dec->init_pic_w = buf_alloc_width ? buf_alloc_width :
+ (dec->vavs2_amstream_dec_info.width ?
+ dec->vavs2_amstream_dec_info.width :
+ dec->work_space_buf->max_width);
+ dec->init_pic_h = buf_alloc_height ? buf_alloc_height :
+ (dec->vavs2_amstream_dec_info.height ?
+ dec->vavs2_amstream_dec_info.height :
+ dec->work_space_buf->max_height);
+#ifndef MV_USE_FIXED_BUF
+ if (init_mv_buf_list(dec) < 0) {
+ pr_err("%s: init_mv_buf_list fail\n", __func__);
+ return -1;
+ }
+#endif
+
+#ifndef AVS2_10B_MMU
+ init_buf_list(dec);
+#else
+ dec->used_buf_num = max_buf_num;
+ if (dec->used_buf_num > MAX_BUF_NUM)
+ dec->used_buf_num = MAX_BUF_NUM;
+ if (dec->used_buf_num > FRAME_BUFFERS)
+ dec->used_buf_num = FRAME_BUFFERS;
+#endif
+ dec->avs2_dec.ref_maxbuffer = dec->used_buf_num - 1;
+ /*init_pic_list(dec);*/
+
+ pts_unstable = ((unsigned long)(dec->vavs2_amstream_dec_info.param)
+ & 0x40) >> 6;
+
+ if ((debug & AVS2_DBG_SEND_PARAM_WITH_REG) == 0) {
+ dec->rpm_addr = kmalloc(RPM_BUF_SIZE, GFP_KERNEL);
+ if (dec->rpm_addr == NULL) {
+ pr_err("%s: failed to alloc rpm buffer\n", __func__);
+ return -1;
+ }
+
+ dec->rpm_phy_addr = dma_map_single(amports_get_dma_device(),
+ dec->rpm_addr, RPM_BUF_SIZE, DMA_FROM_DEVICE);
+ if (dma_mapping_error(amports_get_dma_device(),
+ dec->rpm_phy_addr)) {
+ pr_err("%s: failed to map rpm buffer\n", __func__);
+ kfree(dec->rpm_addr);
+ dec->rpm_addr = NULL;
+ return -1;
+ }
+
+ dec->rpm_ptr = dec->rpm_addr;
+ }
+
+ dec->lmem_addr = dma_alloc_coherent(amports_get_dma_device(),
+ LMEM_BUF_SIZE,
+ &dec->lmem_phy_addr, GFP_KERNEL);
+ if (dec->lmem_addr == NULL) {
+ pr_err("%s: failed to alloc lmem buffer\n", __func__);
+ return -1;
+ }
+/*
+ dec->lmem_phy_addr = dma_map_single(amports_get_dma_device(),
+ dec->lmem_addr, LMEM_BUF_SIZE, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(amports_get_dma_device(),
+ dec->lmem_phy_addr)) {
+ pr_err("%s: failed to map lmem buffer\n", __func__);
+ kfree(dec->lmem_addr);
+ dec->lmem_addr = NULL;
+ return -1;
+ }
+*/
+ dec->lmem_ptr = dec->lmem_addr;
+
+
+#ifdef AVS2_10B_MMU
+ dec->frame_mmu_map_addr = dma_alloc_coherent(amports_get_dma_device(),
+ FRAME_MMU_MAP_SIZE,
+ &dec->frame_mmu_map_phy_addr, GFP_KERNEL);
+ if (dec->frame_mmu_map_addr == NULL) {
+ pr_err("%s: failed to alloc count_buffer\n", __func__);
+ return -1;
+ }
+ memset(dec->frame_mmu_map_addr, 0, COUNT_BUF_SIZE);
+/* dec->frame_mmu_map_phy_addr = dma_map_single(amports_get_dma_device(),
+ dec->frame_mmu_map_addr, FRAME_MMU_MAP_SIZE, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(amports_get_dma_device(),
+ dec->frame_mmu_map_phy_addr)) {
+ pr_err("%s: failed to map count_buffer\n", __func__);
+ kfree(dec->frame_mmu_map_addr);
+ dec->frame_mmu_map_addr = NULL;
+ return -1;
+ }*/
+#endif
+
+ ret = 0;
+ return ret;
+}
+
+/********************************************
+ * Mailbox command
+ ********************************************/
+#define CMD_FINISHED 0
+#define CMD_ALLOC_VIEW 1
+#define CMD_FRAME_DISPLAY 3
+#define CMD_DEBUG 10
+
+
+#define DECODE_BUFFER_NUM_MAX 32
+#define DISPLAY_BUFFER_NUM 6
+
+#define video_domain_addr(adr) (adr&0x7fffffff)
+#define DECODER_WORK_SPACE_SIZE 0x800000
+
+#define spec2canvas(x) \
+ (((x)->uv_canvas_index << 16) | \
+ ((x)->uv_canvas_index << 8) | \
+ ((x)->y_canvas_index << 0))
+
+
+static void set_canvas(struct AVS2Decoder_s *dec,
+ struct avs2_frame_s *pic)
+{
+ int canvas_w = ALIGN(pic->pic_w, 64)/4;
+ int canvas_h = ALIGN(pic->pic_h, 32)/4;
+ int blkmode = mem_map_mode;
+ /*CANVAS_BLKMODE_64X32*/
+ if (pic->double_write_mode) {
+ canvas_w = pic->pic_w /
+ get_double_write_ratio(dec,
+ pic->double_write_mode);
+ canvas_h = pic->pic_h /
+ get_double_write_ratio(dec,
+ pic->double_write_mode);
+
+ if (mem_map_mode == 0)
+ canvas_w = ALIGN(canvas_w, 32);
+ else
+ canvas_w = ALIGN(canvas_w, 64);
+ canvas_h = ALIGN(canvas_h, 32);
+
+ pic->y_canvas_index = 128 + pic->index * 2;
+ pic->uv_canvas_index = 128 + pic->index * 2 + 1;
+
+ canvas_config_ex(pic->y_canvas_index,
+ pic->dw_y_adr, canvas_w, canvas_h,
+ CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ canvas_config_ex(pic->uv_canvas_index,
+ pic->dw_u_v_adr, canvas_w, canvas_h,
+ CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+#ifdef MULTI_INSTANCE_SUPPORT
+ pic->canvas_config[0].phy_addr =
+ pic->dw_y_adr;
+ pic->canvas_config[0].width =
+ canvas_w;
+ pic->canvas_config[0].height =
+ canvas_h;
+ pic->canvas_config[0].block_mode =
+ blkmode;
+ pic->canvas_config[0].endian = 7;
+
+ pic->canvas_config[1].phy_addr =
+ pic->dw_u_v_adr;
+ pic->canvas_config[1].width =
+ canvas_w;
+ pic->canvas_config[1].height =
+ canvas_h;
+ pic->canvas_config[1].block_mode =
+ blkmode;
+ pic->canvas_config[1].endian = 7;
+#endif
+ } else {
+ #ifndef AVS2_10B_MMU
+ pic->y_canvas_index = 128 + pic->index;
+ pic->uv_canvas_index = 128 + pic->index;
+
+ canvas_config_ex(pic->y_canvas_index,
+ pic->mc_y_adr, canvas_w, canvas_h,
+ CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ canvas_config_ex(pic->uv_canvas_index,
+ pic->mc_u_v_adr, canvas_w, canvas_h,
+ CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ #endif
+ }
+}
+
+static void set_frame_info(struct AVS2Decoder_s *dec, struct vframe_s *vf)
+{
+ unsigned int ar;
+
+ vf->duration = dec->frame_dur;
+ vf->duration_pulldown = 0;
+ vf->flag = 0;
+ vf->prop.master_display_colour = dec->vf_dp;
+ vf->signal_type = dec->video_signal_type;
+
+ ar = min_t(u32, dec->frame_ar, DISP_RATIO_ASPECT_RATIO_MAX);
+ vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT);
+
+ return;
+}
+
+static int vavs2_vf_states(struct vframe_states *states, void *op_arg)
+{
+ struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)op_arg;
+
+ states->vf_pool_size = VF_POOL_SIZE;
+ states->buf_free_num = kfifo_len(&dec->newframe_q);
+ states->buf_avail_num = kfifo_len(&dec->display_q);
+
+ if (step == 2)
+ states->buf_avail_num = 0;
+ return 0;
+}
+
+static struct vframe_s *vavs2_vf_peek(void *op_arg)
+{
+ struct vframe_s *vf;
+ struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)op_arg;
+ if (step == 2)
+ return NULL;
+
+ if (force_disp_pic_index & 0x100) {
+ if (force_disp_pic_index & 0x200)
+ return NULL;
+ return &dec->vframe_dummy;
+ }
+
+ if (kfifo_peek(&dec->display_q, &vf))
+ return vf;
+
+ return NULL;
+}
+
+static struct vframe_s *vavs2_vf_get(void *op_arg)
+{
+ struct vframe_s *vf;
+ struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)op_arg;
+ if (step == 2)
+ return NULL;
+ else if (step == 1)
+ step = 2;
+
+ if (force_disp_pic_index & 0x100) {
+ int idx = force_disp_pic_index & 0xff;
+ struct avs2_frame_s *pic = NULL;
+ if (idx >= 0
+ && idx < dec->avs2_dec.ref_maxbuffer)
+ pic = dec->avs2_dec.fref[idx];
+ if (pic == NULL)
+ return NULL;
+ if (force_disp_pic_index & 0x200)
+ return NULL;
+
+ vf = &dec->vframe_dummy;
+
+ set_vframe(dec, vf, pic, 1);
+
+ force_disp_pic_index |= 0x200;
+ return vf;
+ }
+
+ if (kfifo_get(&dec->display_q, &vf)) {
+ uint8_t index = vf->index & 0xff;
+ if (index >= 0 && index < dec->used_buf_num) {
+ dec->vf_get_count++;
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "%s index 0x%x getcount %d type 0x%x w/h %d/%d, pts %d, %lld\n",
+ __func__, index,
+ dec->vf_get_count,
+ vf->type,
+ vf->width, vf->height,
+ vf->pts,
+ vf->pts_us64);
+ return vf;
+ }
+ }
+ return NULL;
+}
+
+static void vavs2_vf_put(struct vframe_s *vf, void *op_arg)
+{
+ struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)op_arg;
+ uint8_t index = vf->index & 0xff;
+
+ if (vf == (&dec->vframe_dummy))
+ return;
+
+ kfifo_put(&dec->newframe_q, (const struct vframe_s *)vf);
+ dec->vf_put_count++;
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "%s index putcount 0x%x %d\n",
+ __func__, vf->index,
+ dec->vf_put_count);
+
+ if (index >= 0
+ && index < dec->used_buf_num) {
+ unsigned long flags;
+ struct avs2_frame_s *pic;
+
+ lock_buffer(dec, flags);
+ if (index == (dec->used_buf_num - 1))
+ pic = dec->avs2_dec.m_bg;
+ else
+ pic = dec->avs2_dec.fref[index];
+ if (pic && pic->vf_ref > 0)
+ pic->vf_ref--;
+ if (dec->wait_buf)
+ WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG,
+ 0x1);
+ dec->last_put_idx = index;
+ dec->new_frame_displayed++;
+ unlock_buffer(dec, flags);
+ }
+
+}
+
+static int vavs2_event_cb(int type, void *data, void *private_data)
+{
+ return 0;
+}
+
+static struct avs2_frame_s *get_disp_pic(struct AVS2Decoder_s *dec,
+ int pos)
+{
+ struct avs2_decoder *avs2_dec = &dec->avs2_dec;
+ struct avs2_frame_s *pic = NULL;
+ int32_t j;
+ for (j = 0; j < avs2_dec->ref_maxbuffer; j++) {
+ if (avs2_dec->fref[j]->to_prepare_disp) {
+ avs2_dec->fref[j]->to_prepare_disp = 0;
+ pic = avs2_dec->fref[j];
+ break;
+ }
+ }
+ return pic;
+
+}
+
+static void set_vframe(struct AVS2Decoder_s *dec,
+ struct vframe_s *vf, struct avs2_frame_s *pic, u8 dummy)
+{
+ unsigned long flags;
+ int stream_offset;
+ stream_offset = pic->stream_offset;
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "%s index = %d\r\n", __func__, pic->index);
+
+ if (pic->double_write_mode)
+ set_canvas(dec, pic);
+
+ display_frame_count[dec->index]++;
+
+ if (!dummy) {
+#ifdef MULTI_INSTANCE_SUPPORT
+ if (vdec_frame_based(hw_to_vdec(dec))) {
+ vf->pts = pic->pts;
+ vf->pts_us64 = pic->pts64;
+ } else
+#endif
+ /* if (pts_lookup_offset(PTS_TYPE_VIDEO,
+ stream_offset, &vf->pts, 0) != 0) { */
+ if (pts_lookup_offset_us64
+ (PTS_TYPE_VIDEO, stream_offset, &vf->pts, 0,
+ &vf->pts_us64) != 0) {
+#ifdef DEBUG_PTS
+ dec->pts_missed++;
+#endif
+ vf->pts = 0;
+ vf->pts_us64 = 0;
+ }
+#ifdef DEBUG_PTS
+ else
+ dec->pts_hit++;
+#endif
+ if (pts_unstable)
+ dec->pts_mode = PTS_NONE_REF_USE_DURATION;
+
+ if ((dec->pts_mode == PTS_NORMAL) && (vf->pts != 0)
+ && dec->get_frame_dur) {
+ int pts_diff = (int)vf->pts - dec->last_lookup_pts;
+
+ if (pts_diff < 0) {
+ dec->pts_mode_switching_count++;
+ dec->pts_mode_recovery_count = 0;
+
+ if (dec->pts_mode_switching_count >=
+ PTS_MODE_SWITCHING_THRESHOLD) {
+ dec->pts_mode =
+ PTS_NONE_REF_USE_DURATION;
+ pr_info
+ ("HEVC: switch to n_d mode.\n");
+ }
+
+ } else {
+ int p = PTS_MODE_SWITCHING_RECOVERY_THREASHOLD;
+ dec->pts_mode_recovery_count++;
+ if (dec->pts_mode_recovery_count > p) {
+ dec->pts_mode_switching_count = 0;
+ dec->pts_mode_recovery_count = 0;
+ }
+ }
+ }
+
+ if (vf->pts != 0)
+ dec->last_lookup_pts = vf->pts;
+#if 0
+ if ((dec->pts_mode == PTS_NONE_REF_USE_DURATION)
+ && (slice_type != KEY_FRAME))
+ vf->pts = dec->last_pts + DUR2PTS(dec->frame_dur);
+#endif
+ dec->last_pts = vf->pts;
+
+ if (vf->pts_us64 != 0)
+ dec->last_lookup_pts_us64 = vf->pts_us64;
+
+#if 0
+ if ((dec->pts_mode == PTS_NONE_REF_USE_DURATION)
+ && (slice_type != KEY_FRAME)) {
+ vf->pts_us64 =
+ dec->last_pts_us64 +
+ (DUR2PTS(dec->frame_dur) * 100 / 9);
+ }
+#endif
+ dec->last_pts_us64 = vf->pts_us64;
+ avs2_print(dec, AVS2_DBG_OUT_PTS,
+ "avs2 dec out pts: vf->pts=%d, vf->pts_us64 = %lld\n",
+ vf->pts, vf->pts_us64);
+
+ }
+
+ vf->index = 0xff00 | pic->index;
+
+ if (pic->double_write_mode & 0x10) {
+ /* double write only */
+ vf->compBodyAddr = 0;
+ vf->compHeadAddr = 0;
+ } else {
+#ifdef AVS2_10B_MMU
+ vf->compBodyAddr = 0;
+ vf->compHeadAddr = pic->header_adr;
+#else
+ vf->compBodyAddr = pic->mc_y_adr; /*body adr*/
+ vf->compHeadAddr = pic->mc_y_adr +
+ pic->comp_body_size;
+ /*head adr*/
+#endif
+ }
+ if (pic->double_write_mode) {
+ vf->type = VIDTYPE_PROGRESSIVE |
+ VIDTYPE_VIU_FIELD;
+ vf->type |= VIDTYPE_VIU_NV21;
+ if (pic->double_write_mode == 3) {
+ vf->type |= VIDTYPE_COMPRESS;
+#ifdef AVS2_10B_MMU
+ vf->type |= VIDTYPE_SCATTER;
+#endif
+ }
+#ifdef MULTI_INSTANCE_SUPPORT
+ if (dec->m_ins_flag) {
+ vf->canvas0Addr = vf->canvas1Addr = -1;
+ vf->plane_num = 2;
+ vf->canvas0_config[0] =
+ pic->canvas_config[0];
+ vf->canvas0_config[1] =
+ pic->canvas_config[1];
+
+ vf->canvas1_config[0] =
+ pic->canvas_config[0];
+ vf->canvas1_config[1] =
+ pic->canvas_config[1];
+
+ } else
+#endif
+ vf->canvas0Addr = vf->canvas1Addr =
+ spec2canvas(pic);
+ } else {
+ vf->canvas0Addr = vf->canvas1Addr = 0;
+ vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD;
+#ifdef AVS2_10B_MMU
+ vf->type |= VIDTYPE_SCATTER;
+#endif
+ }
+
+ switch (pic->bit_depth) {
+ case AVS2_BITS_8:
+ vf->bitdepth = BITDEPTH_Y8 |
+ BITDEPTH_U8 | BITDEPTH_V8;
+ break;
+ case AVS2_BITS_10:
+ case AVS2_BITS_12:
+ vf->bitdepth = BITDEPTH_Y10 |
+ BITDEPTH_U10 | BITDEPTH_V10;
+ break;
+ default:
+ vf->bitdepth = BITDEPTH_Y10 |
+ BITDEPTH_U10 | BITDEPTH_V10;
+ break;
+ }
+ if ((vf->type & VIDTYPE_COMPRESS) == 0)
+ vf->bitdepth =
+ BITDEPTH_Y8 | BITDEPTH_U8 | BITDEPTH_V8;
+ if (pic->bit_depth == AVS2_BITS_8)
+ vf->bitdepth |= BITDEPTH_SAVING_MODE;
+
+ set_frame_info(dec, vf);
+ /* if((vf->width!=pic->width)|
+ (vf->height!=pic->height)) */
+ /* pr_info("aaa: %d/%d, %d/%d\n",
+ vf->width,vf->height, pic->width,
+ pic->height); */
+ vf->width = pic->pic_w /
+ get_double_write_ratio(dec,
+ pic->double_write_mode);
+ vf->height = pic->pic_h /
+ get_double_write_ratio(dec,
+ pic->double_write_mode);
+ if (force_w_h != 0) {
+ vf->width = (force_w_h >> 16) & 0xffff;
+ vf->height = force_w_h & 0xffff;
+ }
+ vf->compWidth = pic->pic_w;
+ vf->compHeight = pic->pic_h;
+ if (force_fps & 0x100) {
+ u32 rate = force_fps & 0xff;
+ if (rate)
+ vf->duration = 96000/rate;
+ else
+ vf->duration = 0;
+ }
+#ifdef AVS2_10B_MMU
+ if (vf->type & VIDTYPE_SCATTER) {
+ vf->mem_handle = decoder_mmu_box_get_mem_handle(
+ dec->mmu_box,
+ pic->index);
+ vf->mem_head_handle = decoder_bmmu_box_get_mem_handle(
+ dec->bmmu_box,
+ HEADER_BUFFER_IDX(pic->index));
+ } else {
+ vf->mem_handle = decoder_bmmu_box_get_mem_handle(
+ dec->bmmu_box,
+ VF_BUFFER_IDX(pic->index));
+ vf->mem_head_handle = decoder_bmmu_box_get_mem_handle(
+ dec->bmmu_box,
+ HEADER_BUFFER_IDX(pic->index));
+ }
+#else
+ vf->mem_handle = decoder_bmmu_box_get_mem_handle(
+ dec->bmmu_box,
+ VF_BUFFER_IDX(pic->index));
+#endif
+
+ if (!dummy) {
+ lock_buffer(dec, flags);
+ pic->vf_ref = 1;
+ unlock_buffer(dec, flags);
+ }
+ dec->vf_pre_count++;
+}
+
+static int avs2_prepare_display_buf(struct AVS2Decoder_s *dec,
+ int pos)
+{
+#ifndef NO_DISPLAY
+ struct vframe_s *vf = NULL;
+ /*unsigned short slice_type;*/
+ struct avs2_frame_s *pic;
+
+ pic = get_disp_pic(dec, pos);
+ if (pic == NULL) {
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "%s pic not available for pos of %d\r\n",
+ __func__, pos);
+ return -1;
+ }
+
+ if (force_disp_pic_index & 0x100) {
+ /*recycle directly*/
+ return -1;
+ }
+
+ if (kfifo_get(&dec->newframe_q, &vf) == 0) {
+ pr_info("fatal error, no available buffer slot.");
+ return -1;
+ }
+
+ if (vf) {
+ set_vframe(dec, vf, pic, 0);
+
+ kfifo_put(&dec->display_q, (const struct vframe_s *)vf);
+
+#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
+ /*count info*/
+ gvs->frame_dur = dec->frame_dur;
+ vdec_count_info(gvs, 0, stream_offset);
+#endif
+ vf_notify_receiver(dec->provider_name,
+ VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
+ }
+/*!NO_DISPLAY*/
+#endif
+ return 0;
+}
+
+static void get_rpm_param(union param_u *params)
+{
+ int i;
+ unsigned int data32;
+ if (debug & AVS2_DBG_BUFMGR)
+ pr_info("enter %s\r\n", __func__);
+ for (i = 0; i < (RPM_END - RPM_BEGIN); i++) {
+ do {
+ data32 = READ_VREG(RPM_CMD_REG);
+ /*pr_info("%x\n", data32);*/
+ } while ((data32 & 0x10000) == 0);
+ params->l.data[i] = data32&0xffff;
+ /*pr_info("%x\n", data32);*/
+ WRITE_VREG(RPM_CMD_REG, 0);
+ }
+ if (debug & AVS2_DBG_BUFMGR)
+ pr_info("leave %s\r\n", __func__);
+}
+static void debug_buffer_mgr_more(struct AVS2Decoder_s *dec)
+{
+ int i;
+ if (!(debug & AVS2_DBG_BUFMGR_MORE))
+ return;
+ pr_info("avs2_param: (%d)\n", dec->avs2_dec.img.number);
+ for (i = 0; i < (RPM_END-RPM_BEGIN); i++) {
+ pr_info("%04x ", dec->avs2_dec.param.l.data[i]);
+ if (((i + 1) & 0xf) == 0)
+ pr_info("\n");
+ }
+}
+
+#ifdef AVS2_10B_MMU
+static void avs2_recycle_mmu_buf_tail(struct AVS2Decoder_s *dec)
+{
+ if (dec->cur_fb_idx_mmu != INVALID_IDX) {
+ if (dec->used_4k_num == -1)
+ dec->used_4k_num =
+ (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16);
+ decoder_mmu_box_free_idx_tail(dec->mmu_box,
+ dec->cur_fb_idx_mmu, dec->used_4k_num);
+
+ dec->cur_fb_idx_mmu = INVALID_IDX;
+ dec->used_4k_num = -1;
+ }
+}
+
+static void avs2_recycle_mmu_buf(struct AVS2Decoder_s *dec)
+{
+ if (dec->cur_fb_idx_mmu != INVALID_IDX) {
+ decoder_mmu_box_free_idx(dec->mmu_box,
+ dec->cur_fb_idx_mmu);
+
+ dec->cur_fb_idx_mmu = INVALID_IDX;
+ dec->used_4k_num = -1;
+ }
+}
+#endif
+
+static void dec_again_process(struct AVS2Decoder_s *dec)
+{
+ amhevc_stop();
+ dec->dec_result = DEC_RESULT_AGAIN;
+ if (dec->process_state ==
+ PROC_STATE_DECODESLICE) {
+ dec->process_state =
+ PROC_STATE_SENDAGAIN;
+#ifdef AVS2_10B_MMU
+ avs2_recycle_mmu_buf(dec);
+#endif
+ }
+ reset_process_time(dec);
+ vdec_schedule_work(&dec->work);
+}
+
+static uint32_t log2i(uint32_t val)
+{
+ uint32_t ret = -1;
+ while (val != 0) {
+ val >>= 1;
+ ret++;
+ }
+ return ret;
+}
+
+static irqreturn_t vavs2_isr_thread_fn(int irq, void *data)
+{
+ struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)data;
+ unsigned int dec_status = dec->dec_status;
+ int i, ret;
+ int32_t start_code = 0;
+ int disp_pos;
+
+ /*if (dec->wait_buf)
+ pr_info("set wait_buf to 0\r\n");
+ */
+ avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+ "%s %x\n", __func__, dec_status);
+#ifndef G12A_BRINGUP_DEBUG
+ if (dec->eos) {
+ PRINT_LINE();
+ dec->process_busy = 0;
+ return IRQ_HANDLED;
+ }
+#endif
+ dec->wait_buf = 0;
+ if ((dec_status == HEVC_NAL_DECODE_DONE) ||
+ (dec_status == AVS2_DECODE_TIMEOUT) ||
+ (dec_status == AVS2_DECODE_BUFEMPTY)
+ ) {
+ PRINT_LINE();
+ if (dec->m_ins_flag) {
+ reset_process_time(dec);
+ if (!vdec_frame_based(hw_to_vdec(dec)))
+ dec_again_process(dec);
+ else {
+ dec->dec_result = DEC_RESULT_GET_DATA;
+ vdec_schedule_work(&dec->work);
+ }
+ }
+ dec->process_busy = 0;
+ return IRQ_HANDLED;
+ } else if (dec_status == HEVC_DECPIC_DATA_DONE) {
+ PRINT_LINE();
+ if (dec->m_ins_flag) {
+ reset_process_time(dec);
+ dec->dec_result = DEC_RESULT_DONE;
+ amhevc_stop();
+ vdec_schedule_work(&dec->work);
+ }
+
+ dec->process_busy = 0;
+ return IRQ_HANDLED;
+ }
+ PRINT_LINE();
+
+ if (dec_status == AVS2_EOS) {
+ if (dec->m_ins_flag)
+ reset_process_time(dec);
+
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "AVS2_EOS, flush buffer\r\n");
+
+ disp_pos = avs2_post_process(&dec->avs2_dec);
+ avs2_prepare_display_buf(dec, disp_pos);
+
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "send AVS2_10B_DISCARD_NAL\r\n");
+ WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_10B_DISCARD_NAL);
+ dec->process_busy = 0;
+ if (dec->m_ins_flag) {
+ dec->dec_result = DEC_RESULT_DONE;
+ amhevc_stop();
+ vdec_schedule_work(&dec->work);
+ }
+ return IRQ_HANDLED;
+ } else if (dec_status == AVS2_DECODE_OVER_SIZE) {
+ avs2_print(dec, 0,
+ "avs2 decode oversize !!\n");
+ debug |= (AVS2_DBG_DIS_LOC_ERROR_PROC |
+ AVS2_DBG_DIS_SYS_ERROR_PROC);
+ dec->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW;
+ if (dec->m_ins_flag)
+ reset_process_time(dec);
+ dec->process_busy = 0;
+ return IRQ_HANDLED;
+ }
+ PRINT_LINE();
+
+ if (dec->m_ins_flag)
+ reset_process_time(dec);
+
+ if ((dec_status == AVS2_HEAD_PIC_I_READY)
+ || (dec_status == AVS2_HEAD_PIC_PB_READY)) {
+ PRINT_LINE();
+
+ if (dec->avs2_dec.hc.cur_pic != NULL &&
+ dec->process_state != PROC_STATE_SENDAGAIN) {
+ int32_t ii;
+#ifdef AVS2_10B_MMU
+ avs2_recycle_mmu_buf_tail(dec);
+#endif
+ disp_pos = avs2_post_process(&dec->avs2_dec);
+ avs2_prepare_display_buf(dec, disp_pos);
+ dec->avs2_dec.hc.cur_pic = NULL;
+#ifdef AVS2_10B_MMU
+ for (ii = 0; ii < dec->avs2_dec.ref_maxbuffer;
+ ii++) {
+ if (dec->avs2_dec.fref[ii]->
+ refered_by_others == 0 &&
+ dec->avs2_dec.fref[ii]->
+ bg_flag == 0 &&
+ dec->avs2_dec.fref[ii]->
+ is_output == -1 &&
+ dec->avs2_dec.fref[ii]->
+ mmu_alloc_flag &&
+ dec->avs2_dec.fref[ii]->
+ vf_ref == 0) {
+ dec->avs2_dec.fref[ii]->
+ mmu_alloc_flag = 0;
+ /*release_buffer_4k(
+ dec->avs2_dec.fref[ii]->index);*/
+ decoder_mmu_box_free_idx(dec->mmu_box,
+ dec->avs2_dec.fref[ii]->index);
+ }
+ }
+#endif
+ }
+
+ if (debug & AVS2_DBG_SEND_PARAM_WITH_REG) {
+ get_rpm_param(
+ &dec->avs2_dec.param);
+ } else {
+ PRINT_LINE();
+ dma_sync_single_for_cpu(
+ amports_get_dma_device(),
+ dec->rpm_phy_addr,
+ RPM_BUF_SIZE,
+ DMA_FROM_DEVICE);
+
+ for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) {
+ int ii;
+ for (ii = 0; ii < 4; ii++)
+ dec->avs2_dec.param.l.data[i + ii] =
+ dec->rpm_ptr[i + 3 - ii];
+ }
+ }
+ PRINT_LINE();
+
+ debug_buffer_mgr_more(dec);
+
+ }
+
+ if (dec_status == AVS2_HEAD_SEQ_READY)
+ start_code = SEQUENCE_HEADER_CODE;
+ else if (dec_status == AVS2_HEAD_PIC_I_READY)
+ start_code = I_PICTURE_START_CODE;
+ else if (dec_status == AVS2_HEAD_PIC_PB_READY)
+ start_code = PB_PICTURE_START_CODE;
+ else if (dec_status == AVS2_HEAD_SEQ_END_READY)
+ start_code = SEQUENCE_END_CODE;
+
+ PRINT_LINE();
+ avs2_prepare_header(&dec->avs2_dec, start_code);
+
+ if (start_code == SEQUENCE_HEADER_CODE)
+ WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE);
+ else if (start_code == I_PICTURE_START_CODE ||
+ start_code == PB_PICTURE_START_CODE) {
+ ret = 0;
+ if (dec->process_state != PROC_STATE_SENDAGAIN) {
+ if (dec->pic_list_init_flag == 0) {
+ int32_t lcu_size_log2 =
+ log2i(dec->avs2_dec.param.p.lcu_size);
+
+ avs2_init_global_buffers(&dec->avs2_dec);
+ /*avs2_dec->m_bg->index is
+ set to dec->used_buf_num - 1*/
+ init_pic_list(dec, lcu_size_log2);
+ init_pic_list_hw(dec);
+ }
+ ret = avs2_process_header(&dec->avs2_dec);
+ if (!dec->m_ins_flag)
+ dec->slice_idx++;
+ }
+ PRINT_LINE();
+#ifdef AVS2_10B_MMU
+ if (ret >= 0) {
+ ret = avs2_alloc_mmu(dec,
+ dec->avs2_dec.hc.cur_pic->index,
+ dec->avs2_dec.img.width,
+ dec->avs2_dec.img.height,
+ dec->avs2_dec.input.sample_bit_depth,
+ dec->frame_mmu_map_addr);
+ if (ret >= 0) {
+ dec->cur_fb_idx_mmu =
+ dec->avs2_dec.hc.cur_pic->index;
+ dec->avs2_dec.hc.cur_pic->mmu_alloc_flag = 1;
+ } else
+ pr_err("can't alloc need mmu1,idx %d ret =%d\n",
+ dec->avs2_dec.hc.cur_pic->index,
+ ret);
+ }
+#endif
+ if (ret < 0) {
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "avs2_bufmgr_process=> %d, AVS2_10B_DISCARD_NAL\r\n",
+ ret);
+ WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_10B_DISCARD_NAL);
+ dec->process_busy = 0;
+ #ifdef AVS2_10B_MMU
+ avs2_recycle_mmu_buf(dec);
+ #endif
+ if (dec->m_ins_flag) {
+ dec->dec_result = DEC_RESULT_DONE;
+ amhevc_stop();
+ vdec_schedule_work(&dec->work);
+ }
+
+ return IRQ_HANDLED;
+ } else {
+ PRINT_LINE();
+ /*
+ struct PIC_BUFFER_CONFIG_s *cur_pic
+ = &cm->cur_frame->buf;
+ cur_pic->decode_idx = dec->frame_count;
+ */
+ if (dec->process_state != PROC_STATE_SENDAGAIN) {
+ if (!dec->m_ins_flag) {
+ dec->frame_count++;
+ decode_frame_count[dec->index]
+ = dec->frame_count;
+ }
+ /*MULTI_INSTANCE_SUPPORT*/
+ if (dec->chunk) {
+ dec->avs2_dec.hc.cur_pic->pts =
+ dec->chunk->pts;
+ dec->avs2_dec.hc.cur_pic->pts64 =
+ dec->chunk->pts64;
+ }
+ /**/
+ }
+ dec->avs2_dec.hc.cur_pic->bit_depth
+ = dec->avs2_dec.input.sample_bit_depth;
+ dec->avs2_dec.hc.cur_pic->double_write_mode
+ = get_double_write_mode(dec);
+
+ PRINT_LINE();
+ config_mc_buffer(dec);
+ config_mcrcc_axi_hw(dec);
+ config_mpred_hw(dec);
+ config_dblk_hw(dec);
+ config_sao_hw(dec);
+ config_alf_hw(dec);
+ config_other_hw(dec);
+
+ avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+ "=>fref0 imgtr_fwRefDistance %d, fref1 imgtr_fwRefDistance %d, dis2/dis3/dis4 %d %d %d img->tr %d\n",
+ dec->avs2_dec.fref[0]->imgtr_fwRefDistance,
+ dec->avs2_dec.fref[1]->imgtr_fwRefDistance,
+ dec->avs2_dec.fref[2]->imgtr_fwRefDistance,
+ dec->avs2_dec.fref[3]->imgtr_fwRefDistance,
+ dec->avs2_dec.fref[4]->imgtr_fwRefDistance,
+ dec->avs2_dec.img.tr);
+
+ WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE);
+
+ }
+ dec->process_busy = 0;
+ dec->process_state = PROC_STATE_DECODESLICE;
+
+ if (dec->m_ins_flag)
+ start_process_time(dec);
+ }
+ dec->process_busy = 0;
+ PRINT_LINE();
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t vavs2_isr(int irq, void *data)
+{
+ int i;
+ unsigned int dec_status;
+ struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)data;
+ uint debug_tag;
+ WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1);
+
+ dec_status = READ_VREG(HEVC_DEC_STATUS_REG);
+
+ if (!dec)
+ return IRQ_HANDLED;
+ if (dec->init_flag == 0)
+ return IRQ_HANDLED;
+ if (dec->process_busy)/*on process.*/
+ return IRQ_HANDLED;
+ dec->dec_status = dec_status;
+ dec->process_busy = 1;
+ if (debug & AVS2_DBG_IRQ_EVENT)
+ avs2_print(dec, 0,
+ "avs2 isr dec status = 0x%x, lcu 0x%x shiftbyte 0x%x (%x %x lev %x, wr %x, rd %x)\n",
+ dec_status, READ_VREG(HEVC_PARSER_LCU_START),
+ READ_VREG(HEVC_SHIFT_BYTE_COUNT),
+ READ_VREG(HEVC_STREAM_START_ADDR),
+ READ_VREG(HEVC_STREAM_END_ADDR),
+ READ_VREG(HEVC_STREAM_LEVEL),
+ READ_VREG(HEVC_STREAM_WR_PTR),
+ READ_VREG(HEVC_STREAM_RD_PTR)
+ );
+
+ debug_tag = READ_HREG(DEBUG_REG1);
+ if (debug_tag & 0x10000) {
+ dma_sync_single_for_cpu(
+ amports_get_dma_device(),
+ dec->lmem_phy_addr,
+ LMEM_BUF_SIZE,
+ DMA_FROM_DEVICE);
+
+ pr_info("LMEM<tag %x>:\n", READ_HREG(DEBUG_REG1));
+ for (i = 0; i < 0x400; i += 4) {
+ int ii;
+ if ((i & 0xf) == 0)
+ pr_info("%03x: ", i);
+ for (ii = 0; ii < 4; ii++) {
+ pr_info("%04x ",
+ dec->lmem_ptr[i + 3 - ii]);
+ }
+ if (((i + ii) & 0xf) == 0)
+ pr_info("\n");
+ }
+
+ if (((udebug_pause_pos & 0xffff)
+ == (debug_tag & 0xffff)) &&
+ (udebug_pause_decode_idx == 0 ||
+ udebug_pause_decode_idx == dec->decode_idx) &&
+ (udebug_pause_val == 0 ||
+ udebug_pause_val == READ_HREG(DEBUG_REG2))) {
+ udebug_pause_pos &= 0xffff;
+ dec->ucode_pause_pos = udebug_pause_pos;
+ } else if (debug_tag & 0x20000)
+ dec->ucode_pause_pos = 0xffffffff;
+ if (dec->ucode_pause_pos)
+ reset_process_time(dec);
+ else
+ WRITE_HREG(DEBUG_REG1, 0);
+ } else if (debug_tag != 0) {
+ pr_info(
+ "dbg%x: %x lcu %x\n", READ_HREG(DEBUG_REG1),
+ READ_HREG(DEBUG_REG2),
+ READ_VREG(HEVC_PARSER_LCU_START));
+ if (((udebug_pause_pos & 0xffff)
+ == (debug_tag & 0xffff)) &&
+ (udebug_pause_decode_idx == 0 ||
+ udebug_pause_decode_idx == dec->decode_idx) &&
+ (udebug_pause_val == 0 ||
+ udebug_pause_val == READ_HREG(DEBUG_REG2))) {
+ udebug_pause_pos &= 0xffff;
+ dec->ucode_pause_pos = udebug_pause_pos;
+ }
+ if (dec->ucode_pause_pos)
+ reset_process_time(dec);
+ else
+ WRITE_HREG(DEBUG_REG1, 0);
+ dec->process_busy = 0;
+ return IRQ_HANDLED;
+ }
+
+ if (!dec->m_ins_flag) {
+ if (dec->error_flag == 1) {
+ dec->error_flag = 2;
+ dec->process_busy = 0;
+ return IRQ_HANDLED;
+ } else if (dec->error_flag == 3) {
+ dec->process_busy = 0;
+ return IRQ_HANDLED;
+ }
+
+ if ((dec->pic_list_init_flag) &&
+ get_free_buf_count(dec) <= 0) {
+ /*
+ if (dec->wait_buf == 0)
+ pr_info("set wait_buf to 1\r\n");
+ */
+ dec->wait_buf = 1;
+ dec->process_busy = 0;
+ return IRQ_HANDLED;
+ } else if (force_disp_pic_index) {
+ dec->process_busy = 0;
+ return IRQ_HANDLED;
+ }
+ }
+ return IRQ_WAKE_THREAD;
+}
+
+static void vavs2_put_timer_func(unsigned long arg)
+{
+ struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)arg;
+ struct timer_list *timer = &dec->timer;
+ uint8_t empty_flag;
+ unsigned int buf_level;
+
+ enum receviver_start_e state = RECEIVER_INACTIVE;
+ if (dec->m_ins_flag) {
+ if (hw_to_vdec(dec)->next_status
+ == VDEC_STATUS_DISCONNECTED) {
+ dec->dec_result = DEC_RESULT_FORCE_EXIT;
+ vdec_schedule_work(&dec->work);
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "vdec requested to be disconnected\n");
+ return;
+ }
+ }
+ if (dec->init_flag == 0) {
+ if (dec->stat & STAT_TIMER_ARM) {
+ timer->expires = jiffies + PUT_INTERVAL;
+ add_timer(&dec->timer);
+ }
+ return;
+ }
+ if (dec->m_ins_flag == 0) {
+ if (vf_get_receiver(dec->provider_name)) {
+ state =
+ vf_notify_receiver(dec->provider_name,
+ VFRAME_EVENT_PROVIDER_QUREY_STATE,
+ NULL);
+ if ((state == RECEIVER_STATE_NULL)
+ || (state == RECEIVER_STATE_NONE))
+ state = RECEIVER_INACTIVE;
+ } else
+ state = RECEIVER_INACTIVE;
+
+ empty_flag = (READ_VREG(HEVC_PARSER_INT_STATUS) >> 6) & 0x1;
+ /* error watchdog */
+ if (empty_flag == 0) {
+ /* decoder has input */
+ if ((debug & AVS2_DBG_DIS_LOC_ERROR_PROC) == 0) {
+
+ buf_level = READ_VREG(HEVC_STREAM_LEVEL);
+ /* receiver has no buffer to recycle */
+ if ((state == RECEIVER_INACTIVE) &&
+ (kfifo_is_empty(&dec->display_q) &&
+ buf_level > 0x200)
+ ) {
+ WRITE_VREG
+ (HEVC_ASSIST_MBOX0_IRQ_REG,
+ 0x1);
+ }
+ }
+
+ if ((debug & AVS2_DBG_DIS_SYS_ERROR_PROC) == 0) {
+ /* receiver has no buffer to recycle */
+ /*if ((state == RECEIVER_INACTIVE) &&
+ (kfifo_is_empty(&dec->display_q))) {
+ pr_info("avs2 something error,need reset\n");
+ }*/
+ }
+ }
+ } else {
+ if (
+ (decode_timeout_val > 0) &&
+ (dec->start_process_time > 0) &&
+ ((1000 * (jiffies - dec->start_process_time) / HZ)
+ > decode_timeout_val)
+ ) {
+ int current_lcu_idx =
+ READ_VREG(HEVC_PARSER_LCU_START)
+ & 0xffffff;
+ if (dec->last_lcu_idx == current_lcu_idx) {
+ if (dec->decode_timeout_count > 0)
+ dec->decode_timeout_count--;
+ if (dec->decode_timeout_count == 0) {
+ if (input_frame_based(
+ hw_to_vdec(dec)) ||
+ (READ_VREG(HEVC_STREAM_LEVEL) > 0x200))
+ timeout_process(dec);
+ else {
+ avs2_print(dec, 0,
+ "timeout & empty, again\n");
+ dec_again_process(dec);
+ }
+ }
+ } else {
+ start_process_time(dec);
+ dec->last_lcu_idx = current_lcu_idx;
+ }
+ }
+ }
+
+ if ((dec->ucode_pause_pos != 0) &&
+ (dec->ucode_pause_pos != 0xffffffff) &&
+ udebug_pause_pos != dec->ucode_pause_pos) {
+ dec->ucode_pause_pos = 0;
+ WRITE_HREG(DEBUG_REG1, 0);
+ }
+ if (debug & AVS2_DBG_FORCE_SEND_AGAIN) {
+ pr_info(
+ "Force Send Again\r\n");
+ debug &= ~AVS2_DBG_FORCE_SEND_AGAIN;
+ reset_process_time(dec);
+ dec->dec_result = DEC_RESULT_AGAIN;
+ if (dec->process_state ==
+ PROC_STATE_DECODESLICE) {
+#ifdef AVS2_10B_MMU
+ avs2_recycle_mmu_buf(dec);
+#endif
+ dec->process_state =
+ PROC_STATE_SENDAGAIN;
+ }
+ amhevc_stop();
+
+ vdec_schedule_work(&dec->work);
+ }
+
+ if (debug & AVS2_DBG_DUMP_DATA) {
+ debug &= ~AVS2_DBG_DUMP_DATA;
+ avs2_print(dec, 0,
+ "%s: chunk size 0x%x off 0x%x sum 0x%x\n",
+ __func__,
+ dec->chunk->size,
+ dec->chunk->offset,
+ get_data_check_sum(dec, dec->chunk->size)
+ );
+ dump_data(dec, dec->chunk->size);
+ }
+ if (debug & AVS2_DBG_DUMP_PIC_LIST) {
+ dump_pic_list(dec);
+ debug &= ~AVS2_DBG_DUMP_PIC_LIST;
+ }
+ if (debug & AVS2_DBG_TRIG_SLICE_SEGMENT_PROC) {
+ WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1);
+ debug &= ~AVS2_DBG_TRIG_SLICE_SEGMENT_PROC;
+ }
+ /*if (debug & AVS2_DBG_HW_RESET) {
+ }*/
+
+ if (radr != 0) {
+ if (rval != 0) {
+ WRITE_VREG(radr, rval);
+ pr_info("WRITE_VREG(%x,%x)\n", radr, rval);
+ } else
+ pr_info("READ_VREG(%x)=%x\n", radr, READ_VREG(radr));
+ rval = 0;
+ radr = 0;
+ }
+ if (pop_shorts != 0) {
+ int i;
+ u32 sum = 0;
+ pr_info("pop stream 0x%x shorts\r\n", pop_shorts);
+ for (i = 0; i < pop_shorts; i++) {
+ u32 data =
+ (READ_HREG(HEVC_SHIFTED_DATA) >> 16);
+ WRITE_HREG(HEVC_SHIFT_COMMAND,
+ (1<<7)|16);
+ if ((i & 0xf) == 0)
+ pr_info("%04x:", i);
+ pr_info("%04x ", data);
+ if (((i + 1) & 0xf) == 0)
+ pr_info("\r\n");
+ sum += data;
+ }
+ pr_info("\r\nsum = %x\r\n", sum);
+ pop_shorts = 0;
+ }
+ if (dbg_cmd != 0) {
+ if (dbg_cmd == 1) {
+ u32 disp_laddr;
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXBB &&
+ get_double_write_mode(dec) == 0) {
+ disp_laddr =
+ READ_VCBUS_REG(AFBC_BODY_BADDR) << 4;
+ } else {
+ struct canvas_s cur_canvas;
+ canvas_read((READ_VCBUS_REG(VD1_IF0_CANVAS0)
+ & 0xff), &cur_canvas);
+ disp_laddr = cur_canvas.addr;
+ }
+ pr_info("current displayed buffer address %x\r\n",
+ disp_laddr);
+ }
+ dbg_cmd = 0;
+ }
+ /*don't changed at start.*/
+ if (dec->get_frame_dur && dec->show_frame_num > 60 &&
+ dec->frame_dur > 0 && dec->saved_resolution !=
+ frame_width * frame_height *
+ (96000 / dec->frame_dur)) {
+ int fps = 96000 / dec->frame_dur;
+ if (hevc_source_changed(VFORMAT_AVS2,
+ frame_width, frame_height, fps) > 0)
+ dec->saved_resolution = frame_width *
+ frame_height * fps;
+ }
+
+ timer->expires = jiffies + PUT_INTERVAL;
+ add_timer(timer);
+}
+
+
+int vavs2_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
+{
+ struct AVS2Decoder_s *dec =
+ (struct AVS2Decoder_s *)vdec->private;
+ vstatus->frame_width = frame_width;
+ vstatus->frame_height = frame_height;
+ if (dec->frame_dur != 0)
+ vstatus->frame_rate = 96000 / dec->frame_dur;
+ else
+ vstatus->frame_rate = -1;
+ vstatus->error_count = 0;
+ vstatus->status = dec->stat | dec->fatal_error;
+ vstatus->frame_dur = dec->frame_dur;
+#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
+ vstatus->bit_rate = gvs->bit_rate;
+ vstatus->frame_data = gvs->frame_data;
+ vstatus->total_data = gvs->total_data;
+ vstatus->frame_count = gvs->frame_count;
+ vstatus->error_frame_count = gvs->error_frame_count;
+ vstatus->drop_frame_count = gvs->drop_frame_count;
+ vstatus->total_data = gvs->total_data;
+ vstatus->samp_cnt = gvs->samp_cnt;
+ vstatus->offset = gvs->offset;
+ snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
+ "%s", DRIVER_NAME);
+#endif
+ return 0;
+}
+
+int vavs2_set_isreset(struct vdec_s *vdec, int isreset)
+{
+ is_reset = isreset;
+ return 0;
+}
+
+static void vavs2_prot_init(struct AVS2Decoder_s *dec)
+{
+ unsigned int data32;
+
+ avs2_config_work_space_hw(dec);
+ if (dec->pic_list_init_flag)
+ init_pic_list_hw(dec);
+
+ avs2_init_decoder_hw(dec);
+
+#if 1
+ avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+ "%s\n", __func__);
+ data32 = READ_VREG(HEVC_STREAM_CONTROL);
+ data32 = data32 |
+ (1 << 0)/*stream_fetch_enable*/
+ ;
+ WRITE_VREG(HEVC_STREAM_CONTROL, data32);
+#if 0
+ data32 = READ_VREG(HEVC_SHIFT_STARTCODE);
+ if (data32 != 0x00000100) {
+ pr_info("avs2 prot init error %d\n", __LINE__);
+ return;
+ }
+ data32 = READ_VREG(HEVC_SHIFT_EMULATECODE);
+ if (data32 != 0x00000300) {
+ pr_info("avs2 prot init error %d\n", __LINE__);
+ return;
+ }
+ WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x12345678);
+ WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x9abcdef0);
+ data32 = READ_VREG(HEVC_SHIFT_STARTCODE);
+ if (data32 != 0x12345678) {
+ pr_info("avs2 prot init error %d\n", __LINE__);
+ return;
+ }
+ data32 = READ_VREG(HEVC_SHIFT_EMULATECODE);
+ if (data32 != 0x9abcdef0) {
+ pr_info("avs2 prot init error %d\n", __LINE__);
+ return;
+ }
+#endif
+ WRITE_VREG(HEVC_SHIFT_STARTCODE, 0x00000100);
+ WRITE_VREG(HEVC_SHIFT_EMULATECODE, 0x00000000);
+#endif
+
+
+
+ WRITE_VREG(HEVC_WAIT_FLAG, 1);
+
+ /* WRITE_VREG(HEVC_MPSR, 1); */
+
+ /* clear mailbox interrupt */
+ WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1);
+
+ /* enable mailbox interrupt */
+ WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 1);
+
+ /* disable PSCALE for hardware sharing */
+ WRITE_VREG(HEVC_PSCALE_CTRL, 0);
+
+ WRITE_VREG(DEBUG_REG1, 0x0);
+ /*check vps/sps/pps/i-slice in ucode*/
+ WRITE_VREG(NAL_SEARCH_CTL, 0x8);
+
+ WRITE_VREG(DECODE_STOP_POS, udebug_flag);
+
+}
+
+static int vavs2_local_init(struct AVS2Decoder_s *dec)
+{
+ int i;
+ int ret;
+ int width, height;
+
+ dec->gvs = vzalloc(sizeof(struct vdec_info));
+ if (NULL == dec->gvs) {
+ avs2_print(dec, 0,
+ "the struct of vdec status malloc failed.\n");
+ return -1;
+ }
+#ifdef DEBUG_PTS
+ dec->pts_missed = 0;
+ dec->pts_hit = 0;
+#endif
+ dec->new_frame_displayed = 0;
+ dec->last_put_idx = -1;
+ dec->saved_resolution = 0;
+ dec->get_frame_dur = false;
+ on_no_keyframe_skiped = 0;
+ width = dec->vavs2_amstream_dec_info.width;
+ height = dec->vavs2_amstream_dec_info.height;
+ dec->frame_dur =
+ (dec->vavs2_amstream_dec_info.rate ==
+ 0) ? 3600 : dec->vavs2_amstream_dec_info.rate;
+ if (width && height)
+ dec->frame_ar = height * 0x100 / width;
+/*
+TODO:FOR VERSION
+*/
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "avs2: ver (%d,%d) decinfo: %dx%d rate=%d\n", avs2_version,
+ 0, width, height, dec->frame_dur);
+
+ if (dec->frame_dur == 0)
+ dec->frame_dur = 96000 / 24;
+
+ INIT_KFIFO(dec->display_q);
+ INIT_KFIFO(dec->newframe_q);
+
+
+ for (i = 0; i < VF_POOL_SIZE; i++) {
+ const struct vframe_s *vf = &dec->vfpool[i];
+ dec->vfpool[i].index = -1;
+ kfifo_put(&dec->newframe_q, vf);
+ }
+
+
+ ret = avs2_local_init(dec);
+
+ return ret;
+}
+
+
+static s32 vavs2_init(struct vdec_s *vdec)
+{
+ int size = -1;
+ int fw_size = 0x1000 * 16;
+ struct firmware_s *fw = NULL;
+ struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)vdec->private;
+ init_timer(&dec->timer);
+
+ dec->stat |= STAT_TIMER_INIT;
+ if (vavs2_local_init(dec) < 0)
+ return -EBUSY;
+
+ fw = vmalloc(sizeof(struct firmware_s) + fw_size);
+ if (IS_ERR_OR_NULL(fw))
+ return -ENOMEM;
+#ifdef MULTI_INSTANCE_SUPPORT
+ if (tee_enabled()) {
+ size = 1;
+ pr_debug ("laod\n");
+ } else
+#endif
+ size = get_firmware_data(VIDEO_DEC_AVS2_MMU, fw->data);
+ if (size < 0) {
+ pr_err("get firmware fail.\n");
+ vfree(fw);
+ return -1;
+ }
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "firmware size %d\n", size);
+ fw->len = fw_size;
+
+ if (dec->m_ins_flag) {
+ dec->timer.data = (ulong) dec;
+ dec->timer.function = vavs2_put_timer_func;
+ dec->timer.expires = jiffies + PUT_INTERVAL;
+
+ /*add_timer(&dec->timer);
+
+ dec->stat |= STAT_TIMER_ARM;
+ dec->stat |= STAT_ISR_REG;*/
+
+ INIT_WORK(&dec->work, avs2_work);
+ dec->fw = fw;
+
+ return 0;
+ }
+
+ amhevc_enable();
+ if (size == 1)
+ pr_info ("tee load ok\n");
+ else if (amhevc_loadmc_ex(VFORMAT_AVS2, NULL, fw->data) < 0) {
+ amhevc_disable();
+ vfree(fw);
+ return -EBUSY;
+ }
+ avs2_print(dec, AVS2_DBG_BUFMGR,
+ "firmware size %d\n", size);
+
+ vfree(fw);
+ dec->stat |= STAT_MC_LOAD;
+
+ /* enable AMRISC side protocol */
+ vavs2_prot_init(dec);
+
+ if (vdec_request_threaded_irq(VDEC_IRQ_0,
+ vavs2_isr,
+ vavs2_isr_thread_fn,
+ IRQF_ONESHOT,/*run thread on this irq disabled*/
+ "vavs2-irq", (void *)dec)) {
+ pr_info("vavs2 irq register error.\n");
+ amhevc_disable();
+ return -ENOENT;
+ }
+
+ dec->stat |= STAT_ISR_REG;
+
+ dec->provider_name = PROVIDER_NAME;
+ vf_provider_init(&vavs2_vf_prov, PROVIDER_NAME,
+ &vavs2_vf_provider, dec);
+ vf_reg_provider(&vavs2_vf_prov);
+ vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL);
+ if (dec->frame_dur != 0) {
+ if (!is_reset)
+ vf_notify_receiver(dec->provider_name,
+ VFRAME_EVENT_PROVIDER_FR_HINT,
+ (void *)
+ ((unsigned long)dec->frame_dur));
+ }
+ dec->stat |= STAT_VF_HOOK;
+
+ dec->timer.data = (ulong)dec;
+ dec->timer.function = vavs2_put_timer_func;
+ dec->timer.expires = jiffies + PUT_INTERVAL;
+
+
+ add_timer(&dec->timer);
+
+ dec->stat |= STAT_TIMER_ARM;
+
+ /* dec->stat |= STAT_KTHREAD; */
+
+ amhevc_start();
+
+ dec->stat |= STAT_VDEC_RUN;
+
+ dec->init_flag = 1;
+ dec->process_busy = 0;
+ avs2_print(dec, AVS2_DBG_BUFMGR_MORE,
+ "%d, vavs2_init, RP=0x%x\n",
+ __LINE__, READ_VREG(HEVC_STREAM_RD_PTR));
+ return 0;
+}
+
+static int vmavs2_stop(struct AVS2Decoder_s *dec)
+{
+ dec->init_flag = 0;
+
+ if (dec->stat & STAT_TIMER_ARM) {
+ del_timer_sync(&dec->timer);
+ dec->stat &= ~STAT_TIMER_ARM;
+ }
+
+ if (dec->stat & STAT_VF_HOOK) {
+ if (!is_reset)
+ vf_notify_receiver(dec->provider_name,
+ VFRAME_EVENT_PROVIDER_FR_END_HINT,
+ NULL);
+
+ vf_unreg_provider(&vavs2_vf_prov);
+ dec->stat &= ~STAT_VF_HOOK;
+ }
+ avs2_local_uninit(dec);
+ reset_process_time(dec);
+ cancel_work_sync(&dec->work);
+ uninit_mmu_buffers(dec);
+
+ return 0;
+}
+
+
+static int vavs2_stop(struct AVS2Decoder_s *dec)
+{
+
+ dec->init_flag = 0;
+
+ if (dec->stat & STAT_VDEC_RUN) {
+ amhevc_stop();
+ dec->stat &= ~STAT_VDEC_RUN;
+ }
+
+ if (dec->stat & STAT_ISR_REG) {
+ if (!dec->m_ins_flag)
+ WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0);
+ vdec_free_irq(VDEC_IRQ_0, (void *)dec);
+ dec->stat &= ~STAT_ISR_REG;
+ }
+
+ if (dec->stat & STAT_TIMER_ARM) {
+ del_timer_sync(&dec->timer);
+ dec->stat &= ~STAT_TIMER_ARM;
+ }
+
+ if (dec->stat & STAT_VF_HOOK) {
+ if (!is_reset)
+ vf_notify_receiver(dec->provider_name,
+ VFRAME_EVENT_PROVIDER_FR_END_HINT,
+ NULL);
+
+ vf_unreg_provider(&vavs2_vf_prov);
+ dec->stat &= ~STAT_VF_HOOK;
+ }
+ avs2_local_uninit(dec);
+
+ if (dec->m_ins_flag)
+ cancel_work_sync(&dec->work);
+ else
+ amhevc_disable();
+ uninit_mmu_buffers(dec);
+ vfree(dec->fw);
+ dec->fw = NULL;
+
+ return 0;
+}
+
+static int amvdec_avs2_mmu_init(struct AVS2Decoder_s *dec)
+{
+ int tvp_flag = vdec_secure(hw_to_vdec(dec)) ?
+ CODEC_MM_FLAGS_TVP : 0;
+
+#ifdef AVS2_10B_MMU
+ dec->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME,
+ dec->index, FRAME_BUFFERS,
+ 48 * SZ_1M,
+ tvp_flag
+ );
+ if (!dec->mmu_box) {
+ pr_err("avs2 alloc mmu box failed!!\n");
+ return -1;
+ }
+#endif
+ dec->bmmu_box = decoder_bmmu_box_alloc_box(
+ DRIVER_NAME,
+ dec->index,
+ MAX_BMMU_BUFFER_NUM,
+ 4 + PAGE_SHIFT,
+ CODEC_MM_FLAGS_CMA_CLEAR |
+ CODEC_MM_FLAGS_FOR_VDECODER |
+ tvp_flag);
+ if (!dec->bmmu_box) {
+ pr_err("avs2 alloc bmmu box failed!!\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int amvdec_avs2_probe(struct platform_device *pdev)
+{
+ struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
+ struct BUF_s BUF[MAX_BUF_NUM];
+ struct AVS2Decoder_s *dec = &gHevc;
+ int ret;
+ pr_info("%s\n", __func__);
+ mutex_lock(&vavs2_mutex);
+
+ memcpy(&BUF[0], &dec->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
+ memset(dec, 0, sizeof(struct AVS2Decoder_s));
+ memcpy(&dec->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
+
+ dec->init_flag = 0;
+
+ dec->eos = 0;
+ dec->start_process_time = 0;
+ dec->timeout_num = 0;
+ dec->fatal_error = 0;
+ dec->show_frame_num = 0;
+ if (pdata == NULL) {
+ avs2_print(dec, 0,
+ "\namvdec_avs2 memory resource undefined.\n");
+ mutex_unlock(&vavs2_mutex);
+ return -EFAULT;
+ }
+ dec->m_ins_flag = 0;
+ dec->platform_dev = pdev;
+ platform_set_drvdata(pdev, pdata);
+
+ if (amvdec_avs2_mmu_init(dec) < 0) {
+ mutex_unlock(&vavs2_mutex);
+ pr_err("avs2 alloc bmmu box failed!!\n");
+ return -1;
+ }
+
+ ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, WORK_SPACE_BUF_ID,
+ work_buf_size, DRIVER_NAME, &pdata->mem_start);
+ if (ret < 0) {
+ uninit_mmu_buffers(dec);
+ mutex_unlock(&vavs2_mutex);
+ return ret;
+ }
+ dec->buf_size = work_buf_size;
+
+ dec->buf_start = pdata->mem_start;
+
+
+ if (debug) {
+ avs2_print(dec, 0,
+ "===AVS2 decoder mem resource 0x%lx size 0x%x\n",
+ pdata->mem_start, dec->buf_size);
+ }
+
+ if (pdata->sys_info)
+ dec->vavs2_amstream_dec_info = *pdata->sys_info;
+ else {
+ dec->vavs2_amstream_dec_info.width = 0;
+ dec->vavs2_amstream_dec_info.height = 0;
+ dec->vavs2_amstream_dec_info.rate = 30;
+ }
+ dec->cma_dev = pdata->cma_dev;
+
+ pdata->private = dec;
+ pdata->dec_status = vavs2_dec_status;
+ pdata->set_isreset = vavs2_set_isreset;
+ is_reset = 0;
+ if (vavs2_init(pdata) < 0) {
+ pr_info("\namvdec_avs2 init failed.\n");
+ avs2_local_uninit(dec);
+ uninit_mmu_buffers(dec);
+ mutex_unlock(&vavs2_mutex);
+ return -ENODEV;
+ }
+ /*set the max clk for smooth playing...*/
+ hevc_source_changed(VFORMAT_AVS2,
+ 4096, 2048, 60);
+ mutex_unlock(&vavs2_mutex);
+
+ return 0;
+}
+
+static int amvdec_avs2_remove(struct platform_device *pdev)
+{
+ struct AVS2Decoder_s *dec = &gHevc;
+ if (debug)
+ pr_info("amvdec_avs2_remove\n");
+
+ mutex_lock(&vavs2_mutex);
+
+ vavs2_stop(dec);
+
+
+ hevc_source_changed(VFORMAT_AVS2, 0, 0, 0);
+
+
+#ifdef DEBUG_PTS
+ pr_info("pts missed %ld, pts hit %ld, duration %d\n",
+ dec->pts_missed, dec->pts_hit, dec->frame_dur);
+#endif
+
+ mutex_unlock(&vavs2_mutex);
+
+ return 0;
+}
+
+/****************************************/
+
+static struct platform_driver amvdec_avs2_driver = {
+ .probe = amvdec_avs2_probe,
+ .remove = amvdec_avs2_remove,
+#ifdef CONFIG_PM
+ .suspend = amhevc_suspend,
+ .resume = amhevc_resume,
+#endif
+ .driver = {
+ .name = DRIVER_NAME,
+ }
+};
+
+static struct codec_profile_t amvdec_avs2_profile = {
+ .name = "avs2",
+ .profile = ""
+};
+
+static unsigned char get_data_check_sum
+ (struct AVS2Decoder_s *dec, int size)
+{
+ int jj;
+ int sum = 0;
+ u8 *data = ((u8 *)dec->chunk->block->start_virt) +
+ dec->chunk->offset;
+ for (jj = 0; jj < size; jj++)
+ sum += data[jj];
+ return sum;
+}
+
+static void dump_data(struct AVS2Decoder_s *dec, int size)
+{
+ int jj;
+ u8 *data = ((u8 *)dec->chunk->block->start_virt) +
+ dec->chunk->offset;
+ int padding_size = dec->chunk->offset &
+ (VDEC_FIFO_ALIGN - 1);
+ avs2_print(dec, 0, "padding: ");
+ for (jj = padding_size; jj > 0; jj--)
+ avs2_print_cont(dec,
+ 0,
+ "%02x ", *(data - jj));
+ avs2_print_cont(dec, 0, "data adr %p\n",
+ data);
+
+ for (jj = 0; jj < size; jj++) {
+ if ((jj & 0xf) == 0)
+ avs2_print(dec,
+ 0,
+ "%06x:", jj);
+ avs2_print_cont(dec,
+ 0,
+ "%02x ", data[jj]);
+ if (((jj + 1) & 0xf) == 0)
+ avs2_print(dec,
+ 0,
+ "\n");
+ }
+ avs2_print(dec,
+ 0,
+ "\n");
+}
+
+static void avs2_work(struct work_struct *work)
+{
+ struct AVS2Decoder_s *dec = container_of(work,
+ struct AVS2Decoder_s, work);
+ struct vdec_s *vdec = hw_to_vdec(dec);
+ /* finished decoding one frame or error,
+ * notify vdec core to switch context
+ */
+ avs2_print(dec, PRINT_FLAG_VDEC_DETAIL,
+ "%s dec_result %d %x %x %x\n",
+ __func__,
+ dec->dec_result,
+ READ_VREG(HEVC_STREAM_LEVEL),
+ READ_VREG(HEVC_STREAM_WR_PTR),
+ READ_VREG(HEVC_STREAM_RD_PTR));
+
+ if (((dec->dec_result == DEC_RESULT_GET_DATA) ||
+ (dec->dec_result == DEC_RESULT_GET_DATA_RETRY))
+ && (hw_to_vdec(dec)->next_status !=
+ VDEC_STATUS_DISCONNECTED)) {
+ if (!vdec_has_more_input(vdec)) {
+ dec->dec_result = DEC_RESULT_EOS;
+ vdec_schedule_work(&dec->work);
+ return;
+ }
+
+ if (dec->dec_result == DEC_RESULT_GET_DATA) {
+ avs2_print(dec, PRINT_FLAG_VDEC_STATUS,
+ "%s DEC_RESULT_GET_DATA %x %x %x\n",
+ __func__,
+ READ_VREG(HEVC_STREAM_LEVEL),
+ READ_VREG(HEVC_STREAM_WR_PTR),
+ READ_VREG(HEVC_STREAM_RD_PTR));
+ vdec_vframe_dirty(vdec, dec->chunk);
+ vdec_clean_input(vdec);
+ }
+
+ if (get_free_buf_count(dec) >=
+ run_ready_min_buf_num) {
+ int r;
+ int decode_size;
+ r = vdec_prepare_input(vdec, &dec->chunk);
+ if (r < 0) {
+ dec->dec_result = DEC_RESULT_GET_DATA_RETRY;
+
+ avs2_print(dec,
+ PRINT_FLAG_VDEC_DETAIL,
+ "amvdec_vh265: Insufficient data\n");
+
+ vdec_schedule_work(&dec->work);
+ return;
+ }
+ dec->dec_result = DEC_RESULT_NONE;
+ avs2_print(dec, PRINT_FLAG_VDEC_STATUS,
+ "%s: chunk size 0x%x sum 0x%x\n",
+ __func__, r,
+ (debug & PRINT_FLAG_VDEC_STATUS) ?
+ get_data_check_sum(dec, r) : 0
+ );
+ if (debug & PRINT_FLAG_VDEC_DATA)
+ dump_data(dec, dec->chunk->size);
+
+ decode_size = dec->chunk->size +
+ (dec->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+
+ WRITE_VREG(HEVC_DECODE_SIZE,
+ READ_VREG(HEVC_DECODE_SIZE) + decode_size);
+
+ vdec_enable_input(vdec);
+
+ WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE);
+
+ start_process_time(dec);
+
+ } else{
+ dec->dec_result = DEC_RESULT_GET_DATA_RETRY;
+
+ avs2_print(dec, PRINT_FLAG_VDEC_DETAIL,
+ "amvdec_vh265: Insufficient data\n");
+
+ vdec_schedule_work(&dec->work);
+ }
+ return;
+ } else if (dec->dec_result == DEC_RESULT_DONE) {
+ /* if (!dec->ctx_valid)
+ dec->ctx_valid = 1; */
+ dec->slice_idx++;
+ dec->frame_count++;
+ dec->process_state = PROC_STATE_INIT;
+ decode_frame_count[dec->index] = dec->frame_count;
+
+#ifdef AVS2_10B_MMU
+ dec->used_4k_num =
+ (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16);
+#endif
+ avs2_print(dec, PRINT_FLAG_VDEC_STATUS,
+ "%s (===> %d) dec_result %d %x %x %x shiftbytes 0x%x decbytes 0x%x\n",
+ __func__,
+ dec->frame_count,
+ dec->dec_result,
+ READ_VREG(HEVC_STREAM_LEVEL),
+ READ_VREG(HEVC_STREAM_WR_PTR),
+ READ_VREG(HEVC_STREAM_RD_PTR),
+ READ_VREG(HEVC_SHIFT_BYTE_COUNT),
+ READ_VREG(HEVC_SHIFT_BYTE_COUNT) -
+ dec->start_shift_bytes
+ );
+ vdec_vframe_dirty(hw_to_vdec(dec), dec->chunk);
+ } else if (dec->dec_result == DEC_RESULT_AGAIN) {
+ /*
+ stream base: stream buf empty or timeout
+ frame base: vdec_prepare_input fail
+ */
+ if (!vdec_has_more_input(vdec)) {
+ dec->dec_result = DEC_RESULT_EOS;
+ vdec_schedule_work(&dec->work);
+ return;
+ }
+ } else if (dec->dec_result == DEC_RESULT_EOS) {
+ int disp_pos;
+ avs2_print(dec, PRINT_FLAG_VDEC_STATUS,
+ "%s: end of stream\n",
+ __func__);
+ dec->eos = 1;
+ disp_pos = avs2_post_process(&dec->avs2_dec);
+ avs2_prepare_display_buf(dec, disp_pos);
+ vdec_vframe_dirty(hw_to_vdec(dec), dec->chunk);
+ } else if (dec->dec_result == DEC_RESULT_FORCE_EXIT) {
+ avs2_print(dec, PRINT_FLAG_VDEC_STATUS,
+ "%s: force exit\n",
+ __func__);
+ if (dec->stat & STAT_VDEC_RUN) {
+ amhevc_stop();
+ dec->stat &= ~STAT_VDEC_RUN;
+ }
+
+ if (dec->stat & STAT_ISR_REG) {
+ if (!dec->m_ins_flag)
+ WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0);
+ vdec_free_irq(VDEC_IRQ_0, (void *)dec);
+ dec->stat &= ~STAT_ISR_REG;
+ }
+ }
+
+ if (dec->stat & STAT_TIMER_ARM) {
+ del_timer_sync(&dec->timer);
+ dec->stat &= ~STAT_TIMER_ARM;
+ }
+ /* mark itself has all HW resource released and input released */
+ vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
+
+ if (dec->vdec_cb)
+ dec->vdec_cb(hw_to_vdec(dec), dec->vdec_cb_arg);
+}
+
+static int avs2_hw_ctx_restore(struct AVS2Decoder_s *dec)
+{
+ /* new to do ... */
+ vavs2_prot_init(dec);
+ return 0;
+}
+
+static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
+{
+ struct AVS2Decoder_s *dec =
+ (struct AVS2Decoder_s *)vdec->private;
+ bool ret = 0;
+ avs2_print(dec,
+ PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__);
+ if (dec->eos)
+ return ret;
+
+ if ((dec->pic_list_init_flag == 0) ||
+ get_free_buf_count(dec) >=
+ run_ready_min_buf_num)
+ ret = 1;
+ if (ret)
+ not_run_ready[dec->index] = 0;
+ else
+ not_run_ready[dec->index]++;
+ return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0;
+}
+
+static void run(struct vdec_s *vdec, unsigned long mask,
+ void (*callback)(struct vdec_s *, void *), void *arg)
+{
+ struct AVS2Decoder_s *dec =
+ (struct AVS2Decoder_s *)vdec->private;
+ int r;
+
+ run_count[dec->index]++;
+ dec->vdec_cb_arg = arg;
+ dec->vdec_cb = callback;
+ /* dec->chunk = vdec_prepare_input(vdec); */
+ hevc_reset_core(vdec);
+
+ r = vdec_prepare_input(vdec, &dec->chunk);
+ if (r < 0) {
+ input_empty[dec->index]++;
+
+ dec->dec_result = DEC_RESULT_AGAIN;
+
+ avs2_print(dec, PRINT_FLAG_VDEC_DETAIL,
+ "ammvdec_vh265: Insufficient data\n");
+
+ vdec_schedule_work(&dec->work);
+ return;
+ }
+ input_empty[dec->index] = 0;
+ dec->dec_result = DEC_RESULT_NONE;
+ dec->start_shift_bytes = READ_VREG(HEVC_SHIFT_BYTE_COUNT);
+
+ if (debug & PRINT_FLAG_VDEC_STATUS) {
+ int ii;
+ avs2_print(dec, 0,
+ "%s (%d): size 0x%x (0x%x 0x%x) sum 0x%x (%x %x %x %x %x) bytes 0x%x",
+ __func__,
+ dec->frame_count, r,
+ dec->chunk ? dec->chunk->size : 0,
+ dec->chunk ? dec->chunk->offset : 0,
+ (vdec_frame_based(vdec) &&
+ (debug & PRINT_FLAG_VDEC_STATUS)) ?
+ get_data_check_sum(dec, r) : 0,
+ READ_VREG(HEVC_STREAM_START_ADDR),
+ READ_VREG(HEVC_STREAM_END_ADDR),
+ READ_VREG(HEVC_STREAM_LEVEL),
+ READ_VREG(HEVC_STREAM_WR_PTR),
+ READ_VREG(HEVC_STREAM_RD_PTR),
+ dec->start_shift_bytes);
+ if (vdec_frame_based(vdec)) {
+ u8 *data = ((u8 *)dec->chunk->block->start_virt) +
+ dec->chunk->offset;
+ avs2_print_cont(dec, 0, "data adr %p:",
+ data);
+ for (ii = 0; ii < 8; ii++)
+ avs2_print_cont(dec, 0, "%02x ",
+ data[ii]);
+ }
+ avs2_print_cont(dec, 0, "\r\n");
+ }
+ if (vdec->mc_loaded) {
+ /*firmware have load before,
+ and not changes to another.
+ ignore reload.
+ */
+ } else if (amhevc_loadmc_ex(VFORMAT_AVS2, NULL, dec->fw->data) < 0) {
+ vdec->mc_loaded = 0;
+ amhevc_disable();
+ avs2_print(dec, 0,
+ "%s: Error amvdec_loadmc fail\n", __func__);
+ return;
+ } else
+ vdec->mc_loaded = 1;
+
+
+ if (avs2_hw_ctx_restore(dec) < 0) {
+ vdec_schedule_work(&dec->work);
+ return;
+ }
+
+ vdec_enable_input(vdec);
+
+ WRITE_VREG(HEVC_DEC_STATUS_REG, AVS2_ACTION_DONE);
+
+ if (vdec_frame_based(vdec)) {
+ if (debug & PRINT_FLAG_VDEC_DATA)
+ dump_data(dec, dec->chunk->size);
+
+ WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0);
+ r = dec->chunk->size +
+ (dec->chunk->offset & (VDEC_FIFO_ALIGN - 1));
+ }
+
+ WRITE_VREG(HEVC_DECODE_SIZE, r);
+ WRITE_VREG(HEVC_DECODE_COUNT, dec->slice_idx);
+ dec->init_flag = 1;
+
+ avs2_print(dec, PRINT_FLAG_VDEC_DETAIL,
+ "%s: start hevc (%x %x %x)\n",
+ __func__,
+ READ_VREG(HEVC_DEC_STATUS_REG),
+ READ_VREG(HEVC_MPC_E),
+ READ_VREG(HEVC_MPSR));
+
+ start_process_time(dec);
+ mod_timer(&dec->timer, jiffies);
+ dec->stat |= STAT_TIMER_ARM;
+ dec->stat |= STAT_ISR_REG;
+ amhevc_start();
+ dec->stat |= STAT_VDEC_RUN;
+}
+
+static void reset(struct vdec_s *vdec)
+{
+
+ struct AVS2Decoder_s *dec =
+ (struct AVS2Decoder_s *)vdec->private;
+
+ avs2_print(dec,
+ PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__);
+
+}
+
+static irqreturn_t avs2_irq_cb(struct vdec_s *vdec, int irq)
+{
+ struct AVS2Decoder_s *dec =
+ (struct AVS2Decoder_s *)vdec->private;
+ return vavs2_isr(0, dec);
+}
+
+static irqreturn_t avs2_threaded_irq_cb(struct vdec_s *vdec, int irq)
+{
+ struct AVS2Decoder_s *dec =
+ (struct AVS2Decoder_s *)vdec->private;
+ return vavs2_isr_thread_fn(0, dec);
+}
+
+static void avs2_dump_state(struct vdec_s *vdec)
+{
+ struct AVS2Decoder_s *dec =
+ (struct AVS2Decoder_s *)vdec->private;
+ int i;
+ avs2_print(dec, 0, "====== %s\n", __func__);
+
+ avs2_print(dec, 0,
+ "width/height (%d/%d), used_buf_num %d\n",
+ dec->avs2_dec.img.width,
+ dec->avs2_dec.img.height,
+ dec->used_buf_num
+ );
+
+ avs2_print(dec, 0,
+ "is_framebase(%d), eos %d, dec_result 0x%x dec_frm %d disp_frm %d run %d not_run_ready %d input_empty %d\n",
+ input_frame_based(vdec),
+ dec->eos,
+ dec->dec_result,
+ decode_frame_count[dec->index],
+ display_frame_count[dec->index],
+ run_count[dec->index],
+ not_run_ready[dec->index],
+ input_empty[dec->index]
+ );
+
+ if (vf_get_receiver(vdec->vf_provider_name)) {
+ enum receviver_start_e state =
+ vf_notify_receiver(vdec->vf_provider_name,
+ VFRAME_EVENT_PROVIDER_QUREY_STATE,
+ NULL);
+ avs2_print(dec, 0,
+ "\nreceiver(%s) state %d\n",
+ vdec->vf_provider_name,
+ state);
+ }
+
+ avs2_print(dec, 0,
+ "%s, newq(%d/%d), dispq(%d/%d), vf prepare/get/put (%d/%d/%d), free_buf_count %d (min %d for run_ready)\n",
+ __func__,
+ kfifo_len(&dec->newframe_q),
+ VF_POOL_SIZE,
+ kfifo_len(&dec->display_q),
+ VF_POOL_SIZE,
+ dec->vf_pre_count,
+ dec->vf_get_count,
+ dec->vf_put_count,
+ get_free_buf_count(dec),
+ run_ready_min_buf_num
+ );
+
+ dump_pic_list(dec);
+
+ for (i = 0; i < MAX_BUF_NUM; i++) {
+ avs2_print(dec, 0,
+ "mv_Buf(%d) start_adr 0x%x size 0x%x used %d\n",
+ i,
+ dec->m_mv_BUF[i].start_adr,
+ dec->m_mv_BUF[i].size,
+ dec->m_mv_BUF[i].used_flag);
+ }
+
+ avs2_print(dec, 0,
+ "HEVC_DEC_STATUS_REG=0x%x\n",
+ READ_VREG(HEVC_DEC_STATUS_REG));
+ avs2_print(dec, 0,
+ "HEVC_MPC_E=0x%x\n",
+ READ_VREG(HEVC_MPC_E));
+ avs2_print(dec, 0,
+ "DECODE_MODE=0x%x\n",
+ READ_VREG(DECODE_MODE));
+ avs2_print(dec, 0,
+ "NAL_SEARCH_CTL=0x%x\n",
+ READ_VREG(NAL_SEARCH_CTL));
+ avs2_print(dec, 0,
+ "HEVC_PARSER_LCU_START=0x%x\n",
+ READ_VREG(HEVC_PARSER_LCU_START));
+ avs2_print(dec, 0,
+ "HEVC_DECODE_SIZE=0x%x\n",
+ READ_VREG(HEVC_DECODE_SIZE));
+ avs2_print(dec, 0,
+ "HEVC_SHIFT_BYTE_COUNT=0x%x\n",
+ READ_VREG(HEVC_SHIFT_BYTE_COUNT));
+ avs2_print(dec, 0,
+ "HEVC_STREAM_START_ADDR=0x%x\n",
+ READ_VREG(HEVC_STREAM_START_ADDR));
+ avs2_print(dec, 0,
+ "HEVC_STREAM_END_ADDR=0x%x\n",
+ READ_VREG(HEVC_STREAM_END_ADDR));
+ avs2_print(dec, 0,
+ "HEVC_STREAM_LEVEL=0x%x\n",
+ READ_VREG(HEVC_STREAM_LEVEL));
+ avs2_print(dec, 0,
+ "HEVC_STREAM_WR_PTR=0x%x\n",
+ READ_VREG(HEVC_STREAM_WR_PTR));
+ avs2_print(dec, 0,
+ "HEVC_STREAM_RD_PTR=0x%x\n",
+ READ_VREG(HEVC_STREAM_RD_PTR));
+ avs2_print(dec, 0,
+ "PARSER_VIDEO_RP=0x%x\n",
+ READ_PARSER_REG(PARSER_VIDEO_RP));
+ avs2_print(dec, 0,
+ "PARSER_VIDEO_WP=0x%x\n",
+ READ_PARSER_REG(PARSER_VIDEO_WP));
+
+ if (input_frame_based(vdec) &&
+ (debug & PRINT_FLAG_VDEC_DATA)
+ ) {
+ int jj;
+ if (dec->chunk && dec->chunk->block &&
+ dec->chunk->size > 0) {
+ u8 *data =
+ ((u8 *)dec->chunk->block->start_virt) +
+ dec->chunk->offset;
+ avs2_print(dec, 0,
+ "frame data size 0x%x\n",
+ dec->chunk->size);
+ for (jj = 0; jj < dec->chunk->size; jj++) {
+ if ((jj & 0xf) == 0)
+ avs2_print(dec, 0,
+ "%06x:", jj);
+ avs2_print_cont(dec, 0,
+ "%02x ", data[jj]);
+ if (((jj + 1) & 0xf) == 0)
+ avs2_print_cont(dec, 0,
+ "\n");
+ }
+ }
+ }
+
+}
+
+static int ammvdec_avs2_probe(struct platform_device *pdev)
+{
+ struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
+ int ret;
+ int config_val;
+ struct vframe_content_light_level_s content_light_level;
+ struct vframe_master_display_colour_s vf_dp;
+
+ struct BUF_s BUF[MAX_BUF_NUM];
+ struct AVS2Decoder_s *dec = NULL;
+ pr_info("%s\n", __func__);
+ if (pdata == NULL) {
+ pr_info("\nammvdec_avs2 memory resource undefined.\n");
+ return -EFAULT;
+ }
+ /*dec = (struct AVS2Decoder_s *)devm_kzalloc(&pdev->dev,
+ sizeof(struct AVS2Decoder_s), GFP_KERNEL);*/
+ memset(&vf_dp, 0, sizeof(struct vframe_master_display_colour_s));
+ dec = vmalloc(sizeof(struct AVS2Decoder_s));
+ memset(dec, 0, sizeof(struct AVS2Decoder_s));
+ if (dec == NULL) {
+ pr_info("\nammvdec_avs2 device data allocation failed\n");
+ return -ENOMEM;
+ }
+ pdata->private = dec;
+ pdata->dec_status = vavs2_dec_status;
+ /* pdata->set_trickmode = set_trickmode; */
+ pdata->run_ready = run_ready;
+ pdata->run = run;
+ pdata->reset = reset;
+ pdata->irq_handler = avs2_irq_cb;
+ pdata->threaded_irq_handler = avs2_threaded_irq_cb;
+ pdata->dump_state = avs2_dump_state;
+
+
+
+ memcpy(&BUF[0], &dec->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
+ memset(dec, 0, sizeof(struct AVS2Decoder_s));
+ memcpy(&dec->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
+
+ dec->index = pdev->id;
+
+ if (pdata->use_vfm_path)
+ snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
+ VFM_DEC_PROVIDER_NAME);
+ else
+ snprintf(pdata->vf_provider_name, VDEC_PROVIDER_NAME_SIZE,
+ MULTI_INSTANCE_PROVIDER_NAME ".%02x", pdev->id & 0xff);
+
+ vf_provider_init(&pdata->vframe_provider, pdata->vf_provider_name,
+ &vavs2_vf_provider, dec);
+
+ dec->provider_name = pdata->vf_provider_name;
+ platform_set_drvdata(pdev, pdata);
+
+ dec->platform_dev = pdev;
+ dec->video_signal_type = 0;
+ if (get_cpu_type() < MESON_CPU_MAJOR_ID_TXLX)
+ dec->stat |= VP9_TRIGGER_FRAME_ENABLE;
+#if 1
+ if ((debug & IGNORE_PARAM_FROM_CONFIG) == 0 &&
+ pdata->config && pdata->config_len) {
+ /*use ptr config for doubel_write_mode, etc*/
+ avs2_print(dec, 0, "pdata->config=%s\n", pdata->config);
+ if (get_config_int(pdata->config, "avs2_double_write_mode",
+ &config_val) == 0)
+ dec->double_write_mode = config_val;
+ else
+ dec->double_write_mode = double_write_mode;
+ if (get_config_int(pdata->config, "HDRStaticInfo",
+ &vf_dp.present_flag) == 0
+ && vf_dp.present_flag == 1) {
+ get_config_int(pdata->config, "mG.x",
+ &vf_dp.primaries[0][0]);
+ get_config_int(pdata->config, "mG.y",
+ &vf_dp.primaries[0][1]);
+ get_config_int(pdata->config, "mB.x",
+ &vf_dp.primaries[1][0]);
+ get_config_int(pdata->config, "mB.y",
+ &vf_dp.primaries[1][1]);
+ get_config_int(pdata->config, "mR.x",
+ &vf_dp.primaries[2][0]);
+ get_config_int(pdata->config, "mR.y",
+ &vf_dp.primaries[2][1]);
+ get_config_int(pdata->config, "mW.x",
+ &vf_dp.white_point[0]);
+ get_config_int(pdata->config, "mW.y",
+ &vf_dp.white_point[1]);
+ get_config_int(pdata->config, "mMaxDL",
+ &vf_dp.luminance[0]);
+ get_config_int(pdata->config, "mMinDL",
+ &vf_dp.luminance[1]);
+ vf_dp.content_light_level.present_flag = 1;
+ get_config_int(pdata->config, "mMaxCLL",
+ &content_light_level.max_content);
+ get_config_int(pdata->config, "mMaxFALL",
+ &content_light_level.max_pic_average);
+ vf_dp.content_light_level = content_light_level;
+ dec->video_signal_type = (1 << 29)
+ | (5 << 26) /* unspecified */
+ | (0 << 25) /* limit */
+ | (1 << 24) /* color available */
+ | (9 << 16) /* 2020 */
+ | (16 << 8) /* 2084 */
+ | (9 << 0); /* 2020 */
+ }
+ dec->vf_dp = vf_dp;
+ } else
+#endif
+ {
+ /*dec->vavs2_amstream_dec_info.width = 0;
+ dec->vavs2_amstream_dec_info.height = 0;
+ dec->vavs2_amstream_dec_info.rate = 30;*/
+ dec->double_write_mode = double_write_mode;
+ }
+ video_signal_type = dec->video_signal_type;
+
+#if 0
+ dec->buf_start = pdata->mem_start;
+ dec->buf_size = pdata->mem_end - pdata->mem_start + 1;
+#else
+ if (amvdec_avs2_mmu_init(dec) < 0) {
+ pr_err("avs2 alloc bmmu box failed!!\n");
+ /* devm_kfree(&pdev->dev, (void *)dec); */
+ vfree((void *)dec);
+ return -1;
+ }
+ dec->cma_alloc_count = PAGE_ALIGN(work_buf_size) / PAGE_SIZE;
+ ret = decoder_bmmu_box_alloc_buf_phy(dec->bmmu_box, WORK_SPACE_BUF_ID,
+ dec->cma_alloc_count * PAGE_SIZE, DRIVER_NAME,
+ &dec->cma_alloc_addr);
+ if (ret < 0) {
+ uninit_mmu_buffers(dec);
+ /* devm_kfree(&pdev->dev, (void *)dec); */
+ vfree((void *)dec);
+ return ret;
+ }
+ dec->buf_start = dec->cma_alloc_addr;
+ dec->buf_size = work_buf_size;
+#endif
+ dec->m_ins_flag = 1;
+
+ dec->init_flag = 0;
+ dec->fatal_error = 0;
+ dec->show_frame_num = 0;
+ if (pdata == NULL) {
+ pr_info("\namvdec_avs2 memory resource undefined.\n");
+ uninit_mmu_buffers(dec);
+ /* devm_kfree(&pdev->dev, (void *)dec); */
+ vfree((void *)dec);
+ return -EFAULT;
+ }
+
+ if (debug) {
+ pr_info("===AVS2 decoder mem resource 0x%lx size 0x%x\n",
+ dec->buf_start,
+ dec->buf_size);
+ }
+
+ if (pdata->sys_info)
+ dec->vavs2_amstream_dec_info = *pdata->sys_info;
+ else {
+ dec->vavs2_amstream_dec_info.width = 0;
+ dec->vavs2_amstream_dec_info.height = 0;
+ dec->vavs2_amstream_dec_info.rate = 30;
+ }
+
+ dec->cma_dev = pdata->cma_dev;
+ if (vavs2_init(pdata) < 0) {
+ pr_info("\namvdec_avs2 init failed.\n");
+ avs2_local_uninit(dec);
+ uninit_mmu_buffers(dec);
+ /* devm_kfree(&pdev->dev, (void *)dec); */
+ vfree((void *)dec);
+ return -ENODEV;
+ }
+ vdec_set_prepare_level(pdata, start_decode_buf_level);
+ hevc_source_changed(VFORMAT_AVS2,
+ 4096, 2048, 60);
+
+ vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+ | CORE_MASK_COMBINE);
+
+ return 0;
+}
+
+static int ammvdec_avs2_remove(struct platform_device *pdev)
+{
+ struct AVS2Decoder_s *dec = (struct AVS2Decoder_s *)
+ (((struct vdec_s *)(platform_get_drvdata(pdev)))->private);
+ if (debug)
+ pr_info("amvdec_avs2_remove\n");
+
+ vmavs2_stop(dec);
+
+ vdec_core_release(hw_to_vdec(dec), CORE_MASK_HEVC);
+
+ vdec_set_status(hw_to_vdec(dec), VDEC_STATUS_DISCONNECTED);
+
+
+#ifdef DEBUG_PTS
+ pr_info("pts missed %ld, pts hit %ld, duration %d\n",
+ dec->pts_missed, dec->pts_hit, dec->frame_dur);
+#endif
+ /* devm_kfree(&pdev->dev, (void *)dec); */
+ vfree((void *)dec);
+ return 0;
+}
+
+static struct platform_driver ammvdec_avs2_driver = {
+ .probe = ammvdec_avs2_probe,
+ .remove = ammvdec_avs2_remove,
+#ifdef CONFIG_PM
+ .suspend = amvdec_suspend,
+ .resume = amvdec_resume,
+#endif
+ .driver = {
+ .name = MULTI_DRIVER_NAME,
+ }
+};
+#endif
+static struct mconfig avs2_configs[] = {
+ MC_PU32("bit_depth_luma", &bit_depth_luma),
+ MC_PU32("bit_depth_chroma", &bit_depth_chroma),
+ MC_PU32("frame_width", &frame_width),
+ MC_PU32("frame_height", &frame_height),
+ MC_PU32("debug", &debug),
+ MC_PU32("radr", &radr),
+ MC_PU32("rval", &rval),
+ MC_PU32("pop_shorts", &pop_shorts),
+ MC_PU32("dbg_cmd", &dbg_cmd),
+ MC_PU32("dbg_skip_decode_index", &dbg_skip_decode_index),
+ MC_PU32("endian", &endian),
+ MC_PU32("step", &step),
+ MC_PU32("udebug_flag", &udebug_flag),
+ MC_PU32("decode_pic_begin", &decode_pic_begin),
+ MC_PU32("slice_parse_begin", &slice_parse_begin),
+ MC_PU32("i_only_flag", &i_only_flag),
+ MC_PU32("error_handle_policy", &error_handle_policy),
+ MC_PU32("buf_alloc_width", &buf_alloc_width),
+ MC_PU32("buf_alloc_height", &buf_alloc_height),
+ MC_PU32("buf_alloc_depth", &buf_alloc_depth),
+ MC_PU32("buf_alloc_size", &buf_alloc_size),
+ MC_PU32("buffer_mode", &buffer_mode),
+ MC_PU32("buffer_mode_dbg", &buffer_mode_dbg),
+ MC_PU32("max_buf_num", &max_buf_num),
+ MC_PU32("dynamic_buf_num_margin", &dynamic_buf_num_margin),
+ MC_PU32("mem_map_mode", &mem_map_mode),
+ MC_PU32("double_write_mode", &double_write_mode),
+ MC_PU32("enable_mem_saving", &enable_mem_saving),
+ MC_PU32("force_w_h", &force_w_h),
+ MC_PU32("force_fps", &force_fps),
+ MC_PU32("max_decoding_time", &max_decoding_time),
+ MC_PU32("on_no_keyframe_skiped", &on_no_keyframe_skiped),
+ MC_PU32("start_decode_buf_level", &start_decode_buf_level),
+ MC_PU32("decode_timeout_val", &decode_timeout_val),
+};
+static struct mconfig_node avs2_node;
+
+static int __init amvdec_avs2_driver_init_module(void)
+{
+
+#ifdef AVS2_10B_MMU
+
+ struct BuffInfo_s *p_buf_info;
+#ifdef SUPPORT_4K2K
+ if (vdec_is_support_4k())
+ p_buf_info = &amvavs2_workbuff_spec[1];
+ else
+ p_buf_info = &amvavs2_workbuff_spec[0];
+#else
+ p_buf_info = &amvavs2_workbuff_spec[0];
+#endif
+ init_buff_spec(NULL, p_buf_info);
+ work_buf_size =
+ (p_buf_info->end_adr - p_buf_info->start_adr
+ + 0xffff) & (~0xffff);
+
+#endif
+ pr_debug("amvdec_avs2 module init\n");
+
+ error_handle_policy = 0;
+
+#ifdef ERROR_HANDLE_DEBUG
+ dbg_nal_skip_flag = 0;
+ dbg_nal_skip_count = 0;
+#endif
+ udebug_flag = 0;
+ decode_pic_begin = 0;
+ slice_parse_begin = 0;
+ step = 0;
+ buf_alloc_size = 0;
+ if (platform_driver_register(&ammvdec_avs2_driver))
+ pr_err("failed to register ammvdec_avs2 driver\n");
+
+ if (platform_driver_register(&amvdec_avs2_driver)) {
+ pr_err("failed to register amvdec_avs2 driver\n");
+ return -ENODEV;
+ }
+
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL
+ /*&& get_cpu_type() != MESON_CPU_MAJOR_ID_GXLX*/) {
+ if (vdec_is_support_4k())
+ amvdec_avs2_profile.profile =
+ "4k, 10bit, dwrite, compressed";
+ else
+ amvdec_avs2_profile.profile =
+ "10bit, dwrite, compressed";
+ } else {
+ amvdec_avs2_profile.name = "avs2_unsupport";
+ }
+
+ vcodec_profile_register(&amvdec_avs2_profile);
+ INIT_REG_NODE_CONFIGS("media.decoder", &avs2_node,
+ "avs2", avs2_configs, CONFIG_FOR_RW);
+
+ return 0;
+}
+
+static void __exit amvdec_avs2_driver_remove_module(void)
+{
+ pr_debug("amvdec_avs2 module remove.\n");
+ platform_driver_unregister(&ammvdec_avs2_driver);
+ platform_driver_unregister(&amvdec_avs2_driver);
+}
+
+/****************************************/
+
+module_param(bit_depth_luma, uint, 0664);
+MODULE_PARM_DESC(bit_depth_luma, "\n amvdec_avs2 bit_depth_luma\n");
+
+module_param(bit_depth_chroma, uint, 0664);
+MODULE_PARM_DESC(bit_depth_chroma, "\n amvdec_avs2 bit_depth_chroma\n");
+
+module_param(frame_width, uint, 0664);
+MODULE_PARM_DESC(frame_width, "\n amvdec_avs2 frame_width\n");
+
+module_param(frame_height, uint, 0664);
+MODULE_PARM_DESC(frame_height, "\n amvdec_avs2 frame_height\n");
+
+module_param(debug, uint, 0664);
+MODULE_PARM_DESC(debug, "\n amvdec_avs2 debug\n");
+
+module_param(radr, uint, 0664);
+MODULE_PARM_DESC(radr, "\nradr\n");
+
+module_param(rval, uint, 0664);
+MODULE_PARM_DESC(rval, "\nrval\n");
+
+module_param(pop_shorts, uint, 0664);
+MODULE_PARM_DESC(pop_shorts, "\nrval\n");
+
+module_param(dbg_cmd, uint, 0664);
+MODULE_PARM_DESC(dbg_cmd, "\ndbg_cmd\n");
+
+module_param(dbg_skip_decode_index, uint, 0664);
+MODULE_PARM_DESC(dbg_skip_decode_index, "\ndbg_skip_decode_index\n");
+
+module_param(endian, uint, 0664);
+MODULE_PARM_DESC(endian, "\nrval\n");
+
+module_param(step, uint, 0664);
+MODULE_PARM_DESC(step, "\n amvdec_avs2 step\n");
+
+module_param(decode_pic_begin, uint, 0664);
+MODULE_PARM_DESC(decode_pic_begin, "\n amvdec_avs2 decode_pic_begin\n");
+
+module_param(slice_parse_begin, uint, 0664);
+MODULE_PARM_DESC(slice_parse_begin, "\n amvdec_avs2 slice_parse_begin\n");
+
+module_param(i_only_flag, uint, 0664);
+MODULE_PARM_DESC(i_only_flag, "\n amvdec_avs2 i_only_flag\n");
+
+module_param(error_handle_policy, uint, 0664);
+MODULE_PARM_DESC(error_handle_policy, "\n amvdec_avs2 error_handle_policy\n");
+
+module_param(buf_alloc_width, uint, 0664);
+MODULE_PARM_DESC(buf_alloc_width, "\n buf_alloc_width\n");
+
+module_param(buf_alloc_height, uint, 0664);
+MODULE_PARM_DESC(buf_alloc_height, "\n buf_alloc_height\n");
+
+module_param(buf_alloc_depth, uint, 0664);
+MODULE_PARM_DESC(buf_alloc_depth, "\n buf_alloc_depth\n");
+
+module_param(buf_alloc_size, uint, 0664);
+MODULE_PARM_DESC(buf_alloc_size, "\n buf_alloc_size\n");
+
+module_param(buffer_mode, uint, 0664);
+MODULE_PARM_DESC(buffer_mode, "\n buffer_mode\n");
+
+module_param(buffer_mode_dbg, uint, 0664);
+MODULE_PARM_DESC(buffer_mode_dbg, "\n buffer_mode_dbg\n");
+/*USE_BUF_BLOCK*/
+module_param(max_buf_num, uint, 0664);
+MODULE_PARM_DESC(max_buf_num, "\n max_buf_num\n");
+
+module_param(dynamic_buf_num_margin, uint, 0664);
+MODULE_PARM_DESC(dynamic_buf_num_margin, "\n dynamic_buf_num_margin\n");
+
+module_param(mv_buf_margin, uint, 0664);
+MODULE_PARM_DESC(mv_buf_margin, "\n mv_buf_margin\n");
+
+module_param(run_ready_min_buf_num, uint, 0664);
+MODULE_PARM_DESC(run_ready_min_buf_num, "\n run_ready_min_buf_num\n");
+
+/**/
+
+module_param(mem_map_mode, uint, 0664);
+MODULE_PARM_DESC(mem_map_mode, "\n mem_map_mode\n");
+
+module_param(double_write_mode, uint, 0664);
+MODULE_PARM_DESC(double_write_mode, "\n double_write_mode\n");
+
+module_param(enable_mem_saving, uint, 0664);
+MODULE_PARM_DESC(enable_mem_saving, "\n enable_mem_saving\n");
+
+module_param(force_w_h, uint, 0664);
+MODULE_PARM_DESC(force_w_h, "\n force_w_h\n");
+
+module_param(force_fps, uint, 0664);
+MODULE_PARM_DESC(force_fps, "\n force_fps\n");
+
+module_param(max_decoding_time, uint, 0664);
+MODULE_PARM_DESC(max_decoding_time, "\n max_decoding_time\n");
+
+module_param(on_no_keyframe_skiped, uint, 0664);
+MODULE_PARM_DESC(on_no_keyframe_skiped, "\n on_no_keyframe_skiped\n");
+
+
+module_param(start_decode_buf_level, int, 0664);
+MODULE_PARM_DESC(start_decode_buf_level,
+ "\n avs2 start_decode_buf_level\n");
+
+module_param(decode_timeout_val, uint, 0664);
+MODULE_PARM_DESC(decode_timeout_val,
+ "\n avs2 decode_timeout_val\n");
+
+module_param_array(decode_frame_count, uint,
+ &max_decode_instance_num, 0664);
+
+module_param_array(display_frame_count, uint,
+ &max_decode_instance_num, 0664);
+
+module_param_array(max_process_time, uint,
+ &max_decode_instance_num, 0664);
+
+module_param_array(run_count, uint,
+ &max_decode_instance_num, 0664);
+
+module_param_array(input_empty, uint,
+ &max_decode_instance_num, 0664);
+
+module_param_array(not_run_ready, uint,
+ &max_decode_instance_num, 0664);
+
+module_param(udebug_flag, uint, 0664);
+MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n");
+
+module_param(udebug_pause_pos, uint, 0664);
+MODULE_PARM_DESC(udebug_pause_pos, "\n udebug_pause_pos\n");
+
+module_param(udebug_pause_val, uint, 0664);
+MODULE_PARM_DESC(udebug_pause_val, "\n udebug_pause_val\n");
+
+module_param(udebug_pause_decode_idx, uint, 0664);
+MODULE_PARM_DESC(udebug_pause_decode_idx, "\n udebug_pause_decode_idx\n");
+
+module_param(force_disp_pic_index, int, 0664);
+MODULE_PARM_DESC(force_disp_pic_index,
+ "\n amvdec_h265 force_disp_pic_index\n");
+
+module_init(amvdec_avs2_driver_init_module);
+module_exit(amvdec_avs2_driver_remove_module);
+
+MODULE_DESCRIPTION("AMLOGIC avs2 Video Decoder Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Tim Yao <tim.yao@amlogic.com>");
diff --git a/drivers/frame_provider/decoder/avs2/vavs2.h b/drivers/frame_provider/decoder/avs2/vavs2.h
new file mode 100644
index 0000000..6b51f61
--- a/dev/null
+++ b/drivers/frame_provider/decoder/avs2/vavs2.h
@@ -0,0 +1,26 @@
+/*
+ * drivers/amlogic/amports/vavs2.h
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+*/
+
+#ifndef VAVS2_H
+#define VAVS2_H
+
+#define AVS2_10B_MMU
+#define MV_USE_FIXED_BUF
+
+void adapt_coef_probs(int pic_count, int prev_kf, int cur_kf, int pre_fc,
+unsigned int *prev_prob, unsigned int *cur_prob, unsigned int *count);
+#endif
diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c
index b3092f8..aa7159b 100644
--- a/drivers/frame_provider/decoder/h264_multi/vmh264.c
+++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c
@@ -108,7 +108,7 @@
#define H264_MMU
static int mmu_enable;
-static int force_enable_mmu = 1;
+static int force_enable_mmu = 0;
unsigned int h264_debug_flag; /* 0xa0000000; */
unsigned int h264_debug_mask = 0xff;
/*
@@ -3377,7 +3377,7 @@ static void check_decoded_pic_error(struct vdec_h264_hw_s *hw)
}
}
-static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec)
+static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
{
int i;
struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)(vdec->private);
@@ -3990,7 +3990,7 @@ send_again:
/**/
return IRQ_HANDLED;
}
-static irqreturn_t vh264_isr(struct vdec_s *vdec)
+static irqreturn_t vh264_isr(struct vdec_s *vdec, int irq)
{
struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)(vdec->private);
struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
@@ -4673,8 +4673,7 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw)
if (!hw->lmem_addr) {
pr_info("%s: failed to alloc lmem_addr\n", __func__);
return -ENOMEM;
- }
- {
+ } else {
hw->lmem_addr_remap = dma_map_single(
amports_get_dma_device(),
(void *)hw->lmem_addr,
@@ -5049,11 +5048,13 @@ result_done:
vdec_set_next_sched(vdec, vdec);
#endif
+ /* mark itself has all HW resource released and input released */
+ vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
if (hw->vdec_cb)
hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg);
}
-static bool run_ready(struct vdec_s *vdec)
+static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
{
bool ret = 0;
struct vdec_h264_hw_s *hw =
@@ -5061,7 +5062,7 @@ static bool run_ready(struct vdec_s *vdec)
#ifndef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (vdec->master)
- return false;
+ return 0;
#endif
if (hw->eos)
return 0;
@@ -5086,7 +5087,7 @@ static bool run_ready(struct vdec_s *vdec)
not_run_ready[DECODE_ID(hw)] = 0;
else
not_run_ready[DECODE_ID(hw)]++;
- return ret;
+ return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0;
}
static unsigned char get_data_check_sum
@@ -5101,7 +5102,7 @@ static unsigned char get_data_check_sum
return sum;
}
-static void run(struct vdec_s *vdec,
+static void run(struct vdec_s *vdec, unsigned long mask,
void (*callback)(struct vdec_s *, void *), void *arg)
{
struct vdec_h264_hw_s *hw =
@@ -5616,6 +5617,9 @@ static int ammvdec_h264_probe(struct platform_device *pdev)
vdec_set_prepare_level(pdata, start_decode_buf_level);
+ vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+ | CORE_MASK_COMBINE);
+
atomic_set(&hw->vh264_active, 1);
return 0;
@@ -5644,6 +5648,8 @@ static int ammvdec_h264_remove(struct platform_device *pdev)
atomic_set(&hw->vh264_active, 0);
+ vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
+
vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED);
ammvdec_h264_mmu_release(hw);
h264_free_hw_stru(&pdev->dev, (void *)hw);
diff --git a/drivers/frame_provider/decoder/h265/vh265.c b/drivers/frame_provider/decoder/h265/vh265.c
index e0c2365..6a7fbb3 100644
--- a/drivers/frame_provider/decoder/h265/vh265.c
+++ b/drivers/frame_provider/decoder/h265/vh265.c
@@ -49,7 +49,7 @@
/*#define TEST_NO_BUF*/
/*#define HEVC_PIC_STRUCT_SUPPORT*/
#define MULTI_INSTANCE_SUPPORT
-#define USE_UNINIT_SEMA
+
/* .buf_size = 0x100000*16,
//4k2k , 0x100000 per buffer */
/* 4096x2304 , 0x120000 per buffer */
@@ -59,11 +59,16 @@
#define MAX_FRAME_4K_NUM 0x1200
#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4)
#define H265_MMU_MAP_BUFFER HEVC_ASSIST_SCRATCH_7
+
+#define HEVC_ASSIST_MMU_MAP_ADDR 0x3009
+
#define HEVC_CM_HEADER_START_ADDR 0x3628
#define HEVC_SAO_MMU_VH1_ADDR 0x363b
#define HEVC_SAO_MMU_VH0_ADDR 0x363a
#define HEVC_SAO_MMU_STATUS 0x3639
+#define HEVC_DBLK_CFGB 0x350b
+#define HEVCD_MPP_DECOMP_AXIURG_CTL 0x34c7
#define MEM_NAME "codec_265"
@@ -126,7 +131,7 @@ static int vh265_stop(struct hevc_state_s *hevc);
#ifdef MULTI_INSTANCE_SUPPORT
static int vmh265_stop(struct hevc_state_s *hevc);
static s32 vh265_init(struct vdec_s *vdec);
-static bool run_ready(struct vdec_s *vdec);
+static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask);
static void reset_process_time(struct hevc_state_s *hevc);
static void start_process_time(struct hevc_state_s *hevc);
static void restart_process_time(struct hevc_state_s *hevc);
@@ -384,6 +389,8 @@ static u32 max_decoding_time;
* 1, do not set error_mark after reset/recover
*bit 5: 0, check total lcu for every picture
* 1, do not check total lcu
+ *bit 6: 0, do not check head error
+ * 1, check head error
*
*/
@@ -455,11 +462,13 @@ static u32 dv_debug;
DEFINE_SPINLOCK(lock);
-struct task_struct *h265_task;
-#undef DEBUG_REG
+struct task_struct *h265_task = NULL;
+#define DEBUG_REG
#ifdef DEBUG_REG
-void WRITE_VREG_DBG(unsigned int adr, unsigned int val)
+void WRITE_VREG_DBG(unsigned adr, unsigned val)
{
+ if (debug & H265_DEBUG_REG)
+ pr_info("%s(%x, %x)\n", __func__, adr, val);
WRITE_VREG(adr, val);
}
@@ -747,7 +756,7 @@ static unsigned short parser_cmd[PARSER_CMD_NUMBER] = {
#define MAX_INT 0x7FFFFFFF
#define RPM_BEGIN 0x100
-#define modification_list_cur 0x140
+#define modification_list_cur 0x148
#define RPM_END 0x180
#define RPS_USED_BIT 14
@@ -793,8 +802,8 @@ union param_u {
unsigned short tiles_enabled_flag;
unsigned short num_tile_columns_minus1;
unsigned short num_tile_rows_minus1;
- unsigned short tile_width[4];
- unsigned short tile_height[4];
+ unsigned short tile_width[8];
+ unsigned short tile_height[8];
unsigned short misc_flag0;
unsigned short pps_beta_offset_div2;
unsigned short pps_tc_offset_div2;
@@ -856,6 +865,7 @@ struct BuffInfo_s {
struct buff_s scalelut;
struct buff_s dblk_para;
struct buff_s dblk_data;
+ struct buff_s dblk_data2;
struct buff_s mmu_vbh;
struct buff_s cm_header;
struct buff_s mpred_above;
@@ -941,6 +951,9 @@ static struct BuffInfo_s amvh265_workbuff_spec[WORK_BUF_SPEC_NUM] = {
.dblk_data = {
.buf_size = 0x40000,
},
+ .dblk_data2 = {
+ .buf_size = 0x40000,
+ }, /*dblk data for adapter*/
.mmu_vbh = {
.buf_size = 0x5000, /*2*16*2304/4, 4K*/
},
@@ -1033,8 +1046,11 @@ static struct BuffInfo_s amvh265_workbuff_spec[WORK_BUF_SPEC_NUM] = {
.buf_size = 0x20000,
},
.dblk_data = {
- .buf_size = 0x40000,
+ .buf_size = 0x80000,
},
+ .dblk_data2 = {
+ .buf_size = 0x80000,
+ }, /*dblk data for adapter*/
.mmu_vbh = {
.buf_size = 0x5000, /*2*16*2304/4, 4K*/
},
@@ -1094,8 +1110,10 @@ static void init_buff_spec(struct hevc_state_s *hevc,
buf_spec->scalelut.buf_start + buf_spec->scalelut.buf_size;
buf_spec->dblk_data.buf_start =
buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size;
- buf_spec->mmu_vbh.buf_start =
+ buf_spec->dblk_data2.buf_start =
buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size;
+ buf_spec->mmu_vbh.buf_start =
+ buf_spec->dblk_data2.buf_start + buf_spec->dblk_data2.buf_size;
buf_spec->mpred_above.buf_start =
buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size;
#ifdef MV_USE_FIXED_BUF
@@ -1164,6 +1182,9 @@ static void init_buff_spec(struct hevc_state_s *hevc,
"dblk_data.buf_start :%x\n",
buf_spec->dblk_data.buf_start);
hevc_print(hevc, 0,
+ "dblk_data2.buf_start :%x\n",
+ buf_spec->dblk_data2.buf_start);
+ hevc_print(hevc, 0,
"mpred_above.buf_start :%x\n",
buf_spec->mpred_above.buf_start);
#ifdef MV_USE_FIXED_BUF
@@ -1265,8 +1286,8 @@ struct PIC_s {
u32 double_write_mode;
} /*PIC_t */;
-#define MAX_TILE_COL_NUM 5
-#define MAX_TILE_ROW_NUM 5
+#define MAX_TILE_COL_NUM 10
+#define MAX_TILE_ROW_NUM 20
struct tile_s {
int width;
int height;
@@ -1548,8 +1569,6 @@ struct hevc_state_s {
u8 head_error_flag;
int valve_count;
struct firmware_s *fw;
- int max_pic_w;
- int max_pic_h;
} /*hevc_stru_t */;
#ifdef SEND_LMEM_WITH_RPM
@@ -2066,11 +2085,7 @@ static int init_mmu_buffers(struct hevc_state_s *hevc)
{
int tvp_flag = vdec_secure(hw_to_vdec(hevc)) ?
CODEC_MM_FLAGS_TVP : 0;
- int buf_size = 64;
- if ((hevc->max_pic_w * hevc->max_pic_h) > 0 && (hevc->max_pic_w * hevc->max_pic_h) <= 1920*1088) {
- buf_size = 24;
- }
- pr_err("William max_w %d max_h %d\n",hevc->max_pic_w,hevc->max_pic_h);
+
if (hevc->mmu_enable) {
hevc->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME,
hevc->index,
@@ -2863,8 +2878,10 @@ static struct PIC_s *output_pic(struct hevc_state_s *hevc,
pic_display = pic;
else if ((pic->POC == pic_display->POC)
&& (pic->decode_idx <
- pic_display->decode_idx))
- pic_display = pic;
+ pic_display->
+ decode_idx))
+ pic_display
+ = pic;
} else
pic_display = pic;
}
@@ -3454,7 +3471,7 @@ static void hevc_config_work_space_hw(struct hevc_state_s *hevc)
if (get_dbg_flag(hevc))
hevc_print(hevc, 0,
- "%s %x %x %x %x %x %x %x %x %x %x %x %x\n",
+ "%s %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
__func__,
buf_spec->ipp.buf_start,
buf_spec->start_adr,
@@ -3467,7 +3484,8 @@ static void hevc_config_work_space_hw(struct hevc_state_s *hevc)
buf_spec->swap_buf2.buf_start,
buf_spec->scalelut.buf_start,
buf_spec->dblk_para.buf_start,
- buf_spec->dblk_data.buf_start);
+ buf_spec->dblk_data.buf_start,
+ buf_spec->dblk_data2.buf_start);
WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, buf_spec->ipp.buf_start);
if ((get_dbg_flag(hevc) & H265_DEBUG_SEND_PARAM_WITH_REG) == 0)
WRITE_VREG(HEVC_RPM_BUFFER, (u32)hevc->rpm_phy_addr);
@@ -3476,9 +3494,14 @@ static void hevc_config_work_space_hw(struct hevc_state_s *hevc)
WRITE_VREG(HEVC_SPS_BUFFER, buf_spec->sps.buf_start);
WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start);
WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start);
- if (hevc->mmu_enable)
- WRITE_VREG(H265_MMU_MAP_BUFFER, hevc->frame_mmu_map_phy_addr);
- else
+ if (hevc->mmu_enable) {
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
+ WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, hevc->frame_mmu_map_phy_addr);
+ hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
+ "write HEVC_ASSIST_MMU_MAP_ADDR\n");
+ } else
+ WRITE_VREG(H265_MMU_MAP_BUFFER, hevc->frame_mmu_map_phy_addr);
+ } else
WRITE_VREG(HEVC_STREAM_SWAP_BUFFER,
buf_spec->swap_buf.buf_start);
WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, buf_spec->swap_buf2.buf_start);
@@ -3488,8 +3511,9 @@ static void hevc_config_work_space_hw(struct hevc_state_s *hevc)
/* cfg_d_addr */
WRITE_VREG(HEVC_DBLK_CFG5, buf_spec->dblk_data.buf_start);
- WRITE_VREG(LMEM_DUMP_ADR, (u32)hevc->lmem_phy_addr);
+ WRITE_VREG(HEVC_DBLK_CFGE, buf_spec->dblk_data2.buf_start);
+ WRITE_VREG(LMEM_DUMP_ADR, (u32)hevc->lmem_phy_addr);
}
static void hevc_init_decoder_hw(struct hevc_state_s *hevc,
@@ -3497,7 +3521,14 @@ static void hevc_init_decoder_hw(struct hevc_state_s *hevc,
{
unsigned int data32;
int i;
-
+#if 0
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
+ /* Set MCR fetch priorities*/
+ data32 = 0x1 | (0x1 << 2) | (0x1 <<3) |
+ (24 << 4) | (32 << 11) | (24 << 18) | (32 << 25);
+ WRITE_VREG(HEVCD_MPP_DECOMP_AXIURG_CTL, data32);
+ }
+#endif
#if 1
/* m8baby test1902 */
if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR)
@@ -3536,6 +3567,8 @@ static void hevc_init_decoder_hw(struct hevc_state_s *hevc,
if (!hevc->m_ins_flag) {
data32 = READ_VREG(HEVC_STREAM_CONTROL);
data32 = data32 | (1 << 0); /* stream_fetch_enable */
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A)
+ data32 |= (0xf << 25); /*arwlen_axi_max*/
WRITE_VREG(HEVC_STREAM_CONTROL, data32);
}
data32 = READ_VREG(HEVC_SHIFT_STARTCODE);
@@ -4172,6 +4205,24 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params)
#endif
/* DBLK CONFIG HERE */
if (hevc->new_pic) {
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
+ data32 = (0x57 << 8) | /* 1st/2nd write both enable*/
+ (0x0 << 0); /* h265 video format*/
+ if (hevc->pic_w >= 1280)
+ data32 |= (0x1 << 4); /*dblk pipeline mode=1 for performance*/
+ data32 &= (~0x300); /*[8]:first write enable (compress) [9]:double write enable (uncompress)*/
+ if (get_double_write_mode(hevc) == 0)
+ data32 |= (0x1 << 8); /*enable first write*/
+ else if (get_double_write_mode(hevc) == 0x10)
+ data32 |= (0x1 << 9); /*double write only*/
+ else
+ data32 |= ((0x1 << 8) |(0x1 << 9));
+
+ WRITE_VREG(HEVC_DBLK_CFGB, data32);
+ hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
+ "[DBLK DEBUG] HEVC1 CFGB : 0x%x\n", data32);
+ }
+
data32 = (hevc->pic_w | hevc->pic_h << 16);
WRITE_VREG(HEVC_DBLK_CFG2, data32);
@@ -4192,6 +4243,16 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params)
64) ? 0 : ((hevc->lcu_size == 32) ? 1 : 2);
WRITE_VREG(HEVC_DBLK_CFG1, data32);
+
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
+ /*if (debug & 0x80) {*/
+ data32 = 1 << 28; /* Debug only: sts1 chooses dblk_main*/
+ WRITE_VREG(HEVC_DBLK_STS1 + 4, data32); /* 0x3510 */
+ hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
+ "[DBLK DEBUG] HEVC1 STS1 : 0x%x\n",
+ data32);
+ /*}*/
+ }
}
#if 0
data32 = READ_VREG(HEVC_SAO_CTRL1);
@@ -4226,11 +4287,13 @@ static void config_sao_hw(struct hevc_state_s *hevc, union param_u *params)
data32 &= (~0xff0);
/* data32 |= 0x670; // Big-Endian per 64-bit */
data32 |= endian; /* Big-Endian per 64-bit */
- data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/
- if (get_double_write_mode(hevc) == 0)
- data32 |= 0x2; /*disable double write*/
- else if (!hevc->mmu_enable && (get_double_write_mode(hevc) & 0x10))
- data32 |= 0x1; /*disable cm*/
+ if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) {
+ data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/
+ if (get_double_write_mode(hevc) == 0)
+ data32 |= 0x2; /*disable double write*/
+ else if (!hevc->mmu_enable && (get_double_write_mode(hevc) & 0x10))
+ data32 |= 0x1; /*disable cm*/
+ }
WRITE_VREG(HEVC_SAO_CTRL1, data32);
if (get_double_write_mode(hevc) & 0x10) {
@@ -5076,17 +5139,6 @@ static int hevc_slice_segment_header_process(struct hevc_state_s *hevc,
hevc->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW;
return 3;
}
- if (hevc->bit_depth_chroma > 10 ||
- hevc->bit_depth_luma > 10) {
- pr_info("unsupport bitdepth : %u,%u\n",
- hevc->bit_depth_chroma,
- hevc->bit_depth_luma);
- if (!hevc->m_ins_flag)
- debug |= (H265_DEBUG_DIS_LOC_ERROR_PROC |
- H265_DEBUG_DIS_SYS_ERROR_PROC);
- hevc->fatal_error |= DECODER_FATAL_ERROR_SIZE_OVERFLOW;
- return 4;
- }
/* it will cause divide 0 error */
if (hevc->pic_w == 0 || hevc->pic_h == 0) {
@@ -5603,13 +5655,6 @@ static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic,
decoder_mmu_box_free_idx(hevc->mmu_box, new_pic->index);
new_pic->scatter_alloc = 0;
}
- if (cur_mmu_4k_number > MAX_FRAME_4K_NUM) {
- pr_err("over max !! 0x%x width %d height %d\n",
- cur_mmu_4k_number,
- new_pic->width,
- new_pic->height);
- return -1;
- }
ret = decoder_mmu_box_alloc_idx(
hevc->mmu_box,
cur_buf_idx,
@@ -6353,7 +6398,7 @@ static void vh265_vf_put(struct vframe_s *vf, void *op_arg)
hevc->m_PIC[index_top]->output_ready = 0;
if (hevc->wait_buf != 0)
- WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG,
+ WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG,
0x1);
}
}
@@ -6368,7 +6413,7 @@ static void vh265_vf_put(struct vframe_s *vf, void *op_arg)
if (hevc->m_PIC[index_bot]->vf_ref == 0) {
hevc->m_PIC[index_bot]->output_ready = 0;
if (hevc->wait_buf != 0)
- WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG,
+ WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG,
0x1);
}
}
@@ -7223,9 +7268,9 @@ static int hevc_recover(struct hevc_state_s *hevc)
WRITE_VREG(HEVC_WAIT_FLAG, 1);
/* clear mailbox interrupt */
- WRITE_VREG(HEVC_ASSIST_MBOX1_CLR_REG, 1);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1);
/* enable mailbox interrupt */
- WRITE_VREG(HEVC_ASSIST_MBOX1_MASK, 1);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 1);
/* disable PSCALE for hardware sharing */
WRITE_VREG(HEVC_PSCALE_CTRL, 0);
@@ -8295,7 +8340,7 @@ static void vh265_check_timer_func(unsigned long arg)
hevc->
error_system_watchdog_count++;
WRITE_VREG
- (HEVC_ASSIST_MBOX1_IRQ_REG,
+ (HEVC_ASSIST_MBOX0_IRQ_REG,
0x1);
}
} else if (hevc->error_flag == 2) {
@@ -8309,7 +8354,7 @@ static void vh265_check_timer_func(unsigned long arg)
hevc->
error_skip_nal_wt_cnt = 0;
WRITE_VREG
- (HEVC_ASSIST_MBOX1_IRQ_REG,
+ (HEVC_ASSIST_MBOX0_IRQ_REG,
0x1);
}
}
@@ -8356,12 +8401,12 @@ static void vh265_check_timer_func(unsigned long arg)
debug &= ~H265_DEBUG_DUMP_PIC_LIST;
}
if (get_dbg_flag(hevc) & H265_DEBUG_TRIG_SLICE_SEGMENT_PROC) {
- WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG, 0x1);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1);
debug &= ~H265_DEBUG_TRIG_SLICE_SEGMENT_PROC;
}
#ifdef TEST_NO_BUF
if (hevc->wait_buf)
- WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG, 0x1);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1);
#endif
if (get_dbg_flag(hevc) & H265_DEBUG_HW_RESET) {
hevc->error_skip_nal_count = error_skip_nal_count;
@@ -8446,7 +8491,7 @@ static int h265_task_handle(void *data)
hevc->pic_list_init_flag = 2;
hevc_print(hevc, 0, "set pic_list_init_flag to 2\n");
- WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG, 0x1);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1);
}
@@ -8486,12 +8531,7 @@ int vh265_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus)
int vh265_dec_status(struct vdec_info *vstatus)
#endif
{
-#ifdef MULTI_INSTANCE_SUPPORT
- struct hevc_state_s *hevc =
- (struct hevc_state_s *)vdec->private;
-#else
struct hevc_state_s *hevc = &gHevc;
-#endif
vstatus->frame_width = hevc->frame_width;
vstatus->frame_height = hevc->frame_height;
if (hevc->frame_dur != 0)
@@ -8514,10 +8554,9 @@ int vh265_dec_status(struct vdec_info *vstatus)
vstatus->samp_cnt = gvs->samp_cnt;
vstatus->offset = gvs->offset;
}
-#endif
snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name),
"%s", DRIVER_NAME);
-
+#endif
return 0;
}
@@ -8586,6 +8625,8 @@ static void config_decode_mode(struct hevc_state_s *hevc)
if (hevc->m_ins_flag)
decode_mode |=
(hevc->start_decoding_flag << 16);
+ /* set MBX0 interrupt flag */
+ decode_mode |= (0x80 << 24);
WRITE_VREG(HEVC_DECODE_MODE, decode_mode);
WRITE_VREG(HEVC_DECODE_MODE2,
hevc->rps_set_id);
@@ -8607,10 +8648,10 @@ static void vh265_prot_init(struct hevc_state_s *hevc)
/* WRITE_VREG(P_HEVC_MPSR, 1); */
/* clear mailbox interrupt */
- WRITE_VREG(HEVC_ASSIST_MBOX1_CLR_REG, 1);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1);
/* enable mailbox interrupt */
- WRITE_VREG(HEVC_ASSIST_MBOX1_MASK, 1);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 1);
/* disable PSCALE for hardware sharing */
WRITE_VREG(HEVC_PSCALE_CTRL, 0);
@@ -8751,12 +8792,16 @@ static s32 vh265_init(struct hevc_state_s *hevc)
size = 1;
else
#endif
- if (mmu_enable && (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL)) {
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
+ size = get_firmware_data(VIDEO_DEC_HEVC_G12A, fw->data);
+ hevc_print(hevc, 0, "vh265 g12a ucode loaded!\n");
+ } else if (mmu_enable && (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL)) {
size = get_firmware_data(VIDEO_DEC_HEVC_MMU, fw->data);
hevc_print(hevc, 0, "vh265 mmu ucode loaded!\n");
- } else
+ } else {
size = get_firmware_data(VIDEO_DEC_HEVC, fw->data);
-
+ hevc_print(hevc, 0, "vh265 ucode loaded!\n");
+ }
if (size < 0) {
pr_err("get firmware fail.\n");
vfree(fw);
@@ -8776,10 +8821,7 @@ static s32 vh265_init(struct hevc_state_s *hevc)
*/
INIT_WORK(&hevc->work, vh265_work);
-#ifdef USE_UNINIT_SEMA
- sema_init(
- &hevc->h265_uninit_done_sema, 0);
-#endif
+
hevc->fw = fw;
return 0;
@@ -8802,7 +8844,7 @@ static s32 vh265_init(struct hevc_state_s *hevc)
/* enable AMRISC side protocol */
vh265_prot_init(hevc);
- if (vdec_request_threaded_irq(VDEC_IRQ_1, vh265_isr,
+ if (vdec_request_threaded_irq(VDEC_IRQ_0, vh265_isr,
vh265_isr_thread_fn,
IRQF_ONESHOT,/*run thread on this irq disabled*/
"vh265-irq", (void *)hevc)) {
@@ -8866,7 +8908,7 @@ static s32 vh265_init(struct hevc_state_s *hevc)
}
}
/* hevc->stat |= STAT_KTHREAD; */
-
+#if 0
if (get_dbg_flag(hevc) & H265_DEBUG_FORCE_CLK) {
hevc_print(hevc, 0, "%s force clk\n", __func__);
WRITE_VREG(HEVC_IQIT_CLK_RST_CTRL,
@@ -8897,7 +8939,7 @@ static s32 vh265_init(struct hevc_state_s *hevc)
WRITE_VREG(HEVCD_MCRCC_CTL1, READ_VREG(HEVCD_MCRCC_CTL1) |
(1 << 3)); /* 3 */
}
-
+#endif
amhevc_start();
hevc->stat |= STAT_VDEC_RUN;
@@ -8941,8 +8983,8 @@ static int vh265_stop(struct hevc_state_s *hevc)
#ifdef MULTI_INSTANCE_SUPPORT
if (!hevc->m_ins_flag)
#endif
- WRITE_VREG(HEVC_ASSIST_MBOX1_MASK, 0);
- vdec_free_irq(VDEC_IRQ_1, (void *)hevc);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0);
+ vdec_free_irq(VDEC_IRQ_0, (void *)hevc);
hevc->stat &= ~STAT_ISR_REG;
}
@@ -8953,10 +8995,11 @@ static int vh265_stop(struct hevc_state_s *hevc)
}
if (hevc->stat & STAT_VF_HOOK) {
- if (fr_hint_status == VDEC_HINTED && !is_reset)
+ if (fr_hint_status == VDEC_HINTED && !is_reset) {
vf_notify_receiver(hevc->provider_name,
VFRAME_EVENT_PROVIDER_FR_END_HINT,
NULL);
+ }
fr_hint_status = VDEC_NO_NEED_HINT;
vf_unreg_provider(&vh265_vf_prov);
hevc->stat &= ~STAT_VF_HOOK;
@@ -9166,7 +9209,7 @@ static void vh265_work(struct work_struct *work)
hevc_print(hevc, 0,
"set pic_list_init_flag to 2\n");
- WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG, 0x1);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1);
return;
}
@@ -9241,7 +9284,7 @@ static void vh265_work(struct work_struct *work)
}
/*if (is_new_pic_available(hevc)) {*/
- if (run_ready(vdec)) {
+ if (run_ready(vdec, VDEC_HEVC)) {
int r;
int decode_size;
r = vdec_prepare_input(vdec, &hevc->chunk);
@@ -9472,8 +9515,8 @@ static void vh265_work(struct work_struct *work)
#ifdef MULTI_INSTANCE_SUPPORT
if (!hevc->m_ins_flag)
#endif
- WRITE_VREG(HEVC_ASSIST_MBOX1_MASK, 0);
- vdec_free_irq(VDEC_IRQ_1, (void *)hevc);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0);
+ vdec_free_irq(VDEC_IRQ_0, (void *)hevc);
hevc->stat &= ~STAT_ISR_REG;
}
}
@@ -9487,8 +9530,6 @@ static void vh265_work(struct work_struct *work)
del_timer_sync(&hevc->timer);
hevc->stat &= ~STAT_TIMER_ARM;
}
- /* mark itself has all HW resource released and input released */
- vdec_set_status(hw_to_vdec(hevc), VDEC_STATUS_CONNECTED);
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
if (hevc->switch_dvlayer_flag) {
@@ -9500,6 +9541,10 @@ static void vh265_work(struct work_struct *work)
vdec_set_next_sched(vdec, vdec);
#endif
+ /* mark itself has all HW resource released and input released */
+ vdec_core_finish_run(vdec, CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
+
+
if (hevc->vdec_cb)
hevc->vdec_cb(hw_to_vdec(hevc), hevc->vdec_cb_arg);
}
@@ -9511,7 +9556,7 @@ static int vh265_hw_ctx_restore(struct hevc_state_s *hevc)
return 0;
}
-static bool run_ready(struct vdec_s *vdec)
+static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
{
struct hevc_state_s *hevc =
(struct hevc_state_s *)vdec->private;
@@ -9523,14 +9568,6 @@ static bool run_ready(struct vdec_s *vdec)
if (hevc->eos)
return 0;
- if ((hevc->fatal_error &
- DECODER_FATAL_ERROR_SIZE_OVERFLOW) ||
- (hevc->fatal_error & DECODER_FATAL_ERROR_UNKNOWN)) {
- /*decoder fatal error,
- *disable run.
- */
- return 0;
- }
if (disp_vframe_valve_level &&
kfifo_len(&hevc->display_q) >=
@@ -9552,10 +9589,10 @@ static bool run_ready(struct vdec_s *vdec)
not_run_ready[hevc->index] = 0;
else
not_run_ready[hevc->index]++;
- return ret;
+ return ret ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0;
}
-static void run(struct vdec_s *vdec,
+static void run(struct vdec_s *vdec, unsigned long mask,
void (*callback)(struct vdec_s *, void *), void *arg)
{
struct hevc_state_s *hevc =
@@ -9624,10 +9661,16 @@ static void run(struct vdec_s *vdec,
}
}
- if (hevc->mmu_enable &&(get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL))
- loadr = amhevc_vdec_loadmc_ex(vdec, "vh265_mc_mmu", hevc->fw->data);
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A)
+ loadr = amhevc_vdec_loadmc_ex(vdec,
+ "vh265_mc_g12a", hevc->fw->data);
+ else if (hevc->mmu_enable &&
+ (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL))
+ loadr = amhevc_vdec_loadmc_ex(vdec,
+ "vh265_mc_mmu", hevc->fw->data);
else
- loadr = amhevc_vdec_loadmc_ex(vdec, "vh265_mc", hevc->fw->data);
+ loadr = amhevc_vdec_loadmc_ex(vdec,
+ "vh265_mc", hevc->fw->data);
if (loadr < 0) {
amhevc_disable();
@@ -9686,7 +9729,7 @@ static void reset(struct vdec_s *vdec)
}
-static irqreturn_t vh265_irq_cb(struct vdec_s *vdec)
+static irqreturn_t vh265_irq_cb(struct vdec_s *vdec, int irq)
{
struct hevc_state_s *hevc =
(struct hevc_state_s *)vdec->private;
@@ -9694,7 +9737,7 @@ static irqreturn_t vh265_irq_cb(struct vdec_s *vdec)
return vh265_isr(0, hevc);
}
-static irqreturn_t vh265_threaded_irq_cb(struct vdec_s *vdec)
+static irqreturn_t vh265_threaded_irq_cb(struct vdec_s *vdec, int irq)
{
struct hevc_state_s *hevc =
(struct hevc_state_s *)vdec->private;
@@ -10091,16 +10134,6 @@ static int ammvdec_h265_probe(struct platform_device *pdev)
hevc->double_write_mode = config_val;
else
hevc->double_write_mode = double_write_mode;
-
- /*use ptr config for max_pic_w, etc*/
- if (get_config_int(pdata->config, "hevc_buf_width",
- &config_val) == 0) {
- hevc->max_pic_w = config_val;
- }
- if (get_config_int(pdata->config, "hevc_buf_height",
- &config_val) == 0) {
- hevc->max_pic_h = config_val;
- }
#endif
} else {
hevc->vh265_amstream_dec_info.width = 0;
@@ -10195,6 +10228,9 @@ static int ammvdec_h265_probe(struct platform_device *pdev)
hevc_source_changed(VFORMAT_HEVC,
3840, 2160, 60);
+ vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+ | CORE_MASK_COMBINE);
+
return 0;
}
@@ -10211,6 +10247,8 @@ static int ammvdec_h265_remove(struct platform_device *pdev)
/* vdec_source_changed(VFORMAT_H264, 0, 0, 0); */
+ vdec_core_release(hw_to_vdec(hevc), CORE_MASK_HEVC);
+
vdec_set_status(hw_to_vdec(hevc), VDEC_STATUS_DISCONNECTED);
vfree((void *)hevc);
diff --git a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
index 2197d50..a0b4493 100644
--- a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
+++ b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
@@ -178,7 +178,7 @@ static void set_frame_info(struct vdec_mjpeg_hw_s *hw, struct vframe_s *vf)
vf->canvas1_config[2] = hw->buffer_spec[vf->index].canvas_config[2];
}
-static irqreturn_t vmjpeg_isr(struct vdec_s *vdec)
+static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq)
{
struct vdec_mjpeg_hw_s *hw = (struct vdec_mjpeg_hw_s *)(vdec->private);
u32 reg;
@@ -662,7 +662,7 @@ static s32 vmjpeg_init(struct vdec_s *vdec)
return 0;
}
-static bool run_ready(struct vdec_s *vdec)
+static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
{
struct vdec_mjpeg_hw_s *hw =
(struct vdec_mjpeg_hw_s *)vdec->private;
@@ -682,10 +682,10 @@ static bool run_ready(struct vdec_s *vdec)
if (level < pre_decode_buf_level)
return 0;
}
- return true;
+ return CORE_MASK_VDEC_1 | CORE_MASK_HEVC;
}
-static void run(struct vdec_s *vdec,
+static void run(struct vdec_s *vdec, unsigned long mask,
void (*callback)(struct vdec_s *, void *), void *arg)
{
struct vdec_mjpeg_hw_s *hw =
@@ -796,6 +796,8 @@ static void vmjpeg_work(struct work_struct *work)
amvdec_stop();
/* mark itself has all HW resource released and input released */
vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_CONNECTED);
+ vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1
+ | CORE_MASK_HEVC);
del_timer_sync(&hw->check_timer);
hw->stat &= ~STAT_TIMER_ARM;
@@ -850,6 +852,9 @@ static int amvdec_mjpeg_probe(struct platform_device *pdev)
return -ENODEV;
}
+ vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+ | CORE_MASK_COMBINE);
+
return 0;
}
@@ -873,6 +878,7 @@ static int amvdec_mjpeg_remove(struct platform_device *pdev)
vfree(hw->fw);
hw->fw = NULL;
+ vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_DISCONNECTED);
return 0;
diff --git a/drivers/frame_provider/decoder/mpeg12/vmpeg12.c b/drivers/frame_provider/decoder/mpeg12/vmpeg12.c
index eecb729..4fd72c6 100644
--- a/drivers/frame_provider/decoder/mpeg12/vmpeg12.c
+++ b/drivers/frame_provider/decoder/mpeg12/vmpeg12.c
@@ -32,13 +32,14 @@
#include <linux/amlogic/cpu_version.h>
#include <linux/amlogic/media/codec_mm/codec_mm.h>
#include <linux/dma-mapping.h>
-
+#include <linux/slab.h>
#include <linux/amlogic/media/utils/vdec_reg.h>
#include "vmpeg12.h"
#include <linux/amlogic/media/registers/register.h>
#include "../../../stream_input/amports/amports_priv.h"
#include "../utils/decoder_mmu_box.h"
#include "../utils/decoder_bmmu_box.h"
+#include <linux/uaccess.h>
#include <linux/amlogic/media/codec_mm/configs.h>
#ifdef CONFIG_AM_VDEC_MPEG12_LOG
@@ -73,6 +74,7 @@ MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_LEVEL_DESC, LOG_DEFAULT_MASK_DESC);
#define MREG_FRAME_OFFSET AV_SCRATCH_D
#define MREG_WAIT_BUFFER AV_SCRATCH_E
#define MREG_FATAL_ERROR AV_SCRATCH_F
+#define MREG_FORCE_I_RDY AV_SCRATCH_G
#define PICINFO_ERROR 0x80000000
#define PICINFO_TYPE_MASK 0x00030000
@@ -168,6 +170,7 @@ static void *ccbuf_phyAddress_virt;
static int ccbuf_phyAddress_is_remaped_nocache;
static u32 lastpts;
static u32 fr_hint_status;
+static u32 last_offset;
static DEFINE_SPINLOCK(lock);
@@ -176,19 +179,41 @@ static u32 frame_rpt_state;
static struct dec_sysinfo vmpeg12_amstream_dec_info;
static struct vdec_info *gvs;
+static struct vdec_s *vdec;
/* for error handling */
static s32 frame_force_skip_flag;
static s32 error_frame_skip_level;
static s32 wait_buffer_counter;
static u32 first_i_frame_ready;
+static u32 force_first_i_ready;
static struct work_struct userdata_push_work;
static struct work_struct notify_work;
static struct work_struct reset_work;
-static struct work_struct set_clk_work;
static bool is_reset;
+struct mpeg12_userdata_recored_t {
+ struct userdata_meta_info_t meta_info;
+ u32 rec_start;
+ u32 rec_len;
+};
+
+#define USERDATA_FIFO_NUM 256
+
+struct mpeg12_userdata_info_t {
+ struct mpeg12_userdata_recored_t records[USERDATA_FIFO_NUM];
+ u8 *data_buf;
+ u8 *data_buf_end;
+ u32 buf_len;
+ u32 read_index;
+ u32 write_index;
+ u32 last_wp;
+};
+
+static struct mpeg12_userdata_info_t *p_userdata_mgr;
+
+
static inline int pool_index(struct vframe_s *vf)
{
if ((vf >= &vfpool[0]) && (vf <= &vfpool[VF_POOL_SIZE - 1]))
@@ -287,15 +312,297 @@ static bool error_skip(u32 info, struct vframe_s *vf)
return false;
}
+
+static void aml_swap_data(uint8_t *user_data, int ud_size)
+{
+ int swap_blocks, i, j, k, m;
+ unsigned char c_temp;
+
+ /* swap byte order */
+ swap_blocks = ud_size / 8;
+ for (i = 0; i < swap_blocks; i++) {
+ j = i * 8;
+ k = j + 7;
+ for (m = 0; m < 4; m++) {
+ c_temp = user_data[j];
+ user_data[j++] = user_data[k];
+ user_data[k--] = c_temp;
+ }
+ }
+}
+
+/*
+#define DUMP_USER_DATA
+*/
+#ifdef DUMP_USER_DATA
+static int last_wp;
+#define DUMP_USER_DATA_HEX
+
+
+#ifdef DUMP_USER_DATA_HEX
+static void print_data(unsigned char *pdata,
+ int len,
+ unsigned int flag,
+ unsigned int duration,
+ unsigned int vpts,
+ unsigned int vpts_valid,
+ int rec_id)
+{
+ int nLeft;
+
+ nLeft = len;
+
+ pr_info("%d len = %d, flag = %d, duration = %d, vpts = 0x%x, vpts_valid = %d\n",
+ rec_id, len, flag,
+ duration, vpts, vpts_valid);
+
+ while (nLeft >= 16) {
+ pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ pdata[0], pdata[1], pdata[2], pdata[3],
+ pdata[4], pdata[5], pdata[6], pdata[7],
+ pdata[8], pdata[9], pdata[10], pdata[11],
+ pdata[12], pdata[13], pdata[14], pdata[15]);
+ nLeft -= 16;
+ pdata += 16;
+ }
+
+
+ while (nLeft > 0) {
+ pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ pdata[0], pdata[1], pdata[2], pdata[3],
+ pdata[4], pdata[5], pdata[6], pdata[7]);
+ nLeft -= 8;
+ pdata += 8;
+ }
+}
+#endif
+
+
+static void dump_data(u8 *pdata,
+ unsigned int user_data_length,
+ unsigned int flag,
+ unsigned int duration,
+ unsigned int vpts,
+ unsigned int vpts_valid,
+ int rec_id)
+{
+ unsigned char szBuf[256];
+
+
+ memset(szBuf, 0, 256);
+ memcpy(szBuf, pdata, user_data_length);
+
+ aml_swap_data(szBuf, user_data_length);
+#ifdef DUMP_USER_DATA_HEX
+ print_data(szBuf,
+ user_data_length,
+ flag,
+ duration,
+ vpts,
+ vpts_valid,
+ rec_id);
+#endif
+
+#ifdef DEBUG_CC_DUMP_ASCII
+ dump_cc_ascii(szBuf+4);
+#endif
+}
+
+
+static void push_to_buf(u8 *pdata, int len, struct userdata_meta_info_t *pmeta);
+
+static void dump_userdata_info(void *puser_data,
+ int len,
+ struct userdata_meta_info_t *pmeta)
+{
+ u8 *pstart;
+
+ pstart = (u8 *)puser_data;
+
+ push_to_buf(pstart+8, len - 8, pmeta);
+ /* push_to_buf(pstart, len, pmeta); */
+}
+
+#define MAX_USER_DATA_SIZE 1572864
+static void *user_data_buf;
+static unsigned char *pbuf_start;
+static int total_len;
+static int bskip;
+static int n_userdata_id;
+
+static void reset_user_data_buf(void)
+{
+ total_len = 0;
+ pbuf_start = user_data_buf;
+ bskip = 0;
+ n_userdata_id = 0;
+}
+
+static void push_to_buf(u8 *pdata, int len, struct userdata_meta_info_t *pmeta)
+{
+ u32 *pLen;
+ int info_cnt;
+ u8 *pbuf_end;
+
+ if (!user_data_buf)
+ return;
+
+ if (bskip) {
+ pr_info("over size, skip\n");
+ return;
+ }
+ info_cnt = 0;
+ pLen = (u32 *)pbuf_start;
+
+ *pLen = len;
+ pbuf_start += sizeof(u32);
+ info_cnt++;
+ pLen++;
+
+ *pLen = pmeta->duration;
+ pbuf_start += sizeof(u32);
+ info_cnt++;
+ pLen++;
+
+ *pLen = pmeta->flags;
+ pbuf_start += sizeof(u32);
+ info_cnt++;
+ pLen++;
+
+ *pLen = pmeta->vpts;
+ pbuf_start += sizeof(u32);
+ info_cnt++;
+ pLen++;
+
+ *pLen = pmeta->vpts_valid;
+ pbuf_start += sizeof(u32);
+ info_cnt++;
+ pLen++;
+
+
+ *pLen = n_userdata_id;
+ pbuf_start += sizeof(u32);
+ info_cnt++;
+ pLen++;
+
+
+
+ pbuf_end = (u8 *)ccbuf_phyAddress_virt + CCBUF_SIZE;
+ if (pdata + len > pbuf_end) {
+ int first_section_len;
+
+ first_section_len = pbuf_end - pdata;
+ memcpy(pbuf_start, pdata, first_section_len);
+ pdata = (u8 *)ccbuf_phyAddress_virt;
+ pbuf_start += first_section_len;
+ memcpy(pbuf_start, pdata, len - first_section_len);
+ pbuf_start += len - first_section_len;
+ } else {
+ memcpy(pbuf_start, pdata, len);
+ pbuf_start += len;
+ }
+
+ total_len += len + info_cnt * sizeof(u32);
+ if (total_len >= MAX_USER_DATA_SIZE-4096)
+ bskip = 1;
+}
+
+static void show_user_data_buf(void)
+{
+ u8 *pbuf;
+ int len;
+ unsigned int flag;
+ unsigned int duration;
+ unsigned int vpts;
+ unsigned int vpts_valid;
+ int rec_id;
+
+ pr_info("show user data buf\n");
+ pbuf = user_data_buf;
+
+ while (pbuf < pbuf_start) {
+ u32 *pLen;
+
+ pLen = (u32 *)pbuf;
+
+ len = *pLen;
+ pLen++;
+ pbuf += sizeof(u32);
+
+ duration = *pLen;
+ pLen++;
+ pbuf += sizeof(u32);
+
+ flag = *pLen;
+ pLen++;
+ pbuf += sizeof(u32);
+
+ vpts = *pLen;
+ pLen++;
+ pbuf += sizeof(u32);
+
+ vpts_valid = *pLen;
+ pLen++;
+ pbuf += sizeof(u32);
+
+ rec_id = *pLen;
+ pLen++;
+ pbuf += sizeof(u32);
+
+ dump_data(pbuf, len, flag, duration, vpts, vpts_valid, rec_id);
+ pbuf += len;
+ }
+}
+#endif
+
+static void vmpeg12_add_userdata(struct userdata_meta_info_t meta_info, int wp);
+/*
+#define PRINT_HEAD_INFO
+*/
static void userdata_push_do_work(struct work_struct *work)
{
u32 reg;
+ u32 offset, pts;
+ u64 pts_us64 = 0;
+ u8 *pdata;
+ u8 head_info[8];
+ struct userdata_meta_info_t meta_info;
+ u32 wp;
+ u32 index;
+ u32 picture_struct;
+ u32 reference;
+ u32 picture_type;
+ u32 temp;
+#ifdef PRINT_HEAD_INFO
+ u8 *ptype_str;
+#endif
+ memset(&meta_info, 0, sizeof(meta_info));
- struct userdata_poc_info_t user_data_poc;
+ meta_info.duration = frame_dur;
- user_data_poc.poc_info = 0;
- user_data_poc.poc_number = 0;
- reg = READ_VREG(MREG_BUFFEROUT);
+ reg = READ_VREG(AV_SCRATCH_M);
+ meta_info.flags = ((reg >> 30) << 1);
+ meta_info.flags |= (VFORMAT_MPEG12 << 3);
+ /* check top_field_first flag */
+ if ((reg >> 28) & 0x1) {
+ meta_info.flags |= (1 << 10);
+ meta_info.flags |= (((reg >> 29) & 0x1) << 11);
+ }
+
+ offset = READ_VREG(AV_SCRATCH_N);
+ if (offset != last_offset) {
+ meta_info.flags |= 1;
+ last_offset = offset;
+ }
+
+ if (pts_pickout_offset_us64
+ (PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) != 0) {
+ pr_info("pick out pts failed by offset = 0x%x\n", offset);
+ pts = -1;
+ meta_info.vpts_valid = 0;
+ } else
+ meta_info.vpts_valid = 1;
+ meta_info.vpts = pts;
if (!ccbuf_phyAddress_is_remaped_nocache &&
ccbuf_phyAddress &&
@@ -305,11 +612,79 @@ static void userdata_push_do_work(struct work_struct *work)
CCBUF_SIZE,
DMA_FROM_DEVICE);
}
- wakeup_userdata_poll(user_data_poc,
- reg & 0xffff,
- (unsigned long)ccbuf_phyAddress_virt,
- CCBUF_SIZE, 0);
- WRITE_VREG(MREG_BUFFEROUT, 0);
+
+
+ if (p_userdata_mgr) {
+ pdata = (u8 *)ccbuf_phyAddress_virt + p_userdata_mgr->last_wp;
+ memcpy(head_info, pdata, 8);
+ } else
+ memset(head_info, 0, 8);
+ aml_swap_data(head_info, 8);
+
+ wp = (head_info[0] << 8 | head_info[1]);
+ index = (head_info[2] << 8 | head_info[3]);
+
+ picture_struct = (head_info[6] << 8 | head_info[7]);
+ temp = (head_info[4] << 8 | head_info[5]);
+ reference = temp & 0x3FF;
+ picture_type = (temp >> 10) & 0x7;
+
+#if 0
+ pr_info("index = %d, wp = %d, ref = %d, type = %d, struct = 0x%x\n",
+ index, wp, reference,
+ picture_type, picture_struct);
+#endif
+ switch (picture_type) {
+ case 1:
+ /* pr_info("I type, pos:%d\n",
+ (meta_info.flags>>1)&0x3); */
+ meta_info.flags |= (1<<7);
+#ifdef PRINT_HEAD_INFO
+ ptype_str = " I";
+#endif
+ break;
+ case 2:
+ /* pr_info("P type, pos:%d\n",
+ (meta_info.flags>>1)&0x3); */
+ meta_info.flags |= (2<<7);
+#ifdef PRINT_HEAD_INFO
+ ptype_str = " P";
+#endif
+ break;
+ case 3:
+ /* pr_info("B type, pos:%d\n",
+ (meta_info.flags>>1)&0x3); */
+ meta_info.flags |= (3<<7);
+#ifdef PRINT_HEAD_INFO
+ ptype_str = " B";
+#endif
+ break;
+ case 4:
+ /* pr_info("D type, pos:%d\n",
+ (meta_info.flags>>1)&0x3); */
+ meta_info.flags |= (4<<7);
+#ifdef PRINT_HEAD_INFO
+ ptype_str = " D";
+#endif
+ break;
+ default:
+ /* pr_info("Unknown type:0x%x, pos:%d\n",
+ pheader->picture_coding_type,
+ (meta_info.flags>>1)&0x3); */
+#ifdef PRINT_HEAD_INFO
+ ptype_str = " U";
+#endif
+ break;
+ }
+#ifdef PRINT_HEAD_INFO
+ pr_info("ref:%d, type:%s, ext:%d, offset:0x%x, first:%d\n",
+ reference, ptype_str,
+ (reg >> 30), offset,
+ (reg >> 28)&0x3);
+#endif
+ vmpeg12_add_userdata(meta_info, reg & 0xffff);
+
+ WRITE_VREG(AV_SCRATCH_M, 0);
}
static void vmpeg12_notify_work(struct work_struct *work)
@@ -333,9 +708,7 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id)
reg = READ_VREG(MREG_BUFFEROUT);
- if ((reg >> 16) == 0xfe) {
- schedule_work(&userdata_push_work);
- } else if (reg) {
+ if (reg) {
info = READ_VREG(MREG_PIC_INFO);
offset = READ_VREG(MREG_FRAME_OFFSET);
seqinfo = READ_VREG(MREG_SEQ_INFO);
@@ -648,6 +1021,10 @@ static irqreturn_t vmpeg12_isr(int irq, void *dev_id)
WRITE_VREG(MREG_BUFFEROUT, 0);
}
+ reg = READ_VREG(AV_SCRATCH_M);
+ if (reg & (1<<16))
+ schedule_work(&userdata_push_work);
+
return IRQ_HANDLED;
}
@@ -725,6 +1102,8 @@ static void vmpeg12_ppmgr_reset(void)
}
#endif
+static void vmpeg12_reset_userdata_fifo(struct vdec_s *vdec, int bInit);
+
static void reset_do_work(struct work_struct *work)
{
amvdec_stop();
@@ -737,19 +1116,12 @@ static void reset_do_work(struct work_struct *work)
vf_reg_provider(&vmpeg_vf_prov);
#endif
vmpeg12_prot_init();
- amvdec_start();
-}
-
-static void vmpeg12_set_clk(struct work_struct *work)
-{
- if (frame_dur > 0 && saved_resolution !=
- frame_width * frame_height * (96000 / frame_dur)) {
- int fps = 96000 / frame_dur;
+ vmpeg12_reset_userdata_fifo(vdec, 1);
+#ifdef DUMP_USER_DATA
+ last_wp = 0;
+#endif
- saved_resolution = frame_width * frame_height * fps;
- vdec_source_changed(VFORMAT_MPEG12,
- frame_width, frame_height, fps);
- }
+ amvdec_start();
}
static void vmpeg_put_timer_func(unsigned long arg)
@@ -806,7 +1178,13 @@ static void vmpeg_put_timer_func(unsigned long arg)
}
}
- schedule_work(&set_clk_work);
+ if (frame_dur > 0 && saved_resolution !=
+ frame_width * frame_height * (96000 / frame_dur)) {
+ int fps = 96000 / frame_dur;
+ saved_resolution = frame_width * frame_height * fps;
+ vdec_source_changed(VFORMAT_MPEG12,
+ frame_width, frame_height, fps);
+ }
timer->expires = jiffies + PUT_INTERVAL;
@@ -845,6 +1223,284 @@ int vmpeg12_set_isreset(struct vdec_s *vdec, int isreset)
return 0;
}
+static DEFINE_MUTEX(userdata_mutex);
+
+
+void vmpeg12_crate_userdata_manager(u8 *userdata_buf, int buf_len)
+{
+ p_userdata_mgr = (struct mpeg12_userdata_info_t *)
+ vmalloc(sizeof(struct mpeg12_userdata_info_t));
+ if (p_userdata_mgr) {
+ memset(p_userdata_mgr, 0,
+ sizeof(struct mpeg12_userdata_info_t));
+ p_userdata_mgr->data_buf = userdata_buf;
+ p_userdata_mgr->buf_len = buf_len;
+ p_userdata_mgr->data_buf_end = userdata_buf + buf_len;
+ }
+}
+
+void vmpeg12_destroy_userdata_manager(void)
+{
+ if (p_userdata_mgr) {
+ vfree(p_userdata_mgr);
+ p_userdata_mgr = NULL;
+ }
+}
+
+static void vmpeg12_add_userdata(struct userdata_meta_info_t meta_info, int wp)
+{
+ struct mpeg12_userdata_recored_t *p_userdata_rec;
+ int data_length;
+
+ mutex_lock(&userdata_mutex);
+
+ if (p_userdata_mgr) {
+ if (wp > p_userdata_mgr->last_wp)
+ data_length = wp - p_userdata_mgr->last_wp;
+ else {
+ p_userdata_mgr->last_wp = 0;
+ data_length = wp - p_userdata_mgr->last_wp;
+ }
+
+ if (data_length & 0x7)
+ data_length = (((data_length + 8) >> 3) << 3);
+/*
+pr_info("wakeup_push: ri:%d, wi:%d, data_len:%d, last_wp:%d, wp:%d, id = %d\n",
+ p_userdata_mgr->read_index,
+ p_userdata_mgr->write_index,
+ data_length,
+ p_userdata_mgr->last_wp,
+ wp,
+ n_userdata_id);
+*/
+ p_userdata_rec = p_userdata_mgr->records
+ + p_userdata_mgr->write_index;
+ p_userdata_rec->meta_info = meta_info;
+ p_userdata_rec->rec_start = p_userdata_mgr->last_wp;
+ p_userdata_rec->rec_len = data_length;
+ p_userdata_mgr->last_wp = wp;
+
+#ifdef DUMP_USER_DATA
+ dump_userdata_info(p_userdata_mgr->data_buf
+ + p_userdata_rec->rec_start,
+ data_length,
+ &meta_info);
+ n_userdata_id++;
+#endif
+
+ p_userdata_mgr->write_index++;
+ if (p_userdata_mgr->write_index >= USERDATA_FIFO_NUM)
+ p_userdata_mgr->write_index = 0;
+ }
+ mutex_unlock(&userdata_mutex);
+
+ vdec_wakeup_userdata_poll(vdec);
+}
+
+
+static int vmpeg12_user_data_read(struct vdec_s *vdec,
+ struct userdata_param_t *puserdata_para)
+{
+ int rec_ri, rec_wi;
+ int rec_len;
+ u8 *rec_data_start;
+ u8 *pdest_buf;
+ struct mpeg12_userdata_recored_t *p_userdata_rec;
+
+
+ u32 data_size;
+ u32 res;
+ int copy_ok = 1;
+
+ pdest_buf = (void *)(puserdata_para->pbuf_addr);
+ mutex_lock(&userdata_mutex);
+
+ if (!p_userdata_mgr) {
+ mutex_unlock(&userdata_mutex);
+ return 0;
+ }
+/*
+ pr_info("ri = %d, wi = %d\n",
+ p_userdata_mgr->read_index,
+ p_userdata_mgr->write_index);
+*/
+ rec_ri = p_userdata_mgr->read_index;
+ rec_wi = p_userdata_mgr->write_index;
+
+ if (rec_ri == rec_wi) {
+ mutex_unlock(&userdata_mutex);
+ return 0;
+ }
+
+ p_userdata_rec = p_userdata_mgr->records + rec_ri;
+
+ rec_len = p_userdata_rec->rec_len;
+ rec_data_start = p_userdata_rec->rec_start + p_userdata_mgr->data_buf;
+/*
+ pr_info("rec_len:%d, rec_start:%d, buf_len:%d\n",
+ p_userdata_rec->rec_len,
+ p_userdata_rec->rec_start,
+ puserdata_para->buf_len);
+*/
+ if (rec_len <= puserdata_para->buf_len) {
+ /* dvb user data buffer is enought to copy the whole recored. */
+ data_size = rec_len;
+ if (rec_data_start + data_size
+ > p_userdata_mgr->data_buf_end) {
+ int first_section_len;
+
+ first_section_len = p_userdata_mgr->buf_len
+ - p_userdata_rec->rec_start;
+ res = (u32)copy_to_user((void *)pdest_buf,
+ (void *)rec_data_start,
+ first_section_len);
+ if (res) {
+ pr_info("p1 read not end res=%d, request=%d\n",
+ res, first_section_len);
+ copy_ok = 0;
+
+ p_userdata_rec->rec_len -=
+ first_section_len - res;
+ p_userdata_rec->rec_start +=
+ first_section_len - res;
+ puserdata_para->data_size =
+ first_section_len - res;
+ } else {
+ res = (u32)copy_to_user(
+ (void *)(pdest_buf+first_section_len),
+ (void *)p_userdata_mgr->data_buf,
+ data_size - first_section_len);
+ if (res) {
+ pr_info("p2 read not end res=%d, request=%d\n",
+ res, data_size);
+ copy_ok = 0;
+ }
+ p_userdata_rec->rec_len -= data_size - res;
+ p_userdata_rec->rec_start =
+ data_size - first_section_len - res;
+ puserdata_para->data_size = data_size - res;
+ }
+ } else {
+ res = (u32)copy_to_user((void *)pdest_buf,
+ (void *)rec_data_start,
+ data_size);
+ if (res) {
+ pr_info("p3 read not end res=%d, request=%d\n",
+ res, data_size);
+ copy_ok = 0;
+ }
+ p_userdata_rec->rec_len -= data_size - res;
+ p_userdata_rec->rec_start += data_size - res;
+ puserdata_para->data_size = data_size - res;
+ }
+
+ if (copy_ok) {
+ p_userdata_mgr->read_index++;
+ if (p_userdata_mgr->read_index >= USERDATA_FIFO_NUM)
+ p_userdata_mgr->read_index = 0;
+ }
+ } else {
+ /* dvb user data buffer is not enought
+ to copy the whole recored. */
+ data_size = puserdata_para->buf_len;
+ if (rec_data_start + data_size
+ > p_userdata_mgr->data_buf_end) {
+ int first_section_len;
+
+ first_section_len = p_userdata_mgr->buf_len
+ - p_userdata_rec->rec_start;
+ res = (u32)copy_to_user((void *)pdest_buf,
+ (void *)rec_data_start,
+ first_section_len);
+ if (res) {
+ pr_info("p4 read not end res=%d, request=%d\n",
+ res, first_section_len);
+ copy_ok = 0;
+ p_userdata_rec->rec_len -=
+ first_section_len - res;
+ p_userdata_rec->rec_start +=
+ first_section_len - res;
+ puserdata_para->data_size =
+ first_section_len - res;
+ } else {
+ /* first secton copy is ok*/
+ res = (u32)copy_to_user(
+ (void *)(pdest_buf+first_section_len),
+ (void *)p_userdata_mgr->data_buf,
+ data_size - first_section_len);
+ if (res) {
+ pr_info("p5 read not end res=%d, request=%d\n",
+ res,
+ data_size - first_section_len);
+ copy_ok = 0;
+ }
+
+ p_userdata_rec->rec_len -= data_size - res;
+ p_userdata_rec->rec_start =
+ data_size - first_section_len - res;
+ puserdata_para->data_size = data_size - res;
+ }
+ } else {
+ res = (u32)copy_to_user((void *)pdest_buf,
+ (void *)rec_data_start,
+ data_size);
+ if (res) {
+ pr_info("p6 read not end res=%d, request=%d\n",
+ res, data_size);
+ copy_ok = 0;
+ }
+
+ p_userdata_rec->rec_len -= data_size - res;
+ p_userdata_rec->rec_start += data_size - res;
+ puserdata_para->data_size = data_size - res;
+ }
+
+ if (copy_ok) {
+ p_userdata_mgr->read_index++;
+ if (p_userdata_mgr->read_index
+ >= USERDATA_FIFO_NUM)
+ p_userdata_mgr->read_index = 0;
+ }
+
+ }
+ res = (u32)copy_to_user((void *)&puserdata_para->meta_info,
+ (void *)&p_userdata_rec->meta_info,
+ sizeof(p_userdata_rec->meta_info));
+
+ if (p_userdata_mgr->read_index <= p_userdata_mgr->write_index)
+ puserdata_para->meta_info.records_in_que =
+ p_userdata_mgr->write_index -
+ p_userdata_mgr->read_index;
+ else
+ puserdata_para->meta_info.records_in_que =
+ p_userdata_mgr->write_index +
+ USERDATA_FIFO_NUM -
+ p_userdata_mgr->read_index;
+ puserdata_para->version = (0<<24|0<<16|0<<8|1);
+
+ mutex_unlock(&userdata_mutex);
+
+ return 1;
+}
+
+static void vmpeg12_reset_userdata_fifo(struct vdec_s *vdec, int bInit)
+{
+ mutex_lock(&userdata_mutex);
+
+ if (p_userdata_mgr) {
+ pr_info("vmpeg12_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n",
+ bInit, p_userdata_mgr->read_index,
+ p_userdata_mgr->write_index);
+ p_userdata_mgr->read_index = 0;
+ p_userdata_mgr->write_index = 0;
+
+ if (bInit)
+ p_userdata_mgr->last_wp = 0;
+ }
+
+ mutex_unlock(&userdata_mutex);
+}
+
static int vmpeg12_vdec_info_init(void)
{
gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL);
@@ -1015,6 +1671,7 @@ static int vmpeg12_prot_init(void)
WRITE_VREG(MREG_CMD, (frame_width << 16) | frame_height);
else
WRITE_VREG(MREG_CMD, 0);
+ WRITE_VREG(MREG_FORCE_I_RDY, (force_first_i_ready & 0x01));
/* clear error count */
WRITE_VREG(MREG_ERROR_COUNT, 0);
WRITE_VREG(MREG_FATAL_ERROR, 0);
@@ -1069,7 +1726,7 @@ static void vmpeg12_local_init(void)
frame_width = frame_height = frame_dur = frame_prog = 0;
frame_force_skip_flag = 0;
wait_buffer_counter = 0;
- first_i_frame_ready = 0;
+ first_i_frame_ready = force_first_i_ready;
saved_resolution = 0;
dec_control &= DEC_CONTROL_INTERNAL_MASK;
}
@@ -1160,6 +1817,17 @@ static s32 vmpeg12_init(void)
return 0;
}
+#ifdef DUMP_USER_DATA
+static int amvdec_mpeg12_init_userdata_dump(void)
+{
+ user_data_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL);
+ if (user_data_buf)
+ return 1;
+ else
+ return 0;
+}
+#endif
+
static int amvdec_mpeg12_probe(struct platform_device *pdev)
{
struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data;
@@ -1177,6 +1845,10 @@ static int amvdec_mpeg12_probe(struct platform_device *pdev)
pdata->dec_status = vmpeg12_dec_status;
pdata->set_isreset = vmpeg12_set_isreset;
+
+ pdata->user_data_read = vmpeg12_user_data_read;
+ pdata->reset_userdata_fifo = vmpeg12_reset_userdata_fifo;
+
is_reset = 0;
vmpeg12_vdec_info_init();
@@ -1188,10 +1860,21 @@ static int amvdec_mpeg12_probe(struct platform_device *pdev)
return -ENODEV;
}
+ vdec = pdata;
+#ifdef DUMP_USER_DATA
+ amvdec_mpeg12_init_userdata_dump();
+#endif
+ vmpeg12_crate_userdata_manager(ccbuf_phyAddress_virt, CCBUF_SIZE);
+
INIT_WORK(&userdata_push_work, userdata_push_do_work);
INIT_WORK(&notify_work, vmpeg12_notify_work);
INIT_WORK(&reset_work, reset_do_work);
- INIT_WORK(&set_clk_work, vmpeg12_set_clk);
+
+ last_offset = 0xFFFFFFFF;
+#ifdef DUMP_USER_DATA
+ last_wp = 0;
+ reset_user_data_buf();
+#endif
amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 probe end.\n");
@@ -1203,7 +1886,6 @@ static int amvdec_mpeg12_remove(struct platform_device *pdev)
cancel_work_sync(&userdata_push_work);
cancel_work_sync(&notify_work);
cancel_work_sync(&reset_work);
- cancel_work_sync(&set_clk_work);
if (stat & STAT_VDEC_RUN) {
amvdec_stop();
@@ -1237,6 +1919,7 @@ static int amvdec_mpeg12_remove(struct platform_device *pdev)
ccbuf_phyAddress_virt = NULL;
ccbuf_phyAddress = 0;
ccbuf_phyAddress_is_remaped_nocache = 0;
+ vmpeg12_destroy_userdata_manager();
if (mm_blk_handle) {
decoder_bmmu_box_free(mm_blk_handle);
@@ -1246,6 +1929,15 @@ static int amvdec_mpeg12_remove(struct platform_device *pdev)
kfree(gvs);
gvs = NULL;
+ vdec = NULL;
+
+#ifdef DUMP_USER_DATA
+ if (user_data_buf) {
+ show_user_data_buf();
+ kfree(user_data_buf);
+ user_data_buf = NULL;
+ }
+#endif
return 0;
}
@@ -1306,6 +1998,8 @@ MODULE_PARM_DESC(dec_control, "\n amvmpeg12 decoder control\n");
module_param(error_frame_skip_level, uint, 0664);
MODULE_PARM_DESC(error_frame_skip_level,
"\n amvdec_mpeg12 error_frame_skip_level\n");
+module_param(force_first_i_ready, uint, 0664);
+MODULE_PARM_DESC(dec_control, "\n amvmpeg12 force_first_i_ready\n");
module_init(amvdec_mpeg12_driver_init_module);
module_exit(amvdec_mpeg12_driver_remove_module);
diff --git a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
index a37dee3..f21d830 100644
--- a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
+++ b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
@@ -342,7 +342,7 @@ static inline void vmpeg4_save_hw_context(struct vdec_mpeg4_hw_s *hw)
hw->reg_rv_ai_mb_count = READ_VREG(RV_AI_MB_COUNT);
}
-static irqreturn_t vmpeg4_isr(struct vdec_s *vdec)
+static irqreturn_t vmpeg4_isr(struct vdec_s *vdec, int irq)
{
u32 reg;
struct vframe_s *vf = NULL;
@@ -387,8 +387,7 @@ static irqreturn_t vmpeg4_isr(struct vdec_s *vdec)
schedule_work(&hw->work);
return IRQ_HANDLED;
- }
- {
+ } else {
picture_type = (reg >> 3) & 7;
repeat_cnt = READ_VREG(MP4_NOT_CODED_CNT);
vop_time_inc = READ_VREG(MP4_VOP_TIME_INC);
@@ -737,7 +736,7 @@ static void vmpeg4_work(struct work_struct *work)
}
/* mark itself has all HW resource released and input released */
- vdec_set_status(hw_to_vdec(hw), VDEC_STATUS_CONNECTED);
+ vdec_core_finish_run(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
if (hw->vdec_cb)
hw->vdec_cb(hw_to_vdec(hw), hw->vdec_cb_arg);
@@ -1097,18 +1096,18 @@ static s32 vmpeg4_init(struct vdec_mpeg4_hw_s *hw)
return 0;
}
-static bool run_ready(struct vdec_s *vdec)
+static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
{
int index;
struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private;
index = find_buffer(hw);
- return index >= 0;
+ return (index >= 0) ? (CORE_MASK_VDEC_1 | CORE_MASK_HEVC) : 0;
}
-static void run(struct vdec_s *vdec, void (*callback)(struct vdec_s *, void *),
- void *arg)
+static void run(struct vdec_s *vdec, unsigned long mask,
+ void (*callback)(struct vdec_s *, void *), void *arg)
{
struct vdec_mpeg4_hw_s *hw = (struct vdec_mpeg4_hw_s *)vdec->private;
int save_reg = READ_VREG(POWER_CTL_VLD);
@@ -1235,6 +1234,9 @@ static int amvdec_mpeg4_probe(struct platform_device *pdev)
return -ENODEV;
}
+ vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+ | CORE_MASK_COMBINE);
+
return 0;
}
@@ -1245,6 +1247,8 @@ static int amvdec_mpeg4_remove(struct platform_device *pdev)
(((struct vdec_s *)(platform_get_drvdata(pdev)))->private);
+ vdec_core_release(hw_to_vdec(hw), CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
+
amvdec_disable();
if (hw->cma_alloc_addr) {
diff --git a/drivers/frame_provider/decoder/real/vreal.c b/drivers/frame_provider/decoder/real/vreal.c
index 9008cc6..91e67e9 100644
--- a/drivers/frame_provider/decoder/real/vreal.c
+++ b/drivers/frame_provider/decoder/real/vreal.c
@@ -317,8 +317,7 @@ static irqreturn_t vreal_isr(int irq, void *dev_id)
WRITE_VREG(TO_AMRISC, ~(1 << buffer_index));
WRITE_VREG(FROM_AMRISC, 0);
return IRQ_HANDLED;
- }
- {
+ } else {
current_vdts +=
vf->duration - (vf->duration >> 4);
vf->pts = current_vdts;
diff --git a/drivers/frame_provider/decoder/utils/amvdec.c b/drivers/frame_provider/decoder/utils/amvdec.c
index 1c4793a..cc1566d 100644
--- a/drivers/frame_provider/decoder/utils/amvdec.c
+++ b/drivers/frame_provider/decoder/utils/amvdec.c
@@ -373,9 +373,13 @@ static s32 amvdec_loadmc(const u32 *p)
return ret;
}
-s32 optee_load_fw(enum vformat_e type, const char *name)
+s32 optee_load_fw(enum vformat_e type, const char *fw_name)
{
s32 ret = 0;
+ char *name = __getname();
+
+ sprintf(name, "%s", fw_name ? fw_name : "null");
+
switch ((u32)type) {
case VFORMAT_VC1:
ret = tee_load_video_fw((u32)VIDEO_DEC_VC1, 0);
@@ -394,7 +398,14 @@ s32 optee_load_fw(enum vformat_e type, const char *name)
break;
case VFORMAT_VP9:
- ret = tee_load_video_fw((u32)VIDEO_DEC_VP9_MMU, 0);
+ if (!strcmp(name, "vp9_mc_g12a"))
+ ret = tee_load_video_fw((u32)VIDEO_DEC_VP9_G12A, 2);
+ else
+ ret = tee_load_video_fw((u32)VIDEO_DEC_VP9_MMU, 0);
+ break;
+
+ case VFORMAT_AVS2:
+ ret = tee_load_video_fw((u32)VIDEO_DEC_AVS2_MMU, 0);
break;
case VFORMAT_HEVC:
@@ -402,6 +413,8 @@ s32 optee_load_fw(enum vformat_e type, const char *name)
ret = tee_load_video_fw((u32)VIDEO_DEC_HEVC, 0);
else if (!strcmp(name, "vh265_mc_mmu"))
ret = tee_load_video_fw((u32)VIDEO_DEC_HEVC_MMU, 0);
+ else if (!strcmp(name, "vh265_mc_g12a"))
+ ret = tee_load_video_fw((u32)VIDEO_DEC_HEVC_G12A, 2);
break;
case VFORMAT_REAL:
@@ -440,10 +453,15 @@ s32 optee_load_fw(enum vformat_e type, const char *name)
ret = tee_load_video_fw((u32)VIDEO_DEC_REAL_V9, 0);
else if (!strcmp(name, "vmmjpeg_mc"))
ret = tee_load_video_fw((u32)VIDEO_DEC_MJPEG_MULTI, 0);
+ else if (!strcmp(name, "vh265_mc_g12a"))
+ ret = tee_load_video_fw((u32)VIDEO_DEC_HEVC_G12A, 2);
else
pr_info("unknow dec format\n");
break;
}
+
+ __putname(name);
+
return ret;
}
EXPORT_SYMBOL(optee_load_fw);
diff --git a/drivers/frame_provider/decoder/utils/vdec.c b/drivers/frame_provider/decoder/utils/vdec.c
index 3f4488b..615ae4e 100644
--- a/drivers/frame_provider/decoder/utils/vdec.c
+++ b/drivers/frame_provider/decoder/utils/vdec.c
@@ -34,6 +34,8 @@
#include <linux/amlogic/media/vfm/vframe_receiver.h>
#include <linux/amlogic/media/video_sink/ionvideo_ext.h>
#include <linux/amlogic/media/vfm/vfm_ext.h>
+/*for VDEC_DEBUG_SUPPORT*/
+#include <linux/time.h>
#include <linux/amlogic/media/utils/vdec_reg.h>
#include "vdec.h"
@@ -78,12 +80,6 @@ static unsigned int debug_trace_num = 16 * 20;
static int step_mode;
static unsigned int clk_config;
-/*
-&1: sched_priority to MAX_RT_PRIO -1.
-&2: always reload firmware.
-*/
-static unsigned int debug;
-
static int hevc_max_reset_count;
#define MAX_INSTANCE_MUN 9
@@ -104,6 +100,7 @@ struct vdec_isr_context_s {
irq_handler_t dev_isr;
irq_handler_t dev_threaded_isr;
void *dev_id;
+ struct vdec_s *vdec;
};
struct vdec_core_s {
@@ -120,9 +117,9 @@ struct vdec_core_s {
struct task_struct *thread;
struct workqueue_struct *vdec_core_wq;
+ unsigned long sched_mask;
struct vdec_isr_context_s isr_context[VDEC_IRQ_MAX];
int power_ref_count[VDEC_MAX];
- void *last_vdec;
};
static struct vdec_core_s *vdec_core;
@@ -154,6 +151,22 @@ unsigned char is_mult_inc(unsigned int type)
}
EXPORT_SYMBOL(is_mult_inc);
+static const bool cores_with_input[VDEC_MAX] = {
+ true, /* VDEC_1 */
+ false, /* VDEC_HCODEC */
+ false, /* VDEC_2 */
+ true, /* VDEC_HEVC / VDEC_HEVC_FRONT */
+ false, /* VDEC_HEVC_BACK */
+};
+
+static const int cores_int[VDEC_MAX] = {
+ VDEC_IRQ_1,
+ VDEC_IRQ_2,
+ VDEC_IRQ_0,
+ VDEC_IRQ_0,
+ VDEC_IRQ_HEVC_BACK
+};
+
unsigned long vdec_core_lock(struct vdec_core_s *core)
{
unsigned long flags;
@@ -336,7 +349,8 @@ static const char * const vdec_device_name[] = {
"amvdec_h265", "ammvdec_h265",
"amvenc_avc", "amvenc_avc",
"jpegenc", "jpegenc",
- "amvdec_vp9", "ammvdec_vp9"
+ "amvdec_vp9", "ammvdec_vp9",
+ "amvdec_avs2", "ammvdec_avs2"
};
@@ -357,11 +371,75 @@ static const char * const vdec_device_name[] = {
"amvdec_h265",
"amvenc_avc",
"jpegenc",
- "amvdec_vp9"
+ "amvdec_vp9",
+ "amvdec_avs2"
};
#endif
+#ifdef VDEC_DEBUG_SUPPORT
+static u64 get_current_clk(void)
+{
+ /*struct timespec xtime = current_kernel_time();
+ u64 usec = xtime.tv_sec * 1000000;
+ usec += xtime.tv_nsec / 1000;
+ */
+ u64 usec = sched_clock();
+ return usec;
+}
+
+static void inc_profi_count(unsigned long mask, u32 *count)
+{
+ enum vdec_type_e type;
+
+ for (type = VDEC_1; type < VDEC_MAX; type++) {
+ if (mask & (1 << type))
+ count[type]++;
+ }
+}
+
+static void update_profi_clk_run(struct vdec_s *vdec,
+ unsigned long mask, u64 clk)
+{
+ enum vdec_type_e type;
+
+ for (type = VDEC_1; type < VDEC_MAX; type++) {
+ if (mask & (1 << type)) {
+ vdec->start_run_clk[type] = clk;
+ if (vdec->profile_start_clk[type] == 0)
+ vdec->profile_start_clk[type] = clk;
+ vdec->total_clk[type] = clk
+ - vdec->profile_start_clk[type];
+ /*pr_info("set start_run_clk %ld\n",
+ vdec->start_run_clk);*/
+
+ }
+ }
+}
+
+static void update_profi_clk_stop(struct vdec_s *vdec,
+ unsigned long mask, u64 clk)
+{
+ enum vdec_type_e type;
+
+ for (type = VDEC_1; type < VDEC_MAX; type++) {
+ if (mask & (1 << type)) {
+ if (vdec->start_run_clk[type] == 0)
+ pr_info("error, start_run_clk[%d] not set\n", type);
+
+ /*pr_info("update run_clk type %d, %ld, %ld, %ld\n",
+ type,
+ clk,
+ vdec->start_run_clk[type],
+ vdec->run_clk[type]);*/
+ vdec->run_clk[type] +=
+ (clk - vdec->start_run_clk[type]);
+ }
+ }
+}
+
+#endif
+
int vdec_set_decinfo(struct vdec_s *vdec, struct dec_sysinfo *p)
{
if (copy_from_user((void *)&vdec->sys_info_store, (void *)p,
@@ -926,6 +1004,14 @@ void vdec_set_eos(struct vdec_s *vdec, bool eos)
}
EXPORT_SYMBOL(vdec_set_eos);
+#ifdef VDEC_DEBUG_SUPPORT
+void vdec_set_step_mode(void)
+{
+ step_mode = 0x1ff;
+}
+EXPORT_SYMBOL(vdec_set_step_mode);
+#endif
+
void vdec_set_next_sched(struct vdec_s *vdec, struct vdec_s *next_vdec)
{
if (vdec && next_vdec) {
@@ -1339,6 +1425,7 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
vdec_input_set_type(&vdec->input, vdec->type,
(vdec->format == VFORMAT_HEVC ||
+ vdec->format == VFORMAT_AVS2 ||
vdec->format == VFORMAT_VP9) ?
VDEC_INPUT_TARGET_HEVC :
VDEC_INPUT_TARGET_VLD);
@@ -1529,7 +1616,14 @@ EXPORT_SYMBOL(vdec_init);
void vdec_release(struct vdec_s *vdec)
{
//trace_vdec_release(vdec);/*DEBUG_TMP*/
-
+#ifdef VDEC_DEBUG_SUPPORT
+ if (step_mode) {
+ pr_info("VDEC_DEBUG: in step_mode, wait release\n");
+ while (step_mode)
+ udelay(10);
+ pr_info("VDEC_DEBUG: step_mode is clear\n");
+ }
+#endif
vdec_disconnect(vdec);
if (vdec->vframe_provider.name) {
@@ -1571,8 +1665,12 @@ void vdec_release(struct vdec_s *vdec)
}
EXPORT_SYMBOL(vdec_release);
+/* For dual running decoders, vdec_reset is only called with master vdec.
+ */
int vdec_reset(struct vdec_s *vdec)
{
+ //trace_vdec_reset(vdec); /*DEBUG_TMP*/
+
vdec_disconnect(vdec);
if (vdec->vframe_provider.name)
@@ -1586,7 +1684,7 @@ int vdec_reset(struct vdec_s *vdec)
if (vdec->slave)
vdec->slave->reset(vdec->slave);
}
- vdec->mc_loaded = 0;/*clear for reload firmware.*/
+
vdec_input_release(&vdec->input);
vf_reg_provider(&vdec->vframe_provider);
@@ -1597,7 +1695,6 @@ int vdec_reset(struct vdec_s *vdec)
vf_reg_provider(&vdec->slave->vframe_provider);
vf_notify_receiver(vdec->slave->vf_provider_name,
VFRAME_EVENT_PROVIDER_START, vdec->slave);
- vdec->slave->mc_loaded = 0;/*clear for reload firmware.*/
}
vdec_connect(vdec);
@@ -1617,18 +1714,72 @@ void vdec_free_cmabuf(void)
mutex_unlock(&vdec_mutex);
}
-static struct vdec_s *active_vdec(struct vdec_core_s *core)
+int vdec_core_request(struct vdec_s *vdec, unsigned long mask)
{
- struct vdec_s *vdec;
- struct list_head *p;
+ vdec->core_mask |= mask;
- list_for_each(p, &core->connected_vdec_list) {
- vdec = list_entry(p, struct vdec_s, list);
- if (vdec->status == VDEC_STATUS_ACTIVE)
- return vdec;
+ if (vdec->slave)
+ vdec->slave->core_mask |= mask;
+
+ return 0;
+}
+EXPORT_SYMBOL(vdec_core_request);
+
+int vdec_core_release(struct vdec_s *vdec, unsigned long mask)
+{
+ vdec->core_mask &= ~mask;
+
+ if (vdec->slave)
+ vdec->slave->core_mask &= ~mask;
+
+ return 0;
+}
+EXPORT_SYMBOL(vdec_core_release);
+
+const bool vdec_core_with_input(unsigned long mask)
+{
+ enum vdec_type_e type;
+
+ for (type = VDEC_1; type < VDEC_MAX; type++) {
+ if ((mask & (1 << type)) && cores_with_input[type])
+ return true;
}
- return NULL;
+ return false;
+}
+
+void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask)
+{
+ unsigned long i;
+ unsigned long t = mask;
+
+ while (t) {
+ i = __ffs(t);
+ clear_bit(i, &vdec->active_mask);
+ t &= ~(1 << i);
+ }
+
+ if (vdec->active_mask == 0)
+ vdec_set_status(vdec, VDEC_STATUS_CONNECTED);
+}
+EXPORT_SYMBOL(vdec_core_finish_run);
+/*
+ * find what core resources are available for vdec
+ */
+static unsigned long vdec_schedule_mask(struct vdec_s *vdec,
+ unsigned long active_mask)
+{
+ unsigned long mask = vdec->core_mask &
+ ~CORE_MASK_COMBINE;
+
+ if (vdec->core_mask & CORE_MASK_COMBINE) {
+ /* combined cores must be granted together */
+ if ((mask & ~active_mask) == mask)
+ return mask;
+ else
+ return 0;
+ } else
+ return mask & ~vdec->sched_mask & ~active_mask;
}
/*
@@ -1657,12 +1808,14 @@ static irqreturn_t vdec_isr(int irq, void *dev_id)
{
struct vdec_isr_context_s *c =
(struct vdec_isr_context_s *)dev_id;
- struct vdec_s *vdec = vdec_core->active_vdec;
+ struct vdec_s *vdec = c->vdec;
if (c->dev_isr)
return c->dev_isr(irq, c->dev_id);
- if (c != &vdec_core->isr_context[VDEC_IRQ_1]) {
+ if ((c != &vdec_core->isr_context[VDEC_IRQ_0]) &&
+ (c != &vdec_core->isr_context[VDEC_IRQ_1]) &&
+ (c != &vdec_core->isr_context[VDEC_IRQ_HEVC_BACK])) {
#if 0
pr_warn("vdec interrupt w/o a valid receiver\n");
#endif
@@ -1684,14 +1837,14 @@ static irqreturn_t vdec_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
- return vdec->irq_handler(vdec);
+ return vdec->irq_handler(vdec, c->index);
}
static irqreturn_t vdec_thread_isr(int irq, void *dev_id)
{
struct vdec_isr_context_s *c =
(struct vdec_isr_context_s *)dev_id;
- struct vdec_s *vdec = vdec_core->active_vdec;
+ struct vdec_s *vdec = c->vdec;
if (c->dev_threaded_isr)
return c->dev_threaded_isr(irq, c->dev_id);
@@ -1702,15 +1855,15 @@ static irqreturn_t vdec_thread_isr(int irq, void *dev_id)
if (!vdec->threaded_irq_handler)
return IRQ_HANDLED;
- return vdec->threaded_irq_handler(vdec);
+ return vdec->threaded_irq_handler(vdec, c->index);
}
-static inline bool vdec_ready_to_run(struct vdec_s *vdec)
+unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask)
{
- bool r;
+ unsigned long ready_mask;
struct vdec_input_s *input = &vdec->input;
-
- if (vdec->status != VDEC_STATUS_CONNECTED)
+ if ((vdec->status != VDEC_STATUS_CONNECTED) &&
+ (vdec->status != VDEC_STATUS_ACTIVE))
return false;
if (!vdec->run_ready)
@@ -1719,51 +1872,89 @@ static inline bool vdec_ready_to_run(struct vdec_s *vdec)
if ((vdec->slave || vdec->master) &&
(vdec->sched == 0))
return false;
-
- /* check frame based input underrun */
- if (input && !input->eos && input_frame_based(input)
- && (!vdec_input_next_chunk(input)))
- return false;
-
- /* check streaming prepare level threshold if not EOS */
- if (input && input_stream_based(input) && !input->eos) {
- u32 rp, wp, level;
-
- rp = READ_PARSER_REG(PARSER_VIDEO_RP);
- wp = READ_PARSER_REG(PARSER_VIDEO_WP);
- if (wp < rp)
- level = input->size + wp - rp;
- else
- level = wp - rp;
-
- if ((level < input->prepare_level) &&
- (pts_get_rec_num(PTS_TYPE_VIDEO,
- vdec->input.total_rd_count) < 2)) {
- vdec->need_more_data |= VDEC_NEED_MORE_DATA;
+#ifdef VDEC_DEBUG_SUPPORT
+ inc_profi_count(mask, vdec->check_count);
+#endif
+ if (vdec_core_with_input(mask)) {
+ /* check frame based input underrun */
+ if (input && !input->eos && input_frame_based(input)
+ && (!vdec_input_next_chunk(input))) {
+#ifdef VDEC_DEBUG_SUPPORT
+ inc_profi_count(mask, vdec->input_underrun_count);
+#endif
return false;
- } else if (level > input->prepare_level)
- vdec->need_more_data &= ~VDEC_NEED_MORE_DATA;
+ }
+ /* check streaming prepare level threshold if not EOS */
+ if (input && input_stream_based(input) && !input->eos) {
+ u32 rp, wp, level;
+
+ rp = READ_PARSER_REG(PARSER_VIDEO_RP);
+ wp = READ_PARSER_REG(PARSER_VIDEO_WP);
+ if (wp < rp)
+ level = input->size + wp - rp;
+ else
+ level = wp - rp;
+
+ if ((level < input->prepare_level) &&
+ (pts_get_rec_num(PTS_TYPE_VIDEO,
+ vdec->input.total_rd_count) < 2)) {
+ vdec->need_more_data |= VDEC_NEED_MORE_DATA;
+#ifdef VDEC_DEBUG_SUPPORT
+ inc_profi_count(mask, vdec->input_underrun_count);
+ if (step_mode & 0x200) {
+ if ((step_mode & 0xff) == vdec->id) {
+ step_mode |= 0xff;
+ return mask;
+ }
+ }
+#endif
+ return false;
+ } else if (level > input->prepare_level)
+ vdec->need_more_data &= ~VDEC_NEED_MORE_DATA;
+ }
}
if (step_mode) {
if ((step_mode & 0xff) != vdec->id)
- return false;
+ return 0;
+ step_mode |= 0xff; /*VDEC_DEBUG_SUPPORT*/
}
- step_mode &= ~0xff;
+ /*step_mode &= ~0xff; not work for id of 0, removed*/
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
vdec_profile(vdec, VDEC_PROFILE_EVENT_CHK_RUN_READY);
#endif
- r = vdec->run_ready(vdec);
-
+ ready_mask = vdec->run_ready(vdec, mask) & mask;
+#ifdef VDEC_DEBUG_SUPPORT
+ if (ready_mask != mask)
+ inc_profi_count(ready_mask ^ mask, vdec->not_run_ready_count);
+#endif
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
- if (r)
+ if (ready_mask)
vdec_profile(vdec, VDEC_PROFILE_EVENT_RUN_READY);
#endif
- return r;
+ return ready_mask;
+}
+
+/* bridge on/off vdec's interrupt processing to vdec core */
+static void vdec_route_interrupt(struct vdec_s *vdec, unsigned long mask,
+ bool enable)
+{
+ enum vdec_type_e type;
+
+ for (type = VDEC_1; type < VDEC_MAX; type++) {
+ if (mask & (1 << type)) {
+ struct vdec_isr_context_s *c =
+ &vdec_core->isr_context[cores_int[type]];
+ if (enable)
+ c->vdec = vdec;
+ else if (c->vdec == vdec)
+ c->vdec = NULL;
+ }
+ }
}
/*
@@ -1775,16 +1966,21 @@ static inline bool vdec_ready_to_run(struct vdec_s *vdec)
* Perform need_more_data checking and set flag is decoder
* is not consuming data.
*/
-static inline void vdec_prepare_run(struct vdec_s *vdec)
+void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask)
{
struct vdec_input_s *input = &vdec->input;
- int type = (vdec_secure(vdec)) ? DMC_DEV_TYPE_SECURE :
+ int secure = (vdec_secure(vdec)) ? DMC_DEV_TYPE_SECURE :
DMC_DEV_TYPE_NON_SECURE;
+ vdec_route_interrupt(vdec, mask, true);
+
+ if (!vdec_core_with_input(mask))
+ return;
+
if (input->target == VDEC_INPUT_TARGET_VLD)
- tee_config_device_secure(DMC_DEV_ID_VDEC, type);
+ tee_config_device_secure(DMC_DEV_ID_VDEC, secure);
else if (input->target == VDEC_INPUT_TARGET_HEVC)
- tee_config_device_secure(DMC_DEV_ID_HEVC, type);
+ tee_config_device_secure(DMC_DEV_ID_HEVC, secure);
if (vdec_stream_based(vdec) &&
((vdec->need_more_data & VDEC_NEED_MORE_DATA_RUN) &&
@@ -1806,35 +2002,55 @@ static inline void vdec_prepare_run(struct vdec_s *vdec)
static int vdec_core_thread(void *data)
{
struct vdec_core_s *core = (struct vdec_core_s *)data;
- struct vdec_s *lastvdec;
- struct sched_param param = {.sched_priority = MAX_RT_PRIO/2};
+
+ struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1};
sched_setscheduler(current, SCHED_FIFO, &param);
allow_signal(SIGTERM);
- lastvdec = NULL;
+
while (down_interruptible(&core->sem) == 0) {
- struct vdec_s *vdec, *tmp;
+ struct vdec_s *vdec, *tmp, *worker;
+ unsigned long sched_mask = 0;
LIST_HEAD(disconnecting_list);
if (kthread_should_stop())
break;
/* clean up previous active vdec's input */
- if ((core->active_vdec) &&
- (core->active_vdec->status == VDEC_STATUS_CONNECTED)) {
- struct vdec_input_s *input = &core->active_vdec->input;
-
- while (!list_empty(&input->vframe_chunk_list)) {
- struct vframe_chunk_s *chunk =
- vdec_input_next_chunk(input);
- if (chunk->flag & VFRAME_CHUNK_FLAG_CONSUMED)
- vdec_input_release_chunk(input, chunk);
- else
- break;
+ list_for_each_entry(vdec, &core->connected_vdec_list, list) {
+ unsigned long mask = vdec->sched_mask &
+ (vdec->active_mask ^ vdec->sched_mask);
+
+ vdec_route_interrupt(vdec, mask, false);
+
+#ifdef VDEC_DEBUG_SUPPORT
+ update_profi_clk_stop(vdec, mask, get_current_clk());
+#endif
+ /*
+ * If decoder released some core resources (mask), then
+ * check if these core resources are associated
+ * with any input side and do input clean up accordingly
+ */
+ if (vdec_core_with_input(mask)) {
+ struct vdec_input_s *input = &vdec->input;
+ while (!list_empty(
+ &input->vframe_chunk_list)) {
+ struct vframe_chunk_s *chunk =
+ vdec_input_next_chunk(input);
+ if (chunk->flag &
+ VFRAME_CHUNK_FLAG_CONSUMED)
+ vdec_input_release_chunk(input,
+ chunk);
+ else
+ break;
+ }
+
+ vdec_save_input_context(vdec);
}
- vdec_save_input_context(core->active_vdec);
+ vdec->sched_mask &= ~mask;
+ core->sched_mask &= ~mask;
}
/*
@@ -1852,8 +2068,6 @@ static int vdec_core_thread(void *data)
* }
*/
- mutex_lock(&vdec_mutex);
-
/* check disconnected decoders */
list_for_each_entry_safe(vdec, tmp,
&core->connected_vdec_list, list) {
@@ -1865,70 +2079,98 @@ static int vdec_core_thread(void *data)
}
}
- /* activate next decoder instance if there is none */
- vdec = active_vdec(core);
-
- if (!vdec) {
- /*
- *round-robin decoder scheduling
- * start from the decoder after previous active
- * decoder instance, if not, then start from beginning
- */
- if (core->active_vdec)
- vdec = list_entry(
- core->active_vdec->list.next,
- struct vdec_s, list);
- else
- vdec = list_entry(
- core->connected_vdec_list.next,
- struct vdec_s, list);
-
+ /* elect next vdec to be scheduled */
+ vdec = core->active_vdec;
+ if (vdec) {
+ vdec = list_entry(vdec->list.next, struct vdec_s, list);
list_for_each_entry_from(vdec,
&core->connected_vdec_list, list) {
- if (vdec_ready_to_run(vdec))
+ sched_mask = vdec_schedule_mask(vdec,
+ core->sched_mask);
+ if (!sched_mask)
+ continue;
+ sched_mask = vdec_ready_to_run(vdec,
+ sched_mask);
+ if (sched_mask)
break;
}
- if ((&vdec->list == &core->connected_vdec_list) &&
- (core->active_vdec)) {
- /* search from beginning */
- list_for_each_entry(vdec,
- &core->connected_vdec_list, list) {
- if (vdec_ready_to_run(vdec))
+ if (&vdec->list == &core->connected_vdec_list)
+ vdec = NULL;
+ }
+
+ if (!vdec) {
+ /* search from beginning */
+ list_for_each_entry(vdec,
+ &core->connected_vdec_list, list) {
+ sched_mask = vdec_schedule_mask(vdec,
+ core->sched_mask);
+ if (vdec == core->active_vdec) {
+ if (!sched_mask) {
+ vdec = NULL;
break;
+ }
+
+ sched_mask = vdec_ready_to_run(vdec,
+ sched_mask);
- if (vdec == core->active_vdec) {
+ if (!sched_mask) {
vdec = NULL;
break;
}
+ break;
}
+
+ if (!sched_mask)
+ continue;
+
+ sched_mask = vdec_ready_to_run(vdec,
+ sched_mask);
+ if (sched_mask)
+ break;
}
if (&vdec->list == &core->connected_vdec_list)
vdec = NULL;
-
- core->active_vdec = NULL;
}
- mutex_unlock(&vdec_mutex);
+ worker = vdec;
+
+ if (vdec) {
+ unsigned long mask = sched_mask;
+ unsigned long i;
+
+ /* setting active_mask should be atomic.
+ * it can be modified by decoder driver callbacks.
+ */
+ while (sched_mask) {
+ i = __ffs(sched_mask);
+ set_bit(i, &vdec->active_mask);
+ sched_mask &= ~(1 << i);
+ }
+
+ /* vdec's sched_mask is only set from core thread */
+ vdec->sched_mask |= mask;
- /* start the vdec instance */
- if ((vdec) && (vdec->status != VDEC_STATUS_ACTIVE)) {
- if (lastvdec != vdec)
- vdec->mc_loaded = 0;/*clear for reload firmware.*/
- if (debug & 2)
- vdec->mc_loaded = 0;/*alway reload firmware.*/
vdec_set_status(vdec, VDEC_STATUS_ACTIVE);
- /* activatate the decoder instance to run */
+ core->sched_mask |= mask;
core->active_vdec = vdec;
#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
vdec_profile(vdec, VDEC_PROFILE_EVENT_RUN);
#endif
- vdec_prepare_run(vdec);
+ vdec_prepare_run(vdec, mask);
+#ifdef VDEC_DEBUG_SUPPORT
+ inc_profi_count(mask, vdec->run_count);
+ update_profi_clk_run(vdec, mask, get_current_clk());
+#endif
+ vdec->run(vdec, mask, vdec_callback, core);
+
- vdec->run(vdec, vdec_callback, core);
- lastvdec = vdec;
+ /* we have some cores scheduled, keep working until
+ * all vdecs are checked with no cores to schedule
+ */
+ up(&core->sem);
}
/* remove disconnected decoder from active list */
@@ -1938,8 +2180,11 @@ static int vdec_core_thread(void *data)
complete(&vdec->inactive_done);
}
- if (!core->active_vdec) {
- usleep_range(1000,2000);
+ /* if there is no new work scheduled and nothing
+ * is running, sleep 20ms
+ */
+ if ((!worker) && (!core->sched_mask)) {
+ msleep(20);
up(&core->sem);
}
@@ -2268,8 +2513,12 @@ void vdec_poweroff(enum vdec_type_e core)
0xc00);
/* power off hevc memories */
WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL);
+
/* disable hevc clock */
hevc_clock_off();
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A)
+ hevc_back_clock_off();
+
/* hevc power off */
WRITE_AOREG(AO_RTI_GEN_PWR_SLEEP0,
READ_AOREG(AO_RTI_GEN_PWR_SLEEP0) |
@@ -2743,6 +2992,123 @@ static ssize_t show_keep_vdec_mem(struct class *class,
return sprintf(buf, "%d\n", keep_vdec_mem);
}
+#ifdef VDEC_DEBUG_SUPPORT
+static ssize_t store_debug(struct class *class,
+ struct class_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct vdec_s *vdec;
+ struct vdec_core_s *core = vdec_core;
+ unsigned long flags;
+
+ unsigned id;
+ unsigned val;
+ ssize_t ret;
+ char cbuf[32];
+
+ cbuf[0] = 0;
+ ret = sscanf(buf, "%s %x %x", cbuf, &id, &val);
+ /*pr_info(
+ "%s(%s)=>ret %ld: %s, %x, %x\n",
+ __func__, buf, ret, cbuf, id, val);*/
+ if (strcmp(cbuf, "schedule") == 0) {
+ pr_info("VDEC_DEBUG: force schedule\n");
+ up(&core->sem);
+ } else if (strcmp(cbuf, "power_off") == 0) {
+ pr_info("VDEC_DEBUG: power off core %d\n", id);
+ vdec_poweroff(id);
+ } else if (strcmp(cbuf, "power_on") == 0) {
+ pr_info("VDEC_DEBUG: power_on core %d\n", id);
+ vdec_poweron(id);
+ } else if (strcmp(cbuf, "wr") == 0) {
+ pr_info("VDEC_DEBUG: WRITE_VREG(0x%x, 0x%x)\n",
+ id, val);
+ WRITE_VREG(id, val);
+ } else if (strcmp(cbuf, "rd") == 0) {
+ pr_info("VDEC_DEBUG: READ_VREG(0x%x) = 0x%x\n",
+ id, READ_VREG(id));
+ } else if (strcmp(cbuf, "read_hevc_clk_reg") == 0) {
+ pr_info(
+ "VDEC_DEBUG: HHI_VDEC4_CLK_CNTL = 0x%x, HHI_VDEC2_CLK_CNTL = 0x%x\n",
+ READ_HHI_REG(HHI_VDEC4_CLK_CNTL),
+ READ_HHI_REG(HHI_VDEC2_CLK_CNTL));
+ }
+
+ flags = vdec_core_lock(vdec_core);
+
+ list_for_each_entry(vdec,
+ &core->connected_vdec_list, list) {
+ pr_info("vdec: status %d, id %d\n", vdec->status, vdec->id);
+ if (((vdec->status == VDEC_STATUS_CONNECTED
+ || vdec->status == VDEC_STATUS_ACTIVE)) &&
+ (vdec->id == id)) {
+ /*to add*/
+ break;
+ }
+ }
+ vdec_core_unlock(vdec_core, flags);
+ return size;
+}
+
+static ssize_t show_debug(struct class *class,
+ struct class_attribute *attr, char *buf)
+{
+ char *pbuf = buf;
+ struct vdec_s *vdec;
+ struct vdec_core_s *core = vdec_core;
+ unsigned long flags = vdec_core_lock(vdec_core);
+
+ pbuf += sprintf(pbuf,
+ "============== help:\n");
+ pbuf += sprintf(pbuf,
+ "'echo xxx > debug' usuage:\n");
+ pbuf += sprintf(pbuf,
+ "schedule - trigger schedule thread to run\n");
+ pbuf += sprintf(pbuf,
+ "power_off core_num - call vdec_poweroff(core_num)\n");
+ pbuf += sprintf(pbuf,
+ "power_on core_num - call vdec_poweron(core_num)\n");
+ pbuf += sprintf(pbuf,
+ "wr adr val - call WRITE_VREG(adr, val)\n");
+ pbuf += sprintf(pbuf,
+ "rd adr - call READ_VREG(adr)\n");
+ pbuf += sprintf(pbuf,
+ "read_hevc_clk_reg - read HHI register for hevc clk\n");
+ pbuf += sprintf(pbuf,
+ "===================\n");
+
+ pbuf += sprintf(pbuf,
+ "name(core)\tschedule_count\trun_count\tinput_underrun\tdecbuf_not_ready\trun_time\n");
+ list_for_each_entry(vdec,
+ &core->connected_vdec_list, list) {
+ enum vdec_type_e type;
+
+ for (type = VDEC_1; type < VDEC_MAX; type++) {
+ if (vdec->core_mask & (1 << type)) {
+ pbuf += sprintf(pbuf, "%s(%d):",
+ vdec->vf_provider_name, type);
+ pbuf += sprintf(pbuf, "\t%d",
+ vdec->check_count[type]);
+ pbuf += sprintf(pbuf, "\t%d",
+ vdec->run_count[type]);
+ pbuf += sprintf(pbuf, "\t%d",
+ vdec->input_underrun_count[type]);
+ pbuf += sprintf(pbuf, "\t%d",
+ vdec->not_run_ready_count[type]);
+ pbuf += sprintf(pbuf,
+ "\t%d%%\n",
+ vdec->total_clk[type] == 0 ? 0 :
+ (u32)((vdec->run_clk[type] * 100)
+ / vdec->total_clk[type]));
+ }
+ }
+ }
+
+ vdec_core_unlock(vdec_core, flags);
+ return pbuf - buf;
+
+}
+#endif
/*irq num as same as .dts*/
/*
@@ -2845,6 +3211,70 @@ void vdec_free_irq(enum vdec_irq_num num, void *dev)
}
EXPORT_SYMBOL(vdec_free_irq);
+struct vdec_s *vdec_get_default_vdec_for_userdata(void)
+{
+ struct vdec_s *vdec;
+ struct vdec_s *ret_vdec;
+ struct vdec_core_s *core = vdec_core;
+ unsigned long flags;
+ int id;
+
+ flags = vdec_core_lock(vdec_core);
+
+ id = 0x10000000;
+ ret_vdec = NULL;
+ if (!list_empty(&core->connected_vdec_list)) {
+ list_for_each_entry(vdec, &core->connected_vdec_list, list) {
+ if (vdec->id < id) {
+ id = vdec->id;
+ ret_vdec = vdec;
+ }
+ }
+ }
+
+ vdec_core_unlock(vdec_core, flags);
+
+ return ret_vdec;
+}
+EXPORT_SYMBOL(vdec_get_default_vdec_for_userdata);
+
+int vdec_read_user_data(struct vdec_s *vdec,
+ struct userdata_param_t *p_userdata_param)
+{
+ int ret = 0;
+
+ if (!vdec)
+ vdec = vdec_get_default_vdec_for_userdata();
+
+ if (vdec) {
+ if (vdec->user_data_read)
+ ret = vdec->user_data_read(vdec, p_userdata_param);
+ }
+ return ret;
+}
+EXPORT_SYMBOL(vdec_read_user_data);
+
+int vdec_wakeup_userdata_poll(struct vdec_s *vdec)
+{
+ /*if (vdec && vdec == vdec_get_default_vdec_for_userdata())
+ amstream_wakeup_userdata_poll();*/ //DEBUG_TMP
+
+ return 0;
+}
+EXPORT_SYMBOL(vdec_wakeup_userdata_poll);
+
+void vdec_reset_userdata_fifo(struct vdec_s *vdec, int bInit)
+{
+ if (!vdec)
+ vdec = vdec_get_default_vdec_for_userdata();
+
+ if (vdec) {
+ if (vdec->reset_userdata_fifo)
+ vdec->reset_userdata_fifo(vdec, bInit);
+ }
+}
+EXPORT_SYMBOL(vdec_reset_userdata_fifo);
+
static int dump_mode;
static ssize_t dump_risc_mem_store(struct class *class,
struct class_attribute *attr,
@@ -2953,14 +3383,20 @@ static ssize_t core_show(struct class *class, struct class_attribute *attr,
else {
struct vdec_s *vdec;
+ pbuf += sprintf(pbuf,
+ " Core: last_sched %p, sched_mask %lx\n",
+ core->active_vdec,
+ core->sched_mask);
+
list_for_each_entry(vdec, &core->connected_vdec_list, list) {
pbuf += sprintf(pbuf,
- "\tvdec.%d (%p (%s)), status = %s,\ttype = %s\n",
+ "\tvdec.%d (%p (%s)), status = %s,\ttype = %s, \tactive_mask = %lx\n",
vdec->id,
vdec,
vdec_device_name[vdec->format * 2],
vdec_status_str(vdec),
- vdec_type_str(vdec));
+ vdec_type_str(vdec),
+ vdec->active_mask);
}
}
@@ -3118,6 +3554,10 @@ static struct class_attribute vdec_class_attrs[] = {
__ATTR_RO(dump_vdec_blocks),
__ATTR_RO(dump_vdec_chunks),
__ATTR_RO(dump_decoder_state),
+#ifdef VDEC_DEBUG_SUPPORT
+ __ATTR(debug, S_IRUGO | S_IWUSR | S_IWGRP,
+ show_debug, store_debug),
+#endif
__ATTR_NULL
};
@@ -3161,13 +3601,29 @@ static int vdec_probe(struct platform_device *pdev)
vdec_core->isr_context[i].irq = -1;
}
+ r = vdec_request_threaded_irq(VDEC_IRQ_0, NULL, NULL,
+ IRQF_ONESHOT, "vdec-0", NULL);
+ if (r < 0) {
+ pr_err("vdec interrupt request failed\n");
+ return r;
+ }
+
r = vdec_request_threaded_irq(VDEC_IRQ_1, NULL, NULL,
IRQF_ONESHOT, "vdec-1", NULL);
if (r < 0) {
pr_err("vdec interrupt request failed\n");
return r;
}
-
+#if 0
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
+ r = vdec_request_threaded_irq(VDEC_IRQ_HEVC_BACK, NULL, NULL,
+ IRQF_ONESHOT, "vdec-hevc_back", NULL);
+ if (r < 0) {
+ pr_err("vdec interrupt request failed\n");
+ return r;
+ }
+ }
+#endif
r = of_reserved_mem_device_init(&pdev->dev);
if (r == 0)
pr_info("vdec_probe done\n");
@@ -3189,13 +3645,8 @@ static int vdec_probe(struct platform_device *pdev)
vdec_core->thread = kthread_run(vdec_core_thread, vdec_core,
"vdec-core");
- vdec_core->vdec_core_wq = alloc_ordered_workqueue("%s",
- __WQ_LEGACY |
- WQ_MEM_RECLAIM |
- WQ_HIGHPRI/*high priority*/
- ,
- "vdec-work");
- /*work queue priority lower than vdec-core.*/
+ vdec_core->vdec_core_wq = create_singlethread_workqueue("threadvdec");
+
return 0;
}
@@ -3303,11 +3754,17 @@ static int __init vdec_mem_setup(struct reserved_mem *rmem)
}
RESERVEDMEM_OF_DECLARE(vdec, "amlogic, vdec-memory", vdec_mem_setup);
-module_param(debug, uint, 0664);
+/*
+uint force_hevc_clock_cntl;
+EXPORT_SYMBOL(force_hevc_clock_cntl);
+
+module_param(force_hevc_clock_cntl, uint, 0664);
+*/
module_param(debug_trace_num, uint, 0664);
module_param(hevc_max_reset_count, int, 0664);
module_param(clk_config, uint, 0664);
module_param(step_mode, int, 0664);
+module_param(debugflags, int, 0664);
/*
*module_init(vdec_module_init);
diff --git a/drivers/frame_provider/decoder/utils/vdec.h b/drivers/frame_provider/decoder/utils/vdec.h
index 13cfa83..0b0e0b8 100644
--- a/drivers/frame_provider/decoder/utils/vdec.h
+++ b/drivers/frame_provider/decoder/utils/vdec.h
@@ -29,6 +29,8 @@
#include <linux/amlogic/media/vfm/vframe_provider.h>
#include <linux/amlogic/media/vfm/vframe_receiver.h>
+/*#define CONFIG_AM_VDEC_DV*/
+
#include "vdec_input.h"
s32 vdec_dev_register(void);
@@ -41,6 +43,8 @@ struct device *get_vdec_device(void);
int vdec_module_init(void);
void vdec_module_exit(void);
+#define VDEC_DEBUG_SUPPORT
+
#define DEC_FLAG_HEVC_WORKAROUND 0x01
#define VDEC_FIFO_ALIGN 8
@@ -50,9 +54,18 @@ enum vdec_type_e {
VDEC_HCODEC,
VDEC_2,
VDEC_HEVC,
+ VDEC_HEVCB,
VDEC_MAX
};
+#define CORE_MASK_VDEC_1 (1 << VDEC_1)
+#define CORE_MASK_HCODEC (1 << VDEC_HCODEC)
+#define CORE_MASK_VDEC_2 (1 << VDEC_2)
+#define CORE_MASK_HEVC (1 << VDEC_HEVC)
+#define CORE_MASK_HEVC_FRONT (1 << VDEC_HEVC)
+#define CORE_MASK_HEVC_BACK (1 << VDEC_HEVCB)
+#define CORE_MASK_COMBINE (1UL << 31)
+
extern void vdec2_power_mode(int level);
extern void vdec_poweron(enum vdec_type_e core);
extern void vdec_poweroff(enum vdec_type_e core);
@@ -81,6 +94,7 @@ enum vdec_irq_num {
VDEC_IRQ_0,
VDEC_IRQ_1,
VDEC_IRQ_2,
+ VDEC_IRQ_HEVC_BACK,
VDEC_IRQ_MAX,
};
@@ -144,6 +158,9 @@ enum vformat_t;
struct vdec_s {
u32 magic;
struct list_head list;
+ unsigned long core_mask;
+ unsigned long active_mask;
+ unsigned long sched_mask;
int id;
struct vdec_s *master;
@@ -203,16 +220,30 @@ struct vdec_s {
int (*set_trickmode)(struct vdec_s *vdec, unsigned long trickmode);
int (*set_isreset)(struct vdec_s *vdec, int isreset);
- bool (*run_ready)(struct vdec_s *vdec);
- void (*run)(struct vdec_s *vdec,
+ unsigned long (*run_ready)(struct vdec_s *vdec, unsigned long mask);
+ void (*run)(struct vdec_s *vdec, unsigned long mask,
void (*callback)(struct vdec_s *, void *), void *);
void (*reset)(struct vdec_s *vdec);
void (*dump_state)(struct vdec_s *vdec);
- irqreturn_t (*irq_handler)(struct vdec_s *);
- irqreturn_t (*threaded_irq_handler)(struct vdec_s *);
+ irqreturn_t (*irq_handler)(struct vdec_s *vdec, int irq);
+ irqreturn_t (*threaded_irq_handler)(struct vdec_s *vdec, int irq);
+
+ int (*user_data_read)(struct vdec_s *vdec,
+ struct userdata_param_t *puserdata_para);
+ void (*reset_userdata_fifo)(struct vdec_s *vdec, int bInit);
/* private */
void *private; /* decoder per instance specific data */
+#ifdef VDEC_DEBUG_SUPPORT
+ u64 profile_start_clk[VDEC_MAX];
+ u64 total_clk[VDEC_MAX];
+ u32 check_count[VDEC_MAX];
+ u32 not_run_ready_count[VDEC_MAX];
+ u32 input_underrun_count[VDEC_MAX];
+ u32 run_count[VDEC_MAX];
+ u64 run_clk[VDEC_MAX];
+ u64 start_run_clk[VDEC_MAX];
+#endif
};
/* common decoder vframe provider name to use default vfm path */
@@ -353,6 +384,29 @@ extern void hevc_reset_core(struct vdec_s *vdec);
extern void vdec_set_suspend_clk(int mode, int hevc);
+extern unsigned long vdec_ready_to_run(struct vdec_s *vdec, unsigned long mask);
+
+extern void vdec_prepare_run(struct vdec_s *vdec, unsigned long mask);
+
+extern int vdec_core_request(struct vdec_s *vdec, unsigned long mask);
+
+extern int vdec_core_release(struct vdec_s *vdec, unsigned long mask);
+
+extern const bool vdec_core_with_input(unsigned long mask);
+
+extern void vdec_core_finish_run(struct vdec_s *vdec, unsigned long mask);
+
+#ifdef VDEC_DEBUG_SUPPORT
+extern void vdec_set_step_mode(void);
+#endif
+
+int vdec_read_user_data(struct vdec_s *vdec,
+ struct userdata_param_t *p_userdata_param);
+
+int vdec_wakeup_userdata_poll(struct vdec_s *vdec);
+
+void vdec_reset_userdata_fifo(struct vdec_s *vdec, int bInit);
+
int vdec_get_debug_flags(void);
unsigned char is_mult_inc(unsigned int);
diff --git a/drivers/frame_provider/decoder/utils/vdec_profile.c b/drivers/frame_provider/decoder/utils/vdec_profile.c
index 95129ae..77eb4e3 100644
--- a/drivers/frame_provider/decoder/utils/vdec_profile.c
+++ b/drivers/frame_provider/decoder/utils/vdec_profile.c
@@ -55,25 +55,41 @@ static const char *event_name[VDEC_PROFILE_MAX_EVENT] = {
"info"
};
-static u64 get_us_time(void)
+#if 0 /* get time from hardware. */
+static u64 get_us_time_hw(void)
{
u32 lo, hi1, hi2;
+ int offset = 0;
+
+ /* txlx, g12a isa register base is 0x3c00 */
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX)
+ offset = 0x1600;
do {
- hi1 = READ_MPEG_REG(ISA_TIMERE_HI);
- lo = READ_MPEG_REG(ISA_TIMERE);
- hi2 = READ_MPEG_REG(ISA_TIMERE_HI);
+ hi1 = READ_MPEG_REG(ISA_TIMERE_HI + offset);
+ lo = READ_MPEG_REG(ISA_TIMERE + offset);
+ hi2 = READ_MPEG_REG(ISA_TIMERE_HI + offset);
} while (hi1 != hi2);
return (((u64)hi1) << 32) | lo;
}
+#endif
+
+static u64 get_us_time_system(void)
+{
+ struct timeval tv;
+
+ do_gettimeofday(&tv);
+
+ return div64_u64(timeval_to_ns(&tv), 1000);
+}
void vdec_profile_more(struct vdec_s *vdec, int event, int para1, int para2)
{
mutex_lock(&vdec_profile_mutex);
recs[rec_wp].vdec = vdec;
- recs[rec_wp].timestamp = get_us_time();
+ recs[rec_wp].timestamp = get_us_time_system();
recs[rec_wp].event = event;
recs[rec_wp].para1 = para1;
recs[rec_wp].para2 = para2;
@@ -208,6 +224,8 @@ err:
int vdec_profile_init_debugfs(void)
{
+ struct dentry *root, *event;
+
root = debugfs_create_dir("vdec_profile", NULL);
if (IS_ERR(root) || !root)
goto err;
diff --git a/drivers/frame_provider/decoder/vp9/vvp9.c b/drivers/frame_provider/decoder/vp9/vvp9.c
index 306f7ab..38a98ee 100644
--- a/drivers/frame_provider/decoder/vp9/vvp9.c
+++ b/drivers/frame_provider/decoder/vp9/vvp9.c
@@ -58,6 +58,15 @@
#define SUPPORT_4K2K
#include "vvp9.h"
+
+#ifdef VP9_10B_MMU
+/*#define SUPPORT_FB_DECODING*/
+/*#define FB_DECODING_TEST_SCHEDULE*/
+#endif
+
+#define HW_MASK_FRONT 0x1
+#define HW_MASK_BACK 0x2
+
#define VP9D_MPP_REFINFO_TBL_ACCCONFIG 0x3442
#define VP9D_MPP_REFINFO_DATA 0x3443
#define VP9D_MPP_REF_SCALE_ENBL 0x3441
@@ -69,7 +78,6 @@
#define HEVC_SAO_MMU_VH0_ADDR 0x363a
#define HEVC_SAO_MMU_STATUS 0x3639
-
#define VP9_10B_DEC_IDLE 0
#define VP9_10B_DEC_FRAME_HEADER 1
#define VP9_10B_DEC_SLICE_SEGMENT 2
@@ -83,6 +91,7 @@
#define HEVC_DECODE_TIMEOUT 0x21
#define HEVC_SEARCH_BUFEMPTY 0x22
#define HEVC_DECODE_OVER_SIZE 0x23
+#define HEVC_S2_DECODING_DONE 0x50
#define VP9_HEAD_PARSER_DONE 0xf0
#define VP9_HEAD_SEARCH_DONE 0xf1
#define VP9_EOS 0xf2
@@ -93,9 +102,9 @@
#undef pr_info
#define pr_info printk
-#define DECODE_MODE_SINGLE 0
-#define DECODE_MODE_MULTI_STREAMBASE 1
-#define DECODE_MODE_MULTI_FRAMEBASE 2
+#define DECODE_MODE_SINGLE ((0x80 << 24) | 0)
+#define DECODE_MODE_MULTI_STREAMBASE ((0x80 << 24) | 1)
+#define DECODE_MODE_MULTI_FRAMEBASE ((0x80 << 24) | 2)
#define VP9_TRIGGER_FRAME_DONE 0x100
@@ -186,13 +195,20 @@ static unsigned int not_run_ready[MAX_DECODE_INSTANCE_NUM];
static u32 decode_timeout_val = 200;
static int start_decode_buf_level = 0x8000;
-static u32 work_buf_size;
+#ifdef VP9_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;
/* DOUBLE_WRITE_MODE is enabled only when NV21 8 bit output is needed */
-/* double_write_mode: 0, no double write; 1, 1:1 ratio; 2, (1/4):(1/4) ratio
- 0x10, double write only
+/* double_write_mode: 0, no double write
+ 1, 1:1 ratio
+ 2, (1/4):(1/4) ratio
+ 4, (1/2):(1/2) ratio
+ 0x10, double write only
*/
static u32 double_write_mode;
@@ -225,13 +241,14 @@ static s32 vvp9_init(struct vdec_s *vdec);
#else
static s32 vvp9_init(struct VP9Decoder_s *pbi);
#endif
-static void vvp9_prot_init(struct VP9Decoder_s *pbi);
+static void vvp9_prot_init(struct VP9Decoder_s *pbi, u32 mask);
static int vvp9_local_init(struct VP9Decoder_s *pbi);
static void vvp9_put_timer_func(unsigned long arg);
static void dump_data(struct VP9Decoder_s *pbi, int size);
static unsigned char get_data_check_sum
(struct VP9Decoder_s *pbi, int size);
static void dump_pic_list(struct VP9Decoder_s *pbi);
+#ifdef VP9_10B_MMU
static int vp9_alloc_mmu(
struct VP9Decoder_s *pbi,
int cur_buf_idx,
@@ -239,7 +256,7 @@ static int vp9_alloc_mmu(
int pic_height,
unsigned short bit_depth,
unsigned int *mmu_index_adr);
-
+#endif
static const char vvp9_dec_id[] = "vvp9-dev";
@@ -261,6 +278,7 @@ static u32 bit_depth_chroma;
static u32 frame_width;
static u32 frame_height;
static u32 video_signal_type;
+static u32 pts_unstable;
static u32 on_no_keyframe_skiped;
#define PROB_SIZE (496 * 2 * 4)
@@ -270,6 +288,20 @@ static u32 on_no_keyframe_skiped;
#define MAX_FRAME_4K_NUM 0x1200
#define FRAME_MMU_MAP_SIZE (MAX_FRAME_4K_NUM * 4)
+#define HEVC_ASSIST_MMU_MAP_ADDR 0x3009
+
+#ifdef SUPPORT_FB_DECODING
+/* register define */
+#define HEVC_ASSIST_HED_FB_W_CTL 0x3006
+#define HEVC_ASSIST_HED_FB_R_CTL 0x3007
+#define HEVC_ASSIST_HED_FB_ADDR 0x3008
+#define HEVC_ASSIST_FB_MMU_MAP_ADDR 0x300a
+#define HEVC_ASSIST_FBD_MMU_MAP_ADDR 0x300b
+
+
+#define MAX_STAGE_PAGE_NUM 0x1200
+#define STAGE_MMU_MAP_SIZE (MAX_STAGE_PAGE_NUM * 4)
+#endif
static inline int div_r32(int64_t m, int n)
{
/*
@@ -349,11 +381,13 @@ typedef unsigned short u16;
#define VP9_DEBUG_MERGE 0x200
#define VP9_DEBUG_DBG_LF_PRINT 0x400
#define VP9_DEBUG_REG 0x800
+#define VP9_DEBUG_2_STAGE 0x1000
+#define VP9_DEBUG_2_STAGE_MORE 0x2000
#define VP9_DEBUG_DIS_LOC_ERROR_PROC 0x10000
#define VP9_DEBUG_DIS_SYS_ERROR_PROC 0x20000
#define VP9_DEBUG_DUMP_PIC_LIST 0x40000
#define VP9_DEBUG_TRIG_SLICE_SEGMENT_PROC 0x80000
-#define VP9_DEBUG_HW_RESET 0x100000
+#define VP9_DEBUG_NO_TRIGGER_FRAME 0x100000
#define VP9_DEBUG_LOAD_UCODE_FROM_FILE 0x200000
#define VP9_DEBUG_FORCE_SEND_AGAIN 0x400000
#define VP9_DEBUG_DUMP_DATA 0x800000
@@ -411,12 +445,13 @@ void WRITE_VREG_DBG2(unsigned int adr, unsigned int val)
#define FRAME_CNT_WINDOW_SIZE 59
#define RATE_CORRECTION_THRESHOLD 5
/**************************************************
- *
- *VP9 buffer management start
- *
- ***************************************************
- */
+
+VP9 buffer management start
+
+***************************************************/
+#ifdef VP9_10B_MMU
#define MMU_COMPRESS_HEADER_SIZE 0x48000
+#endif
#define INVALID_IDX -1 /* Invalid buffer index.*/
@@ -516,11 +551,12 @@ struct PIC_BUFFER_CONFIG_s {
/**/
int slice_idx;
/*buffer*/
+#ifdef VP9_10B_MMU
unsigned long header_adr;
+#endif
unsigned long mpred_mv_wr_start_addr;
- /*unsigned long mc_y_adr;
- *unsigned long mc_u_v_adr;
- */
+ unsigned long mc_y_adr;
+ unsigned long mc_u_v_adr;
unsigned int dw_y_adr;
unsigned int dw_u_v_adr;
int mc_canvas_y;
@@ -608,6 +644,12 @@ enum REFERENCE_MODE {
#define FRAME_BUFFERS (REF_FRAMES + 16)
#define HEADER_FRAME_BUFFERS (FRAME_BUFFERS)
#define MAX_BUF_NUM (FRAME_BUFFERS)
+#define MV_BUFFER_NUM FRAME_BUFFERS
+#ifdef SUPPORT_FB_DECODING
+#define STAGE_MAX_BUFFERS 16
+#else
+#define STAGE_MAX_BUFFERS 0
+#endif
#define FRAME_CONTEXTS_LOG2 2
#define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2)
@@ -618,11 +660,13 @@ enum REFERENCE_MODE {
#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n)
#define WORK_SPACE_BUF_ID (FRAME_BUFFERS + HEADER_FRAME_BUFFERS)
#else
-#define MAX_BMMU_BUFFER_NUM ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS + 1)
+#define MAX_BMMU_BUFFER_NUM \
+ (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + MV_BUFFER_NUM + 1)
#define VF_BUFFER_IDX(n) (n)
#define HEADER_BUFFER_IDX(n) (FRAME_BUFFERS + n)
-#define MV_BUFFER_IDX(n) ((FRAME_BUFFERS * 2) + n)
-#define WORK_SPACE_BUF_ID ((FRAME_BUFFERS * 2) + HEADER_FRAME_BUFFERS)
+#define MV_BUFFER_IDX(n) (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + n)
+#define WORK_SPACE_BUF_ID \
+ (FRAME_BUFFERS + HEADER_FRAME_BUFFERS + MV_BUFFER_NUM)
#endif
struct RefCntBuffer_s {
@@ -730,7 +774,9 @@ struct VP9_Common_s {
int prev_fb_idx;
int new_fb_idx;
+#ifdef VP9_10B_MMU
int cur_fb_idx_mmu;
+#endif
/*last frame's frame type for motion search*/
enum FRAME_TYPE last_frame_type;
enum FRAME_TYPE frame_type;
@@ -889,8 +935,10 @@ struct BuffInfo_s {
struct buff_s dblk_para;
struct buff_s dblk_data;
struct buff_s seg_map;
+#ifdef VP9_10B_MMU
struct buff_s mmu_vbh;
struct buff_s cm_header;
+#endif
struct buff_s mpred_above;
#ifdef MV_USE_FIXED_BUF
struct buff_s mpred_mv;
@@ -912,12 +960,43 @@ struct BuffInfo_s {
#define DEC_RESULT_EOS 9
#define DEC_RESULT_FORCE_EXIT 10
+#define DEC_S1_RESULT_NONE 0
+#define DEC_S1_RESULT_DONE 1
+#define DEC_S1_RESULT_FORCE_EXIT 2
+#define DEC_S1_RESULT_TEST_TRIGGER_DONE 0xf0
+
+#ifdef FB_DECODING_TEST_SCHEDULE
+#define TEST_SET_NONE 0
+#define TEST_SET_PIC_DONE 1
+#define TEST_SET_S2_DONE 2
+#endif
+
static void vp9_work(struct work_struct *work);
#endif
struct loop_filter_info_n;
struct loopfilter;
struct segmentation;
+#ifdef SUPPORT_FB_DECODING
+static void mpred_process(struct VP9Decoder_s *pbi);
+static void vp9_s1_work(struct work_struct *work);
+
+struct stage_buf_s {
+ int index;
+ unsigned short rpm[RPM_END - RPM_BEGIN];
+};
+
+static unsigned int not_run2_ready[MAX_DECODE_INSTANCE_NUM];
+
+static unsigned int run2_count[MAX_DECODE_INSTANCE_NUM];
+
+#ifdef FB_DECODING_TEST_SCHEDULE
+u32 stage_buf_num; /* = 16;*/
+#else
+u32 stage_buf_num;
+#endif
+#endif
+
struct VP9Decoder_s {
#ifdef MULTI_INSTANCE_SUPPORT
unsigned char index;
@@ -944,8 +1023,9 @@ struct VP9Decoder_s {
int double_write_mode;
#endif
+#ifdef VP9_10B_MMU
long used_4k_num;
-
+#endif
unsigned char m_ins_flag;
char *provider_name;
union param_u param;
@@ -965,7 +1045,9 @@ struct VP9Decoder_s {
u32 ucode_pause_pos;
int show_frame_num;
+#ifndef VP9_10B_MMU
struct buff_s mc_buf_spec;
+#endif
struct dec_sysinfo vvp9_amstream_dec_info;
void *rpm_addr;
void *lmem_addr;
@@ -979,13 +1061,15 @@ struct VP9Decoder_s {
dma_addr_t prob_buffer_phy_addr;
dma_addr_t count_buffer_phy_addr;
+#if 1
+ /*VP9_10B_MMU*/
void *frame_mmu_map_addr;
dma_addr_t frame_mmu_map_phy_addr;
-
+#endif
unsigned int use_cma_flag;
struct BUF_s m_BUF[MAX_BUF_NUM];
- struct MVBUF_s m_mv_BUF[MAX_BUF_NUM];
+ struct MVBUF_s m_mv_BUF[MV_BUFFER_NUM];
u32 used_buf_num;
DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE);
DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE);
@@ -1031,11 +1115,10 @@ struct VP9Decoder_s {
uint8_t hold_ref_buf;
uint8_t ready_for_new_data;
struct BufferPool_s vp9_buffer_pool;
-
struct BuffInfo_s *work_space_buf;
-
+#ifndef VP9_10B_MMU
struct buff_s *mc_buf;
-
+#endif
unsigned int frame_width;
unsigned int frame_height;
@@ -1075,11 +1158,38 @@ struct VP9Decoder_s {
int new_frame_displayed;
void *mmu_box;
void *bmmu_box;
- int mmu_enable;
struct vframe_master_display_colour_s vf_dp;
struct firmware_s *fw;
int max_pic_w;
int max_pic_h;
+#ifdef SUPPORT_FB_DECODING
+ int dec_s1_result;
+ int s1_test_cmd;
+ struct work_struct s1_work;
+ int used_stage_buf_num;
+ int s1_pos;
+ int s2_pos;
+ void *stage_mmu_map_addr;
+ dma_addr_t stage_mmu_map_phy_addr;
+ struct stage_buf_s *s1_buf;
+ struct stage_buf_s *s2_buf;
+ struct stage_buf_s *stage_bufs
+ [STAGE_MAX_BUFFERS];
+ unsigned char run2_busy;
+
+ int s1_mv_buf_index;
+ int s1_mv_buf_index_pre;
+ int s1_mv_buf_index_pre_pre;
+ unsigned long s1_mpred_mv_wr_start_addr;
+ unsigned long s1_mpred_mv_wr_start_addr_pre;
+ unsigned short s1_intra_only;
+ unsigned short s1_frame_type;
+ unsigned short s1_width;
+ unsigned short s1_height;
+ unsigned short s1_last_show_frame;
+ union param_u s1_param;
+ u8 back_not_run_ready;
+#endif
} VP9Decoder;
static void resize_context_buffers(struct VP9Decoder_s *pbi,
@@ -1145,28 +1255,26 @@ static int setup_frame_size(
WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (height << 16) | width);
- if (pbi->mmu_enable) {
- /* if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx);*/
- /* cm->prev_fb_idx = cm->new_fb_idx;*/
- /*pr_info
- *("[DEBUG DEBUG]Before alloc_mmu,
- *prev_fb_idx : %d, new_fb_idx : %d\r\n",
- *cm->prev_fb_idx, cm->new_fb_idx);
- */
- ret = vp9_alloc_mmu(pbi,
+#ifdef VP9_10B_MMU
+ /* if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx);*/
+ /* cm->prev_fb_idx = cm->new_fb_idx;*/
+ /*pr_info
+ ("[DEBUG DEBUG]Before alloc_mmu, prev_fb_idx : %d, new_fb_idx : %d\r\n",
+ cm->prev_fb_idx, cm->new_fb_idx);*/
+ ret = vp9_alloc_mmu(pbi,
+ cm->new_fb_idx,
+ params->p.width,
+ params->p.height,
+ params->p.bit_depth,
+ mmu_index_adr);
+ if (ret != 0) {
+ pr_err("can't alloc need mmu1,idx %d ret =%d\n",
cm->new_fb_idx,
- params->p.width,
- params->p.height,
- params->p.bit_depth,
- mmu_index_adr);
- if (ret != 0) {
- pr_err("can't alloc need mmu1,idx %d ret =%d\n",
- cm->new_fb_idx,
- ret);
- return ret;
- }
- cm->cur_fb_idx_mmu = cm->new_fb_idx;
+ ret);
+ return ret;
}
+ cm->cur_fb_idx_mmu = cm->new_fb_idx;
+#endif
resize_context_buffers(pbi, cm, width, height);
setup_display_size(cm, params, print_header_info);
@@ -1237,8 +1345,7 @@ static int setup_frame_size_with_refs(
*/
found = 1;
break;
- }
- {
+ } else {
/*if (print_header_info)
* pr_info
* ("1-bit same_frame_size[%d] read : 0\n", i);
@@ -1270,24 +1377,22 @@ static int setup_frame_size_with_refs(
params->p.height = height;
WRITE_VREG(HEVC_PARSER_PICTURE_SIZE, (height << 16) | width);
- if (pbi->mmu_enable) {
- /*if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx);
- *cm->prev_fb_idx = cm->new_fb_idx;
- */
- /* pr_info
- * ("[DEBUG DEBUG]Before alloc_mmu, prev_fb_idx : %d, new_fb_idx : %d\r\n",
- * cm->prev_fb_idx, cm->new_fb_idx);
- */
- ret = vp9_alloc_mmu(pbi, cm->new_fb_idx,
- params->p.width, params->p.height,
- params->p.bit_depth, mmu_index_adr);
- if (ret != 0) {
- pr_err("can't alloc need mmu,idx %d\r\n",
- cm->new_fb_idx);
- return ret;
- }
- cm->cur_fb_idx_mmu = cm->new_fb_idx;
+#ifdef VP9_10B_MMU
+ /*if(cm->prev_fb_idx >= 0) release_unused_4k(cm->prev_fb_idx);
+ cm->prev_fb_idx = cm->new_fb_idx;*/
+/* pr_info
+ ("[DEBUG DEBUG]Before alloc_mmu, prev_fb_idx : %d, new_fb_idx : %d\r\n",
+ cm->prev_fb_idx, cm->new_fb_idx);*/
+ ret = vp9_alloc_mmu(pbi, cm->new_fb_idx,
+ params->p.width, params->p.height,
+ params->p.bit_depth, mmu_index_adr);
+ if (ret != 0) {
+ pr_err("can't alloc need mmu,idx %d\r\n",
+ cm->new_fb_idx);
+ return ret;
}
+ cm->cur_fb_idx_mmu = cm->new_fb_idx;
+#endif
/*Check to make sure at least one of frames that this frame references
*has valid dimensions.
@@ -1306,19 +1411,18 @@ static int setup_frame_size_with_refs(
}
#if 0
for (i = 0; i < REFS_PER_FRAME; ++i) {
- struct RefBuffer_s * const ref_frame =
- &cm->frame_refs[i];
- if (!valid_ref_frame_img_fmt(
- ref_frame->buf->bit_depth,
- ref_frame->buf->subsampling_x,
- ref_frame->buf->subsampling_y,
- cm->bit_depth,
- cm->subsampling_x,
- cm->subsampling_y)) {
- pr_err
+ struct RefBuffer_s * const ref_frame =
+ &cm->frame_refs[i];
+ if (!valid_ref_frame_img_fmt(
+ ref_frame->buf->bit_depth,
+ ref_frame->buf->subsampling_x,
+ ref_frame->buf->subsampling_y,
+ cm->bit_depth,
+ cm->subsampling_x,
+ cm->subsampling_y))
+ pr_err
("Referenced frame incompatible color fmt\r\n");
return -1;
- }
}
#endif
resize_context_buffers(pbi, cm, width, height);
@@ -1408,6 +1512,12 @@ static int vp9_print_cont(struct VP9Decoder_s *pbi,
return 0;
}
+static void trigger_schedule(struct VP9Decoder_s *pbi)
+{
+ if (pbi->vdec_cb)
+ pbi->vdec_cb(hw_to_vdec(pbi), pbi->vdec_cb_arg);
+}
+
static void reset_process_time(struct VP9Decoder_s *pbi)
{
if (pbi->start_process_time) {
@@ -1440,7 +1550,8 @@ static void timeout_process(struct VP9Decoder_s *pbi)
static u32 get_valid_double_write_mode(struct VP9Decoder_s *pbi)
{
- return ((double_write_mode & 0x80000000) == 0) ?
+ return (pbi->m_ins_flag &&
+ ((double_write_mode & 0x80000000) == 0)) ?
pbi->double_write_mode :
(double_write_mode & 0x7fffffff);
}
@@ -1451,14 +1562,10 @@ static int get_double_write_mode(struct VP9Decoder_s *pbi)
u32 dw;
if (valid_dw_mode == 0x100) {
struct VP9_Common_s *cm = &pbi->common;
- struct PIC_BUFFER_CONFIG_s *cur_pic_config;
- int w, h;
-
- if (!cm->cur_frame)
- return 1;/*no valid frame,*/
- cur_pic_config = &cm->cur_frame->buf;
- w = cur_pic_config->y_crop_width;
- h = cur_pic_config->y_crop_width;
+ struct PIC_BUFFER_CONFIG_s *cur_pic_config
+ = &cm->cur_frame->buf;
+ int w = cur_pic_config->y_crop_width;
+ int h = cur_pic_config->y_crop_width;
if (w > 1920 && h > 1088)
dw = 0x4; /*1:2*/
else
@@ -1502,7 +1609,7 @@ static int get_double_write_ratio(struct VP9Decoder_s *pbi,
}
#define MAX_4K_NUM 0x1200
-
+#ifdef VP9_10B_MMU
int vp9_alloc_mmu(
struct VP9Decoder_s *pbi,
int cur_buf_idx,
@@ -1514,15 +1621,7 @@ int vp9_alloc_mmu(
int bit_depth_10 = (bit_depth == VPX_BITS_10);
int picture_size;
int cur_mmu_4k_number;
- if (!pbi->mmu_box) {
- pr_err("error no mmu box!\n");
- return -1;
- }
- if (bit_depth >= VPX_BITS_12) {
- pbi->fatal_error = DECODER_FATAL_ERROR_SIZE_OVERFLOW;
- pr_err("fatal_error, un support bit depth 12!\n\n");
- return -1;
- }
+
picture_size = compute_losless_comp_body_size(pic_width, pic_height,
bit_depth_10);
cur_mmu_4k_number = ((picture_size + (1 << 12) - 1) >> 12);
@@ -1537,13 +1636,13 @@ int vp9_alloc_mmu(
cur_mmu_4k_number,
mmu_index_adr);
}
-
+#endif
#ifndef MV_USE_FIXED_BUF
static void dealloc_mv_bufs(struct VP9Decoder_s *pbi)
{
int i;
- for (i = 0; i < FRAME_BUFFERS; i++) {
+ for (i = 0; i < MV_BUFFER_NUM; i++) {
if (pbi->m_mv_BUF[i].start_adr) {
if (debug)
pr_info(
@@ -1591,7 +1690,7 @@ static int init_mv_buf_list(struct VP9Decoder_s *pbi)
{
int i;
int ret = 0;
- int count = FRAME_BUFFERS;
+ int count = MV_BUFFER_NUM;
int pic_width = pbi->init_pic_w;
int pic_height = pbi->init_pic_h;
int lcu_size = 64; /*fixed 64*/
@@ -1608,7 +1707,8 @@ static int init_mv_buf_list(struct VP9Decoder_s *pbi)
(~0xffff);
if (mv_buf_margin > 0)
count = REF_FRAMES + mv_buf_margin;
- for (i = 0; i < count; i++) {
+ for (i = 0;
+ i < count && i < MV_BUFFER_NUM; i++) {
if (alloc_mv_buf(pbi, i, size) < 0) {
ret = -1;
break;
@@ -1618,11 +1718,12 @@ static int init_mv_buf_list(struct VP9Decoder_s *pbi)
}
static int get_mv_buf(struct VP9Decoder_s *pbi,
- struct PIC_BUFFER_CONFIG_s *pic)
+ int *mv_buf_index,
+ unsigned long *mpred_mv_wr_start_addr)
{
int i;
int ret = -1;
- for (i = 0; i < FRAME_BUFFERS; i++) {
+ for (i = 0; i < MV_BUFFER_NUM; i++) {
if (pbi->m_mv_BUF[i].start_adr &&
pbi->m_mv_BUF[i].used_flag == 0) {
pbi->m_mv_BUF[i].used_flag = 1;
@@ -1632,15 +1733,15 @@ static int get_mv_buf(struct VP9Decoder_s *pbi,
}
if (ret >= 0) {
- pic->mv_buf_index = ret;
- pic->mpred_mv_wr_start_addr =
+ *mv_buf_index = ret;
+ *mpred_mv_wr_start_addr =
(pbi->m_mv_BUF[ret].start_adr + 0xffff) &
(~0xffff);
if (debug & VP9_DEBUG_BUFMGR_MORE)
pr_info(
"%s => %d (%ld) size 0x%x\n",
__func__, ret,
- pic->mpred_mv_wr_start_addr,
+ *mpred_mv_wr_start_addr,
pbi->m_mv_BUF[ret].size);
} else {
pr_info(
@@ -1651,10 +1752,10 @@ static int get_mv_buf(struct VP9Decoder_s *pbi,
}
static void put_mv_buf(struct VP9Decoder_s *pbi,
- struct PIC_BUFFER_CONFIG_s *pic)
+ int *mv_buf_index)
{
- int i = pic->mv_buf_index;
- if (i >= FRAME_BUFFERS) {
+ int i = *mv_buf_index;
+ if (i >= MV_BUFFER_NUM) {
if (debug & VP9_DEBUG_BUFMGR_MORE)
pr_info(
"%s: index %d beyond range\n",
@@ -1667,7 +1768,7 @@ static void put_mv_buf(struct VP9Decoder_s *pbi,
__func__, i,
pbi->m_mv_BUF[i].used_flag);
- pic->mv_buf_index = -1;
+ *mv_buf_index = -1;
if (pbi->m_mv_BUF[i].start_adr &&
pbi->m_mv_BUF[i].used_flag)
pbi->m_mv_BUF[i].used_flag = 0;
@@ -1683,11 +1784,266 @@ static void put_un_used_mv_bufs(struct VP9Decoder_s *pbi)
(frame_bufs[i].buf.index != -1) &&
(frame_bufs[i].buf.mv_buf_index >= 0)
)
- put_mv_buf(pbi, &frame_bufs[i].buf);
+ put_mv_buf(pbi, &frame_bufs[i].buf.mv_buf_index);
}
}
+
+#ifdef SUPPORT_FB_DECODING
+static bool mv_buf_available(struct VP9Decoder_s *pbi)
+{
+ int i;
+ bool ret = 0;
+ for (i = 0; i < MV_BUFFER_NUM; i++) {
+ if (pbi->m_mv_BUF[i].start_adr &&
+ pbi->m_mv_BUF[i].used_flag == 0) {
+ ret = 1;
+ break;
+ }
+ }
+ return ret;
+}
+#endif
#endif
+#ifdef SUPPORT_FB_DECODING
+static void init_stage_buf(struct VP9Decoder_s *pbi)
+{
+ uint i;
+ for (i = 0; i < STAGE_MAX_BUFFERS
+ && i < stage_buf_num; i++) {
+ pbi->stage_bufs[i] =
+ vmalloc(sizeof(struct stage_buf_s));
+ if (pbi->stage_bufs[i] == NULL) {
+ vp9_print(pbi,
+ 0, "%s vmalloc fail\n", __func__);
+ break;
+ }
+ pbi->stage_bufs[i]->index = i;
+ }
+ pbi->used_stage_buf_num = i;
+ pbi->s1_pos = 0;
+ pbi->s2_pos = 0;
+ pbi->s1_buf = NULL;
+ pbi->s2_buf = NULL;
+ pbi->s1_mv_buf_index = FRAME_BUFFERS;
+ pbi->s1_mv_buf_index_pre = FRAME_BUFFERS;
+ pbi->s1_mv_buf_index_pre_pre = FRAME_BUFFERS;
+
+ if (pbi->used_stage_buf_num > 0)
+ vp9_print(pbi,
+ 0, "%s 2 stage decoding buf %d\n",
+ __func__,
+ pbi->used_stage_buf_num);
+}
+
+static void uninit_stage_buf(struct VP9Decoder_s *pbi)
+{
+ int i;
+ for (i = 0; i < pbi->used_stage_buf_num; i++) {
+ if (pbi->stage_bufs[i])
+ vfree(pbi->stage_bufs[i]);
+ pbi->stage_bufs[i] = NULL;
+ }
+ pbi->used_stage_buf_num = 0;
+ pbi->s1_pos = 0;
+ pbi->s2_pos = 0;
+ pbi->s1_buf = NULL;
+ pbi->s2_buf = NULL;
+}
+
+static int get_s1_buf(
+ struct VP9Decoder_s *pbi)
+{
+ struct stage_buf_s *buf = NULL;
+ int ret = -1;
+ int buf_page_num = MAX_STAGE_PAGE_NUM;
+ int next_s1_pos = pbi->s1_pos + 1;
+
+ if (next_s1_pos >= pbi->used_stage_buf_num)
+ next_s1_pos = 0;
+ if (next_s1_pos == pbi->s2_pos) {
+ pbi->s1_buf = NULL;
+ return ret;
+ }
+
+ buf = pbi->stage_bufs[pbi->s1_pos];
+ ret = decoder_mmu_box_alloc_idx(
+ pbi->mmu_box,
+ buf->index,
+ buf_page_num,
+ pbi->stage_mmu_map_addr);
+ if (ret < 0) {
+ vp9_print(pbi, 0,
+ "%s decoder_mmu_box_alloc fail for index %d (s1_pos %d s2_pos %d)\n",
+ __func__, buf->index,
+ pbi->s1_pos, pbi->s2_pos);
+ buf = NULL;
+ } else {
+ vp9_print(pbi, VP9_DEBUG_2_STAGE,
+ "%s decoder_mmu_box_alloc %d page for index %d (s1_pos %d s2_pos %d)\n",
+ __func__, buf_page_num, buf->index,
+ pbi->s1_pos, pbi->s2_pos);
+ }
+ pbi->s1_buf = buf;
+ return ret;
+}
+
+static void inc_s1_pos(struct VP9Decoder_s *pbi)
+{
+ struct stage_buf_s *buf =
+ pbi->stage_bufs[pbi->s1_pos];
+
+ int used_page_num =
+#ifdef FB_DECODING_TEST_SCHEDULE
+ MAX_STAGE_PAGE_NUM/2;
+#else
+ (READ_VREG(HEVC_ASSIST_HED_FB_W_CTL) >> 16);
+#endif
+ decoder_mmu_box_free_idx_tail(pbi->mmu_box,
+ FRAME_BUFFERS + buf->index, used_page_num);
+
+ pbi->s1_pos++;
+ if (pbi->s1_pos >= pbi->used_stage_buf_num)
+ pbi->s1_pos = 0;
+
+ vp9_print(pbi, VP9_DEBUG_2_STAGE,
+ "%s (used_page_num %d) for index %d (s1_pos %d s2_pos %d)\n",
+ __func__, used_page_num, buf->index,
+ pbi->s1_pos, pbi->s2_pos);
+}
+
+#define s2_buf_available(pbi) (pbi->s1_pos != pbi->s2_pos)
+
+static int get_s2_buf(
+ struct VP9Decoder_s *pbi)
+{
+ int ret = -1;
+ struct stage_buf_s *buf = NULL;
+ if (s2_buf_available(pbi)) {
+ buf = pbi->stage_bufs[pbi->s2_pos];
+ vp9_print(pbi, VP9_DEBUG_2_STAGE,
+ "%s for index %d (s1_pos %d s2_pos %d)\n",
+ __func__, buf->index,
+ pbi->s1_pos, pbi->s2_pos);
+ pbi->s2_buf = buf;
+ ret = 0;
+ }
+ return ret;
+}
+
+static void inc_s2_pos(struct VP9Decoder_s *pbi)
+{
+ struct stage_buf_s *buf =
+ pbi->stage_bufs[pbi->s2_pos];
+ decoder_mmu_box_free_idx(pbi->mmu_box,
+ FRAME_BUFFERS + buf->index);
+ pbi->s2_pos++;
+ if (pbi->s2_pos >= pbi->used_stage_buf_num)
+ pbi->s2_pos = 0;
+ vp9_print(pbi, VP9_DEBUG_2_STAGE,
+ "%s for index %d (s1_pos %d s2_pos %d)\n",
+ __func__, buf->index,
+ pbi->s1_pos, pbi->s2_pos);
+}
+
+static int get_free_stage_buf_num(struct VP9Decoder_s *pbi)
+{
+ int num;
+ if (pbi->s1_pos >= pbi->s2_pos)
+ num = pbi->used_stage_buf_num -
+ (pbi->s1_pos - pbi->s2_pos) - 1;
+ else
+ num = (pbi->s2_pos - pbi->s1_pos) - 1;
+ return num;
+}
+
+#ifndef FB_DECODING_TEST_SCHEDULE
+static DEFINE_SPINLOCK(fb_core_spin_lock);
+
+static u8 is_s2_decoding_finished(struct VP9Decoder_s *pbi)
+{
+ /* to do: VLSI review
+ completion of last LCU decoding in BACK
+ */
+ return 1;
+}
+
+static void start_s1_decoding(struct VP9Decoder_s *pbi)
+{
+ /* to do: VLSI review
+ after parser, how to start LCU decoding in BACK
+ */
+}
+
+static void fb_reset_core(struct vdec_s *vdec, u32 mask)
+{
+ /* to do: VLSI review
+ 1. how to disconnect DMC for FRONT and BACK
+ 2. reset bit 13, 24, FRONT or BACK ??
+ */
+
+ unsigned long flags;
+ u32 reset_bits = 0;
+ if (mask & HW_MASK_FRONT)
+ WRITE_VREG(HEVC_STREAM_CONTROL, 0);
+ spin_lock_irqsave(&fb_core_spin_lock, flags);
+ codec_dmcbus_write(DMC_REQ_CTRL,
+ codec_dmcbus_read(DMC_REQ_CTRL) & (~(1 << 4)));
+ spin_unlock_irqrestore(&fb_core_spin_lock, flags);
+
+ while (!(codec_dmcbus_read(DMC_CHAN_STS)
+ & (1 << 4)))
+ ;
+
+ if ((mask & HW_MASK_FRONT) &&
+ input_frame_based(vdec))
+ WRITE_VREG(HEVC_STREAM_CONTROL, 0);
+
+ /*
+ * 2: assist
+ * 3: parser
+ * 4: parser_state
+ * 8: dblk
+ * 11:mcpu
+ * 12:ccpu
+ * 13:ddr
+ * 14:iqit
+ * 15:ipp
+ * 17:qdct
+ * 18:mpred
+ * 19:sao
+ * 24:hevc_afifo
+ */
+ if (mask & HW_MASK_FRONT) {
+ reset_bits =
+ (1<<3)|(1<<4)|(1<<11)|
+ (1<<12)|(1<<18);
+ }
+ if (mask & HW_MASK_BACK) {
+ reset_bits =
+ (1<<8)|(1<<13)|(1<<14)|(1<<15)|
+ (1<<17)|(1<<19)|(1<<24);
+ }
+ WRITE_VREG(DOS_SW_RESET3, reset_bits);
+#if 0
+ (1<<3)|(1<<4)|(1<<8)|(1<<11)|
+ (1<<12)|(1<<13)|(1<<14)|(1<<15)|
+ (1<<17)|(1<<18)|(1<<19)|(1<<24);
+#endif
+ WRITE_VREG(DOS_SW_RESET3, 0);
+
+
+ spin_lock_irqsave(&fb_core_spin_lock, flags);
+ codec_dmcbus_write(DMC_REQ_CTRL,
+ codec_dmcbus_read(DMC_REQ_CTRL) | (1 << 4));
+ spin_unlock_irqrestore(&fb_core_spin_lock, flags);
+
+}
+#endif
+
+#endif
+
+
static int get_free_fb(struct VP9Decoder_s *pbi)
{
struct VP9_Common_s *const cm = &pbi->common;
@@ -1862,7 +2218,16 @@ int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params)
}
pbi->has_keyframe = 1;
on_no_keyframe_skiped = 0;
-
+/*
+#ifdef VP9_10B_MMU
+ if (!pbi->m_ins_flag)
+ pbi->used_4k_num = (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16);
+ if (cm->prev_fb_idx >= 0) {
+ decoder_mmu_box_free_idx_tail(pbi->mmu_box,
+ cm->prev_fb_idx, pbi->used_4k_num);
+ }
+#endif
+*/
if (cm->new_fb_idx >= 0
&& frame_bufs[cm->new_fb_idx].ref_count == 0){
vp9_release_frame_buffer
@@ -1881,12 +2246,23 @@ int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params)
return -1;
}
#ifndef MV_USE_FIXED_BUF
- if (get_mv_buf(pbi, &pool->frame_bufs[cm->new_fb_idx].buf) < 0) {
- pr_info("get_mv_buf fail\r\n");
- return -1;
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num == 0) {
+#endif
+ if (get_mv_buf(pbi,
+ &pool->frame_bufs[cm->new_fb_idx].
+ buf.mv_buf_index,
+ &pool->frame_bufs[cm->new_fb_idx].
+ buf.mpred_mv_wr_start_addr
+ ) < 0) {
+ pr_info("get_mv_buf fail\r\n");
+ return -1;
+ }
+ if (debug & VP9_DEBUG_BUFMGR_DETAIL)
+ dump_pic_list(pbi);
+#ifdef SUPPORT_FB_DECODING
}
- if (debug & VP9_DEBUG_BUFMGR_DETAIL)
- dump_pic_list(pbi);
+#endif
#endif
cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
/*if (debug & VP9_DEBUG_BUFMGR)
@@ -1894,13 +2270,12 @@ int vp9_bufmgr_process(struct VP9Decoder_s *pbi, union param_u *params)
cm->new_fb_idx);*/
pbi->cur_buf = &frame_bufs[cm->new_fb_idx];
- if (pbi->mmu_enable) {
- /* moved to after picture size ready
- *alloc_mmu(cm, params->p.width, params->p.height,
- *params->p.bit_depth, pbi->frame_mmu_map_addr);
- */
- cm->prev_fb_idx = cm->new_fb_idx;
- }
+#ifdef VP9_10B_MMU
+ /* moved to after picture size ready
+ alloc_mmu(cm, params->p.width, params->p.height,
+ params->p.bit_depth, pbi->frame_mmu_map_addr);*/
+ cm->prev_fb_idx = cm->new_fb_idx;
+#endif
/*read_uncompressed_header()*/
cm->last_frame_type = cm->frame_type;
cm->last_intra_only = cm->intra_only;
@@ -2211,8 +2586,10 @@ int vp9_bufmgr_init(struct VP9Decoder_s *pbi, struct BuffInfo_s *buf_spec_i,
spin_lock_init(&cm->buffer_pool->lock);
cm->prev_fb_idx = INVALID_IDX;
cm->new_fb_idx = INVALID_IDX;
+#ifdef VP9_10B_MMU
pbi->used_4k_num = -1;
cm->cur_fb_idx_mmu = INVALID_IDX;
+#endif
pr_debug
("After vp9_bufmgr_init, prev_fb_idx : %d, new_fb_idx : %d\r\n",
cm->prev_fb_idx, cm->new_fb_idx);
@@ -2225,9 +2602,9 @@ int vp9_bufmgr_init(struct VP9Decoder_s *pbi, struct BuffInfo_s *buf_spec_i,
/* private init */
pbi->work_space_buf = buf_spec_i;
- if (!pbi->mmu_enable)
- pbi->mc_buf = mc_buf_i;
-
+#ifndef VP9_10B_MMU
+ pbi->mc_buf = mc_buf_i;
+#endif
pbi->rpm_addr = NULL;
pbi->lmem_addr = NULL;
@@ -2341,9 +2718,14 @@ static u32 step;
#ifdef SUPPORT_4K2K
static u32 buf_alloc_width = 4096;
static u32 buf_alloc_height = 2304;
+static u32 vp9_max_pic_w = 4096;
+static u32 vp9_max_pic_h = 2304;
#else
static u32 buf_alloc_width = 1920;
static u32 buf_alloc_height = 1088;
+static u32 vp9_max_pic_w = 1920;
+static u32 vp9_max_pic_h = 1088;
+
#endif
static u32 dynamic_buf_num_margin;
#else
@@ -2462,6 +2844,9 @@ static struct device *cma_dev;
*bit [31:20]: used by ucode for debug purpose
*/
#define NAL_SEARCH_CTL HEVC_ASSIST_SCRATCH_I
+ /*[31:24] chip feature
+ 31: 0, use MBOX1; 1, use MBOX0
+ */
#define DECODE_MODE HEVC_ASSIST_SCRATCH_J
#define DECODE_STOP_POS HEVC_ASSIST_SCRATCH_K
@@ -2549,6 +2934,7 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = {
/*4096x2304/64/64 *24 = 0xd800 Bytes*/
.buf_size = 0xd800,
},
+#ifdef VP9_10B_MMU
.mmu_vbh = {
.buf_size = 0x5000, /*2*16*(more than 2304)/4, 4K*/
},
@@ -2560,6 +2946,7 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = {
/* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */
},
#endif
+#endif
.mpred_above = {
.buf_size = 0x10000, /* 2 * size of hevc*/
},
@@ -2649,6 +3036,7 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = {
/*4096x2304/64/64 *24 = 0xd800 Bytes*/
.buf_size = 0xd800,
},
+#ifdef VP9_10B_MMU
.mmu_vbh = {
.buf_size = 0x5000,/*2*16*(more than 2304)/4, 4K*/
},
@@ -2660,6 +3048,7 @@ static struct BuffInfo_s amvvp9_workbuff_spec[WORK_BUF_SPEC_NUM] = {
/* 0x44000 = ((1088*2*1024*4)/32/4)*(32/8) */
},
#endif
+#endif
.mpred_above = {
.buf_size = 0x10000, /* 2 * size of hevc*/
},
@@ -2694,7 +3083,11 @@ int compute_losless_comp_body_size(int width, int height,
width_x64 >>= 6;
height_x32 = height + 31;
height_x32 >>= 5;
- bsize = (is_bit_depth_10?4096:3200)*width_x64*height_x32;
+#ifdef VP9_10B_MMU
+ bsize = (is_bit_depth_10?4096:3200)*width_x64*height_x32;
+#else
+ bsize = (is_bit_depth_10?4096:3072)*width_x64*height_x32;
+#endif
if (debug & VP9_DEBUG_BUFMGR_MORE)
pr_info("%s(%d,%d,%d)=>%d\n",
__func__, width, height,
@@ -2758,15 +3151,15 @@ static void init_buff_spec(struct VP9Decoder_s *pbi,
buf_spec->dblk_para.buf_start + buf_spec->dblk_para.buf_size;
buf_spec->seg_map.buf_start =
buf_spec->dblk_data.buf_start + buf_spec->dblk_data.buf_size;
- if (pbi == NULL || pbi->mmu_enable) {
- buf_spec->mmu_vbh.buf_start =
- buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size;
- buf_spec->mpred_above.buf_start =
- buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size;
- } else {
- buf_spec->mpred_above.buf_start =
+#ifdef VP9_10B_MMU
+ buf_spec->mmu_vbh.buf_start =
buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size;
- }
+ buf_spec->mpred_above.buf_start =
+ buf_spec->mmu_vbh.buf_start + buf_spec->mmu_vbh.buf_size;
+#else
+ buf_spec->mpred_above.buf_start =
+ buf_spec->seg_map.buf_start + buf_spec->seg_map.buf_size;
+#endif
#ifdef MV_USE_FIXED_BUF
buf_spec->mpred_mv.buf_start =
buf_spec->mpred_above.buf_start +
@@ -2835,10 +3228,10 @@ static void init_buff_spec(struct VP9Decoder_s *pbi,
buf_spec->dblk_data.buf_start);
pr_info("seg_map.buf_start :%x\n",
buf_spec->seg_map.buf_start);
- if (pbi->mmu_enable) {
+ #ifdef VP9_10B_MMU
pr_info("mmu_vbh.buf_start :%x\n",
buf_spec->mmu_vbh.buf_start);
- }
+ #endif
pr_info("mpred_above.buf_start :%x\n",
buf_spec->mpred_above.buf_start);
#ifdef MV_USE_FIXED_BUF
@@ -4043,8 +4436,7 @@ static void uninit_mmu_buffers(struct VP9Decoder_s *pbi)
#ifndef MV_USE_FIXED_BUF
dealloc_mv_bufs(pbi);
#endif
- if (pbi->mmu_box)
- decoder_mmu_box_free(pbi->mmu_box);
+ decoder_mmu_box_free(pbi->mmu_box);
pbi->mmu_box = NULL;
if (pbi->bmmu_box)
@@ -4052,6 +4444,121 @@ static void uninit_mmu_buffers(struct VP9Decoder_s *pbi)
pbi->bmmu_box = NULL;
}
+#ifndef VP9_10B_MMU
+static void init_buf_list(struct VP9Decoder_s *pbi)
+{
+ int i;
+ int buf_size;
+#ifndef VP9_10B_MMU
+ int mc_buffer_end = pbi->mc_buf->buf_start + pbi->mc_buf->buf_size;
+#endif
+ pbi->used_buf_num = max_buf_num;
+
+ if (pbi->used_buf_num > MAX_BUF_NUM)
+ pbi->used_buf_num = MAX_BUF_NUM;
+ if (buf_alloc_size > 0) {
+ buf_size = buf_alloc_size;
+ if (debug)
+ pr_info("[Buffer Management] init_buf_list:\n");
+ } else {
+ int pic_width = pbi->init_pic_w;
+ int pic_height = pbi->init_pic_h;
+
+ /*SUPPORT_10BIT*/
+ int losless_comp_header_size = compute_losless_comp_header_size
+ (pic_width, pic_height);
+ int losless_comp_body_size = compute_losless_comp_body_size
+ (pic_width, pic_height, buf_alloc_depth == 10);
+ int mc_buffer_size = losless_comp_header_size
+ + losless_comp_body_size;
+ int mc_buffer_size_h = (mc_buffer_size + 0xffff)>>16;
+
+ int dw_mode = get_double_write_mode_init(pbi);
+
+ if (dw_mode) {
+ int pic_width_dw = pic_width /
+ get_double_write_ratio(pbi, dw_mode);
+ int pic_height_dw = pic_height /
+ get_double_write_ratio(pbi, dw_mode);
+ int lcu_size = 64; /*fixed 64*/
+ int pic_width_64 = (pic_width_dw + 63) & (~0x3f);
+ int pic_height_32 = (pic_height_dw + 31) & (~0x1f);
+ int pic_width_lcu =
+ (pic_width_64 % lcu_size) ? pic_width_64 / lcu_size
+ + 1 : pic_width_64 / lcu_size;
+ int pic_height_lcu =
+ (pic_height_32 % lcu_size) ? pic_height_32 / lcu_size
+ + 1 : pic_height_32 / lcu_size;
+ int lcu_total = pic_width_lcu * pic_height_lcu;
+ int mc_buffer_size_u_v = lcu_total * lcu_size * lcu_size / 2;
+ int mc_buffer_size_u_v_h = (mc_buffer_size_u_v + 0xffff) >> 16;
+ /*64k alignment*/
+ buf_size = ((mc_buffer_size_u_v_h << 16) * 3);
+ } else
+ buf_size = 0;
+
+ if (mc_buffer_size & 0xffff) { /*64k alignment*/
+ mc_buffer_size_h += 1;
+ }
+ if ((dw_mode & 0x10) == 0)
+ buf_size += (mc_buffer_size_h << 16);
+ if (debug) {
+ pr_info
+ ("init_buf_list num %d (width %d height %d):\n",
+ pbi->used_buf_num, pic_width, pic_height);
+ }
+ }
+
+ for (i = 0; i < pbi->used_buf_num; i++) {
+ if (((i + 1) * buf_size) > pbi->mc_buf->buf_size)
+ pbi->use_cma_flag = 1;
+#ifndef VP9_10B_MMU
+ pbi->m_BUF[i].alloc_flag = 0;
+ pbi->m_BUF[i].index = i;
+
+ pbi->use_cma_flag = 1;
+ if (pbi->use_cma_flag) {
+ pbi->m_BUF[i].cma_page_count =
+ PAGE_ALIGN(buf_size) / PAGE_SIZE;
+ if (decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box,
+ VF_BUFFER_IDX(i), buf_size, DRIVER_NAME,
+ &pbi->m_BUF[i].alloc_addr) < 0) {
+ pbi->m_BUF[i].cma_page_count = 0;
+ if (i <= 5) {
+ pbi->fatal_error |=
+ DECODER_FATAL_ERROR_NO_MEM;
+ }
+ break;
+ }
+ pbi->m_BUF[i].start_adr = pbi->m_BUF[i].alloc_addr;
+ } else {
+ pbi->m_BUF[i].cma_page_count = 0;
+ pbi->m_BUF[i].alloc_addr = 0;
+ pbi->m_BUF[i].start_adr =
+ pbi->mc_buf->buf_start + i * buf_size;
+ }
+ pbi->m_BUF[i].size = buf_size;
+ pbi->m_BUF[i].free_start_adr = pbi->m_BUF[i].start_adr;
+
+ if (((pbi->m_BUF[i].start_adr + buf_size) > mc_buffer_end)
+ && (pbi->m_BUF[i].alloc_addr == 0)) {
+ if (debug) {
+ pr_info
+ ("Max mc buffer or mpred_mv buffer is used\n");
+ }
+ break;
+ }
+
+ if (debug) {
+ pr_info("Buffer %d: start_adr %p size %x\n", i,
+ (void *)pbi->m_BUF[i].start_adr,
+ pbi->m_BUF[i].size);
+ }
+#endif
+ }
+ pbi->buf_num = i;
+}
+#endif
static int config_pic(struct VP9Decoder_s *pbi,
struct PIC_BUFFER_CONFIG_s *pic_config)
@@ -4088,6 +4595,8 @@ static int config_pic(struct VP9Decoder_s *pbi,
int mc_buffer_size_u_v_h = 0;
int dw_mode = get_double_write_mode_init(pbi);
+ pbi->lcu_total = lcu_total;
+
if (dw_mode) {
int pic_width_dw = pic_width /
get_double_write_ratio(pbi, dw_mode);
@@ -4112,19 +4621,20 @@ static int config_pic(struct VP9Decoder_s *pbi,
if (mc_buffer_size & 0xffff) /*64k alignment*/
mc_buffer_size_h += 1;
- if ((!pbi->mmu_enable) && ((dw_mode & 0x10) == 0))
+#ifndef VP9_10B_MMU
+ if ((dw_mode & 0x10) == 0)
buf_size += (mc_buffer_size_h << 16);
+#endif
+#ifdef VP9_10B_MMU
+ pic_config->header_adr = decoder_bmmu_box_get_phy_addr(
+ pbi->bmmu_box, HEADER_BUFFER_IDX(pic_config->index));
- if (pbi->mmu_enable) {
- pic_config->header_adr = decoder_bmmu_box_get_phy_addr(
- pbi->bmmu_box, HEADER_BUFFER_IDX(pic_config->index));
-
- if (debug & VP9_DEBUG_BUFMGR_MORE) {
- pr_info("MMU header_adr %d: %ld\n",
- pic_config->index, pic_config->header_adr);
- }
+ if (debug & VP9_DEBUG_BUFMGR_MORE) {
+ pr_info("MMU header_adr %d: %ld\n",
+ pic_config->index, pic_config->header_adr);
}
+#endif
i = pic_config->index;
#ifdef MV_USE_FIXED_BUF
@@ -4133,81 +4643,122 @@ static int config_pic(struct VP9Decoder_s *pbi,
<= mpred_mv_end
) {
#endif
-
- if (buf_size > 0) {
- ret = decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box,
- VF_BUFFER_IDX(i),
- buf_size, DRIVER_NAME,
- &pic_config->cma_alloc_addr);
- if (ret < 0) {
- pr_info(
- "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n",
- VF_BUFFER_IDX(i),
- buf_size
- );
- return ret;
+#ifndef VP9_10B_MMU
+ if (debug) {
+ pr_err("start %x .size=%d\n",
+ pbi->mc_buf_spec.buf_start + i * buf_size,
+ buf_size);
}
- if (pic_config->cma_alloc_addr)
- y_adr = pic_config->cma_alloc_addr;
- else {
- pr_info(
- "decoder_bmmu_box_alloc_buf_phy idx %d size %d return null\n",
- VF_BUFFER_IDX(i),
- buf_size
- );
- return -1;
+#endif
+#ifndef VP9_10B_MMU
+ for (i = 0; i < pbi->buf_num; i++) {
+ y_adr = ((pbi->m_BUF[i].free_start_adr
+ + 0xffff) >> 16) << 16;
+ /*64k alignment*/
+ if ((y_adr+buf_size) <= (pbi->m_BUF[i].start_adr+
+ pbi->m_BUF[i].size)) {
+ pbi->m_BUF[i].free_start_adr =
+ y_adr + buf_size;
+ break;
+ }
}
- }
- {
- /*ensure get_pic_by_POC()
- *not get the buffer not decoded
- */
- pic_config->BUF_index = i;
- pic_config->lcu_total = lcu_total;
-
- pic_config->comp_body_size = losless_comp_body_size;
- pic_config->buf_size = buf_size;
-
- pic_config->mc_canvas_y = pic_config->index;
- pic_config->mc_canvas_u_v = pic_config->index;
- if (dw_mode & 0x10) {
- pic_config->dw_y_adr = y_adr;
- pic_config->dw_u_v_adr = y_adr +
- ((mc_buffer_size_u_v_h << 16) << 1);
-
- pic_config->mc_canvas_y =
- (pic_config->index << 1);
- pic_config->mc_canvas_u_v =
- (pic_config->index << 1) + 1;
- } else if (dw_mode) {
- pic_config->dw_y_adr = y_adr;
- pic_config->dw_u_v_adr = pic_config->dw_y_adr +
- ((mc_buffer_size_u_v_h << 16) << 1);
+ if (i < pbi->buf_num)
+#else
+ /*if ((pbi->mc_buf->buf_start + (i + 1) * buf_size) <
+ pbi->mc_buf->buf_end)
+ y_adr = pbi->mc_buf->buf_start + i * buf_size;
+ else {*/
+ if (buf_size > 0) {
+ ret = decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box,
+ VF_BUFFER_IDX(i),
+ buf_size, DRIVER_NAME,
+ &pic_config->cma_alloc_addr);
+ if (ret < 0) {
+ pr_info(
+ "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n",
+ VF_BUFFER_IDX(i),
+ buf_size
+ );
+ return ret;
+ }
+
+ if (pic_config->cma_alloc_addr)
+ y_adr = pic_config->cma_alloc_addr;
+ else {
+ pr_info(
+ "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_config->BUF_index = i;
+ pic_config->lcu_total = lcu_total;
+
+ pic_config->comp_body_size = losless_comp_body_size;
+ pic_config->buf_size = buf_size;
+#ifndef VP9_10B_MMU
+ pic_config->mc_y_adr = y_adr;
+#endif
+ pic_config->mc_canvas_y = pic_config->index;
+ pic_config->mc_canvas_u_v = pic_config->index;
+#ifndef VP9_10B_MMU
+ if (dw_mode & 0x10) {
+ pic_config->mc_u_v_adr = y_adr +
+ ((mc_buffer_size_u_v_h << 16) << 1);
+
+ pic_config->mc_canvas_y =
+ (pic_config->index << 1);
+ pic_config->mc_canvas_u_v =
+ (pic_config->index << 1) + 1;
+
+ pic_config->dw_y_adr = y_adr;
+ pic_config->dw_u_v_adr = pic_config->mc_u_v_adr;
+ } else
+#endif
+ if (dw_mode) {
+ pic_config->dw_y_adr = y_adr
+#ifndef VP9_10B_MMU
+ + (mc_buffer_size_h << 16)
+#endif
+ ;
+ pic_config->dw_u_v_adr = pic_config->dw_y_adr +
+ ((mc_buffer_size_u_v_h << 16) << 1);
+#ifdef VP9_10B_MMU
+ pic_config->mc_y_adr = pic_config->dw_y_adr;
+ pic_config->mc_u_v_adr = pic_config->dw_u_v_adr;
+#endif
+ }
#ifdef MV_USE_FIXED_BUF
- pic_config->mpred_mv_wr_start_addr =
- pbi->work_space_buf->mpred_mv.buf_start +
- ((pic_config->index * lcu_total)
- * MV_MEM_UNIT);
+ pic_config->mpred_mv_wr_start_addr =
+ pbi->work_space_buf->mpred_mv.buf_start +
+ ((pic_config->index * lcu_total)
+ * MV_MEM_UNIT);
#endif
- if (debug) {
- pr_info
- ("%s index %d BUF_index %d ",
- __func__, pic_config->index,
- pic_config->BUF_index);
- pr_info
- ("comp_body_size %x comp_buf_size %x ",
- pic_config->comp_body_size,
- pic_config->buf_size);
- pr_info
- ("mpred_mv_wr_start_adr %ld\n",
- pic_config->mpred_mv_wr_start_addr);
- pr_info("dw_y_adr %d, pic_config->dw_u_v_adr =%d\n",
- pic_config->dw_y_adr,
- pic_config->dw_u_v_adr);
+ if (debug) {
+ pr_info
+ ("%s index %d BUF_index %d mc_y_adr %lx ",
+ __func__, pic_config->index,
+ pic_config->BUF_index,
+ pic_config->mc_y_adr);
+ pr_info
+ ("comp_body_size %x comp_buf_size %x ",
+ pic_config->comp_body_size,
+ pic_config->buf_size);
+ pr_info
+ ("mpred_mv_wr_start_adr %ld\n",
+ pic_config->mpred_mv_wr_start_addr);
+ pr_info("dw_y_adr %d, pic_config->dw_u_v_adr =%d\n",
+ pic_config->dw_y_adr,
+ pic_config->dw_u_v_adr);
+ }
+ ret = 0;
}
- ret = 0;
- }
#ifdef MV_USE_FIXED_BUF
}
#endif
@@ -4219,23 +4770,22 @@ static void init_pic_list(struct VP9Decoder_s *pbi)
int i;
struct VP9_Common_s *cm = &pbi->common;
struct PIC_BUFFER_CONFIG_s *pic_config;
- if (pbi->mmu_enable) {
- /*alloc VP9 compress header first*/
- for (i = 0; i < pbi->used_buf_num; i++) {
- unsigned long buf_addr;
-
- if (decoder_bmmu_box_alloc_buf_phy
- (pbi->bmmu_box,
- HEADER_BUFFER_IDX(i), MMU_COMPRESS_HEADER_SIZE,
- DRIVER_HEADER_NAME,
- &buf_addr) < 0){
- pr_info("%s malloc compress header failed %d\n",
- DRIVER_HEADER_NAME, i);
- pbi->fatal_error |= DECODER_FATAL_ERROR_NO_MEM;
- return;
- }
+#ifdef VP9_10B_MMU
+ /*alloc VP9 compress header first*/
+ for (i = 0; i < pbi->used_buf_num; i++) {
+ unsigned long buf_addr;
+ if (decoder_bmmu_box_alloc_buf_phy
+ (pbi->bmmu_box,
+ HEADER_BUFFER_IDX(i), MMU_COMPRESS_HEADER_SIZE,
+ DRIVER_HEADER_NAME,
+ &buf_addr) < 0){
+ pr_info("%s malloc compress header failed %d\n",
+ DRIVER_HEADER_NAME, i);
+ pbi->fatal_error |= DECODER_FATAL_ERROR_NO_MEM;
+ return;
}
}
+#endif
for (i = 0; i < pbi->used_buf_num; i++) {
pic_config = &cm->buffer_pool->frame_bufs[i].buf;
pic_config->index = i;
@@ -4250,10 +4800,7 @@ static void init_pic_list(struct VP9Decoder_s *pbi)
}
pic_config->y_crop_width = pbi->init_pic_w;
pic_config->y_crop_height = pbi->init_pic_h;
- pic_config->double_write_mode = get_double_write_mode(pbi);
- if (pic_config->double_write_mode) {
- set_canvas(pbi, pic_config);
- }
+ /*set_canvas(pic_config);*/
}
for (; i < pbi->used_buf_num; i++) {
pic_config = &cm->buffer_pool->frame_bufs[i].buf;
@@ -4282,36 +4829,22 @@ static void init_pic_list_hw(struct VP9Decoder_s *pbi)
if (pic_config->index < 0)
break;
- if (pbi->mmu_enable) {
- /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
- * pic_config->header_adr
- * | (pic_config->mc_canvas_y << 8)|0x1);
- */
- WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA,
- pic_config->header_adr >> 5);
- } else {
- /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
- * pic_config->mc_y_adr
- * | (pic_config->mc_canvas_y << 8) | 0x1);
- */
- WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA,
- pic_config->dw_y_adr >> 5);
- }
-#ifndef LOSLESS_COMPRESS_MODE
- /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
- * pic_config->mc_u_v_adr
- * | (pic_config->mc_canvas_u_v << 8)| 0x1);
- */
- WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic_config->header_adr >> 5);
+#ifdef VP9_10B_MMU
+ /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
+ pic_config->header_adr
+ | (pic_config->mc_canvas_y << 8)|0x1);*/
+ WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic_config->header_adr >> 5);
#else
- if (pic_config->double_write_mode & 0x10) {
- if (pbi->mmu_enable)
- WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA,
- pic_config->header_adr>>5);
- else
- WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA,
- pic_config->dw_u_v_adr >> 5);
- }
+ /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
+ pic_config->mc_y_adr
+ | (pic_config->mc_canvas_y << 8) | 0x1);*/
+ WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic_config->mc_y_adr >> 5);
+#endif
+#ifndef LOSLESS_COMPRESS_MODE
+ /*WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_CMD_ADDR,
+ pic_config->mc_u_v_adr
+ | (pic_config->mc_canvas_u_v << 8)| 0x1);*/
+ WRITE_VREG(HEVCD_MPP_ANC2AXI_TBL_DATA, pic_config->mc_u_v_adr >> 5);
#endif
}
@@ -4333,7 +4866,7 @@ static void dump_pic_list(struct VP9Decoder_s *pbi)
for (i = 0; i < FRAME_BUFFERS; i++) {
pic_config = &cm->buffer_pool->frame_bufs[i].buf;
vp9_print(pbi, 0,
- "Buf(%d) index %d mv_buf_index %d vf_ref %d dec_idx %d slice_type %d w/h %d/%d adr%ld\n",
+ "Buf(%d) index %d mv_buf_index %d ref_count %d vf_ref %d dec_idx %d slice_type %d w/h %d/%d adr%ld\n",
i,
pic_config->index,
#ifndef MV_USE_FIXED_BUF
@@ -4341,6 +4874,8 @@ static void dump_pic_list(struct VP9Decoder_s *pbi)
#else
-1,
#endif
+ cm->buffer_pool->
+ frame_bufs[i].ref_count,
pic_config->vf_ref,
pic_config->decode_idx,
pic_config->slice_type,
@@ -4381,23 +4916,21 @@ static int config_pic_size(struct VP9Decoder_s *pbi, unsigned short bit_depth)
WRITE_VREG(HEVC_SAO_CTRL5, data32);
- if (pbi->mmu_enable) {
- /*bit[4] : paged_mem_mode*/
- WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4));
- } else {
+#ifdef VP9_10B_MMU
+ /*bit[4] : paged_mem_mode*/
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4));
+#else
/*bit[3] smem mdoe*/
- if (bit_depth == VPX_BITS_10)
- WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0 << 3));
- else
- WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (1 << 3));
- }
+ if (bit_depth == VPX_BITS_10)
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0 << 3));
+ else
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (1 << 3));
+#endif
WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5));
/*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/
WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size);
WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size);
WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size);
- if (get_double_write_mode(pbi) & 0x10)
- WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
#else
WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
#endif
@@ -4465,10 +4998,11 @@ static int config_mc_buffer(struct VP9Decoder_s *pbi, unsigned short bit_depth)
WRITE_VREG(VP9D_MPP_REFINFO_DATA,
(pic_config->y_crop_height << 14)
/ cur_pic_config->y_crop_height);
- if (pbi->mmu_enable)
- WRITE_VREG(VP9D_MPP_REFINFO_DATA, 0);
- else
- WRITE_VREG(VP9D_MPP_REFINFO_DATA, ref_pic_body_size >> 5);
+#ifdef VP9_10B_MMU
+ WRITE_VREG(VP9D_MPP_REFINFO_DATA, 0);
+#else
+ WRITE_VREG(VP9D_MPP_REFINFO_DATA, ref_pic_body_size >> 5);
+#endif
}
WRITE_VREG(VP9D_MPP_REF_SCALE_ENBL, scale_enable);
return 0;
@@ -4543,7 +5077,10 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params)
int mc_buffer_size_u_v_h =
(mc_buffer_size_u_v + 0xffff) >> 16;/*64k alignment*/
-
+#ifndef VP9_10B_MMU
+ if ((get_double_write_mode(pbi) & 0x10) == 0)
+ WRITE_VREG(HEVC_CM_BODY_START_ADDR, pic_config->mc_y_adr);
+#endif
if (get_double_write_mode(pbi)) {
WRITE_VREG(HEVC_SAO_Y_START_ADDR, pic_config->dw_y_adr);
WRITE_VREG(HEVC_SAO_C_START_ADDR, pic_config->dw_u_v_adr);
@@ -4553,9 +5090,9 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params)
WRITE_VREG(HEVC_SAO_Y_START_ADDR, 0xffffffff);
WRITE_VREG(HEVC_SAO_C_START_ADDR, 0xffffffff);
}
- if (pbi->mmu_enable)
- WRITE_VREG(HEVC_CM_HEADER_START_ADDR, pic_config->header_adr);
-
+#ifdef VP9_10B_MMU
+ WRITE_VREG(HEVC_CM_HEADER_START_ADDR, pic_config->header_adr);
+#endif
data32 = (mc_buffer_size_u_v_h << 16) << 1;
/*pr_info("data32=%x,mc_buffer_size_u_v_h=%x,lcu_total=%x\n",
* data32, mc_buffer_size_u_v_h, pic_config->lcu_total);
@@ -4581,7 +5118,7 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params)
/*set them all 0 for H265_NV21 (no down-scale)*/
data32 &= ~(0xff << 16);
WRITE_VREG(HEVC_SAO_CTRL5, data32);
- data32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
+ ata32 = READ_VREG(HEVCD_IPP_AXIIF_CONFIG);
data32 &= (~0x30);
/*[5:4] address_format 00:linear 01:32x32 10:64x32*/
data32 |= (MEM_MAP_MODE << 4);
@@ -4626,12 +5163,27 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params)
data32 &= (~0xff0);
/* data32 |= 0x670; // Big-Endian per 64-bit */
data32 |= endian; /* Big-Endian per 64-bit */
- data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/
- if (get_double_write_mode(pbi) == 0)
- data32 |= 0x2; /*disable double write*/
- else if (!pbi->mmu_enable &&
- get_double_write_mode(pbi) & 0x10)
+ if (get_cpu_type() < MESON_CPU_MAJOR_ID_G12A) {
+ data32 &= (~0x3); /*[1]:dw_disable [0]:cm_disable*/
+ if (get_double_write_mode(pbi) == 0)
+ data32 |= 0x2; /*disable double write*/
+#ifndef VP9_10B_MMU
+ else
+ if (get_double_write_mode(pbi) & 0x10)
data32 |= 0x1; /*disable cm*/
+#endif
+ } else { /* >= G12A dw write control */
+ unsigned int data;
+ data = READ_VREG(HEVC_DBLK_CFGB);
+ data &= (~0x300); /*[8]:first write enable (compress) [9]:double write enable (uncompress)*/
+ if (get_double_write_mode(pbi) == 0)
+ data |= (0x1 << 8); /*enable first write*/
+ else if (get_double_write_mode(pbi) == 0x10)
+ data |= (0x1 << 9); /*double write only*/
+ else
+ data |= ((0x1 << 8) |(0x1 << 9));
+ WRITE_VREG(HEVC_DBLK_CFGB, data);
+ }
WRITE_VREG(HEVC_SAO_CTRL1, data32);
if (get_double_write_mode(pbi) & 0x10) {
@@ -4667,18 +5219,12 @@ static void config_sao_hw(struct VP9Decoder_s *pbi, union param_u *params)
#endif
}
-static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi)
+static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi, u32 mask)
{
struct BuffInfo_s *buf_spec = pbi->work_space_buf;
-#ifdef LOSLESS_COMPRESS_MODE
- int losless_comp_header_size =
- compute_losless_comp_header_size(pbi->init_pic_w,
- pbi->init_pic_h);
- int losless_comp_body_size =
- compute_losless_comp_body_size(pbi->init_pic_w,
- pbi->init_pic_h, buf_alloc_depth == 10);
-#endif
+#ifdef VP9_10B_MMU
unsigned int data32;
+#endif
if (debug && pbi->init_flag == 0)
pr_info("%s %x %x %x %x %x %x %x %x %x %x %x %x\n",
__func__,
@@ -4694,50 +5240,77 @@ static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi)
buf_spec->scalelut.buf_start,
buf_spec->dblk_para.buf_start,
buf_spec->dblk_data.buf_start);
- WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE, buf_spec->ipp.buf_start);
- if ((debug & VP9_DEBUG_SEND_PARAM_WITH_REG) == 0)
- WRITE_VREG(HEVC_RPM_BUFFER, (u32)pbi->rpm_phy_addr);
- WRITE_VREG(HEVC_SHORT_TERM_RPS, buf_spec->short_term_rps.buf_start);
- /*WRITE_VREG(HEVC_VPS_BUFFER, buf_spec->vps.buf_start);*/
- /*WRITE_VREG(HEVC_SPS_BUFFER, buf_spec->sps.buf_start);*/
- WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start);
- WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start);
- WRITE_VREG(HEVC_STREAM_SWAP_BUFFER, buf_spec->swap_buf.buf_start);
- WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2, buf_spec->swap_buf2.buf_start);
- WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start);
-
- /* cfg_p_addr */
- WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start);
- /* cfg_d_addr */
- WRITE_VREG(HEVC_DBLK_CFG5, buf_spec->dblk_data.buf_start);
+ if (mask & HW_MASK_FRONT) {
+ if ((debug & VP9_DEBUG_SEND_PARAM_WITH_REG) == 0)
+ WRITE_VREG(HEVC_RPM_BUFFER, (u32)pbi->rpm_phy_addr);
+
+ WRITE_VREG(HEVC_SHORT_TERM_RPS,
+ buf_spec->short_term_rps.buf_start);
+ /*WRITE_VREG(HEVC_VPS_BUFFER, buf_spec->vps.buf_start);*/
+ /*WRITE_VREG(HEVC_SPS_BUFFER, buf_spec->sps.buf_start);*/
+ WRITE_VREG(HEVC_PPS_BUFFER, buf_spec->pps.buf_start);
+ WRITE_VREG(HEVC_STREAM_SWAP_BUFFER,
+ buf_spec->swap_buf.buf_start);
+ WRITE_VREG(HEVC_STREAM_SWAP_BUFFER2,
+ buf_spec->swap_buf2.buf_start);
+ WRITE_VREG(LMEM_DUMP_ADR, (u32)pbi->lmem_phy_addr);
+
+ }
+
+ if (mask & HW_MASK_BACK) {
#ifdef LOSLESS_COMPRESS_MODE
- if (pbi->mmu_enable) {
+ int losless_comp_header_size =
+ compute_losless_comp_header_size(pbi->init_pic_w,
+ pbi->init_pic_h);
+ int losless_comp_body_size =
+ compute_losless_comp_body_size(pbi->init_pic_w,
+ pbi->init_pic_h, buf_alloc_depth == 10);
+#endif
+ WRITE_VREG(HEVCD_IPP_LINEBUFF_BASE,
+ buf_spec->ipp.buf_start);
+ WRITE_VREG(HEVC_SAO_UP, buf_spec->sao_up.buf_start);
+ WRITE_VREG(HEVC_SCALELUT, buf_spec->scalelut.buf_start);
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
+ /* cfg_addr_adp*/
+ WRITE_VREG(HEVC_DBLK_CFGE, buf_spec->dblk_para.buf_start);
+ if (debug & VP9_DEBUG_BUFMGR_MORE)
+ pr_info("Write HEVC_DBLK_CFGE\n");
+ } else {
+ /* cfg_p_addr */
+ WRITE_VREG(HEVC_DBLK_CFG4, buf_spec->dblk_para.buf_start);
+ }
+ /* cfg_d_addr */
+ WRITE_VREG(HEVC_DBLK_CFG5, buf_spec->dblk_data.buf_start);
+
+#ifdef LOSLESS_COMPRESS_MODE
+#ifdef VP9_10B_MMU
/*bit[4] : paged_mem_mode*/
WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, (0x1 << 4));
WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, 0);
- } else {
+#else
/*if(cur_pic_config->bit_depth == VPX_BITS_10)
* WRITE_VREG(P_HEVCD_MPP_DECOMP_CTL1, (0<<3));
*/
/*bit[3] smem mdoe*/
/*else WRITE_VREG(P_HEVCD_MPP_DECOMP_CTL1, (1<<3));*/
/*bit[3] smem mdoe*/
- WRITE_VREG(HEVCD_MPP_DECOMP_CTL2, (losless_comp_body_size >> 5));
- }
- /*WRITE_VREG(P_HEVCD_MPP_DECOMP_CTL2,(losless_comp_body_size >> 5));*/
- /*WRITE_VREG(P_HEVCD_MPP_DECOMP_CTL3,(0xff<<20) | (0xff<<10) | 0xff);*/
-/*8-bit mode */
- WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size);
- WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size);
- WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size);
- if (get_double_write_mode(pbi) & 0x10)
- WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
+ WRITE_VREG(HEVCD_MPP_DECOMP_CTL2,
+ (losless_comp_body_size >> 5));
+#endif
+ /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL2,
+ (losless_comp_body_size >> 5));*/
+ /*WRITE_VREG(HEVCD_MPP_DECOMP_CTL3,
+ (0xff<<20) | (0xff<<10) | 0xff);*/
+ /*8-bit mode */
+ WRITE_VREG(HEVC_CM_BODY_LENGTH, losless_comp_body_size);
+ WRITE_VREG(HEVC_CM_HEADER_OFFSET, losless_comp_body_size);
+ WRITE_VREG(HEVC_CM_HEADER_LENGTH, losless_comp_header_size);
#else
WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
#endif
- if (pbi->mmu_enable) {
+#ifdef VP9_10B_MMU
WRITE_VREG(HEVC_SAO_MMU_VH0_ADDR, buf_spec->mmu_vbh.buf_start);
WRITE_VREG(HEVC_SAO_MMU_VH1_ADDR, buf_spec->mmu_vbh.buf_start
+ buf_spec->mmu_vbh.buf_size/2);
@@ -4749,17 +5322,20 @@ static void vp9_config_work_space_hw(struct VP9Decoder_s *pbi)
data32 = READ_VREG(HEVC_SAO_CTRL5);
data32 |= (1<<10);
WRITE_VREG(HEVC_SAO_CTRL5, data32);
+#endif
+ WRITE_VREG(VP9_SEG_MAP_BUFFER, buf_spec->seg_map.buf_start);
+
+ /**/
+ WRITE_VREG(VP9_PROB_SWAP_BUFFER, pbi->prob_buffer_phy_addr);
+ WRITE_VREG(VP9_COUNT_SWAP_BUFFER, pbi->count_buffer_phy_addr);
+#ifdef VP9_10B_MMU
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A)
+ WRITE_VREG(HEVC_ASSIST_MMU_MAP_ADDR, pbi->frame_mmu_map_phy_addr);
+ else
+ WRITE_VREG(VP9_MMU_MAP_BUFFER, pbi->frame_mmu_map_phy_addr);
+#endif
}
- WRITE_VREG(VP9_SEG_MAP_BUFFER, buf_spec->seg_map.buf_start);
-
- WRITE_VREG(LMEM_DUMP_ADR, (u32)pbi->lmem_phy_addr);
-
- /**/
- WRITE_VREG(VP9_PROB_SWAP_BUFFER, pbi->prob_buffer_phy_addr);
- WRITE_VREG(VP9_COUNT_SWAP_BUFFER, pbi->count_buffer_phy_addr);
- if (pbi->mmu_enable)
- WRITE_VREG(VP9_MMU_MAP_BUFFER, pbi->frame_mmu_map_phy_addr);
}
@@ -4918,7 +5494,16 @@ void vp9_loop_filter_init(struct VP9Decoder_s *pbi)
}
/*video format is VP9*/
- WRITE_VREG(HEVC_DBLK_CFGB, 0x40400001);
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
+ unsigned int data32;
+ data32 = (0x57 << 8) | /*1st/2nd write both enable*/
+ (0x1 << 0); /*vp9 video format*/
+ WRITE_VREG(HEVC_DBLK_CFGB, data32);
+
+ if (debug & VP9_DEBUG_BUFMGR_MORE)
+ pr_info("[DBLK DEBUG] CFGB : 0x%x\n", data32);
+ } else
+ WRITE_VREG(HEVC_DBLK_CFGB, 0x40400001);
}
/* perform this function per frame*/
void vp9_loop_filter_frame_init(struct segmentation *seg,
@@ -5030,13 +5615,22 @@ void vp9_loop_filter_frame_init(struct segmentation *seg,
/* VP9_LPF_LVL_UPDATE */
#endif
-static void vp9_init_decoder_hw(struct VP9Decoder_s *pbi)
+static void vp9_init_decoder_hw(struct VP9Decoder_s *pbi, u32 mask)
{
unsigned int data32;
int i;
+#if 0
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
+ /* Set MCR fetch priorities*/
+ data32 = 0x1 | (0x1 << 2) | (0x1 <<3) |
+ (24 << 4) | (32 << 11) | (24 << 18) | (32 << 25);
+ WRITE_VREG(HEVCD_MPP_DECOMP_AXIURG_CTL, data32);
+ }
+#endif
/*if (debug & VP9_DEBUG_BUFMGR_MORE)
pr_info("%s\n", __func__);*/
+ if (mask & HW_MASK_FRONT) {
data32 = READ_VREG(HEVC_PARSER_INT_CONTROL);
#if 1
/* set bit 31~29 to 3 if HEVC_STREAM_FIFO_CTL[29] is 1 */
@@ -5051,7 +5645,14 @@ static void vp9_init_decoder_hw(struct VP9Decoder_s *pbi)
(0 << 3) |/*startcode_found_int_amrisc_enable*/
(1 << 0) /*parser_int_enable*/
;
- WRITE_VREG(HEVC_PARSER_INT_CONTROL, data32);
+#ifdef SUPPORT_FB_DECODING
+#ifndef FB_DECODING_TEST_SCHEDULE
+ /*fed_fb_slice_done_int_cpu_enable*/
+ if (pbi->used_stage_buf_num > 0)
+ data32 |= (1 << 10);
+#endif
+#endif
+ WRITE_VREG(HEVC_PARSER_INT_CONTROL, data32);
data32 = READ_VREG(HEVC_SHIFT_STATUS);
data32 = data32 |
@@ -5082,27 +5683,40 @@ static void vp9_init_decoder_hw(struct VP9Decoder_s *pbi)
WRITE_VREG(HEVC_DEC_STATUS_REG, 0);
- /*Initial IQIT_SCALELUT memory -- just to avoid X in simulation*/
- #if 0 /*by CS:only need for simulation*/
- WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);/*cfg_p_addr*/
- for (i = 0; i < 1024; i++)
- WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0);
- #endif
+ }
+ if (mask & HW_MASK_BACK) {
+ /*Initial IQIT_SCALELUT memory
+ -- just to avoid X in simulation*/
+
+ WRITE_VREG(HEVC_IQIT_SCALELUT_WR_ADDR, 0);/*cfg_p_addr*/
+ for (i = 0; i < 1024; i++)
+ WRITE_VREG(HEVC_IQIT_SCALELUT_DATA, 0);
+ }
+
+ if (mask & HW_MASK_FRONT) {
+ u32 decode_mode;
#ifdef ENABLE_SWAP_TEST
WRITE_VREG(HEVC_STREAM_SWAP_TEST, 100);
#else
WRITE_VREG(HEVC_STREAM_SWAP_TEST, 0);
#endif
#ifdef MULTI_INSTANCE_SUPPORT
- if (!pbi->m_ins_flag)
- WRITE_VREG(DECODE_MODE, DECODE_MODE_SINGLE);
- else if (vdec_frame_based(hw_to_vdec(pbi)))
- WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_FRAMEBASE);
- else
- WRITE_VREG(DECODE_MODE, DECODE_MODE_MULTI_STREAMBASE);
- WRITE_VREG(HEVC_DECODE_SIZE, 0);
- WRITE_VREG(HEVC_DECODE_COUNT, 0);
+ if (!pbi->m_ins_flag)
+ decode_mode = DECODE_MODE_SINGLE;
+ else if (vdec_frame_based(hw_to_vdec(pbi)))
+ decode_mode = DECODE_MODE_MULTI_FRAMEBASE;
+ else
+ decode_mode = DECODE_MODE_MULTI_STREAMBASE;
+#ifdef SUPPORT_FB_DECODING
+#ifndef FB_DECODING_TEST_SCHEDULE
+ if (pbi->used_stage_buf_num > 0)
+ decode_mode |= (0x01 << 24);
+#endif
+#endif
+ WRITE_VREG(DECODE_MODE, decode_mode);
+ WRITE_VREG(HEVC_DECODE_SIZE, 0);
+ WRITE_VREG(HEVC_DECODE_COUNT, 0);
#else
WRITE_VREG(DECODE_MODE, DECODE_MODE_SINGLE);
WRITE_VREG(HEVC_DECODE_PIC_BEGIN_REG, 0);
@@ -5117,37 +5731,41 @@ static void vp9_init_decoder_hw(struct VP9Decoder_s *pbi)
WRITE_VREG(HEVC_PARSER_CMD_SKIP_2, PARSER_CMD_SKIP_CFG_2);
- WRITE_VREG(HEVC_PARSER_IF_CONTROL,
- /* (1 << 8) |*/ /*sao_sw_pred_enable*/
- (1 << 5) | /*parser_sao_if_en*/
- (1 << 2) | /*parser_mpred_if_en*/
- (1 << 0) /*parser_scaler_if_en*/
- );
- /*Changed to Start MPRED in microcode*/
- /*
- *pr_info("[test.c] Start MPRED\n");
- *WRITE_VREG(HEVC_MPRED_INT_STATUS,
- *(1<<31)
- *);
- */
- WRITE_VREG(HEVCD_IPP_TOP_CNTL,
- (0 << 1) | /*enable ipp*/
- (1 << 0) /*software reset ipp and mpp*/
- );
- WRITE_VREG(HEVCD_IPP_TOP_CNTL,
- (1 << 1) | /*enable ipp*/
- (0 << 0) /*software reset ipp and mpp*/
- );
- if (get_double_write_mode(pbi) & 0x10)
+ WRITE_VREG(HEVC_PARSER_IF_CONTROL,
+ /* (1 << 8) |*/ /*sao_sw_pred_enable*/
+ (1 << 5) | /*parser_sao_if_en*/
+ (1 << 2) | /*parser_mpred_if_en*/
+ (1 << 0) /*parser_scaler_if_en*/
+ );
+ }
+
+ if (mask & HW_MASK_BACK) {
+ /*Changed to Start MPRED in microcode*/
+ /*
+ pr_info("[test.c] Start MPRED\n");
+ WRITE_VREG(HEVC_MPRED_INT_STATUS,
+ (1<<31)
+ );
+ */
+ WRITE_VREG(HEVCD_IPP_TOP_CNTL,
+ (0 << 1) | /*enable ipp*/
+ (1 << 0) /*software reset ipp and mpp*/
+ );
+ WRITE_VREG(HEVCD_IPP_TOP_CNTL,
+ (1 << 1) | /*enable ipp*/
+ (0 << 0) /*software reset ipp and mpp*/
+ );
+#ifdef VP9_10B_NV21
/*Enable NV21 reference read mode for MC*/
WRITE_VREG(HEVCD_MPP_DECOMP_CTL1, 0x1 << 31);
+#endif
-
- /*Initialize mcrcc and decomp perf counters*/
- if (mcrcc_cache_alg_flag &&
- pbi->init_flag == 0) {
- mcrcc_perfcount_reset();
- decomp_perfcount_reset();
+ /*Initialize mcrcc and decomp perf counters*/
+ if (mcrcc_cache_alg_flag &&
+ pbi->init_flag == 0) {
+ mcrcc_perfcount_reset();
+ decomp_perfcount_reset();
+ }
}
return;
}
@@ -5224,7 +5842,6 @@ static void config_mcrcc_axi_hw(struct VP9Decoder_s *pbi)
}
#if 0
- pr_info("before call mcrcc_get_hitrate\r\n");
mcrcc_get_hitrate();
decomp_get_hitrate();
decomp_get_comprate();
@@ -5475,17 +6092,28 @@ static void vp9_local_uninit(struct VP9Decoder_s *pbi)
pbi->count_buffer_addr = NULL;
}
- if (pbi->mmu_enable) {
- if (pbi->frame_mmu_map_addr) {
- if (pbi->frame_mmu_map_phy_addr)
- dma_free_coherent(amports_get_dma_device(),
- FRAME_MMU_MAP_SIZE, pbi->frame_mmu_map_addr,
- pbi->frame_mmu_map_phy_addr);
-
- pbi->frame_mmu_map_addr = NULL;
- }
+#ifdef VP9_10B_MMU
+ if (pbi->frame_mmu_map_addr) {
+ if (pbi->frame_mmu_map_phy_addr)
+ dma_free_coherent(amports_get_dma_device(),
+ FRAME_MMU_MAP_SIZE, pbi->frame_mmu_map_addr,
+ pbi->frame_mmu_map_phy_addr);
+ pbi->frame_mmu_map_addr = NULL;
+ }
+#endif
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->stage_mmu_map_addr) {
+ if (pbi->stage_mmu_map_phy_addr)
+ dma_free_coherent(amports_get_dma_device(),
+ STAGE_MMU_MAP_SIZE * STAGE_MAX_BUFFERS,
+ pbi->stage_mmu_map_addr,
+ pbi->stage_mmu_map_phy_addr);
+ pbi->stage_mmu_map_addr = NULL;
}
+ uninit_stage_buf(pbi);
+#endif
+
#ifdef VP9_LPF_LVL_UPDATE
free_lf_buf(pbi);
#endif
@@ -5520,9 +6148,9 @@ static int vp9_local_init(struct VP9Decoder_s *pbi)
sizeof(struct BuffInfo_s));
#endif
cur_buf_info->start_adr = pbi->buf_start;
- if (!pbi->mmu_enable)
- pbi->mc_buf_spec.buf_end = pbi->buf_start + pbi->buf_size;
-
+#ifndef VP9_10B_MMU
+ pbi->mc_buf_spec.buf_end = pbi->buf_start + pbi->buf_size;
+#endif
#else
/*! MULTI_INSTANCE_SUPPORT*/
#ifdef SUPPORT_4K2K
@@ -5536,18 +6164,38 @@ static int vp9_local_init(struct VP9Decoder_s *pbi)
#endif
init_buff_spec(pbi, cur_buf_info);
+#ifdef VP9_10B_MMU
vp9_bufmgr_init(pbi, cur_buf_info, NULL);
+#else
+ pbi->mc_buf_spec.buf_start = (cur_buf_info->end_adr + 0xffff)
+ & (~0xffff);
+ pbi->mc_buf_spec.buf_size = (pbi->mc_buf_spec.buf_end
+ - pbi->mc_buf_spec.buf_start);
+ if (debug) {
+ pr_err("pbi->mc_buf_spec.buf_start %x-%x\n",
+ pbi->mc_buf_spec.buf_start,
+ pbi->mc_buf_spec.buf_start +
+ pbi->mc_buf_spec.buf_size);
+ }
+ vp9_bufmgr_init(pbi, cur_buf_info, &pbi->mc_buf_spec);
+#endif
if (!vdec_is_support_4k()
&& (buf_alloc_width > 1920 && buf_alloc_height > 1088)) {
buf_alloc_width = 1920;
buf_alloc_height = 1088;
+ if (pbi->max_pic_w > 1920 && pbi->max_pic_h > 1088) {
+ pbi->max_pic_w = 1920;
+ pbi->max_pic_h = 1088;
+ }
}
- pbi->init_pic_w = pbi->max_pic_w ? pbi->max_pic_w : (buf_alloc_width ? buf_alloc_width :
+ pbi->init_pic_w = pbi->max_pic_w ? pbi->max_pic_w :
+ (buf_alloc_width ? buf_alloc_width :
(pbi->vvp9_amstream_dec_info.width ?
pbi->vvp9_amstream_dec_info.width :
pbi->work_space_buf->max_width));
- pbi->init_pic_h = pbi->max_pic_h ? pbi->max_pic_h : (buf_alloc_height ? buf_alloc_height :
+ pbi->init_pic_h = pbi->max_pic_h ? pbi->max_pic_h :
+ (buf_alloc_height ? buf_alloc_height :
(pbi->vvp9_amstream_dec_info.height ?
pbi->vvp9_amstream_dec_info.height :
pbi->work_space_buf->max_height));
@@ -5558,16 +6206,18 @@ static int vp9_local_init(struct VP9Decoder_s *pbi)
}
#endif
-
+#ifndef VP9_10B_MMU
+ init_buf_list(pbi);
+#else
pbi->used_buf_num = max_buf_num;
if (pbi->used_buf_num > MAX_BUF_NUM)
pbi->used_buf_num = MAX_BUF_NUM;
if (pbi->used_buf_num > FRAME_BUFFERS)
pbi->used_buf_num = FRAME_BUFFERS;
-
+#endif
init_pic_list(pbi);
- pbi->pts_unstable = ((unsigned long)(pbi->vvp9_amstream_dec_info.param)
+ pts_unstable = ((unsigned long)(pbi->vvp9_amstream_dec_info.param)
& 0x40) >> 6;
if ((debug & VP9_DEBUG_SEND_PARAM_WITH_REG) == 0) {
@@ -5637,36 +6287,51 @@ static int vp9_local_init(struct VP9Decoder_s *pbi)
}
memset(pbi->count_buffer_addr, 0, COUNT_BUF_SIZE);
/* pbi->count_buffer_phy_addr = dma_map_single(amports_get_dma_device(),
- * pbi->count_buffer_addr, COUNT_BUF_SIZE, DMA_BIDIRECTIONAL);
- * if (dma_mapping_error(amports_get_dma_device(),
- * pbi->count_buffer_phy_addr)) {
- * pr_err("%s: failed to map count_buffer\n", __func__);
- * kfree(pbi->count_buffer_addr);
- * pbi->count_buffer_addr = NULL;
- * return -1;
- * }
- */
- if (pbi->mmu_enable) {
- pbi->frame_mmu_map_addr = dma_alloc_coherent(amports_get_dma_device(),
- FRAME_MMU_MAP_SIZE,
- &pbi->frame_mmu_map_phy_addr, GFP_KERNEL);
- if (pbi->frame_mmu_map_addr == NULL) {
+ pbi->count_buffer_addr, COUNT_BUF_SIZE, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(amports_get_dma_device(),
+ pbi->count_buffer_phy_addr)) {
+ pr_err("%s: failed to map count_buffer\n", __func__);
+ kfree(pbi->count_buffer_addr);
+ pbi->count_buffer_addr = NULL;
+ return -1;
+ }
+*/
+#ifdef VP9_10B_MMU
+ pbi->frame_mmu_map_addr = dma_alloc_coherent(amports_get_dma_device(),
+ FRAME_MMU_MAP_SIZE,
+ &pbi->frame_mmu_map_phy_addr, GFP_KERNEL);
+ if (pbi->frame_mmu_map_addr == NULL) {
+ pr_err("%s: failed to alloc count_buffer\n", __func__);
+ return -1;
+ }
+ memset(pbi->frame_mmu_map_addr, 0, FRAME_MMU_MAP_SIZE);
+/* pbi->frame_mmu_map_phy_addr = dma_map_single(amports_get_dma_device(),
+ pbi->frame_mmu_map_addr, FRAME_MMU_MAP_SIZE, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(amports_get_dma_device(),
+ pbi->frame_mmu_map_phy_addr)) {
+ pr_err("%s: failed to map count_buffer\n", __func__);
+ kfree(pbi->frame_mmu_map_addr);
+ pbi->frame_mmu_map_addr = NULL;
+ return -1;
+ }*/
+#endif
+
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->m_ins_flag && stage_buf_num > 0) {
+ pbi->stage_mmu_map_addr =
+ dma_alloc_coherent(amports_get_dma_device(),
+ STAGE_MMU_MAP_SIZE * STAGE_MAX_BUFFERS,
+ &pbi->stage_mmu_map_phy_addr, GFP_KERNEL);
+ if (pbi->stage_mmu_map_addr == NULL) {
pr_err("%s: failed to alloc count_buffer\n", __func__);
return -1;
}
- memset(pbi->frame_mmu_map_addr, 0, COUNT_BUF_SIZE);
- /* pbi->frame_mmu_map_phy_addr = dma_map_single(amports_get_dma_device(),
- * pbi->frame_mmu_map_addr, FRAME_MMU_MAP_SIZE, DMA_BIDIRECTIONAL);
- * if (dma_mapping_error(amports_get_dma_device(),
- * pbi->frame_mmu_map_phy_addr)) {
- * pr_err("%s: failed to map count_buffer\n", __func__);
- * kfree(pbi->frame_mmu_map_addr);
- * pbi->frame_mmu_map_addr = NULL;
- * return -1;
- * }
- */
- }
+ memset(pbi->stage_mmu_map_addr,
+ 0, STAGE_MMU_MAP_SIZE * STAGE_MAX_BUFFERS);
+ init_stage_buf(pbi);
+ }
+#endif
ret = 0;
return ret;
@@ -5744,6 +6409,18 @@ static void set_canvas(struct VP9Decoder_s *pbi,
blkmode;
pic_config->canvas_config[1].endian = 7;
#endif
+ } else {
+ #ifndef VP9_10B_MMU
+ pic_config->y_canvas_index = 128 + pic_config->index;
+ pic_config->uv_canvas_index = 128 + pic_config->index;
+
+ canvas_config_ex(pic_config->y_canvas_index,
+ pic_config->mc_y_adr, canvas_w, canvas_h,
+ CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ canvas_config_ex(pic_config->uv_canvas_index,
+ pic_config->mc_u_v_adr, canvas_w, canvas_h,
+ CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ #endif
}
}
@@ -5834,11 +6511,16 @@ static void vvp9_vf_put(struct vframe_s *vf, void *op_arg)
pool->frame_bufs[index].buf.vf_ref--;
if (pbi->wait_buf)
- WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG,
+ WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG,
0x1);
pbi->last_put_idx = index;
pbi->new_frame_displayed++;
unlock_buffer_pool(pool, flags);
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num > 0 &&
+ pbi->back_not_run_ready)
+ trigger_schedule(pbi);
+#endif
}
}
@@ -5944,30 +6626,6 @@ static int frame_duration_adapt(struct VP9Decoder_s *pbi, struct vframe_s *vf, u
return true;
}
-static void update_vf_memhandle(struct VP9Decoder_s *pbi,
- struct vframe_s *vf, struct PIC_BUFFER_CONFIG_s *pic)
-{
- if (pic->index < 0) {
- vf->mem_handle = NULL;
- vf->mem_head_handle = NULL;
- } else if (vf->type & VIDTYPE_SCATTER) {
- vf->mem_handle =
- decoder_mmu_box_get_mem_handle(
- pbi->mmu_box, pic->index);
- vf->mem_head_handle =
- decoder_bmmu_box_get_mem_handle(
- pbi->bmmu_box, HEADER_BUFFER_IDX(pic->BUF_index));
- } else {
- vf->mem_handle =
- decoder_bmmu_box_get_mem_handle(
- pbi->bmmu_box, VF_BUFFER_IDX(pic->BUF_index));
- vf->mem_head_handle = NULL;
- /*vf->mem_head_handle =
- *decoder_bmmu_box_get_mem_handle(
- *hevc->bmmu_box, VF_BUFFER_IDX(BUF_index));
- */
- }
-}
static int prepare_display_buf(struct VP9Decoder_s *pbi,
struct PIC_BUFFER_CONFIG_s *pic_config)
@@ -6106,17 +6764,15 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi,
vf->compBodyAddr = 0;
vf->compHeadAddr = 0;
} else {
- if (pbi->mmu_enable) {
- vf->compBodyAddr = 0;
- vf->compHeadAddr = pic_config->header_adr;
- } else {
- /*vf->compBodyAddr = pic_config->mc_y_adr;
- *vf->compHeadAddr = pic_config->mc_y_adr +
- *pic_config->comp_body_size;
- */
- /*head adr*/
- }
- vf->canvas0Addr = vf->canvas1Addr = 0;
+#ifdef VP9_10B_MMU
+ vf->compBodyAddr = 0;
+ vf->compHeadAddr = pic_config->header_adr;
+#else
+ vf->compBodyAddr = pic_config->mc_y_adr; /*body adr*/
+ vf->compHeadAddr = pic_config->mc_y_adr +
+ pic_config->comp_body_size;
+ /*head adr*/
+#endif
}
if (pic_config->double_write_mode) {
vf->type = VIDTYPE_PROGRESSIVE |
@@ -6124,8 +6780,9 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi,
vf->type |= VIDTYPE_VIU_NV21;
if (pic_config->double_write_mode == 3) {
vf->type |= VIDTYPE_COMPRESS;
- if (pbi->mmu_enable)
- vf->type |= VIDTYPE_SCATTER;
+#ifdef VP9_10B_MMU
+ vf->type |= VIDTYPE_SCATTER;
+#endif
}
#ifdef MULTI_INSTANCE_SUPPORT
if (pbi->m_ins_flag) {
@@ -6147,8 +6804,9 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi,
} else {
vf->canvas0Addr = vf->canvas1Addr = 0;
vf->type = VIDTYPE_COMPRESS | VIDTYPE_VIU_FIELD;
- if (pbi->mmu_enable)
- vf->type |= VIDTYPE_SCATTER;
+#ifdef VP9_10B_MMU
+ vf->type |= VIDTYPE_SCATTER;
+#endif
}
switch (pic_config->bit_depth) {
@@ -6199,9 +6857,31 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi,
else
vf->duration = 0;
}
- update_vf_memhandle(pbi, vf, pic_config);
+#ifdef VP9_10B_MMU
+ if (vf->type & VIDTYPE_SCATTER) {
+ vf->mem_handle = decoder_mmu_box_get_mem_handle(
+ pbi->mmu_box,
+ pic_config->index);
+ vf->mem_head_handle = decoder_bmmu_box_get_mem_handle(
+ pbi->bmmu_box,
+ HEADER_BUFFER_IDX(pic_config->index));
+ } else {
+ vf->mem_handle = decoder_bmmu_box_get_mem_handle(
+ pbi->bmmu_box,
+ VF_BUFFER_IDX(pic_config->index));
+ vf->mem_head_handle = decoder_bmmu_box_get_mem_handle(
+ pbi->bmmu_box,
+ HEADER_BUFFER_IDX(pic_config->index));
+ }
+#else
+ vf->mem_handle = decoder_bmmu_box_get_mem_handle(
+ pbi->bmmu_box,
+ VF_BUFFER_IDX(pic_config->index));
+#endif
if (!(pic_config->y_crop_width == 196
- && pic_config->y_crop_height == 196)) {
+ && pic_config->y_crop_height == 196
+ && (debug & VP9_DEBUG_NO_TRIGGER_FRAME) == 0
+ )) {
inc_vf_ref(pbi, pic_config->index);
kfifo_put(&pbi->display_q, (const struct vframe_s *)vf);
pbi->vf_pre_count++;
@@ -6314,7 +6994,7 @@ static void debug_buffer_mgr_more(struct VP9Decoder_s *pbi)
}
-
+#ifdef VP9_10B_MMU
static void vp9_recycle_mmu_buf_tail(struct VP9Decoder_s *pbi)
{
struct VP9_Common_s *const cm = &pbi->common;
@@ -6343,7 +7023,7 @@ static void vp9_recycle_mmu_buf(struct VP9Decoder_s *pbi)
}
}
#endif
-
+#endif
static void dec_again_process(struct VP9Decoder_s *pbi)
{
@@ -6353,19 +7033,179 @@ static void dec_again_process(struct VP9Decoder_s *pbi)
PROC_STATE_DECODESLICE) {
pbi->process_state =
PROC_STATE_SENDAGAIN;
- if (pbi->mmu_enable)
- vp9_recycle_mmu_buf(pbi);
+#ifdef VP9_10B_MMU
+ vp9_recycle_mmu_buf(pbi);
+#endif
}
reset_process_time(pbi);
vdec_schedule_work(&pbi->work);
}
+int continue_decoding(struct VP9Decoder_s *pbi)
+{
+ int ret;
+ int i;
+ struct VP9_Common_s *const cm = &pbi->common;
+ debug_buffer_mgr_more(pbi);
+
+ bit_depth_luma = vp9_param.p.bit_depth;
+ bit_depth_chroma = vp9_param.p.bit_depth;
+
+ if (pbi->process_state != PROC_STATE_SENDAGAIN) {
+ ret = vp9_bufmgr_process(pbi, &vp9_param);
+ if (!pbi->m_ins_flag)
+ pbi->slice_idx++;
+ } else {
+ union param_u *params = &vp9_param;
+#ifdef VP9_10B_MMU
+ ret = vp9_alloc_mmu(pbi,
+ cm->new_fb_idx,
+ params->p.width,
+ params->p.height,
+ params->p.bit_depth,
+ pbi->frame_mmu_map_addr);
+ if (ret >= 0)
+ cm->cur_fb_idx_mmu = cm->new_fb_idx;
+ else
+ pr_err("can't alloc need mmu1,idx %d ret =%d\n",
+ cm->new_fb_idx,
+ ret);
+#else
+ ret = 0;
+#endif
+ WRITE_VREG(HEVC_PARSER_PICTURE_SIZE,
+ (params->p.height << 16) | params->p.width);
+ }
+ if (ret < 0) {
+ pr_info("vp9_bufmgr_process=> %d, VP9_10B_DISCARD_NAL\r\n",
+ ret);
+ WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DISCARD_NAL);
+ cm->show_frame = 0;
+#ifdef VP9_10B_MMU
+ vp9_recycle_mmu_buf(pbi);
+#endif
+#ifdef MULTI_INSTANCE_SUPPORT
+ if (pbi->m_ins_flag) {
+ pbi->dec_result = DEC_RESULT_DONE;
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num == 0)
+#endif
+ amhevc_stop();
+ vdec_schedule_work(&pbi->work);
+ }
+#endif
+ return ret;
+ } else if (ret == 0) {
+ struct PIC_BUFFER_CONFIG_s *cur_pic_config
+ = &cm->cur_frame->buf;
+ cur_pic_config->decode_idx = pbi->frame_count;
+
+ if (pbi->process_state != PROC_STATE_SENDAGAIN) {
+ if (!pbi->m_ins_flag) {
+ pbi->frame_count++;
+ decode_frame_count[pbi->index]
+ = pbi->frame_count;
+ }
+#ifdef MULTI_INSTANCE_SUPPORT
+ if (pbi->chunk) {
+ cur_pic_config->pts = pbi->chunk->pts;
+ cur_pic_config->pts64 = pbi->chunk->pts64;
+ }
+#endif
+ }
+ /*pr_info("Decode Frame Data %d\n", pbi->frame_count);*/
+ config_pic_size(pbi, vp9_param.p.bit_depth);
+
+ if ((pbi->common.frame_type != KEY_FRAME)
+ && (!pbi->common.intra_only)) {
+ config_mc_buffer(pbi, vp9_param.p.bit_depth);
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num == 0)
+#endif
+ config_mpred_hw(pbi);
+ } else {
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num == 0)
+#endif
+ clear_mpred_hw(pbi);
+ }
+#ifdef MCRCC_ENABLE
+ if (mcrcc_cache_alg_flag)
+ config_mcrcc_axi_hw_new(pbi);
+ else
+ config_mcrcc_axi_hw(pbi);
+#endif
+ config_sao_hw(pbi, &vp9_param);
+
+#ifdef VP9_LPF_LVL_UPDATE
+ /*
+ * Get loop filter related picture level parameters from Parser
+ */
+ pbi->lf->mode_ref_delta_enabled = vp9_param.p.mode_ref_delta_enabled;
+ pbi->lf->sharpness_level = vp9_param.p.sharpness_level;
+ for (i = 0; i < 4; i++)
+ pbi->lf->ref_deltas[i] = vp9_param.p.ref_deltas[i];
+ for (i = 0; i < 2; i++)
+ pbi->lf->mode_deltas[i] = vp9_param.p.mode_deltas[i];
+ pbi->default_filt_lvl = vp9_param.p.filter_level;
+ pbi->seg_4lf->enabled = vp9_param.p.seg_enabled;
+ pbi->seg_4lf->abs_delta = vp9_param.p.seg_abs_delta;
+ for (i = 0; i < MAX_SEGMENTS; i++)
+ pbi->seg_4lf->feature_mask[i] = (vp9_param.p.seg_lf_info[i] &
+ 0x8000) ? (1 << SEG_LVL_ALT_LF) : 0;
+ for (i = 0; i < MAX_SEGMENTS; i++)
+ pbi->seg_4lf->feature_data[i][SEG_LVL_ALT_LF]
+ = (vp9_param.p.seg_lf_info[i]
+ & 0x100) ? -(vp9_param.p.seg_lf_info[i]
+ & 0x3f) : (vp9_param.p.seg_lf_info[i] & 0x3f);
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
+ /*Set pipeline mode*/
+ uint32_t lpf_data32 = READ_VREG(HEVC_DBLK_CFGB);
+ /*dblk pipeline mode=1 for performance*/
+ if (vp9_param.p.width >= 1280)
+ lpf_data32 |= (0x1 << 4);
+ else
+ lpf_data32 &= ~(0x3 << 4);
+ WRITE_VREG(HEVC_DBLK_CFGB, lpf_data32);
+ }
+ /*
+ * Update loop filter Thr/Lvl table for every frame
+ */
+ /*pr_info
+ ("vp9_loop_filter (run before every frame decoding start)\n");*/
+ vp9_loop_filter_frame_init(pbi->seg_4lf,
+ pbi->lfi, pbi->lf, pbi->default_filt_lvl);
+#endif
+ /*pr_info("HEVC_DEC_STATUS_REG <= VP9_10B_DECODE_SLICE\n");*/
+ WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE);
+ } else {
+ pr_info("Skip search next start code\n");
+ cm->prev_fb_idx = INVALID_IDX;
+ /*skip, search next start code*/
+ WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE);
+ }
+ pbi->process_state = PROC_STATE_DECODESLICE;
+#ifdef VP9_10B_MMU
+ if (pbi->last_put_idx >= 0 && pbi->last_put_idx < pbi->used_buf_num) {
+ struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs;
+ int i = pbi->last_put_idx;
+ /*free not used buffers.*/
+ if ((frame_bufs[i].ref_count == 0) &&
+ (frame_bufs[i].buf.vf_ref == 0) &&
+ (frame_bufs[i].buf.index != -1)) {
+ decoder_mmu_box_free_idx(pbi->mmu_box, i);
+ }
+ pbi->last_put_idx = -1;
+ }
+#endif
+ return ret;
+}
+
static irqreturn_t vvp9_isr_thread_fn(int irq, void *data)
{
struct VP9Decoder_s *pbi = (struct VP9Decoder_s *)data;
unsigned int dec_status = pbi->dec_status;
- struct VP9_Common_s *const cm = &pbi->common;
- int i, ret;
+ int i;
/*if (pbi->wait_buf)
* pr_info("set wait_buf to 0\r\n");
@@ -6374,6 +7214,28 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data)
return IRQ_HANDLED;
pbi->wait_buf = 0;
#ifdef MULTI_INSTANCE_SUPPORT
+#ifdef SUPPORT_FB_DECODING
+#ifdef FB_DECODING_TEST_SCHEDULE
+ if (pbi->s1_test_cmd == TEST_SET_PIC_DONE)
+ dec_status = HEVC_DECPIC_DATA_DONE;
+ else if (pbi->s1_test_cmd == TEST_SET_S2_DONE
+ && dec_status == HEVC_DECPIC_DATA_DONE)
+ dec_status = HEVC_S2_DECODING_DONE;
+ pbi->s1_test_cmd = TEST_SET_NONE;
+#else
+ /*if (irq != VDEC_IRQ_0)
+ dec_status = HEVC_S2_DECODING_DONE;*/
+#endif
+ if (dec_status == HEVC_S2_DECODING_DONE) {
+ pbi->dec_result = DEC_RESULT_DONE;
+ vdec_schedule_work(&pbi->work);
+#ifdef FB_DECODING_TEST_SCHEDULE
+ amhevc_stop();
+ pbi->dec_s1_result = DEC_S1_RESULT_DONE;
+ vdec_schedule_work(&pbi->s1_work);
+#endif
+ } else
+#endif
if ((dec_status == HEVC_NAL_DECODE_DONE) ||
(dec_status == HEVC_SEARCH_BUFEMPTY) ||
(dec_status == HEVC_DECODE_BUFEMPTY)
@@ -6391,12 +7253,28 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data)
return IRQ_HANDLED;
} else if (dec_status == HEVC_DECPIC_DATA_DONE) {
if (pbi->m_ins_flag) {
- reset_process_time(pbi);
- pbi->dec_result = DEC_RESULT_DONE;
- amhevc_stop();
- if (mcrcc_cache_alg_flag)
- dump_hit_rate(pbi);
- vdec_schedule_work(&pbi->work);
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num > 0) {
+ reset_process_time(pbi);
+ inc_s1_pos(pbi);
+ trigger_schedule(pbi);
+#ifdef FB_DECODING_TEST_SCHEDULE
+ pbi->s1_test_cmd = TEST_SET_S2_DONE;
+#else
+ amhevc_stop();
+ pbi->dec_s1_result = DEC_S1_RESULT_DONE;
+ vdec_schedule_work(&pbi->s1_work);
+#endif
+ } else
+#endif
+ {
+ reset_process_time(pbi);
+ pbi->dec_result = DEC_RESULT_DONE;
+ amhevc_stop();
+ if (mcrcc_cache_alg_flag)
+ dump_hit_rate(pbi);
+ vdec_schedule_work(&pbi->work);
+ }
}
pbi->process_busy = 0;
@@ -6446,10 +7324,14 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data)
if (pbi->m_ins_flag)
reset_process_time(pbi);
#endif
-
- if (pbi->process_state != PROC_STATE_SENDAGAIN) {
- if (pbi->mmu_enable)
- vp9_recycle_mmu_buf_tail(pbi);
+ if (pbi->process_state != PROC_STATE_SENDAGAIN
+#ifdef SUPPORT_FB_DECODING
+ && pbi->used_stage_buf_num == 0
+#endif
+ ) {
+#ifdef VP9_10B_MMU
+ vp9_recycle_mmu_buf_tail(pbi);
+#endif
if (pbi->frame_count > 0)
vp9_bufmgr_postproc(pbi);
@@ -6463,151 +7345,66 @@ static irqreturn_t vvp9_isr_thread_fn(int irq, void *data)
pbi->rpm_phy_addr,
RPM_BUF_SIZE,
DMA_FROM_DEVICE);
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num > 0) {
+ reset_process_time(pbi);
+ get_s1_buf(pbi);
+
+ if (get_mv_buf(pbi,
+ &pbi->s1_mv_buf_index,
+ &pbi->s1_mpred_mv_wr_start_addr
+ ) < 0) {
+ vp9_print(pbi, 0,
+ "%s: Error get_mv_buf fail\n",
+ __func__);
+ }
- for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) {
- int ii;
-
- for (ii = 0; ii < 4; ii++)
- vp9_param.l.data[i + ii] =
- pbi->rpm_ptr[i + 3 - ii];
- }
- }
- debug_buffer_mgr_more(pbi);
+ if (pbi->s1_buf == NULL) {
+ vp9_print(pbi, 0,
+ "%s: Error get_s1_buf fail\n",
+ __func__);
+ pbi->process_busy = 0;
+ return IRQ_HANDLED;
+ }
- bit_depth_luma = vp9_param.p.bit_depth;
- bit_depth_chroma = vp9_param.p.bit_depth;
+ for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) {
+ int ii;
+ for (ii = 0; ii < 4; ii++) {
+ pbi->s1_buf->rpm[i + 3 - ii] =
+ pbi->rpm_ptr[i + 3 - ii];
+ pbi->s1_param.l.data[i + ii] =
+ pbi->rpm_ptr[i + 3 - ii];
+ }
+ }
- if (pbi->process_state != PROC_STATE_SENDAGAIN) {
- ret = vp9_bufmgr_process(pbi, &vp9_param);
- if (!pbi->m_ins_flag)
- pbi->slice_idx++;
- } else {
- union param_u *params = &vp9_param;
- if (pbi->mmu_enable) {
- ret = vp9_alloc_mmu(pbi,
- cm->new_fb_idx,
- params->p.width,
- params->p.height,
- params->p.bit_depth,
- pbi->frame_mmu_map_addr);
- if (ret >= 0)
- cm->cur_fb_idx_mmu = cm->new_fb_idx;
- else
- pr_err("can't alloc need mmu1,idx %d ret =%d\n",
- cm->new_fb_idx,
- ret);
- } else {
- ret = 0;
- }
- WRITE_VREG(HEVC_PARSER_PICTURE_SIZE,
- (params->p.height << 16) | params->p.width);
- }
- if (ret < 0) {
- pr_info("vp9_bufmgr_process=> %d, VP9_10B_DISCARD_NAL\r\n",
- ret);
- WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DISCARD_NAL);
- cm->show_frame = 0;
- pbi->process_busy = 0;
- if (pbi->mmu_enable)
- vp9_recycle_mmu_buf(pbi);
+ mpred_process(pbi);
+#ifdef FB_DECODING_TEST_SCHEDULE
+ pbi->dec_s1_result =
+ DEC_S1_RESULT_TEST_TRIGGER_DONE;
+ vdec_schedule_work(&pbi->s1_work);
+#else
+ WRITE_VREG(HEVC_ASSIST_FB_MMU_MAP_ADDR,
+ pbi->stage_mmu_map_phy_addr +
+ pbi->s1_buf->index * STAGE_MMU_MAP_SIZE);
-#ifdef MULTI_INSTANCE_SUPPORT
- if (pbi->m_ins_flag) {
- pbi->dec_result = DEC_RESULT_DONE;
- amhevc_stop();
- vdec_schedule_work(&pbi->work);
- }
+ start_s1_decoding(pbi);
#endif
- return IRQ_HANDLED;
- } else if (ret == 0) {
- struct PIC_BUFFER_CONFIG_s *cur_pic_config
- = &cm->cur_frame->buf;
- cur_pic_config->decode_idx = pbi->frame_count;
-
- if (pbi->process_state != PROC_STATE_SENDAGAIN) {
- if (!pbi->m_ins_flag) {
- pbi->frame_count++;
- decode_frame_count[pbi->index]
- = pbi->frame_count;
- }
-#ifdef MULTI_INSTANCE_SUPPORT
- if (pbi->chunk) {
- cur_pic_config->pts = pbi->chunk->pts;
- cur_pic_config->pts64 = pbi->chunk->pts64;
- }
+ start_process_time(pbi);
+ pbi->process_busy = 0;
+ return IRQ_HANDLED;
+ } else
#endif
+ for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) {
+ int ii;
+ for (ii = 0; ii < 4; ii++)
+ vp9_param.l.data[i + ii] =
+ pbi->rpm_ptr[i + 3 - ii];
}
- /*pr_info("Decode Frame Data %d\n", pbi->frame_count);*/
- config_pic_size(pbi, vp9_param.p.bit_depth);
- if ((pbi->common.frame_type != KEY_FRAME)
- && (!pbi->common.intra_only)) {
- config_mc_buffer(pbi, vp9_param.p.bit_depth);
- config_mpred_hw(pbi);
- } else {
- clear_mpred_hw(pbi);
}
-#ifdef MCRCC_ENABLE
- if (mcrcc_cache_alg_flag)
- config_mcrcc_axi_hw_new(pbi);
- else
- config_mcrcc_axi_hw(pbi);
-#endif
- config_sao_hw(pbi, &vp9_param);
-
-#ifdef VP9_LPF_LVL_UPDATE
- /*
- * Get loop filter related picture level parameters from Parser
- */
- pbi->lf->mode_ref_delta_enabled = vp9_param.p.mode_ref_delta_enabled;
- pbi->lf->sharpness_level = vp9_param.p.sharpness_level;
- for (i = 0; i < 4; i++)
- pbi->lf->ref_deltas[i] = vp9_param.p.ref_deltas[i];
- for (i = 0; i < 2; i++)
- pbi->lf->mode_deltas[i] = vp9_param.p.mode_deltas[i];
- pbi->default_filt_lvl = vp9_param.p.filter_level;
- pbi->seg_4lf->enabled = vp9_param.p.seg_enabled;
- pbi->seg_4lf->abs_delta = vp9_param.p.seg_abs_delta;
- for (i = 0; i < MAX_SEGMENTS; i++)
- pbi->seg_4lf->feature_mask[i] = (vp9_param.p.seg_lf_info[i] &
- 0x8000) ? (1 << SEG_LVL_ALT_LF) : 0;
- for (i = 0; i < MAX_SEGMENTS; i++)
- pbi->seg_4lf->feature_data[i][SEG_LVL_ALT_LF]
- = (vp9_param.p.seg_lf_info[i]
- & 0x100) ? -(vp9_param.p.seg_lf_info[i]
- & 0x3f) : (vp9_param.p.seg_lf_info[i] & 0x3f);
- /*
- * Update loop filter Thr/Lvl table for every frame
- */
- /*pr_info
- *("vp9_loop_filter (run before every frame decoding start)\n");
- */
- vp9_loop_filter_frame_init(pbi->seg_4lf,
- pbi->lfi, pbi->lf, pbi->default_filt_lvl);
-#endif
- /*pr_info("HEVC_DEC_STATUS_REG <= VP9_10B_DECODE_SLICE\n");*/
- WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE);
- } else {
- pr_info("Skip search next start code\n");
- cm->prev_fb_idx = INVALID_IDX;
- /*skip, search next start code*/
- WRITE_VREG(HEVC_DEC_STATUS_REG, VP9_10B_DECODE_SLICE);
- }
+ continue_decoding(pbi);
pbi->process_busy = 0;
- pbi->process_state = PROC_STATE_DECODESLICE;
- if (pbi->mmu_enable) {
- if (pbi->last_put_idx >= 0 && pbi->last_put_idx < pbi->used_buf_num) {
- struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs;
- int i = pbi->last_put_idx;
- /*free not used buffers.*/
- if ((frame_bufs[i].ref_count == 0) &&
- (frame_bufs[i].buf.vf_ref == 0) &&
- (frame_bufs[i].buf.index != -1)) {
- decoder_mmu_box_free_idx(pbi->mmu_box, i);
- }
- pbi->last_put_idx = -1;
- }
- }
+
#ifdef MULTI_INSTANCE_SUPPORT
if (pbi->m_ins_flag)
start_process_time(pbi);
@@ -6625,7 +7422,7 @@ static irqreturn_t vvp9_isr(int irq, void *data)
struct VP9_Common_s *const cm = &pbi->common;
uint debug_tag;
- WRITE_VREG(HEVC_ASSIST_MBOX1_CLR_REG, 1);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1);
dec_status = READ_VREG(HEVC_DEC_STATUS_REG);
adapt_prob_status = READ_VREG(VP9_ADAPT_PROB_REG);
@@ -6638,7 +7435,8 @@ static irqreturn_t vvp9_isr(int irq, void *data)
pbi->dec_status = dec_status;
pbi->process_busy = 1;
if (debug & VP9_DEBUG_BUFMGR)
- pr_info("vp9 isr dec status = 0x%x, lcu 0x%x shiftbyte 0x%x (%x %x lev %x, wr %x, rd %x)\n",
+ pr_info("vp9 isr (%d) dec status = 0x%x, lcu 0x%x shiftbyte 0x%x (%x %x lev %x, wr %x, rd %x)\n",
+ irq,
dec_status, READ_VREG(HEVC_PARSER_LCU_START),
READ_VREG(HEVC_SHIFT_BYTE_COUNT),
READ_VREG(HEVC_STREAM_START_ADDR),
@@ -6647,6 +7445,10 @@ static irqreturn_t vvp9_isr(int irq, void *data)
READ_VREG(HEVC_STREAM_WR_PTR),
READ_VREG(HEVC_STREAM_RD_PTR)
);
+#ifdef SUPPORT_FB_DECODING
+ /*if (irq != VDEC_IRQ_0)
+ return IRQ_WAKE_THREAD;*/
+#endif
debug_tag = READ_HREG(DEBUG_REG1);
if (debug_tag & 0x10000) {
@@ -6768,6 +7570,13 @@ static void vvp9_put_timer_func(unsigned long arg)
if (pbi->m_ins_flag) {
if (hw_to_vdec(pbi)->next_status
== VDEC_STATUS_DISCONNECTED) {
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->run2_busy)
+ return;
+
+ pbi->dec_s1_result = DEC_S1_RESULT_FORCE_EXIT;
+ vdec_schedule_work(&pbi->s1_work);
+#endif
pbi->dec_result = DEC_RESULT_FORCE_EXIT;
vdec_schedule_work(&pbi->work);
pr_debug(
@@ -6807,7 +7616,7 @@ static void vvp9_put_timer_func(unsigned long arg)
buf_level > 0x200)
) {
WRITE_VREG
- (HEVC_ASSIST_MBOX1_IRQ_REG,
+ (HEVC_ASSIST_MBOX0_IRQ_REG,
0x1);
}
}
@@ -6870,8 +7679,9 @@ static void vvp9_put_timer_func(unsigned long arg)
pbi->dec_result = DEC_RESULT_AGAIN;
if (pbi->process_state ==
PROC_STATE_DECODESLICE) {
- if (pbi->mmu_enable)
- vp9_recycle_mmu_buf(pbi);
+#ifdef VP9_10B_MMU
+ vp9_recycle_mmu_buf(pbi);
+#endif
pbi->process_state =
PROC_STATE_SENDAGAIN;
}
@@ -6897,7 +7707,7 @@ static void vvp9_put_timer_func(unsigned long arg)
debug &= ~VP9_DEBUG_DUMP_PIC_LIST;
}
if (debug & VP9_DEBUG_TRIG_SLICE_SEGMENT_PROC) {
- WRITE_VREG(HEVC_ASSIST_MBOX1_IRQ_REG, 0x1);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1);
debug &= ~VP9_DEBUG_TRIG_SLICE_SEGMENT_PROC;
}
/*if (debug & VP9_DEBUG_HW_RESET) {
@@ -7026,19 +7836,23 @@ static void VP9_DECODE_INIT(void)
}
#endif
-static void vvp9_prot_init(struct VP9Decoder_s *pbi)
+static void vvp9_prot_init(struct VP9Decoder_s *pbi, u32 mask)
{
unsigned int data32;
/* VP9_DECODE_INIT(); */
- vp9_config_work_space_hw(pbi);
- init_pic_list_hw(pbi);
+ vp9_config_work_space_hw(pbi, mask);
+ if (mask & HW_MASK_BACK)
+ init_pic_list_hw(pbi);
- vp9_init_decoder_hw(pbi);
+ vp9_init_decoder_hw(pbi, mask);
#ifdef VP9_LPF_LVL_UPDATE
- vp9_loop_filter_init(pbi);
+ if (mask & HW_MASK_BACK)
+ vp9_loop_filter_init(pbi);
#endif
+ if ((mask & HW_MASK_FRONT) == 0)
+ return;
#if 1
if (debug & VP9_DEBUG_BUFMGR_MORE)
pr_info("%s\n", __func__);
@@ -7047,6 +7861,16 @@ static void vvp9_prot_init(struct VP9Decoder_s *pbi)
(1 << 0)/*stream_fetch_enable*/
;
WRITE_VREG(HEVC_STREAM_CONTROL, data32);
+
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A) {
+ if (debug & VP9_DEBUG_BUFMGR)
+ pr_info("[test.c] Config STREAM_FIFO_CTL\n");
+ data32 = READ_VREG(HEVC_STREAM_FIFO_CTL);
+ data32 = data32 |
+ (1 << 29) // stream_fifo_hole
+ ;
+ WRITE_VREG(HEVC_STREAM_FIFO_CTL, data32);
+ }
#if 0
data32 = READ_VREG(HEVC_SHIFT_STARTCODE);
if (data32 != 0x00000100) {
@@ -7082,10 +7906,10 @@ static void vvp9_prot_init(struct VP9Decoder_s *pbi)
/* WRITE_VREG(HEVC_MPSR, 1); */
/* clear mailbox interrupt */
- WRITE_VREG(HEVC_ASSIST_MBOX1_CLR_REG, 1);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_CLR_REG, 1);
/* enable mailbox interrupt */
- WRITE_VREG(HEVC_ASSIST_MBOX1_MASK, 1);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 1);
/* disable PSCALE for hardware sharing */
WRITE_VREG(HEVC_PSCALE_CTRL, 0);
@@ -7095,7 +7919,45 @@ static void vvp9_prot_init(struct VP9Decoder_s *pbi)
WRITE_VREG(NAL_SEARCH_CTL, 0x8);
WRITE_VREG(DECODE_STOP_POS, udebug_flag);
+#ifdef SUPPORT_FB_DECODING
+#ifndef FB_DECODING_TEST_SCHEDULE
+ if (pbi->used_stage_buf_num > 0) {
+ if (mask & HW_MASK_FRONT) {
+ data32 = READ_VREG(
+ HEVC_ASSIST_HED_FB_W_CTL);
+ data32 = data32 |
+ (1 << 0) /*hed_fb_wr_en*/
+ ;
+ WRITE_VREG(HEVC_ASSIST_HED_FB_W_CTL,
+ data32);
+ }
+ if (mask & HW_MASK_BACK) {
+ data32 = READ_VREG(
+ HEVC_ASSIST_HED_FB_R_CTL);
+ while (data32 & (1 << 7)) {
+ /*wait finish*/
+ data32 = READ_VREG(
+ HEVC_ASSIST_HED_FB_R_CTL);
+ }
+ data32 &= (~(0x1 << 0));
+ /*hed_fb_rd_addr_auto_rd*/
+ data32 &= (~(0x1 << 1));
+ /*rd_id = 0, hed_rd_map_auto_halt_num,
+ after wr 2 ready, then start reading*/
+ data32 |= (0x2 << 16);
+ WRITE_VREG(HEVC_ASSIST_HED_FB_R_CTL,
+ data32);
+
+ data32 |= (0x1 << 11); /*hed_rd_map_auto_halt_en*/
+ data32 |= (0x1 << 1); /*hed_fb_rd_addr_auto_rd*/
+ data32 |= (0x1 << 0); /*hed_fb_rd_en*/
+ WRITE_VREG(HEVC_ASSIST_HED_FB_R_CTL,
+ data32);
+ }
+ }
+#endif
+#endif
}
static int vvp9_local_init(struct VP9Decoder_s *pbi)
@@ -7190,7 +8052,10 @@ static s32 vvp9_init(struct VP9Decoder_s *pbi)
pr_debug ("laod\n");
} else
#endif
- size = get_firmware_data(VIDEO_DEC_VP9_MMU, fw->data);
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A)
+ size = get_firmware_data(VIDEO_DEC_VP9_G12A, fw->data);
+ else
+ size = get_firmware_data(VIDEO_DEC_VP9_MMU, fw->data);
if (size < 0) {
pr_err("get firmware fail.\n");
vfree(fw);
@@ -7211,7 +8076,10 @@ static s32 vvp9_init(struct VP9Decoder_s *pbi)
pbi->stat |= STAT_ISR_REG;*/
INIT_WORK(&pbi->work, vp9_work);
-
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num > 0)
+ INIT_WORK(&pbi->s1_work, vp9_s1_work);
+#endif
pbi->fw = fw;
return 0;
@@ -7233,9 +8101,9 @@ static s32 vvp9_init(struct VP9Decoder_s *pbi)
pbi->stat |= STAT_MC_LOAD;
/* enable AMRISC side protocol */
- vvp9_prot_init(pbi);
+ vvp9_prot_init(pbi, HW_MASK_FRONT | HW_MASK_BACK);
- if (vdec_request_threaded_irq(VDEC_IRQ_1,
+ if (vdec_request_threaded_irq(VDEC_IRQ_0,
vvp9_isr,
vvp9_isr_thread_fn,
IRQF_ONESHOT,/*run thread on this irq disabled*/
@@ -7314,6 +8182,10 @@ static int vmvp9_stop(struct VP9Decoder_s *pbi)
vp9_local_uninit(pbi);
reset_process_time(pbi);
cancel_work_sync(&pbi->work);
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num > 0)
+ cancel_work_sync(&pbi->s1_work);
+#endif
uninit_mmu_buffers(pbi);
return 0;
@@ -7333,8 +8205,8 @@ static int vvp9_stop(struct VP9Decoder_s *pbi)
#ifdef MULTI_INSTANCE_SUPPORT
if (!pbi->m_ins_flag)
#endif
- WRITE_VREG(HEVC_ASSIST_MBOX1_MASK, 0);
- vdec_free_irq(VDEC_IRQ_1, (void *)pbi);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0);
+ vdec_free_irq(VDEC_IRQ_0, (void *)pbi);
pbi->stat &= ~STAT_ISR_REG;
}
@@ -7355,9 +8227,13 @@ static int vvp9_stop(struct VP9Decoder_s *pbi)
vp9_local_uninit(pbi);
#ifdef MULTI_INSTANCE_SUPPORT
- if (pbi->m_ins_flag)
+ if (pbi->m_ins_flag) {
cancel_work_sync(&pbi->work);
- else
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num > 0)
+ cancel_work_sync(&pbi->s1_work);
+#endif
+ } else
amhevc_disable();
#else
amhevc_disable();
@@ -7374,26 +8250,21 @@ static int amvdec_vp9_mmu_init(struct VP9Decoder_s *pbi)
int tvp_flag = vdec_secure(hw_to_vdec(pbi)) ?
CODEC_MM_FLAGS_TVP : 0;
+#ifdef VP9_10B_MMU
int buf_size = 48;
- if ((pbi->max_pic_w * pbi->max_pic_h > 1280*736) &&
- (pbi->max_pic_w * pbi->max_pic_h <= 1920*1088)) {
+ if ((pbi->max_pic_w * pbi->max_pic_h) > 0 && (pbi->max_pic_w * pbi->max_pic_h) <= 1920*1088) {
buf_size = 12;
- } else if ((pbi->max_pic_w * pbi->max_pic_h > 0) &&
- (pbi->max_pic_w * pbi->max_pic_h <= 1280*736)) {
- buf_size = 4;
- }
- if (pbi->mmu_enable) {
- pbi->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME,
- pbi->index, FRAME_BUFFERS,
- buf_size * SZ_1M,
- tvp_flag
- );
- if (!pbi->mmu_box) {
- pr_err("vp9 alloc mmu box failed!!\n");
- return -1;
- }
}
-
+ pbi->mmu_box = decoder_mmu_box_alloc_box(DRIVER_NAME,
+ pbi->index, FRAME_BUFFERS + STAGE_MAX_BUFFERS,
+ buf_size * SZ_1M,
+ tvp_flag
+ );
+ if (!pbi->mmu_box) {
+ pr_err("vp9 alloc mmu box failed!!\n");
+ return -1;
+ }
+#endif
pbi->bmmu_box = decoder_bmmu_box_alloc_box(
DRIVER_NAME,
pbi->index,
@@ -7418,6 +8289,9 @@ static int amvdec_vp9_probe(struct platform_device *pdev)
int i;
#endif
pr_debug("%s\n", __func__);
+
+ WRITE_VREG(DOS_SCRATCH31,4);
+
mutex_lock(&vvp9_mutex);
memcpy(&BUF[0], &pbi->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
@@ -7425,6 +8299,8 @@ static int amvdec_vp9_probe(struct platform_device *pdev)
memcpy(&pbi->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
pbi->init_flag = 0;
+ pbi->max_pic_w = vp9_max_pic_w;
+ pbi->max_pic_h = vp9_max_pic_h;
#ifdef MULTI_INSTANCE_SUPPORT
pbi->eos = 0;
@@ -7443,8 +8319,6 @@ static int amvdec_vp9_probe(struct platform_device *pdev)
pbi->platform_dev = pdev;
platform_set_drvdata(pdev, pdata);
#endif
- pbi->double_write_mode = double_write_mode;
- pbi->mmu_enable = !(pbi->double_write_mode == 0x10);
if (amvdec_vp9_mmu_init(pbi) < 0) {
mutex_unlock(&vvp9_mutex);
pr_err("vp9 alloc bmmu box failed!!\n");
@@ -7463,9 +8337,9 @@ static int amvdec_vp9_probe(struct platform_device *pdev)
#ifdef MULTI_INSTANCE_SUPPORT
pbi->buf_start = pdata->mem_start;
#else
- if (!pbi->mmu_enable)
- pbi->mc_buf_spec.buf_end = pdata->mem_start + pbi->buf_size;
-
+#ifndef VP9_10B_MMU
+ pbi->mc_buf_spec.buf_end = pdata->mem_start + pbi->buf_size;
+#endif
for (i = 0; i < WORK_BUF_SPEC_NUM; i++)
amvvp9_workbuff_spec[i].start_adr = pdata->mem_start;
#endif
@@ -7686,6 +8560,20 @@ static void vp9_work(struct work_struct *work)
}
return;
} else if (pbi->dec_result == DEC_RESULT_DONE) {
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num > 0) {
+#ifndef FB_DECODING_TEST_SCHEDULE
+ if (!is_s2_decoding_finished(pbi)) {
+ vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL,
+ "s2 decoding not done, check again later\n");
+ vdec_schedule_work(&pbi->work);
+ }
+#endif
+ inc_s2_pos(pbi);
+ if (mcrcc_cache_alg_flag)
+ dump_hit_rate(pbi);
+ }
+#endif
/* if (!pbi->ctx_valid)
pbi->ctx_valid = 1; */
pbi->slice_idx++;
@@ -7693,9 +8581,10 @@ static void vp9_work(struct work_struct *work)
pbi->process_state = PROC_STATE_INIT;
decode_frame_count[pbi->index] = pbi->frame_count;
- if (pbi->mmu_enable)
- pbi->used_4k_num =
- (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16);
+#ifdef VP9_10B_MMU
+ pbi->used_4k_num =
+ (READ_VREG(HEVC_SAO_MMU_STATUS) >> 16);
+#endif
vp9_print(pbi, PRINT_FLAG_VDEC_STATUS,
"%s (===> %d) dec_result %d %x %x %x shiftbytes 0x%x decbytes 0x%x\n",
__func__,
@@ -7739,70 +8628,142 @@ static void vp9_work(struct work_struct *work)
#ifdef MULTI_INSTANCE_SUPPORT
if (!pbi->m_ins_flag)
#endif
- WRITE_VREG(HEVC_ASSIST_MBOX1_MASK, 0);
- vdec_free_irq(VDEC_IRQ_1, (void *)pbi);
+ WRITE_VREG(HEVC_ASSIST_MBOX0_MASK, 0);
+ vdec_free_irq(VDEC_IRQ_0, (void *)pbi);
pbi->stat &= ~STAT_ISR_REG;
}
}
- if (pbi->stat & STAT_VDEC_RUN) {
- amhevc_stop();
- pbi->stat &= ~STAT_VDEC_RUN;
- }
-
if (pbi->stat & STAT_TIMER_ARM) {
del_timer_sync(&pbi->timer);
pbi->stat &= ~STAT_TIMER_ARM;
}
/* mark itself has all HW resource released and input released */
- vdec_set_status(hw_to_vdec(pbi), VDEC_STATUS_CONNECTED);
-
- if (pbi->vdec_cb)
- pbi->vdec_cb(hw_to_vdec(pbi), pbi->vdec_cb_arg);
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num > 0)
+ vdec_core_finish_run(hw_to_vdec(pbi), CORE_MASK_HEVC_BACK);
+ else
+ vdec_core_finish_run(hw_to_vdec(pbi), CORE_MASK_VDEC_1
+ | CORE_MASK_HEVC
+ | CORE_MASK_HEVC_FRONT
+ | CORE_MASK_HEVC_BACK
+ );
+#else
+ vdec_core_finish_run(hw_to_vdec(pbi), CORE_MASK_VDEC_1
+ | CORE_MASK_HEVC);
+#endif
+ trigger_schedule(pbi);
}
static int vp9_hw_ctx_restore(struct VP9Decoder_s *pbi)
{
/* new to do ... */
- vvp9_prot_init(pbi);
+#if (!defined SUPPORT_FB_DECODING)
+ vvp9_prot_init(pbi, HW_MASK_FRONT | HW_MASK_BACK);
+#elif (defined FB_DECODING_TEST_SCHEDULE)
+ vvp9_prot_init(pbi, HW_MASK_FRONT | HW_MASK_BACK);
+#else
+ if (pbi->used_stage_buf_num > 0)
+ vvp9_prot_init(pbi, HW_MASK_FRONT);
+ else
+ vvp9_prot_init(pbi, HW_MASK_FRONT | HW_MASK_BACK);
+#endif
return 0;
}
-static bool run_ready(struct vdec_s *vdec)
+static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
{
struct VP9Decoder_s *pbi =
(struct VP9Decoder_s *)vdec->private;
- bool ret = 0;
- vp9_print(pbi,
- PRINT_FLAG_VDEC_DETAIL, "%s\r\n", __func__);
+ unsigned long ret = 0;
+
if (pbi->eos)
return ret;
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num > 0) {
+ if (mask & CORE_MASK_HEVC_FRONT) {
+ if (get_free_stage_buf_num(pbi) > 0
+ && mv_buf_available(pbi))
+ ret |= CORE_MASK_HEVC_FRONT;
+ }
+ if (mask & CORE_MASK_HEVC_BACK) {
+ if (s2_buf_available(pbi) &&
+ (get_free_buf_count(pbi) >=
+ run_ready_min_buf_num)) {
+ ret |= CORE_MASK_HEVC_BACK;
+ pbi->back_not_run_ready = 0;
+ } else
+ pbi->back_not_run_ready = 1;
+#if 0
+ if (get_free_buf_count(pbi) <
+ run_ready_min_buf_num)
+ dump_pic_list(pbi);
+#endif
+ }
+ } else if (get_free_buf_count(pbi) >=
+ run_ready_min_buf_num)
+ ret = CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+ | CORE_MASK_HEVC_FRONT
+ | CORE_MASK_HEVC_BACK;
+ if (ret & CORE_MASK_HEVC_FRONT)
+ not_run_ready[pbi->index] = 0;
+ else
+ not_run_ready[pbi->index]++;
+
+ if (ret & CORE_MASK_HEVC_BACK)
+ not_run2_ready[pbi->index] = 0;
+ else
+ not_run2_ready[pbi->index]++;
+
+ vp9_print(pbi,
+ PRINT_FLAG_VDEC_DETAIL, "%s mask %lx=>%lx (%d %d %d %d)\r\n",
+ __func__, mask, ret,
+ get_free_stage_buf_num(pbi),
+ mv_buf_available(pbi),
+ s2_buf_available(pbi),
+ get_free_buf_count(pbi)
+ );
+
+ return ret;
+
+#else
if (get_free_buf_count(pbi) >=
run_ready_min_buf_num)
- ret = 1;
+ ret = CORE_MASK_VDEC_1 | CORE_MASK_HEVC;
if (ret)
not_run_ready[pbi->index] = 0;
else
not_run_ready[pbi->index]++;
+
+ vp9_print(pbi,
+ PRINT_FLAG_VDEC_DETAIL, "%s mask %lx=>%lx\r\n",
+ __func__, mask, ret);
return ret;
+#endif
}
-static void run(struct vdec_s *vdec,
- void (*callback)(struct vdec_s *, void *), void *arg)
+static void run_front(struct vdec_s *vdec)
{
struct VP9Decoder_s *pbi =
(struct VP9Decoder_s *)vdec->private;
- int r;
+ int ret, size;
run_count[pbi->index]++;
- pbi->vdec_cb_arg = arg;
- pbi->vdec_cb = callback;
/* pbi->chunk = vdec_prepare_input(vdec); */
+#if (!defined SUPPORT_FB_DECODING)
+ hevc_reset_core(vdec);
+#elif (defined FB_DECODING_TEST_SCHEDULE)
hevc_reset_core(vdec);
+#else
+ if (pbi->used_stage_buf_num > 0)
+ fb_reset_core(vdec, HW_MASK_FRONT);
+ else
+ hevc_reset_core(vdec);
+#endif
- r = vdec_prepare_input(vdec, &pbi->chunk);
- if (r < 0) {
+ size = vdec_prepare_input(vdec, &pbi->chunk);
+ if (size < 0) {
input_empty[pbi->index]++;
pbi->dec_result = DEC_RESULT_AGAIN;
@@ -7822,12 +8783,12 @@ static void run(struct vdec_s *vdec,
vp9_print(pbi, 0,
"%s (%d): size 0x%x (0x%x 0x%x) sum 0x%x (%x %x %x %x %x) bytes 0x%x",
__func__,
- pbi->frame_count, r,
+ pbi->frame_count, size,
pbi->chunk ? pbi->chunk->size : 0,
pbi->chunk ? pbi->chunk->offset : 0,
(vdec_frame_based(vdec) &&
(debug & PRINT_FLAG_VDEC_STATUS)) ?
- get_data_check_sum(pbi, r) : 0,
+ get_data_check_sum(pbi, size) : 0,
READ_VREG(HEVC_STREAM_START_ADDR),
READ_VREG(HEVC_STREAM_END_ADDR),
READ_VREG(HEVC_STREAM_LEVEL),
@@ -7845,20 +8806,20 @@ static void run(struct vdec_s *vdec,
}
vp9_print_cont(pbi, 0, "\r\n");
}
- if (vdec->mc_loaded) {
- /*firmware have load before,
- and not changes to another.
- ignore reload.
- */
- } else if ( amhevc_loadmc_ex(VFORMAT_VP9, NULL, pbi->fw->data) < 0) {
- vdec->mc_loaded = 0;
+
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A)
+ ret = amhevc_loadmc_ex(VFORMAT_VP9,
+ "vp9_mc_g12a", pbi->fw->data);
+ else
+ ret = amhevc_loadmc_ex(VFORMAT_VP9, NULL, pbi->fw->data);
+
+ if (ret < 0) {
amhevc_disable();
vp9_print(pbi, 0,
"%s: Error amvdec_loadmc fail\n", __func__);
return;
- } else {
- vdec->mc_loaded = 1;
}
+
if (vp9_hw_ctx_restore(pbi) < 0) {
vdec_schedule_work(&pbi->work);
return;
@@ -7873,10 +8834,10 @@ static void run(struct vdec_s *vdec,
dump_data(pbi, pbi->chunk->size);
WRITE_VREG(HEVC_SHIFT_BYTE_COUNT, 0);
- r = pbi->chunk->size +
+ size = pbi->chunk->size +
(pbi->chunk->offset & (VDEC_FIFO_ALIGN - 1));
}
- WRITE_VREG(HEVC_DECODE_SIZE, r);
+ WRITE_VREG(HEVC_DECODE_SIZE, size);
WRITE_VREG(HEVC_DECODE_COUNT, pbi->slice_idx);
pbi->init_flag = 1;
@@ -7895,6 +8856,167 @@ static void run(struct vdec_s *vdec,
pbi->stat |= STAT_VDEC_RUN;
}
+#ifdef SUPPORT_FB_DECODING
+static void mpred_process(struct VP9Decoder_s *pbi)
+{
+ union param_u *params = &pbi->s1_param;
+ unsigned char use_prev_frame_mvs =
+ !params->p.error_resilient_mode &&
+ params->p.width == pbi->s1_width &&
+ params->p.height == pbi->s1_height &&
+ !pbi->s1_intra_only &&
+ pbi->s1_last_show_frame &&
+ (pbi->s1_frame_type != KEY_FRAME);
+ pbi->s1_width = params->p.width;
+ pbi->s1_height = params->p.height;
+ pbi->s1_frame_type = params->p.frame_type;
+ pbi->s1_intra_only =
+ (params->p.show_frame ||
+ params->p.show_existing_frame)
+ ? 0 : params->p.intra_only;
+ if ((pbi->s1_frame_type != KEY_FRAME)
+ && (!pbi->s1_intra_only)) {
+ unsigned int data32;
+ int mpred_mv_rd_end_addr;
+
+ mpred_mv_rd_end_addr =
+ pbi->s1_mpred_mv_wr_start_addr_pre
+ + (pbi->lcu_total * MV_MEM_UNIT);
+
+ WRITE_VREG(HEVC_MPRED_CTRL3, 0x24122412);
+ WRITE_VREG(HEVC_MPRED_ABV_START_ADDR,
+ pbi->work_space_buf->
+ mpred_above.buf_start);
+
+ data32 = READ_VREG(HEVC_MPRED_CTRL4);
+
+ data32 &= (~(1 << 6));
+ data32 |= (use_prev_frame_mvs << 6);
+ WRITE_VREG(HEVC_MPRED_CTRL4, data32);
+
+ WRITE_VREG(HEVC_MPRED_MV_WR_START_ADDR,
+ pbi->s1_mpred_mv_wr_start_addr);
+ WRITE_VREG(HEVC_MPRED_MV_WPTR,
+ pbi->s1_mpred_mv_wr_start_addr);
+
+ WRITE_VREG(HEVC_MPRED_MV_RD_START_ADDR,
+ pbi->s1_mpred_mv_wr_start_addr_pre);
+ WRITE_VREG(HEVC_MPRED_MV_RPTR,
+ pbi->s1_mpred_mv_wr_start_addr_pre);
+
+ WRITE_VREG(HEVC_MPRED_MV_RD_END_ADDR,
+ mpred_mv_rd_end_addr);
+
+ } else
+ clear_mpred_hw(pbi);
+
+ if (!params->p.show_existing_frame) {
+ pbi->s1_mpred_mv_wr_start_addr_pre =
+ pbi->s1_mpred_mv_wr_start_addr;
+ pbi->s1_last_show_frame =
+ params->p.show_frame;
+ if (pbi->s1_mv_buf_index_pre_pre != MV_BUFFER_NUM)
+ put_mv_buf(pbi, &pbi->s1_mv_buf_index_pre_pre);
+ pbi->s1_mv_buf_index_pre_pre =
+ pbi->s1_mv_buf_index_pre;
+ pbi->s1_mv_buf_index_pre = pbi->s1_mv_buf_index;
+ } else
+ put_mv_buf(pbi, &pbi->s1_mv_buf_index);
+}
+
+static void vp9_s1_work(struct work_struct *s1_work)
+{
+ struct VP9Decoder_s *pbi = container_of(s1_work,
+ struct VP9Decoder_s, s1_work);
+ vp9_print(pbi, PRINT_FLAG_VDEC_DETAIL,
+ "%s dec_s1_result %d\n",
+ __func__,
+ pbi->dec_s1_result);
+
+#ifdef FB_DECODING_TEST_SCHEDULE
+ if (pbi->dec_s1_result ==
+ DEC_S1_RESULT_TEST_TRIGGER_DONE) {
+ pbi->s1_test_cmd = TEST_SET_PIC_DONE;
+ WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG, 0x1);
+ }
+#endif
+ if (pbi->dec_s1_result == DEC_S1_RESULT_DONE ||
+ pbi->dec_s1_result == DEC_S1_RESULT_FORCE_EXIT) {
+
+ vdec_core_finish_run(hw_to_vdec(pbi),
+ CORE_MASK_HEVC_FRONT);
+
+ trigger_schedule(pbi);
+ /*pbi->dec_s1_result = DEC_S1_RESULT_NONE;*/
+ }
+
+}
+
+static void run_back(struct vdec_s *vdec)
+{
+ struct VP9Decoder_s *pbi =
+ (struct VP9Decoder_s *)vdec->private;
+ int i;
+ run2_count[pbi->index]++;
+ if (debug & PRINT_FLAG_VDEC_STATUS) {
+ vp9_print(pbi, 0,
+ "%s", __func__);
+ }
+ pbi->run2_busy = 1;
+#ifndef FB_DECODING_TEST_SCHEDULE
+ fb_reset_core(vdec, HW_MASK_BACK);
+
+ vvp9_prot_init(pbi, HW_MASK_BACK);
+#endif
+ vp9_recycle_mmu_buf_tail(pbi);
+
+ if (pbi->frame_count > 0)
+ vp9_bufmgr_postproc(pbi);
+
+ if (get_s2_buf(pbi) >= 0) {
+ for (i = 0; i < (RPM_END - RPM_BEGIN); i += 4) {
+ int ii;
+ for (ii = 0; ii < 4; ii++)
+ vp9_param.l.data[i + ii] =
+ pbi->s2_buf->rpm[i + 3 - ii];
+ }
+#ifndef FB_DECODING_TEST_SCHEDULE
+ WRITE_VREG(HEVC_ASSIST_FBD_MMU_MAP_ADDR,
+ pbi->stage_mmu_map_phy_addr +
+ pbi->s2_buf->index * STAGE_MMU_MAP_SIZE);
+#endif
+ continue_decoding(pbi);
+ }
+ pbi->run2_busy = 0;
+}
+#endif
+
+static void run(struct vdec_s *vdec, unsigned long mask,
+ void (*callback)(struct vdec_s *, void *), void *arg)
+{
+ struct VP9Decoder_s *pbi =
+ (struct VP9Decoder_s *)vdec->private;
+
+ vp9_print(pbi,
+ PRINT_FLAG_VDEC_DETAIL, "%s mask %lx\r\n",
+ __func__, mask);
+
+ run_count[pbi->index]++;
+ pbi->vdec_cb_arg = arg;
+ pbi->vdec_cb = callback;
+#ifdef SUPPORT_FB_DECODING
+ if ((mask & CORE_MASK_HEVC) ||
+ (mask & CORE_MASK_HEVC_FRONT))
+ run_front(vdec);
+
+ if ((pbi->used_stage_buf_num > 0)
+ && (mask & CORE_MASK_HEVC_BACK))
+ run_back(vdec);
+#else
+ run_front(vdec);
+#endif
+}
+
static void reset(struct vdec_s *vdec)
{
@@ -7906,14 +9028,14 @@ static void reset(struct vdec_s *vdec)
}
-static irqreturn_t vp9_irq_cb(struct vdec_s *vdec)
+static irqreturn_t vp9_irq_cb(struct vdec_s *vdec, int irq)
{
struct VP9Decoder_s *pbi =
(struct VP9Decoder_s *)vdec->private;
return vvp9_isr(0, pbi);
}
-static irqreturn_t vp9_threaded_irq_cb(struct vdec_s *vdec)
+static irqreturn_t vp9_threaded_irq_cb(struct vdec_s *vdec, int irq)
{
struct VP9Decoder_s *pbi =
(struct VP9Decoder_s *)vdec->private;
@@ -8064,6 +9186,9 @@ static int ammvdec_vp9_probe(struct platform_device *pdev)
struct BUF_s BUF[MAX_BUF_NUM];
struct VP9Decoder_s *pbi = NULL;
pr_debug("%s\n", __func__);
+
+ //WRITE_VREG(DOS_SCRATCH31,4);
+
if (pdata == NULL) {
pr_info("\nammvdec_vp9 memory resource undefined.\n");
return -EFAULT;
@@ -8090,7 +9215,7 @@ static int ammvdec_vp9_probe(struct platform_device *pdev)
memcpy(&BUF[0], &pbi->m_BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
- memset(pbi, 0, sizeof(struct VP9Decoder_s));
+ memset(pbi, 0, sizeof(VP9Decoder));
memcpy(&pbi->m_BUF[0], &BUF[0], sizeof(struct BUF_s) * MAX_BUF_NUM);
pbi->index = pdev->id;
@@ -8110,7 +9235,6 @@ static int ammvdec_vp9_probe(struct platform_device *pdev)
pbi->platform_dev = pdev;
pbi->video_signal_type = 0;
- pbi->m_ins_flag = 1;
if (get_cpu_type() < MESON_CPU_MAJOR_ID_TXLX)
pbi->stat |= VP9_TRIGGER_FRAME_ENABLE;
#if 1
@@ -8181,7 +9305,6 @@ static int ammvdec_vp9_probe(struct platform_device *pdev)
pbi->vvp9_amstream_dec_info.rate = 30;*/
pbi->double_write_mode = double_write_mode;
}
- pbi->mmu_enable = !(pbi->double_write_mode == 0x10);
video_signal_type = pbi->video_signal_type;
#if 0
pbi->buf_start = pdata->mem_start;
@@ -8207,6 +9330,7 @@ static int ammvdec_vp9_probe(struct platform_device *pdev)
pbi->buf_start = pbi->cma_alloc_addr;
pbi->buf_size = work_buf_size;
#endif
+ pbi->m_ins_flag = 1;
pbi->init_flag = 0;
pbi->fatal_error = 0;
@@ -8245,6 +9369,18 @@ static int ammvdec_vp9_probe(struct platform_device *pdev)
vdec_set_prepare_level(pdata, start_decode_buf_level);
hevc_source_changed(VFORMAT_VP9,
4096, 2048, 60);
+#ifdef SUPPORT_FB_DECODING
+ if (pbi->used_stage_buf_num > 0)
+ vdec_core_request(pdata,
+ CORE_MASK_HEVC_FRONT | CORE_MASK_HEVC_BACK);
+ else
+ vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+ | CORE_MASK_HEVC_FRONT | CORE_MASK_HEVC_BACK
+ | CORE_MASK_COMBINE);
+#else
+ vdec_core_request(pdata, CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+ | CORE_MASK_COMBINE);
+#endif
return 0;
}
@@ -8257,6 +9393,13 @@ static int ammvdec_vp9_remove(struct platform_device *pdev)
vmvp9_stop(pbi);
+#ifdef SUPPORT_FB_DECODING
+ vdec_core_release(hw_to_vdec(pbi), CORE_MASK_VDEC_1 | CORE_MASK_HEVC
+ | CORE_MASK_HEVC_FRONT | CORE_MASK_HEVC_BACK
+ );
+#else
+ vdec_core_release(hw_to_vdec(pbi), CORE_MASK_VDEC_1 | CORE_MASK_HEVC);
+#endif
vdec_set_status(hw_to_vdec(pbi), VDEC_STATUS_DISCONNECTED);
@@ -8316,12 +9459,16 @@ static struct mconfig vp9_configs[] = {
MC_PU32("on_no_keyframe_skiped", &on_no_keyframe_skiped),
MC_PU32("start_decode_buf_level", &start_decode_buf_level),
MC_PU32("decode_timeout_val", &decode_timeout_val),
+ MC_PU32("vp9_max_pic_w", &vp9_max_pic_w),
+ MC_PU32("vp9_max_pic_h", &vp9_max_pic_h),
};
static struct mconfig_node vp9_node;
static int __init amvdec_vp9_driver_init_module(void)
{
+#ifdef VP9_10B_MMU
+
struct BuffInfo_s *p_buf_info;
#ifdef SUPPORT_4K2K
if (vdec_is_support_4k())
@@ -8336,6 +9483,7 @@ static int __init amvdec_vp9_driver_init_module(void)
(p_buf_info->end_adr - p_buf_info->start_adr
+ 0xffff) & (~0xffff);
+#endif
pr_debug("amvdec_vp9 module init\n");
error_handle_policy = 0;
@@ -8503,6 +9651,12 @@ module_param(decode_timeout_val, uint, 0664);
MODULE_PARM_DESC(decode_timeout_val,
"\n vp9 decode_timeout_val\n");
+module_param(vp9_max_pic_w, uint, 0664);
+MODULE_PARM_DESC(vp9_max_pic_w, "\n vp9_max_pic_w\n");
+
+module_param(vp9_max_pic_h, uint, 0664);
+MODULE_PARM_DESC(vp9_max_pic_h, "\n vp9_max_pic_h\n");
+
module_param_array(decode_frame_count, uint,
&max_decode_instance_num, 0664);
@@ -8522,6 +9676,17 @@ module_param_array(not_run_ready, uint,
&max_decode_instance_num, 0664);
#endif
+#ifdef SUPPORT_FB_DECODING
+module_param_array(not_run2_ready, uint,
+ &max_decode_instance_num, 0664);
+
+module_param_array(run2_count, uint,
+ &max_decode_instance_num, 0664);
+
+module_param(stage_buf_num, uint, 0664);
+MODULE_PARM_DESC(stage_buf_num, "\n amvdec_h265 stage_buf_num\n");
+#endif
+
module_param(udebug_flag, uint, 0664);
MODULE_PARM_DESC(udebug_flag, "\n amvdec_h265 udebug_flag\n");
@@ -8539,4 +9704,4 @@ module_exit(amvdec_vp9_driver_remove_module);
MODULE_DESCRIPTION("AMLOGIC vp9 Video Decoder Driver");
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Tim Yao <tim.yao@amlogic.com>");
+
diff --git a/drivers/frame_provider/decoder/vp9/vvp9.h b/drivers/frame_provider/decoder/vp9/vvp9.h
index 1db9d09..3f4959c 100644
--- a/drivers/frame_provider/decoder/vp9/vvp9.h
+++ b/drivers/frame_provider/decoder/vp9/vvp9.h
@@ -17,7 +17,7 @@
#ifndef VVP9_H
#define VVP9_H
-
+#define VP9_10B_MMU
void adapt_coef_probs(int pic_count, int prev_kf, int cur_kf, int pre_fc,
unsigned int *prev_prob, unsigned int *cur_prob, unsigned int *count);
#endif
diff --git a/drivers/stream_input/amports/amstream.c b/drivers/stream_input/amports/amstream.c
index da385ab..b7db51f 100644
--- a/drivers/stream_input/amports/amstream.c
+++ b/drivers/stream_input/amports/amstream.c
@@ -78,6 +78,9 @@
#include <linux/amlogic/media/codec_mm/codec_mm.h>
#include <linux/amlogic/media/codec_mm/configs.h>
#include "../../frame_provider/decoder/utils/firmware.h"
+#include "../../common/chips/chips.h"
+
+#define G12A_BRINGUP_DEBUG
#define CONFIG_AM_VDEC_REAL //DEBUG_TMP
@@ -605,6 +608,9 @@ static int video_port_init(struct port_priv_s *priv,
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX
&& port->vformat == VFORMAT_H264) {
amports_switch_gate("clk_hevc_mux", 1);
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A)
+ amports_switch_gate("clk_hevcb_mux", 1);
+
vdec_poweron(VDEC_HEVC);
}
} else {
@@ -869,6 +875,15 @@ static int amstream_port_init(struct port_priv_s *priv)
mutex_lock(&amstream_mutex);
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX) {
+ r = check_efuse_chip(port->vformat);
+ if (r) {
+ pr_info("No support video format %d.\n", port->vformat);
+ mutex_unlock(&amstream_mutex);
+ return 0;
+ }
+ }
+
/* try to reload the fw.*/
r = firmware_reload(FW_LOAD_TRY);
if (r)
@@ -897,6 +912,7 @@ static int amstream_port_init(struct port_priv_s *priv)
pvbuf->for_4k = 0;
if (has_hevc_vdec()) {
if (port->vformat == VFORMAT_HEVC ||
+ port->vformat == VFORMAT_AVS2 ||
port->vformat == VFORMAT_VP9)
pvbuf = &bufs[BUF_TYPE_HEVC];
}
@@ -923,6 +939,7 @@ static int amstream_port_init(struct port_priv_s *priv)
(port->flag & PORT_FLAG_SID) ? port->sid : 0xffff,
(port->pcr_inited == 1) ? port->pcrid : 0xffff,
(port->vformat == VFORMAT_HEVC) ||
+ (port->vformat == VFORMAT_AVS2) ||
(port->vformat == VFORMAT_VP9),
vdec);
} else {
@@ -1002,6 +1019,7 @@ static int amstream_port_release(struct port_priv_s *priv)
if (has_hevc_vdec()) {
if (port->vformat == VFORMAT_HEVC
+ || port->vformat == VFORMAT_AVS2
|| port->vformat == VFORMAT_VP9)
pvbuf = &bufs[BUF_TYPE_HEVC];
}
@@ -1158,6 +1176,7 @@ static ssize_t amstream_mpts_write(struct file *file, const char *buf,
if (has_hevc_vdec()) {
pvbuf = (port->vformat == VFORMAT_HEVC ||
+ port->vformat == VFORMAT_AVS2 ||
port->vformat == VFORMAT_VP9) ?
&bufs[BUF_TYPE_HEVC] : &bufs[BUF_TYPE_VIDEO];
} else
@@ -1251,8 +1270,7 @@ static ssize_t amstream_sub_read(struct file *file, char __user *buf,
stbuf_sub_rp_set(sub_rp + data_size - res);
return data_size - res;
- }
- {
+ } else {
if (first_num > 0) {
res = copy_to_user((void *)buf,
(void *)(codec_mm_phys_to_virt(sub_rp)),
@@ -1534,7 +1552,15 @@ static int amstream_open(struct inode *inode, struct file *file)
struct stream_port_s *s;
struct stream_port_s *port = &ports[iminor(inode)];
struct port_priv_s *priv;
-
+#ifdef G12A_BRINGUP_DEBUG
+ if (vdec_get_debug_flags() & 0xff0000) {
+ pr_info("%s force open port %d\n",
+ __func__,
+ ((vdec_get_debug_flags() >> 16) & 0xff) - 1);
+ port = &ports[((vdec_get_debug_flags() >> 16) & 0xff) - 1];
+ }
+ pr_info("%s, port name %s\n", __func__, port->name);
+#endif
if (iminor(inode) >= amstream_port_num)
return -ENODEV;
@@ -1593,6 +1619,8 @@ static int amstream_open(struct inode *inode, struct file *file)
if (port->type &
(PORT_TYPE_MPTS | PORT_TYPE_HEVC)) {
amports_switch_gate("clk_hevc_mux", 1);
+ if (get_cpu_type() >= MESON_CPU_MAJOR_ID_G12A)
+ amports_switch_gate("clk_hevcb_mux", 1);
vdec_poweron(VDEC_HEVC);
}
@@ -1726,7 +1754,8 @@ static int amstream_release(struct inode *inode, struct file *file)
&& bufs[BUF_TYPE_VIDEO].for_4k)
vdec_poweroff(VDEC_HEVC);
- if ((port->vformat == VFORMAT_HEVC
+ if ((port->vformat == VFORMAT_HEVC
+ || port->vformat == VFORMAT_AVS2
|| port->vformat == VFORMAT_VP9)) {
vdec_poweroff(VDEC_HEVC);
} else {
@@ -2242,6 +2271,7 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg)
struct stream_buf_s *buf = NULL;
buf = (this->vformat == VFORMAT_HEVC ||
+ this->vformat == VFORMAT_AVS2 ||
this->vformat == VFORMAT_VP9) ?
&bufs[BUF_TYPE_HEVC] :
&bufs[BUF_TYPE_VIDEO];
@@ -2302,8 +2332,7 @@ static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg)
if ((this->type & PORT_TYPE_VIDEO) == 0) {
pr_err("no video\n");
return -EINVAL;
- }
- {
+ } else {
struct vdec_info vstatus;
struct am_ioctl_parm_ex *p = &parm;
@@ -2628,6 +2657,7 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
struct stream_buf_s *buf = NULL;
buf = (this->vformat == VFORMAT_HEVC ||
+ this->vformat == VFORMAT_AVS2 ||
this->vformat == VFORMAT_VP9) ?
&bufs[BUF_TYPE_HEVC] :
&bufs[BUF_TYPE_VIDEO];
@@ -2821,7 +2851,7 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
return -EINVAL;
if (amstream_adec_status == NULL)
return -ENODEV;
- {
+ else {
struct adec_status astatus;
struct am_io_param para;
struct am_io_param *p = &para;
diff --git a/firmware/video_ucode.bin b/firmware/video_ucode.bin
index 0d748ae..9261727 100644..100755
--- a/firmware/video_ucode.bin
+++ b/firmware/video_ucode.bin
@@ -1,4 +1,4 @@
- Ÿ_K{cöL(rgÛ/4QyG4n(x8΅|i2m]%pgM-ͻuH00%FUfM%n|=x%loUe}РTqnX|1vr9H"K87-de"Gu ]G5D1P_m
+*dodwuC*Q.g'>;؄OM,G;\3I~ڕ_2>Ϩ~G3 dpYܴFNP/-?mN^:K\3vRDvBw9|~cS|O dpaΏpr7 "TvG}i71ȅHZB)!nJj @Pun
B<
@@ -568,14 +568,14 @@ I
G   @= # 
-G"@ 9 # @;
+G"@ 9 # @;
-
+
x
@ `
x
@@ -1223,7 +1223,7 @@ J2 x 
0
`
-
+
-x
@ `
5x
@@ -1890,14 +1890,1744 @@ J2 x 
0
`
-
-
-
+
+
+
+
+
+
+G
+%
+
+@:La
+
+
+
+
+@y
+o
+c
+HCc
+I
+x
+*L6Lǁ Q ;LH2 
+H
+L `
+
+@@ I
+
+x
+ 
+
+@x  
+
+2
+
+( GGCG
+
+<L 
+
+
+ B
+
+
+BD HAd
+
+`
+
+
+`
+
+X  ȃ 
+, 
+
+q@BD HH@d
+
+x
+
+
+@ 
+HA
+
+
+
+ȃ X 
+
+x ! GG
+G$L x 0! $L @$ N
+@
+" 
+N" HD 2P @x ! x A! 
+@
+` @
+
+
+`
+
+
+Hz o
+
+ N
+
+
+
+GI 
+O
+I@
+I
+
+o
+I@
+I
+ Rp
+ 
+
+  I`O
+
+
+
+
+
+LJ
+ 
+
+`
+6x G`
+G
+G
+ 
+
+
+^
+G IGa @
+a  
+G
+
+
+
+`
+x 
+
+@
+@
+P @
+x
+9
+ IG 
+@
+@
+P @
+x
+
+
+GG
+
+
+
+
+H`W
+x
+
+HH
+
+ 
+
+*L 6L @˂@
+@KK
+I
+
+
+
+B r@@x r@
+
+ Gr
+Gr
+
+
+G`
+
+
+G
+b
+
+
+o
+I
+H
+
+
+
+
+G@H
+?I ȑ
+I a
+I I
+
+
+
+
+
+
+
+
+
+
+
+J
+
+x GGP ! @$ N
+@
+" 
+N" HD 2P @x ! x A! 
+GG
+G
+G`
+
+@
+
+@
+H! "
+ 
+
+I
+x F! x
+@
+
+N
+  r
+
+ ! RGIba IGa 
+a  
+
+
+"B @x @@ o
+
+@
+ۆ[@ GL a~  ׀
+
+
+@e
+
+(
+! (@( hQ
+(
+*
+kè
+냨
++B
+
+*
+*
+
+
+! ( 銂( (
+@$ ("Lh
+! ( 銂( hЈ0D x ( D *k
+Q
+*
+*
+k
+p
+*
+
+! h (( m-^ ( (
+@$ ("L( (
+! h (( -^ ( (X0D ( (0D ( (
+$ /"L/ /
+! h (( -^ ( (
+P$ ("L( (
+! h (( --^ ( h؎0D ( $ $("L./(
+
+
+
+! ( 銂( @$ ("Lh
+! ( 銂( hи0D @x ( *
+Q x +kA
+k
+p
+0D ( ) (
+! h (( -^ ( @$ ("L( (
+! h (( ( (X0D ( (0D ( (
+! h (( m-^ ( P$ ("L( (
+! h (( 胂 ( hؾ0D ( $ $("L./((
+@#x IU
+
+@ x 
+@@x  U@U5
+`a@
+
+U@
+
+@V
+
+
+E NNN$ " N
+
+x Ad
+V U
+
+E
+
+G
+G
+c
+
+N N N
+
+  
+@
+!
+G
+
+ߏN Lȃ JB
+
+`
+
+,
+ *C(I(
+,J@($ ,*F ( ) ("L(h ! ( 튂( (
+,J@ ($ ("Lh ! ( 튂(  ,
+("Lh ! ( 튂( 
+
+
+
+
+
+G
+%
+
+@:La
+
+
+
+
+@y
+o
+c
+HCc
+I
+x
+*L6Lǁ Q ;LH2 
+H
+L `
+
+@@ I
+
+x
+ 
+
+@x  
+
+2
+
+( GGCG
+
+<L 
+
+
+ B
+
+
+BD HAd
+
+`
+
+
+`
+
+X  ȃ 
+, 
+
+q@BD HH@d
+
+x
+
+
+@ 
+HA
+
+
+
+ȃ X 
+
+x ! GG
+G$L x 0! $L @$ N
+@
+" 
+N" HD 2P @x ! x A! 
+@
+` @
+
+
+`
+
+
+Hz o
+
+ N
+
+
+
+GI 
+O
+I@
+I
+
+o
+I@
+I
+ Rp
+ 
+
+  I`O
+
+
+
+
+
+LJ
+ 
+
+`
+6x G`
+G
+G
+ 
+
+
+^
+G IGa @
+a  
+G
+
+
+
+`
+x 
+
+@
+@
+P @
+x
+9
+ IG 
+@
+@
+P @
+x
+
+
+GG
+
+
+
+
+H`W
+x
+
+HH
+
+ 
+
+*L 6L @˂@
+@KK
+I
+
+
+
+B r@@x r@
+
+ Gr
+Gr
+
+
+G`
+
+
+G
+b
+
+
+o
+I
+H
+
+
+
+
+G@H
+?I ȑ
+I a
+I I
+
+
+
+
+
+
+
+
+
+
+
+J
+
+x GGP ! @$ N
+@
+" 
+N" HD 2P @x ! x A! 
+GG
+G
+G`
+
+@
+
+@
+H! "
+ 
+
+I
+x F! x
+@
+
+N
+  r
+
+ ! RGIba 
+a  
+
+
+"B @x @@ o
+
+@
+ۆ[@ GL a~  ׀
+
+
+@e
+
+(
+! (@( hQ
+(
+*
+kè
+냨
++B
+
+*
+*
+
+
+! ( 銂( (
+@$ ("Lh
+! ( 銂( hЈ0D x ( D *k
+Q
+*
+*
+k
+p
+*
+
+! h (( m-^ ( (
+@$ ("L( (
+! h (( -^ ( (X0D ( (0D ( (
+$ /"L/ /
+! h (( -^ ( (
+P$ ("L( (
+! h (( --^ ( h؎0D ( $ $("L./(
+
+
+
+! ( 銂( @$ ("Lh
+! ( 銂( hи0D @x ( *
+Q x +kA
+k
+p
+0D ( ) (
+! h (( -^ ( @$ ("L( (
+! h (( ( (X0D ( (0D ( (
+! h (( m-^ ( P$ ("L( (
+! h (( 胂 ( hؾ0D ( $ $("L./((
+@#x IU
+
+@ x 
+@@x  U@U5
+`a@
+
+U@
+
+@V
+
+
+E NNN$ " N
+
+x Ad
+V U
+
+E
+
+G
+G
+c
+
+N N N
+
+  
+@
+!
+G
+
+ߏN Lȃ JB
+
+`
+
+,
+ *C(I(
+,J@($ ,*F ( ) ("L(h ! ( 튂( (
+,J@ ($ ("Lh ! ( 튂(  ,
+("Lh ! ( 튂( 
+
+
+
+
+
+G+
+%
+$
+@x
+@:La
+
+
+
+
+y
+
+
+
+
+
+ , 
+
+
+B I
+
+
+
+
+@
+
+o
+c
+HCc
+I
+x
+*L6Lǁ Q ;LH2 
+H
+L `
+
+@@ I
+
+x x o
+ 
+
+@x  
+
+2
+
+( GG$ $" $" 
+
+<L 
+
+
+@ B
+
+
+BD HAd
+
+`
+
+
+`
+
+X  ȃ 
+, 
+
+q@BD HH@d
+
+x
+
+
+@ 
+HA
+
+
+
+ȃ X 
+
+x ! GG
+G$L x 0! $L @$ N
+@
+" 
+N" HD 2P @x ! x A! 
+
+` @
+
+
+`
+
+
+HR o
+
+ N
+
+
+
+GI 
+O
+I@
+I
+
+o
+I@
+I
+ Rp
+ 
+
+  I`O
+
+
+
+
+
+LJ
+ 
+
+6x G`
+G
+G
+ 
+
+
+@8
+G IGa @
+a  
+G
+
+
+
+`
+x 
+
+@
+@
+P @
+x
+
+ IG 
+@
+@
+P @
+x
+
+ I
+
+GG
+
+
+
+
+H`W @-x
+x
+
+
+ %
+
+
+
+G@H
+?I ȑ
+I a
+I I
+
+
+
+
+
+
+
+
+
+
+
+J
+
+@x GGP ! @$ N
+@
+" 
+N" HD 2P @x ! x A! 
+GG
+G
+G`
+
+@
+
+@
+H! "
+ 
+
+I
+x F! x
+@
+
+N
+  r
+
+ ! RGIba IGa 
+a  
+
+
+"B @x @@ o
+
+@
+ۆ[@ GL
+
+
+f
+
+(
+! (@( hQ2x ( (o
+(
+*
+kè
+냨
++B
+
+*
+*
+
+
+! ( 銂( (
+@$ ("Lh
+! ( 銂( hЈ0D
+,J@($ ,*F ( ) ("L(h ! ( 튂( (
+,J@ ($ ("Lh ! ( 튂(  ,
+("Lh ! ( 튂( 
+*
+*
+k
+p
+*
+
+! h (( m-^ ( (
+@$ ("L( (
+! h (( -^ ( (X0D ( (0D ( (
+$ /"L/ /
+! h (( -^ ( (
+P$ ("L( (
+! h (( --^ ( h؎0D ( $ $("L./(
+
+
+
+! ( 銂( @$ ("Lh
+! ( 銂( hи0D x ( *
+k
+p
+0D ( ) (
+! h (( -^ ( @$ ("L( (
+! h (( ( (X0D ( (0D ( (
+! h (( m-^ ( P$ ("L( (
+! h (( 胂 ( hؾ0D ( $ $("L./((
+"x IU
+
+@ x 
+@@x  U@U5
+`a@
+
+U@
+
+@V
+
+
+E NNN$ " N
+ x Ad
+V U
+x
+E
+
+G
+G
+c
+
+N N N
+
+  
+@
+!
+G
+
+
+
+@1x
+x
+ AH2: B AHB8 IBHB0 B
+ A AH"< J"` BH" CH  AH< I AH8 IH2: AI2@ I"@ BT a IAa  ` H
+
+
+
+I
+
+
+
+ AHR6  AH>   @  @@
+@
+ Ab4 @
+ Ab4 @
+@
+x
+x
+0
+  I @c
+H@a
+
+
+*x
+
+
+ A> @
+ A>  A0 
+H@
+
+0@a
+ 
+ 
+|
+ A> F
+ AS6
+
+
+ AH>
+ AH> H< I H@
+ AH>  AH> Hr0 
+
+
+H
+
+
+l
+I i
+
+
+  AH> I
+Hr0 ɑ A D 0 "@ RAH RH R  @
+
+
+H ȇ $H@
+B @x #F #-FH -
+
+H
+"L B
+BP  v
+&
+2x S
+
+
+
+
+
+PH 
+J` JJp JP
+
+
+
+ 
+H
+
+
+ 
+
+
+ 
+> ~ @ M@ @LÀ
+J
+> ~ @ M@ @LÀL
+
+
+
+
+*KAf
+%K
+
+H2
+
+
+@ x a "@I` @@H2@H
+!
+x a "@I` @@H"@H
+!
+~
+x I
+
+@
+ `
+x
++@
+x I
+
+@
+ `
+x
+,
+@@
+@
+@@
+@"@I
+@
+
+I@J@
+B` H  "|
+I@J@
+Bh H %GH  T I ^  `  "V I "Z   "H  GI
+
+I ɒ H2@ 0H"@ 2
+
+J` 
+J` 
+OH
+
+O
+EH
+HF%G&HGH&G&G&H'HHH'H'H'I(HIH(I(I(J)HJH)J)J)K*HKH*K
+K
+L HLH L LMHMMHMN HN N N O`HH``@Q`R@PPCH
+
+
+2@ @ I
+8
+
+8I 8
+J@ɑ  A H@M
+ @
+o
+
+o
+
+R F>
+n
+
+
+
+
+m
+-<l
+
+-<m
+
+
+ 00
+
+0
+x 1!
+
+
+
+J` 
+J` 
+
+
+@1x
+
+ AH2: B AHB8 IBHB0 B
+ A AH"< J"` BH" CH  AH< I AH8 IH2: AI2@ I"@ BT a `IAa  `  H
+
+
+
+I
+
+
+
+ AHR6  AH>   @  @
+@
+ Ab4 @
+ Ab4 @
+@
+x
+x
+0
+  I @c
+H@a
+
+
+*x
+@x
+
+ A> @
+ A>  A0 
+H@
+
+0@a
+ 
+ 
+v
+ A> F
+ AS6 @
+@r
+
+ AH>
+ AH> H< I H@
+ AH>  AH> Hr0 
+
+
+H
+
+
+f
+I c
+@*
+@&x
+  AH> I
+Hr0 ɑ A D 0 "@ RAH RH R  @
+
+
+H ȇ $H@
+B
+H
+"L B
+BP  v
+&
+2x S
+
+
+
+
+
+PH 
+J` JJp JP
+
+
+
+ 
+H
+
+
+ 
+
+
+ 
+> ~ @ M@ @LÀ
+J
+> ~ @ M@ @LÀL
+
+
+
+
+*KAf
+%K
+
+H2
+
+
+@ x a "@I` @@H2@H
+!
+x a "@I` @@H"@H
+!
+~
+x I
+
+@
+ `
+x
++@
+x I
+
+@
+ `
+x
+,
+@@
+@
+@@
+@"@I
+@
+
+I@J@
+B` H  "|
+I@J@
+Bh H %GH  T I ^  `  "V I "Z   "H  GI
+
+I ɒ H2@ 0H"@ 2
+
+J` 
+J` 
+OH
+
+O
+EH
+HF%G&HGH&G&G&H'HHH'H'H'I(HIH(I(I(J)HJH)J)J)K*HKH*K
+K
+L HLH L LMHMMHMN HN N N O`HH``@Q`R@PPCH
+
+
+2@ @ I
+8
+
+8I 8
+J@ɑ  A H@M
+ @
+o
+
+o
+
+R F>
+n
+
+
+
+
+m
+-<l
+
+-<m
+
+
+ 00
+
+0
+x 1!
+
+
+
+J` 
+J` 
+
+
+@z
+
+
+ s@
+J AHR0  AH! I AH!  AHB8 I AH0  @
+
+ A @
+J>
+ A A A AJ<
+ A"@@ @ AH>  `
+
+
+
+
+
+ AH>
+
+H
+@ s@@y
+x
+
+H22 IH0 H
+
+
+J
+s@ AHR0  AH!  AH! I A AH0 K @
+
+ A @
+J>
+ A A A AJ<
+ A"@@ @@ I
+
+
+
+
+
+
+@ 
+ I
+
+I AH>
+@
+
+
+ 
+
+ I
+ AH0 H.  @ AH> H< H: 
+
+
+
+
+
+x GK`
+
+
+
+@A
+C
+C @
+C O
+C C
+
+`
+
+
+J
+@
+
+
+x NCh @x NC@ x NCH @x NCP
+K@
+ x @ x x  @ I
+
+K@
+
+`
+JB@Jb@H
+
+@x Nb@
+N@ I
+
+
+\
+
+ A>
+
+ @b
+
+
+x M@Q
+S$S$AL
+S
+
+@@ AH>
+
+
+
+
+
+ @ P 
+
+ AH! I AH!  AH>
+H<  AH> @
+H$ H  AH6 @
+
+
+ A `
+
+ A `
+x  AH! I AH!  AH!  AH!  AH>
+P I
+J
+`
+x
+ A> @
+ AH0  AHR6 H4 HR*  AHB8 HB0
+ AHB8  AHR6 HR, HR"
+IIIb IIbI@
+IIIR IIRI 
+II
+@1x
+@6y
+
+ s@3 b
+
+
+s@
+HB
+J
+s@ AH> H< IH26 H4 H2 
+
+@
+
+x @  I@ H  AH>  @
+
+
+
+
+
+## $@x I$ AH> #H< a
+#@ $ I$ AH> b
+H
+
+
+ s@
+x
+
+
+
+
+
+
+
+
+
+`
+
+x I
+Ib
+
+
+
+
+H
+H
+
+@Jo
+
+
+
+x
+
+
+x
+@x
+|x
+
+>
+Hr
+
+
+s@
+Ju
+s@
+ 
+HB
+Jm
+s@%
+I&@x &@
+
+J@ɑ &H&
+
+ȁ @
+I
+ a
+
+J@ɑ ' AH> @a
+ @
+ x J
+@
+
+x
+HH
+J@ɑ  AH>  AH>
+
+
+'
+
+A AH> b
+IbT I( `
+
+@
+
+/I 
+
+Al
+(  @
+
+ @a
+I
+
+(I(I
+
+ {DH2@
+
+
+
+
+@
+
+#I+ $+I$x + AH> a
+I+
+
+(@a
+H+
+@x
+#`
+@x
+
+
+@  A H
+@%
+{
+
+BH/
+
+
+
+9 & `
+&
+
+
+
+Px
+
+
+
+-H.
+H ..x &Hb
+'
+ (&bx
+
+ #
+
+#F #-FH -
+
+
+
+
+`
+
+
+
+E E "`  "d H-- ` , BX - Bx J-H.
+
+
+
+
+
+.J-"
+@x @H
+@
+
+
+ /H
+@ @@
+
+ @K
+H01DH
+HR n
+
+.@a
+ #
+
+
+
+
+
+
+
+@
+@a
+ @
+> ~ @ M@ @LÀ
+J
+> ~ @ M@ @LÀL
+
+
+
+
+ b
+H
+
+
+
+"Ab
+!H!
+X
+_ #
+
+@ x
+ +
+@
+@
+
+
+
+
+
+I.H2
+
+
+x
+x I.I
+!
+
+!
+J J
+@x BX H`
+x BP `
+
+!
+JH H@
+JH
+JH JH
+A1
+
+
+ x I
+@
+A
+ `
+x
+
+ x I
+@
+A
+ `
+x
+!
+@@
+@H3 @ 
+@@
+@"@I
+@
+K
+K
+
+
+
+
+K
+ 3@
+
+
+
+
+
+ 3@
+
+
+
+I@J@
+B` H  "|
+I@J@
+Bh H %GI @ B D I  "H  G "@  "H "P  D @  B  D "@  "D  
+HH/H I@HHHIHII 
+
+ H
+"I H
+H# H
+#ɐ H
+# H
++I H
+H+ H
+'ɑ H
+( H
+,I H
+
+R0 
+
+
+
+2@ @ I
+
+
+
+
+@
+/
+
+/I /
+J@ɑ  A H@M
+ @
+
+ /J2@ -@
+@
+n
+ F>
+m
+
+
+.^a Ѐ
+
+;
+; 
+b I@@
+%A#$AdIA
+#
+@#A
+
+$ J
+
+
+f9&Y
+
+
+
+
+
+
+a @樀
+
+W
+
+
+
+$$f
+$"x
+
+=`
+
+)x = ! d&
+d
+%
+@x
+$$$$$
+
+
+$A$> $
+#Dc/
+
+c
+d!
+
+Q f9@
+@ x e<&a
+d)e
+x Ia
+de
+@ x $@@ $) a
+9 @c@
+c%
+fH
+
+
+#$
+d@
+#
+f! x &
+c
+@
+e
+
+
+%`
+
+
+i2 $$$$$
+d
+
+
+f! $e
+$<
+d&I@
+i2 @
+d
+
+
+f $$<
+
+
+
+hr
+#
+
+C@
+
+`B
+@
+`B
+
+
+(
+! '*
+
+
+
+
+
-@z
+z

-@ s@
+
J AHR0  AH! I AH!  AHB8 I AH0  @
A @
@@ -1906,48 +3636,48 @@ J>
 A"@@ @ AH>  `
-
-
+
+
 AH>
- I
+
H
- s@@y
-
-
+ s@y
+
+@y
H22 IH0 H
-~ s@
-J
+@ s@
+J
s@ AHR0  AH!  AH! I A AH0 K @
A @
J>
 A A A AJ<
- A"@@ @@ I
+ A"@@ @ I

-
+@w s@
FI> o
- 
+ @  I@  @  I  AH> K `
-
- 
+
+
 I
-
+
I AH>
-
-
-
- 
-
- I
+@
+
+
+ 
+
+@ I
 AH0 H.  @ AH> H< H: 
-M
-@? s@y
+
+@ s@
-
+
x GK`
@@ -1969,15 +3699,15 @@ J
x NCh @x NC@ x NCH @x NCP
K@
- x @ x x   I
+ x @ x x  

K@

`
-JB@Jb@H
+JB@Jb@H
@x Nb@
-N@ I
+N@@ I

\
@@ -1989,14 +3719,13 @@ N@ I
x M@Q
S$S$AL
-S
-
+S
+
@@ AH>
-
+
-
-
+
@ P 
@@ -2004,53 +3733,53 @@ S
H<  AH> @
H$ H  AH6 @
-X
+X
 A `
-
+
 A `
x  AH! I AH!  AH!  AH!  AH>
-@K I
+K I
J
`
x
 A> @
 AH0  AHR6 H4 HR*  AHB8 HB0
 AHB8  AHR6 HR, HR"
-IIIb IIbI@
-IIIR IIRI 
-II
+IIIb IIbI@
+IIIR IIRI 
+II
-0y
+

- s@@. b
+ s@. b

-
+
s@
HB
-J
-s@ AH> H< IH26 H4 H2 ' I
-
-|
+J@
+s@ AH> H< IH26 H4 H2 ' I
+
+
-x
-@
+x @ I@ H  AH>  @
+
-
+
-
-!! "@x I" AH> !H< a
-!
+
+## $@x I$ AH> #H< a
+#@  $  I$ AH> b
H

-
- s@
+
+ s@
x
-
+
-
-
+
+
@@ -2060,225 +3789,224 @@ x I
Ib
-
+
H
H
-
+
@Jo
-
-
-x
+
+
+x
-
-x
-@x
-}x
-
-<
-H
+
+x
+@x
+@}x
+
+>
+Hr

-@x
+
s@
-J
-s@
- 
+Jo
+s@
+ 
HB
-Je
-s@#
-I$@x $@
-
-J@ɑ $H$
-
-ȁ 
-I
+Jg
+s@%
+I&@x &@
+
+J@ɑ &H&
+
+ȁ @
+I
a
-
-J@ɑ % AH> @a
- @@. 
+
+J@ɑ ' AH> @a
+ @@0 
x J
@
-
+
x
HH
J@ɑ  AH>  AH>
-
-
-%
+
+
+'
A AH> b
-IbT I& `
-
-
-
--I @
+IbT I( `
+
+@
+
+/I @
Al
-&  @
-
+(  @
+
@a
-I
+I
-&I&I
-
+(I(I
+
  {
-
-
-
-!I) ")I"x ) AH> a
-I)@
-
-&@a
-H)
-@x
-!`
-@x {
-z
+
+@
+
+#I+ $+I$x + AH> a
+I+
+
+(@a
+H+
+@x
+#`
+@x
+

@  A H
-@#
-
-
+@%
+w
+
F> o
-
-
-7 $ `
-$
-
+
+
+9 & `
+&
+
-
-Hx
- 
-
-
-
-+H,
-H,,x $Hb
-'@ ($[x
-
- !
-
-
+
+Ix
+
+
+
+-H.
+H ..x &Hb
+' (&
+
+ #
+
+
`
-
+
I I L F
-ɗ ɗ H a H++ a H,, a @II@ a H
+ɗ ɗ H a H-- a H.. a @II@ a H
ER


-E "`  "d H++ `  ~ J,,`
-ȇ , -` @
-
-
-,J+"
+E "`  "d H-- `  ~ J..`
+ȇ . /` '(@ 
+
+
+
+
+
+.J-"
@x @H
@


- -H
-@ @@
+ /H
+@ @@

- @K
+ @K
H01DH
HR n
-
-,@a
- !
-
+
+.@a
+ #
+
-@
+
-
-
+
+@
@a
- @
+ @
> ~ @ M@ @LÀ
J
> ~ @ M@ @LÀL
-
-@
-@
- b
+
+
+
+ b
H
-
+
-
-
+
"Ab
!H!
X
-_ !
+_ #
-
- +
-@
-@
-
-A
-
-
- 
-I,H2
-
-
-x
-x I,I
-!
+@ x
+ +
+@
+@
+
+
+
+
+
+I.H2
+
+
+x
+x I.I
+!
-!
-J J
+!
+J J
@x BX H`
x BP `
-!
+!
JH H@
JH
-JH JH
-A1
-
-
-p}
-x I
-
-@
+JH JH
+A1
+
+
+ x I
+@
+A
`
-x
-@
-x I
-
-@
+x
+
+ x I
+@
+A
`
-x
- 
-@@
-@
+x
+!
+@@
+@H3 @ 
@@
@"@I
@
-K
-
-K
-
+K
+K
-
+
-
-K
-
+
+K
3@

-
-
-
+
+
+
3@

@@ -2286,89 +4014,87 @@ JH JH
I@J@
B` H  "|
I@J@
-Bh H %GI @ B D I  "H  G "@  "H "P  D @  B  D "@  "D  
-HH-H I@HHHIHIIIHJHJJ JH K HK"KH"L)HL)LLHM#HMHNHNNN  BH OXHXXHXYHYHHOOYYHZHZ
+Bh H %GI @ B D I  "H  G "@  "H "P  D @  B  D "@  "D  
+HH/H I@HHHIHII 
+
 H
- I H
-H! H
-!ɐ H
-! H
-)I H
-H) H
-%ɑ H
-& H
-*I H
-
-P. 
-
-
+"I H
+H# H
+#ɐ H
+# H
++I H
+H+ H
+'ɑ H
+( H
+,I H
+
+R0 
2@ @ I

-
+
-@
--
+@
+/
--I -
+/I /
J@ɑ  A H@M
- @
-
-
+ @
+

-,^a Ѐ
+.^a Ѐ
$@
Y@hB&i
-
+
%A#$AdIA
#
-@#A
-
-$ $
-
-4x
-f9&Y
+@#A
+
+$ K
+
+4x
+f9&Y
-
+
-
+
-
-a @樀
+
+a @樀

-Z
+W
-
+
$$f
-$"x
-
-;`
- x %`
-
+$"x
+
+=`
+
+)x = ! d&
d
%
-@x
-$$$$$
+@x
+$$$$$
$A$> $
#Dc/
c
-d@!
-
+d!
+
Q f9@
@ x e<&a
d)e
x Ia
de
@ x $@@ $) a
-7 @c@
+9 @c@
c%
fH

@@ -2383,47 +4109,45 @@ e
%`
-
-
+
+
i2 $$$$$
d
f! $e
-$<
+$<
d&I@
-i2 
+i2 @
d
-f $$<
+f $$<
+
-
+
hr
#
C@
-
-`b
-
-`b
-
-聂 ((
-! )@( 
-
+
+`B
+@
+`B
+
+
(
! '*
-x )!
-
+
-
-
-
+
+
+
-
+

-
+ s@
J AHR0  AH! I AH!  AHB8 I AH0  @
A @
@@ -2432,48 +4156,50 @@ J>
 A"@@ @ AH>  `
-
-
+
+ 
+   
+
 AH>
- I
+ I
H
- s@
-
-y
+
+
+y
H22 IH0 H
-@ s@
-J
+ s@
+J@
s@ AHR0  AH!  AH! I A AH0 K @
A @
J>
 A A A AJ<
- A"@@ @
+ A"@@ @

-{ s@ 
+| s@ 
FI> o
-@  @ I @  @ I  AH> K `
+@  @ I @  @ I  AH> K `
-
- 
+
+ 
 I
-
+
I AH>
-
-
-
- 
-
- I
+@
+
+
+ 
+
+ I
 AH0 H.  @ AH> H< H: 
-M
-
+
+@F s@y
-
+
x GK`
@@ -2495,15 +4221,15 @@ J
x NCh @x NC@ x NCH @x NCP
K@
- x @ x x  @ I
+ x @ x x   I

K@

`
-JB@Jb@H
+JB@Jb@H
@x Nb@
-N@ I
+N@ I

\
@@ -2515,14 +4241,13 @@ N@ I
x M@Q
S$S$AL
-S
-
+S
+
@@ AH>
-
+
-
-
+
@ P 
@@ -2542,41 +4267,41 @@ J
 A> @
 AH0  AHR6 H4 HR*  AHB8 HB0
 AHB8  AHR6 HR, HR"
-IIIb IIbI@
-IIIR IIRI 
-II
+IIIb IIbI@
+IIIR IIRI 
+II
-6y
+6y

- s@
+

-
+@
s@
HB
-J@
+J
s@ AH> H< IH26 H4 H2 @- I
-
-
+
+
-x  I H AH>  @
+x  I H  AH>  @
-
-!! "@x I" AH> !H< a
-! "@ I" AH> b
+
+## $@x I$ AH> #H< a
+# $@ I$ AH> b
H

-
- s@y
+
+
x
-
+
-
-
+
+
@@ -2586,227 +4311,227 @@ x I
Ib
-
+
H
H
-
+
@Jo
-
+
-x
+x
-
-x
-@x
-}x
-
-<
-H
+
+x
+@x
+@}x
+
+>
+Hr

-@x
+
s@
-Js
-s@
- r s@
+J@u
+s@
+ t s@
HB
-J@k
-s@#
-I$@x $@
-
-J@ɑ $H$
-
-ȁ 
-I
+J
+s@%
+I&@x &@
+
+J@ɑ &H&
+
+ȁ 
+I
a
-
-J@ɑ % AH> @a
- @@. 
+
+J@ɑ ' AH> @a
+ @@0 
x J
@
-
+
x
HH
J@ɑ  AH>  AH>
-
-
-%
+
+
+'
A AH> b
-IbT I& `
-
-
-
--I
+IbT I( `
+
+
+
+/I 
Al
-&  @
-
+(  @
+
@a
-I
+I
-&I&I
-
+(I(I
+
  {
-
-
-
-!I) ")I"x ) AH> a
-I)
-
-&@a
-H)
-@x
-!`
-@x @
-@
+
+
+
+#I+ $+I$x + AH> a
+I+@
+
+(@a
+H+
+@x
+#`
+@x
+

@  A H
-@#
-|
-
+@%
+
+
F> o
-
-
-7 $ `
-$
-
+
+
+9 & `
+&
+
-@
-
-
-
-
-+H,
-H,,x $Hb
-'
-
- !
-
-c
-@ 
-
+
+
+
+
+
+-H.
+H ..x &Hb
+'@  (&ax
+
+ #
+
+@c
+@ 
+
`
-
+
I I L F
-ɗ ɗ H a H++ a H,, a @II@ a H
+ɗ ɗ H a H-- a H.. a @II@ a H
ER


-E "`  "d H++ `  ~ J,,`
-ȇ , -` @
-
-
-,J+"
+E "`  "d H-- `  ~ J..`
+ȇ . /` '( 
+
+
+
+
+
+.J-"
@x @H
@


- -H
-@ @@
+ /H
+@ @@

- @K
+ @K
H01DH
HR n
-
-,@a
- !
-
+
+.@a
+ #
+@
-
+
-
-@
+
+
@a
- @
+ @
> ~ @ M@ @LÀ
J
> ~ @ M@ @LÀL
-
-
-
- b
+
+
+
+ b
H
-
+
-
-
-<
+
+
"Ab
!H!
X
-_ !
+_ #
-
- +
-@
-@
-
-A
-
-
- 
-I,H2
-
-
-x
-x I,I
-!
+@ x
+ +
+@
+@
+
+
+
+
+
+I.H2
+
+
+x
+x I.I
+!
-!
-J J
+!
+J J
@x BX H`
x BP `
-!
+!
JH H@
JH
-JH JH
-A1
-
-
-
-x I
-
-@
+JH JH
+A1
+
+
+ x I
+@
+A
`
-x
-@
-x I
-
-@
+x
+
+ x I
+@
+A
`
-x
- 
-@@
-@
+x
+!
+@@
+@H3 @ 
@@
@"@I
@
-K
-
-K
-
+K
+K
-
+
-
-K
-
+
+K
3@

-
-
-
+
+
+
3@

@@ -2814,94 +4539,92 @@ JH JH
I@J@
B` H  "|
I@J@
-Bh H %GI @ B D I  "H  G "@  "H "P  D @  B  D "@  "D  
-HH-H I@HHHIHIIIHJHJJ JH K HK"KH"L)HL)LLHM#HMHNHNNN  BH OXHXXHXYHYHHOOYYHZHZ
+Bh H %GI @ B D I  "H  G "@  "H "P  D @  B  D "@  "D  
+HH/H I@HHHIHII 
+
 H
- I H
-H! H
-!ɐ H
-! H
-)I H
-H) H
-%ɑ H
-& H
-*I H
-
-P. 
-
-
+"I H
+H# H
+#ɐ H
+# H
++I H
+H+ H
+'ɑ H
+( H
+,I H
+
+R0 
2@ @ I

-
+
-@
--
+@
+/
--I -
+/I /
J@ɑ  A H@M
- @
-
-
+ @
+

-,^a Ѐ
+.^a Ѐ
$@
Y@hB&i
-
+
-9
-9 
+;
+; 
b I@
%A#$AdIA
#
-@#A
-
-$ $
-
-4x
-f9&Y
+@#A
+
+$ K
+
+4x
+f9&Y
-
+
-
+
-
-a @樀
+
+a @樀

-Z
+W
-
+
$$f
-$"x
-
-;`
- x %`
-
+$"x
+
+=`
+
+)x = ! d&
d
%
-@x
-$$$$$
+@x
+$$$$$
$A$> $
#Dc/
c
-d@!
-
+d!
+
Q f9@
@ x e<&a
d)e
x Ia
de
@ x $@@ $) a
-7 @c@
+9 @c@
c%
fH

@@ -2916,40 +4639,39 @@ e
%`
-
-
+
+
i2 $$$$$
d
f! $e
-$<
+$<
d&I@
-i2 
+i2 @
d
-f $$<
+f $$<
+
-
+
hr
#
C@
-
-`b
-
-`b
-
-聂 ((
-! )@( 
-
+
+`B
+@
+`B
+
+
(
! '*
-x )!
-
+
-
+
+
@x
@ `
@x
@@ -3596,7 +5318,7 @@ J2 x 
0
`
-
+
y
G@,
%
@@ -3914,7 +5636,7 @@ G
 *C(I(
,J@($ ,*F ( ) ("L(h ! ( 튂( (
,J@ ($ ("Lh ! ( 튂(  ,
-("Lh ! ( 튂( 
+("Lh ! ( 튂( 
G+
%
@@ -4206,7 +5928,7 @@ G
@
!
G
-
+
y
G@,
%
@@ -4524,7 +6246,7 @@ G
 *C(I(
,J@($ ,*F ( ) ("L(h ! ( 튂( (
,J@ ($ ("Lh ! ( 튂(  ,
-("Lh ! ( 튂( 
+("Lh ! ( 튂( 
I`
x `
x  x
@@ -4796,7 +6518,7 @@ V UU@U5
GG
G
 I &
-
+
I !
`iI@ C
     @
@@ -5194,7 +6916,7 @@ EG
EŅ "  
EG
ņ
-EŇ " 
+EŇ " 
I !
`iI@ C
     @
@@ -5566,12 +7288,12 @@ EŇ@x
EG
ł
EŃ@
-`
-
-+@+@
-
-
-
+`
+
++@+@
+
+
+
y
I
@@ -5580,9 +7302,9 @@ I

H
- AH2: %
+ AH2: '
h OI
-@x
+@x
H
II
@@ -5591,7 +7313,7 @@ H
 AH0  AH! I
-J
+J
 AH> `
x  AH>
0 
@@ -5637,12 +7359,12 @@ HB6
`
I
-
+
OAI
 n
 p
- r  t O
-
+ r  t O
+

@K2
 
@@ -5654,11 +7376,11 @@ I
`

-A
+A
ʣ @ x
- MA@
-
+ MA
+
H0
@@ -5722,7 +7444,7 @@ HAAAH o
- 
+ 
 
9A
@@ -5732,7 +7454,7 @@ HAAAH o



-@
+
H2@ 2
J`  JJ` 
@@ -5746,12 +7468,12 @@ O
H @
 ȇ $H 
`
-
+

- 
+ 
h O@a
  AH0  AH( I   b
@@ -5763,26 +7485,26 @@ H @
H": ` 
2` O
-
+
*CAf
-#G
+#G

-@
+
I  
- }
-
-
- KKa AK@/
-
+ 
+
+
+ KKa AK@/
+
IH2
x J "
$

-
-A1
-@
-
+
+A1
+@
+~
( (+@Q R PPCH
@@ -5849,7 +7571,7 @@ H @H
H2@"@H
`
-P/D
+P/F
H@

H0
@@ -5864,33 +7586,353 @@ b I@@
b
+"
-+.[
++.[
-a . AB+@+
-
-@U
-
-!+ A/
-
+a . AB+@+@
+
+@U
+
+!+ A/
+


-,@l@!
-
+,@l!
+
+
o
 00
0
x 1!
-
+
-J`  JJ` 
-
-+@+@
-
-
-
+J`  JJ` 
+
++@+@
+
+
+
+y
+
+I
+
+@
+
+
+H
+ AH2: !
+h OI
+x
+
+H
+ II
+ I AH2: `
+
+
+ AH0  AH! I
+
+J
+ AH> `
+x  AH>
+0 
+
+Hb2
+
+0 
+
+Hb2
+
+0 
+
+Hb2
+
+0 
+
+Hb2
+
+0 
+
+Hb2
+
+0 
+
+Hb2
+
+4 
+
+HB6
+
+4 
+
+HB6
+
+4 
+
+HB6
+
+
+ a
+ @a
+
+`
+
+I
+
+OAI
+ n
+ p
+ r  t O
+
+
+@K2
+ 
+ 
+@
+ AH> J
+ H
+`
+`
+
+
+A
+
+ʣ @ x
+ MA
+
+
+
+H0
+
+I
+
+
+
+H0
+
+
+H
+
+a
+ @a
+H `
+
+
+"
+AAAH o
+H J
+2X O
+b
+HAAAH o
+
+
+H @
+Hb
+"| AAAH @m
+
+B@ 
+
+
+x HAAAH o
+
+HAAAH o
+
+
+OAHH
+O JB@
+
+
+
+H
+
+
+H
+J
+OA
+"T O
+HAAAH o
+
+H"HAAAH o
+
+
+HAAAH o
+
+
+
+AAAH o
+
+
+
+ 
+ 
+
+9A
+
+
+9J2@ɗ :H
+
+ 
+
+
+H2@ 2
+
+J`  JJ` 
+I
+I
+
+OAH
+
+O
+
+H @
+ ȇ $H f
+ @f
+
+
+
+
+
+
+
+h O@a
+
+  AH0  AH( I   b
+ 
+  OAJb@ O
+#
+
+
+
+H": ` 
+2` O@
+
+*CAf
+#G
+
+
+I  
+ 
+
+
+ KKa AK@/
+
+IH2
+
+x J "
+$
+
+
+A1
+@
+}~
+( (+@Q R PPCH
+
+
+2@ @ I
+@ F>
+o
+
+
+ x J
+-
+
+? AH0 ˂@ɂ@ ʀ 
+`
+
+- AH> 
+
+
+
+? AH0 ˂@ɂ@ 
+ x
+
+
+V  AHb4 b@ bH H2 P T B
+
+@ AH>
+F  AH"< "B  AH> @ 2l ˷ a F 
+ 
+
+
+
+
+?
+
+?
+
+
+?
+
+? 
+@
+
+`
+
+
+
+
+
+H @H
+ I
+@x I
+
+@a
+ I
+b
+IB
+@
+
+`
+
+
+
+
+
+ H2@"@H
+`
+
+P/@:
+H@
+
+H0
+
+
+H0
+
+H? "P 
+@bA˷ a F
+
+b
++"
++.[
+
+a . AB+@+@
+
+a
+
+!+ A/
+
+
+
+,@l!
+
+
+o
+
+ 00
+
+0
+x 1!
+
+
+
+J`  JJ` 
+
++@+@
+
+
+
y
I
@@ -5899,9 +7941,9 @@ I

H
- AH2: @)
+ AH2: +
h OI
-x
+x
H
II
@@ -5910,7 +7952,7 @@ H
 AH0  AH! I
-J
+J
 AH> `
x  AH>
0 
@@ -5956,12 +7998,12 @@ HB6
`
I
-
+
OAI
 n
 p
- r  t O
-
+ r  t O
+

@K2
 
@@ -5973,11 +8015,11 @@ I
`

-A@
+A
ʣ @ x
- MA
-
+ MA@
+
H0
@@ -6041,7 +8083,7 @@ HAAAH o
- @ _  
+  _  
 
9A
@@ -6051,7 +8093,7 @@ HAAAH o



-
+@
H2@ 2
J`  JJ` 
@@ -6065,12 +8107,12 @@ O
H @
 ȇ $H @d
c
-
+

-
+@

h O@a
@@ -6083,26 +8125,26 @@ H @
H": ` 
2` O@
-
+
*CAf
-#G
+#G

-@
+
I  
- }
-
-
- KKa AK@/
-
+ 
+
+
+ KKa AK@/
+
IH2
x J "
$

-
-A1
-@
-@~
+
+A1
+@
+
( (+@Q R PPCH
@@ -6169,7 +8211,7 @@ H @H
H2@"@H
`
-P/D
+P/F
H@

H0
@@ -6184,44 +8226,45 @@ b I@@
b
+"
-+.[
++.[
-a . AB+@+
-
-@U
-
-!+ A/
-
+a . AB+@+@
+
+@U
+
+!+ A/
+


-,@l@!
-
+,@l!
+
+
o
 00
0
x 1!
-
+
-J`  JJ` 
+J`  JJ` 
FL  CL R@ 
I`
-
-x H!
-
+@x `
+
+
G @a
@x
-
+@x


, 

-
+

-@
+

!
@@ -6234,43 +8277,43 @@ J
G$
`
-
+

@I
-
+
GIǁ 
I@
o
-I@Ip v Gv v Gw  p v Gv v Gw  
-
-kW Rk@4P `gP "k@IP rk\P 
-
+I@Ip v Gv v Gw  p v Gv v Gw  
+
+kW Rk
+ȿ

r
-H
-
+H
+
@I
 `

G `
-x
+@x
 G`HR@
`"@
-
+
 b

2 x
-B 
- 
+B 
+ @



-
+
ǁ
c
-
+

@@ -6280,31 +8323,37 @@ G `
@I  ^ G \ G Z 
-I
+I
-
-
+
+
I
@
QGbɑ@I2
QHbIb P PCII b
-
-Q RIc P PCII ?Hba  t
+
+Q RIc P PCII G  B 
+
+G LI B HbBx   a  t
+
x @
 ɀ
-ɱ
+ɱ
-
+

GIǁ a
O
I@I

-
-@Lr@ǁ
+
+@Lr@ǁ
+`
+H
+
I

@a
@@ -6313,7 +8362,7 @@ I
L
H2X
 
-
+
 Ɂ x
@@ -6332,7 +8381,7 @@ H
 a #
HJ ! "
  !
- G
+ G

A Q@
G
@@ -6352,14 +8401,14 @@ G
-
+


I 
-I 
-
+I 
+
AL"CLh @
-
+
(
x (h
@@ -6383,7 +8432,7 @@ i

I
A@_`
-
+@~
A@
@@ -6416,9 +8465,9 @@ E<B
E===  E DL>L
b
-D@ @
-
-x HR& b@I"@J@Hb
+D@ @
+
+x HR& b@I"@J@Hb
 @
I`
x `
@@ -6916,7 +8965,7 @@ HCP HCX "@Ir
C C @ Ir
C
C 3
-C C B LCH
+C C B LCH
 @
I`
@/y `
@@ -7352,13 +9401,117 @@ H
*AL+CLh j@
j
-
-I
+
+I@
+
v
G
-2x
+@2x
 Ha
-
+
+@2x U
+IL
+
+
+
+x
+
+@ x Z
+@
+G2
+
+
+A
+
+
+x
+
+
+
+
+H
+ .
+ta
+ -
+
+0
+G7
+mW Bl0P mJP n
+
+HR
+ II
+
+
+
+
+@Lr@ǁ
+
+@x
+I
+
+
+
+ 
+
+x 
+H@
+ 
+@
+H
+
+@|
+
+@d
+
+ A
+E
+V
+1@D!D A 
+1@D!H DA 
+1@D!L  E)
+ , 
+E A 
+$E
+4XA 
+F A 
+$G
+4XFA 
+H A 
+""$EH
+#4#X
+`
+x
+
+$@
+$@
+Q
+& @x
+
+Q
+
+M3@
+M AH a   t
+
+
+
+
+2a
+-Iȁ
+
+
+Ā`
+!x
+U
+T%H @ID
+T%H @ID
+T%H @ID
+U
+I@
+v
+G
+@2x
+ Ha
+
@2x U@
IL
@@ -7372,87 +9525,269 @@ IL

A
-
-
+
+
x


-
+
H
 .
ta
 -
-_x
-
+px
+0
G7
-mW Bl
-
+mW Bl
+
HR
II
-@Lr@ǁ
+@Lr@ǁ
-@x
+@x
I
-
+
-
- @}
-
-
+
+ 
x 
H@
 
-@
+@
H
-
-@}
-
-@_
-
+
+@
+
+@b
+
 A
-E
-Q
- , 
-D
-FA 
-
-
-A  * 1@1
-$A
-4X
-Q
-@
-
-!
-Q
- F
-F@q@x F F
-F@FF @x F F
-
- J`
-F" I
-F" I
-@x D!H EP
- H
-
-D
-@@ D $L
+E
+T
+1@D!D A 
+1@D!H DA 
+1@D!L  E)
+ , 
+E A 
+$E
+4XA 
+F A 
+$G
+4XFA 
+H A 
+""$EH
+#4#X
+`
+x
+
+$@
+$@
+Q
+
+
+Q
+
M3
-M AH a   t
-
-
+M AH a   t
+
+

2a
--Iȁ
-@L3
-
+-Iȁ
+@L3
+Ā`
+!x
+U
+T%H @ID
+T%H @ID
+T%H @ID
+U
+
+
+
+
+
+
+
+:x
+G @a
+
+@x
+
+
+
+, 
+ 
+
+
+@
+
+!
+
+
+J 
+
+
+, !
+
+ G$
+`
+
+
+
+
+@I
+
+o
+I@Ip v Gv v Gw  p v Gv v Gw  
+
+
+
+k@W F
+
+
+r
+H
+
+@I
+ `
+
+G `
+
+ G`HR@
+`"@
+
+
+ b
+
+2 x
+B 
+ @
+
+
+
+
+
+
+@c
+
+
+
+
+
+J`
+
+
+
+ @I ^ G \ G Z 
+I
+
+
+
+I
+
+QGbɑ@I2
+QHbIb P PCII b
+
+Q RIc P PCII ?Hba  t
+
+\
+
+GIǁ a
+O
+I@I
+
+
+
+
+
+
+>G
+
+
+x QL FLBL
+@Lr@ǁ
+?I H
+I HR
+ I  Ix  I  I  
+
+L
+H2X
+ 
+
+
+
+
+
+
+
+
+
+
+
+AL"CLh ޘ@
+
+
+
+
+
+
+
+
+
+@x  a
+
+I
+A@_`
+T@ GL ~ 
+U
+
+
+A@
+
+
+
+
+
+
+s s Eg
+
+a
+
+
+L@a
+
+
+
+E@a
+@
+L
+
+D
+GIǁ 
+I@
+   !
+<Ȁa
+E<B
+
+B
+
+ =
+E===  E DL>L
+b
+
+D@ @
+
+@x HR& b@I"@J@Hb
+
+
3
 
@@ -7516,7 +9851,7 @@ Ga
H  G
G@
`
-@x `
+@x M`
x
x vG`
@x
@@ -7686,12 +10021,12 @@ GuuG
@b
-
+ x 2 
<
-@x @
-@x  "
+
+
J 
@b
@@ -7699,7 +10034,7 @@ J 

-J
+J


@@ -7709,38 +10044,38 @@ J


-
+

-
-
-@~ G . G. GGs$$
+@~ 
+
+~ G . G. GGs$$
o
-
-
+
+

-H
- $ɀ
-@Ip p  QIs Q #G)!D G)d
+H
+ $@
+@I QIs Q #G)!D G)d
Q;!
-
-
-
-~ 
+
+
+
+
-
+
G," ,@a
-QI
+QI
Q
?
-R1y P,*(I0 (
+R
-
+
N" $
> ?L ?LIB
@@ -7756,34 +10091,34 @@ G
`

-Iʡ
+Iʡ

@ I ȁ
-@x 
+x 
w
-Jx
+Jx
-z~
+z~
-x~
+

A
b
-x G
+x G

-Gǡ@ʡ
-m~ i # +#L
+Gǡ@ʡ
+
G
-
+

+0
-/R
- 
-
+/R
+ 
+
G#
#
q@) #q s 
@@ -7850,12 +10185,12 @@ G$)
G
 
S&
-I
+
*
$ @o
-&I@
+&I@

,
@@ -7881,22 +10216,22 @@ Q
R P 
@ #\ a
L+L
-  
+  
,
} 
I@ `
- ~ I,D b
+ ~ I,D b
@x
-J

+-G%
-!
+!
-J+

-x 
-!
+x 
+!
+
@a
@@ -8102,12 +10437,12 @@ G:G@c
r,s-nuu a u
qs@!
-x t
+x t
~
@@
@@
-
+
}
@@ -8158,7 +10493,7 @@ O
G  @ # 
-G"@  # @
+G"@  # @
L