author | Nanxin 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) |
commit | a6c89e9657159ba7a49d503e99246ebd647e974a (patch) | |
tree | 3e5219aa77267d9ee7259027ac4f7e6629eb8e09 | |
parent | d1ad76720316ef17f6582a1d8b770733567da7b3 (diff) | |
download | media_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>
34 files changed, 17443 insertions, 2413 deletions
@@ -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(¬ify_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(¬ify_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, ¶m); 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 = ¶ 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|OdpaΏpr7
"TvG}i71ȅHZB)!nJj@Pun B< @@ -568,14 +568,14 @@ I G @=# -G"@ 9#@; +G"@ 9#@; - + x @` x @@ -1223,7 +1223,7 @@ J2x 0 ` - + -x @` 5x @@ -1890,14 +1890,1744 @@ J2x 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$Lx0!$L@$N +@ +" +N"HD 2P @x!xA! +@ +`@ + + +` + + +Hzo + +N + + + +GI +O +I@ +I + +o +I@ +I + Rp + + + I`O + + + + + +LJ + + +` +6xG` +G +G + + + +^ +G IGa @ +a +G + + + +` +x + +@ +@ +P @ +x +9 + IG +@ +@ +P @ +x + + +GG + + + + +H`W +x + +HH + + + +*L6L @˂@ +@KK +I + + + +Br@@xr@ + + Gr +Gr + + +G` + + +G +b + + +o +I +H + + + + +G@H +?I ȑ +I a +I I + + + + + + + + + + + +J + +xGGP !@$N +@ +" +N"HD 2P @x!xA! +GG +G +G` + +@ + +@ +H!" + + +I +xF!x +@ + +N + r + + ! RGIba IGa +a + + +"B @x@@ o + +@ +ۆ[@GLa~ ׀ + + +@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./(( +@#xIU + +@ x +@@x U@U5 +`a@ + +U@ + +@V + + +E NNN$"N + +xAd +V U + +E + +G +G +c + +NNN + + +@ +! +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$Lx0!$L@$N +@ +" +N"HD 2P @x!xA! +@ +`@ + + +` + + +Hzo + +N + + + +GI +O +I@ +I + +o +I@ +I + Rp + + + I`O + + + + + +LJ + + +` +6xG` +G +G + + + +^ +G IGa @ +a +G + + + +` +x + +@ +@ +P @ +x +9 + IG +@ +@ +P @ +x + + +GG + + + + +H`W +x + +HH + + + +*L6L @˂@ +@KK +I + + + +Br@@xr@ + + Gr +Gr + + +G` + + +G +b + + +o +I +H + + + + +G@H +?I ȑ +I a +I I + + + + + + + + + + + +J + +xGGP !@$N +@ +" +N"HD 2P @x!xA! +GG +G +G` + +@ + +@ +H!" + + +I +xF!x +@ + +N + r + + ! RGIba +a + + +"B @x@@ o + +@ +ۆ[@GLa~ ׀ + + +@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./(( +@#xIU + +@ x +@@x U@U5 +`a@ + +U@ + +@V + + +E NNN$"N + +xAd +V U + +E + +G +G +c + +NNN + + +@ +! +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 + +xxo + + +@x + +2 + +(GG$$"$" + +<L + + +@B + + +BD HAd + +` + + +` + +X ȃ +, + +q@BD HH@d + +x + + +@ +HA + + + +ȃ X + +x!GG +G$Lx0!$L@$N +@ +" +N"HD 2P @x!xA! + +`@ + + +` + + +HRo + +N + + + +GI +O +I@ +I + +o +I@ +I + Rp + + + I`O + + + + + +LJ + + +6xG` +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 + +@xGGP !@$N +@ +" +N"HD 2P @x!xA! +GG +G +G` + +@ + +@ +H!" + + +I +xF!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./(( +"xIU + +@ x +@@x U@U5 +`a@ + +U@ + +@V + + +E NNN$"N + xAd +V U +x +E + +G +G +c + +NNN + + +@ +! +G + + + +@1x +x +AH2: BAHB8 IBHB0 B +AAH"< J"` BH" CH AH< IAH8 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< IH@ +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 +! +~ +xI + +@ + ` +x ++@ +xI + +@ + ` +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 +LHLHLLMHMMHMNHN
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 +x1! + + + +J` +J` + + +@1x + +AH2: BAHB8 IBHB0 B +AAH"< J"` BH" CH AH< IAH8 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< IH@ +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 +! +~ +xI + +@ + ` +x ++@ +xI + +@ + ` +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 +LHLHLLMHMMHMNHN
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 +x1! + + + +J` +J` + + +@z + + +s@ +JAHR0 AH! IAH! AHB8 IAH0 @ + +A@ +J> +AAAAJ< +A"@@@AH> ` + + + + + +AH> + +H +@s@@y +x + +H22 IH0 H + + +J +s@AHR0 AH! AH! IAAH0 K@ + +A@ +J> +AAAAJ< +A"@@@@I + + + + + + +@ +I + +IAH> +@ + + + + +I +AH0 H. @AH> H< H: + + + + + +x
GK` + + + +@A +C +C @ +C O +C C + +` + + +J +@ +ʀ + + +xNCh @xNC@ xNCH @xNCP +K@ + x
@ x
x
@I + +K@ + +` +JB@Jb@H + +@xNb@ +N@I + + +\ + +A> + +@b + + +xM@Q +S$S$AL +S + +@@AH> + + + + + + @ P + +AH! IAH! AH> +H< AH> @ +H$ H AH6 @ + + +A ` + +A ` +xAH! IAH! AH! AH! AH> +PI +J +` +x +A> @ +AH0 AHR6 H4 HR* AHB8 HB0 +AHB8 AHR6 HR, HR" +IIIb IIbI@ +IIIR IIRI +II +@1x +@6y + + s@3b + + +s@ +HB +J +s@AH> H< IH26 H4 H2 + +@ + +x@ I@H AH> @ + + + + + +## $@xI$AH> #H< a +#@ $I$AH> b +H + + +s@ +x + + + + + + + + + +` + +xI +Ib + + + + +H +H + +@Jo + + + +x + + +x +@x +|x + +> +Hr + + +s@ +Ju +s@ + +HB +Jm +s@% +I&@x &@ + +J@ɑ &H& + +ȁ @ +I + a + +J@ɑ 'AH> @a +
@ +xJ +@ + +x +HH +J@ɑ AH> AH> + + +' + +AAH> b +IbT I(` + +@ + +/I + +Al +( @ + +@a +I + +(I(I + + {DH2@ + + + + +@ + +#I+ $+I$x+AH> a +I+ + +(@a +H+ +@x +#` +@x + + +@ AH +@% +{ + +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 +xI.I +! + +! +J J +@xBX H` +xBP ` + +! +JH H@ +JH +JH JH +A1 + + + xI +@ +ɀ +A + ` +x +
+ xI +@ +ɀ +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 Ѐ + +; +; +bI@@ +%A#$AdIA +# +@#A + +$ J + + +f9&Y + + + + + + +a @樀 + +W + + + +$$f +$"x + +=` + +)x= ! d& +d +% +@x +$$$$$ + + +$A$> $ +#Dc/ + +c +d! + +Q f9@ +@xe<&a +d)e +xIa +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@ + JAHR0 AH! IAH! AHB8 IAH0 @ 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! IAAH0 K@ A@ J> AAAAJ< -A"@@@@I +A"@@@I - +@w s@ FI> o - +@ I@@ I AH> K ` - - + + I - + IAH> - - - - - -I +@ + + + + +@I AH0 H. @AH> H< H: -M -@?s@y + +@s@ - + x
GK` @@ -1969,15 +3699,15 @@ J xNCh @xNC@ xNCH @xNCP K@ - x
@ x
x
I + x
@ x
x
K@ ` -JB@Jb@H +JB@Jb@H @xNb@ -N@I +N@@I \ @@ -1989,14 +3719,13 @@ N@I xM@Q S$S$AL -S - +S + @@AH> - + - - + @ P @@ -2004,53 +3733,53 @@ S H< AH> @ H$ H AH6 @ -X +X A ` - + A ` xAH! IAH! AH! AH! AH> -@KI +KI 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> @ + - + - -!! "@xI"AH> !H< a -! + +## $@xI$AH> #H< a +#@
$I$AH> b H - -s@ + +s@ x - + - - + + @@ -2060,225 +3789,224 @@ xI 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 xJ @ - + x HH J@ɑ AH> AH> - - -% + + +' AAH> 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 + @ AH -@# - - +@% +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 -xI,I -! +@x + + +@ +@ + + + + + +I.H2 + + +x +xI.I +! -! -J J +! +J J @xBX H` xBP ` -! +! JH H@ JH -JH JH -A1 - - -p} -xI - -@ +JH JH +A1 + + + xI +@ +ɀ +A ` -x -@ -xI - -@ +x +
+ xI +@ +ɀ +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@ @xe<&a d)e xIa 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@ JAHR0 AH! IAH! AHB8 IAH0 @ 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! IAAH0 K@ A@ J> AAAAJ< -A"@@@ +A"@@@ -{ s@ +| s@ FI> o -@ @I@ @I AH> K ` +@ @I@ @I AH> K ` - - + + I - + IAH> - - - - - -I +@ + + + + +I AH0 H. @AH> H< H: -M - + +@Fs@y - + x
GK` @@ -2495,15 +4221,15 @@ J xNCh @xNC@ xNCH @xNCP K@ - x
@ x
x
@I + x
@ x
x
I K@ ` -JB@Jb@H +JB@Jb@H @xNb@ -N@I +N@I \ @@ -2515,14 +4241,13 @@ N@I xM@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 - - + + -xIHAH> @ +xIH AH> @ - -!! "@xI"AH> !H< a -! "@I"AH> b + +## $@xI$AH> #H< a +# $@I$AH> b H - -s@y + + x - + - - + + @@ -2586,227 +4311,227 @@ xI 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 xJ @ - + x HH J@ɑ AH> AH> - - -% + + +' AAH> 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 + @ AH -@# -| - +@% + + 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 -xI,I -! +@x + + +@ +@ + + + + + +I.H2 + + +x +xI.I +! -! -J J +! +J J @xBX H` xBP ` -! +! JH H@ JH -JH JH -A1 - - - -xI - -@ +JH JH +A1 + + + xI +@ +ɀ +A ` -x -@ -xI - -@ +x +
+ xI +@ +ɀ +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 +; +; bI@ %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@ @xe<&a d)e xIa 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 @@ J2x 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> ` xAH> 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 xJ
" $ - -A1 -@ - + +A1 +@ +~ ((+@Q R PPCH @@ -5849,7 +7571,7 @@ H @H H2@"@H ` -P/D +P/F H@ H0 @@ -5864,33 +7586,353 @@ bI@@ b +" -+.[ ++.[ -a .
AB+@+ - -@U - -!+A/ - +a .
AB+@+@ + +@U + +!+A/ + -,@l@! - +,@l! + + o 00 0 x1! - + -J` JJ` - -+@+@ - - - +J` JJ` + ++@+@ + + + +y + +I + +@ + + +H +AH2: ! +h OI +x + +H + II + IAH2: ` + + +AH0 AH! I + +J +AH> ` +xAH> +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@ + + +xHAAAH 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 + +xJ
" +$ + + +A1 +@ +}~ +((+@Q R PPCH + + +2@@I +@ F> +o + + +xJ +- + +?AH0 ˂@ɂ@ ʀ +` + +-AH> + + + +?AH0 ˂@ɂ@ +
x + + +V AHb4 b@ bH H2 P T B + +@AH> +F AH"< "B AH> @ 2l ˷ aF + + + + + +? + +? + + +? + +? +@ + +` + + + + + +H @H + I +@xI + +@a + I +b +IB +@ + +` + + + + + +H2@"@H +` + +P/@: +H@ + +H0 + + +H0 + +H? "P +@bA˷ aF + +b ++" ++.[ + +a .
AB+@+@ + +a + +!+A/ + + + +,@l! + + +o + + 00 + +0 +x1! + + + +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> ` xAH> 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 xJ
" $ - -A1 -@ -@~ + +A1 +@ + ((+@Q R PPCH @@ -6169,7 +8211,7 @@ H @H H2@"@H ` -P/D +P/F H@ H0 @@ -6184,44 +8226,45 @@ bI@@ b +" -+.[ ++.[ -a .
AB+@+ - -@U - -!+A/ - +a .
AB+@+@ + +@U + +!+A/ + -,@l@! - +,@l! + + o 00 0 x1! - + -J` JJ` +J` JJ` FL CL R@ I` - -xH! - +@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 - -kWRk@4P`gP"k@IPrk\P - +I@Ip v Gv v Gw p v Gv v Gw + +kWRk +ȿ r -H - +H + @I ` G
` -x +@x G`HR@ `"@ - + b 2x -B - +B +@ - + ǁ c - + @@ -6280,31 +8323,37 @@ G
` @I
^ G \ G Z -I +I - - + + I @ QGbɑ@I2 QHbIb P PCIIb - -QRIc P PCII?Hba t + +QRIc P PCIIG
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@ @ - -xHR& b@I"@J@Hb +D@ @ + +xHR& 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 - + +@2xU +IL + + + +x + +@
xZ +@ +G2 + + +A + + +x + + + + +H +. +ta +- + +0 +G7 +mWBl0PmJPn + +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 + @2xU@ IL @@ -7372,87 +9525,269 @@ IL A - - + + x - + H . ta - -_x - +px +0 G7 -mWBl - +mWBl + 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@xF
F -F@FF @xF
F - -
J` -F" I -F" I -@xD!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@WF + + +r +H + +@I + ` + +G
` + + G`HR@ +`"@ + + +b + +2x +B +@ + + + + + + +ǁ +@c + + + + + +J` + + + + @I ^ G \ G Z +I + + + +I + +QGbɑ@I2 +QHbIb P PCIIb + +QRIc P PCII?Hba t + +\ + +GIǁ a +O +I@I + + + + + + +>G + + +xQL FLBL +@Lr@ǁ +?I H +I HR + I Ix I I + +L +H2X + + + + + + + + + + + + +AL"CLh ޘ@ + + + + + + + + + +@xa + +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@ @ + +@xHR& b@I"@J@Hb + + 3 @@ -7516,7 +9851,7 @@ Ga H G G@ ` -@x` +@xM` x
xvG` @x @@ -7686,12 +10021,12 @@ GuuG @b - + x2 < -@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 ? -R1yP,*(I0 ( +R - + N" $ >?L ?LIB @@ -7756,34 +10091,34 @@ G ` -Iʡ +Iʡ @I
ȁ -@x +x w -Jx +Jx -z~ +z~ -x~ + A b -xG +xG -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 RP @#\ a L+L - + , } I@ ` - ~I,Db + ~I,Db @x -J +-G% -! +! -J+ -x -! +x +! + @a @@ -8102,12 +10437,12 @@ G:G@c r,s-nuua u qs@! -xt +xt ~ @@ @@ - + } @@ -8158,7 +10493,7 @@ O G @# -G"@ #@ +G"@ #@ L |