Add 'qcom/opensource/video-driver/' from commit 'd0f80c27eee09bc53817f8cfd085691c88989c7e'
git-subtree-dir: qcom/opensource/video-driver git-subtree-mainline:e44c5532de
git-subtree-split:d0f80c27ee
Change-Id: repo: https://git.codelinaro.org/clo/la/platform/vendor/opensource/video-driver tag: VIDEO.LA.4.0.r2-06100-lanai.0
This commit is contained in:
commit
f1b172d58b
35
qcom/opensource/video-driver/Android.bp
Normal file
35
qcom/opensource/video-driver/Android.bp
Normal file
@ -0,0 +1,35 @@
|
||||
headers_src = [
|
||||
"include/uapi/*/**/*.h",
|
||||
]
|
||||
|
||||
video_headers_out = [
|
||||
"vidc/media/v4l2_vidc_extensions.h",
|
||||
]
|
||||
|
||||
video_kernel_headers_verbose = "--verbose "
|
||||
genrule {
|
||||
name: "qti_generate_video_kernel_headers",
|
||||
tools: ["headers_install.sh",
|
||||
"unifdef"
|
||||
],
|
||||
tool_files: [
|
||||
"video_kernel_headers.py",
|
||||
],
|
||||
srcs: headers_src,
|
||||
cmd: "python3 -u $(location video_kernel_headers.py) " +
|
||||
video_kernel_headers_verbose +
|
||||
"--header_arch arm64 " +
|
||||
"--gen_dir $(genDir) " +
|
||||
"--video_include_uapi $(locations include/uapi/*/**/*.h) " +
|
||||
"--unifdef $(location unifdef) " +
|
||||
"--headers_install $(location headers_install.sh)",
|
||||
out: video_headers_out,
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "qti_video_kernel_uapi",
|
||||
generated_headers: ["qti_generate_video_kernel_headers"],
|
||||
export_generated_headers: ["qti_generate_video_kernel_headers"],
|
||||
vendor: true,
|
||||
recovery_available: true
|
||||
}
|
51
qcom/opensource/video-driver/Android.mk
Normal file
51
qcom/opensource/video-driver/Android.mk
Normal file
@ -0,0 +1,51 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
TARGET_VIDC_ENABLE := false
|
||||
ifeq ($(TARGET_KERNEL_DLKM_DISABLE), true)
|
||||
ifeq ($(TARGET_KERNEL_DLKM_VIDEO_OVERRIDE), true)
|
||||
TARGET_VIDC_ENABLE := true
|
||||
endif
|
||||
else
|
||||
TARGET_VIDC_ENABLE := true
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_VIDC_ENABLE),true)
|
||||
VIDEO_BLD_DIR := $(shell pwd)/vendor/qcom/opensource/video-driver
|
||||
VIDEO_SELECT := CONFIG_MSM_VIDC_V4L2=m
|
||||
|
||||
# Build msm_video.ko
|
||||
###########################################################
|
||||
# This is set once per LOCAL_PATH, not per (kernel) module
|
||||
KBUILD_OPTIONS := VIDEO_ROOT=$(VIDEO_BLD_DIR)
|
||||
|
||||
KBUILD_OPTIONS += $(VIDEO_SELECT)
|
||||
|
||||
KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS=$(shell pwd)/$(call intermediates-dir-for,DLKM,mmrm-module-symvers)/Module.symvers
|
||||
KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS+=$(shell pwd)/$(call intermediates-dir-for,DLKM,hw-fence-module-symvers)/Module.symvers
|
||||
###########################################################
|
||||
|
||||
DLKM_DIR := device/qcom/common/dlkm
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
# For incremental compilation
|
||||
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*)
|
||||
LOCAL_MODULE := msm_video.ko
|
||||
LOCAL_MODULE_KBUILD_NAME := msm_video/msm_video.ko
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||
LOCAL_MODULE_DDK_BUILD := true
|
||||
LOCAL_MODULE_DDK_SUBTARGET_REGEX := "video.*"
|
||||
ifeq ($(TARGET_BOARD_PLATFORM), volcano)
|
||||
LOCAL_MODULE_DDK_SUBTARGET_REGEX := "$(TARGET_BOARD_PLATFORM)_video.*"
|
||||
endif
|
||||
LOCAL_MODULE_KO_DIRS := msm_video/msm_video.ko
|
||||
|
||||
LOCAL_REQUIRED_MODULES := mmrm-module-symvers
|
||||
LOCAL_REQUIRED_MODULES += hw-fence-module-symvers
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(call intermediates-dir-for,DLKM,mmrm-module-symvers)/Module.symvers
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES += $(call intermediates-dir-for,DLKM,hw-fence-module-symvers)/Module.symvers
|
||||
|
||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||
endif
|
73
qcom/opensource/video-driver/BUILD.bazel
Normal file
73
qcom/opensource/video-driver/BUILD.bazel
Normal file
@ -0,0 +1,73 @@
|
||||
load("//build/kernel/kleaf:kernel.bzl", "ddk_headers")
|
||||
|
||||
package(
|
||||
default_visibility = [
|
||||
"//visibility:public"],
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "uapi_headers",
|
||||
hdrs = glob([
|
||||
"include/uapi/vidc/media/*.h",
|
||||
]),
|
||||
includes = ["include/uapi/vidc"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "pineapple_headers",
|
||||
hdrs = glob([
|
||||
"driver/platform/pineapple/inc/*.h",
|
||||
]),
|
||||
includes = ["driver/platform/pineapple/inc"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "cliffs_headers",
|
||||
hdrs = glob([
|
||||
"driver/platform/cliffs/inc/*.h",
|
||||
]),
|
||||
includes = ["driver/platform/cliffs/inc"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "iris33_headers",
|
||||
hdrs = glob([
|
||||
"driver/variant/iris33/inc/*.h",
|
||||
]),
|
||||
includes = ["driver/variant/iris33/inc"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "iris2_headers",
|
||||
hdrs = glob([
|
||||
"driver/variant/iris2/inc/*.h",
|
||||
]),
|
||||
includes = ["driver/variant/iris2/inc"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "volcano_headers",
|
||||
hdrs = glob([
|
||||
"driver/platform/volcano/inc/*.h",
|
||||
]),
|
||||
includes = ["driver/platform/volcano/inc"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "vidc_headers",
|
||||
hdrs = glob([
|
||||
"driver/vidc/inc/*.h",
|
||||
"driver/variant/common/inc/*.h",
|
||||
"driver/platform/common/inc/*.h"
|
||||
]),
|
||||
includes = ["driver/vidc/inc", "driver/variant/common/inc", "driver/platform/common/inc"]
|
||||
)
|
||||
|
||||
ddk_headers(
|
||||
name = "video_driver_headers",
|
||||
# hdrs = [":pineapple_configs", "uapi_headers", "pineapple_headers", "iris33_headers", "vidc_headers"]
|
||||
hdrs = [":uapi_headers", "pineapple_headers", "cliffs_headers", "iris33_headers", "volcano_headers", "iris2_headers", "vidc_headers"]
|
||||
)
|
||||
|
||||
load(":target.bzl", "define_target_modules")
|
||||
define_target_modules()
|
1
qcom/opensource/video-driver/Kbuild
Normal file
1
qcom/opensource/video-driver/Kbuild
Normal file
@ -0,0 +1 @@
|
||||
obj-m := msm_video/ video/
|
30
qcom/opensource/video-driver/Makefile
Normal file
30
qcom/opensource/video-driver/Makefile
Normal file
@ -0,0 +1,30 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
VIDEO_COMPILE_TIME = $(shell date)
|
||||
VIDEO_COMPILE_BY = $(shell whoami | sed 's/\\/\\\\/')
|
||||
VIDEO_COMPILE_HOST = $(shell uname -n)
|
||||
VIDEO_GEN_PATH = $(VIDEO_ROOT)/driver/vidc/inc/video_generated_h
|
||||
|
||||
all: modules
|
||||
|
||||
$(VIDEO_GEN_PATH): $(shell find . -type f \( -iname \*.c -o -iname \*.h -o -iname \*.mk \))
|
||||
echo '#define VIDEO_COMPILE_TIME "$(VIDEO_COMPILE_TIME)"' > $(VIDEO_GEN_PATH)
|
||||
echo '#define VIDEO_COMPILE_BY "$(VIDEO_COMPILE_BY)"' >> $(VIDEO_GEN_PATH)
|
||||
echo '#define VIDEO_COMPILE_HOST "$(VIDEO_COMPILE_HOST)"' >> $(VIDEO_GEN_PATH)
|
||||
|
||||
modules: $(VIDEO_GEN_PATH)
|
||||
ln -sf $(VIDEO_ROOT)/driver $(VIDEO_ROOT)/msm_video/driver
|
||||
ln -sf $(VIDEO_ROOT)/driver $(VIDEO_ROOT)/video/driver
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(M) modules $(KBUILD_OPTIONS)
|
||||
rm $(VIDEO_ROOT)/msm_video/driver
|
||||
rm $(VIDEO_ROOT)/video/driver
|
||||
|
||||
modules_install:
|
||||
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(M) modules_install
|
||||
|
||||
%:
|
||||
$(MAKE) -C $(KERNEL_SRC) M=$(M) $@ $(KBUILD_OPTIONS)
|
||||
|
||||
clean:
|
||||
rm -f *.o *.ko *.mod.c *.mod.o *~ .*.cmd Module.symvers
|
||||
rm -rf .tmp_versions
|
1
qcom/opensource/video-driver/config/kalama_video.conf
Normal file
1
qcom/opensource/video-driver/config/kalama_video.conf
Normal file
@ -0,0 +1 @@
|
||||
export CONFIG_MSM_VIDC_KALAMA=y
|
7
qcom/opensource/video-driver/config/kalama_video.h
Normal file
7
qcom/opensource/video-driver/config/kalama_video.h
Normal file
@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_MSM_VIDC_KALAMA 1
|
1
qcom/opensource/video-driver/config/pineapple_video.conf
Normal file
1
qcom/opensource/video-driver/config/pineapple_video.conf
Normal file
@ -0,0 +1 @@
|
||||
export CONFIG_MSM_VIDC_PINEAPPLE=y
|
7
qcom/opensource/video-driver/config/pineapple_video.h
Normal file
7
qcom/opensource/video-driver/config/pineapple_video.h
Normal file
@ -0,0 +1,7 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_MSM_VIDC_PINEAPPLE 1
|
2
qcom/opensource/video-driver/config/volcano_video.conf
Normal file
2
qcom/opensource/video-driver/config/volcano_video.conf
Normal file
@ -0,0 +1,2 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
export CONFIG_MSM_VIDC_VOLCANO=y
|
6
qcom/opensource/video-driver/config/volcano_video.h
Normal file
6
qcom/opensource/video-driver/config/volcano_video.h
Normal file
@ -0,0 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CONFIG_MSM_VIDC_VOLCANO 1
|
@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_CLIFFS_H_
|
||||
#define _MSM_VIDC_CLIFFS_H_
|
||||
|
||||
#include "msm_vidc_core.h"
|
||||
|
||||
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
|
||||
int msm_vidc_init_platform_cliffs(struct msm_vidc_core *core);
|
||||
int msm_vidc_deinit_platform_cliffs(struct msm_vidc_core *core);
|
||||
#else
|
||||
int msm_vidc_init_platform_cliffs(struct msm_vidc_core *core)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int msm_vidc_deinit_platform_cliffs(struct msm_vidc_core *core)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _MSM_VIDC_CLIFFS_H_
|
1757
qcom/opensource/video-driver/driver/platform/cliffs/src/cliffs.c
Normal file
1757
qcom/opensource/video-driver/driver/platform/cliffs/src/cliffs.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,388 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_PLATFORM_H_
|
||||
#define _MSM_VIDC_PLATFORM_H_
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_core.h"
|
||||
|
||||
#define DDR_TYPE_LPDDR4 0x6
|
||||
#define DDR_TYPE_LPDDR4X 0x7
|
||||
#define DDR_TYPE_LPDDR5 0x8
|
||||
#define DDR_TYPE_LPDDR5X 0x9
|
||||
|
||||
#define UBWC_CONFIG(mc, ml, hbb, bs1, bs2, bs3, bsp) \
|
||||
{ \
|
||||
.max_channels = mc, \
|
||||
.mal_length = ml, \
|
||||
.highest_bank_bit = hbb, \
|
||||
.bank_swzl_level = bs1, \
|
||||
.bank_swz2_level = bs2, \
|
||||
.bank_swz3_level = bs3, \
|
||||
.bank_spreading = bsp, \
|
||||
}
|
||||
|
||||
#define EFUSE_ENTRY(sa, s, m, sh, p) \
|
||||
{ \
|
||||
.start_address = sa, \
|
||||
.size = s, \
|
||||
.mask = m, \
|
||||
.shift = sh, \
|
||||
.purpose = p \
|
||||
}
|
||||
|
||||
extern u32 vpe_csc_custom_matrix_coeff[MAX_MATRIX_COEFFS];
|
||||
extern u32 vpe_csc_custom_bias_coeff[MAX_BIAS_COEFFS];
|
||||
extern u32 vpe_csc_custom_limit_coeff[MAX_LIMIT_COEFFS];
|
||||
|
||||
struct bw_table {
|
||||
const char *name;
|
||||
u32 min_kbps;
|
||||
u32 max_kbps;
|
||||
};
|
||||
|
||||
struct pd_table {
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct regulator_table {
|
||||
const char *name;
|
||||
bool hw_trigger;
|
||||
};
|
||||
|
||||
struct clk_table {
|
||||
const char *name;
|
||||
u32 clk_id;
|
||||
bool scaling;
|
||||
};
|
||||
|
||||
struct clk_rst_table {
|
||||
const char *name;
|
||||
bool exclusive_release;
|
||||
};
|
||||
|
||||
struct subcache_table {
|
||||
const char *name;
|
||||
u32 llcc_id;
|
||||
};
|
||||
|
||||
struct context_bank_table {
|
||||
const char *name;
|
||||
u32 start;
|
||||
u32 size;
|
||||
bool secure;
|
||||
bool dma_coherant;
|
||||
u32 region;
|
||||
u64 dma_mask;
|
||||
};
|
||||
|
||||
struct freq_table {
|
||||
unsigned long freq;
|
||||
};
|
||||
|
||||
struct reg_preset_table {
|
||||
u32 reg;
|
||||
u32 value;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
struct device_region_table {
|
||||
const char *name;
|
||||
phys_addr_t phy_addr;
|
||||
u32 size;
|
||||
u32 dev_addr;
|
||||
u32 region;
|
||||
};
|
||||
|
||||
struct msm_vidc_ubwc_config_data {
|
||||
u32 max_channels;
|
||||
u32 mal_length;
|
||||
u32 highest_bank_bit;
|
||||
u32 bank_swzl_level;
|
||||
u32 bank_swz2_level;
|
||||
u32 bank_swz3_level;
|
||||
u32 bank_spreading;
|
||||
};
|
||||
|
||||
struct codec_info {
|
||||
u32 v4l2_codec;
|
||||
enum msm_vidc_codec_type vidc_codec;
|
||||
const char *pixfmt_name;
|
||||
};
|
||||
|
||||
struct color_format_info {
|
||||
u32 v4l2_color_format;
|
||||
enum msm_vidc_colorformat_type vidc_color_format;
|
||||
const char *pixfmt_name;
|
||||
};
|
||||
|
||||
struct color_primaries_info {
|
||||
u32 v4l2_color_primaries;
|
||||
enum msm_vidc_color_primaries vidc_color_primaries;
|
||||
};
|
||||
|
||||
struct transfer_char_info {
|
||||
u32 v4l2_transfer_char;
|
||||
enum msm_vidc_transfer_characteristics vidc_transfer_char;
|
||||
};
|
||||
|
||||
struct matrix_coeff_info {
|
||||
u32 v4l2_matrix_coeff;
|
||||
enum msm_vidc_matrix_coefficients vidc_matrix_coeff;
|
||||
};
|
||||
|
||||
struct msm_platform_core_capability {
|
||||
enum msm_vidc_core_capability_type type;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
struct msm_platform_inst_capability {
|
||||
enum msm_vidc_inst_capability_type cap_id;
|
||||
enum msm_vidc_domain_type domain;
|
||||
enum msm_vidc_codec_type codec;
|
||||
s32 min;
|
||||
s32 max;
|
||||
u32 step_or_mask;
|
||||
s32 value;
|
||||
u32 v4l2_id;
|
||||
u32 hfi_id;
|
||||
enum msm_vidc_inst_capability_flags flags;
|
||||
};
|
||||
|
||||
struct msm_platform_inst_cap_dependency {
|
||||
enum msm_vidc_inst_capability_type cap_id;
|
||||
enum msm_vidc_domain_type domain;
|
||||
enum msm_vidc_codec_type codec;
|
||||
enum msm_vidc_inst_capability_type children[MAX_CAP_CHILDREN];
|
||||
int (*adjust)(void *inst, struct v4l2_ctrl *ctrl);
|
||||
int (*set)(void *inst, enum msm_vidc_inst_capability_type cap_id);
|
||||
};
|
||||
|
||||
struct msm_vidc_compat_handle {
|
||||
const char *compat;
|
||||
int (*init_platform)(struct msm_vidc_core *core);
|
||||
int (*init_iris)(struct msm_vidc_core *core);
|
||||
};
|
||||
|
||||
struct msm_vidc_csc_coeff {
|
||||
u32 *vpe_csc_custom_matrix_coeff;
|
||||
u32 *vpe_csc_custom_bias_coeff;
|
||||
u32 *vpe_csc_custom_limit_coeff;
|
||||
};
|
||||
|
||||
struct msm_vidc_efuse_data {
|
||||
u32 start_address;
|
||||
u32 size;
|
||||
u32 mask;
|
||||
u32 shift;
|
||||
enum efuse_purpose purpose;
|
||||
};
|
||||
|
||||
struct msm_vidc_format_capability {
|
||||
struct codec_info *codec_info;
|
||||
u32 codec_info_size;
|
||||
struct color_format_info *color_format_info;
|
||||
u32 color_format_info_size;
|
||||
struct color_primaries_info *color_prim_info;
|
||||
u32 color_prim_info_size;
|
||||
struct transfer_char_info *transfer_char_info;
|
||||
u32 transfer_char_info_size;
|
||||
struct matrix_coeff_info *matrix_coeff_info;
|
||||
u32 matrix_coeff_info_size;
|
||||
};
|
||||
|
||||
enum vpu_version {
|
||||
VPU_VERSION_IRIS33 = 1,
|
||||
VPU_VERSION_IRIS33_2P, // IRIS3 2 PIPE
|
||||
VPU_VERSION_IRIS2_2P, // IRIS2 2 PIPE
|
||||
};
|
||||
|
||||
struct msm_vidc_platform_data {
|
||||
const struct bw_table *bw_tbl;
|
||||
unsigned int bw_tbl_size;
|
||||
const struct regulator_table *regulator_tbl;
|
||||
unsigned int regulator_tbl_size;
|
||||
const struct pd_table *pd_tbl;
|
||||
unsigned int pd_tbl_size;
|
||||
const char * const *opp_tbl;
|
||||
unsigned int opp_tbl_size;
|
||||
const struct clk_table *clk_tbl;
|
||||
unsigned int clk_tbl_size;
|
||||
const struct clk_rst_table *clk_rst_tbl;
|
||||
unsigned int clk_rst_tbl_size;
|
||||
const struct subcache_table *subcache_tbl;
|
||||
unsigned int subcache_tbl_size;
|
||||
const struct context_bank_table *context_bank_tbl;
|
||||
unsigned int context_bank_tbl_size;
|
||||
struct freq_table *freq_tbl;
|
||||
unsigned int freq_tbl_size;
|
||||
const struct reg_preset_table *reg_prst_tbl;
|
||||
unsigned int reg_prst_tbl_size;
|
||||
const struct device_region_table *dev_reg_tbl;
|
||||
unsigned int dev_reg_tbl_size;
|
||||
struct msm_vidc_ubwc_config_data *ubwc_config;
|
||||
const char *fwname;
|
||||
u32 pas_id;
|
||||
bool supports_mmrm;
|
||||
struct msm_platform_core_capability *core_data;
|
||||
u32 core_data_size;
|
||||
struct msm_platform_inst_capability *inst_cap_data;
|
||||
u32 inst_cap_data_size;
|
||||
struct msm_platform_inst_cap_dependency *inst_cap_dependency_data;
|
||||
u32 inst_cap_dependency_data_size;
|
||||
struct msm_vidc_csc_coeff csc_data;
|
||||
struct msm_vidc_efuse_data *efuse_data;
|
||||
unsigned int efuse_data_size;
|
||||
unsigned int sku_version;
|
||||
unsigned int vpu_ver;
|
||||
struct msm_vidc_format_capability *format_data;
|
||||
const u32 *psc_avc_tbl;
|
||||
unsigned int psc_avc_tbl_size;
|
||||
const u32 *psc_hevc_tbl;
|
||||
unsigned int psc_hevc_tbl_size;
|
||||
const u32 *psc_vp9_tbl;
|
||||
unsigned int psc_vp9_tbl_size;
|
||||
const u32 *psc_av1_tbl;
|
||||
unsigned int psc_av1_tbl_size;
|
||||
const u32 *dec_input_prop_avc;
|
||||
unsigned int dec_input_prop_size_avc;
|
||||
const u32 *dec_input_prop_hevc;
|
||||
unsigned int dec_input_prop_size_hevc;
|
||||
const u32 *dec_input_prop_vp9;
|
||||
unsigned int dec_input_prop_size_vp9;
|
||||
const u32 *dec_input_prop_av1;
|
||||
unsigned int dec_input_prop_size_av1;
|
||||
const u32 *dec_output_prop_avc;
|
||||
unsigned int dec_output_prop_size_avc;
|
||||
const u32 *dec_output_prop_hevc;
|
||||
unsigned int dec_output_prop_size_hevc;
|
||||
const u32 *dec_output_prop_vp9;
|
||||
unsigned int dec_output_prop_size_vp9;
|
||||
const u32 *dec_output_prop_av1;
|
||||
unsigned int dec_output_prop_size_av1;
|
||||
const u32 *msm_vidc_ssr_type;
|
||||
unsigned int msm_vidc_ssr_type_size;
|
||||
|
||||
};
|
||||
|
||||
struct msm_vidc_platform {
|
||||
struct msm_vidc_platform_data data;
|
||||
};
|
||||
|
||||
static inline bool is_sys_cache_present(struct msm_vidc_core *core)
|
||||
{
|
||||
return !!core->platform->data.subcache_tbl_size;
|
||||
}
|
||||
|
||||
static inline bool is_mmrm_supported(struct msm_vidc_core *core)
|
||||
{
|
||||
return !!core->platform->data.supports_mmrm;
|
||||
}
|
||||
|
||||
int msm_vidc_init_platform(struct msm_vidc_core *core);
|
||||
int msm_vidc_read_efuse(struct msm_vidc_core *core);
|
||||
|
||||
/* control framework support functions */
|
||||
|
||||
enum msm_vidc_inst_capability_type msm_vidc_get_cap_id(struct msm_vidc_inst *inst, u32 id);
|
||||
int msm_vidc_update_cap_value(struct msm_vidc_inst *inst, u32 cap,
|
||||
s32 adjusted_val, const char *func);
|
||||
bool is_parent_available(struct msm_vidc_inst *inst, u32 cap_id,
|
||||
u32 check_parent, const char *func);
|
||||
int msm_vidc_get_parent_value(struct msm_vidc_inst *inst, u32 cap, u32 parent,
|
||||
s32 *value, const char *func);
|
||||
u32 msm_vidc_get_port_info(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_v4l2_menu_to_hfi(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_inst_capability_type cap_id, u32 *value);
|
||||
int msm_vidc_v4l2_to_hfi_enum(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_inst_capability_type cap_id, u32 *value);
|
||||
int msm_vidc_packetize_control(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_inst_capability_type cap_id, u32 payload_type,
|
||||
void *hfi_val, u32 payload_size, const char *func);
|
||||
int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_layer_bitrate(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_bitrate_mode(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_entropy_mode(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_profile(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_ltr_count(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_use_ltr(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_mark_ltr(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_delta_based_rc(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_output_order(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_input_buf_host_max_count(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_output_buf_host_max_count(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_transform_8x8(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_chroma_qp_index_offset(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_slice_count(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_layer_count(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_gop_size(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_b_frame(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_peak_bitrate(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_hevc_min_qp(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_hevc_max_qp(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_hevc_i_frame_qp(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_hevc_p_frame_qp(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_hevc_b_frame_qp(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_blur_type(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_blur_resolution(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_brs(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_bitrate_boost(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_min_quality(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_enc_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_dec_lowlatency_mode(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_session_priority(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_roi_info(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_all_intra(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_dec_outbuf_fence_type(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_dec_outbuf_fence_direction(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_dec_slice_mode(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_preprocess(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_eva_stats(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_sei_mastering_disp(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_sei_cll(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_hdr10plus(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_transcoding_stats(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_set_header_mode(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_deblock_mode(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_min_qp(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_max_qp(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_frame_qp(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_req_sync_frame(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_chroma_qp_index_offset(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_slice_count(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_layer_count_and_type(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_gop_size(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_bitrate(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_layer_bitrate(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_u32(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_u32_packed(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_u32_enum(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_constant_quality(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_vbr_related_properties(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_cbr_related_properties(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_use_and_mark_ltr(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_nal_length(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_session_priority(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_flip(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_rotation(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_blur_resolution(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_stage(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_pipe(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_csc_custom_matrix(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_level(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_preprocess(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_reserve_duration(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_q16(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_vui_timing_info(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_outbuf_fence_type(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_outbuf_fence_direction(void *instance, enum msm_vidc_inst_capability_type cap_id);
|
||||
|
||||
#endif // _MSM_VIDC_PLATFORM_H_
|
@ -0,0 +1,268 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_PLATFORM_EXT_H_
|
||||
#define _MSM_VIDC_PLATFORM_EXT_H_
|
||||
|
||||
#include "msm_vidc_control.h"
|
||||
|
||||
/* HEIC encoder and decoder */
|
||||
#define V4L2_PIX_FMT_VIDC_HEIC v4l2_fourcc('H', 'E', 'I', 'C')
|
||||
|
||||
#define V4L2_META_FMT_VIDC v4l2_fourcc('Q', 'M', 'E', 'T')
|
||||
|
||||
#ifndef V4L2_CID_MPEG_VIDC_SECURE
|
||||
#define V4L2_CID_MPEG_VIDC_SECURE (V4L2_CID_MPEG_VIDC_BASE + 0x1)
|
||||
#endif
|
||||
|
||||
#ifndef V4L2_CID_MPEG_VIDC_LOWLATENCY_REQUEST
|
||||
#define V4L2_CID_MPEG_VIDC_LOWLATENCY_REQUEST (V4L2_CID_MPEG_VIDC_BASE + 0x3)
|
||||
#endif
|
||||
|
||||
/* FIXme: */
|
||||
#define V4L2_CID_MPEG_VIDC_CODEC_CONFIG (V4L2_CID_MPEG_VIDC_BASE + 0x4)
|
||||
#define V4L2_CID_MPEG_VIDC_FRAME_RATE (V4L2_CID_MPEG_VIDC_BASE + 0x5)
|
||||
#define V4L2_CID_MPEG_VIDC_OPERATING_RATE (V4L2_CID_MPEG_VIDC_BASE + 0x6)
|
||||
|
||||
#ifndef V4L2_CID_MPEG_VIDC_TIME_DELTA_BASED_RC
|
||||
#define V4L2_CID_MPEG_VIDC_TIME_DELTA_BASED_RC (V4L2_CID_MPEG_VIDC_BASE + 0xD)
|
||||
#endif
|
||||
|
||||
/* Encoder quality controls */
|
||||
#define V4L2_CID_MPEG_VIDC_CONTENT_ADAPTIVE_CODING \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0xE)
|
||||
#define V4L2_CID_MPEG_VIDC_QUALITY_BITRATE_BOOST \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0xF)
|
||||
#define V4L2_CID_MPEG_VIDC_VIDEO_BLUR_TYPES \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x10)
|
||||
enum v4l2_mpeg_vidc_blur_types {
|
||||
VIDC_BLUR_NONE = 0x0,
|
||||
VIDC_BLUR_EXTERNAL = 0x1,
|
||||
VIDC_BLUR_ADAPTIVE = 0x2,
|
||||
};
|
||||
|
||||
/* (blur width) << 16 | (blur height) */
|
||||
#define V4L2_CID_MPEG_VIDC_VIDEO_BLUR_RESOLUTION \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x11)
|
||||
/* TODO: jdas: compound control for matrix */
|
||||
#define V4L2_CID_MPEG_VIDC_VIDEO_VPE_CSC_CUSTOM_MATRIX \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x12)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_LTR_MARK_USE_DETAILS \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x13)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_SEQ_HEADER_NAL \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x14)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_DPB_LUMA_CHROMA_MISR \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x15)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_OPB_LUMA_CHROMA_MISR \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x16)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_INTERLACE \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x17)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_CONCEALED_MB_COUNT \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x18)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_HISTOGRAM_INFO \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x19)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_SEI_MASTERING_DISPLAY_COLOUR \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x1A)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_SEI_CONTENT_LIGHT_LEVEL \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x1B)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_HDR10PLUS \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x1C)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_EVA_STATS \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x1D)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_BUFFER_TAG \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x1E)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_SUBFRAME_OUTPUT \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x1F)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_ROI_INFO \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x20)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_TIMESTAMP \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x21)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_ENC_QP_METADATA \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x22)
|
||||
#define V4L2_CID_MPEG_VIDC_MIN_BITSTREAM_SIZE_OVERWRITE \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x23)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_BITSTREAM_RESOLUTION \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x24)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_CROP_OFFSETS \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x25)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_SALIENCY_INFO \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x26)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_TRANSCODE_STAT_INFO \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x27)
|
||||
|
||||
/* Encoder Super frame control */
|
||||
#define V4L2_CID_MPEG_VIDC_SUPERFRAME (V4L2_CID_MPEG_VIDC_BASE + 0x28)
|
||||
/* Thumbnail Mode control */
|
||||
#define V4L2_CID_MPEG_VIDC_THUMBNAIL_MODE (V4L2_CID_MPEG_VIDC_BASE + 0x29)
|
||||
|
||||
/* Priority control */
|
||||
#ifndef V4L2_CID_MPEG_VIDC_PRIORITY
|
||||
#define V4L2_CID_MPEG_VIDC_PRIORITY (V4L2_CID_MPEG_VIDC_BASE + 0x2A)
|
||||
#endif
|
||||
|
||||
/* Metadata DPB Tag List*/
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_DPB_TAG_LIST \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x2B)
|
||||
/* Encoder Input Compression Ratio control */
|
||||
#define V4L2_CID_MPEG_VIDC_ENC_INPUT_COMPRESSION_RATIO \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x2C)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_DEC_QP_METADATA \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x2E)
|
||||
|
||||
/* Encoder Complexity control */
|
||||
#ifndef V4L2_CID_MPEG_VIDC_VENC_COMPLEXITY
|
||||
#define V4L2_CID_MPEG_VIDC_VENC_COMPLEXITY \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x2F)
|
||||
#endif
|
||||
|
||||
/* Decoder Max Number of Reorder Frames */
|
||||
#ifndef V4L2_CID_MPEG_VIDC_METADATA_MAX_NUM_REORDER_FRAMES
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_MAX_NUM_REORDER_FRAMES \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x30)
|
||||
#endif
|
||||
|
||||
/* Control IDs for AV1 */
|
||||
#define V4L2_CID_MPEG_VIDC_AV1_PROFILE (V4L2_CID_MPEG_VIDC_BASE + 0x31)
|
||||
enum v4l2_mpeg_vidc_av1_profile {
|
||||
V4L2_MPEG_VIDC_AV1_PROFILE_MAIN = 0,
|
||||
V4L2_MPEG_VIDC_AV1_PROFILE_HIGH = 1,
|
||||
V4L2_MPEG_VIDC_AV1_PROFILE_PROFESSIONAL = 2,
|
||||
};
|
||||
|
||||
#define V4L2_CID_MPEG_VIDC_AV1_LEVEL (V4L2_CID_MPEG_VIDC_BASE + 0x32)
|
||||
enum v4l2_mpeg_vidc_av1_level {
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_2_0 = 0,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_2_1 = 1,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_2_2 = 2,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_2_3 = 3,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_3_0 = 4,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_3_1 = 5,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_3_2 = 6,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_3_3 = 7,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_4_0 = 8,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_4_1 = 9,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_4_2 = 10,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_4_3 = 11,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_5_0 = 12,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_5_1 = 13,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_5_2 = 14,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_5_3 = 15,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_6_0 = 16,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_6_1 = 17,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_6_2 = 18,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_6_3 = 19,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_7_0 = 20,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_7_1 = 21,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_7_2 = 22,
|
||||
V4L2_MPEG_VIDC_AV1_LEVEL_7_3 = 23,
|
||||
};
|
||||
|
||||
#define V4L2_CID_MPEG_VIDC_AV1_TIER (V4L2_CID_MPEG_VIDC_BASE + 0x33)
|
||||
enum v4l2_mpeg_vidc_av1_tier {
|
||||
V4L2_MPEG_VIDC_AV1_TIER_MAIN = 0,
|
||||
V4L2_MPEG_VIDC_AV1_TIER_HIGH = 1,
|
||||
};
|
||||
|
||||
/* Decoder Timestamp Reorder control */
|
||||
#define V4L2_CID_MPEG_VIDC_TS_REORDER (V4L2_CID_MPEG_VIDC_BASE + 0x34)
|
||||
/* AV1 Decoder Film Grain */
|
||||
#define V4L2_CID_MPEG_VIDC_AV1D_FILM_GRAIN_PRESENT \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x35)
|
||||
/* Enables Output buffer fence id via input metadata */
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_OUTBUF_FENCE \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x38)
|
||||
/* Control to set fence id to driver in order get corresponding fence fd */
|
||||
#define V4L2_CID_MPEG_VIDC_SW_FENCE_ID \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x39)
|
||||
/*
|
||||
* Control to get fence fd from driver for the fence id
|
||||
* set via V4L2_CID_MPEG_VIDC_SW_FENCE_ID
|
||||
*/
|
||||
#define V4L2_CID_MPEG_VIDC_SW_FENCE_FD \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x3A)
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_PICTURE_TYPE \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x3B)
|
||||
|
||||
/* Encoder Slice Delivery Mode
|
||||
* set format has a dependency on this control
|
||||
* and gets invoked when this control is updated.
|
||||
*/
|
||||
#define V4L2_CID_MPEG_VIDC_HEVC_ENCODE_DELIVERY_MODE \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x3C)
|
||||
|
||||
#define V4L2_CID_MPEG_VIDC_H264_ENCODE_DELIVERY_MODE \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x3D)
|
||||
|
||||
#define V4L2_CID_MPEG_VIDC_CRITICAL_PRIORITY \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x3E)
|
||||
#define V4L2_CID_MPEG_VIDC_RESERVE_DURATION \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x3F)
|
||||
|
||||
#define V4L2_CID_MPEG_VIDC_METADATA_DOLBY_RPU \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x40)
|
||||
|
||||
#define V4L2_CID_MPEG_VIDC_CLIENT_ID \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x41)
|
||||
|
||||
#define V4L2_CID_MPEG_VIDC_LAST_FLAG_EVENT_ENABLE \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x42)
|
||||
|
||||
#ifndef V4L2_CID_MPEG_VIDC_VUI_TIMING_INFO
|
||||
#define V4L2_CID_MPEG_VIDC_VUI_TIMING_INFO \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x43)
|
||||
#endif
|
||||
|
||||
#define V4L2_CID_MPEG_VIDC_EARLY_NOTIFY_ENABLE \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x44)
|
||||
|
||||
#define V4L2_CID_MPEG_VIDC_EARLY_NOTIFY_LINE_COUNT \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x45)
|
||||
|
||||
/*
|
||||
* This control is introduced to overcome v4l2 limitation
|
||||
* of allowing only standard colorspace info via s_fmt.
|
||||
* v4l_sanitize_colorspace() is introduced in s_fmt ioctl
|
||||
* to reject private colorspace. Through this control, client
|
||||
* can set private colorspace info and/or use this control
|
||||
* to set colorspace dynamically.
|
||||
* The control value is 32 bits packed as:
|
||||
* [ 0 - 7] : matrix coefficients
|
||||
* [ 8 - 15] : transfer characteristics
|
||||
* [16 - 23] : colour primaries
|
||||
* [24 - 31] : range
|
||||
* This control is only for encoder.
|
||||
* Currently g_fmt in v4l2 does not santize colorspace,
|
||||
* hence this control is not introduced for decoder.
|
||||
*/
|
||||
#define V4L2_CID_MPEG_VIDC_SIGNAL_COLOR_INFO \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x46)
|
||||
|
||||
/* control to enable csc */
|
||||
#define V4L2_CID_MPEG_VIDC_CSC \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x47)
|
||||
|
||||
#define V4L2_CID_MPEG_VIDC_DRIVER_VERSION \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x48)
|
||||
|
||||
#define V4L2_CID_MPEG_VIDC_GRID_WIDTH \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x49)
|
||||
|
||||
#define V4L2_CID_MPEG_VIDC_MAX_NUM_REORDER_FRAMES \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x4A)
|
||||
|
||||
#define V4L2_CID_MPEG_VIDC_INTERLACE \
|
||||
(V4L2_CID_MPEG_VIDC_BASE + 0x4B)
|
||||
|
||||
int msm_vidc_adjust_ir_period(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_dec_frame_rate(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_dec_operating_rate(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_adjust_delivery_mode(void *instance, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_set_ir_period(void *instance,
|
||||
enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_set_signal_color_info(void *instance,
|
||||
enum msm_vidc_inst_capability_type cap_id);
|
||||
int msm_vidc_adjust_csc(void *instance, struct v4l2_ctrl *ctrl);
|
||||
|
||||
#endif
|
@ -0,0 +1,240 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _PERF_STATIC_MODEL_H_
|
||||
#define _PERF_STATIC_MODEL_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Reordered CODECS to match Bitrate Table rows */
|
||||
#define CODEC_H264_CAVLC 0
|
||||
#define CODEC_H264 1
|
||||
#define CODEC_HEVC 2
|
||||
#define CODEC_VP9 3
|
||||
#define CODEC_AV1 4
|
||||
|
||||
#define CODEC_BSE_FrameFactor 0
|
||||
#define CODEC_BSE_MBFactor 1
|
||||
#define CODEC_BSE_LUC_SIZE 2
|
||||
|
||||
#define CODEC_GOP_IPP 0
|
||||
#define CODEC_GOP_IbP 1
|
||||
#define CODEC_GOP_I1B2b1P 2
|
||||
#define CODEC_GOP_I3B4b1P 3
|
||||
#define CODEC_GOP_PONLY 4
|
||||
#define CODEC_GOP_bONLY 5
|
||||
#define CODEC_GOP_BONLY 6
|
||||
#define CODEC_GOP_IONLY 7
|
||||
|
||||
#define CODEC_ENCODER_GOP_Bb_ENTRY 0
|
||||
#define CODEC_ENCODER_GOP_P_ENTRY 1
|
||||
#define CODEC_ENCODER_GOP_FACTORY_ENTRY 2
|
||||
|
||||
#define CODEC_ENTROPY_CODING_CAVLC 0
|
||||
#define CODEC_ENTROPY_CODING_CABAC 1
|
||||
|
||||
#define CODEC_VSPVPP_MODE_1S 1
|
||||
#define CODEC_VSPVPP_MODE_2S 2
|
||||
|
||||
#define COMP_SETTING_PWC 0
|
||||
#define COMP_SETTING_AVG 1
|
||||
#define COMP_SETTING_POWER 2
|
||||
|
||||
#define CODEC_BITDEPTH_8 8
|
||||
#define CODEC_BITDEPTH_10 10
|
||||
|
||||
#define ENCODE_YUV 0
|
||||
#define ENCODE_RGB 1
|
||||
|
||||
#define COMPLEXITY_PWC 0
|
||||
#define COMPLEXITY_AVG 1
|
||||
#define COMPLEXITY_POWER 2
|
||||
|
||||
#define MAX_LINE 2048
|
||||
#ifndef VENUS_MAX_FILENAME_LENGTH
|
||||
#define VENUS_MAX_FILENAME_LENGTH 1024
|
||||
#endif
|
||||
|
||||
#define CODEC_ENCODER 1
|
||||
#define CODEC_DECODER 2
|
||||
|
||||
#define COMPLEXITY_THRESHOLD 2
|
||||
|
||||
enum chipset_generation {
|
||||
MSM_KONA = 0,
|
||||
MSM_LAHAINA,
|
||||
MSM_WAIPIO,
|
||||
MSM_MAKENA,
|
||||
MSM_KALAMA,
|
||||
MSM_QOGNITION,
|
||||
MSM_PINEAPPLE,
|
||||
MSM_MAX,
|
||||
};
|
||||
|
||||
enum regression_mode {
|
||||
/* ignores client set cr and bitrate settings */
|
||||
REGRESSION_MODE_SANITY = 1,
|
||||
/* cr and bitrate default mode */
|
||||
REGRESSION_MODE_DEFAULT,
|
||||
/* custom mode where client will set cr and bitrate values */
|
||||
REGRESSION_MODE_CUSTOM,
|
||||
};
|
||||
|
||||
/*
|
||||
* If firmware provided motion_vector_complexity is >= 2 then set the
|
||||
* complexity_setting as PWC (performance worst case)
|
||||
* If the motion_vector_complexity is < 2 then set the complexity_setting
|
||||
* as AVG (average case value)
|
||||
*/
|
||||
enum complexity_setting {
|
||||
COMPLEXITY_SETTING_PWC = 0,
|
||||
COMPLEXITY_SETTING_AVG = 1,
|
||||
COMPLEXITY_SETTING_PWR = 2,
|
||||
};
|
||||
|
||||
/*
|
||||
* If firmware provided motion_vector_complexity is >= 2 then set the
|
||||
* refframe_complexity as PWC (performance worst case)
|
||||
* If the motion_vector_complexity is < 2 then set the refframe_complexity
|
||||
* as AVG (average case value)
|
||||
*/
|
||||
enum refframe_complexity {
|
||||
REFFRAME_COMPLEXITY_PWC = 4,
|
||||
REFFRAME_COMPLEXITY_AVG = 2,
|
||||
REFFRAME_COMPLEXITY_PWR = 1,
|
||||
};
|
||||
|
||||
struct api_calculation_input {
|
||||
/*2: decoder; 1: encoder */
|
||||
u32 decoder_or_encoder;
|
||||
|
||||
/* enum chipset_generation */
|
||||
u32 chipset_gen;
|
||||
|
||||
u32 codec;
|
||||
u32 lcu_size;
|
||||
u32 pipe_num;
|
||||
u32 frame_rate;
|
||||
u32 frame_width;
|
||||
u32 frame_height;
|
||||
u32 vsp_vpp_mode;
|
||||
u32 entropy_coding_mode;
|
||||
u32 hierachical_layer;
|
||||
|
||||
/* PWC, AVG/POWER */
|
||||
u32 complexity_setting;
|
||||
|
||||
u32 status_llc_onoff;
|
||||
u32 bitdepth;
|
||||
u32 linear_opb;
|
||||
|
||||
/* AV1D FG */
|
||||
u32 split_opb;
|
||||
|
||||
u32 linear_ipb;
|
||||
u32 lossy_ipb;
|
||||
u32 ipb_yuvrgb;
|
||||
u32 encoder_multiref;
|
||||
u32 bitrate_mbps;
|
||||
u32 refframe_complexity;
|
||||
u32 cr_ipb;
|
||||
u32 cr_rpb;
|
||||
u32 cr_dpb;
|
||||
u32 cr_opb;
|
||||
u32 av1d_commer_tile_enable;
|
||||
u32 regression_mode;
|
||||
|
||||
/* used in aurora for depth map decode */
|
||||
u32 lumaonly_decode;
|
||||
|
||||
/* used in freq and bitrate table selection*/
|
||||
u32 vpu_ver;
|
||||
};
|
||||
|
||||
struct corner_voting {
|
||||
u32 percent_lowbound;
|
||||
u32 percent_highbound;
|
||||
};
|
||||
|
||||
struct api_calculation_freq_output {
|
||||
u32 vpp_min_freq;
|
||||
u32 vsp_min_freq;
|
||||
u32 tensilica_min_freq;
|
||||
u32 hw_min_freq;
|
||||
u32 enc_hqmode;
|
||||
struct corner_voting usecase_corner;
|
||||
};
|
||||
|
||||
struct api_calculation_bw_output {
|
||||
u32 vsp_read_noc;
|
||||
u32 vsp_write_noc;
|
||||
u32 vsp_read_ddr;
|
||||
u32 vsp_write_ddr;
|
||||
u32 vsp_rd_wr_total_noc;
|
||||
u32 vsp_rd_wr_total_ddr;
|
||||
|
||||
u32 collocated_rd_noc;
|
||||
u32 collocated_wr_noc;
|
||||
u32 collocated_rd_ddr;
|
||||
u32 collocated_wr_ddr;
|
||||
u32 collocated_rd_wr_total_noc;
|
||||
u32 collocated_rd_wr_total_ddr;
|
||||
|
||||
u32 dpb_rd_y_noc;
|
||||
u32 dpb_rd_crcb_noc;
|
||||
u32 dpb_rdwr_duetooverlap_noc;
|
||||
u32 dpb_wr_noc;
|
||||
u32 dpb_rd_y_ddr;
|
||||
u32 dpb_rd_crcb_ddr;
|
||||
u32 dpb_rdwr_duetooverlap_ddr;
|
||||
u32 dpb_wr_ddr;
|
||||
u32 dpb_rd_wr_total_noc;
|
||||
u32 dpb_rd_wr_total_ddr;
|
||||
|
||||
u32 opb_write_total_noc;
|
||||
u32 opb_write_total_ddr;
|
||||
|
||||
u32 ipb_rd_total_noc;
|
||||
u32 ipb_rd_total_ddr;
|
||||
|
||||
u32 bse_tlb_rd_noc;
|
||||
u32 bse_tlb_wr_noc;
|
||||
u32 bse_tlb_rd_ddr;
|
||||
u32 bse_tlb_wr_ddr;
|
||||
u32 bse_rd_wr_total_noc;
|
||||
u32 bse_rd_wr_total_ddr;
|
||||
|
||||
u32 statistics_rd_noc;
|
||||
u32 statistics_wr_noc;
|
||||
u32 statistics_rd_ddr;
|
||||
u32 statistics_wr_ddr;
|
||||
|
||||
u32 mmu_rd_noc;
|
||||
u32 mmu_rd_ddr;
|
||||
|
||||
u32 noc_bw_rd;
|
||||
u32 noc_bw_wr;
|
||||
u32 ddr_bw_rd;
|
||||
u32 ddr_bw_wr;
|
||||
|
||||
/* llc BW components for aurora */
|
||||
u32 dpb_rd_y_llc;
|
||||
u32 dpb_rd_crcb_llc;
|
||||
u32 dpb_wr_llc;
|
||||
u32 bse_tlb_rd_llc;
|
||||
u32 bse_tlb_wr_llc;
|
||||
u32 vsp_read_llc;
|
||||
u32 vsp_write_llc;
|
||||
|
||||
u32 llc_bw_rd;
|
||||
u32 llc_bw_wr;
|
||||
};
|
||||
|
||||
int msm_vidc_calculate_frequency(struct api_calculation_input codec_input,
|
||||
struct api_calculation_freq_output *codec_output);
|
||||
int msm_vidc_calculate_bandwidth(struct api_calculation_input codec_input,
|
||||
struct api_calculation_bw_output *codec_output);
|
||||
|
||||
#endif /*_PERF_STATIC_MODEL_H_ */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,259 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <media/v4l2_vidc_extensions.h>
|
||||
#include "msm_vidc_platform_ext.h"
|
||||
#include "hfi_packet.h"
|
||||
#include "hfi_property.h"
|
||||
#include "venus_hfi.h"
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_venc.h"
|
||||
#include "msm_vidc_platform.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
|
||||
int msm_vidc_adjust_ir_period(void *instance, struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
s32 adjusted_value, all_intra = 0, roi_enable = 0,
|
||||
pix_fmts = MSM_VIDC_FMT_NONE;
|
||||
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
|
||||
|
||||
adjusted_value = ctrl ? ctrl->val : inst->capabilities[IR_PERIOD].value;
|
||||
|
||||
if (msm_vidc_get_parent_value(inst, IR_PERIOD, ALL_INTRA,
|
||||
&all_intra, __func__) ||
|
||||
msm_vidc_get_parent_value(inst, IR_PERIOD, META_ROI_INFO,
|
||||
&roi_enable, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
if (all_intra) {
|
||||
adjusted_value = 0;
|
||||
i_vpr_h(inst, "%s: intra refresh unsupported, all intra: %d\n",
|
||||
__func__, all_intra);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (roi_enable) {
|
||||
i_vpr_h(inst,
|
||||
"%s: intra refresh unsupported with roi metadata\n",
|
||||
__func__);
|
||||
adjusted_value = 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (inst->codec == MSM_VIDC_HEVC) {
|
||||
if (msm_vidc_get_parent_value(inst, IR_PERIOD,
|
||||
PIX_FMTS, &pix_fmts, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
if (is_10bit_colorformat(pix_fmts)) {
|
||||
i_vpr_h(inst,
|
||||
"%s: intra refresh is supported only for 8 bit\n",
|
||||
__func__);
|
||||
adjusted_value = 0;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BITRATE_MODE dependency is NOT common across all chipsets.
|
||||
* Hence, do not return error if not specified as one of the parent.
|
||||
*/
|
||||
if (is_parent_available(inst, IR_PERIOD, BITRATE_MODE, __func__) &&
|
||||
inst->hfi_rc_type != HFI_RC_CBR_CFR &&
|
||||
inst->hfi_rc_type != HFI_RC_CBR_VFR)
|
||||
adjusted_value = 0;
|
||||
|
||||
exit:
|
||||
msm_vidc_update_cap_value(inst, IR_PERIOD, adjusted_value, __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_adjust_dec_frame_rate(void *instance, struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
|
||||
u32 adjusted_value = 0;
|
||||
|
||||
if (is_encode_session(inst)) {
|
||||
d_vpr_e("%s: adjust framerate invalid for enc\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
adjusted_value = ctrl ? ctrl->val : inst->capabilities[FRAME_RATE].value;
|
||||
msm_vidc_update_cap_value(inst, FRAME_RATE, adjusted_value, __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_adjust_dec_operating_rate(void *instance, struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
|
||||
u32 adjusted_value = 0;
|
||||
|
||||
if (is_encode_session(inst)) {
|
||||
d_vpr_e("%s: adjust operating rate invalid for enc\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
adjusted_value = ctrl ? ctrl->val : inst->capabilities[OPERATING_RATE].value;
|
||||
msm_vidc_update_cap_value(inst, OPERATING_RATE, adjusted_value, __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_adjust_delivery_mode(void *instance, struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
s32 adjusted_value;
|
||||
s32 slice_mode = -1;
|
||||
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
|
||||
|
||||
if (is_decode_session(inst))
|
||||
return 0;
|
||||
|
||||
adjusted_value = ctrl ? ctrl->val : inst->capabilities[DELIVERY_MODE].value;
|
||||
|
||||
if (msm_vidc_get_parent_value(inst, DELIVERY_MODE, SLICE_MODE,
|
||||
&slice_mode, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
/* Slice encode delivery mode is only supported for Max MB slice mode */
|
||||
if (slice_mode != V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB)
|
||||
adjusted_value = 0;
|
||||
|
||||
msm_vidc_update_cap_value(inst, DELIVERY_MODE, adjusted_value, __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_set_ir_period(void *instance,
|
||||
enum msm_vidc_inst_capability_type cap_id)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
|
||||
u32 ir_type = 0;
|
||||
struct msm_vidc_core *core;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
if (inst->capabilities[IR_TYPE].value ==
|
||||
V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_RANDOM) {
|
||||
if (inst->bufq[OUTPUT_PORT].vb2q->streaming) {
|
||||
i_vpr_h(inst, "%s: dynamic random intra refresh not allowed\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
ir_type = HFI_PROP_IR_RANDOM_PERIOD;
|
||||
} else if (inst->capabilities[IR_TYPE].value ==
|
||||
V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD_TYPE_CYCLIC) {
|
||||
ir_type = HFI_PROP_IR_CYCLIC_PERIOD;
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: invalid ir_type %d\n",
|
||||
__func__, inst->capabilities[IR_TYPE]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = venus_hfi_set_ir_period(inst, ir_type, cap_id);
|
||||
if (rc) {
|
||||
i_vpr_e(inst, "%s: failed to set ir period %d\n",
|
||||
__func__, inst->capabilities[IR_PERIOD].value);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_set_signal_color_info(void *instance,
|
||||
enum msm_vidc_inst_capability_type cap_id)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
|
||||
u32 color_info, matrix_coeff, transfer_char, primaries, range;
|
||||
u32 full_range = 0;
|
||||
u32 colour_description_present_flag = 0;
|
||||
u32 video_signal_type_present_flag = 0, hfi_value = 0;
|
||||
struct v4l2_format *input_fmt;
|
||||
u32 pix_fmt;
|
||||
/* Unspecified video format */
|
||||
u32 video_format = 5;
|
||||
|
||||
if (!(inst->capabilities[cap_id].flags & CAP_FLAG_CLIENT_SET)) {
|
||||
i_vpr_h(inst, "%s: colorspace not configured via control\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
color_info = inst->capabilities[cap_id].value;
|
||||
matrix_coeff = color_info & 0xFF;
|
||||
transfer_char = (color_info & 0xFF00) >> 8;
|
||||
primaries = (color_info & 0xFF0000) >> 16;
|
||||
range = (color_info & 0xFF000000) >> 24;
|
||||
|
||||
input_fmt = &inst->fmts[INPUT_PORT];
|
||||
pix_fmt = v4l2_colorformat_to_driver(inst,
|
||||
input_fmt->fmt.pix_mp.pixelformat, __func__);
|
||||
if (primaries != V4L2_COLORSPACE_DEFAULT ||
|
||||
matrix_coeff != V4L2_YCBCR_ENC_DEFAULT ||
|
||||
transfer_char != V4L2_XFER_FUNC_DEFAULT) {
|
||||
colour_description_present_flag = 1;
|
||||
video_signal_type_present_flag = 1;
|
||||
primaries = v4l2_color_primaries_to_driver(inst,
|
||||
primaries, __func__);
|
||||
matrix_coeff = v4l2_matrix_coeff_to_driver(inst,
|
||||
matrix_coeff, __func__);
|
||||
transfer_char = v4l2_transfer_char_to_driver(inst,
|
||||
transfer_char, __func__);
|
||||
} else if (is_rgba_colorformat(pix_fmt)) {
|
||||
colour_description_present_flag = 1;
|
||||
video_signal_type_present_flag = 1;
|
||||
primaries = MSM_VIDC_PRIMARIES_BT709;
|
||||
matrix_coeff = MSM_VIDC_MATRIX_COEFF_BT709;
|
||||
transfer_char = MSM_VIDC_TRANSFER_BT709;
|
||||
full_range = 0;
|
||||
}
|
||||
|
||||
if (range != V4L2_QUANTIZATION_DEFAULT) {
|
||||
video_signal_type_present_flag = 1;
|
||||
full_range = range == V4L2_QUANTIZATION_FULL_RANGE ? 1 : 0;
|
||||
}
|
||||
|
||||
hfi_value = (matrix_coeff & 0xFF) |
|
||||
((transfer_char << 8) & 0xFF00) |
|
||||
((primaries << 16) & 0xFF0000) |
|
||||
((colour_description_present_flag << 24) & 0x1000000) |
|
||||
((full_range << 25) & 0x2000000) |
|
||||
((video_format << 26) & 0x1C000000) |
|
||||
((video_signal_type_present_flag << 29) & 0x20000000);
|
||||
|
||||
rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_32_PACKED,
|
||||
&hfi_value, sizeof(u32), __func__);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_adjust_csc(void *instance, struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
s32 adjusted_value;
|
||||
s32 pix_fmt = -1;
|
||||
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
|
||||
|
||||
if (is_decode_session(inst))
|
||||
return 0;
|
||||
|
||||
adjusted_value = ctrl ? ctrl->val : inst->capabilities[CSC].value;
|
||||
|
||||
if (msm_vidc_get_parent_value(inst, CSC, PIX_FMTS,
|
||||
&pix_fmt, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
/* disable csc for 10-bit encoding */
|
||||
if (is_10bit_colorformat(pix_fmt))
|
||||
adjusted_value = 0;
|
||||
|
||||
msm_vidc_update_cap_value(inst, CSC, adjusted_value, __func__);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,238 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "perf_static_model.h"
|
||||
|
||||
#define ENABLE_FINEBITRATE_SUBUHD60 0
|
||||
|
||||
/*
|
||||
* Chipset Generation Technology: SW/FW overhead profiling
|
||||
* need update with new numbers
|
||||
*/
|
||||
static u32 frequency_table_kalama[2][6] = {
|
||||
/* //make lowsvs_D1 as invalid; */
|
||||
{533, 444, 366, 338, 240, 0},
|
||||
{800, 666, 549, 507, 360, 0},
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO Move to kalama.c
|
||||
* TODO Replace hardcoded values with
|
||||
* ENCODER_VPP_TARGET_CLK_PER_MB_KALAMA in CPP file.
|
||||
*/
|
||||
|
||||
/* Tensilica cycles */
|
||||
#define DECODER_VPP_FW_OVERHEAD_KALAMA 66234
|
||||
|
||||
/* Tensilica cycles; this is measured in Lahaina 1stage with FW profiling */
|
||||
#define DECODER_VPPVSP1STAGE_FW_OVERHEAD_KALAMA 93000
|
||||
|
||||
#define DECODER_VSP_FW_OVERHEAD_KALAMA \
|
||||
(DECODER_VPPVSP1STAGE_FW_OVERHEAD_KALAMA - DECODER_VPP_FW_OVERHEAD_KALAMA)
|
||||
|
||||
/* Tensilica cycles; encoder has ARP register */
|
||||
#define ENCODER_VPP_FW_OVERHEAD_KALAMA 48405
|
||||
|
||||
#define ENCODER_VPPVSP1STAGE_FW_OVERHEAD_KALAMA \
|
||||
(ENCODER_VPP_FW_OVERHEAD_KALAMA + DECODER_VSP_FW_OVERHEAD_KALAMA)
|
||||
|
||||
#define DECODER_SW_OVERHEAD_KALAMA 489583
|
||||
#define ENCODER_SW_OVERHEAD_KALAMA 489583
|
||||
|
||||
/* Video IP Core Technology: pipefloor and pipe penlaty */
|
||||
static u32 encoder_vpp_target_clk_per_mb_kalama[2] = {320, 675};
|
||||
static u32 decoder_vpp_target_clk_per_mb_kalama = 200;
|
||||
|
||||
/*
|
||||
* These pipe penalty numbers only applies to 4 pipe
|
||||
* For 2pipe and 1pipe, these numbers need recalibrate
|
||||
*/
|
||||
static u32 pipe_penalty_kalama[3][3] = {
|
||||
/* NON AV1 */
|
||||
{1059, 1059, 1059},
|
||||
/* AV1 RECOMMENDED TILE 1080P_V2XH1, UHD_V2X2, 8KUHD_V8X2 */
|
||||
{1410, 1248, 1226},
|
||||
/* AV1 YOUTUBE/NETFLIX TILE 1080P_V4XH2_V4X1, UHD_V8X4_V8X1, 8KUHD_V8X8_V8X1 */
|
||||
{2039, 2464, 1191},
|
||||
};
|
||||
|
||||
/*
|
||||
* Video IP Core Technology: bitrate constraint
|
||||
* HW limit bitrate table (these values are measured end to end fw/sw impacts are also considered)
|
||||
* TODO Can we convert to Cycles/MB? This will remove DIVISION.
|
||||
*/
|
||||
static u32 bitrate_table_kalama_2stage_fp[5][10] = {
|
||||
/* h264 cavlc */
|
||||
{0, 220, 220, 220, 220, 220, 220, 220, 220, 220},
|
||||
/* h264 cabac */
|
||||
{0, 140, 150, 160, 175, 190, 190, 190, 190, 190},
|
||||
/* h265 */
|
||||
{90, 140, 160, 180, 190, 200, 200, 200, 200, 200},
|
||||
/* vp9 */
|
||||
{90, 90, 90, 90, 90, 90, 90, 90, 90, 90},
|
||||
/* av1 */
|
||||
{130, 130, 120, 120, 120, 120, 120, 120, 120, 120},
|
||||
};
|
||||
|
||||
/*
|
||||
* HW limit bitrate table (these values are measured
|
||||
* end to end fw/sw impacts are also considered)
|
||||
*/
|
||||
static u32 bitrate_table_kalama_1stage_fp[5][10] = { /* 1-stage assume IPPP */
|
||||
/* h264 cavlc */
|
||||
{0, 220, 220, 220, 220, 220, 220, 220, 220, 220},
|
||||
/* h264 cabac */
|
||||
{0, 110, 150, 150, 150, 150, 150, 150, 150, 150},
|
||||
/* h265 */
|
||||
{0, 140, 150, 150, 150, 150, 150, 150, 150, 150},
|
||||
/* vp9 */
|
||||
{0, 70, 70, 70, 70, 70, 70, 70, 70, 70},
|
||||
/* av1 */
|
||||
{0, 100, 100, 100, 100, 100, 100, 100, 100, 100},
|
||||
};
|
||||
|
||||
/* rec pwc and power bitrate table */
|
||||
static u32 bitrate_table_kalama_rec_fp[5][10] = {
|
||||
/* rec. worst bitrate based on bitrate table */
|
||||
#if ENABLE_FINEBITRATE_SUBUHD60
|
||||
/* h264 cavlc */
|
||||
{0, 168, 150, 120, 100, 90, 50, 32, 20, 14},
|
||||
/* h264 cabac 8bit */
|
||||
{0, 134, 109, 84, 67, 56, 35, 23, 14, 10},
|
||||
/* h265 10bit assumption */
|
||||
{70, 140, 116, 92, 74, 62, 39, 25, 16, 11},
|
||||
/* vp9 (profiled content from youtube and nflx) */
|
||||
{70, 70, 65, 55, 45, 35, 20, 8, 6, 5},
|
||||
/* av1 (profiled content from youtube and nflx) */
|
||||
{100, 100, 85, 70, 55, 30, 15, 5, 5, 5},
|
||||
#else
|
||||
/* h264 cavlc */
|
||||
{0, 168, 150, 120, 100, 90, 90, 90, 90, 90},
|
||||
/* h264 cabac 8bit */
|
||||
{0, 134, 109, 84, 67, 56, 56, 56, 56, 56},
|
||||
/* h265 10bit assumption */
|
||||
{70, 140, 116, 92, 74, 62, 62, 62, 62, 62},
|
||||
/* vp9 */
|
||||
{70, 70, 65, 55, 45, 35, 35, 35, 35, 35},
|
||||
/* av1 */
|
||||
{100, 100, 85, 70, 55, 50, 50, 50, 50, 50},
|
||||
#endif
|
||||
};
|
||||
|
||||
static u32 input_bitrate_fp;
|
||||
|
||||
/* 8KUHD60; UHD240; 1080p960 with B */
|
||||
static u32 fp_pixel_count_bar0 = 3840 * 2160 * 240;
|
||||
/* 8KUHD60; UHD240; 1080p960 without B */
|
||||
static u32 fp_pixel_count_bar1 = 3840 * 2160 * 240;
|
||||
/* 1080p720 */
|
||||
static u32 fp_pixel_count_bar2 = 3840 * 2160 * 180;
|
||||
/* UHD120 */
|
||||
static u32 fp_pixel_count_bar3 = 3840 * 2160 * 120;
|
||||
/* UHD90 */
|
||||
static u32 fp_pixel_count_bar4 = 3840 * 2160 * 90;
|
||||
/* UHD60 */
|
||||
static u32 fp_pixel_count_bar5 = 3840 * 2160 * 60;
|
||||
/* UHD30; FHD120; HD240 */
|
||||
static u32 fp_pixel_count_bar6 = 3840 * 2160 * 30;
|
||||
/* FHD60 */
|
||||
static u32 fp_pixel_count_bar7 = 1920 * 1080 * 60;
|
||||
/* FHD30 */
|
||||
static u32 fp_pixel_count_bar8 = 1920 * 1080 * 30;
|
||||
/* HD30 */
|
||||
static u32 fp_pixel_count_bar9 = 1280 * 720 * 30;
|
||||
|
||||
static u32 codec_encoder_gop_complexity_table_fp[8][3];
|
||||
static u32 codec_mbspersession_kalama;
|
||||
|
||||
static u32 cr_table_basic_kalama[7][4] = {
|
||||
{1920, 1080, 20, 40},
|
||||
{3840, 2160, 42, 84},
|
||||
{4096, 2160, 44, 88},
|
||||
{4096, 2304, 48, 96},
|
||||
{1280, 720, 7, 14},
|
||||
{2560, 1440, 32, 64},
|
||||
{7680, 4320, 84, 168},
|
||||
};
|
||||
|
||||
/* 100x */
|
||||
static u32 dpbopb_ubwc30_cr_table_cratio_kalama[7][12] = {
|
||||
{237, 399, 272, 137, 225, 158, 185, 259, 203, 138, 167, 152},
|
||||
{269, 404, 302, 202, 367, 238, 210, 299, 232, 134, 181, 149},
|
||||
{269, 404, 302, 202, 367, 238, 210, 299, 232, 134, 181, 149},
|
||||
{269, 404, 302, 202, 367, 238, 210, 299, 232, 134, 181, 149},
|
||||
{237, 399, 272, 137, 225, 158, 185, 259, 203, 138, 167, 152},
|
||||
{269, 404, 302, 202, 367, 238, 210, 299, 232, 134, 181, 149},
|
||||
{269, 404, 302, 202, 367, 238, 210, 299, 232, 134, 181, 149},
|
||||
};
|
||||
|
||||
/* 100x */
|
||||
static u32 rpb_ubwc30_cr_table_cratio_kalama[7][12] = {
|
||||
{193, 294, 218, 135, 214, 155, 175, 241, 191, 139, 162, 149},
|
||||
{285, 406, 316, 207, 373, 243, 201, 280, 221, 139, 177, 152},
|
||||
{285, 406, 316, 207, 373, 243, 201, 280, 221, 139, 177, 152},
|
||||
{285, 406, 316, 207, 373, 243, 201, 280, 221, 139, 177, 152},
|
||||
{193, 294, 218, 135, 214, 155, 175, 241, 191, 139, 162, 149},
|
||||
{285, 406, 316, 207, 373, 243, 201, 280, 221, 139, 177, 152},
|
||||
{285, 406, 316, 207, 373, 243, 201, 280, 221, 139, 177, 152},
|
||||
};
|
||||
|
||||
/* 100x */
|
||||
static u32 ipblossy_ubwc30_cr_table_cratio_kalama[7][12] = {
|
||||
{215, 215, 215, 174, 174, 174, 266, 266, 266, 231, 231, 231},
|
||||
{254, 254, 254, 219, 219, 219, 292, 292, 292, 249, 249, 249},
|
||||
{254, 254, 254, 219, 219, 219, 292, 292, 292, 249, 249, 249},
|
||||
{254, 254, 254, 219, 219, 219, 292, 292, 292, 249, 249, 249},
|
||||
{215, 215, 215, 174, 174, 174, 266, 266, 266, 231, 231, 231},
|
||||
{254, 254, 254, 219, 219, 219, 292, 292, 292, 249, 249, 249},
|
||||
{254, 254, 254, 219, 219, 219, 292, 292, 292, 249, 249, 249},
|
||||
};
|
||||
|
||||
/* 100x */
|
||||
static u32 ipblossless_ubwc30_cr_table_cratio_kalama[7][12] = {
|
||||
{185, 215, 194, 147, 178, 159, 162, 181, 169, 138, 161, 146},
|
||||
{186, 217, 195, 151, 183, 161, 164, 182, 170, 140, 168, 148},
|
||||
{186, 217, 195, 151, 183, 161, 164, 182, 170, 140, 168, 148},
|
||||
{186, 217, 195, 151, 183, 161, 164, 182, 170, 140, 168, 148},
|
||||
{185, 215, 194, 147, 178, 159, 162, 181, 169, 138, 161, 146},
|
||||
{186, 217, 195, 151, 183, 161, 164, 182, 170, 140, 168, 148},
|
||||
{186, 217, 195, 151, 183, 161, 164, 182, 170, 140, 168, 148},
|
||||
};
|
||||
|
||||
/* 100x */
|
||||
static u32 en_original_compression_factor_rgba_pwd_kalama = 243;
|
||||
/* 100x */
|
||||
static u32 en_original_compression_factor_rgba_avg_kalama = 454;
|
||||
|
||||
static u32 av1_num_tiles_kalama[7][3] = {
|
||||
{2, 1, 1},
|
||||
{4, 2, 2},
|
||||
{4, 2, 2},
|
||||
{4, 2, 2},
|
||||
{1, 1, 1},
|
||||
{2, 1, 1},
|
||||
{16, 4, 4},
|
||||
};
|
||||
|
||||
/* H I J K L M N O P
|
||||
* TotalW Total R Frequency Write Read
|
||||
* Name B b P B b P B b P
|
||||
* I3B4b1P 0.5 1.875 3 4 1 1 0 1 2 2 1
|
||||
* I1B2b1P 0.5 1.75 1 2 1 1 0 1 2 2 1
|
||||
* IbP 0.5 1.5 0 1 1 1 0 1 2 2 1
|
||||
* IPP 1 1 0 0 1 1 0 1 2 2 1
|
||||
* P 1 1 0 0 1 1 0 1 2 2 1
|
||||
* smallB 0 2 0 1 0 1 0 1 2 2 1
|
||||
* bigB 1 2 1 0 0 1 0 1 2 2 1
|
||||
*
|
||||
* Total W = SUMPRODUCT(H16:J16, K16 : M16) / SUM(H16:J16)
|
||||
* Total R = SUMPRODUCT(H16:J16, N16 : P16) / SUM(H16:J16)
|
||||
*/
|
||||
|
||||
/* 1000x */
|
||||
static u32 kalama_en_readfactor[7] = {1000, 1500, 1750, 1875, 1000, 2000, 2000};
|
||||
/* 1000x */
|
||||
static u32 kalama_en_writefactor[7] = {1000, 500, 500, 500, 1000, 0, 1000};
|
||||
static u32 kalama_en_frame_num_parallel = 1;
|
@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_KALAMA_H_
|
||||
#define _MSM_VIDC_KALAMA_H_
|
||||
|
||||
#include "msm_vidc_core.h"
|
||||
|
||||
#if defined(CONFIG_MSM_VIDC_KALAMA)
|
||||
int msm_vidc_init_platform_kalama(struct msm_vidc_core *core);
|
||||
#else
|
||||
int msm_vidc_init_platform_kalama(struct msm_vidc_core *core)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _MSM_VIDC_KALAMA_H_
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_PINEAPPLE_H_
|
||||
#define _MSM_VIDC_PINEAPPLE_H_
|
||||
|
||||
#include "msm_vidc_core.h"
|
||||
|
||||
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
|
||||
int msm_vidc_init_platform_pineapple(struct msm_vidc_core *core);
|
||||
#else
|
||||
int msm_vidc_init_platform_pineapple(struct msm_vidc_core *core)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _MSM_VIDC_PINEAPPLE_H_
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_VOLCANO_H_
|
||||
#define _MSM_VIDC_VOLCANO_H_
|
||||
|
||||
#include "msm_vidc_core.h"
|
||||
|
||||
#if defined(CONFIG_MSM_VIDC_VOLCANO)
|
||||
int msm_vidc_init_platform_volcano(struct msm_vidc_core *core);
|
||||
int msm_vidc_deinit_platform_volcano(struct msm_vidc_core *core);
|
||||
#else
|
||||
int msm_vidc_init_platform_volcano(struct msm_vidc_core *core)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int msm_vidc_deinit_platform_volcano(struct msm_vidc_core *core)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _MSM_VIDC_VOLCANO_H_
|
File diff suppressed because it is too large
Load Diff
1681
qcom/opensource/video-driver/driver/platform/volcano/src/volcano.c
Normal file
1681
qcom/opensource/video-driver/driver/platform/volcano/src/volcano.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_WAIPIO_H_
|
||||
#define _MSM_VIDC_WAIPIO_H_
|
||||
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_iris2.h"
|
||||
|
||||
#if defined(CONFIG_MSM_VIDC_WAIPIO)
|
||||
struct context_bank_info *msm_vidc_context_bank(struct msm_vidc_core *core,
|
||||
enum msm_vidc_buffer_region region);
|
||||
int msm_vidc_init_platform_waipio(struct msm_vidc_core *core);
|
||||
#else
|
||||
struct context_bank_info *msm_vidc_context_bank(struct msm_vidc_core *core,
|
||||
enum msm_vidc_buffer_region region)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int msm_vidc_init_platform_waipio(struct msm_vidc_core *core)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _MSM_VIDC_WAIPIO_H_
|
1841
qcom/opensource/video-driver/driver/platform/waipio/src/waipio.c
Normal file
1841
qcom/opensource/video-driver/driver/platform/waipio/src/waipio.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_VARIANT_H_
|
||||
#define _MSM_VIDC_VARIANT_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct msm_vidc_core;
|
||||
|
||||
int __write_register_masked(struct msm_vidc_core *core, u32 reg, u32 value,
|
||||
u32 mask);
|
||||
int __write_register(struct msm_vidc_core *core, u32 reg, u32 value);
|
||||
int __read_register(struct msm_vidc_core *core, u32 reg, u32 *value);
|
||||
int __read_register_with_poll_timeout(struct msm_vidc_core *core, u32 reg,
|
||||
u32 mask, u32 exp_val, u32 sleep_us, u32 timeout_us);
|
||||
int __set_registers(struct msm_vidc_core *core);
|
||||
|
||||
#endif
|
@ -0,0 +1,161 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vidc_state.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
#include "msm_vidc_variant.h"
|
||||
#include "msm_vidc_platform.h"
|
||||
#include "venus_hfi.h"
|
||||
|
||||
int __write_register(struct msm_vidc_core *core, u32 reg, u32 value)
|
||||
{
|
||||
u32 hwiosymaddr = reg;
|
||||
u8 *base_addr;
|
||||
int rc = 0;
|
||||
|
||||
rc = __strict_check(core, __func__);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE)) {
|
||||
d_vpr_e("HFI Write register failed : Power is OFF\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
base_addr = core->resource->register_base_addr;
|
||||
d_vpr_l("regwrite(%pK + %#x) = %#x\n", base_addr, hwiosymaddr, value);
|
||||
base_addr += hwiosymaddr;
|
||||
writel_relaxed(value, base_addr);
|
||||
|
||||
/* Memory barrier to make sure value is written into the register */
|
||||
wmb();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Argument mask is used to specify which bits to update. In case mask is 0x11,
|
||||
* only bits 0 & 4 will be updated with corresponding bits from value. To update
|
||||
* entire register with value, set mask = 0xFFFFFFFF.
|
||||
*/
|
||||
int __write_register_masked(struct msm_vidc_core *core, u32 reg, u32 value,
|
||||
u32 mask)
|
||||
{
|
||||
u32 prev_val, new_val;
|
||||
u8 *base_addr;
|
||||
int rc = 0;
|
||||
|
||||
rc = __strict_check(core, __func__);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE)) {
|
||||
d_vpr_e("%s: register write failed, power is off\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
base_addr = core->resource->register_base_addr;
|
||||
base_addr += reg;
|
||||
|
||||
prev_val = readl_relaxed(base_addr);
|
||||
/*
|
||||
* Memory barrier to ensure register read is correct
|
||||
*/
|
||||
rmb();
|
||||
|
||||
new_val = (prev_val & ~mask) | (value & mask);
|
||||
d_vpr_l(
|
||||
"Base addr: %pK, writing to: %#x, previous-value: %#x, value: %#x, mask: %#x, new-value: %#x...\n",
|
||||
base_addr, reg, prev_val, value, mask, new_val);
|
||||
writel_relaxed(new_val, base_addr);
|
||||
/*
|
||||
* Memory barrier to make sure value is written into the register.
|
||||
*/
|
||||
wmb();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int __read_register(struct msm_vidc_core *core, u32 reg, u32 *value)
|
||||
{
|
||||
int rc = 0;
|
||||
u8 *base_addr;
|
||||
|
||||
if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE)) {
|
||||
d_vpr_e("HFI Read register failed : Power is OFF\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
base_addr = core->resource->register_base_addr;
|
||||
|
||||
*value = readl_relaxed(base_addr + reg);
|
||||
/*
|
||||
* Memory barrier to make sure value is read correctly from the
|
||||
* register.
|
||||
*/
|
||||
rmb();
|
||||
d_vpr_l("regread(%pK + %#x) = %#x\n", base_addr, reg, *value);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int __read_register_with_poll_timeout(struct msm_vidc_core *core, u32 reg,
|
||||
u32 mask, u32 exp_val, u32 sleep_us,
|
||||
u32 timeout_us)
|
||||
{
|
||||
int rc = 0;
|
||||
u32 val = 0;
|
||||
u8 *addr;
|
||||
|
||||
if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE)) {
|
||||
d_vpr_e("%s failed: Power is OFF\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
addr = (u8 *)core->resource->register_base_addr + reg;
|
||||
|
||||
rc = readl_relaxed_poll_timeout(addr, val, ((val & mask) == exp_val), sleep_us, timeout_us);
|
||||
/*
|
||||
* Memory barrier to make sure value is read correctly from the
|
||||
* register.
|
||||
*/
|
||||
rmb();
|
||||
d_vpr_l(
|
||||
"regread(%pK + %#x) = %#x. rc %d, mask %#x, exp_val %#x, cond %u, sleep %u, timeout %u\n",
|
||||
core->resource->register_base_addr, reg, val, rc, mask, exp_val,
|
||||
((val & mask) == exp_val), sleep_us, timeout_us);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int __set_registers(struct msm_vidc_core *core)
|
||||
{
|
||||
const struct reg_preset_table *reg_prst;
|
||||
unsigned int prst_count;
|
||||
int cnt, rc = 0;
|
||||
|
||||
reg_prst = core->platform->data.reg_prst_tbl;
|
||||
prst_count = core->platform->data.reg_prst_tbl_size;
|
||||
|
||||
/* skip if there is no preset reg available */
|
||||
if (!reg_prst || !prst_count)
|
||||
return 0;
|
||||
|
||||
for (cnt = 0; cnt < prst_count; cnt++) {
|
||||
rc = __write_register_masked(core, reg_prst[cnt].reg,
|
||||
reg_prst[cnt].value, reg_prst[cnt].mask);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __H_MSM_VIDC_BUFFER_IRIS2_H__
|
||||
#define __H_MSM_VIDC_BUFFER_IRIS2_H__
|
||||
|
||||
#include "msm_vidc_inst.h"
|
||||
|
||||
int msm_buffer_size_iris2(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
int msm_buffer_min_count_iris2(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
int msm_buffer_extra_count_iris2(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
|
||||
#endif // __H_MSM_VIDC_BUFFER_IRIS2_H__
|
@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_IRIS2_H_
|
||||
#define _MSM_VIDC_IRIS2_H_
|
||||
|
||||
#include "msm_vidc_core.h"
|
||||
|
||||
#if defined(CONFIG_MSM_VIDC_VOLCANO)
|
||||
int msm_vidc_init_iris2(struct msm_vidc_core *core);
|
||||
int msm_vidc_adjust_blur_type_iris2(void *instance, struct v4l2_ctrl *ctrl);
|
||||
#else
|
||||
static inline int msm_vidc_init_iris2(struct msm_vidc_core *core)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int msm_vidc_adjust_blur_type_iris2(void *instance, struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _MSM_VIDC_IRIS2_H_
|
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __H_MSM_VIDC_POWER_IRIS2_H__
|
||||
#define __H_MSM_VIDC_POWER_IRIS2_H__
|
||||
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_power.h"
|
||||
|
||||
u64 msm_vidc_calc_freq_iris2(struct msm_vidc_inst *inst, u32 data_size);
|
||||
int msm_vidc_calc_bw_iris2(struct msm_vidc_inst *inst,
|
||||
struct vidc_bus_vote_data *vote_data);
|
||||
|
||||
#endif
|
@ -0,0 +1,582 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "hfi_property.h"
|
||||
#include "hfi_buffer_iris2.h"
|
||||
#include "msm_vidc_buffer_iris2.h"
|
||||
#include "msm_vidc_buffer.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_media_info.h"
|
||||
#include "msm_vidc_platform.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
|
||||
static u32 msm_vidc_decoder_bin_size_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, num_vpp_pipes;
|
||||
struct v4l2_format *f;
|
||||
bool is_interlaced;
|
||||
u32 vpp_delay;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
if (inst->decode_vpp_delay.enable)
|
||||
vpp_delay = inst->decode_vpp_delay.size;
|
||||
else
|
||||
vpp_delay = DEFAULT_BSE_VPP_DELAY;
|
||||
if (inst->capabilities[CODED_FRAMES].value ==
|
||||
CODED_FRAMES_PROGRESSIVE)
|
||||
is_interlaced = false;
|
||||
else
|
||||
is_interlaced = true;
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_BIN_H264D(size, width, height,
|
||||
is_interlaced, vpp_delay, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_BIN_H265D(size, width, height,
|
||||
0, vpp_delay, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_VP9)
|
||||
HFI_BUFFER_BIN_VP9D(size, width, height,
|
||||
0, num_vpp_pipes);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_comv_size_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height, out_min_count, vpp_delay;
|
||||
struct v4l2_format *f;
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
if (inst->decode_vpp_delay.enable)
|
||||
vpp_delay = inst->decode_vpp_delay.size;
|
||||
else
|
||||
vpp_delay = DEFAULT_BSE_VPP_DELAY;
|
||||
out_min_count = inst->buffers.output.min_count;
|
||||
out_min_count = max(vpp_delay + 1, out_min_count);
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_COMV_H264D(size, width, height, out_min_count);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_COMV_H265D(size, width, height, out_min_count);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_non_comv_size_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height, num_vpp_pipes;
|
||||
struct msm_vidc_core *core;
|
||||
struct v4l2_format *f;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_NON_COMV_H264D(size, width, height, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_NON_COMV_H265D(size, width, height, num_vpp_pipes);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_line_size_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, out_min_count, num_vpp_pipes, vpp_delay;
|
||||
struct v4l2_format *f;
|
||||
bool is_opb;
|
||||
u32 color_fmt;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
|
||||
color_fmt = v4l2_colorformat_to_driver(inst,
|
||||
inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat, __func__);
|
||||
if (is_linear_colorformat(color_fmt))
|
||||
is_opb = true;
|
||||
else
|
||||
is_opb = false;
|
||||
/*
|
||||
* assume worst case, since color format is unknown at this
|
||||
* time
|
||||
*/
|
||||
is_opb = true;
|
||||
|
||||
if (inst->decode_vpp_delay.enable)
|
||||
vpp_delay = inst->decode_vpp_delay.size;
|
||||
else
|
||||
vpp_delay = DEFAULT_BSE_VPP_DELAY;
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
out_min_count = inst->buffers.output.min_count;
|
||||
out_min_count = max(vpp_delay + 1, out_min_count);
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_LINE_H264D(size, width, height, is_opb,
|
||||
num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_LINE_H265D(size, width, height, is_opb,
|
||||
num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_VP9)
|
||||
HFI_BUFFER_LINE_VP9D(size, width, height, out_min_count,
|
||||
is_opb, num_vpp_pipes);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_persist_size_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 rpu_enabled = 0;
|
||||
|
||||
if (inst->capabilities[META_DOLBY_RPU].value)
|
||||
rpu_enabled = 1;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_PERSIST_H264D(size, rpu_enabled);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_PERSIST_H265D(size, rpu_enabled);
|
||||
else if (inst->codec == MSM_VIDC_VP9)
|
||||
HFI_BUFFER_PERSIST_VP9D(size);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_dpb_size_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
|
||||
u32 color_fmt, width, height, size = 0;
|
||||
struct v4l2_format *f;
|
||||
|
||||
color_fmt = inst->capabilities[PIX_FMTS].value;
|
||||
if (!is_linear_colorformat(color_fmt))
|
||||
return size;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (color_fmt == MSM_VIDC_FMT_NV12) {
|
||||
color_fmt = MSM_VIDC_FMT_NV12C;
|
||||
HFI_NV12_UBWC_IL_CALC_BUF_SIZE_V2(size, width, height,
|
||||
video_y_stride_bytes(color_fmt, width),
|
||||
video_y_scanlines(color_fmt, height),
|
||||
video_uv_stride_bytes(color_fmt, width),
|
||||
video_uv_scanlines(color_fmt, height),
|
||||
video_y_meta_stride(color_fmt, width),
|
||||
video_y_meta_scanlines(color_fmt, height),
|
||||
video_uv_meta_stride(color_fmt, width),
|
||||
video_uv_meta_scanlines(color_fmt, height));
|
||||
} else if (color_fmt == MSM_VIDC_FMT_P010) {
|
||||
color_fmt = MSM_VIDC_FMT_TP10C;
|
||||
HFI_YUV420_TP10_UBWC_CALC_BUF_SIZE(size,
|
||||
video_y_stride_bytes(color_fmt, width),
|
||||
video_y_scanlines(color_fmt, height),
|
||||
video_uv_stride_bytes(color_fmt, width),
|
||||
video_uv_scanlines(color_fmt, height),
|
||||
video_y_meta_stride(color_fmt, width),
|
||||
video_y_meta_scanlines(color_fmt, height),
|
||||
video_uv_meta_stride(color_fmt, width),
|
||||
video_uv_meta_scanlines(color_fmt, height));
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
/* encoder internal buffers */
|
||||
static u32 msm_vidc_encoder_bin_size_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, num_vpp_pipes, stage;
|
||||
struct v4l2_format *f;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
stage = inst->capabilities[STAGE].value;
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_BIN_H264E(size, inst->hfi_rc_type, width,
|
||||
height, stage, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_BIN_H265E(size, inst->hfi_rc_type, width,
|
||||
height, stage, num_vpp_pipes);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_get_recon_buf_count(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 num_buf_recon = 0;
|
||||
s32 n_bframe, ltr_count, hp_layers = 0, hb_layers = 0;
|
||||
bool is_hybrid_hp = false;
|
||||
u32 hfi_codec = 0;
|
||||
|
||||
n_bframe = inst->capabilities[B_FRAME].value;
|
||||
ltr_count = inst->capabilities[LTR_COUNT].value;
|
||||
|
||||
if (inst->hfi_layer_type == HFI_HIER_B) {
|
||||
hb_layers = inst->capabilities[ENH_LAYER_COUNT].value + 1;
|
||||
} else {
|
||||
hp_layers = inst->capabilities[ENH_LAYER_COUNT].value + 1;
|
||||
if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR)
|
||||
is_hybrid_hp = true;
|
||||
}
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
hfi_codec = HFI_CODEC_ENCODE_AVC;
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
hfi_codec = HFI_CODEC_ENCODE_HEVC;
|
||||
|
||||
HFI_IRIS2_ENC_RECON_BUF_COUNT(num_buf_recon, n_bframe, ltr_count,
|
||||
hp_layers, hb_layers, is_hybrid_hp, hfi_codec);
|
||||
|
||||
return num_buf_recon;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_comv_size_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height, num_recon = 0;
|
||||
struct v4l2_format *f;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
num_recon = msm_vidc_get_recon_buf_count(inst);
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_COMV_H264E(size, width, height, num_recon);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_COMV_H265E(size, width, height, num_recon);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_non_comv_size_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, num_vpp_pipes;
|
||||
struct v4l2_format *f;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_NON_COMV_H264E(size, width, height, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_NON_COMV_H265E(size, width, height, num_vpp_pipes);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_line_size_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, pixfmt, num_vpp_pipes;
|
||||
bool is_tenbit = false;
|
||||
struct v4l2_format *f;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
pixfmt = inst->capabilities[PIX_FMTS].value;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
is_tenbit = (pixfmt == MSM_VIDC_FMT_P010 || pixfmt == MSM_VIDC_FMT_TP10C);
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_LINE_H264E(size, width, height, is_tenbit, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_LINE_H265E(size, width, height, is_tenbit, num_vpp_pipes);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_dpb_size_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height, pixfmt;
|
||||
struct v4l2_format *f;
|
||||
bool is_tenbit;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
pixfmt = inst->capabilities[PIX_FMTS].value;
|
||||
is_tenbit = (pixfmt == MSM_VIDC_FMT_P010 || pixfmt == MSM_VIDC_FMT_TP10C);
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_DPB_H264E(size, width, height);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_DPB_H265E(size, width, height, is_tenbit);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_arp_size_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
|
||||
HFI_BUFFER_ARP_ENC(size);
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_vpss_size_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
bool ds_enable = false, is_tenbit = false, blur = false;
|
||||
u32 rotation_val = HFI_ROTATION_NONE;
|
||||
u32 width, height, driver_colorfmt;
|
||||
struct v4l2_format *f;
|
||||
|
||||
ds_enable = is_scaling_enabled(inst);
|
||||
msm_vidc_v4l2_to_hfi_enum(inst, ROTATION, &rotation_val);
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
if (is_rotation_90_or_270(inst)) {
|
||||
/*
|
||||
* output width and height are rotated,
|
||||
* so unrotate them to use as arguments to
|
||||
* HFI_BUFFER_VPSS_ENC.
|
||||
*/
|
||||
width = f->fmt.pix_mp.height;
|
||||
height = f->fmt.pix_mp.width;
|
||||
} else {
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
}
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
driver_colorfmt = v4l2_colorformat_to_driver(inst,
|
||||
f->fmt.pix_mp.pixelformat, __func__);
|
||||
is_tenbit = is_10bit_colorformat(driver_colorfmt);
|
||||
if (inst->capabilities[BLUR_TYPES].value != MSM_VIDC_BLUR_NONE)
|
||||
blur = true;
|
||||
|
||||
HFI_BUFFER_VPSS_ENC(size, width, height, ds_enable, blur, is_tenbit);
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
struct msm_vidc_buf_type_handle {
|
||||
enum msm_vidc_buffer_type type;
|
||||
u32 (*handle)(struct msm_vidc_inst *inst);
|
||||
};
|
||||
|
||||
int msm_buffer_size_iris2(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
int i;
|
||||
u32 size = 0, buf_type_handle_size = 0;
|
||||
const struct msm_vidc_buf_type_handle *buf_type_handle_arr = NULL;
|
||||
static const struct msm_vidc_buf_type_handle dec_buf_type_handle[] = {
|
||||
{MSM_VIDC_BUF_INPUT, msm_vidc_decoder_input_size },
|
||||
{MSM_VIDC_BUF_OUTPUT, msm_vidc_decoder_output_size },
|
||||
{MSM_VIDC_BUF_INPUT_META, msm_vidc_decoder_input_meta_size },
|
||||
{MSM_VIDC_BUF_OUTPUT_META, msm_vidc_decoder_output_meta_size },
|
||||
{MSM_VIDC_BUF_BIN, msm_vidc_decoder_bin_size_iris2 },
|
||||
{MSM_VIDC_BUF_COMV, msm_vidc_decoder_comv_size_iris2 },
|
||||
{MSM_VIDC_BUF_NON_COMV, msm_vidc_decoder_non_comv_size_iris2 },
|
||||
{MSM_VIDC_BUF_LINE, msm_vidc_decoder_line_size_iris2 },
|
||||
{MSM_VIDC_BUF_PERSIST, msm_vidc_decoder_persist_size_iris2 },
|
||||
{MSM_VIDC_BUF_DPB, msm_vidc_decoder_dpb_size_iris2 },
|
||||
};
|
||||
static const struct msm_vidc_buf_type_handle enc_buf_type_handle[] = {
|
||||
{MSM_VIDC_BUF_INPUT, msm_vidc_encoder_input_size },
|
||||
{MSM_VIDC_BUF_OUTPUT, msm_vidc_encoder_output_size },
|
||||
{MSM_VIDC_BUF_INPUT_META, msm_vidc_encoder_input_meta_size },
|
||||
{MSM_VIDC_BUF_OUTPUT_META, msm_vidc_encoder_output_meta_size },
|
||||
{MSM_VIDC_BUF_BIN, msm_vidc_encoder_bin_size_iris2 },
|
||||
{MSM_VIDC_BUF_COMV, msm_vidc_encoder_comv_size_iris2 },
|
||||
{MSM_VIDC_BUF_NON_COMV, msm_vidc_encoder_non_comv_size_iris2 },
|
||||
{MSM_VIDC_BUF_LINE, msm_vidc_encoder_line_size_iris2 },
|
||||
{MSM_VIDC_BUF_DPB, msm_vidc_encoder_dpb_size_iris2 },
|
||||
{MSM_VIDC_BUF_ARP, msm_vidc_encoder_arp_size_iris2 },
|
||||
{MSM_VIDC_BUF_VPSS, msm_vidc_encoder_vpss_size_iris2 },
|
||||
};
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
buf_type_handle_size = ARRAY_SIZE(dec_buf_type_handle);
|
||||
buf_type_handle_arr = dec_buf_type_handle;
|
||||
} else if (is_encode_session(inst)) {
|
||||
buf_type_handle_size = ARRAY_SIZE(enc_buf_type_handle);
|
||||
buf_type_handle_arr = enc_buf_type_handle;
|
||||
}
|
||||
|
||||
/* handle invalid session */
|
||||
if (!buf_type_handle_arr || !buf_type_handle_size) {
|
||||
i_vpr_e(inst, "%s: invalid session %d\n", __func__, inst->domain);
|
||||
return size;
|
||||
}
|
||||
|
||||
/* fetch buffer size */
|
||||
for (i = 0; i < buf_type_handle_size; i++) {
|
||||
if (buf_type_handle_arr[i].type == buffer_type) {
|
||||
size = buf_type_handle_arr[i].handle(inst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle unknown buffer type */
|
||||
if (i == buf_type_handle_size) {
|
||||
i_vpr_e(inst, "%s: unknown buffer type %#x\n", __func__, buffer_type);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "buffer_size: type: %11s, size: %9u\n", buf_name(buffer_type), size);
|
||||
|
||||
exit:
|
||||
return size;
|
||||
}
|
||||
|
||||
static int msm_vidc_input_min_count_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 input_min_count = 0;
|
||||
u32 total_hb_layer = 0;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
input_min_count = MIN_DEC_INPUT_BUFFERS;
|
||||
} else if (is_encode_session(inst)) {
|
||||
total_hb_layer = is_hierb_type_requested(inst) ?
|
||||
inst->capabilities[ENH_LAYER_COUNT].value + 1 : 0;
|
||||
if (inst->codec == MSM_VIDC_H264 &&
|
||||
!inst->capabilities[LAYER_ENABLE].value) {
|
||||
total_hb_layer = 0;
|
||||
}
|
||||
HFI_IRIS2_ENC_MIN_INPUT_BUF_COUNT(input_min_count,
|
||||
total_hb_layer);
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: invalid domain %d\n", __func__, inst->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_thumbnail_session(inst) || is_image_session(inst))
|
||||
input_min_count = 1;
|
||||
|
||||
return input_min_count;
|
||||
}
|
||||
|
||||
static int msm_buffer_dpb_count(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int count = 0;
|
||||
u32 color_fmt;
|
||||
|
||||
/* decoder dpb buffer count */
|
||||
if (is_decode_session(inst)) {
|
||||
color_fmt = inst->capabilities[PIX_FMTS].value;
|
||||
if (is_linear_colorformat(color_fmt)) {
|
||||
count = inst->fw_min_count ?
|
||||
inst->fw_min_count : inst->buffers.output.min_count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/* encoder dpb buffer count */
|
||||
return msm_vidc_get_recon_buf_count(inst);
|
||||
}
|
||||
|
||||
int msm_buffer_min_count_iris2(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
switch (buffer_type) {
|
||||
case MSM_VIDC_BUF_INPUT:
|
||||
case MSM_VIDC_BUF_INPUT_META:
|
||||
count = msm_vidc_input_min_count_iris2(inst);
|
||||
break;
|
||||
case MSM_VIDC_BUF_OUTPUT:
|
||||
case MSM_VIDC_BUF_OUTPUT_META:
|
||||
count = msm_vidc_output_min_count(inst);
|
||||
break;
|
||||
case MSM_VIDC_BUF_BIN:
|
||||
case MSM_VIDC_BUF_COMV:
|
||||
case MSM_VIDC_BUF_NON_COMV:
|
||||
case MSM_VIDC_BUF_LINE:
|
||||
case MSM_VIDC_BUF_PERSIST:
|
||||
case MSM_VIDC_BUF_ARP:
|
||||
case MSM_VIDC_BUF_VPSS:
|
||||
count = msm_vidc_internal_buffer_count(inst, buffer_type);
|
||||
break;
|
||||
case MSM_VIDC_BUF_DPB:
|
||||
count = msm_buffer_dpb_count(inst);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
i_vpr_l(inst, " min_count: type: %11s, count: %9u\n", buf_name(buffer_type), count);
|
||||
return count;
|
||||
}
|
||||
|
||||
int msm_buffer_extra_count_iris2(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
switch (buffer_type) {
|
||||
case MSM_VIDC_BUF_INPUT:
|
||||
case MSM_VIDC_BUF_INPUT_META:
|
||||
count = msm_vidc_input_extra_count(inst);
|
||||
break;
|
||||
case MSM_VIDC_BUF_OUTPUT:
|
||||
case MSM_VIDC_BUF_OUTPUT_META:
|
||||
count = msm_vidc_output_extra_count(inst);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "extra_count: type: %11s, count: %9u\n", buf_name(buffer_type), count);
|
||||
return count;
|
||||
}
|
@ -0,0 +1,960 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include "msm_vidc_iris2.h"
|
||||
#include "msm_vidc_buffer_iris2.h"
|
||||
#include "msm_vidc_power_iris2.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vidc_platform.h"
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_buffer.h"
|
||||
#include "msm_vidc_state.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
#include "msm_vidc_variant.h"
|
||||
#include "venus_hfi.h"
|
||||
|
||||
#define VIDEO_ARCH_LX 1
|
||||
|
||||
#define VCODEC_BASE_OFFS_IRIS2 0x00000000
|
||||
#define AON_MVP_NOC_RESET 0x0001F000
|
||||
#define CPU_BASE_OFFS_IRIS2 0x000A0000
|
||||
#define AON_BASE_OFFS 0x000E0000
|
||||
#define CPU_CS_BASE_OFFS_IRIS2 (CPU_BASE_OFFS_IRIS2)
|
||||
#define CPU_IC_BASE_OFFS_IRIS2 (CPU_BASE_OFFS_IRIS2)
|
||||
|
||||
#define CPU_CS_A2HSOFTINTCLR_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x1C)
|
||||
#define CPU_CS_VCICMD_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x20)
|
||||
#define CPU_CS_VCICMDARG0_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x24)
|
||||
#define CPU_CS_VCICMDARG1_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x28)
|
||||
#define CPU_CS_VCICMDARG2_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x2C)
|
||||
#define CPU_CS_VCICMDARG3_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x30)
|
||||
#define CPU_CS_VMIMSG_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x34)
|
||||
#define CPU_CS_VMIMSGAG0_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x38)
|
||||
#define CPU_CS_VMIMSGAG1_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x3C)
|
||||
#define CPU_CS_SCIACMD_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x48)
|
||||
#define CPU_CS_H2XSOFTINTEN_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x148)
|
||||
|
||||
/* HFI_CTRL_STATUS */
|
||||
#define CPU_CS_SCIACMDARG0_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x4C)
|
||||
#define CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_BMSK_IRIS2 0xfe
|
||||
#define CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY_IRIS2 0x100
|
||||
#define CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK_IRIS2 0x40000000
|
||||
|
||||
/* HFI_QTBL_INFO */
|
||||
#define CPU_CS_SCIACMDARG1_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x50)
|
||||
|
||||
/* HFI_QTBL_ADDR */
|
||||
#define CPU_CS_SCIACMDARG2_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x54)
|
||||
|
||||
/* HFI_VERSION_INFO */
|
||||
#define CPU_CS_SCIACMDARG3_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x58)
|
||||
|
||||
/* SFR_ADDR */
|
||||
#define CPU_CS_SCIBCMD_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x5C)
|
||||
|
||||
/* MMAP_ADDR */
|
||||
#define CPU_CS_SCIBCMDARG0_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x60)
|
||||
|
||||
/* UC_REGION_ADDR */
|
||||
#define CPU_CS_SCIBARG1_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x64)
|
||||
|
||||
/* UC_REGION_ADDR */
|
||||
#define CPU_CS_SCIBARG2_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x68)
|
||||
|
||||
#define CPU_CS_AHB_BRIDGE_SYNC_RESET (CPU_CS_BASE_OFFS_IRIS2 + 0x160)
|
||||
#define CPU_CS_AHB_BRIDGE_SYNC_RESET_STATUS (CPU_CS_BASE_OFFS_IRIS2 + 0x164)
|
||||
|
||||
/* FAL10 Feature Control */
|
||||
#define CPU_CS_X2RPMh_IRIS2 (CPU_CS_BASE_OFFS_IRIS2 + 0x168)
|
||||
#define CPU_CS_X2RPMh_MASK0_BMSK_IRIS2 0x1
|
||||
#define CPU_CS_X2RPMh_MASK0_SHFT_IRIS2 0x0
|
||||
#define CPU_CS_X2RPMh_MASK1_BMSK_IRIS2 0x2
|
||||
#define CPU_CS_X2RPMh_MASK1_SHFT_IRIS2 0x1
|
||||
#define CPU_CS_X2RPMh_SWOVERRIDE_BMSK_IRIS2 0x4
|
||||
#define CPU_CS_X2RPMh_SWOVERRIDE_SHFT_IRIS2 0x3
|
||||
|
||||
#define CPU_IC_SOFTINT_IRIS2 (CPU_IC_BASE_OFFS_IRIS2 + 0x150)
|
||||
#define CPU_IC_SOFTINT_H2A_SHFT_IRIS2 0x0
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* MODULE: AON_MVP_NOC_RESET_REGISTERS
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
#define AON_WRAPPER_MVP_NOC_RESET_REQ (AON_MVP_NOC_RESET + 0x000)
|
||||
#define AON_WRAPPER_MVP_NOC_RESET_ACK (AON_MVP_NOC_RESET + 0x004)
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* MODULE: wrapper
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
#define WRAPPER_BASE_OFFS_IRIS2 0x000B0000
|
||||
#define WRAPPER_INTR_STATUS_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x0C)
|
||||
#define WRAPPER_INTR_STATUS_A2HWD_BMSK_IRIS2 0x8
|
||||
#define WRAPPER_INTR_STATUS_A2H_BMSK_IRIS2 0x4
|
||||
|
||||
#define WRAPPER_INTR_MASK_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x10)
|
||||
#define WRAPPER_INTR_MASK_A2HWD_BMSK_IRIS2 0x8
|
||||
#define WRAPPER_INTR_MASK_A2HCPU_BMSK_IRIS2 0x4
|
||||
|
||||
#define WRAPPER_CPU_CLOCK_CONFIG_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x2000)
|
||||
#define WRAPPER_CPU_CGC_DIS_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x2010)
|
||||
#define WRAPPER_CPU_STATUS_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x2014)
|
||||
|
||||
#define WRAPPER_DEBUG_BRIDGE_LPI_CONTROL_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x54)
|
||||
#define WRAPPER_DEBUG_BRIDGE_LPI_STATUS_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x58)
|
||||
#define WRAPPER_CORE_CLOCK_CONFIG_IRIS2 (WRAPPER_BASE_OFFS_IRIS2 + 0x88)
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* MODULE: tz_wrapper
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
#define WRAPPER_TZ_BASE_OFFS 0x000C0000
|
||||
#define WRAPPER_TZ_CPU_CLOCK_CONFIG (WRAPPER_TZ_BASE_OFFS)
|
||||
#define WRAPPER_TZ_CPU_STATUS (WRAPPER_TZ_BASE_OFFS + 0x10)
|
||||
|
||||
#define CTRL_INIT_IRIS2 CPU_CS_SCIACMD_IRIS2
|
||||
|
||||
#define CTRL_STATUS_IRIS2 CPU_CS_SCIACMDARG0_IRIS2
|
||||
#define CTRL_ERROR_STATUS__M_IRIS2 \
|
||||
CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_BMSK_IRIS2
|
||||
#define CTRL_INIT_IDLE_MSG_BMSK_IRIS2 \
|
||||
CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK_IRIS2
|
||||
#define CTRL_STATUS_PC_READY_IRIS2 \
|
||||
CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY_IRIS2
|
||||
|
||||
|
||||
#define QTBL_INFO_IRIS2 CPU_CS_SCIACMDARG1_IRIS2
|
||||
|
||||
#define QTBL_ADDR_IRIS2 CPU_CS_SCIACMDARG2_IRIS2
|
||||
|
||||
#define VERSION_INFO_IRIS2 CPU_CS_SCIACMDARG3_IRIS2
|
||||
|
||||
#define SFR_ADDR_IRIS2 CPU_CS_SCIBCMD_IRIS2
|
||||
#define MMAP_ADDR_IRIS2 CPU_CS_SCIBCMDARG0_IRIS2
|
||||
#define UC_REGION_ADDR_IRIS2 CPU_CS_SCIBARG1_IRIS2
|
||||
#define UC_REGION_SIZE_IRIS2 CPU_CS_SCIBARG2_IRIS2
|
||||
|
||||
#define AON_WRAPPER_MVP_NOC_LPI_CONTROL (AON_BASE_OFFS)
|
||||
#define AON_WRAPPER_MVP_NOC_LPI_STATUS (AON_BASE_OFFS + 0x4)
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* MODULE: VCODEC_SS registers
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
#define VCODEC_SS_IDLE_STATUSn (VCODEC_BASE_OFFS_IRIS2 + 0x70)
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* MODULE: vcodec noc error log registers (iris2)
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
#define VCODEC_NOC_VIDEO_A_NOC_BASE_OFFS 0x00010000
|
||||
#define VCODEC_NOC_ERL_MAIN_SWID_LOW 0x00011200
|
||||
#define VCODEC_NOC_ERL_MAIN_SWID_HIGH 0x00011204
|
||||
#define VCODEC_NOC_ERL_MAIN_MAINCTL_LOW 0x00011208
|
||||
#define VCODEC_NOC_ERL_MAIN_ERRVLD_LOW 0x00011210
|
||||
#define VCODEC_NOC_ERL_MAIN_ERRCLR_LOW 0x00011218
|
||||
#define VCODEC_NOC_ERL_MAIN_ERRLOG0_LOW 0x00011220
|
||||
#define VCODEC_NOC_ERL_MAIN_ERRLOG0_HIGH 0x00011224
|
||||
#define VCODEC_NOC_ERL_MAIN_ERRLOG1_LOW 0x00011228
|
||||
#define VCODEC_NOC_ERL_MAIN_ERRLOG1_HIGH 0x0001122C
|
||||
#define VCODEC_NOC_ERL_MAIN_ERRLOG2_LOW 0x00011230
|
||||
#define VCODEC_NOC_ERL_MAIN_ERRLOG2_HIGH 0x00011234
|
||||
#define VCODEC_NOC_ERL_MAIN_ERRLOG3_LOW 0x00011238
|
||||
#define VCODEC_NOC_ERL_MAIN_ERRLOG3_HIGH 0x0001123C
|
||||
|
||||
static int __interrupt_init_iris2(struct msm_vidc_core *core)
|
||||
{
|
||||
u32 mask_val = 0;
|
||||
int rc = 0;
|
||||
|
||||
/* All interrupts should be disabled initially 0x1F6 : Reset value */
|
||||
rc = __read_register(core, WRAPPER_INTR_MASK_IRIS2, &mask_val);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Write 0 to unmask CPU and WD interrupts */
|
||||
mask_val &= ~(WRAPPER_INTR_MASK_A2HWD_BMSK_IRIS2 |
|
||||
WRAPPER_INTR_MASK_A2HCPU_BMSK_IRIS2);
|
||||
rc = __write_register(core, WRAPPER_INTR_MASK_IRIS2, mask_val);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __setup_ucregion_memory_map_iris2(struct msm_vidc_core *core)
|
||||
{
|
||||
u32 value;
|
||||
int rc = 0;
|
||||
|
||||
value = (u32)core->iface_q_table.align_device_addr;
|
||||
rc = __write_register(core, UC_REGION_ADDR_IRIS2, value);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
value = SHARED_QSIZE;
|
||||
rc = __write_register(core, UC_REGION_SIZE_IRIS2, value);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
value = (u32)core->iface_q_table.align_device_addr;
|
||||
rc = __write_register(core, QTBL_ADDR_IRIS2, value);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = __write_register(core, QTBL_INFO_IRIS2, 0x01);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* update queues vaddr for debug purpose */
|
||||
value = (u32)((u64)core->iface_q_table.align_virtual_addr);
|
||||
rc = __write_register(core, CPU_CS_VCICMDARG0_IRIS2, value);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
value = (u32)((u64)core->iface_q_table.align_virtual_addr >> 32);
|
||||
rc = __write_register(core, CPU_CS_VCICMDARG1_IRIS2, value);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (core->sfr.align_device_addr) {
|
||||
value = (u32)core->sfr.align_device_addr + VIDEO_ARCH_LX;
|
||||
rc = __write_register(core, SFR_ADDR_IRIS2, value);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __power_off_iris2_hardware(struct msm_vidc_core *core)
|
||||
{
|
||||
int rc = 0, i;
|
||||
u32 value = 0;
|
||||
|
||||
if (is_core_sub_state(core, CORE_SUBSTATE_FW_PWR_CTRL)) {
|
||||
d_vpr_h("%s: hardware power control enabled\n", __func__);
|
||||
goto disable_power;
|
||||
}
|
||||
|
||||
/*
|
||||
* check to make sure core clock branch enabled else
|
||||
* we cannot read vcodec top idle register
|
||||
*/
|
||||
rc = __read_register(core, WRAPPER_CORE_CLOCK_CONFIG_IRIS2, &value);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (value) {
|
||||
d_vpr_h("%s: core clock config not enabled, enabling it to read vcodec registers\n",
|
||||
__func__);
|
||||
rc = __write_register(core, WRAPPER_CORE_CLOCK_CONFIG_IRIS2, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* add MNoC idle check before collapsing MVS0 per HPG update
|
||||
* poll for NoC DMA idle -> HPG 6.1.1
|
||||
*/
|
||||
for (i = 0; i < core->capabilities[NUM_VPP_PIPE].value; i++) {
|
||||
rc = __read_register_with_poll_timeout(core, VCODEC_SS_IDLE_STATUSn + 4*i,
|
||||
0x400000, 0x400000, 2000, 20000);
|
||||
if (rc)
|
||||
d_vpr_h("%s: VCODEC_SS_IDLE_STATUSn (%d) is not idle (%#x)\n",
|
||||
__func__, i, value);
|
||||
}
|
||||
|
||||
/* Apply partial reset on MSF interface and wait for ACK */
|
||||
rc = __write_register(core, AON_WRAPPER_MVP_NOC_RESET_REQ, 0x3);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = __read_register_with_poll_timeout(core, AON_WRAPPER_MVP_NOC_RESET_ACK,
|
||||
0x3, 0x3, 200, 2000);
|
||||
if (rc)
|
||||
d_vpr_h("%s: AON_WRAPPER_MVP_NOC_RESET assert failed\n", __func__);
|
||||
|
||||
/* De-assert partial reset on MSF interface and wait for ACK */
|
||||
rc = __write_register(core, AON_WRAPPER_MVP_NOC_RESET_REQ, 0x0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = __read_register_with_poll_timeout(core, AON_WRAPPER_MVP_NOC_RESET_ACK,
|
||||
0x3, 0x0, 200, 2000);
|
||||
if (rc)
|
||||
d_vpr_h("%s: AON_WRAPPER_MVP_NOC_RESET de-assert failed\n", __func__);
|
||||
|
||||
/*
|
||||
* Reset both sides of 2 ahb2ahb_bridges (TZ and non-TZ)
|
||||
* do we need to check status register here?
|
||||
*/
|
||||
rc = __write_register(core, CPU_CS_AHB_BRIDGE_SYNC_RESET, 0x3);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = __write_register(core, CPU_CS_AHB_BRIDGE_SYNC_RESET, 0x2);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = __write_register(core, CPU_CS_AHB_BRIDGE_SYNC_RESET, 0x0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
disable_power:
|
||||
/* power down process */
|
||||
rc = call_res_op(core, gdsc_off, core, "vcodec");
|
||||
if (rc) {
|
||||
d_vpr_e("%s: disable regulator vcodec failed\n", __func__);
|
||||
rc = 0;
|
||||
}
|
||||
rc = call_res_op(core, clk_disable, core, "video_cc_mvs0_clk");
|
||||
if (rc) {
|
||||
d_vpr_e("%s: disable unprepare video_cc_mvs0_clk failed\n", __func__);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __power_off_iris2_controller(struct msm_vidc_core *core)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/*
|
||||
* mask fal10_veto QLPAC error since fal10_veto can go 1
|
||||
* when pwwait == 0 and clamped to 0 -> HPG 6.1.2
|
||||
*/
|
||||
rc = __write_register(core, CPU_CS_X2RPMh_IRIS2, 0x3);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* set MNoC to low power, set PD_NOC_QREQ (bit 0) */
|
||||
rc = __write_register_masked(core, AON_WRAPPER_MVP_NOC_LPI_CONTROL,
|
||||
0x1, BIT(0));
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = __read_register_with_poll_timeout(core, AON_WRAPPER_MVP_NOC_LPI_STATUS,
|
||||
0x1, 0x1, 200, 2000);
|
||||
if (rc)
|
||||
d_vpr_h("%s: AON_WRAPPER_MVP_NOC_LPI_CONTROL failed\n", __func__);
|
||||
|
||||
/* Set Debug bridge Low power */
|
||||
rc = __write_register(core, WRAPPER_DEBUG_BRIDGE_LPI_CONTROL_IRIS2, 0x7);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = __read_register_with_poll_timeout(core, WRAPPER_DEBUG_BRIDGE_LPI_STATUS_IRIS2,
|
||||
0x7, 0x7, 200, 2000);
|
||||
if (rc)
|
||||
d_vpr_h("%s: debug bridge low power failed\n", __func__);
|
||||
|
||||
/* Debug bridge LPI release */
|
||||
rc = __write_register(core, WRAPPER_DEBUG_BRIDGE_LPI_CONTROL_IRIS2, 0x0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = __read_register_with_poll_timeout(core, WRAPPER_DEBUG_BRIDGE_LPI_STATUS_IRIS2,
|
||||
0xffffffff, 0x0, 200, 2000);
|
||||
if (rc)
|
||||
d_vpr_h("%s: debug bridge release failed\n", __func__);
|
||||
|
||||
/* Turn off MVP MVS0C core clock */
|
||||
rc = call_res_op(core, clk_disable, core, "video_cc_mvs0c_clk");
|
||||
if (rc) {
|
||||
d_vpr_e("%s: disable unprepare video_cc_mvs0c_clk failed\n", __func__);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
/* Disable gcc_video_axi0_clk clock */
|
||||
rc = call_res_op(core, clk_disable, core, "gcc_video_axi0_clk");
|
||||
if (rc) {
|
||||
d_vpr_e("%s: disable unprepare gcc_video_axi0_clk failed\n", __func__);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
rc = call_res_op(core, reset_bridge, core);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: reset bridge failed\n", __func__);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
/* power down process */
|
||||
rc = call_res_op(core, gdsc_off, core, "iris-ctl");
|
||||
if (rc) {
|
||||
d_vpr_e("%s: disable regulator iris-ctl failed\n", __func__);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __power_off_iris2(struct msm_vidc_core *core)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE))
|
||||
return 0;
|
||||
|
||||
/**
|
||||
* Reset video_cc_mvs0_clk_src value to resolve MMRM high video
|
||||
* clock projection issue.
|
||||
*/
|
||||
rc = call_res_op(core, set_clks, core, 0);
|
||||
if (rc)
|
||||
d_vpr_e("%s: resetting clocks failed\n", __func__);
|
||||
|
||||
if (__power_off_iris2_hardware(core))
|
||||
d_vpr_e("%s: failed to power off hardware\n", __func__);
|
||||
|
||||
if (__power_off_iris2_controller(core))
|
||||
d_vpr_e("%s: failed to power off controller\n", __func__);
|
||||
|
||||
rc = call_res_op(core, set_bw, core, 0, 0);
|
||||
if (rc)
|
||||
d_vpr_e("%s: failed to unvote buses\n", __func__);
|
||||
|
||||
if (!call_venus_op(core, watchdog, core, core->intr_status))
|
||||
disable_irq_nosync(core->resource->irq);
|
||||
|
||||
msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE, 0, __func__);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __power_on_iris2_controller(struct msm_vidc_core *core)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = call_res_op(core, gdsc_on, core, "iris-ctl");
|
||||
if (rc)
|
||||
goto fail_regulator;
|
||||
|
||||
rc = call_res_op(core, reset_bridge, core);
|
||||
if (rc)
|
||||
goto fail_reset_ahb2axi;
|
||||
|
||||
rc = call_res_op(core, clk_enable, core, "gcc_video_axi0_clk");
|
||||
if (rc)
|
||||
goto fail_clk_axi;
|
||||
|
||||
rc = call_res_op(core, clk_enable, core, "video_cc_mvs0c_clk");
|
||||
if (rc)
|
||||
goto fail_clk_controller;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_clk_controller:
|
||||
call_res_op(core, clk_disable, core, "gcc_video_axi0_clk");
|
||||
fail_clk_axi:
|
||||
fail_reset_ahb2axi:
|
||||
call_res_op(core, gdsc_off, core, "iris-ctl");
|
||||
fail_regulator:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __power_on_iris2_hardware(struct msm_vidc_core *core)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = call_res_op(core, gdsc_on, core, "vcodec");
|
||||
if (rc)
|
||||
goto fail_regulator;
|
||||
|
||||
rc = call_res_op(core, clk_enable, core, "video_cc_mvs0_clk");
|
||||
if (rc)
|
||||
goto fail_clk_controller;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_clk_controller:
|
||||
call_res_op(core, gdsc_off, core, "vcodec");
|
||||
fail_regulator:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __power_on_iris2(struct msm_vidc_core *core)
|
||||
{
|
||||
struct frequency_table *freq_tbl;
|
||||
u32 freq = 0;
|
||||
int rc = 0;
|
||||
|
||||
if (is_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE))
|
||||
return 0;
|
||||
|
||||
if (!core_in_valid_state(core)) {
|
||||
d_vpr_e("%s: invalid core state %s\n",
|
||||
__func__, core_state_name(core->state));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Vote for all hardware resources */
|
||||
rc = call_res_op(core, set_bw, core, INT_MAX, INT_MAX);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: failed to vote buses, rc %d\n", __func__, rc);
|
||||
goto fail_vote_buses;
|
||||
}
|
||||
|
||||
rc = __power_on_iris2_controller(core);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: failed to power on iris2 controller\n", __func__);
|
||||
goto fail_power_on_controller;
|
||||
}
|
||||
|
||||
rc = __power_on_iris2_hardware(core);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: failed to power on iris2 hardware\n", __func__);
|
||||
goto fail_power_on_hardware;
|
||||
}
|
||||
/* video controller and hardware powered on successfully */
|
||||
rc = msm_vidc_change_core_sub_state(core, 0, CORE_SUBSTATE_POWER_ENABLE, __func__);
|
||||
if (rc)
|
||||
goto fail_power_on_substate;
|
||||
|
||||
freq_tbl = core->resource->freq_set.freq_tbl;
|
||||
freq = core->power.clk_freq ? core->power.clk_freq :
|
||||
freq_tbl[0].freq;
|
||||
|
||||
rc = call_res_op(core, set_clks, core, freq);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: failed to scale clocks\n", __func__);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
core->power.clk_freq = freq;
|
||||
|
||||
/*
|
||||
* Re-program all of the registers that get reset as a result of
|
||||
* regulator_disable() and _enable()
|
||||
*/
|
||||
__set_registers(core);
|
||||
|
||||
__interrupt_init_iris2(core);
|
||||
core->intr_status = 0;
|
||||
enable_irq(core->resource->irq);
|
||||
|
||||
return rc;
|
||||
|
||||
fail_power_on_substate:
|
||||
__power_off_iris2_hardware(core);
|
||||
fail_power_on_hardware:
|
||||
__power_off_iris2_controller(core);
|
||||
fail_power_on_controller:
|
||||
call_res_op(core, set_bw, core, 0, 0);
|
||||
fail_vote_buses:
|
||||
msm_vidc_change_core_sub_state(core, CORE_SUBSTATE_POWER_ENABLE, 0, __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __prepare_pc_iris2(struct msm_vidc_core *core)
|
||||
{
|
||||
int rc = 0;
|
||||
u32 wfi_status = 0, idle_status = 0, pc_ready = 0;
|
||||
u32 ctrl_status = 0;
|
||||
|
||||
rc = __read_register(core, CTRL_STATUS_IRIS2, &ctrl_status);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
pc_ready = ctrl_status & CTRL_STATUS_PC_READY_IRIS2;
|
||||
idle_status = ctrl_status & BIT(30);
|
||||
|
||||
if (pc_ready) {
|
||||
d_vpr_h("Already in pc_ready state\n");
|
||||
return 0;
|
||||
}
|
||||
rc = __read_register(core, WRAPPER_TZ_CPU_STATUS, &wfi_status);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
wfi_status &= BIT(0);
|
||||
if (!wfi_status || !idle_status) {
|
||||
d_vpr_e("Skipping PC, wfi status not set\n");
|
||||
goto skip_power_off;
|
||||
}
|
||||
|
||||
rc = __prepare_pc(core);
|
||||
if (rc) {
|
||||
d_vpr_e("Failed __prepare_pc %d\n", rc);
|
||||
goto skip_power_off;
|
||||
}
|
||||
|
||||
rc = __read_register_with_poll_timeout(core, CTRL_STATUS_IRIS2,
|
||||
CTRL_STATUS_PC_READY_IRIS2, CTRL_STATUS_PC_READY_IRIS2, 250, 2500);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: Skip PC. Ctrl status not set\n", __func__);
|
||||
goto skip_power_off;
|
||||
}
|
||||
|
||||
rc = __read_register_with_poll_timeout(core, WRAPPER_TZ_CPU_STATUS,
|
||||
BIT(0), 0x1, 250, 2500);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: Skip PC. Wfi status not set\n", __func__);
|
||||
goto skip_power_off;
|
||||
}
|
||||
return rc;
|
||||
|
||||
skip_power_off:
|
||||
rc = __read_register(core, CTRL_STATUS_IRIS2, &ctrl_status);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = __read_register(core, WRAPPER_TZ_CPU_STATUS, &wfi_status);
|
||||
if (rc)
|
||||
return rc;
|
||||
wfi_status &= BIT(0);
|
||||
d_vpr_e("Skip PC, wfi=%#x, idle=%#x, pcr=%#x, ctrl=%#x)\n",
|
||||
wfi_status, idle_status, pc_ready, ctrl_status);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static int __raise_interrupt_iris2(struct msm_vidc_core *core)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = __write_register(core, CPU_IC_SOFTINT_IRIS2, 1 << CPU_IC_SOFTINT_H2A_SHFT_IRIS2);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __watchdog_iris2(struct msm_vidc_core *core, u32 intr_status)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (intr_status & WRAPPER_INTR_STATUS_A2HWD_BMSK_IRIS2) {
|
||||
d_vpr_e("%s: received watchdog interrupt\n", __func__);
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __noc_error_info_iris2(struct msm_vidc_core *core)
|
||||
{
|
||||
/*
|
||||
* we are not supposed to access vcodec subsystem registers
|
||||
* unless vcodec core clock WRAPPER_CORE_CLOCK_CONFIG_IRIS2 is enabled.
|
||||
* core clock might have been disabled by video firmware as part of
|
||||
* inter frame power collapse (power plane control feature).
|
||||
*/
|
||||
|
||||
/*
|
||||
val = __read_register(core, VCODEC_NOC_ERL_MAIN_SWID_LOW);
|
||||
d_vpr_e("VCODEC_NOC_ERL_MAIN_SWID_LOW: %#x\n", val);
|
||||
val = __read_register(core, VCODEC_NOC_ERL_MAIN_SWID_HIGH);
|
||||
d_vpr_e("VCODEC_NOC_ERL_MAIN_SWID_HIGH: %#x\n", val);
|
||||
val = __read_register(core, VCODEC_NOC_ERL_MAIN_MAINCTL_LOW);
|
||||
d_vpr_e("VCODEC_NOC_ERL_MAIN_MAINCTL_LOW: %#x\n", val);
|
||||
val = __read_register(core, VCODEC_NOC_ERL_MAIN_ERRVLD_LOW);
|
||||
d_vpr_e("VCODEC_NOC_ERL_MAIN_ERRVLD_LOW: %#x\n", val);
|
||||
val = __read_register(core, VCODEC_NOC_ERL_MAIN_ERRCLR_LOW);
|
||||
d_vpr_e("VCODEC_NOC_ERL_MAIN_ERRCLR_LOW: %#x\n", val);
|
||||
val = __read_register(core, VCODEC_NOC_ERL_MAIN_ERRLOG0_LOW);
|
||||
d_vpr_e("VCODEC_NOC_ERL_MAIN_ERRLOG0_LOW: %#x\n", val);
|
||||
val = __read_register(core, VCODEC_NOC_ERL_MAIN_ERRLOG0_HIGH);
|
||||
d_vpr_e("VCODEC_NOC_ERL_MAIN_ERRLOG0_HIGH: %#x\n", val);
|
||||
val = __read_register(core, VCODEC_NOC_ERL_MAIN_ERRLOG1_LOW);
|
||||
d_vpr_e("VCODEC_NOC_ERL_MAIN_ERRLOG1_LOW: %#x\n", val);
|
||||
val = __read_register(core, VCODEC_NOC_ERL_MAIN_ERRLOG1_HIGH);
|
||||
d_vpr_e("VCODEC_NOC_ERL_MAIN_ERRLOG1_HIGH: %#x\n", val);
|
||||
val = __read_register(core, VCODEC_NOC_ERL_MAIN_ERRLOG2_LOW);
|
||||
d_vpr_e("VCODEC_NOC_ERL_MAIN_ERRLOG2_LOW: %#x\n", val);
|
||||
val = __read_register(core, VCODEC_NOC_ERL_MAIN_ERRLOG2_HIGH);
|
||||
d_vpr_e("VCODEC_NOC_ERL_MAIN_ERRLOG2_HIGH: %#x\n", val);
|
||||
val = __read_register(core, VCODEC_NOC_ERL_MAIN_ERRLOG3_LOW);
|
||||
d_vpr_e("VCODEC_NOC_ERL_MAIN_ERRLOG3_LOW: %#x\n", val);
|
||||
val = __read_register(core, VCODEC_NOC_ERL_MAIN_ERRLOG3_HIGH);
|
||||
d_vpr_e("VCODEC_NOC_ERL_MAIN_ERRLOG3_HIGH: %#x\n", val);
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __clear_interrupt_iris2(struct msm_vidc_core *core)
|
||||
{
|
||||
u32 intr_status = 0, mask = 0;
|
||||
int rc = 0;
|
||||
|
||||
rc = __read_register(core, WRAPPER_INTR_STATUS_IRIS2, &intr_status);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
mask = (WRAPPER_INTR_STATUS_A2H_BMSK_IRIS2|
|
||||
WRAPPER_INTR_STATUS_A2HWD_BMSK_IRIS2|
|
||||
CTRL_INIT_IDLE_MSG_BMSK_IRIS2);
|
||||
|
||||
if (intr_status & mask) {
|
||||
core->intr_status |= intr_status;
|
||||
core->reg_count++;
|
||||
d_vpr_l("INTERRUPT: times: %d interrupt_status: %d\n",
|
||||
core->reg_count, intr_status);
|
||||
} else {
|
||||
core->spur_count++;
|
||||
}
|
||||
|
||||
rc = __write_register(core, CPU_CS_A2HSOFTINTCLR_IRIS2, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __boot_firmware_iris2(struct msm_vidc_core *core)
|
||||
{
|
||||
int rc = 0;
|
||||
u32 ctrl_init_val = 0, ctrl_status = 0, count = 0, max_tries = 1000;
|
||||
|
||||
rc = __setup_ucregion_memory_map_iris2(core);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
ctrl_init_val = BIT(0);
|
||||
|
||||
rc = __write_register(core, CTRL_INIT_IRIS2, ctrl_init_val);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
while (!ctrl_status && count < max_tries) {
|
||||
rc = __read_register(core, CTRL_STATUS_IRIS2, &ctrl_status);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if ((ctrl_status & CTRL_ERROR_STATUS__M_IRIS2) == 0x4) {
|
||||
d_vpr_e("invalid setting for UC_REGION\n");
|
||||
break;
|
||||
}
|
||||
|
||||
usleep_range(50, 100);
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count >= max_tries) {
|
||||
d_vpr_e("Error booting up vidc firmware\n");
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
/* Enable interrupt before sending commands to venus */
|
||||
rc = __write_register(core, CPU_CS_H2XSOFTINTEN_IRIS2, 0x1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = __write_register(core, CPU_CS_X2RPMh_IRIS2, 0x0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_decide_work_mode_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 work_mode;
|
||||
struct v4l2_format *inp_f;
|
||||
u32 width, height;
|
||||
bool res_ok = false;
|
||||
|
||||
work_mode = MSM_VIDC_STAGE_2;
|
||||
inp_f = &inst->fmts[INPUT_PORT];
|
||||
|
||||
if (is_image_decode_session(inst))
|
||||
work_mode = MSM_VIDC_STAGE_1;
|
||||
|
||||
if (is_image_session(inst))
|
||||
goto exit;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
height = inp_f->fmt.pix_mp.height;
|
||||
width = inp_f->fmt.pix_mp.width;
|
||||
res_ok = res_is_less_than(width, height, 1280, 720);
|
||||
if (inst->capabilities[CODED_FRAMES].value ==
|
||||
CODED_FRAMES_INTERLACE ||
|
||||
inst->capabilities[LOWLATENCY_MODE].value ||
|
||||
res_ok) {
|
||||
work_mode = MSM_VIDC_STAGE_1;
|
||||
}
|
||||
} else if (is_encode_session(inst)) {
|
||||
height = inst->crop.height;
|
||||
width = inst->crop.width;
|
||||
res_ok = !res_is_greater_than(width, height, 4096, 2160);
|
||||
if (res_ok &&
|
||||
(inst->capabilities[LOWLATENCY_MODE].value)) {
|
||||
work_mode = MSM_VIDC_STAGE_1;
|
||||
}
|
||||
if (inst->capabilities[SLICE_MODE].value ==
|
||||
V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
|
||||
work_mode = MSM_VIDC_STAGE_1;
|
||||
}
|
||||
if (inst->capabilities[LOSSLESS].value)
|
||||
work_mode = MSM_VIDC_STAGE_2;
|
||||
|
||||
if (!inst->capabilities[GOP_SIZE].value)
|
||||
work_mode = MSM_VIDC_STAGE_2;
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: invalid session type\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
exit:
|
||||
i_vpr_h(inst, "Configuring work mode = %u low latency = %u, gop size = %u\n",
|
||||
work_mode, inst->capabilities[LOWLATENCY_MODE].value,
|
||||
inst->capabilities[GOP_SIZE].value);
|
||||
msm_vidc_update_cap_value(inst, STAGE, work_mode, __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_decide_work_route_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 work_route;
|
||||
struct msm_vidc_core *core;
|
||||
|
||||
core = inst->core;
|
||||
work_route = core->capabilities[NUM_VPP_PIPE].value;
|
||||
|
||||
if (is_image_session(inst))
|
||||
goto exit;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
if (inst->capabilities[CODED_FRAMES].value ==
|
||||
CODED_FRAMES_INTERLACE)
|
||||
work_route = MSM_VIDC_PIPE_1;
|
||||
} else if (is_encode_session(inst)) {
|
||||
u32 slice_mode;
|
||||
|
||||
slice_mode = inst->capabilities[SLICE_MODE].value;
|
||||
|
||||
/*TODO Pipe=1 for legacy CBR*/
|
||||
if (slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES)
|
||||
work_route = MSM_VIDC_PIPE_1;
|
||||
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: invalid session type\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
exit:
|
||||
i_vpr_h(inst, "Configuring work route = %u", work_route);
|
||||
msm_vidc_update_cap_value(inst, PIPE, work_route, __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_adjust_blur_type_iris2(void *instance, struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
s32 adjusted_value;
|
||||
struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
|
||||
s32 rc_type = -1, cac = -1;
|
||||
s32 pix_fmts = -1, min_quality = -1;
|
||||
|
||||
adjusted_value = ctrl ? ctrl->val :
|
||||
inst->capabilities[BLUR_TYPES].value;
|
||||
|
||||
if (adjusted_value == MSM_VIDC_BLUR_NONE)
|
||||
return 0;
|
||||
|
||||
if (msm_vidc_get_parent_value(inst, BLUR_TYPES, BITRATE_MODE,
|
||||
&rc_type, __func__) ||
|
||||
msm_vidc_get_parent_value(inst, BLUR_TYPES,
|
||||
CONTENT_ADAPTIVE_CODING, &cac, __func__) ||
|
||||
msm_vidc_get_parent_value(inst, BLUR_TYPES, PIX_FMTS,
|
||||
&pix_fmts, __func__) ||
|
||||
msm_vidc_get_parent_value(inst, BLUR_TYPES, MIN_QUALITY,
|
||||
&min_quality, __func__))
|
||||
return -EINVAL;
|
||||
|
||||
if (adjusted_value == MSM_VIDC_BLUR_EXTERNAL) {
|
||||
if (is_scaling_enabled(inst) || min_quality)
|
||||
adjusted_value = MSM_VIDC_BLUR_NONE;
|
||||
} else if (adjusted_value == MSM_VIDC_BLUR_ADAPTIVE) {
|
||||
if (is_scaling_enabled(inst) || min_quality ||
|
||||
(rc_type != HFI_RC_VBR_CFR) ||
|
||||
!cac ||
|
||||
is_10bit_colorformat(pix_fmts)) {
|
||||
adjusted_value = MSM_VIDC_BLUR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
msm_vidc_update_cap_value(inst, BLUR_TYPES,
|
||||
adjusted_value, __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_decide_quality_mode_iris2(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 mbpf, mbps, max_hq_mbpf, max_hq_mbps;
|
||||
u32 mode = MSM_VIDC_POWER_SAVE_MODE;
|
||||
|
||||
if (!is_encode_session(inst))
|
||||
return 0;
|
||||
|
||||
/* image session always runs at quality mode */
|
||||
if (is_image_session(inst)) {
|
||||
mode = MSM_VIDC_MAX_QUALITY_MODE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbpf = msm_vidc_get_mbs_per_frame(inst);
|
||||
mbps = mbpf * msm_vidc_get_fps(inst);
|
||||
core = inst->core;
|
||||
max_hq_mbpf = core->capabilities[MAX_MBPF_HQ].value;;
|
||||
max_hq_mbps = core->capabilities[MAX_MBPS_HQ].value;;
|
||||
|
||||
/* NRT session to have max quality unless client configures lesser complexity */
|
||||
if (!is_realtime_session(inst) && mbpf <= max_hq_mbpf) {
|
||||
mode = MSM_VIDC_MAX_QUALITY_MODE;
|
||||
if (inst->capabilities[COMPLEXITY].value < DEFAULT_COMPLEXITY)
|
||||
mode = MSM_VIDC_POWER_SAVE_MODE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Power saving always disabled for CQ and LOSSLESS RC modes. */
|
||||
if (inst->capabilities[LOSSLESS].value ||
|
||||
(mbpf <= max_hq_mbpf && mbps <= max_hq_mbps))
|
||||
mode = MSM_VIDC_MAX_QUALITY_MODE;
|
||||
|
||||
exit:
|
||||
msm_vidc_update_cap_value(inst, QUALITY_MODE, mode, __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct msm_vidc_venus_ops iris2_ops = {
|
||||
.boot_firmware = __boot_firmware_iris2,
|
||||
.raise_interrupt = __raise_interrupt_iris2,
|
||||
.clear_interrupt = __clear_interrupt_iris2,
|
||||
.power_on = __power_on_iris2,
|
||||
.power_off = __power_off_iris2,
|
||||
.prepare_pc = __prepare_pc_iris2,
|
||||
.watchdog = __watchdog_iris2,
|
||||
.noc_error_info = __noc_error_info_iris2,
|
||||
};
|
||||
|
||||
static struct msm_vidc_session_ops msm_session_ops = {
|
||||
.buffer_size = msm_buffer_size_iris2,
|
||||
.min_count = msm_buffer_min_count_iris2,
|
||||
.extra_count = msm_buffer_extra_count_iris2,
|
||||
.calc_freq = msm_vidc_calc_freq_iris2,
|
||||
.calc_bw = msm_vidc_calc_bw_iris2,
|
||||
.decide_work_route = msm_vidc_decide_work_route_iris2,
|
||||
.decide_work_mode = msm_vidc_decide_work_mode_iris2,
|
||||
.decide_quality_mode = msm_vidc_decide_quality_mode_iris2,
|
||||
};
|
||||
|
||||
int msm_vidc_init_iris2(struct msm_vidc_core *core)
|
||||
{
|
||||
d_vpr_h("%s()\n", __func__);
|
||||
core->venus_ops = &iris2_ops;
|
||||
core->session_ops = &msm_session_ops;
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,706 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "msm_vidc_power_iris2.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
|
||||
u64 msm_vidc_calc_freq_iris2(struct msm_vidc_inst *inst, u32 data_size)
|
||||
{
|
||||
u64 freq = 0;
|
||||
struct msm_vidc_core *core;
|
||||
u64 vsp_cycles = 0, vpp_cycles = 0, fw_cycles = 0;
|
||||
u64 fw_vpp_cycles = 0, bitrate = 0;
|
||||
u32 vpp_cycles_per_mb;
|
||||
u32 mbs_per_second;
|
||||
u32 operating_rate, vsp_factor_num = 1, vsp_factor_den = 1;
|
||||
u32 base_cycles = 0;
|
||||
u32 fps, mbpf;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
mbpf = msm_vidc_get_mbs_per_frame(inst);
|
||||
fps = inst->max_rate;
|
||||
mbs_per_second = mbpf * fps;
|
||||
|
||||
/*
|
||||
* Calculate vpp, vsp, fw cycles separately for encoder and decoder.
|
||||
* Even though, most part is common now, in future it may change
|
||||
* between them.
|
||||
*/
|
||||
fw_cycles = fps * inst->capabilities[MB_CYCLES_FW].value;
|
||||
fw_vpp_cycles = fps * inst->capabilities[MB_CYCLES_FW_VPP].value;
|
||||
|
||||
if (is_encode_session(inst)) {
|
||||
vpp_cycles_per_mb = is_low_power_session(inst) ?
|
||||
inst->capabilities[MB_CYCLES_LP].value :
|
||||
inst->capabilities[MB_CYCLES_VPP].value;
|
||||
|
||||
vpp_cycles = mbs_per_second * vpp_cycles_per_mb /
|
||||
inst->capabilities[PIPE].value;
|
||||
|
||||
/* Factor 1.25 for IbP and 1.375 for I1B2b1P GOP structure */
|
||||
if (inst->capabilities[B_FRAME].value > 1)
|
||||
vpp_cycles += (vpp_cycles / 4) + (vpp_cycles / 8);
|
||||
else if (inst->capabilities[B_FRAME].value)
|
||||
vpp_cycles += vpp_cycles / 4;
|
||||
/* 21 / 20 is minimum overhead factor */
|
||||
vpp_cycles += max(div_u64(vpp_cycles, 20), fw_vpp_cycles);
|
||||
/* 1.01 is multi-pipe overhead */
|
||||
if (inst->capabilities[PIPE].value > 1)
|
||||
vpp_cycles += div_u64(vpp_cycles, 100);
|
||||
/*
|
||||
* 1080p@480fps usecase needs exactly 338MHz
|
||||
* without any margin left. Hence, adding 2 percent
|
||||
* extra to bump it to next level (366MHz).
|
||||
*/
|
||||
if (fps == 480)
|
||||
vpp_cycles += div_u64(vpp_cycles * 2, 100);
|
||||
|
||||
/*
|
||||
* Add 5 percent extra for 720p@960fps use case
|
||||
* to bump it to next level (366MHz).
|
||||
*/
|
||||
if (fps == 960)
|
||||
vpp_cycles += div_u64(vpp_cycles * 5, 100);
|
||||
|
||||
/* VSP */
|
||||
/* bitrate is based on fps, scale it using operating rate */
|
||||
operating_rate = inst->capabilities[OPERATING_RATE].value >> 16;
|
||||
if (operating_rate >
|
||||
(inst->capabilities[FRAME_RATE].value >> 16) &&
|
||||
(inst->capabilities[FRAME_RATE].value >> 16)) {
|
||||
vsp_factor_num = operating_rate;
|
||||
vsp_factor_den = inst->capabilities[FRAME_RATE].value >> 16;
|
||||
}
|
||||
vsp_cycles = div_u64(((u64)inst->capabilities[BIT_RATE].value *
|
||||
vsp_factor_num), vsp_factor_den);
|
||||
|
||||
base_cycles = inst->capabilities[MB_CYCLES_VSP].value;
|
||||
if (inst->codec == MSM_VIDC_VP9) {
|
||||
vsp_cycles = div_u64(vsp_cycles * 170, 100);
|
||||
} else if (inst->capabilities[ENTROPY_MODE].value ==
|
||||
V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC) {
|
||||
vsp_cycles = div_u64(vsp_cycles * 135, 100);
|
||||
} else {
|
||||
base_cycles = 0;
|
||||
vsp_cycles = div_u64(vsp_cycles, 2);
|
||||
}
|
||||
/* VSP FW Overhead 1.05 */
|
||||
vsp_cycles = div_u64(vsp_cycles * 21, 20);
|
||||
|
||||
if (inst->capabilities[STAGE].value == MSM_VIDC_STAGE_1)
|
||||
vsp_cycles = vsp_cycles * 3;
|
||||
|
||||
vsp_cycles += mbs_per_second * base_cycles;
|
||||
|
||||
} else if (is_decode_session(inst)) {
|
||||
/* VPP */
|
||||
vpp_cycles = mbs_per_second * inst->capabilities[MB_CYCLES_VPP].value /
|
||||
inst->capabilities[PIPE].value;
|
||||
/* 21 / 20 is minimum overhead factor */
|
||||
vpp_cycles += max(vpp_cycles / 20, fw_vpp_cycles);
|
||||
/* 1.059 is multi-pipe overhead */
|
||||
if (inst->capabilities[PIPE].value > 1)
|
||||
vpp_cycles += div_u64(vpp_cycles * 59, 1000);
|
||||
|
||||
/* VSP */
|
||||
base_cycles = inst->has_bframe ?
|
||||
80 : inst->capabilities[MB_CYCLES_VSP].value;
|
||||
bitrate = fps * data_size * 8;
|
||||
vsp_cycles = bitrate;
|
||||
|
||||
if (inst->codec == MSM_VIDC_VP9) {
|
||||
vsp_cycles = div_u64(vsp_cycles * 170, 100);
|
||||
} else if (inst->capabilities[ENTROPY_MODE].value ==
|
||||
V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC) {
|
||||
vsp_cycles = div_u64(vsp_cycles * 135, 100);
|
||||
} else {
|
||||
base_cycles = 0;
|
||||
vsp_cycles = div_u64(vsp_cycles, 2);
|
||||
}
|
||||
/* VSP FW overhead 1.05 */
|
||||
vsp_cycles = div_u64(vsp_cycles * 21, 20);
|
||||
|
||||
if (inst->capabilities[STAGE].value == MSM_VIDC_STAGE_1)
|
||||
vsp_cycles = vsp_cycles * 3;
|
||||
|
||||
vsp_cycles += mbs_per_second * base_cycles;
|
||||
|
||||
/* Add 25 percent extra for 960fps use case */
|
||||
if (fps >= 960)
|
||||
vsp_cycles += div_u64(vpp_cycles * 25, 100);
|
||||
|
||||
if (inst->codec == MSM_VIDC_VP9 &&
|
||||
inst->capabilities[STAGE].value ==
|
||||
MSM_VIDC_STAGE_2 &&
|
||||
inst->capabilities[PIPE].value == 4 &&
|
||||
bitrate > 90000000)
|
||||
vsp_cycles = msm_vidc_max_freq(inst);
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: Unknown session type\n", __func__);
|
||||
return msm_vidc_max_freq(inst);
|
||||
}
|
||||
|
||||
freq = max(vpp_cycles, vsp_cycles);
|
||||
freq = max(freq, fw_cycles);
|
||||
|
||||
i_vpr_p(inst, "%s: filled len %d, required freq %llu, fps %u, mbpf %u\n",
|
||||
__func__, data_size, freq, fps, mbpf);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static u64 __calculate_decoder(struct vidc_bus_vote_data *d)
|
||||
{
|
||||
/*
|
||||
* XXX: Don't fool around with any of the hardcoded numbers unless you
|
||||
* know /exactly/ what you're doing. Many of these numbers are
|
||||
* measured heuristics and hardcoded numbers taken from the firmware.
|
||||
*/
|
||||
/* Decoder parameters */
|
||||
int width, height, lcu_size, fps, dpb_bpp;
|
||||
bool unified_dpb_opb, dpb_compression_enabled = true,
|
||||
opb_compression_enabled = false,
|
||||
llc_ref_read_l2_cache_enabled = false,
|
||||
llc_top_line_buf_enabled = false;
|
||||
fp_t dpb_read_compression_factor, dpb_opb_scaling_ratio,
|
||||
dpb_write_compression_factor, opb_write_compression_factor,
|
||||
qsmmu_bw_overhead_factor;
|
||||
bool is_h264_category = true;
|
||||
|
||||
/* Derived parameters */
|
||||
int lcu_per_frame, collocated_bytes_per_lcu, tnbr_per_lcu;
|
||||
unsigned long bitrate;
|
||||
unsigned int num_vpp_pipes;
|
||||
|
||||
fp_t bins_to_bit_factor, vsp_read_factor, vsp_write_factor,
|
||||
dpb_factor, dpb_write_factor, y_bw_no_ubwc_8bpp;
|
||||
fp_t y_bw_no_ubwc_10bpp = 0, y_bw_10bpp_p010 = 0,
|
||||
motion_vector_complexity = 0;
|
||||
fp_t dpb_total = 0;
|
||||
|
||||
/* Output parameters */
|
||||
struct {
|
||||
fp_t vsp_read, vsp_write, collocated_read, collocated_write,
|
||||
dpb_read, dpb_write, opb_read, opb_write,
|
||||
line_buffer_read, line_buffer_write,
|
||||
total;
|
||||
} ddr = {0};
|
||||
|
||||
struct {
|
||||
fp_t dpb_read, line_buffer_read, line_buffer_write, total;
|
||||
} llc = {0};
|
||||
|
||||
unsigned long ret = 0;
|
||||
unsigned int integer_part, frac_part;
|
||||
|
||||
width = max(d->input_width, BASELINE_DIMENSIONS.width);
|
||||
height = max(d->input_height, BASELINE_DIMENSIONS.height);
|
||||
|
||||
fps = d->fps;
|
||||
|
||||
lcu_size = d->lcu_size;
|
||||
|
||||
dpb_bpp = __bpp(d->color_formats[0]);
|
||||
|
||||
unified_dpb_opb = d->num_formats == 1;
|
||||
|
||||
dpb_opb_scaling_ratio = fp_div(FP_INT(d->input_width * d->input_height),
|
||||
FP_INT(d->output_width * d->output_height));
|
||||
|
||||
opb_compression_enabled = d->num_formats >= 2 &&
|
||||
__ubwc(d->color_formats[1]);
|
||||
|
||||
integer_part = Q16_INT(d->compression_ratio);
|
||||
frac_part = Q16_FRAC(d->compression_ratio);
|
||||
dpb_read_compression_factor = FP(integer_part, frac_part, 100);
|
||||
|
||||
integer_part = Q16_INT(d->complexity_factor);
|
||||
frac_part = Q16_FRAC(d->complexity_factor);
|
||||
motion_vector_complexity = FP(integer_part, frac_part, 100);
|
||||
|
||||
dpb_write_compression_factor = dpb_read_compression_factor;
|
||||
opb_write_compression_factor = opb_compression_enabled ?
|
||||
dpb_write_compression_factor : FP_ONE;
|
||||
|
||||
num_vpp_pipes = d->num_vpp_pipes;
|
||||
|
||||
if (d->codec == MSM_VIDC_HEVC ||
|
||||
d->codec == MSM_VIDC_HEIC ||
|
||||
d->codec == MSM_VIDC_VP9) {
|
||||
/* H264, VP8, MPEG2 use the same settings */
|
||||
/* HEVC, VP9 use the same setting */
|
||||
is_h264_category = false;
|
||||
}
|
||||
if (d->use_sys_cache) {
|
||||
llc_ref_read_l2_cache_enabled = true;
|
||||
if (is_h264_category)
|
||||
llc_top_line_buf_enabled = true;
|
||||
}
|
||||
|
||||
/* Derived parameters setup */
|
||||
lcu_per_frame = DIV_ROUND_UP(width, lcu_size) *
|
||||
DIV_ROUND_UP(height, lcu_size);
|
||||
|
||||
bitrate = DIV_ROUND_UP(d->bitrate, 1000000);
|
||||
|
||||
bins_to_bit_factor = FP_INT(4);
|
||||
|
||||
vsp_write_factor = bins_to_bit_factor;
|
||||
vsp_read_factor = bins_to_bit_factor + FP_INT(2);
|
||||
|
||||
collocated_bytes_per_lcu = lcu_size == 16 ? 16 :
|
||||
lcu_size == 32 ? 64 : 256;
|
||||
|
||||
dpb_factor = FP(1, 50, 100);
|
||||
dpb_write_factor = FP(1, 5, 100);
|
||||
|
||||
/* This change is applicable for all IRIS2 targets,
|
||||
* But currently being done only for IRIS2 with 2 pipe
|
||||
* and 1 pipe due to timeline constraints.
|
||||
*/
|
||||
if (num_vpp_pipes != 4)
|
||||
tnbr_per_lcu = lcu_size == 16 ? 64 :
|
||||
lcu_size == 32 ? 64 : 128;
|
||||
else
|
||||
tnbr_per_lcu = lcu_size == 16 ? 128 :
|
||||
lcu_size == 32 ? 64 : 128;
|
||||
|
||||
/* .... For DDR & LLC ...... */
|
||||
ddr.vsp_read = fp_div(fp_mult(FP_INT(bitrate),
|
||||
vsp_read_factor), FP_INT(8));
|
||||
ddr.vsp_write = fp_div(fp_mult(FP_INT(bitrate),
|
||||
vsp_write_factor), FP_INT(8));
|
||||
|
||||
ddr.collocated_read = fp_div(FP_INT(lcu_per_frame *
|
||||
collocated_bytes_per_lcu * fps), FP_INT(bps(1)));
|
||||
ddr.collocated_write = ddr.collocated_read;
|
||||
|
||||
y_bw_no_ubwc_8bpp = fp_div(FP_INT(width * height * fps),
|
||||
FP_INT(1000 * 1000));
|
||||
|
||||
if (dpb_bpp != 8) {
|
||||
y_bw_no_ubwc_10bpp =
|
||||
fp_div(fp_mult(y_bw_no_ubwc_8bpp, FP_INT(256)),
|
||||
FP_INT(192));
|
||||
y_bw_10bpp_p010 = y_bw_no_ubwc_8bpp * 2;
|
||||
}
|
||||
|
||||
ddr.dpb_read = dpb_bpp == 8 ? y_bw_no_ubwc_8bpp : y_bw_no_ubwc_10bpp;
|
||||
ddr.dpb_read = fp_div(fp_mult(ddr.dpb_read,
|
||||
fp_mult(dpb_factor, motion_vector_complexity)),
|
||||
dpb_read_compression_factor);
|
||||
|
||||
ddr.dpb_write = dpb_bpp == 8 ? y_bw_no_ubwc_8bpp : y_bw_no_ubwc_10bpp;
|
||||
ddr.dpb_write = fp_div(fp_mult(ddr.dpb_write,
|
||||
fp_mult(dpb_factor, dpb_write_factor)),
|
||||
dpb_write_compression_factor);
|
||||
|
||||
dpb_total = ddr.dpb_read + ddr.dpb_write;
|
||||
|
||||
if (llc_ref_read_l2_cache_enabled) {
|
||||
ddr.dpb_read = fp_div(ddr.dpb_read, is_h264_category ?
|
||||
FP(1, 30, 100) : FP(1, 14, 100));
|
||||
llc.dpb_read = dpb_total - ddr.dpb_write - ddr.dpb_read;
|
||||
}
|
||||
|
||||
ddr.opb_read = FP_ZERO;
|
||||
ddr.opb_write = unified_dpb_opb ? FP_ZERO : (dpb_bpp == 8 ?
|
||||
y_bw_no_ubwc_8bpp : (opb_compression_enabled ?
|
||||
y_bw_no_ubwc_10bpp : y_bw_10bpp_p010));
|
||||
ddr.opb_write = fp_div(fp_mult(dpb_factor, ddr.opb_write),
|
||||
fp_mult(dpb_opb_scaling_ratio, opb_write_compression_factor));
|
||||
|
||||
ddr.line_buffer_read =
|
||||
fp_div(FP_INT(tnbr_per_lcu * lcu_per_frame * fps),
|
||||
FP_INT(bps(1)));
|
||||
ddr.line_buffer_write = ddr.line_buffer_read;
|
||||
if (llc_top_line_buf_enabled) {
|
||||
llc.line_buffer_read = ddr.line_buffer_read;
|
||||
llc.line_buffer_write = ddr.line_buffer_write;
|
||||
ddr.line_buffer_write = ddr.line_buffer_read = FP_ZERO;
|
||||
}
|
||||
|
||||
ddr.total = ddr.vsp_read + ddr.vsp_write +
|
||||
ddr.collocated_read + ddr.collocated_write +
|
||||
ddr.dpb_read + ddr.dpb_write +
|
||||
ddr.opb_read + ddr.opb_write +
|
||||
ddr.line_buffer_read + ddr.line_buffer_write;
|
||||
|
||||
qsmmu_bw_overhead_factor = FP(1, 3, 100);
|
||||
|
||||
ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor);
|
||||
llc.total = llc.dpb_read + llc.line_buffer_read +
|
||||
llc.line_buffer_write + ddr.total;
|
||||
|
||||
/* Add 25 percent extra for 960fps use case */
|
||||
if (fps >= 960) {
|
||||
ddr.total += div_u64(ddr.total * 25, 100);
|
||||
llc.total += div_u64(llc.total * 25, 100);
|
||||
}
|
||||
|
||||
/* Dump all the variables for easier debugging */
|
||||
if (msm_vidc_debug & VIDC_BUS) {
|
||||
struct dump dump[] = {
|
||||
{"DECODER PARAMETERS", "", DUMP_HEADER_MAGIC},
|
||||
{"lcu size", "%d", lcu_size},
|
||||
{"dpb bitdepth", "%d", dpb_bpp},
|
||||
{"frame rate", "%d", fps},
|
||||
{"dpb/opb unified", "%d", unified_dpb_opb},
|
||||
{"dpb/opb downscaling ratio", DUMP_FP_FMT,
|
||||
dpb_opb_scaling_ratio},
|
||||
{"dpb compression", "%d", dpb_compression_enabled},
|
||||
{"opb compression", "%d", opb_compression_enabled},
|
||||
{"dpb read compression factor", DUMP_FP_FMT,
|
||||
dpb_read_compression_factor},
|
||||
{"dpb write compression factor", DUMP_FP_FMT,
|
||||
dpb_write_compression_factor},
|
||||
{"frame width", "%d", width},
|
||||
{"frame height", "%d", height},
|
||||
{"llc ref read l2 cache enabled", "%d",
|
||||
llc_ref_read_l2_cache_enabled},
|
||||
{"llc top line buf enabled", "%d",
|
||||
llc_top_line_buf_enabled},
|
||||
|
||||
{"DERIVED PARAMETERS (1)", "", DUMP_HEADER_MAGIC},
|
||||
{"lcus/frame", "%d", lcu_per_frame},
|
||||
{"bitrate (Mbit/sec)", "%d", bitrate},
|
||||
{"bins to bit factor", DUMP_FP_FMT, bins_to_bit_factor},
|
||||
{"dpb write factor", DUMP_FP_FMT, dpb_write_factor},
|
||||
{"vsp read factor", DUMP_FP_FMT, vsp_read_factor},
|
||||
{"vsp write factor", DUMP_FP_FMT, vsp_write_factor},
|
||||
{"tnbr/lcu", "%d", tnbr_per_lcu},
|
||||
{"collocated bytes/LCU", "%d", collocated_bytes_per_lcu},
|
||||
{"bw for NV12 8bpc)", DUMP_FP_FMT, y_bw_no_ubwc_8bpp},
|
||||
{"bw for NV12 10bpc)", DUMP_FP_FMT, y_bw_no_ubwc_10bpp},
|
||||
|
||||
{"DERIVED PARAMETERS (2)", "", DUMP_HEADER_MAGIC},
|
||||
{"mv complexity", DUMP_FP_FMT, motion_vector_complexity},
|
||||
{"qsmmu_bw_overhead_factor", DUMP_FP_FMT,
|
||||
qsmmu_bw_overhead_factor},
|
||||
|
||||
{"INTERMEDIATE DDR B/W", "", DUMP_HEADER_MAGIC},
|
||||
{"vsp read", DUMP_FP_FMT, ddr.vsp_read},
|
||||
{"vsp write", DUMP_FP_FMT, ddr.vsp_write},
|
||||
{"collocated read", DUMP_FP_FMT, ddr.collocated_read},
|
||||
{"collocated write", DUMP_FP_FMT, ddr.collocated_write},
|
||||
{"line buffer read", DUMP_FP_FMT, ddr.line_buffer_read},
|
||||
{"line buffer write", DUMP_FP_FMT, ddr.line_buffer_write},
|
||||
{"opb read", DUMP_FP_FMT, ddr.opb_read},
|
||||
{"opb write", DUMP_FP_FMT, ddr.opb_write},
|
||||
{"dpb read", DUMP_FP_FMT, ddr.dpb_read},
|
||||
{"dpb write", DUMP_FP_FMT, ddr.dpb_write},
|
||||
{"dpb total", DUMP_FP_FMT, dpb_total},
|
||||
{"INTERMEDIATE LLC B/W", "", DUMP_HEADER_MAGIC},
|
||||
{"llc dpb read", DUMP_FP_FMT, llc.dpb_read},
|
||||
{"llc line buffer read", DUMP_FP_FMT, llc.line_buffer_read},
|
||||
{"llc line buffer write", DUMP_FP_FMT, llc.line_buffer_write},
|
||||
|
||||
};
|
||||
__dump(dump, ARRAY_SIZE(dump));
|
||||
}
|
||||
|
||||
d->calc_bw_ddr = kbps(fp_round(ddr.total));
|
||||
d->calc_bw_llcc = kbps(fp_round(llc.total));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u64 __calculate_encoder(struct vidc_bus_vote_data *d)
|
||||
{
|
||||
/*
|
||||
* XXX: Don't fool around with any of the hardcoded numbers unless you
|
||||
* know /exactly/ what you're doing. Many of these numbers are
|
||||
* measured heuristics and hardcoded numbers taken from the firmware.
|
||||
*/
|
||||
/* Encoder Parameters */
|
||||
int width, height, fps, lcu_size, bitrate, lcu_per_frame,
|
||||
collocated_bytes_per_lcu, tnbr_per_lcu, dpb_bpp,
|
||||
original_color_format, vertical_tile_width, rotation;
|
||||
bool work_mode_1, original_compression_enabled,
|
||||
low_power, cropping_or_scaling,
|
||||
b_frames_enabled = false,
|
||||
llc_ref_chroma_cache_enabled = false,
|
||||
llc_top_line_buf_enabled = false,
|
||||
llc_vpss_rot_line_buf_enabled = false;
|
||||
|
||||
unsigned int bins_to_bit_factor;
|
||||
fp_t dpb_compression_factor,
|
||||
original_compression_factor,
|
||||
original_compression_factor_y,
|
||||
y_bw_no_ubwc_8bpp, y_bw_no_ubwc_10bpp = 0, y_bw_10bpp_p010 = 0,
|
||||
input_compression_factor,
|
||||
downscaling_ratio,
|
||||
ref_y_read_bw_factor, ref_cbcr_read_bw_factor,
|
||||
recon_write_bw_factor,
|
||||
total_ref_read_crcb,
|
||||
qsmmu_bw_overhead_factor;
|
||||
fp_t integer_part, frac_part;
|
||||
unsigned long ret = 0;
|
||||
|
||||
/* Output parameters */
|
||||
struct {
|
||||
fp_t vsp_read, vsp_write, collocated_read, collocated_write,
|
||||
ref_read_y, ref_read_crcb, ref_write,
|
||||
ref_write_overlap, orig_read,
|
||||
line_buffer_read, line_buffer_write,
|
||||
total;
|
||||
} ddr = {0};
|
||||
|
||||
struct {
|
||||
fp_t ref_read_crcb, line_buffer, total;
|
||||
} llc = {0};
|
||||
|
||||
/* Encoder Parameters setup */
|
||||
rotation = d->rotation;
|
||||
cropping_or_scaling = false;
|
||||
vertical_tile_width = 960;
|
||||
/*
|
||||
* recon_write_bw_factor varies according to resolution and bit-depth,
|
||||
* here use 1.08(1.075) for worst case.
|
||||
* Similar for ref_y_read_bw_factor, it can reach 1.375 for worst case,
|
||||
* here use 1.3 for average case, and can somewhat balance the
|
||||
* worst case assumption for UBWC CR factors.
|
||||
*/
|
||||
recon_write_bw_factor = FP(1, 8, 100);
|
||||
ref_y_read_bw_factor = FP(1, 30, 100);
|
||||
ref_cbcr_read_bw_factor = FP(1, 50, 100);
|
||||
|
||||
|
||||
/* Derived Parameters */
|
||||
fps = d->fps;
|
||||
width = max(d->output_width, BASELINE_DIMENSIONS.width);
|
||||
height = max(d->output_height, BASELINE_DIMENSIONS.height);
|
||||
downscaling_ratio = fp_div(FP_INT(d->input_width * d->input_height),
|
||||
FP_INT(d->output_width * d->output_height));
|
||||
downscaling_ratio = max(downscaling_ratio, FP_ONE);
|
||||
bitrate = d->bitrate > 0 ? DIV_ROUND_UP(d->bitrate, 1000000) :
|
||||
__lut(width, height, fps)->bitrate;
|
||||
lcu_size = d->lcu_size;
|
||||
lcu_per_frame = DIV_ROUND_UP(width, lcu_size) *
|
||||
DIV_ROUND_UP(height, lcu_size);
|
||||
tnbr_per_lcu = 16;
|
||||
|
||||
dpb_bpp = __bpp(d->color_formats[0]);
|
||||
|
||||
y_bw_no_ubwc_8bpp = fp_div(FP_INT(width * height * fps),
|
||||
FP_INT(1000 * 1000));
|
||||
|
||||
if (dpb_bpp != 8) {
|
||||
y_bw_no_ubwc_10bpp = fp_div(fp_mult(y_bw_no_ubwc_8bpp,
|
||||
FP_INT(256)), FP_INT(192));
|
||||
y_bw_10bpp_p010 = y_bw_no_ubwc_8bpp * 2;
|
||||
}
|
||||
|
||||
b_frames_enabled = d->b_frames_enabled;
|
||||
original_color_format = d->num_formats >= 1 ?
|
||||
d->color_formats[0] : MSM_VIDC_FMT_NV12C;
|
||||
|
||||
original_compression_enabled = __ubwc(original_color_format);
|
||||
|
||||
work_mode_1 = d->work_mode == MSM_VIDC_STAGE_1;
|
||||
low_power = d->power_mode == VIDC_POWER_LOW;
|
||||
bins_to_bit_factor = 4;
|
||||
|
||||
if (d->use_sys_cache) {
|
||||
llc_ref_chroma_cache_enabled = true;
|
||||
llc_top_line_buf_enabled = true,
|
||||
llc_vpss_rot_line_buf_enabled = true;
|
||||
}
|
||||
|
||||
integer_part = Q16_INT(d->compression_ratio);
|
||||
frac_part = Q16_FRAC(d->compression_ratio);
|
||||
dpb_compression_factor = FP(integer_part, frac_part, 100);
|
||||
|
||||
integer_part = Q16_INT(d->input_cr);
|
||||
frac_part = Q16_FRAC(d->input_cr);
|
||||
input_compression_factor = FP(integer_part, frac_part, 100);
|
||||
|
||||
original_compression_factor = original_compression_factor_y =
|
||||
!original_compression_enabled ? FP_ONE :
|
||||
__compression_ratio(__lut(width, height, fps), dpb_bpp);
|
||||
/* use input cr if it is valid (not 1), otherwise use lut */
|
||||
if (original_compression_enabled &&
|
||||
input_compression_factor != FP_ONE) {
|
||||
original_compression_factor = input_compression_factor;
|
||||
/* Luma usually has lower compression factor than Chroma,
|
||||
* input cf is overall cf, add 1.08 factor for Luma cf
|
||||
*/
|
||||
original_compression_factor_y =
|
||||
input_compression_factor > FP(1, 8, 100) ?
|
||||
fp_div(input_compression_factor, FP(1, 8, 100)) :
|
||||
input_compression_factor;
|
||||
}
|
||||
|
||||
ddr.vsp_read = fp_div(FP_INT(bitrate * bins_to_bit_factor), FP_INT(8));
|
||||
ddr.vsp_write = ddr.vsp_read + fp_div(FP_INT(bitrate), FP_INT(8));
|
||||
|
||||
collocated_bytes_per_lcu = lcu_size == 16 ? 16 :
|
||||
lcu_size == 32 ? 64 : 256;
|
||||
|
||||
ddr.collocated_read = fp_div(FP_INT(lcu_per_frame *
|
||||
collocated_bytes_per_lcu * fps), FP_INT(bps(1)));
|
||||
|
||||
ddr.collocated_write = ddr.collocated_read;
|
||||
|
||||
ddr.ref_read_y = dpb_bpp == 8 ?
|
||||
y_bw_no_ubwc_8bpp : y_bw_no_ubwc_10bpp;
|
||||
if (b_frames_enabled)
|
||||
ddr.ref_read_y = ddr.ref_read_y * 2;
|
||||
ddr.ref_read_y = fp_div(ddr.ref_read_y, dpb_compression_factor);
|
||||
|
||||
ddr.ref_read_crcb = fp_mult((ddr.ref_read_y / 2),
|
||||
ref_cbcr_read_bw_factor);
|
||||
|
||||
if (width > vertical_tile_width) {
|
||||
ddr.ref_read_y = fp_mult(ddr.ref_read_y,
|
||||
ref_y_read_bw_factor);
|
||||
}
|
||||
|
||||
if (llc_ref_chroma_cache_enabled) {
|
||||
total_ref_read_crcb = ddr.ref_read_crcb;
|
||||
ddr.ref_read_crcb = fp_div(ddr.ref_read_crcb,
|
||||
ref_cbcr_read_bw_factor);
|
||||
llc.ref_read_crcb = total_ref_read_crcb - ddr.ref_read_crcb;
|
||||
}
|
||||
|
||||
ddr.ref_write = dpb_bpp == 8 ? y_bw_no_ubwc_8bpp : y_bw_no_ubwc_10bpp;
|
||||
ddr.ref_write = fp_div(fp_mult(ddr.ref_write, FP(1, 50, 100)),
|
||||
dpb_compression_factor);
|
||||
|
||||
if (width > vertical_tile_width) {
|
||||
ddr.ref_write_overlap = fp_mult(ddr.ref_write,
|
||||
(recon_write_bw_factor - FP_ONE));
|
||||
ddr.ref_write = fp_mult(ddr.ref_write, recon_write_bw_factor);
|
||||
}
|
||||
|
||||
ddr.orig_read = dpb_bpp == 8 ? y_bw_no_ubwc_8bpp :
|
||||
(original_compression_enabled ? y_bw_no_ubwc_10bpp :
|
||||
y_bw_10bpp_p010);
|
||||
ddr.orig_read = fp_div(fp_mult(fp_mult(ddr.orig_read, FP(1, 50, 100)),
|
||||
downscaling_ratio), original_compression_factor);
|
||||
if (rotation == 90 || rotation == 270)
|
||||
ddr.orig_read *= lcu_size == 32 ? (dpb_bpp == 8 ? 1 : 3) : 2;
|
||||
|
||||
ddr.line_buffer_read =
|
||||
fp_div(FP_INT(tnbr_per_lcu * lcu_per_frame * fps),
|
||||
FP_INT(bps(1)));
|
||||
|
||||
ddr.line_buffer_write = ddr.line_buffer_read;
|
||||
if (llc_top_line_buf_enabled) {
|
||||
llc.line_buffer = ddr.line_buffer_read + ddr.line_buffer_write;
|
||||
ddr.line_buffer_read = ddr.line_buffer_write = FP_ZERO;
|
||||
}
|
||||
|
||||
ddr.total = ddr.vsp_read + ddr.vsp_write +
|
||||
ddr.collocated_read + ddr.collocated_write +
|
||||
ddr.ref_read_y + ddr.ref_read_crcb +
|
||||
ddr.ref_write + ddr.ref_write_overlap +
|
||||
ddr.orig_read +
|
||||
ddr.line_buffer_read + ddr.line_buffer_write;
|
||||
|
||||
qsmmu_bw_overhead_factor = FP(1, 3, 100);
|
||||
ddr.total = fp_mult(ddr.total, qsmmu_bw_overhead_factor);
|
||||
llc.total = llc.ref_read_crcb + llc.line_buffer + ddr.total;
|
||||
|
||||
if (msm_vidc_debug & VIDC_BUS) {
|
||||
struct dump dump[] = {
|
||||
{"ENCODER PARAMETERS", "", DUMP_HEADER_MAGIC},
|
||||
{"width", "%d", width},
|
||||
{"height", "%d", height},
|
||||
{"fps", "%d", fps},
|
||||
{"dpb bitdepth", "%d", dpb_bpp},
|
||||
{"input downscaling ratio", DUMP_FP_FMT, downscaling_ratio},
|
||||
{"rotation", "%d", rotation},
|
||||
{"cropping or scaling", "%d", cropping_or_scaling},
|
||||
{"low power mode", "%d", low_power},
|
||||
{"work Mode", "%d", work_mode_1},
|
||||
{"B frame enabled", "%d", b_frames_enabled},
|
||||
{"original frame format", "%#x", original_color_format},
|
||||
{"original compression enabled", "%d",
|
||||
original_compression_enabled},
|
||||
{"dpb compression factor", DUMP_FP_FMT,
|
||||
dpb_compression_factor},
|
||||
{"input compression factor", DUMP_FP_FMT,
|
||||
input_compression_factor},
|
||||
{"llc ref chroma cache enabled", DUMP_FP_FMT,
|
||||
llc_ref_chroma_cache_enabled},
|
||||
{"llc top line buf enabled", DUMP_FP_FMT,
|
||||
llc_top_line_buf_enabled},
|
||||
{"llc vpss rot line buf enabled ", DUMP_FP_FMT,
|
||||
llc_vpss_rot_line_buf_enabled},
|
||||
|
||||
{"DERIVED PARAMETERS", "", DUMP_HEADER_MAGIC},
|
||||
{"lcu size", "%d", lcu_size},
|
||||
{"bitrate (Mbit/sec)", "%lu", bitrate},
|
||||
{"bins to bit factor", "%u", bins_to_bit_factor},
|
||||
{"original compression factor", DUMP_FP_FMT,
|
||||
original_compression_factor},
|
||||
{"original compression factor y", DUMP_FP_FMT,
|
||||
original_compression_factor_y},
|
||||
{"qsmmu_bw_overhead_factor",
|
||||
DUMP_FP_FMT, qsmmu_bw_overhead_factor},
|
||||
{"bw for NV12 8bpc)", DUMP_FP_FMT, y_bw_no_ubwc_8bpp},
|
||||
{"bw for NV12 10bpc)", DUMP_FP_FMT, y_bw_no_ubwc_10bpp},
|
||||
|
||||
{"INTERMEDIATE B/W DDR", "", DUMP_HEADER_MAGIC},
|
||||
{"vsp read", DUMP_FP_FMT, ddr.vsp_read},
|
||||
{"vsp write", DUMP_FP_FMT, ddr.vsp_write},
|
||||
{"collocated read", DUMP_FP_FMT, ddr.collocated_read},
|
||||
{"collocated write", DUMP_FP_FMT, ddr.collocated_write},
|
||||
{"ref read y", DUMP_FP_FMT, ddr.ref_read_y},
|
||||
{"ref read crcb", DUMP_FP_FMT, ddr.ref_read_crcb},
|
||||
{"ref write", DUMP_FP_FMT, ddr.ref_write},
|
||||
{"ref write overlap", DUMP_FP_FMT, ddr.ref_write_overlap},
|
||||
{"original read", DUMP_FP_FMT, ddr.orig_read},
|
||||
{"line buffer read", DUMP_FP_FMT, ddr.line_buffer_read},
|
||||
{"line buffer write", DUMP_FP_FMT, ddr.line_buffer_write},
|
||||
{"INTERMEDIATE LLC B/W", "", DUMP_HEADER_MAGIC},
|
||||
{"llc ref read crcb", DUMP_FP_FMT, llc.ref_read_crcb},
|
||||
{"llc line buffer", DUMP_FP_FMT, llc.line_buffer},
|
||||
};
|
||||
__dump(dump, ARRAY_SIZE(dump));
|
||||
}
|
||||
|
||||
d->calc_bw_ddr = kbps(fp_round(ddr.total));
|
||||
d->calc_bw_llcc = kbps(fp_round(llc.total));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u64 __calculate(struct msm_vidc_inst *inst, struct vidc_bus_vote_data *d)
|
||||
{
|
||||
u64 value = 0;
|
||||
|
||||
switch (d->domain) {
|
||||
case MSM_VIDC_ENCODER:
|
||||
value = __calculate_encoder(d);
|
||||
break;
|
||||
case MSM_VIDC_DECODER:
|
||||
value = __calculate_decoder(d);
|
||||
break;
|
||||
default:
|
||||
i_vpr_e(inst, "%s: Unknown Domain %#x", __func__, d->domain);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int msm_vidc_calc_bw_iris2(struct msm_vidc_inst *inst,
|
||||
struct vidc_bus_vote_data *vidc_data)
|
||||
{
|
||||
int value = 0;
|
||||
|
||||
if (!vidc_data)
|
||||
return value;
|
||||
|
||||
value = __calculate(inst, vidc_data);
|
||||
|
||||
return value;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __H_MSM_VIDC_BUFFER_IRIS3_H__
|
||||
#define __H_MSM_VIDC_BUFFER_IRIS3_H__
|
||||
|
||||
#include "msm_vidc_inst.h"
|
||||
|
||||
int msm_buffer_size_iris3(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
int msm_buffer_min_count_iris3(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
int msm_buffer_extra_count_iris3(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
|
||||
#endif // __H_MSM_VIDC_BUFFER_IRIS3_H__
|
@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_IRIS3_H_
|
||||
#define _MSM_VIDC_IRIS3_H_
|
||||
|
||||
#include "msm_vidc_core.h"
|
||||
|
||||
#if defined(CONFIG_MSM_VIDC_KALAMA)
|
||||
int msm_vidc_init_iris3(struct msm_vidc_core *core);
|
||||
int msm_vidc_adjust_bitrate_boost_iris3(void *instance, struct v4l2_ctrl *ctrl);
|
||||
#else
|
||||
static inline int msm_vidc_init_iris3(struct msm_vidc_core *core)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int msm_vidc_adjust_bitrate_boost_iris3(void *instance, struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _MSM_VIDC_IRIS3_H_
|
@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __H_MSM_VIDC_POWER_IRIS3_H__
|
||||
#define __H_MSM_VIDC_POWER_IRIS3_H__
|
||||
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_power.h"
|
||||
|
||||
#define ENABLE_LEGACY_POWER_CALCULATIONS 0
|
||||
|
||||
u64 msm_vidc_calc_freq_iris3(struct msm_vidc_inst *inst, u32 data_size);
|
||||
int msm_vidc_calc_bw_iris3(struct msm_vidc_inst *inst,
|
||||
struct vidc_bus_vote_data *vote_data);
|
||||
|
||||
#endif
|
@ -0,0 +1,736 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "msm_vidc_buffer_iris3.h"
|
||||
#include "msm_vidc_buffer.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
#include "msm_media_info.h"
|
||||
#include "msm_vidc_platform.h"
|
||||
#include "hfi_property.h"
|
||||
#include "hfi_buffer_iris3.h"
|
||||
|
||||
static u32 msm_vidc_decoder_bin_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, num_vpp_pipes;
|
||||
struct v4l2_format *f;
|
||||
bool is_interlaced;
|
||||
u32 vpp_delay;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
if (inst->decode_vpp_delay.enable)
|
||||
vpp_delay = inst->decode_vpp_delay.size;
|
||||
else
|
||||
vpp_delay = DEFAULT_BSE_VPP_DELAY;
|
||||
if (inst->capabilities[CODED_FRAMES].value ==
|
||||
CODED_FRAMES_PROGRESSIVE)
|
||||
is_interlaced = false;
|
||||
else
|
||||
is_interlaced = true;
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_BIN_H264D(size, width, height,
|
||||
is_interlaced, vpp_delay, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_BIN_H265D(size, width, height,
|
||||
0, vpp_delay, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_VP9)
|
||||
HFI_BUFFER_BIN_VP9D(size, width, height,
|
||||
0, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_AV1)
|
||||
HFI_BUFFER_BIN_AV1D(size, width, height, is_interlaced,
|
||||
0, num_vpp_pipes);
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_comv_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height, num_comv, vpp_delay;
|
||||
struct v4l2_format *f;
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_AV1) {
|
||||
/*
|
||||
* AV1 requires larger COMV buffer size to meet performance
|
||||
* for certain use cases. Increase the COMV buffer size by
|
||||
* increasing COMV bufcount. Use lower count for 8k to
|
||||
* achieve performance but save memory.
|
||||
*/
|
||||
if (res_is_greater_than(width, height, 4096, 2176))
|
||||
num_comv = inst->buffers.output.min_count + 3;
|
||||
else
|
||||
num_comv = inst->buffers.output.min_count + 7;
|
||||
} else {
|
||||
num_comv = inst->buffers.output.min_count;
|
||||
}
|
||||
msm_vidc_update_cap_value(inst, NUM_COMV, num_comv, __func__);
|
||||
|
||||
if (inst->codec == MSM_VIDC_HEIC
|
||||
&& is_thumbnail_session(inst)) {
|
||||
vpp_delay = 0;
|
||||
} else {
|
||||
if (inst->decode_vpp_delay.enable)
|
||||
vpp_delay = inst->decode_vpp_delay.size;
|
||||
else
|
||||
vpp_delay = DEFAULT_BSE_VPP_DELAY;
|
||||
}
|
||||
|
||||
num_comv = max(vpp_delay + 1, num_comv);
|
||||
if (inst->codec == MSM_VIDC_H264) {
|
||||
HFI_BUFFER_COMV_H264D(size, width, height, num_comv);
|
||||
} else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC) {
|
||||
HFI_BUFFER_COMV_H265D(size, width, height, num_comv);
|
||||
} else if (inst->codec == MSM_VIDC_AV1) {
|
||||
/*
|
||||
* When DRAP is enabled, COMV buffer is part of PERSIST buffer and
|
||||
* should not be allocated separately.
|
||||
* When DRAP is disabled, COMV buffer must be allocated.
|
||||
*/
|
||||
if (inst->capabilities[DRAP].value)
|
||||
size = 0;
|
||||
else
|
||||
HFI_BUFFER_COMV_AV1D(size, width, height, num_comv);
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_non_comv_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height, num_vpp_pipes;
|
||||
struct msm_vidc_core *core;
|
||||
struct v4l2_format *f;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_NON_COMV_H264D(size, width, height, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_NON_COMV_H265D(size, width, height, num_vpp_pipes);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_line_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, out_min_count, num_vpp_pipes, vpp_delay;
|
||||
struct v4l2_format *f;
|
||||
bool is_opb;
|
||||
u32 color_fmt;
|
||||
|
||||
core = inst->core;
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
|
||||
color_fmt = v4l2_colorformat_to_driver(inst,
|
||||
inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat, __func__);
|
||||
if (is_linear_colorformat(color_fmt))
|
||||
is_opb = true;
|
||||
else
|
||||
is_opb = false;
|
||||
/*
|
||||
* assume worst case, since color format is unknown at this
|
||||
* time.
|
||||
*/
|
||||
is_opb = true;
|
||||
|
||||
if (inst->decode_vpp_delay.enable)
|
||||
vpp_delay = inst->decode_vpp_delay.size;
|
||||
else
|
||||
vpp_delay = DEFAULT_BSE_VPP_DELAY;
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
out_min_count = inst->buffers.output.min_count;
|
||||
out_min_count = max(vpp_delay + 1, out_min_count);
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_LINE_H264D(size, width, height, is_opb,
|
||||
num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_LINE_H265D(size, width, height, is_opb,
|
||||
num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_VP9)
|
||||
HFI_BUFFER_LINE_VP9D(size, width, height, out_min_count,
|
||||
is_opb, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_AV1)
|
||||
HFI_BUFFER_LINE_AV1D(size, width, height, is_opb,
|
||||
num_vpp_pipes);
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_partial_data_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height;
|
||||
struct v4l2_format *f;
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_AV1)
|
||||
HFI_BUFFER_IBC_AV1D(size, width, height);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_persist_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 rpu_enabled = 0;
|
||||
|
||||
if (inst->capabilities[META_DOLBY_RPU].value)
|
||||
rpu_enabled = 1;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264) {
|
||||
HFI_BUFFER_PERSIST_H264D(size, rpu_enabled);
|
||||
} else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC) {
|
||||
HFI_BUFFER_PERSIST_H265D(size, rpu_enabled);
|
||||
} else if (inst->codec == MSM_VIDC_VP9) {
|
||||
HFI_BUFFER_PERSIST_VP9D(size);
|
||||
} else if (inst->codec == MSM_VIDC_AV1) {
|
||||
/*
|
||||
* When DRAP is enabled, COMV buffer is part of PERSIST buffer and
|
||||
* should not be allocated separately. PERSIST buffer should include
|
||||
* COMV buffer calculated with width, height, refcount.
|
||||
* When DRAP is disabled, COMV buffer should not be included in PERSIST
|
||||
* buffer.
|
||||
*/
|
||||
if (inst->capabilities[DRAP].value)
|
||||
HFI_BUFFER_PERSIST_AV1D(size,
|
||||
inst->capabilities[FRAME_WIDTH].max,
|
||||
inst->capabilities[FRAME_HEIGHT].max, 16);
|
||||
else
|
||||
HFI_BUFFER_PERSIST_AV1D(size, 0, 0, 0);
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_dpb_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
|
||||
u32 size = 0;
|
||||
u32 color_fmt;
|
||||
u32 width, height;
|
||||
struct v4l2_format *f;
|
||||
|
||||
/*
|
||||
* For legacy codecs (non-AV1), DPB is calculated only
|
||||
* for linear formats. For AV1, DPB is needed for film-grain
|
||||
* enabled bitstreams (UBWC & linear).
|
||||
*/
|
||||
color_fmt = inst->capabilities[PIX_FMTS].value;
|
||||
if (!is_linear_colorformat(color_fmt)) {
|
||||
if (inst->codec != MSM_VIDC_AV1)
|
||||
return size;
|
||||
|
||||
if (inst->codec == MSM_VIDC_AV1 &&
|
||||
!inst->capabilities[FILM_GRAIN].value)
|
||||
return size;
|
||||
}
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (color_fmt == MSM_VIDC_FMT_NV12 ||
|
||||
color_fmt == MSM_VIDC_FMT_NV12C) {
|
||||
color_fmt = MSM_VIDC_FMT_NV12C;
|
||||
HFI_NV12_UBWC_IL_CALC_BUF_SIZE_V2(size, width, height,
|
||||
video_y_stride_bytes(color_fmt, width),
|
||||
video_y_scanlines(color_fmt, height),
|
||||
video_uv_stride_bytes(color_fmt, width),
|
||||
video_uv_scanlines(color_fmt, height),
|
||||
video_y_meta_stride(color_fmt, width),
|
||||
video_y_meta_scanlines(color_fmt, height),
|
||||
video_uv_meta_stride(color_fmt, width),
|
||||
video_uv_meta_scanlines(color_fmt, height));
|
||||
} else if (color_fmt == MSM_VIDC_FMT_P010 ||
|
||||
color_fmt == MSM_VIDC_FMT_TP10C) {
|
||||
color_fmt = MSM_VIDC_FMT_TP10C;
|
||||
HFI_YUV420_TP10_UBWC_CALC_BUF_SIZE(size,
|
||||
video_y_stride_bytes(color_fmt, width),
|
||||
video_y_scanlines(color_fmt, height),
|
||||
video_uv_stride_bytes(color_fmt, width),
|
||||
video_uv_scanlines(color_fmt, height),
|
||||
video_y_meta_stride(color_fmt, width),
|
||||
video_y_meta_scanlines(color_fmt, height),
|
||||
video_uv_meta_stride(color_fmt, width),
|
||||
video_uv_meta_scanlines(color_fmt, height));
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
/* encoder internal buffers */
|
||||
static u32 msm_vidc_encoder_bin_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, num_vpp_pipes, stage, profile;
|
||||
struct v4l2_format *f;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
stage = inst->capabilities[STAGE].value;
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
profile = inst->capabilities[PROFILE].value;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_BIN_H264E(size, inst->hfi_rc_type, width,
|
||||
height, stage, num_vpp_pipes, profile);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_BIN_H265E(size, inst->hfi_rc_type, width,
|
||||
height, stage, num_vpp_pipes, profile);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_get_recon_buf_count(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 num_buf_recon = 0;
|
||||
s32 n_bframe, ltr_count, hp_layers = 0, hb_layers = 0;
|
||||
bool is_hybrid_hp = false;
|
||||
u32 hfi_codec = 0;
|
||||
|
||||
n_bframe = inst->capabilities[B_FRAME].value;
|
||||
ltr_count = inst->capabilities[LTR_COUNT].value;
|
||||
|
||||
if (inst->hfi_layer_type == HFI_HIER_B) {
|
||||
hb_layers = inst->capabilities[ENH_LAYER_COUNT].value + 1;
|
||||
} else {
|
||||
hp_layers = inst->capabilities[ENH_LAYER_COUNT].value + 1;
|
||||
if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR)
|
||||
is_hybrid_hp = true;
|
||||
}
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
hfi_codec = HFI_CODEC_ENCODE_AVC;
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
hfi_codec = HFI_CODEC_ENCODE_HEVC;
|
||||
|
||||
HFI_IRIS3_ENC_RECON_BUF_COUNT(num_buf_recon, n_bframe, ltr_count,
|
||||
hp_layers, hb_layers, is_hybrid_hp, hfi_codec);
|
||||
|
||||
return num_buf_recon;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_comv_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height, num_recon = 0;
|
||||
struct v4l2_format *f;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
num_recon = msm_vidc_get_recon_buf_count(inst);
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_COMV_H264E(size, width, height, num_recon);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_COMV_H265E(size, width, height, num_recon);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_non_comv_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, num_vpp_pipes;
|
||||
struct v4l2_format *f;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_NON_COMV_H264E(size, width, height, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_NON_COMV_H265E(size, width, height, num_vpp_pipes);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_line_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, pixfmt, num_vpp_pipes;
|
||||
bool is_tenbit = false;
|
||||
struct v4l2_format *f;
|
||||
|
||||
core = inst->core;
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
pixfmt = inst->capabilities[PIX_FMTS].value;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
is_tenbit = (pixfmt == MSM_VIDC_FMT_P010 || pixfmt == MSM_VIDC_FMT_TP10C);
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_LINE_H264E(size, width, height, is_tenbit, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_LINE_H265E(size, width, height, is_tenbit, num_vpp_pipes);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_dpb_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height, pixfmt;
|
||||
struct v4l2_format *f;
|
||||
bool is_tenbit;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
pixfmt = inst->capabilities[PIX_FMTS].value;
|
||||
is_tenbit = (pixfmt == MSM_VIDC_FMT_P010 || pixfmt == MSM_VIDC_FMT_TP10C);
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_DPB_H264E(size, width, height);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_DPB_H265E(size, width, height, is_tenbit);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_arp_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
|
||||
HFI_BUFFER_ARP_ENC(size);
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_vpss_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
bool ds_enable = false, is_tenbit = false, blur = false;
|
||||
u32 rotation_val = HFI_ROTATION_NONE;
|
||||
u32 width, height, driver_colorfmt;
|
||||
struct v4l2_format *f;
|
||||
|
||||
ds_enable = is_scaling_enabled(inst);
|
||||
msm_vidc_v4l2_to_hfi_enum(inst, ROTATION, &rotation_val);
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
if (is_rotation_90_or_270(inst)) {
|
||||
/*
|
||||
* output width and height are rotated,
|
||||
* so unrotate them to use as arguments to
|
||||
* HFI_BUFFER_VPSS_ENC.
|
||||
*/
|
||||
width = f->fmt.pix_mp.height;
|
||||
height = f->fmt.pix_mp.width;
|
||||
} else {
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
}
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
driver_colorfmt = v4l2_colorformat_to_driver(inst,
|
||||
f->fmt.pix_mp.pixelformat, __func__);
|
||||
is_tenbit = is_10bit_colorformat(driver_colorfmt);
|
||||
if (inst->capabilities[BLUR_TYPES].value != MSM_VIDC_BLUR_NONE)
|
||||
blur = true;
|
||||
|
||||
HFI_BUFFER_VPSS_ENC(size, width, height, ds_enable, blur, is_tenbit);
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_output_size_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 frame_size;
|
||||
struct v4l2_format *f;
|
||||
bool is_ten_bit = false;
|
||||
int bitrate_mode, frame_rc;
|
||||
u32 hfi_rc_type = HFI_RC_VBR_CFR;
|
||||
enum msm_vidc_codec_type codec;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
codec = v4l2_codec_to_driver(inst, f->fmt.pix_mp.pixelformat, __func__);
|
||||
if (codec == MSM_VIDC_HEVC || codec == MSM_VIDC_HEIC)
|
||||
is_ten_bit = true;
|
||||
|
||||
bitrate_mode = inst->capabilities[BITRATE_MODE].value;
|
||||
frame_rc = inst->capabilities[FRAME_RC_ENABLE].value;
|
||||
if (!frame_rc && !is_image_session(inst))
|
||||
hfi_rc_type = HFI_RC_OFF;
|
||||
else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
|
||||
hfi_rc_type = HFI_RC_CQ;
|
||||
|
||||
HFI_BUFFER_BITSTREAM_ENC(frame_size, f->fmt.pix_mp.width,
|
||||
f->fmt.pix_mp.height, hfi_rc_type, is_ten_bit);
|
||||
|
||||
frame_size = msm_vidc_enc_delivery_mode_based_output_buf_size(inst, frame_size);
|
||||
|
||||
return frame_size;
|
||||
}
|
||||
|
||||
struct msm_vidc_buf_type_handle {
|
||||
enum msm_vidc_buffer_type type;
|
||||
u32 (*handle)(struct msm_vidc_inst *inst);
|
||||
};
|
||||
|
||||
int msm_buffer_size_iris3(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
int i;
|
||||
u32 size = 0, buf_type_handle_size = 0;
|
||||
const struct msm_vidc_buf_type_handle *buf_type_handle_arr = NULL;
|
||||
static const struct msm_vidc_buf_type_handle dec_buf_type_handle[] = {
|
||||
{MSM_VIDC_BUF_INPUT, msm_vidc_decoder_input_size },
|
||||
{MSM_VIDC_BUF_OUTPUT, msm_vidc_decoder_output_size },
|
||||
{MSM_VIDC_BUF_INPUT_META, msm_vidc_decoder_input_meta_size },
|
||||
{MSM_VIDC_BUF_OUTPUT_META, msm_vidc_decoder_output_meta_size },
|
||||
{MSM_VIDC_BUF_BIN, msm_vidc_decoder_bin_size_iris3 },
|
||||
{MSM_VIDC_BUF_COMV, msm_vidc_decoder_comv_size_iris3 },
|
||||
{MSM_VIDC_BUF_NON_COMV, msm_vidc_decoder_non_comv_size_iris3 },
|
||||
{MSM_VIDC_BUF_LINE, msm_vidc_decoder_line_size_iris3 },
|
||||
{MSM_VIDC_BUF_PERSIST, msm_vidc_decoder_persist_size_iris3 },
|
||||
{MSM_VIDC_BUF_DPB, msm_vidc_decoder_dpb_size_iris3 },
|
||||
{MSM_VIDC_BUF_PARTIAL_DATA, msm_vidc_decoder_partial_data_size_iris3 },
|
||||
};
|
||||
static const struct msm_vidc_buf_type_handle enc_buf_type_handle[] = {
|
||||
{MSM_VIDC_BUF_INPUT, msm_vidc_encoder_input_size },
|
||||
{MSM_VIDC_BUF_OUTPUT, msm_vidc_encoder_output_size_iris3 },
|
||||
{MSM_VIDC_BUF_INPUT_META, msm_vidc_encoder_input_meta_size },
|
||||
{MSM_VIDC_BUF_OUTPUT_META, msm_vidc_encoder_output_meta_size },
|
||||
{MSM_VIDC_BUF_BIN, msm_vidc_encoder_bin_size_iris3 },
|
||||
{MSM_VIDC_BUF_COMV, msm_vidc_encoder_comv_size_iris3 },
|
||||
{MSM_VIDC_BUF_NON_COMV, msm_vidc_encoder_non_comv_size_iris3 },
|
||||
{MSM_VIDC_BUF_LINE, msm_vidc_encoder_line_size_iris3 },
|
||||
{MSM_VIDC_BUF_DPB, msm_vidc_encoder_dpb_size_iris3 },
|
||||
{MSM_VIDC_BUF_ARP, msm_vidc_encoder_arp_size_iris3 },
|
||||
{MSM_VIDC_BUF_VPSS, msm_vidc_encoder_vpss_size_iris3 },
|
||||
};
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
buf_type_handle_size = ARRAY_SIZE(dec_buf_type_handle);
|
||||
buf_type_handle_arr = dec_buf_type_handle;
|
||||
} else if (is_encode_session(inst)) {
|
||||
buf_type_handle_size = ARRAY_SIZE(enc_buf_type_handle);
|
||||
buf_type_handle_arr = enc_buf_type_handle;
|
||||
}
|
||||
|
||||
/* handle invalid session */
|
||||
if (!buf_type_handle_arr || !buf_type_handle_size) {
|
||||
i_vpr_e(inst, "%s: invalid session %d\n", __func__, inst->domain);
|
||||
return size;
|
||||
}
|
||||
|
||||
/* fetch buffer size */
|
||||
for (i = 0; i < buf_type_handle_size; i++) {
|
||||
if (buf_type_handle_arr[i].type == buffer_type) {
|
||||
size = buf_type_handle_arr[i].handle(inst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle unknown buffer type */
|
||||
if (i == buf_type_handle_size) {
|
||||
i_vpr_e(inst, "%s: unknown buffer type %#x\n", __func__, buffer_type);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "buffer_size: type: %11s, size: %9u\n", buf_name(buffer_type), size);
|
||||
|
||||
exit:
|
||||
return size;
|
||||
}
|
||||
|
||||
static int msm_vidc_input_min_count_iris3(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 input_min_count = 0;
|
||||
u32 total_hb_layer = 0;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
input_min_count = MIN_DEC_INPUT_BUFFERS;
|
||||
} else if (is_encode_session(inst)) {
|
||||
total_hb_layer = is_hierb_type_requested(inst) ?
|
||||
inst->capabilities[ENH_LAYER_COUNT].value + 1 : 0;
|
||||
if (inst->codec == MSM_VIDC_H264 &&
|
||||
!inst->capabilities[LAYER_ENABLE].value) {
|
||||
total_hb_layer = 0;
|
||||
}
|
||||
HFI_IRIS3_ENC_MIN_INPUT_BUF_COUNT(input_min_count,
|
||||
total_hb_layer);
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: invalid domain %d\n", __func__, inst->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_thumbnail_session(inst) || is_image_session(inst))
|
||||
input_min_count = 1;
|
||||
|
||||
return input_min_count;
|
||||
}
|
||||
|
||||
static int msm_buffer_dpb_count(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int count = 0;
|
||||
u32 color_fmt;
|
||||
|
||||
/* decoder dpb buffer count */
|
||||
if (is_decode_session(inst)) {
|
||||
color_fmt = inst->capabilities[PIX_FMTS].value;
|
||||
if (is_linear_colorformat(color_fmt) ||
|
||||
(inst->codec == MSM_VIDC_AV1 &&
|
||||
(inst->capabilities[FILM_GRAIN].value)))
|
||||
count = inst->buffers.output.min_count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* encoder dpb buffer count */
|
||||
return msm_vidc_get_recon_buf_count(inst);
|
||||
}
|
||||
|
||||
static int msm_buffer_delivery_mode_based_min_count_iris3(struct msm_vidc_inst *inst,
|
||||
uint32_t count)
|
||||
{
|
||||
struct v4l2_format *f;
|
||||
struct msm_vidc_core *core = NULL;
|
||||
u32 width, height, total_num_slices = 1;
|
||||
u32 hfi_codec = 0;
|
||||
u32 max_mbs_per_slice = 0;
|
||||
u32 slice_mode = 0;
|
||||
u32 delivery_mode = 0;
|
||||
u32 num_vpp_pipes;
|
||||
|
||||
slice_mode = inst->capabilities[SLICE_MODE].value;
|
||||
delivery_mode = inst->capabilities[DELIVERY_MODE].value;
|
||||
|
||||
if (slice_mode != V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB ||
|
||||
(!delivery_mode))
|
||||
return count;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
max_mbs_per_slice = inst->capabilities[SLICE_MAX_MB].value;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
hfi_codec = HFI_CODEC_ENCODE_AVC;
|
||||
else if (inst->codec == MSM_VIDC_HEVC)
|
||||
hfi_codec = HFI_CODEC_ENCODE_HEVC;
|
||||
|
||||
core = inst->core;
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
|
||||
HFI_IRIS3_ENC_MB_BASED_MULTI_SLICE_COUNT(total_num_slices, width, height,
|
||||
hfi_codec, max_mbs_per_slice, num_vpp_pipes);
|
||||
|
||||
return (total_num_slices * count);
|
||||
}
|
||||
|
||||
int msm_buffer_min_count_iris3(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
switch (buffer_type) {
|
||||
case MSM_VIDC_BUF_INPUT:
|
||||
case MSM_VIDC_BUF_INPUT_META:
|
||||
count = msm_vidc_input_min_count_iris3(inst);
|
||||
break;
|
||||
case MSM_VIDC_BUF_OUTPUT:
|
||||
case MSM_VIDC_BUF_OUTPUT_META:
|
||||
count = msm_vidc_output_min_count(inst);
|
||||
count = msm_buffer_delivery_mode_based_min_count_iris3(inst, count);
|
||||
break;
|
||||
case MSM_VIDC_BUF_BIN:
|
||||
case MSM_VIDC_BUF_COMV:
|
||||
case MSM_VIDC_BUF_NON_COMV:
|
||||
case MSM_VIDC_BUF_LINE:
|
||||
case MSM_VIDC_BUF_PERSIST:
|
||||
case MSM_VIDC_BUF_ARP:
|
||||
case MSM_VIDC_BUF_VPSS:
|
||||
case MSM_VIDC_BUF_PARTIAL_DATA:
|
||||
count = msm_vidc_internal_buffer_count(inst, buffer_type);
|
||||
break;
|
||||
case MSM_VIDC_BUF_DPB:
|
||||
count = msm_buffer_dpb_count(inst);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
i_vpr_l(inst, " min_count: type: %11s, count: %9u\n", buf_name(buffer_type), count);
|
||||
return count;
|
||||
}
|
||||
|
||||
int msm_buffer_extra_count_iris3(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
switch (buffer_type) {
|
||||
case MSM_VIDC_BUF_INPUT:
|
||||
case MSM_VIDC_BUF_INPUT_META:
|
||||
count = msm_vidc_input_extra_count(inst);
|
||||
break;
|
||||
case MSM_VIDC_BUF_OUTPUT:
|
||||
case MSM_VIDC_BUF_OUTPUT_META:
|
||||
count = msm_vidc_output_extra_count(inst);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "extra_count: type: %11s, count: %9u\n", buf_name(buffer_type), count);
|
||||
return count;
|
||||
}
|
@ -0,0 +1,928 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "kalama_technology.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
|
||||
u32 calculate_number_lcus_kalama(u32 width, u32 height, u32 lcu_size)
|
||||
{
|
||||
u32 mbs_width = (width % lcu_size) ?
|
||||
(width / lcu_size + 1) : (width / lcu_size);
|
||||
u32 mbs_height = (height % lcu_size) ?
|
||||
(height / lcu_size + 1) : (height / lcu_size);
|
||||
|
||||
return mbs_width * mbs_height;
|
||||
}
|
||||
|
||||
u32 calculate_number_ubwctiles_kalama(
|
||||
u32 width, u32 height, u32 tile_w, u32 tile_h)
|
||||
{
|
||||
u32 tiles_width = (width % tile_w) ?
|
||||
(width / tile_w + 1) : (width / tile_w);
|
||||
u32 tiles_height = (height % tile_h) ?
|
||||
(height / tile_h + 1) : (height / tile_h);
|
||||
|
||||
return tiles_width * tiles_height;
|
||||
}
|
||||
|
||||
struct compression_factors {
|
||||
u32 dpb_cf_y;
|
||||
u32 dpb_cf_cbcr;
|
||||
u32 opb_cf_ycbcr;
|
||||
u32 dpb_cr_y;
|
||||
u32 ipb_cr_y;
|
||||
u32 ipb_cr;
|
||||
} compression_factor;
|
||||
|
||||
u32 get_compression_factors(struct compression_factors *compression_factor,
|
||||
struct api_calculation_input codec_input)
|
||||
{
|
||||
u8 cr_index_entry, cr_index_y, cr_index_c, cr_index_uni;
|
||||
u32 frame_width;
|
||||
u32 frame_height;
|
||||
|
||||
frame_width = codec_input.frame_width;
|
||||
frame_height = codec_input.frame_height;
|
||||
if (frame_width * frame_height <= 1920 * 1080)
|
||||
cr_index_entry = 0;
|
||||
else
|
||||
cr_index_entry = 1;
|
||||
|
||||
if (codec_input.bitdepth == CODEC_BITDEPTH_8) {
|
||||
/* NOT PWC or average and power case */
|
||||
if (codec_input.complexity_setting != 0) {
|
||||
cr_index_y = 0;
|
||||
cr_index_c = 1;
|
||||
cr_index_uni = 2;
|
||||
} else {
|
||||
cr_index_y = 3;
|
||||
cr_index_c = 4;
|
||||
cr_index_uni = 5;
|
||||
}
|
||||
} else {
|
||||
/* NOT PWC or average and power case */
|
||||
if (codec_input.complexity_setting != 0) {
|
||||
cr_index_y = 6;
|
||||
cr_index_c = 7;
|
||||
cr_index_uni = 8;
|
||||
} else {
|
||||
cr_index_y = 9;
|
||||
cr_index_c = 10;
|
||||
cr_index_uni = 11;
|
||||
}
|
||||
}
|
||||
|
||||
if (codec_input.decoder_or_encoder == CODEC_DECODER) {
|
||||
compression_factor->dpb_cf_y =
|
||||
dpbopb_ubwc30_cr_table_cratio_kalama[cr_index_entry][cr_index_y];
|
||||
compression_factor->dpb_cf_cbcr =
|
||||
dpbopb_ubwc30_cr_table_cratio_kalama[cr_index_entry][cr_index_c];
|
||||
compression_factor->opb_cf_ycbcr =
|
||||
dpbopb_ubwc30_cr_table_cratio_kalama[cr_index_entry][cr_index_uni];
|
||||
|
||||
if ((codec_input.regression_mode == 3) &&
|
||||
/* input cr numbers from interface */
|
||||
((codec_input.cr_dpb != 0) || (codec_input.cr_opb != 0))) {
|
||||
compression_factor->dpb_cf_y = (u32)(codec_input.cr_dpb * 100);
|
||||
compression_factor->dpb_cf_cbcr = (u32)(codec_input.cr_dpb * 100);
|
||||
compression_factor->opb_cf_ycbcr = (u32)(codec_input.cr_opb * 100);
|
||||
}
|
||||
} else { /* encoder */
|
||||
/*
|
||||
* IPB CR Table Choice; static sheet (if framewidth<3840, use lossless table)
|
||||
* (else, use lossy table)
|
||||
* stick to this choice for SW purpose (no change for SW)
|
||||
*/
|
||||
if (frame_width < 3840) {
|
||||
compression_factor->ipb_cr =
|
||||
ipblossless_ubwc30_cr_table_cratio_kalama[cr_index_entry]
|
||||
[cr_index_uni];
|
||||
compression_factor->ipb_cr_y =
|
||||
ipblossless_ubwc30_cr_table_cratio_kalama[cr_index_entry]
|
||||
[cr_index_y];
|
||||
} else {
|
||||
compression_factor->ipb_cr =
|
||||
ipblossy_ubwc30_cr_table_cratio_kalama[cr_index_entry]
|
||||
[cr_index_uni];
|
||||
compression_factor->ipb_cr_y =
|
||||
ipblossy_ubwc30_cr_table_cratio_kalama[cr_index_entry]
|
||||
[cr_index_y];
|
||||
}
|
||||
|
||||
compression_factor->dpb_cf_y =
|
||||
rpb_ubwc30_cr_table_cratio_kalama[cr_index_entry][cr_index_y];
|
||||
|
||||
compression_factor->dpb_cf_cbcr =
|
||||
rpb_ubwc30_cr_table_cratio_kalama[cr_index_entry][cr_index_c];
|
||||
|
||||
if ((codec_input.regression_mode == 3) &&
|
||||
/* input cr from interface */
|
||||
((codec_input.cr_ipb != 0) || (codec_input.cr_rpb != 0))) {
|
||||
compression_factor->dpb_cf_y = (u32)(codec_input.cr_rpb * 100);
|
||||
compression_factor->dpb_cf_cbcr = (u32)(codec_input.cr_rpb * 100);
|
||||
compression_factor->ipb_cr_y = (u32)(codec_input.cr_ipb * 100);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int calculate_bandwidth_decoder_iris3(
|
||||
struct api_calculation_input codec_input,
|
||||
struct api_calculation_bw_output *codec_output)
|
||||
{
|
||||
/* common control parameters */
|
||||
u32 frame_width;
|
||||
u32 frame_height;
|
||||
u32 frame_lcu_size = 16; /* initialized to h264 */
|
||||
u32 lcu_per_frame;
|
||||
u32 target_bitrate;
|
||||
u32 collocated_bytes_per_lcu = 16; /* initialized to h264 */
|
||||
u32 av1d_segment_read_per_lcu;
|
||||
u32 av1d_fe_leftlinebuffer_perlcu_tileboudary;
|
||||
|
||||
u32 frame420_y_bw_linear_8bpp;
|
||||
u32 frame420_y_bw_no_ubwc_tile_10bpp;
|
||||
u32 frame420_y_bw_linear_10bpp;
|
||||
|
||||
u16 ubwc_tile_w;
|
||||
u16 ubwc_tile_h;
|
||||
|
||||
u32 dpb_compression_factor_y;
|
||||
u32 dpb_compression_factor_cbcr;
|
||||
|
||||
u32 reconstructed_write_bw_factor_rd;
|
||||
u32 reference_y_read_bw_factor;
|
||||
u32 reference_cbcr_read_bw_factor;
|
||||
|
||||
/* decoder control parameters */
|
||||
u32 decoder_vsp_read_factor = 6;
|
||||
u32 bins_to_bits_factor = 4;
|
||||
|
||||
u32 dpb_to_opb_ratios_ds = 1;
|
||||
|
||||
u8 llc_enabled_ref_y_rd = 1;
|
||||
u8 llc_enable_ref_crcb_rd = 1;
|
||||
u8 llc_enabled_bse_tlb = 1;
|
||||
/* this is for 2pipe and 1pipe LLC */
|
||||
u8 llc_enable_probtable_av1d_21pipe = 0;
|
||||
|
||||
u32 opb_compression_factor_ycbcr;
|
||||
u32 dpb_ubwc_tile_width_pixels;
|
||||
u32 dpb_ubwc_tile_height_pixels;
|
||||
u32 decoder_frame_complexity_factor;
|
||||
u32 llc_saving = 130; /* Initialized to H264 */
|
||||
|
||||
u16 av1_tile_numbers;
|
||||
u32 av1_collated_seg_buffer_rd_wr;
|
||||
/* need divide by 1M at later step; */
|
||||
u32 av1_probability_table_rdwr_bytesperframe = 22784;
|
||||
u32 av1_fe_left_line_buffer_rdwr;
|
||||
|
||||
u32 bse_tlb_byte_per_lcu = 0;
|
||||
|
||||
u32 large_bw_calculation_fp = 0;
|
||||
|
||||
llc_enabled_ref_y_rd = (codec_input.status_llc_onoff) ? 1 : 0;
|
||||
llc_enable_ref_crcb_rd = (codec_input.status_llc_onoff) ? 1 : 0;
|
||||
/* H265D BSE tlb in LLC will be pored in Kailua */
|
||||
llc_enabled_bse_tlb = (codec_input.status_llc_onoff) ? 1 : 0;
|
||||
|
||||
frame_width = codec_input.frame_width;
|
||||
frame_height = codec_input.frame_height;
|
||||
if ((codec_input.codec == CODEC_H264) ||
|
||||
(codec_input.codec == CODEC_H264_CAVLC)) {
|
||||
frame_lcu_size = 16;
|
||||
collocated_bytes_per_lcu = 16;
|
||||
llc_saving = 130;
|
||||
} else if (codec_input.codec == CODEC_HEVC) {
|
||||
if (codec_input.lcu_size == 32) {
|
||||
frame_lcu_size = 32;
|
||||
collocated_bytes_per_lcu = 64;
|
||||
llc_saving = 114;
|
||||
} else if (codec_input.lcu_size == 64) {
|
||||
frame_lcu_size = 64;
|
||||
collocated_bytes_per_lcu = 256;
|
||||
llc_saving = 107;
|
||||
}
|
||||
} else if (codec_input.codec == CODEC_VP9) {
|
||||
if (codec_input.lcu_size == 32) {
|
||||
frame_lcu_size = 32;
|
||||
collocated_bytes_per_lcu = 64;
|
||||
llc_saving = 114;
|
||||
} else if (codec_input.lcu_size == 64) {
|
||||
frame_lcu_size = 64;
|
||||
collocated_bytes_per_lcu = 256;
|
||||
llc_saving = 107;
|
||||
}
|
||||
} else if (codec_input.codec == CODEC_AV1) {
|
||||
u32 av1d_leftline_cdef = (2944 + 896 + 896);
|
||||
u32 av1d_leftline_scaling = (2176 + 1408 + 1408);
|
||||
u32 av1d_leftline_fg = (1280);
|
||||
u32 av1d_leftline_lr = (1536 + 1024 + 1024);
|
||||
|
||||
av1d_fe_leftlinebuffer_perlcu_tileboudary =
|
||||
av1d_leftline_cdef + av1d_leftline_scaling +
|
||||
av1d_leftline_fg + av1d_leftline_lr;
|
||||
|
||||
if (codec_input.lcu_size == 128) {
|
||||
frame_lcu_size = 128;
|
||||
collocated_bytes_per_lcu = 4 * 512;
|
||||
av1d_segment_read_per_lcu = 512;
|
||||
llc_saving = 104;
|
||||
} else if (codec_input.lcu_size == 32) {
|
||||
frame_lcu_size = 32;
|
||||
collocated_bytes_per_lcu = 4 * 512 / (128 * 128 / 32 / 32);
|
||||
av1d_segment_read_per_lcu = 512 / (128 * 128 / 32 / 32);
|
||||
av1d_fe_leftlinebuffer_perlcu_tileboudary =
|
||||
av1d_fe_leftlinebuffer_perlcu_tileboudary / (128 * 128 / 32 / 32);
|
||||
llc_saving = 114;
|
||||
} else if (codec_input.lcu_size == 64) {
|
||||
frame_lcu_size = 64;
|
||||
collocated_bytes_per_lcu = 4 * 512 / (128 * 128 / 64 / 64);
|
||||
av1d_segment_read_per_lcu = 512 / (128 * 128 / 64 / 64);
|
||||
av1d_fe_leftlinebuffer_perlcu_tileboudary =
|
||||
av1d_fe_leftlinebuffer_perlcu_tileboudary / (128 * 128 / 64 / 64);
|
||||
llc_saving = 107;
|
||||
}
|
||||
}
|
||||
|
||||
lcu_per_frame =
|
||||
calculate_number_lcus_kalama(frame_width, frame_height, frame_lcu_size);
|
||||
|
||||
target_bitrate = (u32)(codec_input.bitrate_mbps); /* Mbps */
|
||||
|
||||
ubwc_tile_w = (codec_input.bitdepth == CODEC_BITDEPTH_8) ? 32 : 48;
|
||||
ubwc_tile_h = (codec_input.bitdepth == CODEC_BITDEPTH_8) ? 8 : 4;
|
||||
|
||||
frame420_y_bw_linear_8bpp =
|
||||
((calculate_number_ubwctiles_kalama(frame_width, frame_height, 32, 8) *
|
||||
256 * codec_input.frame_rate + 999) / 1000 + 999) / 1000;
|
||||
|
||||
frame420_y_bw_no_ubwc_tile_10bpp =
|
||||
((calculate_number_ubwctiles_kalama(frame_width, frame_height, 48, 4) *
|
||||
256 * codec_input.frame_rate + 999) / 1000 + 999) / 1000;
|
||||
frame420_y_bw_linear_10bpp = ((frame_width * frame_height *
|
||||
codec_input.frame_rate * 2 + 999) / 1000 + 999) / 1000;
|
||||
|
||||
/* TODO Integrate Compression Ratio returned by FW */
|
||||
get_compression_factors(&compression_factor, codec_input);
|
||||
dpb_compression_factor_y = compression_factor.dpb_cf_y;
|
||||
dpb_compression_factor_cbcr = compression_factor.dpb_cf_cbcr;
|
||||
opb_compression_factor_ycbcr = compression_factor.opb_cf_ycbcr;
|
||||
|
||||
dpb_ubwc_tile_width_pixels = ubwc_tile_w;
|
||||
|
||||
dpb_ubwc_tile_height_pixels = ubwc_tile_h;
|
||||
|
||||
decoder_frame_complexity_factor =
|
||||
(codec_input.complexity_setting == 0) ?
|
||||
400 : ((codec_input.complexity_setting == 1) ? 266 : 100);
|
||||
|
||||
reconstructed_write_bw_factor_rd = (codec_input.complexity_setting == 0) ?
|
||||
105 : 100;
|
||||
|
||||
reference_y_read_bw_factor = llc_saving;
|
||||
|
||||
reference_cbcr_read_bw_factor = llc_saving;
|
||||
|
||||
if (codec_input.codec == CODEC_AV1) {
|
||||
u8 av1tile_index_entry, av1tile_complexity;
|
||||
|
||||
if (frame_width * frame_height <= 1280 * 720)
|
||||
av1tile_index_entry = 4;
|
||||
else if (frame_width * frame_height <= 1920 * 1080)
|
||||
av1tile_index_entry = 0;
|
||||
else if (frame_width * frame_height <= 2560 * 1440)
|
||||
av1tile_index_entry = 5;
|
||||
else if (frame_width * frame_height <= 4096 * 2304)
|
||||
av1tile_index_entry = 1;
|
||||
else
|
||||
av1tile_index_entry = 6;
|
||||
|
||||
/* NOT PWC //or average and power case */
|
||||
if (codec_input.complexity_setting != 0)
|
||||
av1tile_complexity = 1;
|
||||
else
|
||||
av1tile_complexity = 0;
|
||||
|
||||
av1_tile_numbers = av1_num_tiles_kalama[av1tile_index_entry][av1tile_complexity];
|
||||
|
||||
/* these bw can be ignored */
|
||||
av1_collated_seg_buffer_rd_wr =
|
||||
((av1d_segment_read_per_lcu * lcu_per_frame *
|
||||
codec_input.frame_rate + 999) / 1000 + 999) / 1000;
|
||||
|
||||
av1_fe_left_line_buffer_rdwr =
|
||||
(((av1d_fe_leftlinebuffer_perlcu_tileboudary *
|
||||
frame_height * (av1_tile_numbers > 1 ? av1_tile_numbers / 2 : 0)
|
||||
+ 999) / 1000 + 999) / 1000 + (frame_lcu_size - 1)) / frame_lcu_size;
|
||||
}
|
||||
|
||||
if (codec_input.codec == CODEC_HEVC) {
|
||||
if (codec_input.lcu_size == 32)
|
||||
bse_tlb_byte_per_lcu = 64;
|
||||
else if (codec_input.lcu_size == 16)
|
||||
bse_tlb_byte_per_lcu = 32;
|
||||
else
|
||||
bse_tlb_byte_per_lcu = 128;
|
||||
} else if ((codec_input.codec == CODEC_H264) ||
|
||||
(codec_input.codec == CODEC_H264_CAVLC)) {
|
||||
bse_tlb_byte_per_lcu = 64;
|
||||
} else if (codec_input.codec == CODEC_VP9) {
|
||||
bse_tlb_byte_per_lcu = 304;
|
||||
} else if (codec_input.codec == CODEC_AV1) {
|
||||
if (codec_input.lcu_size == 128)
|
||||
bse_tlb_byte_per_lcu = 2064;
|
||||
else if (codec_input.lcu_size == 64)
|
||||
bse_tlb_byte_per_lcu = 1056;
|
||||
else if (codec_input.lcu_size == 32)
|
||||
bse_tlb_byte_per_lcu = 2064 / (128 * 128 / 32 / 32);
|
||||
}
|
||||
|
||||
codec_output->noc_bw_rd = 0;
|
||||
codec_output->noc_bw_wr = 0;
|
||||
codec_output->ddr_bw_rd = 0;
|
||||
codec_output->ddr_bw_wr = 0;
|
||||
|
||||
large_bw_calculation_fp = 0;
|
||||
large_bw_calculation_fp = ((target_bitrate *
|
||||
decoder_vsp_read_factor + 7) / 8);
|
||||
|
||||
codec_output->vsp_read_noc = large_bw_calculation_fp;
|
||||
|
||||
codec_output->vsp_read_ddr = codec_output->vsp_read_noc;
|
||||
|
||||
large_bw_calculation_fp = ((target_bitrate *
|
||||
bins_to_bits_factor + 7) / 8);
|
||||
|
||||
codec_output->vsp_write_noc = large_bw_calculation_fp;
|
||||
codec_output->vsp_write_ddr = codec_output->vsp_write_noc;
|
||||
|
||||
/* accumulation */
|
||||
codec_output->noc_bw_rd += codec_output->vsp_read_noc;
|
||||
codec_output->ddr_bw_rd += codec_output->vsp_read_ddr;
|
||||
codec_output->noc_bw_wr += codec_output->vsp_write_noc;
|
||||
codec_output->ddr_bw_wr += codec_output->vsp_write_ddr;
|
||||
|
||||
large_bw_calculation_fp = 0;
|
||||
large_bw_calculation_fp = ((collocated_bytes_per_lcu *
|
||||
lcu_per_frame * codec_input.frame_rate + 999) / 1000 + 999) / 1000;
|
||||
codec_output->collocated_rd_noc = large_bw_calculation_fp;
|
||||
codec_output->collocated_wr_noc = codec_output->collocated_rd_noc;
|
||||
codec_output->collocated_rd_ddr = codec_output->collocated_rd_noc;
|
||||
codec_output->collocated_wr_ddr = codec_output->collocated_wr_noc;
|
||||
|
||||
codec_output->collocated_rd_wr_total_noc =
|
||||
(u32)(codec_output->collocated_rd_noc + codec_output->collocated_wr_noc);
|
||||
|
||||
codec_output->collocated_rd_wr_total_ddr =
|
||||
codec_output->collocated_rd_wr_total_noc;
|
||||
|
||||
/* accumulation */
|
||||
codec_output->noc_bw_rd += codec_output->collocated_rd_noc;
|
||||
codec_output->noc_bw_wr += codec_output->collocated_wr_noc;
|
||||
codec_output->ddr_bw_rd += codec_output->collocated_rd_ddr;
|
||||
codec_output->ddr_bw_wr += codec_output->collocated_wr_ddr;
|
||||
|
||||
large_bw_calculation_fp = 0;
|
||||
large_bw_calculation_fp = ((codec_input.bitdepth == CODEC_BITDEPTH_8) ?
|
||||
frame420_y_bw_linear_8bpp :
|
||||
frame420_y_bw_no_ubwc_tile_10bpp) * decoder_frame_complexity_factor;
|
||||
|
||||
large_bw_calculation_fp =
|
||||
(large_bw_calculation_fp + dpb_compression_factor_y - 1) /
|
||||
dpb_compression_factor_y;
|
||||
|
||||
codec_output->dpb_rd_y_noc = large_bw_calculation_fp;
|
||||
|
||||
large_bw_calculation_fp = ((codec_input.bitdepth == CODEC_BITDEPTH_8) ?
|
||||
frame420_y_bw_linear_8bpp : frame420_y_bw_no_ubwc_tile_10bpp) *
|
||||
decoder_frame_complexity_factor;
|
||||
|
||||
large_bw_calculation_fp =
|
||||
(large_bw_calculation_fp + dpb_compression_factor_cbcr - 1) /
|
||||
dpb_compression_factor_cbcr / 2;
|
||||
|
||||
codec_output->dpb_rd_crcb_noc = large_bw_calculation_fp;
|
||||
codec_output->dpb_rdwr_duetooverlap_noc = 0;
|
||||
|
||||
large_bw_calculation_fp = ((codec_input.bitdepth == CODEC_BITDEPTH_8) ?
|
||||
frame420_y_bw_linear_8bpp : frame420_y_bw_no_ubwc_tile_10bpp) *
|
||||
reconstructed_write_bw_factor_rd;
|
||||
|
||||
large_bw_calculation_fp = ((codec_input.bitdepth == CODEC_BITDEPTH_8) ?
|
||||
frame420_y_bw_linear_8bpp : frame420_y_bw_no_ubwc_tile_10bpp) *
|
||||
reconstructed_write_bw_factor_rd;
|
||||
|
||||
large_bw_calculation_fp = large_bw_calculation_fp *
|
||||
(dpb_compression_factor_y / 2 + dpb_compression_factor_cbcr);
|
||||
|
||||
large_bw_calculation_fp = (large_bw_calculation_fp + dpb_compression_factor_y - 1) /
|
||||
dpb_compression_factor_y;
|
||||
|
||||
large_bw_calculation_fp =
|
||||
(large_bw_calculation_fp + dpb_compression_factor_cbcr - 1) /
|
||||
dpb_compression_factor_cbcr;
|
||||
|
||||
codec_output->dpb_wr_noc = large_bw_calculation_fp;
|
||||
|
||||
codec_output->dpb_rd_y_ddr = (llc_enabled_ref_y_rd) ?
|
||||
((codec_output->dpb_rd_y_noc * 100 + reference_y_read_bw_factor - 1) /
|
||||
reference_y_read_bw_factor) : codec_output->dpb_rd_y_noc;
|
||||
|
||||
codec_output->dpb_rd_crcb_ddr = (llc_enable_ref_crcb_rd) ?
|
||||
((codec_output->dpb_rd_crcb_noc * 100 +
|
||||
reference_cbcr_read_bw_factor - 1) /
|
||||
reference_cbcr_read_bw_factor) : codec_output->dpb_rd_crcb_noc;
|
||||
|
||||
codec_output->dpb_rdwr_duetooverlap_ddr = 0;
|
||||
codec_output->dpb_wr_ddr = codec_output->dpb_wr_noc;
|
||||
|
||||
/* accumulation */
|
||||
codec_output->noc_bw_rd += codec_output->dpb_rd_y_noc;
|
||||
codec_output->noc_bw_rd += codec_output->dpb_rd_crcb_noc;
|
||||
codec_output->noc_bw_rd += codec_output->dpb_rdwr_duetooverlap_noc;
|
||||
codec_output->noc_bw_wr += codec_output->dpb_wr_noc;
|
||||
codec_output->ddr_bw_rd += codec_output->dpb_rd_y_ddr;
|
||||
codec_output->ddr_bw_rd += codec_output->dpb_rd_crcb_ddr;
|
||||
codec_output->ddr_bw_rd += codec_output->dpb_rdwr_duetooverlap_ddr;
|
||||
codec_output->ddr_bw_wr += codec_output->dpb_wr_ddr;
|
||||
|
||||
if (codec_input.linear_opb || codec_input.split_opb) {
|
||||
if (codec_input.linear_opb) {
|
||||
if (codec_input.bitdepth == CODEC_BITDEPTH_8) {
|
||||
large_bw_calculation_fp = ((frame420_y_bw_linear_8bpp) *
|
||||
3 / 2 / dpb_to_opb_ratios_ds);
|
||||
|
||||
codec_output->opb_write_total_noc = large_bw_calculation_fp;
|
||||
} else {
|
||||
large_bw_calculation_fp = ((frame420_y_bw_linear_10bpp) *
|
||||
3 / 2 / dpb_to_opb_ratios_ds);
|
||||
|
||||
codec_output->opb_write_total_noc = large_bw_calculation_fp;
|
||||
}
|
||||
} else { /* (CODEC_INPUT.split_opb) */
|
||||
if (codec_input.bitdepth == CODEC_BITDEPTH_8) {
|
||||
large_bw_calculation_fp =
|
||||
(frame420_y_bw_linear_8bpp * 3 / 2 / dpb_to_opb_ratios_ds *
|
||||
100 + opb_compression_factor_ycbcr - 1) /
|
||||
opb_compression_factor_ycbcr;
|
||||
|
||||
codec_output->opb_write_total_noc = large_bw_calculation_fp;
|
||||
} else {
|
||||
large_bw_calculation_fp =
|
||||
(frame420_y_bw_no_ubwc_tile_10bpp * 3 / 2 /
|
||||
dpb_to_opb_ratios_ds * 100 +
|
||||
opb_compression_factor_ycbcr - 1) /
|
||||
opb_compression_factor_ycbcr;
|
||||
|
||||
codec_output->opb_write_total_noc = large_bw_calculation_fp;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
codec_output->opb_write_total_noc = 0;
|
||||
}
|
||||
|
||||
codec_output->opb_write_total_ddr = codec_output->opb_write_total_noc;
|
||||
|
||||
/* accumulation */
|
||||
codec_output->noc_bw_wr += codec_output->opb_write_total_noc;
|
||||
codec_output->ddr_bw_wr += codec_output->opb_write_total_ddr;
|
||||
|
||||
large_bw_calculation_fp = ((bse_tlb_byte_per_lcu * lcu_per_frame *
|
||||
codec_input.frame_rate + 999) / 1000 + 999) / 1000;
|
||||
|
||||
codec_output->bse_tlb_rd_noc = large_bw_calculation_fp;
|
||||
|
||||
if (llc_enabled_bse_tlb)
|
||||
codec_output->bse_tlb_rd_ddr = 0;
|
||||
else
|
||||
codec_output->bse_tlb_rd_ddr = codec_output->bse_tlb_rd_noc;
|
||||
|
||||
codec_output->bse_tlb_wr_noc = codec_output->bse_tlb_rd_noc;
|
||||
|
||||
if (llc_enabled_bse_tlb)
|
||||
codec_output->bse_tlb_wr_ddr = 0;
|
||||
else
|
||||
codec_output->bse_tlb_wr_ddr = codec_output->bse_tlb_wr_noc;
|
||||
|
||||
/* accumulation */
|
||||
codec_output->noc_bw_rd += codec_output->bse_tlb_rd_noc;
|
||||
codec_output->ddr_bw_rd += codec_output->bse_tlb_rd_ddr;
|
||||
codec_output->noc_bw_wr += codec_output->bse_tlb_wr_noc;
|
||||
codec_output->ddr_bw_wr += codec_output->bse_tlb_wr_ddr;
|
||||
|
||||
if (codec_input.codec == CODEC_AV1) {
|
||||
codec_output->statistics_rd_noc = (av1_collated_seg_buffer_rd_wr +
|
||||
av1_probability_table_rdwr_bytesperframe * av1_tile_numbers /
|
||||
1000 / 1000 + av1_fe_left_line_buffer_rdwr);
|
||||
|
||||
codec_output->statistics_wr_noc = (av1_collated_seg_buffer_rd_wr +
|
||||
av1_probability_table_rdwr_bytesperframe * av1_tile_numbers /
|
||||
1000 / 1000 + av1_fe_left_line_buffer_rdwr);
|
||||
|
||||
if (llc_enable_probtable_av1d_21pipe) {
|
||||
/* assert(CODEC_INPUT.pipe_num != 4); */
|
||||
codec_output->statistics_rd_ddr = codec_output->statistics_rd_noc -
|
||||
av1_probability_table_rdwr_bytesperframe *
|
||||
av1_tile_numbers / 1000 / 1000;
|
||||
|
||||
codec_output->statistics_wr_ddr = codec_output->statistics_wr_noc -
|
||||
av1_probability_table_rdwr_bytesperframe *
|
||||
av1_tile_numbers / 1000 / 1000;
|
||||
} else {
|
||||
codec_output->statistics_rd_ddr = codec_output->statistics_rd_noc;
|
||||
codec_output->statistics_wr_ddr = codec_output->statistics_wr_noc;
|
||||
}
|
||||
|
||||
/* accumulation */
|
||||
codec_output->noc_bw_rd += codec_output->statistics_rd_noc;
|
||||
codec_output->ddr_bw_rd += codec_output->statistics_rd_ddr;
|
||||
codec_output->noc_bw_wr += codec_output->statistics_wr_noc;
|
||||
codec_output->ddr_bw_wr += codec_output->statistics_wr_ddr;
|
||||
}
|
||||
|
||||
|
||||
codec_output->mmu_rd_ddr = 0;
|
||||
codec_output->mmu_rd_noc = 0;
|
||||
/* accumulation */
|
||||
codec_output->noc_bw_rd += codec_output->mmu_rd_noc;
|
||||
codec_output->ddr_bw_rd += codec_output->mmu_rd_ddr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int calculate_bandwidth_encoder_iris3(
|
||||
struct api_calculation_input codec_input,
|
||||
struct api_calculation_bw_output *codec_output)
|
||||
{
|
||||
/* common control parameters */
|
||||
u32 frame_width;
|
||||
u32 frame_height;
|
||||
u32 frame_lcu_size;
|
||||
u32 lcu_per_frame;
|
||||
u32 target_bitrate;
|
||||
u32 collocated_bytes_per_lcu;
|
||||
|
||||
u32 frame420_y_bw_linear_8bpp;
|
||||
u32 frame420_y_bw_no_ubwc_tile_10bpp;
|
||||
u32 frame420_y_bw_linear_10bpp;
|
||||
|
||||
u16 ubwc_tile_w;
|
||||
u16 ubwc_tile_h;
|
||||
|
||||
u32 dpb_compression_factor_y;
|
||||
u32 dpb_compression_factor_cbcr;
|
||||
|
||||
u32 reconstructed_write_bw_factor_rd;
|
||||
u32 reference_y_read_bw_factor;
|
||||
u32 reference_crcb_read_bw_factor;
|
||||
|
||||
/* encoder control parameters */
|
||||
u32 en_vertical_tiles_width = 960;
|
||||
|
||||
u8 en_rotation_90_270 = 0;
|
||||
/* TODO Can we use (codec_input.status_llc_onoff) for enc_llc_*? */
|
||||
u8 en_llc_enable_ref_rd_crcb = 0;
|
||||
u8 en_llc_enable_rec_wr_uncompleted = 0;
|
||||
u8 en_llc_enable_ref_rd_y_overlap = 0;
|
||||
|
||||
u32 en_bins_to_bits_factor = 4;
|
||||
u32 en_search_windows_size_horizontal = 96;
|
||||
|
||||
u32 en_tile_number;
|
||||
u32 ipb_compression_factor_y;
|
||||
u32 ipb_compression_factor;
|
||||
|
||||
u32 large_bw_calculation_fp = 0;
|
||||
|
||||
/* TODO Are these really needed in Encoder? */
|
||||
u32 bse_tlb_byte_per_lcu = 0;
|
||||
u8 llc_enabled_bse_tlb = 1;
|
||||
|
||||
/*H265D BSE tlb in LLC will be pored in Kailua */
|
||||
llc_enabled_bse_tlb = (codec_input.status_llc_onoff) ? 1 : 0;
|
||||
|
||||
frame_width = codec_input.frame_width;
|
||||
frame_height = codec_input.frame_height;
|
||||
if ((codec_input.codec == CODEC_H264) ||
|
||||
(codec_input.codec == CODEC_H264_CAVLC)) {
|
||||
frame_lcu_size = 16;
|
||||
collocated_bytes_per_lcu = 16;
|
||||
} else if (codec_input.codec == CODEC_HEVC) {
|
||||
frame_lcu_size = 32;
|
||||
collocated_bytes_per_lcu = 64;
|
||||
} else {
|
||||
/* TODO What is the value for VP9, AV1? */
|
||||
frame_lcu_size = 16;
|
||||
collocated_bytes_per_lcu = 16; /* TODO Fixes Uninitialized compilation error. */
|
||||
}
|
||||
|
||||
lcu_per_frame =
|
||||
calculate_number_lcus_kalama(frame_width, frame_height, frame_lcu_size);
|
||||
|
||||
bse_tlb_byte_per_lcu = 16; /* TODO Should be in common declaration */
|
||||
|
||||
target_bitrate = (u32)(codec_input.bitrate_mbps); /* Mbps */
|
||||
|
||||
ubwc_tile_w = (codec_input.bitdepth == CODEC_BITDEPTH_8) ? 32 : 48;
|
||||
ubwc_tile_h = (codec_input.bitdepth == CODEC_BITDEPTH_8) ? 8 : 4;
|
||||
|
||||
/* yuv */
|
||||
if (codec_input.ipb_yuvrgb == 0) {
|
||||
frame420_y_bw_linear_8bpp =
|
||||
((calculate_number_ubwctiles_kalama(frame_width, frame_height,
|
||||
32, 8) * 256 * codec_input.frame_rate + 999) / 1000 + 999) / 1000;
|
||||
} else { /* RGBA */
|
||||
frame420_y_bw_linear_8bpp =
|
||||
((calculate_number_ubwctiles_kalama(frame_width, frame_height,
|
||||
6, 4) * 256 * codec_input.frame_rate + 999) / 1000 + 999) / 1000;
|
||||
}
|
||||
|
||||
frame420_y_bw_no_ubwc_tile_10bpp =
|
||||
((calculate_number_ubwctiles_kalama(frame_width, frame_height, 48, 4) *
|
||||
256 * codec_input.frame_rate + 999) / 1000 + 999) / 1000;
|
||||
|
||||
frame420_y_bw_linear_10bpp = ((frame_width * frame_height *
|
||||
codec_input.frame_rate * 2 + 999) / 1000 + 999) / 1000;
|
||||
|
||||
/* TODO Integrate Compression Ratio returned by FW */
|
||||
get_compression_factors(&compression_factor, codec_input);
|
||||
dpb_compression_factor_y = compression_factor.dpb_cf_y;
|
||||
dpb_compression_factor_cbcr = compression_factor.dpb_cf_cbcr;
|
||||
ipb_compression_factor_y = compression_factor.ipb_cr_y;
|
||||
ipb_compression_factor = compression_factor.ipb_cr;
|
||||
|
||||
en_tile_number = (frame_width % en_vertical_tiles_width) ?
|
||||
((frame_width / en_vertical_tiles_width) + 1) :
|
||||
(frame_width / en_vertical_tiles_width);
|
||||
|
||||
en_tile_number = en_tile_number * 100;
|
||||
|
||||
/* ceil is same as excel roundup (float, 0); */
|
||||
reconstructed_write_bw_factor_rd = ((en_tile_number - 100) * 2 *
|
||||
((codec_input.lcu_size + ubwc_tile_w - 1) / ubwc_tile_w) *
|
||||
ubwc_tile_w + (frame_width - 1)) / (frame_width)+100;
|
||||
|
||||
reference_y_read_bw_factor = ((en_tile_number - 100) * 2 *
|
||||
((en_search_windows_size_horizontal + ubwc_tile_w - 1) / ubwc_tile_w) *
|
||||
ubwc_tile_w + (frame_width - 1)) / frame_width + 100;
|
||||
|
||||
reference_crcb_read_bw_factor = 150;
|
||||
|
||||
codec_output->noc_bw_rd = 0;
|
||||
codec_output->noc_bw_wr = 0;
|
||||
codec_output->ddr_bw_rd = 0;
|
||||
codec_output->ddr_bw_wr = 0;
|
||||
|
||||
large_bw_calculation_fp = (target_bitrate * en_bins_to_bits_factor + 7) / 8;
|
||||
codec_output->vsp_read_noc = large_bw_calculation_fp;
|
||||
codec_output->vsp_read_ddr = codec_output->vsp_read_noc;
|
||||
large_bw_calculation_fp = (target_bitrate + 7) / 8;
|
||||
|
||||
codec_output->vsp_write_noc = codec_output->vsp_read_noc +
|
||||
large_bw_calculation_fp;
|
||||
|
||||
codec_output->vsp_write_ddr = codec_output->vsp_write_noc;
|
||||
|
||||
/* accumulation */
|
||||
codec_output->noc_bw_rd += codec_output->vsp_read_noc;
|
||||
codec_output->ddr_bw_rd += codec_output->vsp_read_ddr;
|
||||
codec_output->noc_bw_wr += codec_output->vsp_write_noc;
|
||||
codec_output->ddr_bw_wr += codec_output->vsp_write_ddr;
|
||||
|
||||
large_bw_calculation_fp = ((collocated_bytes_per_lcu * lcu_per_frame *
|
||||
codec_input.frame_rate + 999) / 1000 + 999) / 1000;
|
||||
|
||||
codec_output->collocated_rd_noc = large_bw_calculation_fp;
|
||||
codec_output->collocated_wr_noc = codec_output->collocated_rd_noc;
|
||||
codec_output->collocated_rd_ddr = codec_output->collocated_rd_noc;
|
||||
codec_output->collocated_wr_ddr = codec_output->collocated_wr_noc;
|
||||
|
||||
codec_output->collocated_rd_wr_total_noc =
|
||||
(u32)(codec_output->collocated_rd_noc + codec_output->collocated_wr_noc);
|
||||
codec_output->collocated_rd_wr_total_ddr =
|
||||
codec_output->collocated_rd_wr_total_noc;
|
||||
|
||||
/* accumulation */
|
||||
codec_output->noc_bw_rd += codec_output->collocated_rd_noc;
|
||||
codec_output->noc_bw_wr += codec_output->collocated_wr_noc;
|
||||
codec_output->ddr_bw_rd += codec_output->collocated_rd_ddr;
|
||||
codec_output->ddr_bw_wr += codec_output->collocated_wr_ddr;
|
||||
|
||||
large_bw_calculation_fp = 0;
|
||||
|
||||
large_bw_calculation_fp = ((codec_input.bitdepth == CODEC_BITDEPTH_8) ?
|
||||
frame420_y_bw_linear_8bpp :
|
||||
frame420_y_bw_no_ubwc_tile_10bpp) * reference_y_read_bw_factor;
|
||||
|
||||
large_bw_calculation_fp = (large_bw_calculation_fp *
|
||||
kalama_en_readfactor[codec_input.hierachical_layer]);
|
||||
|
||||
large_bw_calculation_fp = (large_bw_calculation_fp +
|
||||
dpb_compression_factor_y - 1) / dpb_compression_factor_y;
|
||||
|
||||
large_bw_calculation_fp = (large_bw_calculation_fp + 999) / 1000;
|
||||
|
||||
codec_output->dpb_rd_y_noc = large_bw_calculation_fp;
|
||||
|
||||
large_bw_calculation_fp = 0;
|
||||
|
||||
large_bw_calculation_fp = ((codec_input.bitdepth == CODEC_BITDEPTH_8) ?
|
||||
frame420_y_bw_linear_8bpp :
|
||||
frame420_y_bw_no_ubwc_tile_10bpp) * reference_crcb_read_bw_factor / 2;
|
||||
|
||||
large_bw_calculation_fp = large_bw_calculation_fp *
|
||||
kalama_en_readfactor[codec_input.hierachical_layer];
|
||||
|
||||
large_bw_calculation_fp = (large_bw_calculation_fp +
|
||||
dpb_compression_factor_cbcr - 1) / dpb_compression_factor_cbcr;
|
||||
|
||||
large_bw_calculation_fp = (large_bw_calculation_fp + 999) / 1000;
|
||||
codec_output->dpb_rd_crcb_noc = large_bw_calculation_fp;
|
||||
|
||||
large_bw_calculation_fp = 0;
|
||||
|
||||
large_bw_calculation_fp = ((codec_input.bitdepth == CODEC_BITDEPTH_8) ?
|
||||
frame420_y_bw_linear_8bpp : frame420_y_bw_no_ubwc_tile_10bpp) *
|
||||
reconstructed_write_bw_factor_rd *
|
||||
kalama_en_writefactor[codec_input.hierachical_layer] /
|
||||
kalama_en_frame_num_parallel;
|
||||
|
||||
large_bw_calculation_fp = (large_bw_calculation_fp + 999) / 1000;
|
||||
|
||||
large_bw_calculation_fp = large_bw_calculation_fp *
|
||||
(dpb_compression_factor_cbcr + dpb_compression_factor_y / 2);
|
||||
|
||||
large_bw_calculation_fp = (large_bw_calculation_fp +
|
||||
dpb_compression_factor_y - 1) / dpb_compression_factor_y;
|
||||
|
||||
large_bw_calculation_fp = (large_bw_calculation_fp +
|
||||
dpb_compression_factor_cbcr - 1) / dpb_compression_factor_cbcr;
|
||||
|
||||
codec_output->dpb_wr_noc = large_bw_calculation_fp;
|
||||
|
||||
/*
|
||||
* Summary:
|
||||
* by default (for both HFR and HSR cases) :
|
||||
* -Any resolution and fps >= 120, enable layering.
|
||||
* (120 -> 3, 240 -> 4, 480 -> 5)
|
||||
* - (once we enable layering) : 50 per cent frames are Non - reference
|
||||
* frames.recon write is disable by Venus firmware
|
||||
* - Customer has ability to enable / disable layering.
|
||||
* Hence, recon write savings would not be there if
|
||||
* customer explicitly disables layer encoding.
|
||||
*/
|
||||
|
||||
/*HFR Cases use alternating rec write if not PWC*/
|
||||
if ((codec_input.frame_rate >= 120) && (codec_input.complexity_setting != 0))
|
||||
codec_output->dpb_wr_noc = codec_output->dpb_wr_noc / 2;
|
||||
|
||||
/* for power cases with [B1] adaptive non-ref b frame */
|
||||
/* power caes IbP non reference b */
|
||||
if ((codec_input.hierachical_layer >= 1) &&
|
||||
(codec_input.hierachical_layer <= 3) &&
|
||||
(codec_input.complexity_setting != 0))
|
||||
codec_output->dpb_wr_noc = codec_output->dpb_wr_noc / 2;
|
||||
|
||||
large_bw_calculation_fp = 0;
|
||||
large_bw_calculation_fp = codec_output->dpb_wr_noc *
|
||||
(reconstructed_write_bw_factor_rd - 100);
|
||||
|
||||
large_bw_calculation_fp = (large_bw_calculation_fp +
|
||||
reconstructed_write_bw_factor_rd - 1) / reconstructed_write_bw_factor_rd;
|
||||
|
||||
codec_output->dpb_rdwr_duetooverlap_noc = large_bw_calculation_fp;
|
||||
|
||||
codec_output->dpb_rd_y_ddr = (en_llc_enable_ref_rd_y_overlap) ?
|
||||
(codec_output->dpb_rd_y_noc * 100 + reference_y_read_bw_factor - 1) /
|
||||
reference_y_read_bw_factor : codec_output->dpb_rd_y_noc;
|
||||
|
||||
codec_output->dpb_rd_crcb_ddr = (en_llc_enable_ref_rd_crcb) ?
|
||||
(codec_output->dpb_rd_crcb_noc * 100 + reference_crcb_read_bw_factor - 1) /
|
||||
reference_crcb_read_bw_factor : codec_output->dpb_rd_crcb_noc;
|
||||
|
||||
codec_output->dpb_rdwr_duetooverlap_ddr = (en_llc_enable_rec_wr_uncompleted) ?
|
||||
0 : codec_output->dpb_rdwr_duetooverlap_noc;
|
||||
|
||||
codec_output->dpb_wr_ddr = (en_llc_enable_rec_wr_uncompleted) ?
|
||||
0 : codec_output->dpb_wr_noc;
|
||||
|
||||
/* accumulation */
|
||||
codec_output->noc_bw_rd += codec_output->dpb_rd_y_noc;
|
||||
codec_output->noc_bw_rd += codec_output->dpb_rd_crcb_noc;
|
||||
codec_output->noc_bw_rd += codec_output->dpb_rdwr_duetooverlap_noc;
|
||||
codec_output->noc_bw_wr += codec_output->dpb_wr_noc;
|
||||
codec_output->ddr_bw_rd += codec_output->dpb_rd_y_ddr;
|
||||
codec_output->ddr_bw_rd += codec_output->dpb_rd_crcb_ddr;
|
||||
codec_output->ddr_bw_rd += codec_output->dpb_rdwr_duetooverlap_ddr;
|
||||
codec_output->ddr_bw_wr += codec_output->dpb_wr_ddr;
|
||||
|
||||
if (codec_input.bitdepth == CODEC_BITDEPTH_8) {
|
||||
if (codec_input.ipb_yuvrgb == 0) { /* yuv */
|
||||
large_bw_calculation_fp = ((frame420_y_bw_linear_8bpp) * 3 / 2);
|
||||
codec_output->ipb_rd_total_noc = large_bw_calculation_fp;
|
||||
if (codec_input.linear_ipb == 0) {
|
||||
codec_output->ipb_rd_total_noc =
|
||||
(large_bw_calculation_fp * 100 +
|
||||
ipb_compression_factor - 1) / ipb_compression_factor;
|
||||
}
|
||||
} else { /* rgb */
|
||||
large_bw_calculation_fp = frame420_y_bw_linear_8bpp;
|
||||
codec_output->ipb_rd_total_noc = large_bw_calculation_fp;
|
||||
if (codec_input.linear_ipb == 0) {
|
||||
if (codec_input.complexity_setting == 0) /* pwc */
|
||||
codec_output->ipb_rd_total_noc =
|
||||
(large_bw_calculation_fp * 100 +
|
||||
en_original_compression_factor_rgba_pwd_kalama
|
||||
- 1) /
|
||||
en_original_compression_factor_rgba_pwd_kalama;
|
||||
else
|
||||
codec_output->ipb_rd_total_noc =
|
||||
(large_bw_calculation_fp * 100 +
|
||||
en_original_compression_factor_rgba_avg_kalama - 1) /
|
||||
en_original_compression_factor_rgba_avg_kalama;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (codec_input.linear_ipb == 1) {
|
||||
large_bw_calculation_fp = (frame420_y_bw_linear_10bpp) * 3 / 2;
|
||||
codec_output->ipb_rd_total_noc = large_bw_calculation_fp;
|
||||
} else {
|
||||
large_bw_calculation_fp = (frame420_y_bw_no_ubwc_tile_10bpp *
|
||||
300 / 2 + ipb_compression_factor - 1) / ipb_compression_factor;
|
||||
codec_output->ipb_rd_total_noc = large_bw_calculation_fp;
|
||||
}
|
||||
}
|
||||
|
||||
if (en_rotation_90_270) {
|
||||
if (codec_input.codec == CODEC_HEVC) {
|
||||
if ((codec_input.bitdepth == CODEC_BITDEPTH_8) &&
|
||||
(codec_input.ipb_yuvrgb == 0))
|
||||
codec_output->ipb_rd_total_noc = codec_output->ipb_rd_total_noc
|
||||
* 1;
|
||||
else
|
||||
codec_output->ipb_rd_total_noc = codec_output->ipb_rd_total_noc
|
||||
* 3;
|
||||
} else {
|
||||
codec_output->ipb_rd_total_noc = codec_output->ipb_rd_total_noc * 2;
|
||||
}
|
||||
}
|
||||
|
||||
codec_output->ipb_rd_total_ddr = codec_output->ipb_rd_total_noc;
|
||||
|
||||
/* accumulation */
|
||||
codec_output->noc_bw_rd += codec_output->ipb_rd_total_noc;
|
||||
codec_output->ddr_bw_rd += codec_output->ipb_rd_total_ddr;
|
||||
|
||||
codec_output->bse_tlb_rd_noc =
|
||||
((bse_tlb_byte_per_lcu * lcu_per_frame * codec_input.frame_rate + 999)
|
||||
/ 1000 + 999) / 1000;
|
||||
|
||||
if (llc_enabled_bse_tlb) /* TODO should be common declaration */
|
||||
codec_output->bse_tlb_rd_ddr = 0;
|
||||
else
|
||||
codec_output->bse_tlb_rd_ddr = codec_output->bse_tlb_rd_noc;
|
||||
|
||||
codec_output->bse_tlb_wr_noc = codec_output->bse_tlb_rd_noc;
|
||||
|
||||
if (llc_enabled_bse_tlb)
|
||||
codec_output->bse_tlb_wr_ddr = 0;
|
||||
else
|
||||
codec_output->bse_tlb_wr_ddr = codec_output->bse_tlb_wr_noc;
|
||||
|
||||
/* accumulation */
|
||||
codec_output->noc_bw_rd += codec_output->bse_tlb_rd_noc;
|
||||
codec_output->ddr_bw_rd += codec_output->bse_tlb_rd_ddr;
|
||||
codec_output->noc_bw_wr += codec_output->bse_tlb_wr_noc;
|
||||
codec_output->ddr_bw_wr += codec_output->bse_tlb_wr_ddr;
|
||||
|
||||
codec_output->mmu_rd_ddr = 0;
|
||||
codec_output->mmu_rd_noc = 0;
|
||||
/* accumulation */
|
||||
codec_output->noc_bw_rd += codec_output->mmu_rd_noc;
|
||||
codec_output->ddr_bw_rd += codec_output->mmu_rd_ddr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_calculate_bandwidth(struct api_calculation_input codec_input,
|
||||
struct api_calculation_bw_output *codec_output)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (codec_input.decoder_or_encoder == CODEC_DECODER) {
|
||||
rc = calculate_bandwidth_decoder_iris3(codec_input, codec_output);
|
||||
} else if (codec_input.decoder_or_encoder == CODEC_ENCODER) {
|
||||
rc = calculate_bandwidth_encoder_iris3(codec_input, codec_output);
|
||||
} else {
|
||||
d_vpr_e("%s: invalid codec\n", codec_input.decoder_or_encoder);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -0,0 +1,557 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "kalama_technology.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
|
||||
static u32 calculate_number_mbs_kalama(u32 width, u32 height, u32 lcu_size)
|
||||
{
|
||||
u32 mbs_width = (width % lcu_size) ?
|
||||
(width / lcu_size + 1) : (width / lcu_size);
|
||||
|
||||
u32 mbs_height = (height % lcu_size) ?
|
||||
(height / lcu_size + 1) : (height / lcu_size);
|
||||
|
||||
return mbs_width * mbs_height * (lcu_size / 16) * (lcu_size / 16);
|
||||
}
|
||||
|
||||
static int initialize_encoder_complexity_table(void)
|
||||
{
|
||||
/* Beging Calculate Encoder GOP Complexity Table and HW Floor numbers */
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_Bb_ENTRY] = 70000;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_P_ENTRY] = 10000;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_Bb_ENTRY] * 150 +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_P_ENTRY] * 100);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] +
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_P_ENTRY] - 1);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] /
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_P_ENTRY]);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_Bb_ENTRY] = 30000;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_P_ENTRY] = 10000;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_Bb_ENTRY] * 150 +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_P_ENTRY] * 100);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] +
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_P_ENTRY] - 1);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] /
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_P_ENTRY]);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_Bb_ENTRY] = 10000;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_P_ENTRY] = 10000;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_Bb_ENTRY] * 150 +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_P_ENTRY] * 100);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_FACTORY_ENTRY] +
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_P_ENTRY] - 1);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_FACTORY_ENTRY] /
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_P_ENTRY]);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_Bb_ENTRY] = 0;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_P_ENTRY] = 1;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_Bb_ENTRY] * 150 +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_P_ENTRY] * 100);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_FACTORY_ENTRY] +
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_P_ENTRY] - 1);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_FACTORY_ENTRY] /
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_P_ENTRY]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 get_bitrate_entry(u32 pixle_count)
|
||||
{
|
||||
u32 bitrate_entry = 0;
|
||||
|
||||
if (pixle_count >= fp_pixel_count_bar1)
|
||||
bitrate_entry = 1;
|
||||
else if (pixle_count >= fp_pixel_count_bar2)
|
||||
bitrate_entry = 2;
|
||||
else if (pixle_count >= fp_pixel_count_bar3)
|
||||
bitrate_entry = 3;
|
||||
else if (pixle_count >= fp_pixel_count_bar4)
|
||||
bitrate_entry = 4;
|
||||
else if (pixle_count >= fp_pixel_count_bar5)
|
||||
bitrate_entry = 5;
|
||||
else if (pixle_count >= fp_pixel_count_bar6)
|
||||
bitrate_entry = 6;
|
||||
else if (pixle_count >= fp_pixel_count_bar7)
|
||||
bitrate_entry = 7;
|
||||
else if (pixle_count >= fp_pixel_count_bar8)
|
||||
bitrate_entry = 8;
|
||||
else if (pixle_count >= fp_pixel_count_bar9)
|
||||
bitrate_entry = 9;
|
||||
else
|
||||
bitrate_entry = 9;
|
||||
|
||||
return bitrate_entry;
|
||||
}
|
||||
|
||||
static int calculate_vsp_min_freq(struct api_calculation_input codec_input,
|
||||
struct api_calculation_freq_output *codec_output)
|
||||
{
|
||||
/*
|
||||
* VSP calculation
|
||||
* different methodology from Lahaina
|
||||
*/
|
||||
u32 vsp_hw_min_frequency = 0;
|
||||
/* UInt32 decoder_vsp_fw_overhead = 100 + 5; // amplified by 100x */
|
||||
u32 fw_sw_vsp_offset = 1000 + 55; /* amplified by 1000x */
|
||||
|
||||
/*
|
||||
* Ignore fw_sw_vsp_offset, as this is baked into the reference bitrate tables.
|
||||
* As a consequence remove x1000 multipler as well.
|
||||
*/
|
||||
u32 codec = codec_input.codec;
|
||||
/* UInt32 *bitratetable; */
|
||||
u32 pixle_count = codec_input.frame_width *
|
||||
codec_input.frame_height * codec_input.frame_rate;
|
||||
|
||||
u8 bitrate_entry = get_bitrate_entry(pixle_count); /* TODO EXTRACT */
|
||||
|
||||
input_bitrate_fp = ((u32)(codec_input.bitrate_mbps * 100 + 99)) / 100;
|
||||
vsp_hw_min_frequency = frequency_table_kalama[0][1] * input_bitrate_fp * 1000;
|
||||
|
||||
/* 8KUHD60fps with B frame */
|
||||
if ((pixle_count >= fp_pixel_count_bar0) &&
|
||||
(codec_input.hierachical_layer != CODEC_GOP_IPP)) {
|
||||
/*
|
||||
* FORMULA: VSPfreq = NOMINAL * (InputBitrate / ReferenceBitrate);
|
||||
* ReferenceBitrate = 0 for,
|
||||
* - 1Stage TURBO, all Codecs.
|
||||
* - 2Stage TURBO, H264 & H265.
|
||||
*
|
||||
* 8KUHD60fps with B frame
|
||||
* - bitrate_entry = 0
|
||||
* - Clock=NOMINAL for H264 & 2Stage H265. Because bitrate
|
||||
* table entry for TURBO is 0.
|
||||
*
|
||||
* TODO : Reduce these conditions by removing the zero entries from Bitrate table.
|
||||
*/
|
||||
vsp_hw_min_frequency = frequency_table_kalama[0][1] *
|
||||
input_bitrate_fp * 1000;
|
||||
|
||||
if (codec_input.codec == CODEC_AV1)
|
||||
vsp_hw_min_frequency = frequency_table_kalama[0][0] *
|
||||
input_bitrate_fp * 1000;
|
||||
|
||||
if ((codec_input.codec == CODEC_H264) ||
|
||||
(codec_input.codec == CODEC_H264_CAVLC) ||
|
||||
((codec_input.codec == CODEC_HEVC) &&
|
||||
(codec_input.vsp_vpp_mode == CODEC_VSPVPP_MODE_1S))) {
|
||||
vsp_hw_min_frequency =
|
||||
DIV_ROUND_UP(frequency_table_kalama[0][1], fw_sw_vsp_offset);
|
||||
} else if (((codec_input.codec == CODEC_HEVC) &&
|
||||
(codec_input.vsp_vpp_mode == CODEC_VSPVPP_MODE_2S))
|
||||
|| (codec_input.codec == CODEC_VP9)
|
||||
|| (codec_input.codec == CODEC_AV1)) {
|
||||
if (codec_input.vsp_vpp_mode == CODEC_VSPVPP_MODE_2S) {
|
||||
vsp_hw_min_frequency = DIV_ROUND_UP(vsp_hw_min_frequency,
|
||||
(bitrate_table_kalama_2stage_fp[codec][0] *
|
||||
fw_sw_vsp_offset));
|
||||
} else {
|
||||
vsp_hw_min_frequency = DIV_ROUND_UP(vsp_hw_min_frequency,
|
||||
(bitrate_table_kalama_1stage_fp[codec][0] *
|
||||
fw_sw_vsp_offset));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vsp_hw_min_frequency = frequency_table_kalama[0][1] *
|
||||
input_bitrate_fp * 1000;
|
||||
|
||||
if (codec_input.codec == CODEC_AV1 && bitrate_entry == 1)
|
||||
vsp_hw_min_frequency = frequency_table_kalama[0][0] *
|
||||
input_bitrate_fp * 1000;
|
||||
|
||||
if ((codec_input.codec == CODEC_H264_CAVLC) &&
|
||||
(codec_input.entropy_coding_mode == CODEC_ENTROPY_CODING_CAVLC))
|
||||
codec = CODEC_H264_CAVLC;
|
||||
else if ((codec_input.codec == CODEC_H264) &&
|
||||
(codec_input.entropy_coding_mode == CODEC_ENTROPY_CODING_CABAC))
|
||||
codec = CODEC_H264;
|
||||
|
||||
if (codec_input.vsp_vpp_mode == CODEC_VSPVPP_MODE_2S)
|
||||
vsp_hw_min_frequency = DIV_ROUND_UP(vsp_hw_min_frequency,
|
||||
(bitrate_table_kalama_2stage_fp[codec][bitrate_entry]) *
|
||||
fw_sw_vsp_offset);
|
||||
else
|
||||
vsp_hw_min_frequency = DIV_ROUND_UP(vsp_hw_min_frequency,
|
||||
(bitrate_table_kalama_1stage_fp[codec][bitrate_entry]) *
|
||||
fw_sw_vsp_offset);
|
||||
}
|
||||
|
||||
codec_output->vsp_min_freq = vsp_hw_min_frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 calculate_pipe_penalty(struct api_calculation_input codec_input)
|
||||
{
|
||||
u32 pipe_penalty_codec = 0;
|
||||
u8 avid_commercial_content = 0;
|
||||
u32 pixel_count = 0;
|
||||
|
||||
/* decoder */
|
||||
if (codec_input.decoder_or_encoder == CODEC_DECODER) {
|
||||
pipe_penalty_codec = pipe_penalty_kalama[0][0];
|
||||
avid_commercial_content = codec_input.av1d_commer_tile_enable;
|
||||
if (codec_input.codec == CODEC_AV1) {
|
||||
pixel_count = codec_input.frame_width * codec_input.frame_height;
|
||||
if (pixel_count <= 1920 * 1080)
|
||||
pipe_penalty_codec =
|
||||
pipe_penalty_kalama[avid_commercial_content + 1][0];
|
||||
else if (pixel_count < 3840 * 2160)
|
||||
pipe_penalty_codec =
|
||||
(pipe_penalty_kalama[avid_commercial_content + 1][0] +
|
||||
pipe_penalty_kalama[avid_commercial_content + 1][1]) / 2;
|
||||
else if ((pixel_count == 3840 * 2160) ||
|
||||
(pixel_count == 4096 * 2160) || (pixel_count == 4096 * 2304))
|
||||
pipe_penalty_codec =
|
||||
pipe_penalty_kalama[avid_commercial_content + 1][1];
|
||||
else if (pixel_count < 7680 * 4320)
|
||||
pipe_penalty_codec =
|
||||
(pipe_penalty_kalama[avid_commercial_content + 1][1] +
|
||||
pipe_penalty_kalama[avid_commercial_content + 1][2]) / 2;
|
||||
else
|
||||
pipe_penalty_codec =
|
||||
pipe_penalty_kalama[avid_commercial_content + 1][2];
|
||||
}
|
||||
} else {
|
||||
pipe_penalty_codec = 101;
|
||||
}
|
||||
|
||||
return pipe_penalty_codec;
|
||||
}
|
||||
|
||||
static int calculate_vpp_min_freq(struct api_calculation_input codec_input,
|
||||
struct api_calculation_freq_output *codec_output)
|
||||
{
|
||||
u32 vpp_hw_min_frequency = 0;
|
||||
u32 fmin = 0;
|
||||
u32 tensilica_min_frequency = 0;
|
||||
u32 decoder_vsp_fw_overhead = 100 + 5; /* amplified by 100x */
|
||||
/* UInt32 fw_sw_vsp_offset = 1000 + 55; amplified by 1000x */
|
||||
/* TODO from calculate_sw_vsp_min_freq */
|
||||
u32 vsp_hw_min_frequency = codec_output->vsp_min_freq;
|
||||
u32 pipe_penalty_codec = 0;
|
||||
u32 fmin_fwoverhead105 = 0;
|
||||
u32 fmin_measured_fwoverhead = 0;
|
||||
u32 lpmode_uhd_cycle_permb = 0;
|
||||
u32 hqmode1080p_cycle_permb = 0;
|
||||
u32 encoder_vpp_target_clk_per_mb = 0;
|
||||
|
||||
codec_mbspersession_kalama =
|
||||
calculate_number_mbs_kalama(codec_input.frame_width,
|
||||
codec_input.frame_height, codec_input.lcu_size) *
|
||||
codec_input.frame_rate;
|
||||
|
||||
/* Section 2. 0 VPP/VSP calculation */
|
||||
if (codec_input.decoder_or_encoder == CODEC_DECODER) { /* decoder */
|
||||
vpp_hw_min_frequency = ((decoder_vpp_target_clk_per_mb_kalama) *
|
||||
(codec_mbspersession_kalama) + codec_input.pipe_num - 1) /
|
||||
(codec_input.pipe_num);
|
||||
|
||||
vpp_hw_min_frequency = (vpp_hw_min_frequency + 99999) / 1000000;
|
||||
|
||||
if (codec_input.pipe_num > 1) {
|
||||
pipe_penalty_codec = calculate_pipe_penalty(codec_input);
|
||||
vpp_hw_min_frequency = (vpp_hw_min_frequency *
|
||||
pipe_penalty_codec + 999) / 1000;
|
||||
}
|
||||
|
||||
if (codec_input.vsp_vpp_mode == CODEC_VSPVPP_MODE_2S) {
|
||||
/* FW overhead, convert FW cycles to impact to one pipe */
|
||||
u64 decoder_vpp_fw_overhead = 0;
|
||||
|
||||
decoder_vpp_fw_overhead =
|
||||
DIV_ROUND_UP((DECODER_VPP_FW_OVERHEAD_KALAMA * 10 *
|
||||
codec_input.frame_rate), 15);
|
||||
|
||||
decoder_vpp_fw_overhead =
|
||||
DIV_ROUND_UP((decoder_vpp_fw_overhead * 1000),
|
||||
(codec_mbspersession_kalama *
|
||||
decoder_vpp_target_clk_per_mb_kalama / codec_input.pipe_num));
|
||||
|
||||
decoder_vpp_fw_overhead += 1000;
|
||||
decoder_vpp_fw_overhead = (decoder_vpp_fw_overhead < 1050) ?
|
||||
1050 : decoder_vpp_fw_overhead;
|
||||
|
||||
/* VPP HW + FW */
|
||||
if (codec_input.linear_opb == 1 &&
|
||||
codec_input.bitdepth == CODEC_BITDEPTH_10)
|
||||
/* multiply by 1.20 for 10b case */
|
||||
decoder_vpp_fw_overhead = 1200 + decoder_vpp_fw_overhead - 1000;
|
||||
|
||||
vpp_hw_min_frequency = (vpp_hw_min_frequency *
|
||||
decoder_vpp_fw_overhead + 999) / 1000;
|
||||
|
||||
/* VSP HW+FW */
|
||||
vsp_hw_min_frequency =
|
||||
(vsp_hw_min_frequency * decoder_vsp_fw_overhead + 99) / 100;
|
||||
|
||||
fmin = (vpp_hw_min_frequency > vsp_hw_min_frequency) ?
|
||||
vpp_hw_min_frequency : vsp_hw_min_frequency;
|
||||
} else {
|
||||
/* 1-stage need SW cycles + FW cycles + HW time */
|
||||
if (codec_input.linear_opb == 1 &&
|
||||
codec_input.bitdepth == CODEC_BITDEPTH_10)
|
||||
/* multiply by 1.20 for 10b linear case */
|
||||
vpp_hw_min_frequency =
|
||||
(vpp_hw_min_frequency * 1200 + 999) / 1000;
|
||||
|
||||
/*
|
||||
* HW time
|
||||
* comment: 02/23/2021 SY: the bitrate is measured bitrate,
|
||||
* the overlapping effect is already considered into bitrate.
|
||||
* no need to add extra anymore
|
||||
*/
|
||||
fmin = (vpp_hw_min_frequency > vsp_hw_min_frequency) ?
|
||||
vpp_hw_min_frequency : vsp_hw_min_frequency;
|
||||
|
||||
/* FW time */
|
||||
fmin_fwoverhead105 = (fmin * 105 + 99) / 100;
|
||||
fmin_measured_fwoverhead = fmin +
|
||||
(((DECODER_VPPVSP1STAGE_FW_OVERHEAD_KALAMA *
|
||||
codec_input.frame_rate * 10 + 14) / 15 + 999) / 1000 + 999) /
|
||||
1000;
|
||||
|
||||
fmin = (fmin_fwoverhead105 > fmin_measured_fwoverhead) ?
|
||||
fmin_fwoverhead105 : fmin_measured_fwoverhead;
|
||||
}
|
||||
|
||||
tensilica_min_frequency = (DECODER_SW_OVERHEAD_KALAMA * 10 + 14) / 15;
|
||||
tensilica_min_frequency = (tensilica_min_frequency + 999) / 1000;
|
||||
tensilica_min_frequency = tensilica_min_frequency * codec_input.frame_rate;
|
||||
tensilica_min_frequency = (tensilica_min_frequency + 999) / 1000;
|
||||
fmin = (tensilica_min_frequency > fmin) ? tensilica_min_frequency : fmin;
|
||||
} else { /* encoder */
|
||||
/* Decide LP/HQ */
|
||||
u8 hq_mode = 0;
|
||||
|
||||
if (codec_input.pipe_num > 1)
|
||||
if (codec_input.frame_width * codec_input.frame_height <=
|
||||
1920 * 1080)
|
||||
if (codec_input.frame_width * codec_input.frame_height *
|
||||
codec_input.frame_rate <= 1920 * 1080 * 60)
|
||||
hq_mode = 1;
|
||||
|
||||
codec_output->enc_hqmode = hq_mode;
|
||||
|
||||
/* Section 1. 0 */
|
||||
/* TODO ONETIME call, should be in another place. */
|
||||
initialize_encoder_complexity_table();
|
||||
|
||||
/* End Calculate Encoder GOP Complexity Table */
|
||||
|
||||
/* VPP base cycle */
|
||||
lpmode_uhd_cycle_permb = (320 *
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[codec_input.hierachical_layer][CODEC_ENCODER_GOP_FACTORY_ENTRY]
|
||||
+ 99) / 100;
|
||||
|
||||
if ((codec_input.frame_width == 1920) &&
|
||||
((codec_input.frame_height == 1080) ||
|
||||
(codec_input.frame_height == 1088)) &&
|
||||
(codec_input.frame_rate >= 480))
|
||||
lpmode_uhd_cycle_permb = (90 * 4 *
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[codec_input.hierachical_layer][CODEC_ENCODER_GOP_FACTORY_ENTRY]
|
||||
+ 99) / 100;
|
||||
|
||||
if ((codec_input.frame_width == 1280) &&
|
||||
((codec_input.frame_height == 720) ||
|
||||
(codec_input.frame_height == 768)) &&
|
||||
(codec_input.frame_rate >= 960))
|
||||
lpmode_uhd_cycle_permb = (99 * 4 *
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[codec_input.hierachical_layer][CODEC_ENCODER_GOP_FACTORY_ENTRY]
|
||||
+ 99) / 100;
|
||||
|
||||
hqmode1080p_cycle_permb = (675 *
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[codec_input.hierachical_layer][CODEC_ENCODER_GOP_FACTORY_ENTRY]
|
||||
+ 99) / 100;
|
||||
|
||||
encoder_vpp_target_clk_per_mb = (hq_mode) ?
|
||||
hqmode1080p_cycle_permb : lpmode_uhd_cycle_permb;
|
||||
|
||||
vpp_hw_min_frequency = ((encoder_vpp_target_clk_per_mb) *
|
||||
(codec_mbspersession_kalama) + codec_input.pipe_num - 1) /
|
||||
(codec_input.pipe_num);
|
||||
|
||||
vpp_hw_min_frequency = (vpp_hw_min_frequency + 99999) / 1000000;
|
||||
|
||||
if (codec_input.pipe_num > 1) {
|
||||
u32 pipe_penalty_codec = 101;
|
||||
|
||||
vpp_hw_min_frequency = (vpp_hw_min_frequency *
|
||||
pipe_penalty_codec + 99) / 100;
|
||||
}
|
||||
|
||||
if (codec_input.vsp_vpp_mode == CODEC_VSPVPP_MODE_2S) {
|
||||
/* FW overhead, convert FW cycles to impact to one pipe */
|
||||
u64 encoder_vpp_fw_overhead = 0;
|
||||
|
||||
encoder_vpp_fw_overhead =
|
||||
DIV_ROUND_UP((ENCODER_VPP_FW_OVERHEAD_KALAMA * 10 *
|
||||
codec_input.frame_rate), 15);
|
||||
|
||||
encoder_vpp_fw_overhead =
|
||||
DIV_ROUND_UP((encoder_vpp_fw_overhead * 1000),
|
||||
(codec_mbspersession_kalama * encoder_vpp_target_clk_per_mb /
|
||||
codec_input.pipe_num));
|
||||
|
||||
encoder_vpp_fw_overhead += 1000;
|
||||
|
||||
encoder_vpp_fw_overhead = (encoder_vpp_fw_overhead < 1050) ?
|
||||
1050 : encoder_vpp_fw_overhead;
|
||||
|
||||
/* VPP HW + FW */
|
||||
vpp_hw_min_frequency = (vpp_hw_min_frequency *
|
||||
encoder_vpp_fw_overhead + 999) / 1000;
|
||||
|
||||
/* TODO : decoder_vsp_fw_overhead? */
|
||||
vsp_hw_min_frequency = (vsp_hw_min_frequency *
|
||||
decoder_vsp_fw_overhead + 99) / 100;
|
||||
|
||||
fmin = (vpp_hw_min_frequency > vsp_hw_min_frequency) ?
|
||||
vpp_hw_min_frequency : vsp_hw_min_frequency;
|
||||
} else {
|
||||
/* HW time */
|
||||
fmin = (vpp_hw_min_frequency > vsp_hw_min_frequency) ?
|
||||
vpp_hw_min_frequency : vsp_hw_min_frequency;
|
||||
|
||||
/* FW time */
|
||||
fmin_fwoverhead105 = (fmin * 105 + 99) / 100;
|
||||
fmin_measured_fwoverhead = fmin +
|
||||
(((DECODER_VPPVSP1STAGE_FW_OVERHEAD_KALAMA *
|
||||
codec_input.frame_rate * 10 + 14) / 15 + 999) /
|
||||
1000 + 999) / 1000;
|
||||
|
||||
fmin = (fmin_fwoverhead105 > fmin_measured_fwoverhead) ?
|
||||
fmin_fwoverhead105 : fmin_measured_fwoverhead;
|
||||
/* SW time */
|
||||
}
|
||||
|
||||
tensilica_min_frequency = (ENCODER_SW_OVERHEAD_KALAMA * 10 + 14) / 15;
|
||||
tensilica_min_frequency = (tensilica_min_frequency + 999) / 1000;
|
||||
|
||||
tensilica_min_frequency = tensilica_min_frequency *
|
||||
codec_input.frame_rate;
|
||||
|
||||
tensilica_min_frequency = (tensilica_min_frequency + 999) / 1000;
|
||||
|
||||
fmin = (tensilica_min_frequency > fmin) ?
|
||||
tensilica_min_frequency : fmin;
|
||||
}
|
||||
|
||||
codec_output->vpp_min_freq = vpp_hw_min_frequency;
|
||||
codec_output->vsp_min_freq = vsp_hw_min_frequency;
|
||||
codec_output->tensilica_min_freq = tensilica_min_frequency;
|
||||
codec_output->hw_min_freq = fmin;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_calculate_frequency(struct api_calculation_input codec_input,
|
||||
struct api_calculation_freq_output *codec_output)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = calculate_vsp_min_freq(codec_input, codec_output);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = calculate_vpp_min_freq(codec_input, codec_output);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return rc;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __H_MSM_VIDC_BUFFER_IRIS3_3_H__
|
||||
#define __H_MSM_VIDC_BUFFER_IRIS3_3_H__
|
||||
|
||||
#include "msm_vidc_inst.h"
|
||||
|
||||
int msm_buffer_size_iris33(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
int msm_buffer_min_count_iris33(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
int msm_buffer_extra_count_iris33(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
|
||||
#endif // __H_MSM_VIDC_BUFFER_IRIS3_3_H__
|
@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_IRIS3_3_H_
|
||||
#define _MSM_VIDC_IRIS3_3_H_
|
||||
|
||||
#include "msm_vidc_core.h"
|
||||
|
||||
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
|
||||
int msm_vidc_init_iris33(struct msm_vidc_core *core);
|
||||
int msm_vidc_adjust_bitrate_boost_iris33(void *instance, struct v4l2_ctrl *ctrl);
|
||||
#else
|
||||
static inline int msm_vidc_init_iris33(struct msm_vidc_core *core)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int msm_vidc_adjust_bitrate_boost_iris33(void *instance, struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _MSM_VIDC_IRIS3_3_H_
|
@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __H_MSM_VIDC_POWER_IRIS3_3_H__
|
||||
#define __H_MSM_VIDC_POWER_IRIS3_3_H__
|
||||
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_power.h"
|
||||
|
||||
#define ENABLE_LEGACY_POWER_CALCULATIONS 0
|
||||
|
||||
int msm_vidc_ring_buf_count_iris33(struct msm_vidc_inst *inst, u32 data_size);
|
||||
u64 msm_vidc_calc_freq_iris33(struct msm_vidc_inst *inst, u32 data_size);
|
||||
int msm_vidc_calc_bw_iris33(struct msm_vidc_inst *inst,
|
||||
struct vidc_bus_vote_data *vote_data);
|
||||
|
||||
#endif
|
@ -0,0 +1,743 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "msm_vidc_buffer_iris33.h"
|
||||
#include "msm_vidc_buffer.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
#include "msm_media_info.h"
|
||||
#include "msm_vidc_platform.h"
|
||||
#include "hfi_property.h"
|
||||
#include "hfi_buffer_iris33.h"
|
||||
|
||||
static u32 msm_vidc_decoder_bin_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, num_vpp_pipes;
|
||||
struct v4l2_format *f;
|
||||
bool is_interlaced;
|
||||
u32 vpp_delay;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
if (inst->decode_vpp_delay.enable)
|
||||
vpp_delay = inst->decode_vpp_delay.size;
|
||||
else
|
||||
vpp_delay = DEFAULT_BSE_VPP_DELAY;
|
||||
if (inst->capabilities[CODED_FRAMES].value ==
|
||||
CODED_FRAMES_PROGRESSIVE)
|
||||
is_interlaced = false;
|
||||
else
|
||||
is_interlaced = true;
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_BIN_H264D(size, width, height,
|
||||
is_interlaced, vpp_delay, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_BIN_H265D(size, width, height,
|
||||
0, vpp_delay, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_VP9)
|
||||
HFI_BUFFER_BIN_VP9D(size, width, height,
|
||||
0, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_AV1)
|
||||
HFI_BUFFER_BIN_AV1D(size, width, height, is_interlaced,
|
||||
0, num_vpp_pipes);
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_comv_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height, num_comv, vpp_delay;
|
||||
struct v4l2_format *f;
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_AV1) {
|
||||
/*
|
||||
* AV1 requires larger COMV buffer size to meet performance
|
||||
* for certain use cases. Increase the COMV buffer size by
|
||||
* increasing COMV bufcount. Use lower count for 8k to
|
||||
* achieve performance but save memory.
|
||||
*/
|
||||
if (res_is_greater_than(width, height, 4096, 2176))
|
||||
num_comv = inst->fw_min_count ?
|
||||
inst->fw_min_count + 3 : inst->buffers.output.min_count + 3;
|
||||
else
|
||||
num_comv = inst->fw_min_count ?
|
||||
inst->fw_min_count + 7 : inst->buffers.output.min_count + 7;
|
||||
} else {
|
||||
num_comv = inst->buffers.output.min_count;
|
||||
}
|
||||
msm_vidc_update_cap_value(inst, NUM_COMV, num_comv, __func__);
|
||||
|
||||
if (inst->codec == MSM_VIDC_HEIC
|
||||
&& is_thumbnail_session(inst)) {
|
||||
vpp_delay = 0;
|
||||
} else {
|
||||
if (inst->decode_vpp_delay.enable)
|
||||
vpp_delay = inst->decode_vpp_delay.size;
|
||||
else
|
||||
vpp_delay = DEFAULT_BSE_VPP_DELAY;
|
||||
}
|
||||
|
||||
num_comv = max(vpp_delay + 1, num_comv);
|
||||
if (inst->codec == MSM_VIDC_H264) {
|
||||
HFI_BUFFER_COMV_H264D(size, width, height, num_comv);
|
||||
} else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC) {
|
||||
HFI_BUFFER_COMV_H265D(size, width, height, num_comv);
|
||||
} else if (inst->codec == MSM_VIDC_AV1) {
|
||||
/*
|
||||
* When DRAP is enabled, COMV buffer is part of PERSIST buffer and
|
||||
* should not be allocated separately.
|
||||
* When DRAP is disabled, COMV buffer must be allocated.
|
||||
*/
|
||||
if (inst->capabilities[DRAP].value)
|
||||
size = 0;
|
||||
else
|
||||
HFI_BUFFER_COMV_AV1D(size, width, height, num_comv);
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_non_comv_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height, num_vpp_pipes;
|
||||
struct msm_vidc_core *core;
|
||||
struct v4l2_format *f;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_NON_COMV_H264D(size, width, height, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_NON_COMV_H265D(size, width, height, num_vpp_pipes);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_line_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, out_min_count, num_vpp_pipes, vpp_delay;
|
||||
struct v4l2_format *f;
|
||||
bool is_opb;
|
||||
u32 color_fmt;
|
||||
|
||||
core = inst->core;
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
|
||||
color_fmt = v4l2_colorformat_to_driver(inst,
|
||||
inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat, __func__);
|
||||
if (is_linear_colorformat(color_fmt))
|
||||
is_opb = true;
|
||||
else
|
||||
is_opb = false;
|
||||
/*
|
||||
* assume worst case, since color format is unknown at this
|
||||
* time.
|
||||
*/
|
||||
is_opb = true;
|
||||
|
||||
if (inst->decode_vpp_delay.enable)
|
||||
vpp_delay = inst->decode_vpp_delay.size;
|
||||
else
|
||||
vpp_delay = DEFAULT_BSE_VPP_DELAY;
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
out_min_count = inst->buffers.output.min_count;
|
||||
out_min_count = max(vpp_delay + 1, out_min_count);
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_LINE_H264D(size, width, height, is_opb,
|
||||
num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_LINE_H265D(size, width, height, is_opb,
|
||||
num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_VP9)
|
||||
HFI_BUFFER_LINE_VP9D(size, width, height, out_min_count,
|
||||
is_opb, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_AV1)
|
||||
HFI_BUFFER_LINE_AV1D(size, width, height, is_opb,
|
||||
num_vpp_pipes);
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_partial_data_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height;
|
||||
struct v4l2_format *f;
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_AV1)
|
||||
HFI_BUFFER_IBC_AV1D(size, width, height);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_persist_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 rpu_enabled = 0;
|
||||
|
||||
if (inst->capabilities[META_DOLBY_RPU].value)
|
||||
rpu_enabled = 1;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264) {
|
||||
HFI_BUFFER_PERSIST_H264D(size, rpu_enabled);
|
||||
} else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC) {
|
||||
HFI_BUFFER_PERSIST_H265D(size, rpu_enabled);
|
||||
} else if (inst->codec == MSM_VIDC_VP9) {
|
||||
HFI_BUFFER_PERSIST_VP9D(size);
|
||||
} else if (inst->codec == MSM_VIDC_AV1) {
|
||||
/*
|
||||
* When DRAP is enabled, COMV buffer is part of PERSIST buffer and
|
||||
* should not be allocated separately. PERSIST buffer should include
|
||||
* COMV buffer calculated with width, height, refcount.
|
||||
* When DRAP is disabled, COMV buffer should not be included in PERSIST
|
||||
* buffer.
|
||||
*/
|
||||
if (inst->capabilities[DRAP].value)
|
||||
HFI_BUFFER_PERSIST_AV1D(size,
|
||||
inst->capabilities[FRAME_WIDTH].max,
|
||||
inst->capabilities[FRAME_HEIGHT].max, 16);
|
||||
else
|
||||
HFI_BUFFER_PERSIST_AV1D(size, 0, 0, 0);
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_decoder_dpb_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
|
||||
u32 size = 0;
|
||||
u32 color_fmt;
|
||||
u32 width, height;
|
||||
u32 interlace = 0;
|
||||
struct v4l2_format *f;
|
||||
|
||||
/*
|
||||
* For legacy codecs (non-AV1), DPB is calculated only
|
||||
* for linear formats. For AV1, DPB is needed for film-grain
|
||||
* enabled bitstreams (UBWC & linear).
|
||||
*/
|
||||
color_fmt = inst->capabilities[PIX_FMTS].value;
|
||||
if (!is_linear_colorformat(color_fmt)) {
|
||||
if (inst->codec != MSM_VIDC_AV1)
|
||||
return size;
|
||||
|
||||
if (inst->codec == MSM_VIDC_AV1 &&
|
||||
!inst->capabilities[FILM_GRAIN].value)
|
||||
return size;
|
||||
}
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264 &&
|
||||
res_is_less_than_or_equal_to(width, height, 1920, 1088))
|
||||
interlace = 1;
|
||||
|
||||
if (color_fmt == MSM_VIDC_FMT_NV12 ||
|
||||
color_fmt == MSM_VIDC_FMT_NV12C) {
|
||||
color_fmt = MSM_VIDC_FMT_NV12C;
|
||||
HFI_NV12_UBWC_IL_CALC_BUF_SIZE_V2(size, width, height,
|
||||
video_y_stride_bytes(color_fmt, width),
|
||||
video_y_scanlines(color_fmt, height),
|
||||
video_uv_stride_bytes(color_fmt, width),
|
||||
video_uv_scanlines(color_fmt, height),
|
||||
video_y_meta_stride(color_fmt, width),
|
||||
video_y_meta_scanlines(color_fmt, height),
|
||||
video_uv_meta_stride(color_fmt, width),
|
||||
video_uv_meta_scanlines(color_fmt, height),
|
||||
interlace);
|
||||
} else if (color_fmt == MSM_VIDC_FMT_P010 ||
|
||||
color_fmt == MSM_VIDC_FMT_TP10C) {
|
||||
color_fmt = MSM_VIDC_FMT_TP10C;
|
||||
HFI_YUV420_TP10_UBWC_CALC_BUF_SIZE(size,
|
||||
video_y_stride_bytes(color_fmt, width),
|
||||
video_y_scanlines(color_fmt, height),
|
||||
video_uv_stride_bytes(color_fmt, width),
|
||||
video_uv_scanlines(color_fmt, height),
|
||||
video_y_meta_stride(color_fmt, width),
|
||||
video_y_meta_scanlines(color_fmt, height),
|
||||
video_uv_meta_stride(color_fmt, width),
|
||||
video_uv_meta_scanlines(color_fmt, height));
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
/* encoder internal buffers */
|
||||
static u32 msm_vidc_encoder_bin_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, num_vpp_pipes, stage, profile, ring_buf_count;
|
||||
struct v4l2_format *f;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
stage = inst->capabilities[STAGE].value;
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
profile = inst->capabilities[PROFILE].value;
|
||||
ring_buf_count = inst->capabilities[ENC_RING_BUFFER_COUNT].value;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_BIN_H264E(size, inst->hfi_rc_type, width,
|
||||
height, stage, num_vpp_pipes, profile, ring_buf_count);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_BIN_H265E(size, inst->hfi_rc_type, width,
|
||||
height, stage, num_vpp_pipes, profile, ring_buf_count);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_get_recon_buf_count(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 num_buf_recon = 0;
|
||||
s32 n_bframe, ltr_count, hp_layers = 0, hb_layers = 0;
|
||||
bool is_hybrid_hp = false;
|
||||
u32 hfi_codec = 0;
|
||||
|
||||
n_bframe = inst->capabilities[B_FRAME].value;
|
||||
ltr_count = inst->capabilities[LTR_COUNT].value;
|
||||
|
||||
if (inst->hfi_layer_type == HFI_HIER_B) {
|
||||
hb_layers = inst->capabilities[ENH_LAYER_COUNT].value + 1;
|
||||
} else {
|
||||
hp_layers = inst->capabilities[ENH_LAYER_COUNT].value + 1;
|
||||
if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR)
|
||||
is_hybrid_hp = true;
|
||||
}
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
hfi_codec = HFI_CODEC_ENCODE_AVC;
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
hfi_codec = HFI_CODEC_ENCODE_HEVC;
|
||||
|
||||
HFI_IRIS3_ENC_RECON_BUF_COUNT(num_buf_recon, n_bframe, ltr_count,
|
||||
hp_layers, hb_layers, is_hybrid_hp, hfi_codec);
|
||||
|
||||
return num_buf_recon;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_comv_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height, num_recon = 0;
|
||||
struct v4l2_format *f;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
num_recon = msm_vidc_get_recon_buf_count(inst);
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_COMV_H264E(size, width, height, num_recon);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_COMV_H265E(size, width, height, num_recon);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_non_comv_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, num_vpp_pipes;
|
||||
struct v4l2_format *f;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_NON_COMV_H264E(size, width, height, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_NON_COMV_H265E(size, width, height, num_vpp_pipes);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_line_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
u32 size = 0;
|
||||
u32 width, height, pixfmt, num_vpp_pipes;
|
||||
bool is_tenbit = false;
|
||||
struct v4l2_format *f;
|
||||
|
||||
core = inst->core;
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
pixfmt = inst->capabilities[PIX_FMTS].value;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
is_tenbit = (pixfmt == MSM_VIDC_FMT_P010 || pixfmt == MSM_VIDC_FMT_TP10C);
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_LINE_H264E(size, width, height, is_tenbit, num_vpp_pipes);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_LINE_H265E(size, width, height, is_tenbit, num_vpp_pipes);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_dpb_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 width, height, pixfmt;
|
||||
struct v4l2_format *f;
|
||||
bool is_tenbit;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
pixfmt = inst->capabilities[PIX_FMTS].value;
|
||||
is_tenbit = (pixfmt == MSM_VIDC_FMT_P010 || pixfmt == MSM_VIDC_FMT_TP10C);
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
HFI_BUFFER_DPB_H264E(size, width, height);
|
||||
else if (inst->codec == MSM_VIDC_HEVC || inst->codec == MSM_VIDC_HEIC)
|
||||
HFI_BUFFER_DPB_H265E(size, width, height, is_tenbit);
|
||||
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_arp_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
|
||||
HFI_BUFFER_ARP_ENC(size);
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_vpss_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
bool ds_enable = false, is_tenbit = false, blur = false;
|
||||
u32 rotation_val = HFI_ROTATION_NONE;
|
||||
u32 width, height, driver_colorfmt;
|
||||
struct v4l2_format *f;
|
||||
|
||||
ds_enable = is_scaling_enabled(inst);
|
||||
msm_vidc_v4l2_to_hfi_enum(inst, ROTATION, &rotation_val);
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
if (is_rotation_90_or_270(inst)) {
|
||||
/*
|
||||
* output width and height are rotated,
|
||||
* so unrotate them to use as arguments to
|
||||
* HFI_BUFFER_VPSS_ENC.
|
||||
*/
|
||||
width = f->fmt.pix_mp.height;
|
||||
height = f->fmt.pix_mp.width;
|
||||
} else {
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
}
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
driver_colorfmt = v4l2_colorformat_to_driver(inst,
|
||||
f->fmt.pix_mp.pixelformat, __func__);
|
||||
is_tenbit = is_10bit_colorformat(driver_colorfmt);
|
||||
if (inst->capabilities[BLUR_TYPES].value != MSM_VIDC_BLUR_NONE)
|
||||
blur = true;
|
||||
|
||||
HFI_BUFFER_VPSS_ENC(size, width, height, ds_enable, blur, is_tenbit);
|
||||
i_vpr_l(inst, "%s: size %d\n", __func__, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_encoder_output_size_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 frame_size;
|
||||
struct v4l2_format *f;
|
||||
bool is_ten_bit = false;
|
||||
int bitrate_mode, frame_rc;
|
||||
u32 hfi_rc_type = HFI_RC_VBR_CFR;
|
||||
enum msm_vidc_codec_type codec;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
codec = v4l2_codec_to_driver(inst, f->fmt.pix_mp.pixelformat, __func__);
|
||||
if (codec == MSM_VIDC_HEVC || codec == MSM_VIDC_HEIC)
|
||||
is_ten_bit = true;
|
||||
|
||||
bitrate_mode = inst->capabilities[BITRATE_MODE].value;
|
||||
frame_rc = inst->capabilities[FRAME_RC_ENABLE].value;
|
||||
if (!frame_rc && !is_image_session(inst))
|
||||
hfi_rc_type = HFI_RC_OFF;
|
||||
else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
|
||||
hfi_rc_type = HFI_RC_CQ;
|
||||
|
||||
HFI_BUFFER_BITSTREAM_ENC(frame_size, f->fmt.pix_mp.width,
|
||||
f->fmt.pix_mp.height, hfi_rc_type, is_ten_bit);
|
||||
|
||||
frame_size = msm_vidc_enc_delivery_mode_based_output_buf_size(inst, frame_size);
|
||||
|
||||
return frame_size;
|
||||
}
|
||||
|
||||
struct msm_vidc_buf_type_handle {
|
||||
enum msm_vidc_buffer_type type;
|
||||
u32 (*handle)(struct msm_vidc_inst *inst);
|
||||
};
|
||||
|
||||
int msm_buffer_size_iris33(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
int i;
|
||||
u32 size = 0, buf_type_handle_size = 0;
|
||||
const struct msm_vidc_buf_type_handle *buf_type_handle_arr = NULL;
|
||||
static const struct msm_vidc_buf_type_handle dec_buf_type_handle[] = {
|
||||
{MSM_VIDC_BUF_INPUT, msm_vidc_decoder_input_size },
|
||||
{MSM_VIDC_BUF_OUTPUT, msm_vidc_decoder_output_size },
|
||||
{MSM_VIDC_BUF_INPUT_META, msm_vidc_decoder_input_meta_size },
|
||||
{MSM_VIDC_BUF_OUTPUT_META, msm_vidc_decoder_output_meta_size },
|
||||
{MSM_VIDC_BUF_BIN, msm_vidc_decoder_bin_size_iris33 },
|
||||
{MSM_VIDC_BUF_COMV, msm_vidc_decoder_comv_size_iris33 },
|
||||
{MSM_VIDC_BUF_NON_COMV, msm_vidc_decoder_non_comv_size_iris33 },
|
||||
{MSM_VIDC_BUF_LINE, msm_vidc_decoder_line_size_iris33 },
|
||||
{MSM_VIDC_BUF_PERSIST, msm_vidc_decoder_persist_size_iris33 },
|
||||
{MSM_VIDC_BUF_DPB, msm_vidc_decoder_dpb_size_iris33 },
|
||||
{MSM_VIDC_BUF_PARTIAL_DATA, msm_vidc_decoder_partial_data_size_iris33 },
|
||||
};
|
||||
static const struct msm_vidc_buf_type_handle enc_buf_type_handle[] = {
|
||||
{MSM_VIDC_BUF_INPUT, msm_vidc_encoder_input_size },
|
||||
{MSM_VIDC_BUF_OUTPUT, msm_vidc_encoder_output_size_iris33 },
|
||||
{MSM_VIDC_BUF_INPUT_META, msm_vidc_encoder_input_meta_size },
|
||||
{MSM_VIDC_BUF_OUTPUT_META, msm_vidc_encoder_output_meta_size },
|
||||
{MSM_VIDC_BUF_BIN, msm_vidc_encoder_bin_size_iris33 },
|
||||
{MSM_VIDC_BUF_COMV, msm_vidc_encoder_comv_size_iris33 },
|
||||
{MSM_VIDC_BUF_NON_COMV, msm_vidc_encoder_non_comv_size_iris33 },
|
||||
{MSM_VIDC_BUF_LINE, msm_vidc_encoder_line_size_iris33 },
|
||||
{MSM_VIDC_BUF_DPB, msm_vidc_encoder_dpb_size_iris33 },
|
||||
{MSM_VIDC_BUF_ARP, msm_vidc_encoder_arp_size_iris33 },
|
||||
{MSM_VIDC_BUF_VPSS, msm_vidc_encoder_vpss_size_iris33 },
|
||||
};
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
buf_type_handle_size = ARRAY_SIZE(dec_buf_type_handle);
|
||||
buf_type_handle_arr = dec_buf_type_handle;
|
||||
} else if (is_encode_session(inst)) {
|
||||
buf_type_handle_size = ARRAY_SIZE(enc_buf_type_handle);
|
||||
buf_type_handle_arr = enc_buf_type_handle;
|
||||
}
|
||||
|
||||
/* handle invalid session */
|
||||
if (!buf_type_handle_arr || !buf_type_handle_size) {
|
||||
i_vpr_e(inst, "%s: invalid session %d\n", __func__, inst->domain);
|
||||
return size;
|
||||
}
|
||||
|
||||
/* fetch buffer size */
|
||||
for (i = 0; i < buf_type_handle_size; i++) {
|
||||
if (buf_type_handle_arr[i].type == buffer_type) {
|
||||
size = buf_type_handle_arr[i].handle(inst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle unknown buffer type */
|
||||
if (i == buf_type_handle_size) {
|
||||
i_vpr_e(inst, "%s: unknown buffer type %#x\n", __func__, buffer_type);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "buffer_size: type: %11s, size: %9u\n", buf_name(buffer_type), size);
|
||||
|
||||
exit:
|
||||
return size;
|
||||
}
|
||||
|
||||
static int msm_vidc_input_min_count_iris33(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 input_min_count = 0;
|
||||
u32 total_hb_layer = 0;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
input_min_count = MIN_DEC_INPUT_BUFFERS;
|
||||
} else if (is_encode_session(inst)) {
|
||||
total_hb_layer = is_hierb_type_requested(inst) ?
|
||||
inst->capabilities[ENH_LAYER_COUNT].value + 1 : 0;
|
||||
if (inst->codec == MSM_VIDC_H264 &&
|
||||
!inst->capabilities[LAYER_ENABLE].value) {
|
||||
total_hb_layer = 0;
|
||||
}
|
||||
HFI_IRIS3_ENC_MIN_INPUT_BUF_COUNT(input_min_count,
|
||||
total_hb_layer);
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: invalid domain %d\n", __func__, inst->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_thumbnail_session(inst) || is_image_session(inst))
|
||||
input_min_count = 1;
|
||||
|
||||
return input_min_count;
|
||||
}
|
||||
|
||||
static int msm_buffer_dpb_count(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
/* encoder dpb buffer count */
|
||||
if (is_encode_session(inst))
|
||||
return msm_vidc_get_recon_buf_count(inst);
|
||||
|
||||
/* decoder dpb buffer count */
|
||||
if (is_split_mode_enabled(inst)) {
|
||||
count = inst->fw_min_count ?
|
||||
inst->fw_min_count : inst->buffers.output.min_count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int msm_buffer_delivery_mode_based_min_count_iris33(struct msm_vidc_inst *inst,
|
||||
uint32_t count)
|
||||
{
|
||||
struct v4l2_format *f;
|
||||
struct msm_vidc_core *core = NULL;
|
||||
u32 width, height, total_num_slices = 1;
|
||||
u32 hfi_codec = 0;
|
||||
u32 max_mbs_per_slice = 0;
|
||||
u32 slice_mode = 0;
|
||||
u32 delivery_mode = 0;
|
||||
u32 num_vpp_pipes;
|
||||
|
||||
slice_mode = inst->capabilities[SLICE_MODE].value;
|
||||
delivery_mode = inst->capabilities[DELIVERY_MODE].value;
|
||||
|
||||
if (slice_mode != V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB ||
|
||||
(!delivery_mode))
|
||||
return count;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
|
||||
max_mbs_per_slice = inst->capabilities[SLICE_MAX_MB].value;
|
||||
|
||||
if (inst->codec == MSM_VIDC_H264)
|
||||
hfi_codec = HFI_CODEC_ENCODE_AVC;
|
||||
else if (inst->codec == MSM_VIDC_HEVC)
|
||||
hfi_codec = HFI_CODEC_ENCODE_HEVC;
|
||||
|
||||
core = inst->core;
|
||||
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
|
||||
HFI_IRIS3_ENC_MB_BASED_MULTI_SLICE_COUNT(total_num_slices, width, height,
|
||||
hfi_codec, max_mbs_per_slice, num_vpp_pipes);
|
||||
|
||||
return (total_num_slices * count);
|
||||
}
|
||||
|
||||
int msm_buffer_min_count_iris33(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
switch (buffer_type) {
|
||||
case MSM_VIDC_BUF_INPUT:
|
||||
case MSM_VIDC_BUF_INPUT_META:
|
||||
count = msm_vidc_input_min_count_iris33(inst);
|
||||
break;
|
||||
case MSM_VIDC_BUF_OUTPUT:
|
||||
case MSM_VIDC_BUF_OUTPUT_META:
|
||||
count = msm_vidc_output_min_count(inst);
|
||||
count = msm_buffer_delivery_mode_based_min_count_iris33(inst, count);
|
||||
break;
|
||||
case MSM_VIDC_BUF_BIN:
|
||||
case MSM_VIDC_BUF_COMV:
|
||||
case MSM_VIDC_BUF_NON_COMV:
|
||||
case MSM_VIDC_BUF_LINE:
|
||||
case MSM_VIDC_BUF_PERSIST:
|
||||
case MSM_VIDC_BUF_ARP:
|
||||
case MSM_VIDC_BUF_VPSS:
|
||||
case MSM_VIDC_BUF_PARTIAL_DATA:
|
||||
count = msm_vidc_internal_buffer_count(inst, buffer_type);
|
||||
break;
|
||||
case MSM_VIDC_BUF_DPB:
|
||||
count = msm_buffer_dpb_count(inst);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
i_vpr_l(inst, " min_count: type: %11s, count: %9u\n", buf_name(buffer_type), count);
|
||||
return count;
|
||||
}
|
||||
|
||||
int msm_buffer_extra_count_iris33(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
switch (buffer_type) {
|
||||
case MSM_VIDC_BUF_INPUT:
|
||||
case MSM_VIDC_BUF_INPUT_META:
|
||||
count = msm_vidc_input_extra_count(inst);
|
||||
break;
|
||||
case MSM_VIDC_BUF_OUTPUT:
|
||||
case MSM_VIDC_BUF_OUTPUT_META:
|
||||
count = msm_vidc_output_extra_count(inst);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "extra_count: type: %11s, count: %9u\n", buf_name(buffer_type), count);
|
||||
return count;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,726 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "perf_static_model.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
#include "msm_vidc_platform.h"
|
||||
|
||||
#define ENABLE_FINEBITRATE_SUBUHD60 0
|
||||
|
||||
static u32 codec_encoder_gop_complexity_table_fp[8][3];
|
||||
static u32 codec_mbspersession_iris33;
|
||||
static u32 input_bitrate_fp;
|
||||
|
||||
/*
|
||||
* Chipset Generation Technology: SW/FW overhead profiling
|
||||
* need update with new numbers
|
||||
*/
|
||||
static u32 frequency_table_iris33[2][6] = {
|
||||
/* //make lowsvs_D1 as invalid; */
|
||||
{533, 480, 435, 380, 300, 196},
|
||||
{840, 720, 652, 570, 450, 294},
|
||||
};
|
||||
|
||||
static u32 frequency_table_iris33_2p[2][6] = {
|
||||
/* //make lowsvs_D1 as invalid; */
|
||||
{ 533, 444, 366, 338, 240, 192 },
|
||||
{ 800, 666, 549, 507, 360, 288 },
|
||||
};
|
||||
|
||||
/*
|
||||
* TODO Move to pineapple.c
|
||||
* TODO Replace hardcoded values with
|
||||
* ENCODER_VPP_TARGET_CLK_PER_MB_IRIS33 in CPP file.
|
||||
*/
|
||||
|
||||
/* Tensilica cycles profiled by FW team in lanai device Feb 2022 */
|
||||
#define DECODER_VPP_FW_OVERHEAD_IRIS33_AV1D ((80000*3)/2)
|
||||
#define DECODER_VPP_FW_OVERHEAD_IRIS33_NONAV1D ((60000*3)/2)
|
||||
|
||||
/* Tensilica cycles */
|
||||
#define DECODER_VPP_FW_OVERHEAD_IRIS33 (0)
|
||||
|
||||
/* Tensilica cycles; this is measured in Lahaina 1stage with FW profiling */
|
||||
#define DECODER_VPPVSP1STAGE_FW_OVERHEAD_IRIS33 (93000)
|
||||
|
||||
#define DECODER_VSP_FW_OVERHEAD_IRIS33 \
|
||||
(DECODER_VPPVSP1STAGE_FW_OVERHEAD_IRIS33 - DECODER_VPP_FW_OVERHEAD_IRIS33)
|
||||
|
||||
/* Tensilica cycles; encoder has ARP register */
|
||||
#define ENCODER_VPP_FW_OVERHEAD_IRIS33 (69000*3/2)
|
||||
|
||||
#define ENCODER_VPPVSP1STAGE_FW_OVERHEAD_IRIS33 \
|
||||
(ENCODER_VPP_FW_OVERHEAD_IRIS33 + DECODER_VSP_FW_OVERHEAD_IRIS33)
|
||||
|
||||
#define DECODER_SW_OVERHEAD_IRIS33 (489583)
|
||||
#define ENCODER_SW_OVERHEAD_IRIS33 (489583)
|
||||
|
||||
/* Video IP Core Technology: pipefloor and pipe penlaty */
|
||||
// static u32 encoder_vpp_target_clk_per_mb_iris33[2] = {320, 675};
|
||||
static u32 decoder_vpp_target_clk_per_mb_iris33 = 200;
|
||||
|
||||
/*
|
||||
* These pipe penalty numbers only applies to 4 pipe
|
||||
* For 2pipe and 1pipe, these numbers need recalibrate
|
||||
*/
|
||||
static u32 pipe_penalty_iris33[3][3] = {
|
||||
/* NON AV1 */
|
||||
{1059, 1059, 1059},
|
||||
/* AV1 RECOMMENDED TILE 1080P_V2XH1, UHD_V2X2, 8KUHD_V8X2 */
|
||||
{1410, 1248, 1226},
|
||||
/* AV1 YOUTUBE/NETFLIX TILE 1080P_V4XH2_V4X1, UHD_V8X4_V8X1, 8KUHD_V8X8_V8X1 */
|
||||
{2039, 2464, 1191},
|
||||
};
|
||||
|
||||
static u32 pipe_penalty_iris33_2p[3][3] = {
|
||||
/* NON AV1 */
|
||||
{ 1059, 1059, 1059 },
|
||||
/* AV1 RECOMMENDED TILE 1080P_V2XH1, UHD_V2X2, 8KUHD_V8X2 */
|
||||
{ 1123, 1079, 1079 },
|
||||
/* AV1 YOUTUBE/NETFLIX TILE 1080P_V4XH2_V4X1, UHD_V8X4_V8X1, 8KUHD_V8X8_V8X1 */
|
||||
{ 1197, 1287, 1051 },
|
||||
};
|
||||
|
||||
/*
|
||||
* Video IP Core Technology: bitrate constraint
|
||||
* HW limit bitrate table (these values are measured end to end fw/sw impacts are also considered)
|
||||
* TODO Can we convert to Cycles/MB? This will remove DIVISION.
|
||||
*/
|
||||
static u32 bitrate_table_iris33_2stage_fp[5][10] = {
|
||||
/* h264 cavlc */
|
||||
{0, 220, 220, 220, 220, 220, 220, 220, 220, 220},
|
||||
/* h264 cabac */
|
||||
{0, 140, 150, 160, 175, 190, 190, 190, 190, 190},
|
||||
/* h265 */
|
||||
{90, 140, 160, 180, 190, 200, 200, 200, 200, 200},
|
||||
/* vp9 */
|
||||
{90, 90, 90, 90, 90, 90, 90, 90, 90, 90},
|
||||
/* av1 */
|
||||
{130, 130, 120, 120, 120, 120, 120, 120, 120, 120},
|
||||
};
|
||||
|
||||
static u32 bitrate_table_iris33_2p_2stage_fp[5][10] = {
|
||||
/* h264 cavlc */
|
||||
{ 0, 220, 220, 220, 220, 220, 220, 220, 220, 220 },
|
||||
/* h264 cabac */
|
||||
{ 0, 140, 150, 160, 160, 160, 160, 160, 160, 160 },
|
||||
/* h265 */
|
||||
{ 90, 140, 160, 160, 160, 160, 160, 160, 160, 160 },
|
||||
/*vp9 */
|
||||
{ 90, 90, 90, 90, 90, 90, 90, 90, 90, 90 },
|
||||
{ 130, 130, 120, 120, 120, 120, 120, 120, 120, 120 },
|
||||
};
|
||||
|
||||
/*
|
||||
* HW limit bitrate table (these values are measured
|
||||
* end to end fw/sw impacts are also considered)
|
||||
*/
|
||||
static u32 bitrate_table_iris33_1stage_fp[5][10] = { /* 1-stage assume IPPP */
|
||||
/* h264 cavlc */
|
||||
{0, 220, 220, 220, 220, 220, 220, 220, 220, 220},
|
||||
/* h264 cabac */
|
||||
{0, 110, 150, 150, 150, 150, 150, 150, 150, 150},
|
||||
/* h265 */
|
||||
{0, 140, 150, 150, 150, 150, 150, 150, 150, 150},
|
||||
/* vp9 */
|
||||
{0, 70, 70, 70, 70, 70, 70, 70, 70, 70},
|
||||
/* av1 */
|
||||
{0, 100, 100, 100, 100, 100, 100, 100, 100, 100},
|
||||
};
|
||||
|
||||
/* 8KUHD60; UHD240; 1080p960 with B */
|
||||
static u32 fp_pixel_count_bar0 = 3840 * 2160 * 240;
|
||||
/* 8KUHD60; UHD240; 1080p960 without B */
|
||||
static u32 fp_pixel_count_bar1 = 3840 * 2160 * 240;
|
||||
/* 1080p720 */
|
||||
static u32 fp_pixel_count_bar2 = 3840 * 2160 * 180;
|
||||
/* UHD120 */
|
||||
static u32 fp_pixel_count_bar3 = 3840 * 2160 * 120;
|
||||
/* UHD90 */
|
||||
static u32 fp_pixel_count_bar4 = 3840 * 2160 * 90;
|
||||
/* UHD60 */
|
||||
static u32 fp_pixel_count_bar5 = 3840 * 2160 * 60;
|
||||
/* UHD30; FHD120; HD240 */
|
||||
static u32 fp_pixel_count_bar6 = 3840 * 2160 * 30;
|
||||
/* FHD60 */
|
||||
static u32 fp_pixel_count_bar7 = 1920 * 1080 * 60;
|
||||
/* FHD30 */
|
||||
static u32 fp_pixel_count_bar8 = 1920 * 1080 * 30;
|
||||
/* HD30 */
|
||||
static u32 fp_pixel_count_bar9 = 1280 * 720 * 30;
|
||||
|
||||
static u32 calculate_number_mbs_iris33(u32 width, u32 height, u32 lcu_size)
|
||||
{
|
||||
u32 mbs_width = (width % lcu_size) ?
|
||||
(width / lcu_size + 1) : (width / lcu_size);
|
||||
|
||||
u32 mbs_height = (height % lcu_size) ?
|
||||
(height / lcu_size + 1) : (height / lcu_size);
|
||||
|
||||
return mbs_width * mbs_height * (lcu_size / 16) * (lcu_size / 16);
|
||||
}
|
||||
|
||||
static int initialize_encoder_complexity_table(void)
|
||||
{
|
||||
/* Beging Calculate Encoder GOP Complexity Table and HW Floor numbers */
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_Bb_ENTRY] = 70000;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_P_ENTRY] = 10000;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_Bb_ENTRY] * 150 +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_P_ENTRY] * 100);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] +
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_P_ENTRY] - 1);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] /
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I3B4b1P][CODEC_ENCODER_GOP_P_ENTRY]);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_Bb_ENTRY] = 30000;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_P_ENTRY] = 10000;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_Bb_ENTRY] * 150 +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_P_ENTRY] * 100);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] +
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_P_ENTRY] - 1);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_FACTORY_ENTRY] /
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_I1B2b1P][CODEC_ENCODER_GOP_P_ENTRY]);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_Bb_ENTRY] = 10000;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_P_ENTRY] = 10000;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_Bb_ENTRY] * 150 +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_P_ENTRY] * 100);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_FACTORY_ENTRY] +
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_P_ENTRY] - 1);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_FACTORY_ENTRY] /
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IbP][CODEC_ENCODER_GOP_P_ENTRY]);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_Bb_ENTRY] = 0;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_P_ENTRY] = 1;
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_Bb_ENTRY] * 150 +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_P_ENTRY] * 100);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_FACTORY_ENTRY] +
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_P_ENTRY] - 1);
|
||||
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_FACTORY_ENTRY] =
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_FACTORY_ENTRY] /
|
||||
(codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_Bb_ENTRY] +
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[CODEC_GOP_IPP][CODEC_ENCODER_GOP_P_ENTRY]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 get_bitrate_entry(u32 pixle_count)
|
||||
{
|
||||
u32 bitrate_entry = 0;
|
||||
|
||||
if (pixle_count >= fp_pixel_count_bar1)
|
||||
bitrate_entry = 1;
|
||||
else if (pixle_count >= fp_pixel_count_bar2)
|
||||
bitrate_entry = 2;
|
||||
else if (pixle_count >= fp_pixel_count_bar3)
|
||||
bitrate_entry = 3;
|
||||
else if (pixle_count >= fp_pixel_count_bar4)
|
||||
bitrate_entry = 4;
|
||||
else if (pixle_count >= fp_pixel_count_bar5)
|
||||
bitrate_entry = 5;
|
||||
else if (pixle_count >= fp_pixel_count_bar6)
|
||||
bitrate_entry = 6;
|
||||
else if (pixle_count >= fp_pixel_count_bar7)
|
||||
bitrate_entry = 7;
|
||||
else if (pixle_count >= fp_pixel_count_bar8)
|
||||
bitrate_entry = 8;
|
||||
else if (pixle_count >= fp_pixel_count_bar9)
|
||||
bitrate_entry = 9;
|
||||
else
|
||||
bitrate_entry = 9;
|
||||
|
||||
return bitrate_entry;
|
||||
}
|
||||
|
||||
static int calculate_vsp_min_freq(struct api_calculation_input codec_input,
|
||||
struct api_calculation_freq_output *codec_output)
|
||||
{
|
||||
u32 (*frequency_table_value)[6];
|
||||
u32 (*bitrate_table_2stage_value)[10];
|
||||
/*
|
||||
* VSP calculation
|
||||
* different methodology from Lahaina
|
||||
*/
|
||||
u32 vsp_hw_min_frequency = 0;
|
||||
/* UInt32 decoder_vsp_fw_overhead = 100 + 5; // amplified by 100x */
|
||||
u32 fw_sw_vsp_offset = 1000 + 55; /* amplified by 1000x */
|
||||
|
||||
/*
|
||||
* Ignore fw_sw_vsp_offset, as this is baked into the reference bitrate tables.
|
||||
* As a consequence remove x1000 multipler as well.
|
||||
*/
|
||||
u32 codec = codec_input.codec;
|
||||
/* UInt32 *bitratetable; */
|
||||
u32 pixle_count = codec_input.frame_width *
|
||||
codec_input.frame_height * codec_input.frame_rate;
|
||||
|
||||
u8 bitrate_entry = get_bitrate_entry(pixle_count); /* TODO EXTRACT */
|
||||
|
||||
input_bitrate_fp = ((u32)(codec_input.bitrate_mbps * 100 + 99)) / 100;
|
||||
|
||||
if (codec_input.vpu_ver == VPU_VERSION_IRIS33) {
|
||||
frequency_table_value = frequency_table_iris33;
|
||||
bitrate_table_2stage_value = bitrate_table_iris33_2stage_fp;
|
||||
} else if (codec_input.vpu_ver == VPU_VERSION_IRIS33_2P) {
|
||||
frequency_table_value = frequency_table_iris33_2p;
|
||||
bitrate_table_2stage_value = bitrate_table_iris33_2p_2stage_fp;
|
||||
}
|
||||
|
||||
/* 8KUHD60fps with B frame */
|
||||
if ((pixle_count >= fp_pixel_count_bar0) &&
|
||||
(codec_input.hierachical_layer != CODEC_GOP_IPP)) {
|
||||
/*
|
||||
* FORMULA: VSPfreq = NOMINAL * (InputBitrate / ReferenceBitrate);
|
||||
* ReferenceBitrate = 0 for,
|
||||
* - 1Stage TURBO, all Codecs.
|
||||
* - 2Stage TURBO, H264 & H265.
|
||||
*
|
||||
* 8KUHD60fps with B frame
|
||||
* - bitrate_entry = 0
|
||||
* - Clock=NOMINAL for H264 & 2Stage H265. Because bitrate
|
||||
* table entry for TURBO is 0.
|
||||
*
|
||||
* TODO : Reduce these conditions by removing the zero entries from Bitrate table.
|
||||
*/
|
||||
|
||||
vsp_hw_min_frequency = frequency_table_value[0][2] *
|
||||
input_bitrate_fp * 1000;
|
||||
|
||||
if (codec_input.codec == CODEC_AV1)
|
||||
vsp_hw_min_frequency = frequency_table_value[0][1] *
|
||||
input_bitrate_fp * 1000;
|
||||
|
||||
if ((codec_input.codec == CODEC_H264) ||
|
||||
(codec_input.codec == CODEC_H264_CAVLC)) {
|
||||
vsp_hw_min_frequency = (frequency_table_value[0][2] * 1000 +
|
||||
(fw_sw_vsp_offset - 1));
|
||||
vsp_hw_min_frequency =
|
||||
DIV_ROUND_UP(vsp_hw_min_frequency, fw_sw_vsp_offset);
|
||||
} else {
|
||||
if (codec_input.vsp_vpp_mode == CODEC_VSPVPP_MODE_2S) {
|
||||
vsp_hw_min_frequency = vsp_hw_min_frequency +
|
||||
(bitrate_table_2stage_value[codec][0] *
|
||||
fw_sw_vsp_offset - 1);
|
||||
vsp_hw_min_frequency = DIV_ROUND_UP(vsp_hw_min_frequency,
|
||||
(bitrate_table_2stage_value[codec][0]) *
|
||||
fw_sw_vsp_offset);
|
||||
} else {
|
||||
vsp_hw_min_frequency = vsp_hw_min_frequency +
|
||||
(bitrate_table_iris33_1stage_fp[codec][0] *
|
||||
fw_sw_vsp_offset - 1);
|
||||
vsp_hw_min_frequency = DIV_ROUND_UP(vsp_hw_min_frequency,
|
||||
(bitrate_table_iris33_1stage_fp[codec][0]) *
|
||||
fw_sw_vsp_offset);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vsp_hw_min_frequency = frequency_table_value[0][2] *
|
||||
input_bitrate_fp * 1000;
|
||||
|
||||
if (codec_input.codec == CODEC_AV1 && bitrate_entry == 1)
|
||||
vsp_hw_min_frequency = frequency_table_value[0][1] *
|
||||
input_bitrate_fp * 1000;
|
||||
|
||||
if (codec_input.vsp_vpp_mode == CODEC_VSPVPP_MODE_2S) {
|
||||
vsp_hw_min_frequency = vsp_hw_min_frequency +
|
||||
(bitrate_table_2stage_value[codec][bitrate_entry] *
|
||||
fw_sw_vsp_offset - 1);
|
||||
vsp_hw_min_frequency = DIV_ROUND_UP(vsp_hw_min_frequency,
|
||||
(bitrate_table_2stage_value[codec][bitrate_entry]) *
|
||||
fw_sw_vsp_offset);
|
||||
} else {
|
||||
vsp_hw_min_frequency = vsp_hw_min_frequency +
|
||||
(bitrate_table_iris33_1stage_fp[codec][bitrate_entry] *
|
||||
fw_sw_vsp_offset - 1);
|
||||
vsp_hw_min_frequency = DIV_ROUND_UP(vsp_hw_min_frequency,
|
||||
(bitrate_table_iris33_1stage_fp[codec][bitrate_entry]) *
|
||||
fw_sw_vsp_offset);
|
||||
}
|
||||
}
|
||||
|
||||
codec_output->vsp_min_freq = vsp_hw_min_frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 calculate_pipe_penalty(struct api_calculation_input codec_input)
|
||||
{
|
||||
u32 pipe_penalty_codec = 0;
|
||||
u8 avid_commercial_content = 0;
|
||||
u32 pixel_count = 0;
|
||||
u32 (*pipe_penalty_value)[3];
|
||||
|
||||
if (codec_input.vpu_ver == VPU_VERSION_IRIS33)
|
||||
pipe_penalty_value = pipe_penalty_iris33;
|
||||
else if (codec_input.vpu_ver == VPU_VERSION_IRIS33_2P)
|
||||
pipe_penalty_value = pipe_penalty_iris33_2p;
|
||||
|
||||
/* decoder */
|
||||
if (codec_input.decoder_or_encoder == CODEC_DECODER) {
|
||||
pipe_penalty_codec = pipe_penalty_value[0][0];
|
||||
avid_commercial_content = codec_input.av1d_commer_tile_enable;
|
||||
if (codec_input.codec == CODEC_AV1) {
|
||||
pixel_count = codec_input.frame_width * codec_input.frame_height;
|
||||
if (pixel_count <= 1920 * 1080)
|
||||
pipe_penalty_codec =
|
||||
pipe_penalty_value[avid_commercial_content + 1][0];
|
||||
else if (pixel_count < 3840 * 2160)
|
||||
pipe_penalty_codec =
|
||||
(pipe_penalty_value[avid_commercial_content + 1][0] +
|
||||
pipe_penalty_value[avid_commercial_content + 1][1]) / 2;
|
||||
else if ((pixel_count == 3840 * 2160) ||
|
||||
(pixel_count == 4096 * 2160) || (pixel_count == 4096 * 2304))
|
||||
pipe_penalty_codec =
|
||||
pipe_penalty_value[avid_commercial_content + 1][1];
|
||||
else if (pixel_count < 7680 * 4320)
|
||||
pipe_penalty_codec =
|
||||
(pipe_penalty_value[avid_commercial_content + 1][1] +
|
||||
pipe_penalty_value[avid_commercial_content + 1][2]) / 2;
|
||||
else
|
||||
pipe_penalty_codec =
|
||||
pipe_penalty_value[avid_commercial_content + 1][2];
|
||||
}
|
||||
} else {
|
||||
pipe_penalty_codec = 101;
|
||||
}
|
||||
|
||||
return pipe_penalty_codec;
|
||||
}
|
||||
|
||||
static int calculate_vpp_min_freq(struct api_calculation_input codec_input,
|
||||
struct api_calculation_freq_output *codec_output)
|
||||
{
|
||||
u32 vpp_hw_min_frequency = 0;
|
||||
u32 fmin = 0;
|
||||
u32 tensilica_min_frequency = 0;
|
||||
u32 decoder_vsp_fw_overhead = 100 + 5; /* amplified by 100x */
|
||||
/* UInt32 fw_sw_vsp_offset = 1000 + 55; amplified by 1000x */
|
||||
/* TODO from calculate_sw_vsp_min_freq */
|
||||
u32 vsp_hw_min_frequency = codec_output->vsp_min_freq;
|
||||
u32 pipe_penalty_codec = 0;
|
||||
u32 fmin_fwoverhead105 = 0;
|
||||
u32 fmin_measured_fwoverhead = 0;
|
||||
u32 lpmode_uhd_cycle_permb = 0;
|
||||
u32 hqmode1080p_cycle_permb = 0;
|
||||
u32 encoder_vpp_target_clk_per_mb = 0;
|
||||
u32 decoder_vpp_fw_overhead = DECODER_VPP_FW_OVERHEAD_IRIS33;
|
||||
|
||||
codec_mbspersession_iris33 =
|
||||
calculate_number_mbs_iris33(codec_input.frame_width,
|
||||
codec_input.frame_height, codec_input.lcu_size) *
|
||||
codec_input.frame_rate;
|
||||
|
||||
/* Section 2. 0 VPP/VSP calculation */
|
||||
if (codec_input.decoder_or_encoder == CODEC_DECODER) { /* decoder */
|
||||
vpp_hw_min_frequency = ((decoder_vpp_target_clk_per_mb_iris33) *
|
||||
(codec_mbspersession_iris33) + codec_input.pipe_num - 1) /
|
||||
(codec_input.pipe_num);
|
||||
|
||||
vpp_hw_min_frequency = (vpp_hw_min_frequency + 99999) / 1000000;
|
||||
|
||||
if (codec_input.pipe_num > 1) {
|
||||
pipe_penalty_codec = calculate_pipe_penalty(codec_input);
|
||||
vpp_hw_min_frequency = (vpp_hw_min_frequency *
|
||||
pipe_penalty_codec + 999) / 1000;
|
||||
}
|
||||
|
||||
if (codec_input.codec == CODEC_AV1)
|
||||
decoder_vpp_fw_overhead = DECODER_VPP_FW_OVERHEAD_IRIS33_AV1D;
|
||||
else
|
||||
decoder_vpp_fw_overhead = DECODER_VPP_FW_OVERHEAD_IRIS33_NONAV1D;
|
||||
|
||||
if (codec_input.vsp_vpp_mode == CODEC_VSPVPP_MODE_2S) {
|
||||
/* FW overhead, convert FW cycles to impact to one pipe */
|
||||
|
||||
decoder_vpp_fw_overhead =
|
||||
DIV_ROUND_UP((decoder_vpp_fw_overhead * 10 *
|
||||
codec_input.frame_rate), 15);
|
||||
|
||||
decoder_vpp_fw_overhead =
|
||||
DIV_ROUND_UP((decoder_vpp_fw_overhead * 1000),
|
||||
(codec_mbspersession_iris33 *
|
||||
decoder_vpp_target_clk_per_mb_iris33 / codec_input.pipe_num));
|
||||
|
||||
decoder_vpp_fw_overhead += 1000;
|
||||
decoder_vpp_fw_overhead = (decoder_vpp_fw_overhead < 1050) ?
|
||||
1050 : decoder_vpp_fw_overhead;
|
||||
|
||||
/* VPP HW + FW */
|
||||
if (codec_input.linear_opb == 1 &&
|
||||
codec_input.bitdepth == CODEC_BITDEPTH_10)
|
||||
/* multiply by 1.20 for 10b case */
|
||||
decoder_vpp_fw_overhead = 1200 + decoder_vpp_fw_overhead - 1000;
|
||||
|
||||
vpp_hw_min_frequency = (vpp_hw_min_frequency *
|
||||
decoder_vpp_fw_overhead + 999) / 1000;
|
||||
|
||||
/* VSP HW+FW */
|
||||
vsp_hw_min_frequency =
|
||||
(vsp_hw_min_frequency * decoder_vsp_fw_overhead + 99) / 100;
|
||||
|
||||
fmin = (vpp_hw_min_frequency > vsp_hw_min_frequency) ?
|
||||
vpp_hw_min_frequency : vsp_hw_min_frequency;
|
||||
} else {
|
||||
/* 1-stage need SW cycles + FW cycles + HW time */
|
||||
if (codec_input.linear_opb == 1 &&
|
||||
codec_input.bitdepth == CODEC_BITDEPTH_10)
|
||||
/* multiply by 1.20 for 10b linear case */
|
||||
vpp_hw_min_frequency =
|
||||
(vpp_hw_min_frequency * 1200 + 999) / 1000;
|
||||
|
||||
/*
|
||||
* HW time
|
||||
* comment: 02/23/2021 SY: the bitrate is measured bitrate,
|
||||
* the overlapping effect is already considered into bitrate.
|
||||
* no need to add extra anymore
|
||||
*/
|
||||
fmin = (vpp_hw_min_frequency > vsp_hw_min_frequency) ?
|
||||
vpp_hw_min_frequency : vsp_hw_min_frequency;
|
||||
|
||||
/* FW time */
|
||||
fmin_fwoverhead105 = (fmin * 105 + 99) / 100;
|
||||
fmin_measured_fwoverhead = fmin +
|
||||
(((DECODER_VPPVSP1STAGE_FW_OVERHEAD_IRIS33 *
|
||||
codec_input.frame_rate * 10 + 14) / 15 + 999) / 1000 + 999) /
|
||||
1000;
|
||||
|
||||
fmin = (fmin_fwoverhead105 > fmin_measured_fwoverhead) ?
|
||||
fmin_fwoverhead105 : fmin_measured_fwoverhead;
|
||||
}
|
||||
|
||||
tensilica_min_frequency = (DECODER_SW_OVERHEAD_IRIS33 * 10 + 14) / 15;
|
||||
tensilica_min_frequency = (tensilica_min_frequency + 999) / 1000;
|
||||
tensilica_min_frequency = tensilica_min_frequency * codec_input.frame_rate;
|
||||
tensilica_min_frequency = (tensilica_min_frequency + 999) / 1000;
|
||||
fmin = (tensilica_min_frequency > fmin) ? tensilica_min_frequency : fmin;
|
||||
} else { /* encoder */
|
||||
/* Decide LP/HQ */
|
||||
u8 hq_mode = 0;
|
||||
|
||||
if (codec_input.pipe_num > 1)
|
||||
if (codec_input.frame_width * codec_input.frame_height <=
|
||||
1920 * 1080)
|
||||
if (codec_input.frame_width * codec_input.frame_height *
|
||||
codec_input.frame_rate <= 1920 * 1080 * 60)
|
||||
hq_mode = 1;
|
||||
|
||||
codec_output->enc_hqmode = hq_mode;
|
||||
|
||||
/* Section 1. 0 */
|
||||
/* TODO ONETIME call, should be in another place. */
|
||||
initialize_encoder_complexity_table();
|
||||
|
||||
/* End Calculate Encoder GOP Complexity Table */
|
||||
|
||||
/* VPP base cycle */
|
||||
lpmode_uhd_cycle_permb = (320 *
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[codec_input.hierachical_layer][CODEC_ENCODER_GOP_FACTORY_ENTRY]
|
||||
+ 99) / 100;
|
||||
|
||||
if ((codec_input.frame_width == 1920) &&
|
||||
((codec_input.frame_height == 1080) ||
|
||||
(codec_input.frame_height == 1088)) &&
|
||||
(codec_input.frame_rate >= 480))
|
||||
lpmode_uhd_cycle_permb = (90 * 4 *
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[codec_input.hierachical_layer][CODEC_ENCODER_GOP_FACTORY_ENTRY]
|
||||
+ 99) / 100;
|
||||
|
||||
if ((codec_input.frame_width == 1280) &&
|
||||
((codec_input.frame_height == 720) ||
|
||||
(codec_input.frame_height == 768)) &&
|
||||
(codec_input.frame_rate >= 960))
|
||||
lpmode_uhd_cycle_permb = (99 * 4 *
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[codec_input.hierachical_layer][CODEC_ENCODER_GOP_FACTORY_ENTRY]
|
||||
+ 99) / 100;
|
||||
|
||||
hqmode1080p_cycle_permb = (675 *
|
||||
codec_encoder_gop_complexity_table_fp
|
||||
[codec_input.hierachical_layer][CODEC_ENCODER_GOP_FACTORY_ENTRY]
|
||||
+ 99) / 100;
|
||||
|
||||
encoder_vpp_target_clk_per_mb = (hq_mode) ?
|
||||
hqmode1080p_cycle_permb : lpmode_uhd_cycle_permb;
|
||||
|
||||
vpp_hw_min_frequency = ((encoder_vpp_target_clk_per_mb) *
|
||||
(codec_mbspersession_iris33) + codec_input.pipe_num - 1) /
|
||||
(codec_input.pipe_num);
|
||||
|
||||
vpp_hw_min_frequency = (vpp_hw_min_frequency + 99999) / 1000000;
|
||||
|
||||
if (codec_input.pipe_num > 1) {
|
||||
u32 pipe_penalty_codec = 101;
|
||||
|
||||
vpp_hw_min_frequency = (vpp_hw_min_frequency *
|
||||
pipe_penalty_codec + 99) / 100;
|
||||
}
|
||||
|
||||
if (codec_input.vsp_vpp_mode == CODEC_VSPVPP_MODE_2S) {
|
||||
/* FW overhead, convert FW cycles to impact to one pipe */
|
||||
u64 encoder_vpp_fw_overhead = 0;
|
||||
|
||||
encoder_vpp_fw_overhead =
|
||||
DIV_ROUND_UP((ENCODER_VPP_FW_OVERHEAD_IRIS33 * 10 *
|
||||
codec_input.frame_rate), 15);
|
||||
|
||||
encoder_vpp_fw_overhead =
|
||||
DIV_ROUND_UP((encoder_vpp_fw_overhead * 1000),
|
||||
(codec_mbspersession_iris33 * encoder_vpp_target_clk_per_mb /
|
||||
codec_input.pipe_num));
|
||||
|
||||
encoder_vpp_fw_overhead += 1000;
|
||||
|
||||
encoder_vpp_fw_overhead = (encoder_vpp_fw_overhead < 1050) ?
|
||||
1050 : encoder_vpp_fw_overhead;
|
||||
|
||||
/* VPP HW + FW */
|
||||
vpp_hw_min_frequency = (vpp_hw_min_frequency *
|
||||
encoder_vpp_fw_overhead + 999) / 1000;
|
||||
|
||||
/* TODO : decoder_vsp_fw_overhead? */
|
||||
vsp_hw_min_frequency = (vsp_hw_min_frequency *
|
||||
decoder_vsp_fw_overhead + 99) / 100;
|
||||
|
||||
fmin = (vpp_hw_min_frequency > vsp_hw_min_frequency) ?
|
||||
vpp_hw_min_frequency : vsp_hw_min_frequency;
|
||||
} else {
|
||||
/* HW time */
|
||||
fmin = (vpp_hw_min_frequency > vsp_hw_min_frequency) ?
|
||||
vpp_hw_min_frequency : vsp_hw_min_frequency;
|
||||
|
||||
/* FW time */
|
||||
fmin_fwoverhead105 = (fmin * 105 + 99) / 100;
|
||||
fmin_measured_fwoverhead = fmin +
|
||||
(((DECODER_VPPVSP1STAGE_FW_OVERHEAD_IRIS33 *
|
||||
codec_input.frame_rate * 10 + 14) / 15 + 999) /
|
||||
1000 + 999) / 1000;
|
||||
|
||||
fmin = (fmin_fwoverhead105 > fmin_measured_fwoverhead) ?
|
||||
fmin_fwoverhead105 : fmin_measured_fwoverhead;
|
||||
/* SW time */
|
||||
}
|
||||
|
||||
tensilica_min_frequency = (ENCODER_SW_OVERHEAD_IRIS33 * 10 + 14) / 15;
|
||||
tensilica_min_frequency = (tensilica_min_frequency + 999) / 1000;
|
||||
|
||||
tensilica_min_frequency = tensilica_min_frequency *
|
||||
codec_input.frame_rate;
|
||||
|
||||
tensilica_min_frequency = (tensilica_min_frequency + 999) / 1000;
|
||||
|
||||
fmin = (tensilica_min_frequency > fmin) ?
|
||||
tensilica_min_frequency : fmin;
|
||||
}
|
||||
|
||||
codec_output->vpp_min_freq = vpp_hw_min_frequency;
|
||||
codec_output->vsp_min_freq = vsp_hw_min_frequency;
|
||||
codec_output->tensilica_min_freq = tensilica_min_frequency;
|
||||
codec_output->hw_min_freq = fmin;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_calculate_frequency(struct api_calculation_input codec_input,
|
||||
struct api_calculation_freq_output *codec_output)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = calculate_vsp_min_freq(codec_input, codec_output);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = calculate_vpp_min_freq(codec_input, codec_output);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return rc;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
18
qcom/opensource/video-driver/driver/vidc/inc/firmware.h
Normal file
18
qcom/opensource/video-driver/driver/vidc/inc/firmware.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_FIRMWARE_H_
|
||||
#define _MSM_VIDC_FIRMWARE_H_
|
||||
|
||||
struct msm_vidc_core;
|
||||
|
||||
int fw_load(struct msm_vidc_core *core);
|
||||
int fw_unload(struct msm_vidc_core *core);
|
||||
int fw_suspend(struct msm_vidc_core *core);
|
||||
int fw_resume(struct msm_vidc_core *core);
|
||||
void fw_coredump(struct msm_vidc_core *core);
|
||||
|
||||
#endif
|
68
qcom/opensource/video-driver/driver/vidc/inc/fixedpoint.h
Normal file
68
qcom/opensource/video-driver/driver/vidc/inc/fixedpoint.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifdef _FIXP_ARITH_H
|
||||
#error "This implementation is meant to override fixp-arith.h, don't use both"
|
||||
#endif
|
||||
|
||||
#ifndef _FIXEDPOINT_H_
|
||||
#define _FIXEDPOINT_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/bits.h>
|
||||
|
||||
/*
|
||||
* Normally would typedef'ed, but checkpatch doesn't like typedef.
|
||||
* Also should be normally typedef'ed to intmax_t but that doesn't seem to be
|
||||
* available in the kernel
|
||||
*/
|
||||
#define fp_t size_t
|
||||
|
||||
/* (Arbitrarily) make the first 25% of the bits to be the fractional bits */
|
||||
#define FP_FRACTIONAL_BITS ((sizeof(fp_t) * 8) / 4)
|
||||
|
||||
#define FP(__i, __f_n, __f_d) \
|
||||
((((fp_t)(__i)) << FP_FRACTIONAL_BITS) + \
|
||||
(((__f_n) << FP_FRACTIONAL_BITS) / (__f_d)))
|
||||
|
||||
#define FP_INT(__i) FP(__i, 0, 1)
|
||||
#define FP_ONE FP_INT(1)
|
||||
#define FP_ZERO FP_INT(0)
|
||||
|
||||
static inline size_t fp_frac_base(void)
|
||||
{
|
||||
return GENMASK(FP_FRACTIONAL_BITS - 1, 0);
|
||||
}
|
||||
|
||||
static inline size_t fp_frac(fp_t a)
|
||||
{
|
||||
return a & GENMASK(FP_FRACTIONAL_BITS - 1, 0);
|
||||
}
|
||||
|
||||
static inline size_t fp_int(fp_t a)
|
||||
{
|
||||
return a >> FP_FRACTIONAL_BITS;
|
||||
}
|
||||
|
||||
static inline size_t fp_round(fp_t a)
|
||||
{
|
||||
/* is the fractional part >= frac_max / 2? */
|
||||
bool round_up = fp_frac(a) >= fp_frac_base() / 2;
|
||||
|
||||
return fp_int(a) + round_up;
|
||||
}
|
||||
|
||||
static inline fp_t fp_mult(fp_t a, fp_t b)
|
||||
{
|
||||
return (a * b) >> FP_FRACTIONAL_BITS;
|
||||
}
|
||||
|
||||
static inline fp_t fp_div(fp_t a, fp_t b)
|
||||
{
|
||||
return (a << FP_FRACTIONAL_BITS) / b;
|
||||
}
|
||||
|
||||
#endif
|
190
qcom/opensource/video-driver/driver/vidc/inc/hfi_command.h
Normal file
190
qcom/opensource/video-driver/driver/vidc/inc/hfi_command.h
Normal file
@ -0,0 +1,190 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __H_HFI_COMMAND_H__
|
||||
#define __H_HFI_COMMAND_H__
|
||||
|
||||
//todo: DP: remove below headers
|
||||
#include <linux/types.h>
|
||||
#include <linux/bits.h>
|
||||
|
||||
#define HFI_VIDEO_ARCH_LX 0x1
|
||||
|
||||
struct hfi_header {
|
||||
u32 size;
|
||||
u32 session_id;
|
||||
u32 header_id;
|
||||
u32 reserved[4];
|
||||
u32 num_packets;
|
||||
};
|
||||
|
||||
struct hfi_packet {
|
||||
u32 size;
|
||||
u32 type;
|
||||
u32 flags;
|
||||
u32 payload_info;
|
||||
u32 port;
|
||||
u32 packet_id;
|
||||
u32 reserved[2];
|
||||
};
|
||||
|
||||
struct hfi_buffer {
|
||||
u32 type;
|
||||
u32 index;
|
||||
u64 base_address;
|
||||
u32 addr_offset;
|
||||
u32 buffer_size;
|
||||
u32 data_offset;
|
||||
u32 data_size;
|
||||
u64 timestamp;
|
||||
u32 flags;
|
||||
u32 reserved[5];
|
||||
};
|
||||
|
||||
enum hfi_packet_host_flags {
|
||||
HFI_HOST_FLAGS_NONE = 0x00000000,
|
||||
HFI_HOST_FLAGS_INTR_REQUIRED = 0x00000001,
|
||||
HFI_HOST_FLAGS_RESPONSE_REQUIRED = 0x00000002,
|
||||
HFI_HOST_FLAGS_NON_DISCARDABLE = 0x00000004,
|
||||
HFI_HOST_FLAGS_GET_PROPERTY = 0x00000008,
|
||||
};
|
||||
|
||||
enum hfi_packet_firmware_flags {
|
||||
HFI_FW_FLAGS_NONE = 0x00000000,
|
||||
HFI_FW_FLAGS_SUCCESS = 0x00000001,
|
||||
HFI_FW_FLAGS_INFORMATION = 0x00000002,
|
||||
HFI_FW_FLAGS_SESSION_ERROR = 0x00000004,
|
||||
HFI_FW_FLAGS_SYSTEM_ERROR = 0x00000008,
|
||||
};
|
||||
|
||||
enum hfi_packet_payload_info {
|
||||
HFI_PAYLOAD_NONE = 0x00000000,
|
||||
HFI_PAYLOAD_U32 = 0x00000001,
|
||||
HFI_PAYLOAD_S32 = 0x00000002,
|
||||
HFI_PAYLOAD_U64 = 0x00000003,
|
||||
HFI_PAYLOAD_S64 = 0x00000004,
|
||||
HFI_PAYLOAD_STRUCTURE = 0x00000005,
|
||||
HFI_PAYLOAD_BLOB = 0x00000006,
|
||||
HFI_PAYLOAD_STRING = 0x00000007,
|
||||
HFI_PAYLOAD_Q16 = 0x00000008,
|
||||
HFI_PAYLOAD_U32_ENUM = 0x00000009,
|
||||
HFI_PAYLOAD_32_PACKED = 0x0000000a,
|
||||
HFI_PAYLOAD_U32_ARRAY = 0x0000000b,
|
||||
HFI_PAYLOAD_S32_ARRAY = 0x0000000c,
|
||||
HFI_PAYLOAD_64_PACKED = 0x0000000d,
|
||||
};
|
||||
|
||||
enum hfi_packet_port_type {
|
||||
HFI_PORT_NONE = 0x00000000,
|
||||
HFI_PORT_BITSTREAM = 0x00000001,
|
||||
HFI_PORT_RAW = 0x00000002,
|
||||
};
|
||||
|
||||
enum hfi_buffer_type {
|
||||
HFI_BUFFER_BITSTREAM = 0x00000001,
|
||||
HFI_BUFFER_RAW = 0x00000002,
|
||||
HFI_BUFFER_METADATA = 0x00000003,
|
||||
HFI_BUFFER_SUBCACHE = 0x00000004,
|
||||
HFI_BUFFER_PARTIAL_DATA = 0x00000005,
|
||||
HFI_BUFFER_DPB = 0x00000006,
|
||||
HFI_BUFFER_BIN = 0x00000007,
|
||||
HFI_BUFFER_LINE = 0x00000008,
|
||||
HFI_BUFFER_ARP = 0x00000009,
|
||||
HFI_BUFFER_COMV = 0x0000000A,
|
||||
HFI_BUFFER_NON_COMV = 0x0000000B,
|
||||
HFI_BUFFER_PERSIST = 0x0000000C,
|
||||
HFI_BUFFER_VPSS = 0x0000000D,
|
||||
};
|
||||
|
||||
enum hfi_buffer_host_flags {
|
||||
HFI_BUF_HOST_FLAG_NONE = 0x00000000,
|
||||
HFI_BUF_HOST_FLAG_RELEASE = 0x00000001,
|
||||
HFI_BUF_HOST_FLAG_READONLY = 0x00000010,
|
||||
HFI_BUF_HOST_FLAG_CODEC_CONFIG = 0x00000100,
|
||||
HFI_BUF_HOST_FLAGS_CB_NON_SECURE = 0x00000200,
|
||||
HFI_BUF_HOST_FLAGS_CB_SECURE_PIXEL = 0x00000400,
|
||||
HFI_BUF_HOST_FLAGS_CB_SECURE_BITSTREAM = 0x00000800,
|
||||
HFI_BUF_HOST_FLAGS_CB_SECURE_NON_PIXEL = 0x00001000,
|
||||
HFI_BUF_HOST_FLAGS_CB_NON_SECURE_PIXEL = 0x00002000,
|
||||
};
|
||||
|
||||
enum hfi_buffer_firmware_flags {
|
||||
HFI_BUF_FW_FLAG_NONE = 0x00000000,
|
||||
HFI_BUF_FW_FLAG_RELEASE_DONE = 0x00000001,
|
||||
HFI_BUF_FW_FLAG_READONLY = 0x00000010,
|
||||
HFI_BUF_FW_FLAG_CODEC_CONFIG = 0x00000100,
|
||||
HFI_BUF_FW_FLAG_LAST = 0x10000000,
|
||||
HFI_BUF_FW_FLAG_PSC_LAST = 0x20000000,
|
||||
};
|
||||
|
||||
enum hfi_metapayload_header_flags {
|
||||
HFI_METADATA_FLAGS_NONE = 0x00000000,
|
||||
HFI_METADATA_FLAGS_TOP_FIELD = 0x00000001,
|
||||
HFI_METADATA_FLAGS_BOTTOM_FIELD = 0x00000002,
|
||||
};
|
||||
|
||||
struct metabuf_header {
|
||||
u32 count;
|
||||
u32 size;
|
||||
u32 version;
|
||||
u32 reserved[5];
|
||||
};
|
||||
|
||||
struct metapayload_header {
|
||||
u32 type;
|
||||
u32 size;
|
||||
u32 version;
|
||||
u32 offset;
|
||||
u32 flags;
|
||||
u32 reserved[3];
|
||||
};
|
||||
|
||||
enum hfi_property_mode_type {
|
||||
HFI_MODE_NONE = 0x00000000,
|
||||
HFI_MODE_PORT_SETTINGS_CHANGE = 0x00000001,
|
||||
HFI_MODE_PROPERTY = 0x00000002,
|
||||
HFI_MODE_METADATA = 0x00000004,
|
||||
HFI_MODE_DYNAMIC_METADATA = 0x00000005,
|
||||
};
|
||||
|
||||
enum hfi_reserve_type {
|
||||
HFI_RESERVE_START = 0x1,
|
||||
HFI_RESERVE_STOP = 0x2,
|
||||
};
|
||||
|
||||
#define HFI_CMD_BEGIN 0x01000000
|
||||
#define HFI_CMD_INIT 0x01000001
|
||||
#define HFI_CMD_POWER_COLLAPSE 0x01000002
|
||||
#define HFI_CMD_OPEN 0x01000003
|
||||
#define HFI_CMD_CLOSE 0x01000004
|
||||
#define HFI_CMD_START 0x01000005
|
||||
#define HFI_CMD_STOP 0x01000006
|
||||
#define HFI_CMD_DRAIN 0x01000007
|
||||
#define HFI_CMD_RESUME 0x01000008
|
||||
#define HFI_CMD_BUFFER 0x01000009
|
||||
#define HFI_CMD_DELIVERY_MODE 0x0100000A
|
||||
#define HFI_CMD_SUBSCRIBE_MODE 0x0100000B
|
||||
#define HFI_CMD_SETTINGS_CHANGE 0x0100000C
|
||||
|
||||
#define HFI_SSR_TYPE_SW_ERR_FATAL 0x1
|
||||
#define HFI_SSR_TYPE_SW_DIV_BY_ZERO 0x2
|
||||
#define HFI_SSR_TYPE_CPU_WDOG_IRQ 0x3
|
||||
#define HFI_SSR_TYPE_NOC_ERROR 0x4
|
||||
#define HFI_BITMASK_HW_CLIENT_ID 0x000000f0
|
||||
#define HFI_BITMASK_SSR_TYPE 0x0000000f
|
||||
#define HFI_CMD_SSR 0x0100000D
|
||||
|
||||
#define HFI_STABILITY_TYPE_VCODEC_HUNG 0x1
|
||||
#define HFI_STABILITY_TYPE_ENC_BUFFER_FULL 0x2
|
||||
#define HFI_BITMASK_STABILITY_TYPE 0x0000000f
|
||||
#define HFI_CMD_STABILITY 0x0100000E
|
||||
|
||||
#define HFI_CMD_RESERVE 0x0100000F
|
||||
#define HFI_CMD_FLUSH 0x01000010
|
||||
#define HFI_CMD_PAUSE 0x01000011
|
||||
#define HFI_CMD_END 0x01FFFFFF
|
||||
|
||||
#endif //__H_HFI_COMMAND_H__
|
59
qcom/opensource/video-driver/driver/vidc/inc/hfi_packet.h
Normal file
59
qcom/opensource/video-driver/driver/vidc/inc/hfi_packet.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _HFI_PACKET_H_
|
||||
#define _HFI_PACKET_H_
|
||||
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_core.h"
|
||||
#include "hfi_command.h"
|
||||
#include "hfi_property.h"
|
||||
|
||||
u32 get_hfi_port(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_port_type port);
|
||||
u32 get_hfi_port_from_buffer_type(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
u32 hfi_buf_type_from_driver(enum msm_vidc_domain_type domain,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
u32 hfi_buf_type_to_driver(enum msm_vidc_domain_type domain,
|
||||
enum hfi_buffer_type buffer_type,
|
||||
enum hfi_packet_port_type port_type);
|
||||
u32 get_hfi_codec(struct msm_vidc_inst *inst);
|
||||
u32 get_hfi_colorformat(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_colorformat_type colorformat);
|
||||
int get_hfi_buffer(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_buffer *buffer,
|
||||
struct hfi_buffer *buf);
|
||||
int hfi_create_header(u8 *packet, u32 packet_size,
|
||||
u32 session_id, u32 header_id);
|
||||
int hfi_create_packet(u8 *packet, u32 packet_size,
|
||||
u32 pkt_type, u32 pkt_flags,
|
||||
u32 payload_type, u32 port,
|
||||
u32 packet_id, void *payload,
|
||||
u32 payload_size);
|
||||
int hfi_create_buffer(u8 *packet, u32 packet_size, u32 *offset,
|
||||
enum msm_vidc_domain_type domain,
|
||||
struct msm_vidc_buffer *data);
|
||||
int hfi_packet_sys_init(struct msm_vidc_core *core,
|
||||
u8 *pkt, u32 pkt_size);
|
||||
int hfi_packet_image_version(struct msm_vidc_core *core,
|
||||
u8 *pkt, u32 pkt_size);
|
||||
int hfi_packet_sys_pc_prep(struct msm_vidc_core *core,
|
||||
u8 *pkt, u32 pkt_size);
|
||||
int hfi_packet_sys_debug_config(struct msm_vidc_core *core,
|
||||
u8 *pkt, u32 pkt_size,
|
||||
u32 debug_config);
|
||||
int hfi_packet_session_command(struct msm_vidc_inst *inst,
|
||||
u32 pkt_type, u32 flags,
|
||||
u32 port, u32 session_id,
|
||||
u32 payload_type, void *payload,
|
||||
u32 payload_size);
|
||||
int hfi_packet_sys_intraframe_powercollapse(struct msm_vidc_core *core,
|
||||
u8 *pkt, u32 pkt_size,
|
||||
u32 enable);
|
||||
|
||||
#endif // _HFI_PACKET_H_
|
666
qcom/opensource/video-driver/driver/vidc/inc/hfi_property.h
Normal file
666
qcom/opensource/video-driver/driver/vidc/inc/hfi_property.h
Normal file
@ -0,0 +1,666 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __H_HFI_PROPERTY_H__
|
||||
#define __H_HFI_PROPERTY_H__
|
||||
|
||||
//todo: DP: remove below header
|
||||
#include <linux/types.h>
|
||||
|
||||
#define HFI_PROP_BEGIN 0x03000000
|
||||
#define HFI_PROP_IMAGE_VERSION 0x03000001
|
||||
#define HFI_PROP_INTRA_FRAME_POWER_COLLAPSE 0x03000002
|
||||
#define HFI_PROP_UBWC_MAX_CHANNELS 0x03000003
|
||||
#define HFI_PROP_UBWC_MAL_LENGTH 0x03000004
|
||||
#define HFI_PROP_UBWC_HBB 0x03000005
|
||||
#define HFI_PROP_UBWC_BANK_SWZL_LEVEL1 0x03000006
|
||||
#define HFI_PROP_UBWC_BANK_SWZL_LEVEL2 0x03000007
|
||||
#define HFI_PROP_UBWC_BANK_SWZL_LEVEL3 0x03000008
|
||||
#define HFI_PROP_UBWC_BANK_SPREADING 0x03000009
|
||||
|
||||
enum hfi_debug_config {
|
||||
HFI_DEBUG_CONFIG_DEFAULT = 0x00000000,
|
||||
HFI_DEBUG_CONFIG_CLRDBGQ = 0x00000001,
|
||||
HFI_DEBUG_CONFIG_WFI = 0x00000002,
|
||||
HFI_DEBUG_CONFIG_ARM9WD = 0x00000004,
|
||||
};
|
||||
|
||||
#define HFI_PROP_DEBUG_CONFIG 0x0300000a
|
||||
|
||||
enum hfi_debug_log_level {
|
||||
HFI_DEBUG_LOG_NONE = 0x00000000,
|
||||
HFI_DEBUG_LOG_ERROR = 0x00000001,
|
||||
HFI_DEBUG_LOG_FATAL = 0x00000002,
|
||||
HFI_DEBUG_LOG_PERF = 0x00000004,
|
||||
HFI_DEBUG_LOG_HIGH = 0x00000008,
|
||||
HFI_DEBUG_LOG_MEDIUM = 0x00000010,
|
||||
HFI_DEBUG_LOG_LOW = 0x00000020,
|
||||
};
|
||||
|
||||
struct hfi_debug_header {
|
||||
u32 size;
|
||||
u32 debug_level;
|
||||
u32 reserved[2];
|
||||
};
|
||||
|
||||
#define HFI_PROP_DEBUG_LOG_LEVEL 0x0300000b
|
||||
|
||||
#define HFI_PROP_FENCE_CLIENT_DATA 0x0300000d
|
||||
|
||||
enum hfi_codec_type {
|
||||
HFI_CODEC_DECODE_AVC = 1,
|
||||
HFI_CODEC_ENCODE_AVC = 2,
|
||||
HFI_CODEC_DECODE_HEVC = 3,
|
||||
HFI_CODEC_ENCODE_HEVC = 4,
|
||||
HFI_CODEC_DECODE_VP9 = 5,
|
||||
HFI_CODEC_DECODE_MPEG2 = 6,
|
||||
HFI_CODEC_DECODE_AV1 = 7,
|
||||
};
|
||||
|
||||
#define HFI_PROP_CODEC 0x03000100
|
||||
|
||||
enum hfi_color_format {
|
||||
HFI_COLOR_FMT_OPAQUE = 0,
|
||||
HFI_COLOR_FMT_NV12 = 1,
|
||||
HFI_COLOR_FMT_NV12_UBWC = 2,
|
||||
HFI_COLOR_FMT_P010 = 3,
|
||||
HFI_COLOR_FMT_TP10_UBWC = 4,
|
||||
HFI_COLOR_FMT_RGBA8888 = 5,
|
||||
HFI_COLOR_FMT_RGBA8888_UBWC = 6,
|
||||
HFI_COLOR_FMT_NV21 = 7,
|
||||
};
|
||||
|
||||
#define HFI_PROP_COLOR_FORMAT 0x03000101
|
||||
|
||||
#define HFI_PROP_SECURE 0x03000102
|
||||
|
||||
#define HFI_BITMASK_BITSTREAM_WIDTH 0xffff0000
|
||||
#define HFI_BITMASK_BITSTREAM_HEIGHT 0x0000ffff
|
||||
#define HFI_PROP_BITSTREAM_RESOLUTION 0x03000103
|
||||
|
||||
#define HFI_BITMASK_LINEAR_STRIDE 0xffff0000
|
||||
#define HFI_BITMASK_LINEAR_SCANLINE 0x0000ffff
|
||||
#define HFI_PROP_LINEAR_STRIDE_SCANLINE 0x03000104
|
||||
|
||||
#define HFI_BITMASK_CROP_RIGHT_OFFSET 0xffff0000
|
||||
#define HFI_BITMASK_CROP_BOTTOM_OFFSET 0x0000ffff
|
||||
#define HFI_BITMASK_CROP_LEFT_OFFSET 0xffff0000
|
||||
#define HFI_BITMASK_CROP_TOP_OFFSET 0x0000ffff
|
||||
#define HFI_PROP_CROP_OFFSETS 0x03000105
|
||||
|
||||
#define HFI_PROP_SESSION_PRIORITY 0x03000106
|
||||
|
||||
enum hfi_avc_profile_type {
|
||||
HFI_AVC_PROFILE_BASELINE = 0,
|
||||
HFI_AVC_PROFILE_CONSTRAINED_BASELINE = 1,
|
||||
HFI_AVC_PROFILE_MAIN = 2,
|
||||
HFI_AVC_PROFILE_HIGH = 4,
|
||||
HFI_AVC_PROFILE_CONSTRAINED_HIGH = 17
|
||||
};
|
||||
|
||||
enum hfi_hevc_profile_type {
|
||||
HFI_H265_PROFILE_MAIN = 0,
|
||||
HFI_H265_PROFILE_MAIN_STILL_PICTURE = 1,
|
||||
HFI_H265_PROFILE_MAIN_10 = 2,
|
||||
HFI_H265_PROFILE_MAIN_10_STILL_PICTURE = 3,
|
||||
};
|
||||
|
||||
enum hfi_vp9_profile_type {
|
||||
HFI_VP9_PROFILE_0 = 0,
|
||||
HFI_VP9_PROFILE_1 = 1,
|
||||
HFI_VP9_PROFILE_2 = 2,
|
||||
HFI_VP9_PROFILE_3 = 3,
|
||||
};
|
||||
|
||||
enum hfi_mpeg2_profile_type {
|
||||
HFI_MP2_PROFILE_SIMPLE = 0,
|
||||
HFI_MP2_PROFILE_MAIN = 1,
|
||||
};
|
||||
|
||||
enum hfi_av1_profile_type {
|
||||
HFI_AV1_PROFILE_MAIN = 0,
|
||||
HFI_AV1_PROFILE_HIGH = 1,
|
||||
HFI_AV1_PROFILE_PROF = 2,
|
||||
};
|
||||
|
||||
#define HFI_PROP_PROFILE 0x03000107
|
||||
|
||||
enum hfi_avc_level_type {
|
||||
HFI_AVC_LEVEL_1_0 = 0,
|
||||
HFI_AVC_LEVEL_1B = 1,
|
||||
HFI_AVC_LEVEL_1_1 = 2,
|
||||
HFI_AVC_LEVEL_1_2 = 3,
|
||||
HFI_AVC_LEVEL_1_3 = 4,
|
||||
HFI_AVC_LEVEL_2_0 = 5,
|
||||
HFI_AVC_LEVEL_2_1 = 6,
|
||||
HFI_AVC_LEVEL_2_2 = 7,
|
||||
HFI_AVC_LEVEL_3_0 = 8,
|
||||
HFI_AVC_LEVEL_3_1 = 9,
|
||||
HFI_AVC_LEVEL_3_2 = 10,
|
||||
HFI_AVC_LEVEL_4_0 = 11,
|
||||
HFI_AVC_LEVEL_4_1 = 12,
|
||||
HFI_AVC_LEVEL_4_2 = 13,
|
||||
HFI_AVC_LEVEL_5_0 = 14,
|
||||
HFI_AVC_LEVEL_5_1 = 15,
|
||||
HFI_AVC_LEVEL_5_2 = 16,
|
||||
HFI_AVC_LEVEL_6_0 = 17,
|
||||
HFI_AVC_LEVEL_6_1 = 18,
|
||||
HFI_AVC_LEVEL_6_2 = 19,
|
||||
};
|
||||
|
||||
enum hfi_hevc_level_type {
|
||||
HFI_H265_LEVEL_1 = 0,
|
||||
HFI_H265_LEVEL_2 = 1,
|
||||
HFI_H265_LEVEL_2_1 = 2,
|
||||
HFI_H265_LEVEL_3 = 3,
|
||||
HFI_H265_LEVEL_3_1 = 4,
|
||||
HFI_H265_LEVEL_4 = 5,
|
||||
HFI_H265_LEVEL_4_1 = 6,
|
||||
HFI_H265_LEVEL_5 = 7,
|
||||
HFI_H265_LEVEL_5_1 = 8,
|
||||
HFI_H265_LEVEL_5_2 = 9,
|
||||
HFI_H265_LEVEL_6 = 10,
|
||||
HFI_H265_LEVEL_6_1 = 11,
|
||||
HFI_H265_LEVEL_6_2 = 12,
|
||||
};
|
||||
|
||||
enum hfi_vp9_level_type {
|
||||
HFI_VP9_LEVEL_1_0 = 0,
|
||||
HFI_VP9_LEVEL_1_1 = 1,
|
||||
HFI_VP9_LEVEL_2_0 = 2,
|
||||
HFI_VP9_LEVEL_2_1 = 3,
|
||||
HFI_VP9_LEVEL_3_0 = 4,
|
||||
HFI_VP9_LEVEL_3_1 = 5,
|
||||
HFI_VP9_LEVEL_4_0 = 6,
|
||||
HFI_VP9_LEVEL_4_1 = 7,
|
||||
HFI_VP9_LEVEL_5_0 = 8,
|
||||
HFI_VP9_LEVEL_5_1 = 9,
|
||||
HFI_VP9_LEVEL_6_0 = 10,
|
||||
HFI_VP9_LEVEL_6_1 = 11,
|
||||
};
|
||||
|
||||
enum hfi_mpeg2_level_type {
|
||||
HFI_MP2_LEVEL_LOW = 0,
|
||||
HFI_MP2_LEVEL_MAIN = 1,
|
||||
HFI_MP2_LEVEL_HIGH_1440 = 2,
|
||||
HFI_MP2_LEVEL_HIGH = 3,
|
||||
};
|
||||
|
||||
enum hfi_av1_level_type {
|
||||
HFI_AV1_LEVEL_2_0 = 0,
|
||||
HFI_AV1_LEVEL_2_1 = 1,
|
||||
HFI_AV1_LEVEL_2_2 = 2,
|
||||
HFI_AV1_LEVEL_2_3 = 3,
|
||||
HFI_AV1_LEVEL_3_0 = 4,
|
||||
HFI_AV1_LEVEL_3_1 = 5,
|
||||
HFI_AV1_LEVEL_3_2 = 6,
|
||||
HFI_AV1_LEVEL_3_3 = 7,
|
||||
HFI_AV1_LEVEL_4_0 = 8,
|
||||
HFI_AV1_LEVEL_4_1 = 9,
|
||||
HFI_AV1_LEVEL_4_2 = 10,
|
||||
HFI_AV1_LEVEL_4_3 = 11,
|
||||
HFI_AV1_LEVEL_5_0 = 12,
|
||||
HFI_AV1_LEVEL_5_1 = 13,
|
||||
HFI_AV1_LEVEL_5_2 = 14,
|
||||
HFI_AV1_LEVEL_5_3 = 15,
|
||||
HFI_AV1_LEVEL_6_0 = 16,
|
||||
HFI_AV1_LEVEL_6_1 = 17,
|
||||
HFI_AV1_LEVEL_6_2 = 18,
|
||||
HFI_AV1_LEVEL_6_3 = 19,
|
||||
HFI_AV1_LEVEL_7_0 = 20,
|
||||
HFI_AV1_LEVEL_7_1 = 21,
|
||||
HFI_AV1_LEVEL_7_2 = 22,
|
||||
HFI_AV1_LEVEL_7_3 = 23,
|
||||
HFI_AV1_LEVEL_MAX = 31,
|
||||
};
|
||||
|
||||
enum hfi_codec_level_type {
|
||||
HFI_LEVEL_NONE = 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
#define HFI_PROP_LEVEL 0x03000108
|
||||
|
||||
enum hfi_hevc_tier_type {
|
||||
HFI_H265_TIER_MAIN = 0,
|
||||
HFI_H265_TIER_HIGH = 1,
|
||||
};
|
||||
|
||||
enum hfi_av1_tier_type {
|
||||
HFI_AV1_TIER_MAIN = 0,
|
||||
HFI_AV1_TIER_HIGH = 1,
|
||||
};
|
||||
|
||||
#define HFI_PROP_TIER 0x03000109
|
||||
|
||||
#define HFI_PROP_STAGE 0x0300010a
|
||||
|
||||
#define HFI_PROP_PIPE 0x0300010b
|
||||
|
||||
#define HFI_PROP_FRAME_RATE 0x0300010c
|
||||
|
||||
#define HFI_BITMASK_CONCEAL_LUMA 0x000003ff
|
||||
#define HFI_BITMASK_CONCEAL_CB 0x000ffC00
|
||||
#define HFI_BITMASK_CONCEAL_CR 0x3ff00000
|
||||
#define HFI_PROP_CONCEAL_COLOR_8BIT 0x0300010d
|
||||
|
||||
#define HFI_BITMASK_CONCEAL_LUMA 0x000003ff
|
||||
#define HFI_BITMASK_CONCEAL_CB 0x000ffC00
|
||||
#define HFI_BITMASK_CONCEAL_CR 0x3ff00000
|
||||
#define HFI_PROP_CONCEAL_COLOR_10BIT 0x0300010e
|
||||
|
||||
#define HFI_BITMASK_LUMA_BIT_DEPTH 0xffff0000
|
||||
#define HFI_BITMASK_CHROMA_BIT_DEPTH 0x0000ffff
|
||||
#define HFI_PROP_LUMA_CHROMA_BIT_DEPTH 0x0300010f
|
||||
|
||||
#define HFI_BITMASK_FRAME_MBS_ONLY_FLAG 0x00000001
|
||||
#define HFI_BITMASK_MB_ADAPTIVE_FRAME_FIELD_FLAG 0x00000002
|
||||
#define HFI_PROP_CODED_FRAMES 0x03000120
|
||||
|
||||
#define HFI_PROP_CABAC_SESSION 0x03000121
|
||||
|
||||
#define HFI_PROP_8X8_TRANSFORM 0x03000122
|
||||
|
||||
#define HFI_PROP_BUFFER_HOST_MAX_COUNT 0x03000123
|
||||
|
||||
#define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT 0x03000124
|
||||
|
||||
#define HFI_PROP_BUFFER_MAXDPB_COUNT 0x03000125
|
||||
|
||||
#define HFI_PROP_BUFFER_MAX_NUM_REFERENCE 0x03000126
|
||||
|
||||
#define HFI_PROP_MAX_NUM_REORDER_FRAMES 0x03000127
|
||||
|
||||
#define HFI_PROP_PIC_ORDER_CNT_TYPE 0x03000128
|
||||
|
||||
enum hfi_deblock_mode {
|
||||
HFI_DEBLOCK_ALL_BOUNDARY = 0x0,
|
||||
HFI_DEBLOCK_DISABLE = 0x1,
|
||||
HFI_DEBLOCK_DISABLE_AT_SLICE_BOUNDARY = 0x2,
|
||||
};
|
||||
|
||||
#define HFI_PROP_DEBLOCKING_MODE 0x03000129
|
||||
|
||||
enum hfi_rate_control {
|
||||
HFI_RC_VBR_CFR = 0x00000000,
|
||||
HFI_RC_CBR_CFR = 0x00000001,
|
||||
HFI_RC_CQ = 0x00000002,
|
||||
HFI_RC_OFF = 0x00000003,
|
||||
HFI_RC_CBR_VFR = 0x00000004,
|
||||
HFI_RC_LOSSLESS = 0x00000005,
|
||||
};
|
||||
|
||||
#define HFI_PROP_RATE_CONTROL 0x0300012a
|
||||
|
||||
#define HFI_PROP_TIME_DELTA_BASED_RATE_CONTROL 0x0300012b
|
||||
|
||||
#define HFI_PROP_CONTENT_ADAPTIVE_CODING 0x0300012c
|
||||
|
||||
#define HFI_PROP_BITRATE_BOOST 0x0300012d
|
||||
|
||||
#define HFI_BITMASK_QP_I 0x000000ff
|
||||
#define HFI_BITMASK_QP_P 0x0000ff00
|
||||
#define HFI_BITMASK_QP_B 0x00ff0000
|
||||
#define HFI_BITMASK_QP_ENABLE 0x0f000000
|
||||
#define HFI_BITMASK_QP_LAYERS 0xf0000000
|
||||
#define HFI_PROP_QP_PACKED 0x0300012e
|
||||
|
||||
#define HFI_PROP_MIN_QP_PACKED 0x0300012f
|
||||
|
||||
#define HFI_PROP_MAX_QP_PACKED 0x03000130
|
||||
|
||||
#define HFI_PROP_IR_RANDOM_PERIOD 0x03000131
|
||||
|
||||
#define HFI_PROP_MULTI_SLICE_MB_COUNT 0x03000132
|
||||
|
||||
#define HFI_PROP_MULTI_SLICE_BYTES_COUNT 0x03000133
|
||||
|
||||
#define HFI_PROP_LTR_COUNT 0x03000134
|
||||
|
||||
#define HFI_PROP_LTR_MARK 0x03000135
|
||||
|
||||
#define HFI_PROP_LTR_USE 0x03000136
|
||||
|
||||
#define HFI_PROP_LTR_MARK_USE_DETAILS 0x03000137
|
||||
|
||||
enum hfi_layer_encoding_type {
|
||||
HFI_HIER_P_SLIDING_WINDOW = 0x1,
|
||||
HFI_HIER_P_HYBRID_LTR = 0x2,
|
||||
HFI_HIER_B = 0x3,
|
||||
};
|
||||
|
||||
#define HFI_PROP_LAYER_ENCODING_TYPE 0x03000138
|
||||
|
||||
#define HFI_PROP_LAYER_COUNT 0x03000139
|
||||
|
||||
enum hfi_chromaqp_offset_mode {
|
||||
HFI_ADAPTIVE_CHROMAQP_OFFSET = 0x0,
|
||||
HFI_FIXED_CHROMAQP_OFFSET = 0x1,
|
||||
};
|
||||
|
||||
#define HFI_BITMASK_CHROMA_CB_OFFSET 0x0000ffff
|
||||
#define HFI_BITMASK_CHROMA_CR_OFFSET 0xffff0000
|
||||
#define HFI_PROP_CHROMA_QP_OFFSET 0x0300013a
|
||||
|
||||
#define HFI_PROP_TOTAL_BITRATE 0x0300013b
|
||||
|
||||
#define HFI_PROP_BITRATE_LAYER1 0x0300013c
|
||||
|
||||
#define HFI_PROP_BITRATE_LAYER2 0x0300013d
|
||||
|
||||
#define HFI_PROP_BITRATE_LAYER3 0x0300013e
|
||||
|
||||
#define HFI_PROP_BITRATE_LAYER4 0x0300013f
|
||||
|
||||
#define HFI_PROP_BITRATE_LAYER5 0x03000140
|
||||
|
||||
#define HFI_PROP_BITRATE_LAYER6 0x03000141
|
||||
|
||||
#define HFI_PROP_BASELAYER_PRIORITYID 0x03000142
|
||||
|
||||
#define HFI_PROP_CONSTANT_QUALITY 0x03000143
|
||||
|
||||
#define HFI_PROP_HEIC_GRID_ENABLE 0x03000144
|
||||
|
||||
enum hfi_syncframe_request_mode {
|
||||
HFI_SYNC_FRAME_REQUEST_WITHOUT_SEQ_HDR = 0x00000001,
|
||||
HFI_SYNC_FRAME_REQUEST_WITH_PREFIX_SEQ_HDR = 0x00000002,
|
||||
};
|
||||
|
||||
#define HFI_PROP_REQUEST_SYNC_FRAME 0x03000145
|
||||
|
||||
#define HFI_PROP_MAX_GOP_FRAMES 0x03000146
|
||||
|
||||
#define HFI_PROP_MAX_B_FRAMES 0x03000147
|
||||
|
||||
enum hfi_quality_mode {
|
||||
HFI_MODE_MAX_QUALITY = 0x1,
|
||||
HFI_MODE_POWER_SAVE = 0x2,
|
||||
};
|
||||
|
||||
#define HFI_PROP_QUALITY_MODE 0x03000148
|
||||
|
||||
enum hfi_seq_header_mode {
|
||||
HFI_SEQ_HEADER_SEPERATE_FRAME = 0x00000001,
|
||||
HFI_SEQ_HEADER_JOINED_WITH_1ST_FRAME = 0x00000002,
|
||||
HFI_SEQ_HEADER_PREFIX_WITH_SYNC_FRAME = 0x00000004,
|
||||
HFI_SEQ_HEADER_METADATA = 0x00000008,
|
||||
};
|
||||
|
||||
#define HFI_PROP_SEQ_HEADER_MODE 0x03000149
|
||||
|
||||
#define HFI_PROP_METADATA_SEQ_HEADER_NAL 0x0300014a
|
||||
|
||||
enum hfi_rotation {
|
||||
HFI_ROTATION_NONE = 0x00000000,
|
||||
HFI_ROTATION_90 = 0x00000001,
|
||||
HFI_ROTATION_180 = 0x00000002,
|
||||
HFI_ROTATION_270 = 0x00000003,
|
||||
};
|
||||
|
||||
#define HFI_PROP_ROTATION 0x0300014b
|
||||
|
||||
enum hfi_flip {
|
||||
HFI_DISABLE_FLIP = 0x00000000,
|
||||
HFI_HORIZONTAL_FLIP = 0x00000001,
|
||||
HFI_VERTICAL_FLIP = 0x00000002,
|
||||
};
|
||||
|
||||
#define HFI_PROP_FLIP 0x0300014c
|
||||
|
||||
#define HFI_PROP_SCALAR 0x0300014d
|
||||
|
||||
enum hfi_blur_types {
|
||||
HFI_BLUR_NONE = 0x00000000,
|
||||
HFI_BLUR_EXTERNAL = 0x00000001,
|
||||
HFI_BLUR_ADAPTIVE = 0x00000002,
|
||||
};
|
||||
|
||||
#define HFI_PROP_BLUR_TYPES 0x0300014e
|
||||
|
||||
#define HFI_BITMASK_BLUR_WIDTH 0xffff0000
|
||||
#define HFI_BITMASK_BLUR_HEIGHT 0x0000ffff
|
||||
#define HFI_PROP_BLUR_RESOLUTION 0x0300014f
|
||||
|
||||
#define HFI_BITMASK_SPS_ID 0x000000ff
|
||||
#define HFI_BITMASK_PPS_ID 0x0000ff00
|
||||
#define HFI_BITMASK_VPS_ID 0x00ff0000
|
||||
#define HFI_PROP_SEQUENCE_HEADER_IDS 0x03000150
|
||||
|
||||
#define HFI_PROP_AUD 0x03000151
|
||||
|
||||
#define HFI_PROP_DPB_LUMA_CHROMA_MISR 0x03000153
|
||||
|
||||
#define HFI_PROP_OPB_LUMA_CHROMA_MISR 0x03000154
|
||||
|
||||
#define HFI_BITMASK_QP_I 0x000000ff
|
||||
#define HFI_BITMASK_QP_P 0x0000ff00
|
||||
#define HFI_BITMASK_QP_B 0x00ff0000
|
||||
#define HFI_BITMASK_QP_ENABLE 0x0f000000
|
||||
#define HFI_BITMASK_QP_LAYERS 0xf0000000
|
||||
#define HFI_PROP_SIGNAL_COLOR_INFO 0x03000155
|
||||
|
||||
enum hfi_interlace_info {
|
||||
HFI_INTERLACE_INFO_NONE = 0x00000000,
|
||||
HFI_FRAME_PROGRESSIVE = 0x00000001,
|
||||
HFI_FRAME_MBAFF = 0x00000002,
|
||||
HFI_FRAME_INTERLEAVE_TOPFIELD_FIRST = 0x00000004,
|
||||
HFI_FRAME_INTERLEAVE_BOTTOMFIELD_FIRST = 0x00000008,
|
||||
HFI_FRAME_INTERLACE_TOPFIELD_FIRST = 0x00000010,
|
||||
HFI_FRAME_INTERLACE_BOTTOMFIELD_FIRST = 0x00000020,
|
||||
};
|
||||
|
||||
#define HFI_PROP_INTERLACE_INFO 0x03000156
|
||||
|
||||
#define HFI_PROP_CSC 0x03000157
|
||||
|
||||
#define HFI_PROP_CSC_MATRIX 0x03000158
|
||||
|
||||
#define HFI_PROP_CSC_BIAS 0x03000159
|
||||
|
||||
#define HFI_PROP_CSC_LIMIT 0x0300015a
|
||||
|
||||
#define HFI_PROP_DECODE_ORDER_OUTPUT 0x0300015b
|
||||
|
||||
#define HFI_PROP_TIMESTAMP 0x0300015c
|
||||
|
||||
#define HFI_PROP_FRAMERATE_FROM_BITSTREAM 0x0300015d
|
||||
|
||||
#define HFI_PROP_SEI_RECOVERY_POINT 0x0300015e
|
||||
|
||||
#define HFI_PROP_CONEALED_MB_COUNT 0x0300015f
|
||||
|
||||
#define HFI_BITMASK_SAR_WIDTH 0xffff0000
|
||||
#define HFI_BITMASK_SAR_HEIGHT 0x0000ffff
|
||||
#define HFI_PROP_SAR_RESOLUTION 0x03000160
|
||||
|
||||
#define HFI_PROP_HISTOGRAM_INFO 0x03000161
|
||||
|
||||
enum hfi_picture_type {
|
||||
HFI_PICTURE_IDR = 0x00000001,
|
||||
HFI_PICTURE_P = 0x00000002,
|
||||
HFI_PICTURE_B = 0x00000004,
|
||||
HFI_PICTURE_I = 0x00000008,
|
||||
HFI_PICTURE_CRA = 0x00000010,
|
||||
HFI_PICTURE_BLA = 0x00000020,
|
||||
HFI_PICTURE_NOSHOW = 0x00000040,
|
||||
};
|
||||
|
||||
#define HFI_PROP_PICTURE_TYPE 0x03000162
|
||||
|
||||
#define HFI_PROP_SEI_MASTERING_DISPLAY_COLOUR 0x03000163
|
||||
|
||||
#define HFI_PROP_SEI_CONTENT_LIGHT_LEVEL 0x03000164
|
||||
|
||||
#define HFI_PROP_SEI_HDR10PLUS_USERDATA 0x03000165
|
||||
|
||||
#define HFI_PROP_SEI_STREAM_USERDATA 0x03000166
|
||||
|
||||
#define HFI_PROP_EVA_STAT_INFO 0x03000167
|
||||
|
||||
#define HFI_PROP_DEC_DEFAULT_HEADER 0x03000168
|
||||
|
||||
#define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169
|
||||
|
||||
#define HFI_PROP_NO_OUTPUT 0x0300016a
|
||||
|
||||
#define HFI_PROP_BUFFER_TAG 0x0300016b
|
||||
|
||||
#define HFI_PROP_BUFFER_MARK 0x0300016c
|
||||
|
||||
#define HFI_PROP_SUBFRAME_OUTPUT 0x0300016d
|
||||
|
||||
#define HFI_PROP_ENC_QP_METADATA 0x0300016e
|
||||
|
||||
#define HFI_PROP_DEC_QP_METADATA 0x0300016f
|
||||
|
||||
#define HFI_PROP_SEI_FRAME_PACKING_ARRANGEMENT 0x03000170
|
||||
|
||||
#define HFI_PROP_SEI_PAN_SCAN_RECT 0x03000171
|
||||
|
||||
#define HFI_PROP_THUMBNAIL_MODE 0x03000172
|
||||
|
||||
#define HFI_PROP_ROI_INFO 0x03000173
|
||||
|
||||
#define HFI_PROP_WORST_COMPRESSION_RATIO 0x03000174
|
||||
|
||||
#define HFI_PROP_WORST_COMPLEXITY_FACTOR 0x03000175
|
||||
|
||||
#define HFI_PROP_VBV_DELAY 0x03000176
|
||||
|
||||
#define HFI_PROP_SEQ_CHANGE_AT_SYNC_FRAME 0x03000177
|
||||
|
||||
#define HFI_BITMASK_RAW_WIDTH 0xffff0000
|
||||
#define HFI_BITMASK_RAW_HEIGHT 0x0000ffff
|
||||
#define HFI_PROP_RAW_RESOLUTION 0x03000178
|
||||
|
||||
#define HFI_PROP_DPB_TAG_LIST 0x03000179
|
||||
|
||||
#define HFI_PROP_DPB_LIST 0x0300017A
|
||||
|
||||
enum hfi_nal_length_field_type {
|
||||
HFI_NAL_LENGTH_STARTCODES = 0,
|
||||
HFI_NAL_LENGTH_SIZE_4 = 4,
|
||||
};
|
||||
|
||||
#define HFI_PROP_NAL_LENGTH_FIELD 0x0300017B
|
||||
|
||||
#define HFI_PROP_TOTAL_PEAK_BITRATE 0x0300017C
|
||||
|
||||
#define HFI_PROP_MAINTAIN_MIN_QUALITY 0x0300017D
|
||||
|
||||
#define HFI_PROP_IR_CYCLIC_PERIOD 0x0300017E
|
||||
|
||||
#define HFI_PROP_ENABLE_SLICE_DELIVERY 0x0300017F
|
||||
|
||||
#define HFI_PROP_AV1_FILM_GRAIN_PRESENT 0x03000180
|
||||
|
||||
#define HFI_PROP_AV1_SUPER_BLOCK_ENABLED 0x03000181
|
||||
|
||||
#define HFI_PROP_AV1_OP_POINT 0x03000182
|
||||
|
||||
#define HFI_PROP_SUBFRAME_INPUT 0x03000183
|
||||
|
||||
#define HFI_PROP_OPB_ENABLE 0x03000184
|
||||
|
||||
#define HFI_PROP_AV1_TILE_ROWS_COLUMNS 0x03000187
|
||||
|
||||
#define HFI_PROP_AV1_DRAP_CONFIG 0x03000189
|
||||
|
||||
enum hfi_saliency_type {
|
||||
HFI_SALIENCY_NONE,
|
||||
HFI_SALIENCY_TYPE0,
|
||||
};
|
||||
|
||||
#define HFI_PROP_ROI_AS_SALIENCY_INFO 0x0300018A
|
||||
|
||||
#define HFI_PROP_FENCE 0x0300018B
|
||||
|
||||
#define HFI_PROP_REQUEST_PREPROCESS 0x0300018E
|
||||
|
||||
#define HFI_PROP_UBWC_STRIDE_SCANLINE 0x03000190
|
||||
|
||||
#define HFI_PROP_TRANSCODING_STAT_INFO 0x03000191
|
||||
|
||||
#define HFI_PROP_DOLBY_RPU_METADATA 0x03000192
|
||||
|
||||
#define HFI_PROP_COMV_BUFFER_COUNT 0x03000193
|
||||
|
||||
#define HFI_PROP_DISABLE_VUI_TIMING_INFO 0x03000194
|
||||
|
||||
#define HFI_PROP_SLICE_DECODE 0x03000196
|
||||
|
||||
#define HFI_PROP_AV1_UNIFORM_TILE_SPACING 0x03000197
|
||||
|
||||
#define HFI_PROP_ENC_RING_BIN_BUF 0x0300019C
|
||||
|
||||
/* u32 */
|
||||
enum hfi_fence_type {
|
||||
HFI_SW_FENCE = 0x00000001,
|
||||
HFI_SYNX_V2_FENCE = 0x00000002,
|
||||
};
|
||||
|
||||
#define HFI_PROP_FENCE_TYPE 0x0300019D
|
||||
|
||||
enum hfi_fence_direction_type {
|
||||
HFI_FENCE_TX_ENABLE = 0x00000001,
|
||||
HFI_FENCE_RX_ENABLE = 0x00000002,
|
||||
};
|
||||
|
||||
#define HFI_PROP_FENCE_DIRECTION 0x0300019E
|
||||
|
||||
#define HFI_PROP_FENCE_ERROR_DATA_CORRUPT 0x0300019F
|
||||
|
||||
#define HFI_PROP_END 0x03FFFFFF
|
||||
|
||||
#define HFI_SESSION_ERROR_BEGIN 0x04000000
|
||||
|
||||
#define HFI_ERROR_UNKNOWN_SESSION 0x04000001
|
||||
|
||||
#define HFI_ERROR_MAX_SESSIONS 0x04000002
|
||||
|
||||
#define HFI_ERROR_FATAL 0x04000003
|
||||
|
||||
#define HFI_ERROR_INVALID_STATE 0x04000004
|
||||
|
||||
#define HFI_ERROR_INSUFFICIENT_RESOURCES 0x04000005
|
||||
|
||||
#define HFI_ERROR_BUFFER_NOT_SET 0x04000006
|
||||
|
||||
#define HFI_ERROR_DRAP_CONFIG_EXCEED 0x04000007
|
||||
|
||||
#define HFI_SESSION_ERROR_END 0x04FFFFFF
|
||||
|
||||
#define HFI_SYSTEM_ERROR_BEGIN 0x05000000
|
||||
|
||||
#define HFI_SYS_ERROR_WD_TIMEOUT 0x05000001
|
||||
|
||||
#define HFI_SYS_ERROR_NOC 0x05000002
|
||||
|
||||
#define HFI_SYS_ERROR_FATAL 0x05000003
|
||||
|
||||
#define HFI_SYSTEM_ERROR_END 0x05FFFFFF
|
||||
|
||||
#define HFI_INFORMATION_BEGIN 0x06000000
|
||||
|
||||
#define HFI_INFO_UNSUPPORTED 0x06000001
|
||||
|
||||
#define HFI_INFO_DATA_CORRUPT 0x06000002
|
||||
|
||||
#define HFI_INFO_NEGATIVE_TIMESTAMP 0x06000003
|
||||
|
||||
#define HFI_INFO_BUFFER_OVERFLOW 0x06000004
|
||||
|
||||
#define HFI_INFO_VCODEC_RESET 0x06000005
|
||||
|
||||
#define HFI_INFO_HFI_FLAG_DRAIN_LAST 0x06000006
|
||||
|
||||
#define HFI_INFO_HFI_FLAG_PSC_LAST 0x06000007
|
||||
|
||||
#define HFI_INFO_FENCE_SIGNAL_ERROR 0x06000008
|
||||
|
||||
#define HFI_INFORMATION_END 0x06FFFFFF
|
||||
|
||||
#endif //__H_HFI_PROPERTY_H__
|
612
qcom/opensource/video-driver/driver/vidc/inc/msm_media_info.h
Normal file
612
qcom/opensource/video-driver/driver/vidc/inc/msm_media_info.h
Normal file
@ -0,0 +1,612 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __MSM_MEDIA_INFO_H__
|
||||
#define __MSM_MEDIA_INFO_H__
|
||||
|
||||
#include "msm_vidc_internal.h"
|
||||
|
||||
/* Width and Height should be multiple of 16 */
|
||||
#define INTERLACE_WIDTH_MAX 1920
|
||||
#define INTERLACE_HEIGHT_MAX 1920
|
||||
#define INTERLACE_MB_PER_FRAME_MAX ((1920 * 1088) / 256)
|
||||
|
||||
#ifndef MSM_MEDIA_ALIGN
|
||||
#define MSM_MEDIA_ALIGN(__sz, __align) (((__align) & ((__align) - 1)) ?\
|
||||
((((__sz) + (__align) - 1) / (__align)) * (__align)) :\
|
||||
(((__sz) + (__align) - 1) & (~((__align) - 1))))
|
||||
#endif
|
||||
|
||||
#ifndef MSM_MEDIA_ROUNDUP
|
||||
#define MSM_MEDIA_ROUNDUP(__sz, __r) (((__sz) + ((__r) - 1)) / (__r))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Function arguments:
|
||||
* @v4l2_fmt
|
||||
* @width
|
||||
* Progressive: width
|
||||
* Interlaced: width
|
||||
*/
|
||||
static inline unsigned int video_y_stride_bytes(unsigned int colorformat,
|
||||
unsigned int width)
|
||||
{
|
||||
unsigned int alignment, stride = 0;
|
||||
|
||||
if (!width)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_NV12:
|
||||
case MSM_VIDC_FMT_NV21:
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
alignment = 128;
|
||||
stride = MSM_MEDIA_ALIGN(width, alignment);
|
||||
break;
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
alignment = 256;
|
||||
stride = MSM_MEDIA_ALIGN(width, 192);
|
||||
stride = MSM_MEDIA_ALIGN(stride * 4 / 3, alignment);
|
||||
break;
|
||||
case MSM_VIDC_FMT_P010:
|
||||
alignment = 256;
|
||||
stride = MSM_MEDIA_ALIGN(width * 2, alignment);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
invalid_input:
|
||||
return stride;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function arguments:
|
||||
* @v4l2_fmt
|
||||
* @width
|
||||
* Progressive: width
|
||||
* Interlaced: width
|
||||
*/
|
||||
static inline unsigned int video_y_stride_pix(unsigned int colorformat,
|
||||
unsigned int width)
|
||||
{
|
||||
unsigned int alignment, stride = 0;
|
||||
|
||||
if (!width)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_NV12:
|
||||
case MSM_VIDC_FMT_NV21:
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
case MSM_VIDC_FMT_P010:
|
||||
alignment = 128;
|
||||
stride = MSM_MEDIA_ALIGN(width, alignment);
|
||||
break;
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
alignment = 192;
|
||||
stride = MSM_MEDIA_ALIGN(width, alignment);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
invalid_input:
|
||||
return stride;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function arguments:
|
||||
* @v4l2_fmt
|
||||
* @width
|
||||
* Progressive: width
|
||||
* Interlaced: width
|
||||
*/
|
||||
static inline unsigned int video_uv_stride_bytes(unsigned int colorformat,
|
||||
unsigned int width)
|
||||
{
|
||||
unsigned int alignment, stride = 0;
|
||||
|
||||
if (!width)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_NV21:
|
||||
case MSM_VIDC_FMT_NV12:
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
alignment = 128;
|
||||
stride = MSM_MEDIA_ALIGN(width, alignment);
|
||||
break;
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
alignment = 256;
|
||||
stride = MSM_MEDIA_ALIGN(width, 192);
|
||||
stride = MSM_MEDIA_ALIGN(stride * 4 / 3, alignment);
|
||||
break;
|
||||
case MSM_VIDC_FMT_P010:
|
||||
alignment = 256;
|
||||
stride = MSM_MEDIA_ALIGN(width * 2, alignment);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
invalid_input:
|
||||
return stride;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function arguments:
|
||||
* @v4l2_fmt
|
||||
* @width
|
||||
* Progressive: width
|
||||
* Interlaced: width
|
||||
*/
|
||||
static inline unsigned int video_uv_stride_pix(unsigned int colorformat,
|
||||
unsigned int width)
|
||||
{
|
||||
unsigned int alignment, stride = 0;
|
||||
|
||||
if (!width)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_NV21:
|
||||
case MSM_VIDC_FMT_NV12:
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
case MSM_VIDC_FMT_P010:
|
||||
alignment = 128;
|
||||
stride = MSM_MEDIA_ALIGN(width, alignment);
|
||||
break;
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
alignment = 192;
|
||||
stride = MSM_MEDIA_ALIGN(width, alignment);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
invalid_input:
|
||||
return stride;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function arguments:
|
||||
* @v4l2_fmt
|
||||
* @height
|
||||
* Progressive: height
|
||||
* Interlaced: (height+1)>>1
|
||||
*/
|
||||
static inline unsigned int video_y_scanlines(unsigned int colorformat,
|
||||
unsigned int height)
|
||||
{
|
||||
unsigned int alignment, sclines = 0;
|
||||
|
||||
if (!height)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_NV12:
|
||||
case MSM_VIDC_FMT_NV21:
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
case MSM_VIDC_FMT_P010:
|
||||
alignment = 32;
|
||||
break;
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
alignment = 16;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
sclines = MSM_MEDIA_ALIGN(height, alignment);
|
||||
invalid_input:
|
||||
return sclines;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function arguments:
|
||||
* @v4l2_fmt
|
||||
* @height
|
||||
* Progressive: height
|
||||
* Interlaced: (height+1)>>1
|
||||
*/
|
||||
static inline unsigned int video_uv_scanlines(unsigned int colorformat,
|
||||
unsigned int height)
|
||||
{
|
||||
unsigned int alignment, sclines = 0;
|
||||
|
||||
if (!height)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_NV21:
|
||||
case MSM_VIDC_FMT_NV12:
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
case MSM_VIDC_FMT_P010:
|
||||
alignment = 16;
|
||||
break;
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
alignment = 32;
|
||||
break;
|
||||
default:
|
||||
goto invalid_input;
|
||||
}
|
||||
|
||||
sclines = MSM_MEDIA_ALIGN((height + 1) >> 1, alignment);
|
||||
|
||||
invalid_input:
|
||||
return sclines;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function arguments:
|
||||
* @v4l2_fmt
|
||||
* @width
|
||||
* Progressive: width
|
||||
* Interlaced: width
|
||||
*/
|
||||
static inline unsigned int video_y_meta_stride(unsigned int colorformat,
|
||||
unsigned int width)
|
||||
{
|
||||
int y_tile_width = 0, y_meta_stride = 0;
|
||||
|
||||
if (!width)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
y_tile_width = 32;
|
||||
break;
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
y_tile_width = 48;
|
||||
break;
|
||||
default:
|
||||
goto invalid_input;
|
||||
}
|
||||
|
||||
y_meta_stride = MSM_MEDIA_ROUNDUP(width, y_tile_width);
|
||||
y_meta_stride = MSM_MEDIA_ALIGN(y_meta_stride, 64);
|
||||
|
||||
invalid_input:
|
||||
return y_meta_stride;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function arguments:
|
||||
* @v4l2_fmt
|
||||
* @height
|
||||
* Progressive: height
|
||||
* Interlaced: (height+1)>>1
|
||||
*/
|
||||
static inline unsigned int video_y_meta_scanlines(unsigned int colorformat,
|
||||
unsigned int height)
|
||||
{
|
||||
int y_tile_height = 0, y_meta_scanlines = 0;
|
||||
|
||||
if (!height)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
y_tile_height = 8;
|
||||
break;
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
y_tile_height = 4;
|
||||
break;
|
||||
default:
|
||||
goto invalid_input;
|
||||
}
|
||||
|
||||
y_meta_scanlines = MSM_MEDIA_ROUNDUP(height, y_tile_height);
|
||||
y_meta_scanlines = MSM_MEDIA_ALIGN(y_meta_scanlines, 16);
|
||||
|
||||
invalid_input:
|
||||
return y_meta_scanlines;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function arguments:
|
||||
* @v4l2_fmt
|
||||
* @width
|
||||
* Progressive: width
|
||||
* Interlaced: width
|
||||
*/
|
||||
static inline unsigned int video_uv_meta_stride(unsigned int colorformat,
|
||||
unsigned int width)
|
||||
{
|
||||
int uv_tile_width = 0, uv_meta_stride = 0;
|
||||
|
||||
if (!width)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
uv_tile_width = 16;
|
||||
break;
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
uv_tile_width = 24;
|
||||
break;
|
||||
default:
|
||||
goto invalid_input;
|
||||
}
|
||||
|
||||
uv_meta_stride = MSM_MEDIA_ROUNDUP((width + 1) >> 1, uv_tile_width);
|
||||
uv_meta_stride = MSM_MEDIA_ALIGN(uv_meta_stride, 64);
|
||||
|
||||
invalid_input:
|
||||
return uv_meta_stride;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function arguments:
|
||||
* @v4l2_fmt
|
||||
* @height
|
||||
* Progressive: height
|
||||
* Interlaced: (height+1)>>1
|
||||
*/
|
||||
static inline unsigned int video_uv_meta_scanlines(unsigned int colorformat,
|
||||
unsigned int height)
|
||||
{
|
||||
int uv_tile_height = 0, uv_meta_scanlines = 0;
|
||||
|
||||
if (!height)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
uv_tile_height = 8;
|
||||
break;
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
uv_tile_height = 4;
|
||||
break;
|
||||
default:
|
||||
goto invalid_input;
|
||||
}
|
||||
|
||||
uv_meta_scanlines = MSM_MEDIA_ROUNDUP((height + 1) >> 1, uv_tile_height);
|
||||
uv_meta_scanlines = MSM_MEDIA_ALIGN(uv_meta_scanlines, 16);
|
||||
|
||||
invalid_input:
|
||||
return uv_meta_scanlines;
|
||||
}
|
||||
|
||||
static inline unsigned int video_rgb_stride_bytes(unsigned int colorformat,
|
||||
unsigned int width)
|
||||
{
|
||||
unsigned int alignment = 0, stride = 0, bpp = 4;
|
||||
|
||||
if (!width)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_RGBA8888C:
|
||||
case MSM_VIDC_FMT_RGBA8888:
|
||||
alignment = 256;
|
||||
break;
|
||||
default:
|
||||
goto invalid_input;
|
||||
}
|
||||
|
||||
stride = MSM_MEDIA_ALIGN(width * bpp, alignment);
|
||||
|
||||
invalid_input:
|
||||
return stride;
|
||||
}
|
||||
|
||||
static inline unsigned int video_rgb_stride_pix(unsigned int colorformat,
|
||||
unsigned int width)
|
||||
{
|
||||
unsigned int bpp = 4;
|
||||
|
||||
return video_rgb_stride_bytes(colorformat, width) / bpp;
|
||||
}
|
||||
|
||||
static inline unsigned int video_rgb_scanlines(unsigned int colorformat,
|
||||
unsigned int height)
|
||||
{
|
||||
unsigned int alignment = 0, scanlines = 0;
|
||||
|
||||
if (!height)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_RGBA8888C:
|
||||
alignment = 16;
|
||||
break;
|
||||
case MSM_VIDC_FMT_RGBA8888:
|
||||
alignment = 32;
|
||||
break;
|
||||
default:
|
||||
goto invalid_input;
|
||||
}
|
||||
|
||||
scanlines = MSM_MEDIA_ALIGN(height, alignment);
|
||||
|
||||
invalid_input:
|
||||
return scanlines;
|
||||
}
|
||||
|
||||
static inline unsigned int video_rgb_meta_stride(unsigned int colorformat,
|
||||
unsigned int width)
|
||||
{
|
||||
int rgb_tile_width = 0, rgb_meta_stride = 0;
|
||||
|
||||
if (!width)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_RGBA8888C:
|
||||
case MSM_VIDC_FMT_RGBA8888:
|
||||
rgb_tile_width = 16;
|
||||
break;
|
||||
default:
|
||||
goto invalid_input;
|
||||
}
|
||||
|
||||
rgb_meta_stride = MSM_MEDIA_ROUNDUP(width, rgb_tile_width);
|
||||
rgb_meta_stride = MSM_MEDIA_ALIGN(rgb_meta_stride, 64);
|
||||
|
||||
invalid_input:
|
||||
return rgb_meta_stride;
|
||||
}
|
||||
|
||||
static inline unsigned int video_rgb_meta_scanlines(unsigned int colorformat,
|
||||
unsigned int height)
|
||||
{
|
||||
int rgb_tile_height = 0, rgb_meta_scanlines = 0;
|
||||
|
||||
if (!height)
|
||||
goto invalid_input;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_RGBA8888C:
|
||||
case MSM_VIDC_FMT_RGBA8888:
|
||||
rgb_tile_height = 4;
|
||||
break;
|
||||
default:
|
||||
goto invalid_input;
|
||||
}
|
||||
|
||||
rgb_meta_scanlines = MSM_MEDIA_ROUNDUP(height, rgb_tile_height);
|
||||
rgb_meta_scanlines = MSM_MEDIA_ALIGN(rgb_meta_scanlines, 16);
|
||||
|
||||
invalid_input:
|
||||
return rgb_meta_scanlines;
|
||||
}
|
||||
|
||||
static inline unsigned int video_buffer_size(unsigned int colorformat,
|
||||
unsigned int pix_width,
|
||||
unsigned int pix_height,
|
||||
unsigned int interlace)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
unsigned int y_plane, uv_plane, y_stride,
|
||||
uv_stride, y_sclines, uv_sclines;
|
||||
unsigned int y_ubwc_plane = 0, uv_ubwc_plane = 0;
|
||||
unsigned int y_meta_stride = 0, y_meta_scanlines = 0;
|
||||
unsigned int uv_meta_stride = 0, uv_meta_scanlines = 0;
|
||||
unsigned int y_meta_plane = 0, uv_meta_plane = 0;
|
||||
unsigned int rgb_stride = 0, rgb_scanlines = 0;
|
||||
unsigned int rgb_plane = 0, rgb_ubwc_plane = 0, rgb_meta_plane = 0;
|
||||
unsigned int rgb_meta_stride = 0, rgb_meta_scanlines = 0;
|
||||
|
||||
if (!pix_width || !pix_height)
|
||||
goto invalid_input;
|
||||
|
||||
y_stride = video_y_stride_bytes(colorformat, pix_width);
|
||||
uv_stride = video_uv_stride_bytes(colorformat, pix_width);
|
||||
y_sclines = video_y_scanlines(colorformat, pix_height);
|
||||
uv_sclines = video_uv_scanlines(colorformat, pix_height);
|
||||
rgb_stride = video_rgb_stride_bytes(colorformat, pix_width);
|
||||
rgb_scanlines = video_rgb_scanlines(colorformat, pix_height);
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_NV21:
|
||||
case MSM_VIDC_FMT_NV12:
|
||||
case MSM_VIDC_FMT_P010:
|
||||
y_plane = y_stride * y_sclines;
|
||||
uv_plane = uv_stride * uv_sclines;
|
||||
size = y_plane + uv_plane;
|
||||
break;
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
y_meta_stride = video_y_meta_stride(colorformat, pix_width);
|
||||
uv_meta_stride = video_uv_meta_stride(colorformat, pix_width);
|
||||
if (!interlace && colorformat == MSM_VIDC_FMT_NV12C) {
|
||||
y_ubwc_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
|
||||
uv_ubwc_plane = MSM_MEDIA_ALIGN(uv_stride * uv_sclines, 4096);
|
||||
y_meta_scanlines =
|
||||
video_y_meta_scanlines(colorformat, pix_height);
|
||||
y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride *
|
||||
y_meta_scanlines, 4096);
|
||||
uv_meta_scanlines =
|
||||
video_uv_meta_scanlines(colorformat, pix_height);
|
||||
uv_meta_plane = MSM_MEDIA_ALIGN(uv_meta_stride *
|
||||
uv_meta_scanlines,
|
||||
4096);
|
||||
size = (y_ubwc_plane + uv_ubwc_plane + y_meta_plane +
|
||||
uv_meta_plane);
|
||||
} else {
|
||||
if (pix_width <= INTERLACE_WIDTH_MAX &&
|
||||
pix_height <= INTERLACE_HEIGHT_MAX &&
|
||||
(pix_height * pix_width) / 256 <= INTERLACE_MB_PER_FRAME_MAX) {
|
||||
y_sclines =
|
||||
video_y_scanlines(colorformat, (pix_height + 1) >> 1);
|
||||
y_ubwc_plane =
|
||||
MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
|
||||
uv_sclines =
|
||||
video_uv_scanlines(colorformat, (pix_height + 1) >> 1);
|
||||
uv_ubwc_plane =
|
||||
MSM_MEDIA_ALIGN(uv_stride * uv_sclines, 4096);
|
||||
y_meta_scanlines =
|
||||
video_y_meta_scanlines(colorformat, (pix_height + 1) >> 1);
|
||||
y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride *
|
||||
y_meta_scanlines,
|
||||
4096);
|
||||
uv_meta_scanlines =
|
||||
video_uv_meta_scanlines(colorformat, (pix_height + 1) >> 1);
|
||||
uv_meta_plane = MSM_MEDIA_ALIGN(uv_meta_stride *
|
||||
uv_meta_scanlines,
|
||||
4096);
|
||||
size = (y_ubwc_plane + uv_ubwc_plane + y_meta_plane +
|
||||
uv_meta_plane)*2;
|
||||
} else {
|
||||
y_sclines = video_y_scanlines(colorformat, pix_height);
|
||||
y_ubwc_plane =
|
||||
MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
|
||||
uv_sclines = video_uv_scanlines(colorformat, pix_height);
|
||||
uv_ubwc_plane =
|
||||
MSM_MEDIA_ALIGN(uv_stride * uv_sclines, 4096);
|
||||
y_meta_scanlines =
|
||||
video_y_meta_scanlines(colorformat, pix_height);
|
||||
y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride *
|
||||
y_meta_scanlines,
|
||||
4096);
|
||||
uv_meta_scanlines =
|
||||
video_uv_meta_scanlines(colorformat, pix_height);
|
||||
uv_meta_plane = MSM_MEDIA_ALIGN(uv_meta_stride *
|
||||
uv_meta_scanlines,
|
||||
4096);
|
||||
size = (y_ubwc_plane + uv_ubwc_plane + y_meta_plane +
|
||||
uv_meta_plane);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
y_ubwc_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
|
||||
uv_ubwc_plane = MSM_MEDIA_ALIGN(uv_stride * uv_sclines, 4096);
|
||||
y_meta_stride = video_y_meta_stride(colorformat, pix_width);
|
||||
y_meta_scanlines = video_y_meta_scanlines(colorformat, pix_height);
|
||||
y_meta_plane = MSM_MEDIA_ALIGN(y_meta_stride *
|
||||
y_meta_scanlines, 4096);
|
||||
uv_meta_stride = video_uv_meta_stride(colorformat, pix_width);
|
||||
uv_meta_scanlines = video_uv_meta_scanlines(colorformat, pix_height);
|
||||
uv_meta_plane = MSM_MEDIA_ALIGN(uv_meta_stride *
|
||||
uv_meta_scanlines,
|
||||
4096);
|
||||
|
||||
size = y_ubwc_plane + uv_ubwc_plane + y_meta_plane +
|
||||
uv_meta_plane;
|
||||
break;
|
||||
case MSM_VIDC_FMT_RGBA8888C:
|
||||
rgb_ubwc_plane = MSM_MEDIA_ALIGN(rgb_stride * rgb_scanlines,
|
||||
4096);
|
||||
rgb_meta_stride = video_rgb_meta_stride(colorformat, pix_width);
|
||||
rgb_meta_scanlines = video_rgb_meta_scanlines(colorformat,
|
||||
pix_height);
|
||||
rgb_meta_plane = MSM_MEDIA_ALIGN(rgb_meta_stride *
|
||||
rgb_meta_scanlines, 4096);
|
||||
size = rgb_ubwc_plane + rgb_meta_plane;
|
||||
break;
|
||||
case MSM_VIDC_FMT_RGBA8888:
|
||||
rgb_plane = MSM_MEDIA_ALIGN(rgb_stride * rgb_scanlines, 4096);
|
||||
size = rgb_plane;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
invalid_input:
|
||||
size = MSM_MEDIA_ALIGN(size, 4096);
|
||||
return size;
|
||||
}
|
||||
|
||||
#endif
|
43
qcom/opensource/video-driver/driver/vidc/inc/msm_vdec.h
Normal file
43
qcom/opensource/video-driver/driver/vidc/inc/msm_vdec.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VDEC_H_
|
||||
#define _MSM_VDEC_H_
|
||||
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_core.h"
|
||||
|
||||
int msm_vdec_streamoff_input(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_streamon_input(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_streamoff_output(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_streamon_output(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
|
||||
int msm_vdec_try_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
|
||||
int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
|
||||
int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
|
||||
int msm_vdec_s_selection(struct msm_vidc_inst *inst, struct v4l2_selection *s);
|
||||
int msm_vdec_g_selection(struct msm_vidc_inst *inst, struct v4l2_selection *s);
|
||||
int msm_vdec_subscribe_event(struct msm_vidc_inst *inst,
|
||||
const struct v4l2_event_subscription *sub);
|
||||
int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f);
|
||||
int msm_vdec_inst_init(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_inst_deinit(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_init_input_subcr_params(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_stop_cmd(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_start_cmd(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_handle_release_buffer(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_buffer *buf);
|
||||
int msm_vdec_set_num_comv(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_subscribe_metadata(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_port_type port);
|
||||
int msm_vdec_get_input_internal_buffers(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_create_input_internal_buffers(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_queue_input_internal_buffers(struct msm_vidc_inst *inst);
|
||||
int msm_vdec_release_input_internal_buffers(struct msm_vidc_inst *inst);
|
||||
|
||||
#endif // _MSM_VDEC_H_
|
36
qcom/opensource/video-driver/driver/vidc/inc/msm_venc.h
Normal file
36
qcom/opensource/video-driver/driver/vidc/inc/msm_venc.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VENC_H_
|
||||
#define _MSM_VENC_H_
|
||||
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_core.h"
|
||||
|
||||
int msm_venc_streamoff_input(struct msm_vidc_inst *inst);
|
||||
int msm_venc_streamon_input(struct msm_vidc_inst *inst);
|
||||
int msm_venc_streamoff_output(struct msm_vidc_inst *inst);
|
||||
int msm_venc_streamon_output(struct msm_vidc_inst *inst);
|
||||
int msm_venc_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
|
||||
int msm_venc_stop_cmd(struct msm_vidc_inst *inst);
|
||||
int msm_venc_start_cmd(struct msm_vidc_inst *inst);
|
||||
int msm_venc_try_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
|
||||
int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
|
||||
int msm_venc_s_fmt_output(struct msm_vidc_inst *inst, struct v4l2_format *f);
|
||||
int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
|
||||
int msm_venc_s_selection(struct msm_vidc_inst *inst, struct v4l2_selection *s);
|
||||
int msm_venc_g_selection(struct msm_vidc_inst *inst, struct v4l2_selection *s);
|
||||
int msm_venc_s_param(struct msm_vidc_inst *inst,
|
||||
struct v4l2_streamparm *s_parm);
|
||||
int msm_venc_g_param(struct msm_vidc_inst *inst,
|
||||
struct v4l2_streamparm *s_parm);
|
||||
int msm_venc_subscribe_event(struct msm_vidc_inst *inst,
|
||||
const struct v4l2_event_subscription *sub);
|
||||
int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f);
|
||||
int msm_venc_inst_init(struct msm_vidc_inst *inst);
|
||||
int msm_venc_inst_deinit(struct msm_vidc_inst *inst);
|
||||
|
||||
#endif // _MSM_VENC_H_
|
57
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc.h
Normal file
57
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_H_
|
||||
#define _MSM_VIDC_H_
|
||||
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/media-device.h>
|
||||
|
||||
union msm_v4l2_cmd {
|
||||
struct v4l2_decoder_cmd dec;
|
||||
struct v4l2_encoder_cmd enc;
|
||||
};
|
||||
|
||||
void *msm_vidc_open(struct msm_vidc_core *core, u32 session_type);
|
||||
int msm_vidc_close(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_querycap(struct msm_vidc_inst *inst, struct v4l2_capability *cap);
|
||||
int msm_vidc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f);
|
||||
int msm_vidc_try_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
|
||||
int msm_vidc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
|
||||
int msm_vidc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
|
||||
int msm_vidc_s_selection(struct msm_vidc_inst *inst, struct v4l2_selection *s);
|
||||
int msm_vidc_g_selection(struct msm_vidc_inst *inst, struct v4l2_selection *s);
|
||||
int msm_vidc_s_param(struct msm_vidc_inst *inst, struct v4l2_streamparm *sp);
|
||||
int msm_vidc_g_param(struct msm_vidc_inst *inst, struct v4l2_streamparm *sp);
|
||||
int msm_vidc_reqbufs(struct msm_vidc_inst *inst, struct v4l2_requestbuffers *b);
|
||||
int msm_vidc_querybuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b);
|
||||
int msm_vidc_create_bufs(struct msm_vidc_inst *inst, struct v4l2_create_buffers *b);
|
||||
int msm_vidc_prepare_buf(struct msm_vidc_inst *inst, struct media_device *mdev,
|
||||
struct v4l2_buffer *b);
|
||||
int msm_vidc_release_buffer(struct msm_vidc_inst *inst, int buffer_type,
|
||||
unsigned int buffer_index);
|
||||
int msm_vidc_qbuf(struct msm_vidc_inst *inst, struct media_device *mdev,
|
||||
struct v4l2_buffer *b);
|
||||
int msm_vidc_dqbuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b);
|
||||
int msm_vidc_streamon(struct msm_vidc_inst *inst, enum v4l2_buf_type i);
|
||||
int msm_vidc_query_ctrl(struct msm_vidc_inst *inst, struct v4l2_queryctrl *ctrl);
|
||||
int msm_vidc_query_menu(struct msm_vidc_inst *inst, struct v4l2_querymenu *qmenu);
|
||||
int msm_vidc_streamoff(struct msm_vidc_inst *inst, enum v4l2_buf_type i);
|
||||
int msm_vidc_try_cmd(struct msm_vidc_inst *inst, union msm_v4l2_cmd *cmd);
|
||||
int msm_vidc_start_cmd(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_stop_cmd(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_poll(struct msm_vidc_inst *inst, struct file *filp,
|
||||
struct poll_table_struct *pt);
|
||||
int msm_vidc_subscribe_event(struct msm_vidc_inst *inst,
|
||||
const struct v4l2_event_subscription *sub);
|
||||
int msm_vidc_unsubscribe_event(struct msm_vidc_inst *inst,
|
||||
const struct v4l2_event_subscription *sub);
|
||||
int msm_vidc_dqevent(struct msm_vidc_inst *inst, struct v4l2_event *event);
|
||||
int msm_vidc_g_crop(struct msm_vidc_inst *inst, struct v4l2_crop *a);
|
||||
int msm_vidc_enum_framesizes(struct msm_vidc_inst *inst, struct v4l2_frmsizeenum *fsize);
|
||||
int msm_vidc_enum_frameintervals(struct msm_vidc_inst *inst, struct v4l2_frmivalenum *fival);
|
||||
|
||||
#endif
|
@ -0,0 +1,38 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __H_MSM_VIDC_BUFFER_H__
|
||||
#define __H_MSM_VIDC_BUFFER_H__
|
||||
|
||||
#include "msm_vidc_inst.h"
|
||||
|
||||
#define MIN_DEC_INPUT_BUFFERS 4
|
||||
#define MIN_DEC_OUTPUT_BUFFERS 4
|
||||
|
||||
#define MIN_ENC_INPUT_BUFFERS 4
|
||||
#define MIN_ENC_OUTPUT_BUFFERS 4
|
||||
|
||||
#define DCVS_ENC_EXTRA_INPUT_BUFFERS 4
|
||||
#define DCVS_DEC_EXTRA_OUTPUT_BUFFERS 4
|
||||
|
||||
u32 msm_vidc_input_min_count(struct msm_vidc_inst *inst);
|
||||
u32 msm_vidc_output_min_count(struct msm_vidc_inst *inst);
|
||||
u32 msm_vidc_input_extra_count(struct msm_vidc_inst *inst);
|
||||
u32 msm_vidc_output_extra_count(struct msm_vidc_inst *inst);
|
||||
u32 msm_vidc_internal_buffer_count(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
u32 msm_vidc_decoder_input_size(struct msm_vidc_inst *inst);
|
||||
u32 msm_vidc_decoder_output_size(struct msm_vidc_inst *inst);
|
||||
u32 msm_vidc_decoder_input_meta_size(struct msm_vidc_inst *inst);
|
||||
u32 msm_vidc_decoder_output_meta_size(struct msm_vidc_inst *inst);
|
||||
u32 msm_vidc_encoder_input_size(struct msm_vidc_inst *inst);
|
||||
u32 msm_vidc_encoder_output_size(struct msm_vidc_inst *inst);
|
||||
u32 msm_vidc_encoder_input_meta_size(struct msm_vidc_inst *inst);
|
||||
u32 msm_vidc_encoder_output_meta_size(struct msm_vidc_inst *inst);
|
||||
u32 msm_vidc_enc_delivery_mode_based_output_buf_size(struct msm_vidc_inst *inst,
|
||||
u32 frame_size);
|
||||
|
||||
#endif // __H_MSM_VIDC_BUFFER_H__
|
@ -0,0 +1,26 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_CONTROL_H_
|
||||
#define _MSM_VIDC_CONTROL_H_
|
||||
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
|
||||
int msm_vidc_ctrl_handler_init(struct msm_vidc_inst *inst, bool init);
|
||||
int msm_vidc_ctrl_handler_deinit(struct msm_vidc_inst *inst);
|
||||
int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl);
|
||||
int msm_v4l2_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_s_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl);
|
||||
int msm_vidc_prepare_dependency_list(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_adjust_v4l2_properties(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_set_v4l2_properties(struct msm_vidc_inst *inst);
|
||||
bool is_valid_cap_id(enum msm_vidc_inst_capability_type cap_id);
|
||||
bool is_valid_cap(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_inst_capability_type cap_id);
|
||||
enum msm_vidc_inst_capability_type
|
||||
msm_vidc_get_cap_id(struct msm_vidc_inst *inst, u32 id);
|
||||
#endif
|
131
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_core.h
Normal file
131
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_core.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_CORE_H_
|
||||
#define _MSM_VIDC_CORE_H_
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_state.h"
|
||||
#include "venus_hfi_queue.h"
|
||||
#include "resources.h"
|
||||
|
||||
struct msm_vidc_core;
|
||||
|
||||
#define MAX_EVENTS 30
|
||||
|
||||
#define call_venus_op(d, op, ...) \
|
||||
(((d) && (d)->venus_ops && (d)->venus_ops->op) ? \
|
||||
((d)->venus_ops->op(__VA_ARGS__)) : 0)
|
||||
|
||||
struct msm_vidc_venus_ops {
|
||||
int (*boot_firmware)(struct msm_vidc_core *core);
|
||||
int (*raise_interrupt)(struct msm_vidc_core *core);
|
||||
int (*clear_interrupt)(struct msm_vidc_core *core);
|
||||
int (*prepare_pc)(struct msm_vidc_core *core);
|
||||
int (*power_on)(struct msm_vidc_core *core);
|
||||
int (*power_off)(struct msm_vidc_core *core);
|
||||
int (*watchdog)(struct msm_vidc_core *core, u32 intr_status);
|
||||
int (*noc_error_info)(struct msm_vidc_core *core);
|
||||
};
|
||||
|
||||
struct msm_vidc_synx_fence_data {
|
||||
u32 client_id;
|
||||
void *session;
|
||||
u32 client_flags; /* not used */
|
||||
struct msm_vidc_mem queue;
|
||||
};
|
||||
|
||||
struct msm_vidc_mem_addr {
|
||||
u32 align_device_addr;
|
||||
u8 *align_virtual_addr;
|
||||
u32 mem_size;
|
||||
struct msm_vidc_mem mem;
|
||||
};
|
||||
|
||||
struct msm_vidc_iface_q_info {
|
||||
void *q_hdr;
|
||||
struct msm_vidc_mem_addr q_array;
|
||||
};
|
||||
|
||||
struct msm_video_device {
|
||||
enum msm_vidc_domain_type type;
|
||||
struct video_device vdev;
|
||||
struct v4l2_m2m_dev *m2m_dev;
|
||||
};
|
||||
|
||||
struct msm_vidc_core_power {
|
||||
u64 clk_freq;
|
||||
u64 bw_ddr;
|
||||
u64 bw_llcc;
|
||||
};
|
||||
|
||||
struct msm_vidc_core {
|
||||
struct platform_device *pdev;
|
||||
struct msm_video_device vdev[2];
|
||||
struct v4l2_device v4l2_dev;
|
||||
struct media_device media_dev;
|
||||
struct list_head instances;
|
||||
struct list_head dangling_instances;
|
||||
struct dentry *debugfs_parent;
|
||||
struct dentry *debugfs_root;
|
||||
char fw_version[MAX_NAME_LENGTH];
|
||||
enum msm_vidc_core_state state;
|
||||
int (*state_handle)(struct msm_vidc_core *core,
|
||||
enum msm_vidc_core_event_type type,
|
||||
struct msm_vidc_event_data *data);
|
||||
enum msm_vidc_core_sub_state sub_state;
|
||||
char sub_state_name[MAX_NAME_LENGTH];
|
||||
struct mutex lock;
|
||||
struct msm_vidc_resource *resource;
|
||||
struct msm_vidc_platform *platform;
|
||||
u32 intr_status;
|
||||
u32 spur_count;
|
||||
u32 reg_count;
|
||||
u32 enc_codecs_count;
|
||||
u32 dec_codecs_count;
|
||||
struct msm_vidc_core_capability capabilities[CORE_CAP_MAX + 1];
|
||||
struct msm_vidc_inst_capability *inst_caps;
|
||||
struct msm_vidc_mem_addr sfr;
|
||||
struct msm_vidc_mem_addr iface_q_table;
|
||||
struct msm_vidc_mem_addr mmap_buf;
|
||||
struct msm_vidc_mem_addr aon_reg;
|
||||
struct msm_vidc_mem_addr fence_reg;
|
||||
struct msm_vidc_mem_addr qtimer_reg;
|
||||
struct msm_vidc_iface_q_info iface_queues[VIDC_IFACEQ_NUMQ];
|
||||
struct delayed_work pm_work;
|
||||
struct workqueue_struct *pm_workq;
|
||||
struct workqueue_struct *batch_workq;
|
||||
struct delayed_work fw_unload_work;
|
||||
struct work_struct ssr_work;
|
||||
struct msm_vidc_core_power power;
|
||||
struct msm_vidc_ssr ssr;
|
||||
u32 skip_pc_count;
|
||||
u32 last_packet_type;
|
||||
u8 *packet;
|
||||
u32 packet_size;
|
||||
u8 *response_packet;
|
||||
struct v4l2_file_operations *v4l2_file_ops;
|
||||
struct v4l2_ioctl_ops *v4l2_ioctl_ops_enc;
|
||||
struct v4l2_ioctl_ops *v4l2_ioctl_ops_dec;
|
||||
struct v4l2_ctrl_ops *v4l2_ctrl_ops;
|
||||
struct vb2_ops *vb2_ops;
|
||||
struct vb2_mem_ops *vb2_mem_ops;
|
||||
struct v4l2_m2m_ops *v4l2_m2m_ops;
|
||||
struct msm_vidc_venus_ops *venus_ops;
|
||||
const struct msm_vidc_resources_ops *res_ops;
|
||||
struct msm_vidc_session_ops *session_ops;
|
||||
const struct msm_vidc_memory_ops *mem_ops;
|
||||
struct media_device_ops *media_device_ops;
|
||||
const struct msm_vidc_fence_ops *fence_ops;
|
||||
u32 header_id;
|
||||
u32 packet_id;
|
||||
u32 sys_init_id;
|
||||
struct msm_vidc_synx_fence_data synx_fence_data;
|
||||
};
|
||||
|
||||
#endif // _MSM_VIDC_CORE_H_
|
206
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_debug.h
Normal file
206
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_debug.h
Normal file
@ -0,0 +1,206 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __MSM_VIDC_DEBUG__
|
||||
#define __MSM_VIDC_DEBUG__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
struct msm_vidc_core;
|
||||
struct msm_vidc_inst;
|
||||
|
||||
#ifndef VIDC_DBG_LABEL
|
||||
#define VIDC_DBG_LABEL "msm_vidc"
|
||||
#endif
|
||||
|
||||
/* Allow only 6 prints/sec */
|
||||
#define VIDC_DBG_SESSION_RATELIMIT_INTERVAL (1 * HZ)
|
||||
#define VIDC_DBG_SESSION_RATELIMIT_BURST 6
|
||||
|
||||
#define VIDC_DBG_TAG_INST VIDC_DBG_LABEL ": %4s: %s: "
|
||||
#define VIDC_DBG_TAG_CORE VIDC_DBG_LABEL ": %4s: %08x: %s: "
|
||||
#define FW_DBG_TAG VIDC_DBG_LABEL ": %6s: "
|
||||
#define DEFAULT_SID ((u32)-1)
|
||||
|
||||
#ifndef MSM_VIDC_EMPTY_BRACE
|
||||
#define MSM_VIDC_EMPTY_BRACE {},
|
||||
#endif
|
||||
|
||||
extern unsigned int msm_vidc_debug;
|
||||
extern unsigned int msm_fw_debug;
|
||||
extern bool msm_vidc_lossless_encode;
|
||||
extern bool msm_vidc_syscache_disable;
|
||||
extern int msm_vidc_clock_voting;
|
||||
extern int msm_vidc_ddr_bw;
|
||||
extern int msm_vidc_llc_bw;
|
||||
extern bool msm_vidc_fw_dump;
|
||||
extern unsigned int msm_vidc_enable_bugon;
|
||||
extern bool msm_vidc_synx_fence_enable;
|
||||
|
||||
/* do not modify the log message as it is used in test scripts */
|
||||
#define FMT_STRING_SET_CTRL \
|
||||
"%s: state %s, name %s, id 0x%x value %d\n"
|
||||
#define FMT_STRING_STATE_CHANGE \
|
||||
"%s: state changed to %s from %s\n"
|
||||
#define FMT_STRING_MSG_SFR \
|
||||
"SFR Message from FW: %s\n"
|
||||
#define FMT_STRING_FAULT_HANDLER \
|
||||
"%s: faulting address: %lx\n"
|
||||
#define FMT_STRING_SET_CAP \
|
||||
"set cap: name: %24s, cap value: %#10x, hfi: %#10llx\n"
|
||||
#define FMT_STRING_SYSTEM_ERROR \
|
||||
"%s: system error received\n"
|
||||
#define FMT_STRING_BOOT_FIRMWARE_ERROR \
|
||||
"Error booting up vidc firmware, ctrl status %#x, ctrl init %#x\n"
|
||||
|
||||
/* To enable messages OR these values and
|
||||
* echo the result to debugfs file.
|
||||
*
|
||||
* To enable all messages set msm_vidc_debug = 0x101F
|
||||
*/
|
||||
|
||||
enum vidc_msg_prio_drv {
|
||||
VIDC_ERR = 0x00000001,
|
||||
VIDC_HIGH = 0x00000002,
|
||||
VIDC_LOW = 0x00000004,
|
||||
VIDC_PERF = 0x00000008,
|
||||
VIDC_PKT = 0x00000010,
|
||||
VIDC_BUS = 0x00000020,
|
||||
VIDC_STAT = 0x00000040,
|
||||
VIDC_ENCODER = 0x00000100,
|
||||
VIDC_DECODER = 0x00000200,
|
||||
VIDC_PRINTK = 0x10000000,
|
||||
VIDC_FTRACE = 0x20000000,
|
||||
};
|
||||
|
||||
enum vidc_msg_prio_fw {
|
||||
FW_LOW = 0x00000001,
|
||||
FW_MED = 0x00000002,
|
||||
FW_HIGH = 0x00000004,
|
||||
FW_ERROR = 0x00000008,
|
||||
FW_FATAL = 0x00000010,
|
||||
FW_PERF = 0x00000020,
|
||||
FW_CACHE_LOW = 0x00000100,
|
||||
FW_CACHE_MED = 0x00000200,
|
||||
FW_CACHE_HIGH = 0x00000400,
|
||||
FW_CACHE_ERROR = 0x00000800,
|
||||
FW_CACHE_FATAL = 0x00001000,
|
||||
FW_CACHE_PERF = 0x00002000,
|
||||
FW_PRINTK = 0x10000000,
|
||||
FW_FTRACE = 0x20000000,
|
||||
};
|
||||
|
||||
#define DRV_LOG (VIDC_ERR | VIDC_PRINTK)
|
||||
#define DRV_LOGSHIFT (0)
|
||||
#define DRV_LOGMASK (0x0FFFFFFF)
|
||||
|
||||
#define FW_LOG (FW_ERROR | FW_FATAL | FW_PRINTK)
|
||||
#define FW_LOGSHIFT (0)
|
||||
#define FW_LOGMASK (0x0FFFFFFF)
|
||||
|
||||
#define dprintk_inst(__level, __level_str, inst, __fmt, ...) \
|
||||
do { \
|
||||
if (inst && (msm_vidc_debug & (__level))) { \
|
||||
pr_info(VIDC_DBG_TAG_INST __fmt, \
|
||||
__level_str, \
|
||||
inst->debug_str, \
|
||||
##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define i_vpr_e(inst, __fmt, ...) dprintk_inst(VIDC_ERR, "err ", inst, __fmt, ##__VA_ARGS__)
|
||||
#define i_vpr_i(inst, __fmt, ...) dprintk_inst(VIDC_HIGH, "high", inst, __fmt, ##__VA_ARGS__)
|
||||
#define i_vpr_h(inst, __fmt, ...) dprintk_inst(VIDC_HIGH, "high", inst, __fmt, ##__VA_ARGS__)
|
||||
#define i_vpr_l(inst, __fmt, ...) dprintk_inst(VIDC_LOW, "low ", inst, __fmt, ##__VA_ARGS__)
|
||||
#define i_vpr_p(inst, __fmt, ...) dprintk_inst(VIDC_PERF, "perf", inst, __fmt, ##__VA_ARGS__)
|
||||
#define i_vpr_t(inst, __fmt, ...) dprintk_inst(VIDC_PKT, "pkt ", inst, __fmt, ##__VA_ARGS__)
|
||||
#define i_vpr_b(inst, __fmt, ...) dprintk_inst(VIDC_BUS, "bus ", inst, __fmt, ##__VA_ARGS__)
|
||||
#define i_vpr_s(inst, __fmt, ...) dprintk_inst(VIDC_STAT, "stat", inst, __fmt, ##__VA_ARGS__)
|
||||
|
||||
#define i_vpr_hp(inst, __fmt, ...) \
|
||||
dprintk_inst(VIDC_HIGH | VIDC_PERF, "high", inst, __fmt, ##__VA_ARGS__)
|
||||
#define i_vpr_hs(inst, __fmt, ...) \
|
||||
dprintk_inst(VIDC_HIGH | VIDC_STAT, "stat", inst, __fmt, ##__VA_ARGS__)
|
||||
|
||||
#define dprintk_core(__level, __level_str, __fmt, ...) \
|
||||
do { \
|
||||
if (msm_vidc_debug & (__level)) { \
|
||||
pr_info(VIDC_DBG_TAG_CORE __fmt, \
|
||||
__level_str, \
|
||||
DEFAULT_SID, \
|
||||
"codec", \
|
||||
##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define d_vpr_e(__fmt, ...) dprintk_core(VIDC_ERR, "err ", __fmt, ##__VA_ARGS__)
|
||||
#define d_vpr_h(__fmt, ...) dprintk_core(VIDC_HIGH, "high", __fmt, ##__VA_ARGS__)
|
||||
#define d_vpr_l(__fmt, ...) dprintk_core(VIDC_LOW, "low ", __fmt, ##__VA_ARGS__)
|
||||
#define d_vpr_p(__fmt, ...) dprintk_core(VIDC_PERF, "perf", __fmt, ##__VA_ARGS__)
|
||||
#define d_vpr_t(__fmt, ...) dprintk_core(VIDC_PKT, "pkt ", __fmt, ##__VA_ARGS__)
|
||||
#define d_vpr_b(__fmt, ...) dprintk_core(VIDC_BUS, "bus ", __fmt, ##__VA_ARGS__)
|
||||
#define d_vpr_s(__fmt, ...) dprintk_core(VIDC_STAT, "stat", __fmt, ##__VA_ARGS__)
|
||||
#define d_vpr_hs(__fmt, ...) \
|
||||
dprintk_core(VIDC_HIGH | VIDC_STAT, "high", __fmt, ##__VA_ARGS__)
|
||||
|
||||
#define dprintk_ratelimit(__level, __level_str, __fmt, ...) \
|
||||
do { \
|
||||
if (msm_vidc_check_ratelimit()) { \
|
||||
dprintk_core(__level, __level_str, __fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define dprintk_firmware(__level, __fmt, ...) \
|
||||
do { \
|
||||
if ((msm_fw_debug & (__level)) & FW_PRINTK) { \
|
||||
pr_info(FW_DBG_TAG __fmt, \
|
||||
"fw", \
|
||||
##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define MSM_VIDC_FATAL(value) \
|
||||
do { \
|
||||
if (value) { \
|
||||
d_vpr_e("bug on\n"); \
|
||||
BUG_ON(value); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
enum msm_vidc_debugfs_event {
|
||||
MSM_VIDC_DEBUGFS_EVENT_ETB,
|
||||
MSM_VIDC_DEBUGFS_EVENT_EBD,
|
||||
MSM_VIDC_DEBUGFS_EVENT_FTB,
|
||||
MSM_VIDC_DEBUGFS_EVENT_FBD,
|
||||
};
|
||||
|
||||
enum msm_vidc_bug_on_error {
|
||||
MSM_VIDC_BUG_ON_FATAL = BIT(0),
|
||||
MSM_VIDC_BUG_ON_NOC = BIT(1),
|
||||
MSM_VIDC_BUG_ON_WD_TIMEOUT = BIT(2),
|
||||
};
|
||||
|
||||
struct dentry *msm_vidc_debugfs_init_drv(void);
|
||||
struct dentry *msm_vidc_debugfs_init_core(struct msm_vidc_core *core);
|
||||
struct dentry *msm_vidc_debugfs_init_inst(struct msm_vidc_inst *inst,
|
||||
struct dentry *parent);
|
||||
void msm_vidc_debugfs_deinit_inst(struct msm_vidc_inst *inst);
|
||||
void msm_vidc_debugfs_update(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_debugfs_event e);
|
||||
int msm_vidc_check_ratelimit(void);
|
||||
void msm_vidc_show_stats(struct msm_vidc_inst *inst);
|
||||
|
||||
static inline bool is_stats_enabled(void)
|
||||
{
|
||||
return !!(msm_vidc_debug & VIDC_STAT);
|
||||
}
|
||||
|
||||
#endif
|
630
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_driver.h
Normal file
630
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_driver.h
Normal file
@ -0,0 +1,630 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_DRIVER_H_
|
||||
#define _MSM_VIDC_DRIVER_H_
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/iommu.h>
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
|
||||
#define MSM_VIDC_SESSION_INACTIVE_THRESHOLD_MS 1000
|
||||
|
||||
enum msm_vidc_debugfs_event;
|
||||
|
||||
static inline bool is_decode_session(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return inst->domain == MSM_VIDC_DECODER;
|
||||
}
|
||||
|
||||
static inline bool is_encode_session(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return inst->domain == MSM_VIDC_ENCODER;
|
||||
}
|
||||
|
||||
static inline bool is_image_encode_session(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return inst->codec == MSM_VIDC_HEIC && inst->domain == MSM_VIDC_ENCODER;
|
||||
}
|
||||
|
||||
static inline bool is_image_decode_session(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return inst->codec == MSM_VIDC_HEIC && inst->domain == MSM_VIDC_DECODER;
|
||||
}
|
||||
|
||||
static inline bool is_image_session(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return inst->codec == MSM_VIDC_HEIC;
|
||||
}
|
||||
|
||||
static inline bool is_secure_session(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return !!(inst->capabilities[SECURE_MODE].value);
|
||||
}
|
||||
|
||||
static inline bool is_input_buffer(enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
return buffer_type == MSM_VIDC_BUF_INPUT;
|
||||
}
|
||||
|
||||
static inline bool is_output_buffer(enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
return buffer_type == MSM_VIDC_BUF_OUTPUT;
|
||||
}
|
||||
|
||||
static inline bool is_input_meta_buffer(enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
return buffer_type == MSM_VIDC_BUF_INPUT_META;
|
||||
}
|
||||
|
||||
static inline bool is_output_meta_buffer(enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
return buffer_type == MSM_VIDC_BUF_OUTPUT_META;
|
||||
}
|
||||
|
||||
static inline bool is_ts_reorder_allowed(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return !!(inst->capabilities[TS_REORDER].value &&
|
||||
is_decode_session(inst) && !is_image_session(inst));
|
||||
}
|
||||
|
||||
static inline bool is_scaling_enabled(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return inst->crop.left != inst->compose.left ||
|
||||
inst->crop.top != inst->compose.top ||
|
||||
inst->crop.width != inst->compose.width ||
|
||||
inst->crop.height != inst->compose.height;
|
||||
}
|
||||
|
||||
static inline bool is_rotation_90_or_270(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return inst->capabilities[ROTATION].value == 90 ||
|
||||
inst->capabilities[ROTATION].value == 270;
|
||||
}
|
||||
|
||||
static inline bool is_internal_buffer(enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
return buffer_type == MSM_VIDC_BUF_BIN ||
|
||||
buffer_type == MSM_VIDC_BUF_ARP ||
|
||||
buffer_type == MSM_VIDC_BUF_COMV ||
|
||||
buffer_type == MSM_VIDC_BUF_NON_COMV ||
|
||||
buffer_type == MSM_VIDC_BUF_LINE ||
|
||||
buffer_type == MSM_VIDC_BUF_DPB ||
|
||||
buffer_type == MSM_VIDC_BUF_PERSIST ||
|
||||
buffer_type == MSM_VIDC_BUF_VPSS ||
|
||||
buffer_type == MSM_VIDC_BUF_PARTIAL_DATA;
|
||||
}
|
||||
|
||||
static inline bool is_meta_cap(struct msm_vidc_inst *inst, u32 cap)
|
||||
{
|
||||
if (inst->capabilities[cap].flags & CAP_FLAG_META)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool is_meta_rx_inp_enabled(struct msm_vidc_inst *inst, u32 cap)
|
||||
{
|
||||
bool enabled = false;
|
||||
|
||||
if (!is_meta_cap(inst, cap))
|
||||
return false;
|
||||
|
||||
if (inst->capabilities[cap].value & MSM_VIDC_META_ENABLE &&
|
||||
inst->capabilities[cap].value & MSM_VIDC_META_RX_INPUT)
|
||||
enabled = true;
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static inline bool is_meta_rx_out_enabled(struct msm_vidc_inst *inst, u32 cap)
|
||||
{
|
||||
bool enabled = false;
|
||||
|
||||
if (!is_meta_cap(inst, cap))
|
||||
return false;
|
||||
|
||||
if (inst->capabilities[cap].value & MSM_VIDC_META_ENABLE &&
|
||||
inst->capabilities[cap].value & MSM_VIDC_META_RX_OUTPUT)
|
||||
enabled = true;
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static inline bool is_meta_tx_inp_enabled(struct msm_vidc_inst *inst, u32 cap)
|
||||
{
|
||||
bool enabled = false;
|
||||
|
||||
if (!is_meta_cap(inst, cap))
|
||||
return false;
|
||||
|
||||
if (inst->capabilities[cap].value & MSM_VIDC_META_ENABLE &&
|
||||
inst->capabilities[cap].value & MSM_VIDC_META_TX_INPUT)
|
||||
enabled = true;
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static inline bool is_dyn_meta_tx_inp_enabled(struct msm_vidc_inst *inst, u32 cap)
|
||||
{
|
||||
bool enabled = false;
|
||||
|
||||
if (!is_meta_cap(inst, cap))
|
||||
return false;
|
||||
|
||||
if (inst->capabilities[cap].value & MSM_VIDC_META_DYN_ENABLE &&
|
||||
inst->capabilities[cap].value & MSM_VIDC_META_TX_INPUT)
|
||||
enabled = true;
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static inline bool is_meta_tx_out_enabled(struct msm_vidc_inst *inst, u32 cap)
|
||||
{
|
||||
bool enabled = false;
|
||||
|
||||
if (!is_meta_cap(inst, cap))
|
||||
return false;
|
||||
|
||||
if (inst->capabilities[cap].value & MSM_VIDC_META_ENABLE &&
|
||||
inst->capabilities[cap].value & MSM_VIDC_META_TX_OUTPUT)
|
||||
enabled = true;
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static inline bool is_dyn_meta_tx_out_enabled(struct msm_vidc_inst *inst, u32 cap)
|
||||
{
|
||||
bool enabled = false;
|
||||
|
||||
if (!is_meta_cap(inst, cap))
|
||||
return false;
|
||||
|
||||
if (inst->capabilities[cap].value & MSM_VIDC_META_DYN_ENABLE &&
|
||||
inst->capabilities[cap].value & MSM_VIDC_META_TX_OUTPUT)
|
||||
enabled = true;
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static inline bool is_any_meta_tx_out_enabled(struct msm_vidc_inst *inst)
|
||||
{
|
||||
bool enabled = false;
|
||||
u32 i;
|
||||
|
||||
for (i = INST_CAP_NONE + 1; i < INST_CAP_MAX; i++) {
|
||||
if (is_meta_tx_out_enabled(inst, i) ||
|
||||
is_dyn_meta_tx_out_enabled(inst, i)) {
|
||||
enabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static inline bool is_any_meta_tx_inp_enabled(struct msm_vidc_inst *inst)
|
||||
{
|
||||
bool enabled = false;
|
||||
u32 i;
|
||||
|
||||
for (i = INST_CAP_NONE + 1; i < INST_CAP_MAX; i++) {
|
||||
if (is_meta_tx_inp_enabled(inst, i) ||
|
||||
is_dyn_meta_tx_inp_enabled(inst, i)) {
|
||||
enabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static inline bool is_input_meta_enabled(struct msm_vidc_inst *inst)
|
||||
{
|
||||
bool enabled = false;
|
||||
u32 i;
|
||||
|
||||
for (i = INST_CAP_NONE + 1; i < INST_CAP_MAX; i++) {
|
||||
if (is_meta_tx_inp_enabled(inst, i) ||
|
||||
is_dyn_meta_tx_inp_enabled(inst, i) ||
|
||||
is_meta_rx_inp_enabled(inst, i)) {
|
||||
enabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static inline bool is_output_meta_enabled(struct msm_vidc_inst *inst)
|
||||
{
|
||||
bool enabled = false;
|
||||
u32 i;
|
||||
|
||||
for (i = INST_CAP_NONE + 1; i < INST_CAP_MAX; i++) {
|
||||
if (is_meta_tx_out_enabled(inst, i) ||
|
||||
is_dyn_meta_tx_out_enabled(inst, i) ||
|
||||
is_meta_rx_out_enabled(inst, i)) {
|
||||
enabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static inline bool is_meta_enabled(struct msm_vidc_inst *inst, unsigned int type)
|
||||
{
|
||||
bool enabled = false;
|
||||
|
||||
if (type == MSM_VIDC_BUF_INPUT)
|
||||
enabled = is_input_meta_enabled(inst);
|
||||
else if (type == MSM_VIDC_BUF_OUTPUT)
|
||||
enabled = is_output_meta_enabled(inst);
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static inline bool is_outbuf_fence_enabled(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return is_meta_rx_inp_enabled(inst, META_OUTBUF_FENCE);
|
||||
}
|
||||
|
||||
static inline bool is_linear_yuv_colorformat(enum msm_vidc_colorformat_type colorformat)
|
||||
{
|
||||
return colorformat == MSM_VIDC_FMT_NV12 ||
|
||||
colorformat == MSM_VIDC_FMT_NV21 ||
|
||||
colorformat == MSM_VIDC_FMT_P010;
|
||||
}
|
||||
|
||||
static inline bool is_linear_rgba_colorformat(enum msm_vidc_colorformat_type colorformat)
|
||||
{
|
||||
return colorformat == MSM_VIDC_FMT_RGBA8888;
|
||||
}
|
||||
|
||||
static inline bool is_linear_colorformat(enum msm_vidc_colorformat_type colorformat)
|
||||
{
|
||||
return is_linear_yuv_colorformat(colorformat) || is_linear_rgba_colorformat(colorformat);
|
||||
}
|
||||
|
||||
static inline bool is_ubwc_colorformat(enum msm_vidc_colorformat_type colorformat)
|
||||
{
|
||||
return colorformat == MSM_VIDC_FMT_NV12C ||
|
||||
colorformat == MSM_VIDC_FMT_TP10C ||
|
||||
colorformat == MSM_VIDC_FMT_RGBA8888C;
|
||||
}
|
||||
|
||||
static inline bool is_10bit_colorformat(enum msm_vidc_colorformat_type colorformat)
|
||||
{
|
||||
return colorformat == MSM_VIDC_FMT_P010 ||
|
||||
colorformat == MSM_VIDC_FMT_TP10C;
|
||||
}
|
||||
|
||||
static inline bool is_8bit_colorformat(enum msm_vidc_colorformat_type colorformat)
|
||||
{
|
||||
return colorformat == MSM_VIDC_FMT_NV12 ||
|
||||
colorformat == MSM_VIDC_FMT_NV12C ||
|
||||
colorformat == MSM_VIDC_FMT_NV21 ||
|
||||
colorformat == MSM_VIDC_FMT_RGBA8888 ||
|
||||
colorformat == MSM_VIDC_FMT_RGBA8888C;
|
||||
}
|
||||
|
||||
static inline bool is_rgba_colorformat(enum msm_vidc_colorformat_type colorformat)
|
||||
{
|
||||
return colorformat == MSM_VIDC_FMT_RGBA8888 ||
|
||||
colorformat == MSM_VIDC_FMT_RGBA8888C;
|
||||
}
|
||||
|
||||
static inline bool is_split_mode_enabled(struct msm_vidc_inst *inst)
|
||||
{
|
||||
if (!is_decode_session(inst))
|
||||
return false;
|
||||
|
||||
if (is_linear_colorformat(inst->capabilities[PIX_FMTS].value) ||
|
||||
(inst->codec == MSM_VIDC_AV1 &&
|
||||
inst->capabilities[FILM_GRAIN].value))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool is_thumbnail_session(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return !!(inst->capabilities[THUMBNAIL_MODE].value);
|
||||
}
|
||||
|
||||
static inline bool is_low_power_session(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return (inst->capabilities[QUALITY_MODE].value ==
|
||||
MSM_VIDC_POWER_SAVE_MODE);
|
||||
}
|
||||
|
||||
static inline bool is_realtime_session(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return inst->capabilities[PRIORITY].value == 0 ? true : false;
|
||||
}
|
||||
|
||||
static inline bool is_critical_priority_session(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return !!(inst->capabilities[CRITICAL_PRIORITY].value);
|
||||
}
|
||||
|
||||
static inline bool is_lowlatency_session(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return !!(inst->capabilities[LOWLATENCY_MODE].value);
|
||||
}
|
||||
|
||||
static inline bool is_hierb_type_requested(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return (inst->codec == MSM_VIDC_H264 &&
|
||||
inst->capabilities[LAYER_TYPE].value ==
|
||||
V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B) ||
|
||||
(inst->codec == MSM_VIDC_HEVC &&
|
||||
inst->capabilities[LAYER_TYPE].value ==
|
||||
V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B);
|
||||
}
|
||||
|
||||
static inline bool is_active_session(u64 prev, u64 curr)
|
||||
{
|
||||
u64 ts_delta;
|
||||
|
||||
if (!prev || !curr)
|
||||
return true;
|
||||
|
||||
ts_delta = (prev < curr) ? curr - prev : prev - curr;
|
||||
|
||||
return ((ts_delta / NSEC_PER_MSEC) <=
|
||||
MSM_VIDC_SESSION_INACTIVE_THRESHOLD_MS);
|
||||
}
|
||||
|
||||
static inline bool is_session_error(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return inst->state == MSM_VIDC_ERROR;
|
||||
}
|
||||
|
||||
static inline bool is_secure_region(enum msm_vidc_buffer_region region)
|
||||
{
|
||||
return !(region == MSM_VIDC_NON_SECURE ||
|
||||
region == MSM_VIDC_NON_SECURE_PIXEL);
|
||||
}
|
||||
|
||||
static inline bool is_enc_slice_delivery_mode(struct msm_vidc_inst *inst)
|
||||
{
|
||||
if (is_decode_session(inst))
|
||||
return false;
|
||||
|
||||
return (inst->capabilities[SLICE_MODE].value ==
|
||||
V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB &&
|
||||
inst->capabilities[DELIVERY_MODE].value);
|
||||
}
|
||||
|
||||
const char *cap_name(enum msm_vidc_inst_capability_type cap_id);
|
||||
const char *v4l2_pixelfmt_name(struct msm_vidc_inst *inst, u32 pixelfmt);
|
||||
const char *v4l2_type_name(u32 port);
|
||||
void print_vidc_buffer(u32 tag, const char *tag_str, const char *str,
|
||||
struct msm_vidc_inst *inst, struct msm_vidc_buffer *vbuf);
|
||||
void print_vb2_buffer(const char *str, struct msm_vidc_inst *inst,
|
||||
struct vb2_buffer *vb2);
|
||||
enum msm_vidc_codec_type v4l2_codec_to_driver(struct msm_vidc_inst *inst,
|
||||
u32 v4l2_codec, const char *func);
|
||||
u32 v4l2_codec_from_driver(struct msm_vidc_inst *inst, enum msm_vidc_codec_type codec,
|
||||
const char *func);
|
||||
enum msm_vidc_colorformat_type v4l2_colorformat_to_driver(struct msm_vidc_inst *inst,
|
||||
u32 colorformat, const char *func);
|
||||
u32 v4l2_colorformat_from_driver(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_colorformat_type colorformat,
|
||||
const char *func);
|
||||
u32 v4l2_color_primaries_to_driver(struct msm_vidc_inst *inst,
|
||||
u32 v4l2_primaries, const char *func);
|
||||
u32 v4l2_color_primaries_from_driver(struct msm_vidc_inst *inst,
|
||||
u32 vidc_color_primaries, const char *func);
|
||||
u32 v4l2_transfer_char_to_driver(struct msm_vidc_inst *inst,
|
||||
u32 v4l2_transfer_char, const char *func);
|
||||
u32 v4l2_transfer_char_from_driver(struct msm_vidc_inst *inst,
|
||||
u32 vidc_transfer_char, const char *func);
|
||||
u32 v4l2_matrix_coeff_to_driver(struct msm_vidc_inst *inst,
|
||||
u32 v4l2_matrix_coeff, const char *func);
|
||||
u32 v4l2_matrix_coeff_from_driver(struct msm_vidc_inst *inst,
|
||||
u32 vidc_matrix_coeff, const char *func);
|
||||
int v4l2_type_to_driver_port(struct msm_vidc_inst *inst, u32 type,
|
||||
const char *func);
|
||||
const char *allow_name(enum msm_vidc_allow allow);
|
||||
int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type, u32 index);
|
||||
int msm_vidc_get_internal_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
int msm_vidc_queue_internal_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
int msm_vidc_alloc_and_queue_session_internal_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
int msm_vidc_release_internal_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
int msm_vidc_vb2_buffer_done(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_buffer *buf);
|
||||
int msm_vidc_remove_dangling_session(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_remove_session(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_add_session(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_session_open(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_session_set_codec(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_session_set_secure_mode(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_session_set_default_header(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_session_streamoff(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_port_type port);
|
||||
int msm_vidc_session_close(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_kill_session(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_get_inst_capability(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_change_core_state(struct msm_vidc_core *core,
|
||||
enum msm_vidc_core_state request_state,
|
||||
const char *func);
|
||||
int msm_vidc_change_core_sub_state(struct msm_vidc_core *core,
|
||||
enum msm_vidc_core_sub_state clear_sub_states,
|
||||
enum msm_vidc_core_sub_state set_sub_states,
|
||||
const char *func);
|
||||
int msm_vidc_core_init(struct msm_vidc_core *core);
|
||||
int msm_vidc_core_init_wait(struct msm_vidc_core *core);
|
||||
int msm_vidc_core_deinit(struct msm_vidc_core *core, bool force);
|
||||
int msm_vidc_print_residency_stats(struct msm_vidc_core *core);
|
||||
int msm_vidc_reset_residency_stats(struct msm_vidc_core *core);
|
||||
int msm_vidc_core_deinit_locked(struct msm_vidc_core *core, bool force);
|
||||
int msm_vidc_inst_timeout(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_print_buffer_info(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_print_inst_info(struct msm_vidc_inst *inst);
|
||||
void msm_vidc_print_core_info(struct msm_vidc_core *core);
|
||||
int msm_vidc_smmu_fault_handler(struct iommu_domain *domain,
|
||||
struct device *dev, unsigned long iova,
|
||||
int flags, void *data);
|
||||
int msm_vidc_trigger_ssr(struct msm_vidc_core *core,
|
||||
u64 trigger_ssr_val);
|
||||
void msm_vidc_ssr_handler(struct work_struct *work);
|
||||
int msm_vidc_trigger_stability(struct msm_vidc_core *core,
|
||||
u64 trigger_stability_val);
|
||||
void msm_vidc_stability_handler(struct work_struct *work);
|
||||
int cancel_stability_work_sync(struct msm_vidc_inst *inst);
|
||||
void msm_vidc_fw_unload_handler(struct work_struct *work);
|
||||
int msm_vidc_suspend(struct msm_vidc_core *core);
|
||||
void msm_vidc_batch_handler(struct work_struct *work);
|
||||
int msm_vidc_v4l2_fh_init(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_v4l2_fh_deinit(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_vb2_queue_init(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_vb2_queue_deinit(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_get_control(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl);
|
||||
struct msm_vidc_buffers *msm_vidc_get_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type,
|
||||
const char *func);
|
||||
struct msm_vidc_mem_list *msm_vidc_get_mem_info(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type,
|
||||
const char *func);
|
||||
struct msm_vidc_buffer *msm_vidc_get_driver_buf(struct msm_vidc_inst *inst,
|
||||
struct vb2_buffer *vb2);
|
||||
int msm_vidc_allocate_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buf_type, u32 num_buffers);
|
||||
int msm_vidc_free_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buf_type);
|
||||
void msm_vidc_update_stats(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_buffer *buf,
|
||||
enum msm_vidc_debugfs_event etype);
|
||||
void msm_vidc_stats_handler(struct work_struct *work);
|
||||
int schedule_stats_work(struct msm_vidc_inst *inst);
|
||||
int cancel_stats_work_sync(struct msm_vidc_inst *inst);
|
||||
void msm_vidc_print_stats(struct msm_vidc_inst *inst);
|
||||
void msm_vidc_print_memory_stats(struct msm_vidc_inst *inst);
|
||||
enum msm_vidc_buffer_type v4l2_type_to_driver(u32 type, const char *func);
|
||||
int msm_vidc_buf_queue(struct msm_vidc_inst *inst, struct msm_vidc_buffer *buf);
|
||||
int msm_vidc_queue_buffer_single(struct msm_vidc_inst *inst,
|
||||
struct vb2_buffer *vb2);
|
||||
int msm_vidc_queue_deferred_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buf_type);
|
||||
int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_buffer *buffer);
|
||||
void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_flush_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type type);
|
||||
int msm_vidc_flush_read_only_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type type);
|
||||
struct msm_vidc_buffer *get_meta_buffer(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_buffer *vbuf);
|
||||
struct msm_vidc_inst *get_inst_ref(struct msm_vidc_core *core,
|
||||
struct msm_vidc_inst *instance);
|
||||
struct msm_vidc_inst *get_inst(struct msm_vidc_core *core,
|
||||
u32 session_id);
|
||||
void put_inst(struct msm_vidc_inst *inst);
|
||||
bool msm_vidc_allow_metadata_delivery(struct msm_vidc_inst *inst,
|
||||
u32 cap_id, u32 port);
|
||||
bool msm_vidc_allow_metadata_subscription(struct msm_vidc_inst *inst,
|
||||
u32 cap_id, u32 port);
|
||||
bool msm_vidc_allow_property(struct msm_vidc_inst *inst, u32 hfi_id);
|
||||
enum msm_vidc_allow msm_vidc_allow_input_psc(struct msm_vidc_inst *inst);
|
||||
bool msm_vidc_allow_drain_last_flag(struct msm_vidc_inst *inst);
|
||||
bool msm_vidc_allow_psc_last_flag(struct msm_vidc_inst *inst);
|
||||
enum msm_vidc_allow msm_vidc_allow_pm_suspend(struct msm_vidc_core *core);
|
||||
int msm_vidc_state_change_streamon(struct msm_vidc_inst *inst, u32 type);
|
||||
int msm_vidc_state_change_streamoff(struct msm_vidc_inst *inst, u32 type);
|
||||
int msm_vidc_state_change_input_psc(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_state_change_drain_last_flag(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_state_change_psc_last_flag(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_process_drain(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_process_resume(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_process_streamon_input(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_process_streamon_output(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_process_stop_done(struct msm_vidc_inst *inst,
|
||||
enum signal_session_response signal_type);
|
||||
int msm_vidc_process_drain_done(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_process_drain_last_flag(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_process_psc_last_flag(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst);
|
||||
u32 msm_vidc_get_max_bitrate(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_get_fps(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_num_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type type,
|
||||
enum msm_vidc_buffer_attributes attr);
|
||||
void core_lock(struct msm_vidc_core *core, const char *function);
|
||||
void core_unlock(struct msm_vidc_core *core, const char *function);
|
||||
void inst_lock(struct msm_vidc_inst *inst, const char *function);
|
||||
void inst_unlock(struct msm_vidc_inst *inst, const char *function);
|
||||
void client_lock(struct msm_vidc_inst *inst, const char *function);
|
||||
void client_unlock(struct msm_vidc_inst *inst, const char *function);
|
||||
int msm_vidc_update_bitstream_buffer_size(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_update_meta_port_settings(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_update_buffer_count(struct msm_vidc_inst *inst, u32 port);
|
||||
void msm_vidc_schedule_core_deinit(struct msm_vidc_core *core);
|
||||
bool msm_vidc_is_super_buffer(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_init_core_caps(struct msm_vidc_core *core);
|
||||
int msm_vidc_init_instance_caps(struct msm_vidc_core *core);
|
||||
int msm_vidc_deinit_core_caps(struct msm_vidc_core *core);
|
||||
int msm_vidc_update_debug_str(struct msm_vidc_inst *inst);
|
||||
void msm_vidc_allow_dcvs(struct msm_vidc_inst *inst);
|
||||
bool msm_vidc_allow_decode_batch(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_check_session_supported(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_check_core_mbpf(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_update_timestamp_rate(struct msm_vidc_inst *inst, u64 timestamp);
|
||||
int msm_vidc_set_auto_framerate(struct msm_vidc_inst *inst, u64 timestamp);
|
||||
int msm_vidc_get_timestamp_rate(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_flush_ts(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_ts_reorder_insert_timestamp(struct msm_vidc_inst *inst, u64 timestamp);
|
||||
int msm_vidc_ts_reorder_remove_timestamp(struct msm_vidc_inst *inst, u64 timestamp);
|
||||
int msm_vidc_ts_reorder_get_first_timestamp(struct msm_vidc_inst *inst, u64 *timestamp);
|
||||
int msm_vidc_ts_reorder_flush(struct msm_vidc_inst *inst);
|
||||
const char *buf_name(enum msm_vidc_buffer_type type);
|
||||
bool res_is_greater_than(u32 width, u32 height,
|
||||
u32 ref_width, u32 ref_height);
|
||||
bool res_is_greater_than_or_equal_to(u32 width, u32 height,
|
||||
u32 ref_width, u32 ref_height);
|
||||
bool res_is_less_than(u32 width, u32 height,
|
||||
u32 ref_width, u32 ref_height);
|
||||
bool res_is_less_than_or_equal_to(u32 width, u32 height,
|
||||
u32 ref_width, u32 ref_height);
|
||||
bool is_hevc_10bit_decode_session(struct msm_vidc_inst *inst);
|
||||
int signal_session_msg_receipt(struct msm_vidc_inst *inst,
|
||||
enum signal_session_response cmd);
|
||||
int msm_vidc_get_properties(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_update_input_rate(struct msm_vidc_inst *inst, u64 time_us);
|
||||
int msm_vidc_add_buffer_stats(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_buffer *buf, u64 timestamp);
|
||||
int msm_vidc_remove_buffer_stats(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_buffer *buf, u64 timestamp);
|
||||
int msm_vidc_flush_buffer_stats(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_get_input_rate(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_get_frame_rate(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_get_operating_rate(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_alloc_and_queue_input_internal_buffers(struct msm_vidc_inst *inst);
|
||||
int vb2_buffer_to_driver(struct vb2_buffer *vb2, struct msm_vidc_buffer *buf);
|
||||
bool is_ssr_type_allowed(struct msm_vidc_core *core, u32 type);
|
||||
struct msm_vidc_buffer *msm_vidc_fetch_buffer(struct msm_vidc_inst *inst,
|
||||
struct vb2_buffer *vb2);
|
||||
struct context_bank_info
|
||||
*msm_vidc_get_context_bank_for_region(struct msm_vidc_core *core,
|
||||
enum msm_vidc_buffer_region region);
|
||||
struct context_bank_info
|
||||
*msm_vidc_get_context_bank_for_device(struct msm_vidc_core *core, struct device *dev);
|
||||
|
||||
#endif // _MSM_VIDC_DRIVER_H_
|
||||
|
300
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_events.h
Normal file
300
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_events.h
Normal file
@ -0,0 +1,300 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#if !defined(_TRACE_MSM_VIDC_H) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_MSM_VIDC_H
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM msm_vidc_events
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_FILE msm_vidc_events
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
#include "msm_vidc_inst.h"
|
||||
|
||||
DECLARE_EVENT_CLASS(msm_v4l2_vidc_inst,
|
||||
|
||||
TP_PROTO(char *dummy, struct msm_vidc_inst *inst),
|
||||
|
||||
TP_ARGS(dummy, inst),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(char *, dummy)
|
||||
__field(const char *, debug_str)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->dummy = dummy;
|
||||
__entry->debug_str = inst ? inst->debug_str : (u8 *)"";
|
||||
),
|
||||
|
||||
TP_printk("%s: %s\n", __entry->dummy, __entry->debug_str)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_v4l2_vidc_inst, msm_v4l2_vidc_open,
|
||||
|
||||
TP_PROTO(char *dummy, struct msm_vidc_inst *inst),
|
||||
|
||||
TP_ARGS(dummy, inst)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_v4l2_vidc_inst, msm_v4l2_vidc_close,
|
||||
|
||||
TP_PROTO(char *dummy, struct msm_vidc_inst *inst),
|
||||
|
||||
TP_ARGS(dummy, inst)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(msm_v4l2_vidc_fw_load,
|
||||
|
||||
TP_PROTO(char *dummy),
|
||||
|
||||
TP_ARGS(dummy),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(char *, dummy)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->dummy = dummy;
|
||||
),
|
||||
|
||||
TP_printk("%s\n", __entry->dummy)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_v4l2_vidc_fw_load, msm_v4l2_vidc_fw_load,
|
||||
|
||||
TP_PROTO(char *dummy),
|
||||
|
||||
TP_ARGS(dummy)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(msm_vidc_driver,
|
||||
|
||||
TP_PROTO(struct msm_vidc_inst *inst, const char *func,
|
||||
const char *old_state, const char *new_state),
|
||||
|
||||
TP_ARGS(inst, func, old_state, new_state),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, debug_str)
|
||||
__field(const char *, func)
|
||||
__field(const char *, old_state)
|
||||
__field(const char *, new_state)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->debug_str = inst ? inst->debug_str : (u8 *)"";
|
||||
__entry->func = func;
|
||||
__entry->old_state = old_state;
|
||||
__entry->new_state = new_state;
|
||||
),
|
||||
|
||||
TP_printk("%s: %s: state changed to %s from %s\n",
|
||||
__entry->debug_str,
|
||||
__entry->func,
|
||||
__entry->new_state,
|
||||
__entry->old_state)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_vidc_driver, msm_vidc_common_state_change,
|
||||
|
||||
TP_PROTO(struct msm_vidc_inst *inst, const char *func,
|
||||
const char *old_state, const char *new_state),
|
||||
|
||||
TP_ARGS(inst, func, old_state, new_state)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(venus_hfi_var,
|
||||
|
||||
TP_PROTO(u32 cp_start, u32 cp_size,
|
||||
u32 cp_nonpixel_start, u32 cp_nonpixel_size),
|
||||
|
||||
TP_ARGS(cp_start, cp_size, cp_nonpixel_start, cp_nonpixel_size),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, cp_start)
|
||||
__field(u32, cp_size)
|
||||
__field(u32, cp_nonpixel_start)
|
||||
__field(u32, cp_nonpixel_size)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->cp_start = cp_start;
|
||||
__entry->cp_size = cp_size;
|
||||
__entry->cp_nonpixel_start = cp_nonpixel_start;
|
||||
__entry->cp_nonpixel_size = cp_nonpixel_size;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"TZBSP_MEM_PROTECT_VIDEO_VAR done, cp_start : 0x%x, cp_size : 0x%x, cp_nonpixel_start : 0x%x, cp_nonpixel_size : 0x%x\n",
|
||||
__entry->cp_start,
|
||||
__entry->cp_size,
|
||||
__entry->cp_nonpixel_start,
|
||||
__entry->cp_nonpixel_size)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(venus_hfi_var, venus_hfi_var_done,
|
||||
|
||||
TP_PROTO(u32 cp_start, u32 cp_size,
|
||||
u32 cp_nonpixel_start, u32 cp_nonpixel_size),
|
||||
|
||||
TP_ARGS(cp_start, cp_size, cp_nonpixel_start, cp_nonpixel_size)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(msm_v4l2_vidc_buffer_events,
|
||||
|
||||
TP_PROTO(struct msm_vidc_inst *inst, const char *str, const char *buf_type,
|
||||
struct msm_vidc_buffer *vbuf, unsigned long inode, long ref_count),
|
||||
|
||||
TP_ARGS(inst, str, buf_type, vbuf, inode, ref_count),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u8 *, debug_str)
|
||||
__field(const char *, str)
|
||||
__field(const char *, buf_type)
|
||||
__field(u32, index)
|
||||
__field(int, fd)
|
||||
__field(u32, data_offset)
|
||||
__field(u64, device_addr)
|
||||
__field(unsigned long, inode)
|
||||
__field(long, ref_count)
|
||||
__field(u32, buffer_size)
|
||||
__field(u32, data_size)
|
||||
__field(u32, flags)
|
||||
__field(u64, timestamp)
|
||||
__field(int, attr)
|
||||
__field(u64, etb)
|
||||
__field(u64, ebd)
|
||||
__field(u64, ftb)
|
||||
__field(u64, fbd)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->debug_str = inst ? inst->debug_str : (u8 *)"";
|
||||
__entry->str = str;
|
||||
__entry->buf_type = buf_type;
|
||||
__entry->index = vbuf ? vbuf->index : -1;
|
||||
__entry->fd = vbuf ? vbuf->fd : 0;
|
||||
__entry->data_offset = vbuf ? vbuf->data_offset : 0;
|
||||
__entry->device_addr = vbuf ? vbuf->device_addr : 0;
|
||||
__entry->inode = inode;
|
||||
__entry->ref_count = ref_count;
|
||||
__entry->buffer_size = vbuf ? vbuf->buffer_size : 0;
|
||||
__entry->data_size = vbuf ? vbuf->data_size : 0;
|
||||
__entry->flags = vbuf ? vbuf->flags : 0;
|
||||
__entry->timestamp = vbuf ? vbuf->timestamp : 0;
|
||||
__entry->attr = vbuf ? vbuf->attr : 0;
|
||||
__entry->etb = inst ? inst->debug_count.etb : 0;
|
||||
__entry->ebd = inst ? inst->debug_count.ebd : 0;
|
||||
__entry->ftb = inst ? inst->debug_count.ftb : 0;
|
||||
__entry->fbd = inst ? inst->debug_count.fbd : 0;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s: %s: %s: idx %2d fd %3d off %d daddr %#llx inode %8lu ref %2ld size %8d filled %8d flags %#x ts %8lld attr %#x counts(etb ebd ftb fbd) %4llu %4llu %4llu %4llu\n",
|
||||
__entry->debug_str, __entry->str, __entry->buf_type, __entry->index, __entry->fd,
|
||||
__entry->data_offset, __entry->device_addr, __entry->inode, __entry->ref_count,
|
||||
__entry->buffer_size, __entry->data_size, __entry->flags, __entry->timestamp,
|
||||
__entry->attr, __entry->etb, __entry->ebd, __entry->ftb, __entry->fbd)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_v4l2_vidc_buffer_events, msm_v4l2_vidc_buffer_event_log,
|
||||
|
||||
TP_PROTO(struct msm_vidc_inst *inst, const char *str, const char *buf_type,
|
||||
struct msm_vidc_buffer *vbuf, unsigned long inode, long ref_count),
|
||||
|
||||
TP_ARGS(inst, str, buf_type, vbuf, inode, ref_count)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(msm_vidc_perf,
|
||||
|
||||
TP_PROTO(struct msm_vidc_inst *inst, u64 clk_freq, u64 bw_ddr, u64 bw_llcc),
|
||||
|
||||
TP_ARGS(inst, clk_freq, bw_ddr, bw_llcc),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u8 *, debug_str)
|
||||
__field(u64, curr_freq)
|
||||
__field(u32, ddr_bw)
|
||||
__field(u32, sys_cache_bw)
|
||||
__field(u32, dcvs_flags)
|
||||
__field(u64, clk_freq)
|
||||
__field(u64, bw_ddr)
|
||||
__field(u64, bw_llcc)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->debug_str = inst ? inst->debug_str : (u8 *)"";
|
||||
__entry->curr_freq = inst ? inst->power.curr_freq : 0;
|
||||
__entry->ddr_bw = inst ? inst->power.ddr_bw : 0;
|
||||
__entry->sys_cache_bw = inst ? inst->power.sys_cache_bw : 0;
|
||||
__entry->dcvs_flags = inst ? inst->power.dcvs_flags : 0;
|
||||
__entry->clk_freq = clk_freq;
|
||||
__entry->bw_ddr = bw_ddr;
|
||||
__entry->bw_llcc = bw_llcc;
|
||||
),
|
||||
|
||||
TP_printk("%s: power: inst: clk %lld ddr %d llcc %d dcvs flags %#x, core: clk %lld ddr %lld llcc %lld\n",
|
||||
__entry->debug_str, __entry->curr_freq, __entry->ddr_bw, __entry->sys_cache_bw,
|
||||
__entry->dcvs_flags, __entry->clk_freq, __entry->bw_ddr, __entry->bw_llcc)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_vidc_perf, msm_vidc_perf_power_scale,
|
||||
|
||||
TP_PROTO(struct msm_vidc_inst *inst, u64 clk_freq, u64 bw_ddr, u64 bw_llcc),
|
||||
|
||||
TP_ARGS(inst, clk_freq, bw_ddr, bw_llcc)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(msm_vidc_buffer_dma_ops,
|
||||
|
||||
TP_PROTO(const char *buffer_op, void *dmabuf, u8 size, void *kvaddr,
|
||||
const char *buf_name, u8 secure, u32 region),
|
||||
|
||||
TP_ARGS(buffer_op, dmabuf, size, kvaddr, buf_name, secure, region),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, buffer_op)
|
||||
__field(void *, dmabuf)
|
||||
__field(u8, size)
|
||||
__field(void *, kvaddr)
|
||||
__field(const char *, buf_name)
|
||||
__field(u8, secure)
|
||||
__field(u32, region)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->buffer_op = buffer_op;
|
||||
__entry->dmabuf = dmabuf;
|
||||
__entry->size = size;
|
||||
__entry->kvaddr = kvaddr;
|
||||
__entry->buf_name = buf_name;
|
||||
__entry->secure = secure;
|
||||
__entry->region = region;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s: dmabuf %pK, size %d, kvaddr %pK, buffer_type %s, secure %d, region %d\n",
|
||||
__entry->buffer_op, __entry->dmabuf, __entry->size, __entry->kvaddr,
|
||||
__entry->buf_name, __entry->secure, __entry->region)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_vidc_buffer_dma_ops, msm_vidc_dma_buffer,
|
||||
|
||||
TP_PROTO(const char *buffer_op, void *dmabuf, u8 size, void *kvaddr,
|
||||
const char *buf_name, u8 secure, u32 region),
|
||||
|
||||
TP_ARGS(buffer_op, dmabuf, size, kvaddr, buf_name, secure, region)
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
/* This part must be outside protection */
|
||||
#include <trace/define_trace.h>
|
@ -0,0 +1,34 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __H_MSM_VIDC_FENCE_H__
|
||||
#define __H_MSM_VIDC_FENCE_H__
|
||||
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_buffer.h"
|
||||
|
||||
int msm_vidc_fence_init(struct msm_vidc_inst *inst);
|
||||
void msm_vidc_fence_deinit(struct msm_vidc_inst *inst);
|
||||
|
||||
#define call_fence_op(c, op, ...) \
|
||||
(((c) && (c)->fence_ops && (c)->fence_ops->op) ? \
|
||||
((c)->fence_ops->op(__VA_ARGS__)) : 0)
|
||||
|
||||
struct msm_vidc_fence_ops {
|
||||
int (*fence_register)(struct msm_vidc_core *core);
|
||||
int (*fence_deregister)(struct msm_vidc_core *core);
|
||||
struct msm_vidc_fence *(*fence_create)(struct msm_vidc_inst *inst);
|
||||
int (*fence_create_fd)(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_fence *fence);
|
||||
void (*fence_destroy)(struct msm_vidc_inst *inst,
|
||||
u64 fence_id);
|
||||
int (*fence_signal)(struct msm_vidc_inst *inst,
|
||||
u64 fence_id);
|
||||
void (*fence_recover)(struct msm_vidc_core *core);
|
||||
};
|
||||
|
||||
const struct msm_vidc_fence_ops *get_dma_fence_ops(void);
|
||||
|
||||
#endif // __H_MSM_VIDC_FENCE_H__
|
150
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_inst.h
Normal file
150
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_inst.h
Normal file
@ -0,0 +1,150 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_INST_H_
|
||||
#define _MSM_VIDC_INST_H_
|
||||
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_memory.h"
|
||||
#include "msm_vidc_state.h"
|
||||
#include "hfi_property.h"
|
||||
|
||||
struct msm_vidc_inst;
|
||||
|
||||
#define call_session_op(c, op, ...) \
|
||||
(((c) && (c)->session_ops && (c)->session_ops->op) ? \
|
||||
((c)->session_ops->op(__VA_ARGS__)) : 0)
|
||||
|
||||
struct msm_vidc_session_ops {
|
||||
u64 (*calc_freq)(struct msm_vidc_inst *inst, u32 data_size);
|
||||
int (*calc_bw)(struct msm_vidc_inst *inst,
|
||||
struct vidc_bus_vote_data *vote_data);
|
||||
int (*decide_work_route)(struct msm_vidc_inst *inst);
|
||||
int (*decide_work_mode)(struct msm_vidc_inst *inst);
|
||||
int (*decide_quality_mode)(struct msm_vidc_inst *inst);
|
||||
int (*buffer_size)(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type type);
|
||||
int (*min_count)(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type type);
|
||||
int (*extra_count)(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type type);
|
||||
int (*ring_buf_count)(struct msm_vidc_inst *inst, u32 data_size);
|
||||
};
|
||||
|
||||
struct msm_vidc_mem_list_info {
|
||||
struct msm_vidc_mem_list bin;
|
||||
struct msm_vidc_mem_list arp;
|
||||
struct msm_vidc_mem_list comv;
|
||||
struct msm_vidc_mem_list non_comv;
|
||||
struct msm_vidc_mem_list line;
|
||||
struct msm_vidc_mem_list dpb;
|
||||
struct msm_vidc_mem_list persist;
|
||||
struct msm_vidc_mem_list vpss;
|
||||
struct msm_vidc_mem_list partial_data;
|
||||
};
|
||||
|
||||
struct msm_vidc_buffers_info {
|
||||
struct msm_vidc_buffers input;
|
||||
struct msm_vidc_buffers output;
|
||||
struct msm_vidc_buffers read_only;
|
||||
struct msm_vidc_buffers input_meta;
|
||||
struct msm_vidc_buffers output_meta;
|
||||
struct msm_vidc_buffers bin;
|
||||
struct msm_vidc_buffers arp;
|
||||
struct msm_vidc_buffers comv;
|
||||
struct msm_vidc_buffers non_comv;
|
||||
struct msm_vidc_buffers line;
|
||||
struct msm_vidc_buffers dpb;
|
||||
struct msm_vidc_buffers persist;
|
||||
struct msm_vidc_buffers vpss;
|
||||
struct msm_vidc_buffers partial_data;
|
||||
};
|
||||
|
||||
struct buf_queue {
|
||||
struct vb2_queue *vb2q;
|
||||
};
|
||||
|
||||
struct msm_vidc_inst {
|
||||
struct list_head list;
|
||||
struct mutex lock;
|
||||
struct mutex ctx_q_lock;
|
||||
struct mutex client_lock;
|
||||
enum msm_vidc_state state;
|
||||
int (*event_handle)(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_event event,
|
||||
void *data);
|
||||
enum msm_vidc_sub_state sub_state;
|
||||
char sub_state_name[MAX_NAME_LENGTH];
|
||||
enum msm_vidc_domain_type domain;
|
||||
enum msm_vidc_codec_type codec;
|
||||
void *core;
|
||||
struct kref kref;
|
||||
u32 session_id;
|
||||
u8 debug_str[24];
|
||||
void *packet;
|
||||
u32 packet_size;
|
||||
struct v4l2_format fmts[MAX_PORT];
|
||||
struct v4l2_ctrl_handler ctrl_handler;
|
||||
struct v4l2_fh fh;
|
||||
struct v4l2_m2m_dev *m2m_dev;
|
||||
struct v4l2_m2m_ctx *m2m_ctx;
|
||||
u32 num_ctrls;
|
||||
enum hfi_rate_control hfi_rc_type;
|
||||
enum hfi_layer_encoding_type hfi_layer_type;
|
||||
bool request;
|
||||
struct buf_queue bufq[MAX_PORT];
|
||||
struct msm_vidc_rectangle crop;
|
||||
struct msm_vidc_rectangle compose;
|
||||
struct msm_vidc_power power;
|
||||
struct vidc_bus_vote_data bus_data;
|
||||
struct msm_memory_pool pool[MSM_MEM_POOL_MAX];
|
||||
struct msm_vidc_buffers_info buffers;
|
||||
struct msm_vidc_mem_list_info mem_info;
|
||||
struct msm_vidc_timestamps timestamps;
|
||||
struct msm_vidc_timestamps ts_reorder; /* struct msm_vidc_timestamp */
|
||||
struct msm_vidc_subscription_params subcr_params[MAX_PORT];
|
||||
struct msm_vidc_hfi_frame_info hfi_frame_info;
|
||||
struct msm_vidc_decode_batch decode_batch;
|
||||
struct msm_vidc_decode_vpp_delay decode_vpp_delay;
|
||||
struct msm_vidc_session_idle session_idle;
|
||||
struct delayed_work stats_work;
|
||||
struct work_struct stability_work;
|
||||
struct msm_vidc_stability stability;
|
||||
struct workqueue_struct *workq;
|
||||
struct list_head enc_input_crs;
|
||||
struct list_head dmabuf_tracker; /* struct msm_memory_dmabuf */
|
||||
struct list_head input_timer_list; /* struct msm_vidc_input_timer */
|
||||
struct list_head caps_list;
|
||||
struct list_head children_list; /* struct msm_vidc_inst_cap_entry */
|
||||
struct list_head firmware_list; /* struct msm_vidc_inst_cap_entry */
|
||||
struct list_head pending_pkts; /* struct hfi_pending_packet */
|
||||
struct list_head fence_list; /* struct msm_vidc_fence */
|
||||
struct list_head buffer_stats_list; /* struct msm_vidc_buffer_stats */
|
||||
bool once_per_session_set;
|
||||
bool ipsc_properties_set;
|
||||
bool opsc_properties_set;
|
||||
bool caps_list_prepared;
|
||||
struct dentry *debugfs_root;
|
||||
struct msm_vidc_debug debug;
|
||||
struct debug_buf_count debug_count;
|
||||
struct msm_vidc_statistics stats;
|
||||
struct msm_vidc_inst_cap capabilities[INST_CAP_MAX + 1];
|
||||
struct completion completions[MAX_SIGNAL];
|
||||
struct msm_vidc_fence_context fence_context;
|
||||
bool active;
|
||||
u64 last_qbuf_time_ns;
|
||||
u64 initial_time_us;
|
||||
u32 max_input_data_size;
|
||||
u32 dpb_list_payload[MAX_DPB_LIST_ARRAY_SIZE];
|
||||
bool input_dpb_list_enabled;
|
||||
bool output_dpb_list_enabled;
|
||||
u32 auto_framerate;
|
||||
u32 max_rate;
|
||||
bool has_bframe;
|
||||
bool ir_enabled;
|
||||
u32 adjust_priority;
|
||||
bool iframe;
|
||||
u32 fw_min_count;
|
||||
};
|
||||
|
||||
#endif // _MSM_VIDC_INST_H_
|
1058
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_internal.h
Normal file
1058
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_internal.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,93 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_MEMORY_H_
|
||||
#define _MSM_VIDC_MEMORY_H_
|
||||
|
||||
#include "msm_vidc_internal.h"
|
||||
|
||||
struct msm_vidc_core;
|
||||
struct msm_vidc_inst;
|
||||
|
||||
#define MSM_MEM_POOL_PACKET_SIZE 1024
|
||||
|
||||
struct msm_memory_dmabuf {
|
||||
struct list_head list;
|
||||
struct dma_buf *dmabuf;
|
||||
u32 refcount;
|
||||
};
|
||||
|
||||
enum msm_memory_pool_type {
|
||||
MSM_MEM_POOL_BUFFER = 0,
|
||||
MSM_MEM_POOL_ALLOC_MAP,
|
||||
MSM_MEM_POOL_TIMESTAMP,
|
||||
MSM_MEM_POOL_DMABUF,
|
||||
MSM_MEM_POOL_PACKET,
|
||||
MSM_MEM_POOL_BUF_TIMER,
|
||||
MSM_MEM_POOL_BUF_STATS,
|
||||
MSM_MEM_POOL_MAX,
|
||||
};
|
||||
|
||||
struct msm_memory_alloc_header {
|
||||
struct list_head list;
|
||||
u32 type;
|
||||
bool busy;
|
||||
void *buf;
|
||||
};
|
||||
|
||||
struct msm_memory_pool {
|
||||
u32 size;
|
||||
char *name;
|
||||
struct list_head free_pool; /* list of struct msm_memory_alloc_header */
|
||||
struct list_head busy_pool; /* list of struct msm_memory_alloc_header */
|
||||
};
|
||||
|
||||
void *msm_vidc_pool_alloc(struct msm_vidc_inst *inst,
|
||||
enum msm_memory_pool_type type);
|
||||
void msm_vidc_pool_free(struct msm_vidc_inst *inst, void *vidc_buf);
|
||||
int msm_vidc_pools_init(struct msm_vidc_inst *inst);
|
||||
void msm_vidc_pools_deinit(struct msm_vidc_inst *inst);
|
||||
|
||||
#define call_mem_op(c, op, ...) \
|
||||
(((c) && (c)->mem_ops && (c)->mem_ops->op) ? \
|
||||
((c)->mem_ops->op(__VA_ARGS__)) : 0)
|
||||
|
||||
struct msm_vidc_memory_ops {
|
||||
struct dma_buf *(*dma_buf_get)(struct msm_vidc_inst *inst,
|
||||
int fd);
|
||||
void (*dma_buf_put)(struct msm_vidc_inst *inst,
|
||||
struct dma_buf *dmabuf);
|
||||
void (*dma_buf_put_completely)(struct msm_vidc_inst *inst,
|
||||
struct msm_memory_dmabuf *buf);
|
||||
struct dma_buf_attachment *(*dma_buf_attach)(struct msm_vidc_core *core,
|
||||
struct dma_buf *dbuf, struct device *dev);
|
||||
int (*dma_buf_detach)(struct msm_vidc_core *core, struct dma_buf *dbuf,
|
||||
struct dma_buf_attachment *attach);
|
||||
struct sg_table
|
||||
*(*dma_buf_map_attachment)(struct msm_vidc_core *core,
|
||||
struct dma_buf_attachment *attach);
|
||||
int (*dma_buf_unmap_attachment)(struct msm_vidc_core *core,
|
||||
struct dma_buf_attachment *attach,
|
||||
struct sg_table *table);
|
||||
int (*memory_alloc_map)(struct msm_vidc_core *core,
|
||||
struct msm_vidc_mem *mem);
|
||||
int (*memory_unmap_free)(struct msm_vidc_core *core,
|
||||
struct msm_vidc_mem *mem);
|
||||
int (*mem_dma_map_page)(struct msm_vidc_core *core,
|
||||
struct msm_vidc_mem *mem);
|
||||
int (*mem_dma_unmap_page)(struct msm_vidc_core *core,
|
||||
struct msm_vidc_mem *mem);
|
||||
u32 (*buffer_region)(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type);
|
||||
int (*iommu_map)(struct msm_vidc_core *core,
|
||||
struct msm_vidc_mem *mem);
|
||||
int (*iommu_unmap)(struct msm_vidc_core *core,
|
||||
struct msm_vidc_mem *mem);
|
||||
};
|
||||
|
||||
const struct msm_vidc_memory_ops *get_mem_ops(void);
|
||||
|
||||
#endif // _MSM_VIDC_MEMORY_H_
|
@ -0,0 +1,14 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_MEMORY_EXT_H_
|
||||
#define _MSM_VIDC_MEMORY_EXT_H_
|
||||
|
||||
#include "msm_vidc_memory.h"
|
||||
|
||||
const struct msm_vidc_memory_ops *get_mem_ops_ext(void);
|
||||
|
||||
#endif // _MSM_VIDC_MEMORY_EXT_H_
|
257
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_power.h
Normal file
257
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_power.h
Normal file
@ -0,0 +1,257 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_POWER_H_
|
||||
#define _MSM_VIDC_POWER_H_
|
||||
|
||||
#include "fixedpoint.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
|
||||
#define COMPRESSION_RATIO_MAX 5
|
||||
|
||||
/* TODO: Move to dtsi OR use source clock instead of branch clock.*/
|
||||
#define MSM_VIDC_CLOCK_SOURCE_SCALING_RATIO 3
|
||||
|
||||
enum vidc_bus_type {
|
||||
PERF,
|
||||
DDR,
|
||||
LLCC,
|
||||
};
|
||||
|
||||
/*
|
||||
* Minimum dimensions for which to calculate bandwidth.
|
||||
* This means that anything bandwidth(0, 0) ==
|
||||
* bandwidth(BASELINE_DIMENSIONS.width, BASELINE_DIMENSIONS.height)
|
||||
*/
|
||||
static const struct {
|
||||
int height, width;
|
||||
} BASELINE_DIMENSIONS = {
|
||||
.width = 1280,
|
||||
.height = 720,
|
||||
};
|
||||
|
||||
/* converts Mbps to bps (the "b" part can be bits or bytes based on context) */
|
||||
#define kbps(__mbps) ((__mbps) * 1000)
|
||||
#define bps(__mbps) (kbps(__mbps) * 1000)
|
||||
|
||||
#define GENERATE_COMPRESSION_PROFILE(__bpp, __worst) { \
|
||||
.bpp = __bpp, \
|
||||
.ratio = __worst, \
|
||||
}
|
||||
|
||||
/*
|
||||
* The below table is a structural representation of the following table:
|
||||
* Resolution | Bitrate | Compression Ratio |
|
||||
* ............|............|.........................................|
|
||||
* Width Height|Average High|Avg_8bpc Worst_8bpc Avg_10bpc Worst_10bpc|
|
||||
* 1280 720| 7 14| 1.69 1.28 1.49 1.23|
|
||||
* 1920 1080| 20 40| 1.69 1.28 1.49 1.23|
|
||||
* 2560 1440| 32 64| 2.2 1.26 1.97 1.22|
|
||||
* 3840 2160| 42 84| 2.2 1.26 1.97 1.22|
|
||||
* 4096 2160| 44 88| 2.2 1.26 1.97 1.22|
|
||||
* 4096 2304| 48 96| 2.2 1.26 1.97 1.22|
|
||||
*/
|
||||
static struct lut {
|
||||
int frame_size; /* width x height */
|
||||
int frame_rate;
|
||||
unsigned long bitrate;
|
||||
struct {
|
||||
int bpp;
|
||||
fp_t ratio;
|
||||
} compression_ratio[COMPRESSION_RATIO_MAX];
|
||||
} const LUT[] = {
|
||||
{
|
||||
.frame_size = 1280 * 720,
|
||||
.frame_rate = 30,
|
||||
.bitrate = 14,
|
||||
.compression_ratio = {
|
||||
GENERATE_COMPRESSION_PROFILE(8,
|
||||
FP(1, 28, 100)),
|
||||
GENERATE_COMPRESSION_PROFILE(10,
|
||||
FP(1, 23, 100)),
|
||||
}
|
||||
},
|
||||
{
|
||||
.frame_size = 1280 * 720,
|
||||
.frame_rate = 60,
|
||||
.bitrate = 22,
|
||||
.compression_ratio = {
|
||||
GENERATE_COMPRESSION_PROFILE(8,
|
||||
FP(1, 28, 100)),
|
||||
GENERATE_COMPRESSION_PROFILE(10,
|
||||
FP(1, 23, 100)),
|
||||
}
|
||||
},
|
||||
{
|
||||
.frame_size = 1920 * 1088,
|
||||
.frame_rate = 30,
|
||||
.bitrate = 40,
|
||||
.compression_ratio = {
|
||||
GENERATE_COMPRESSION_PROFILE(8,
|
||||
FP(1, 28, 100)),
|
||||
GENERATE_COMPRESSION_PROFILE(10,
|
||||
FP(1, 23, 100)),
|
||||
}
|
||||
},
|
||||
{
|
||||
.frame_size = 1920 * 1088,
|
||||
.frame_rate = 60,
|
||||
.bitrate = 64,
|
||||
.compression_ratio = {
|
||||
GENERATE_COMPRESSION_PROFILE(8,
|
||||
FP(1, 28, 100)),
|
||||
GENERATE_COMPRESSION_PROFILE(10,
|
||||
FP(1, 23, 100)),
|
||||
}
|
||||
},
|
||||
{
|
||||
.frame_size = 2560 * 1440,
|
||||
.frame_rate = 30,
|
||||
.bitrate = 64,
|
||||
.compression_ratio = {
|
||||
GENERATE_COMPRESSION_PROFILE(8,
|
||||
FP(1, 26, 100)),
|
||||
GENERATE_COMPRESSION_PROFILE(10,
|
||||
FP(1, 22, 100)),
|
||||
}
|
||||
},
|
||||
{
|
||||
.frame_size = 2560 * 1440,
|
||||
.frame_rate = 60,
|
||||
.bitrate = 102,
|
||||
.compression_ratio = {
|
||||
GENERATE_COMPRESSION_PROFILE(8,
|
||||
FP(1, 26, 100)),
|
||||
GENERATE_COMPRESSION_PROFILE(10,
|
||||
FP(1, 22, 100)),
|
||||
}
|
||||
},
|
||||
{
|
||||
.frame_size = 3840 * 2160,
|
||||
.frame_rate = 30,
|
||||
.bitrate = 84,
|
||||
.compression_ratio = {
|
||||
GENERATE_COMPRESSION_PROFILE(8,
|
||||
FP(1, 26, 100)),
|
||||
GENERATE_COMPRESSION_PROFILE(10,
|
||||
FP(1, 22, 100)),
|
||||
}
|
||||
},
|
||||
{
|
||||
.frame_size = 3840 * 2160,
|
||||
.frame_rate = 60,
|
||||
.bitrate = 134,
|
||||
.compression_ratio = {
|
||||
GENERATE_COMPRESSION_PROFILE(8,
|
||||
FP(1, 26, 100)),
|
||||
GENERATE_COMPRESSION_PROFILE(10,
|
||||
FP(1, 22, 100)),
|
||||
}
|
||||
},
|
||||
{
|
||||
.frame_size = 4096 * 2160,
|
||||
.frame_rate = 30,
|
||||
.bitrate = 88,
|
||||
.compression_ratio = {
|
||||
GENERATE_COMPRESSION_PROFILE(8,
|
||||
FP(1, 26, 100)),
|
||||
GENERATE_COMPRESSION_PROFILE(10,
|
||||
FP(1, 22, 100)),
|
||||
}
|
||||
},
|
||||
{
|
||||
.frame_size = 4096 * 2160,
|
||||
.frame_rate = 60,
|
||||
.bitrate = 141,
|
||||
.compression_ratio = {
|
||||
GENERATE_COMPRESSION_PROFILE(8,
|
||||
FP(1, 26, 100)),
|
||||
GENERATE_COMPRESSION_PROFILE(10,
|
||||
FP(1, 22, 100)),
|
||||
}
|
||||
},
|
||||
{
|
||||
.frame_size = 4096 * 2304,
|
||||
.frame_rate = 30,
|
||||
.bitrate = 96,
|
||||
.compression_ratio = {
|
||||
GENERATE_COMPRESSION_PROFILE(8,
|
||||
FP(1, 26, 100)),
|
||||
GENERATE_COMPRESSION_PROFILE(10,
|
||||
FP(1, 22, 100)),
|
||||
}
|
||||
},
|
||||
{
|
||||
.frame_size = 4096 * 2304,
|
||||
.frame_rate = 60,
|
||||
.bitrate = 154,
|
||||
.compression_ratio = {
|
||||
GENERATE_COMPRESSION_PROFILE(8,
|
||||
FP(1, 26, 100)),
|
||||
GENERATE_COMPRESSION_PROFILE(10,
|
||||
FP(1, 22, 100)),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static inline u32 get_type_frm_name(const char *name)
|
||||
{
|
||||
if (!strcmp(name, "venus-llcc"))
|
||||
return LLCC;
|
||||
else if (!strcmp(name, "venus-ddr"))
|
||||
return DDR;
|
||||
else
|
||||
return PERF;
|
||||
}
|
||||
|
||||
#define DUMP_HEADER_MAGIC 0xdeadbeef
|
||||
#define DUMP_FP_FMT "%FP" /* special format for fp_t */
|
||||
|
||||
struct dump {
|
||||
char *key;
|
||||
char *format;
|
||||
size_t val;
|
||||
};
|
||||
|
||||
struct lut const *__lut(int width, int height, int fps);
|
||||
fp_t __compression_ratio(struct lut const *entry, int bpp);
|
||||
void __dump(struct dump dump[], int len);
|
||||
|
||||
static inline bool __ubwc(enum msm_vidc_colorformat_type f)
|
||||
{
|
||||
switch (f) {
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int __bpp(enum msm_vidc_colorformat_type f)
|
||||
{
|
||||
switch (f) {
|
||||
case MSM_VIDC_FMT_NV12:
|
||||
case MSM_VIDC_FMT_NV21:
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
case MSM_VIDC_FMT_RGBA8888C:
|
||||
return 8;
|
||||
case MSM_VIDC_FMT_P010:
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
return 10;
|
||||
default:
|
||||
d_vpr_e("Unsupported colorformat (%x)", f);
|
||||
return INT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
u64 msm_vidc_max_freq(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_scale_power(struct msm_vidc_inst *inst, bool scale_buses);
|
||||
void msm_vidc_power_data_reset(struct msm_vidc_inst *inst);
|
||||
|
||||
#endif
|
116
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_state.h
Normal file
116
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_state.h
Normal file
@ -0,0 +1,116 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_STATE_H_
|
||||
#define _MSM_VIDC_STATE_H_
|
||||
|
||||
#include "msm_vidc_internal.h"
|
||||
|
||||
struct msm_vidc_core;
|
||||
|
||||
#define FOREACH_CORE_STATE(CORE_STATE) { \
|
||||
CORE_STATE(CORE_DEINIT) \
|
||||
CORE_STATE(CORE_INIT_WAIT) \
|
||||
CORE_STATE(CORE_INIT) \
|
||||
CORE_STATE(CORE_ERROR) \
|
||||
}
|
||||
|
||||
#define FOREACH_EVENT(EVENT) { \
|
||||
EVENT(TRY_FMT) \
|
||||
EVENT(S_FMT) \
|
||||
EVENT(REQBUFS) \
|
||||
EVENT(S_CTRL) \
|
||||
EVENT(STREAMON) \
|
||||
EVENT(STREAMOFF) \
|
||||
EVENT(CMD_START) \
|
||||
EVENT(CMD_STOP) \
|
||||
EVENT(BUF_QUEUE) \
|
||||
}
|
||||
|
||||
enum msm_vidc_core_state FOREACH_CORE_STATE(GENERATE_MSM_VIDC_ENUM);
|
||||
|
||||
enum msm_vidc_core_sub_state {
|
||||
CORE_SUBSTATE_NONE = 0x0,
|
||||
CORE_SUBSTATE_POWER_ENABLE = BIT(0),
|
||||
CORE_SUBSTATE_GDSC_HANDOFF = BIT(1),
|
||||
CORE_SUBSTATE_PM_SUSPEND = BIT(2),
|
||||
CORE_SUBSTATE_FW_PWR_CTRL = BIT(3),
|
||||
CORE_SUBSTATE_PAGE_FAULT = BIT(4),
|
||||
CORE_SUBSTATE_CPU_WATCHDOG = BIT(5),
|
||||
CORE_SUBSTATE_VIDEO_UNRESPONSIVE = BIT(6),
|
||||
CORE_SUBSTATE_MAX = BIT(7),
|
||||
};
|
||||
|
||||
enum msm_vidc_core_event_type {
|
||||
CORE_EVENT_NONE = BIT(0),
|
||||
CORE_EVENT_UPDATE_SUB_STATE = BIT(1),
|
||||
};
|
||||
|
||||
#define FOREACH_STATE(STATE) { \
|
||||
STATE(OPEN) \
|
||||
STATE(INPUT_STREAMING) \
|
||||
STATE(OUTPUT_STREAMING) \
|
||||
STATE(STREAMING) \
|
||||
STATE(CLOSE) \
|
||||
STATE(ERROR) \
|
||||
}
|
||||
|
||||
enum msm_vidc_state FOREACH_STATE(GENERATE_MSM_VIDC_ENUM);
|
||||
|
||||
#define MSM_VIDC_SUB_STATE_NONE 0
|
||||
#define MSM_VIDC_MAX_SUB_STATES 7
|
||||
/*
|
||||
* max value of inst->sub_state if all
|
||||
* the 6 valid bits are set i.e 111111==>63
|
||||
*/
|
||||
#define MSM_VIDC_MAX_SUB_STATE_VALUE ((1 << MSM_VIDC_MAX_SUB_STATES) - 1)
|
||||
|
||||
enum msm_vidc_sub_state {
|
||||
MSM_VIDC_DRAIN = BIT(0),
|
||||
MSM_VIDC_DRC = BIT(1),
|
||||
MSM_VIDC_DRAIN_LAST_BUFFER = BIT(2),
|
||||
MSM_VIDC_DRC_LAST_BUFFER = BIT(3),
|
||||
MSM_VIDC_INPUT_PAUSE = BIT(4),
|
||||
MSM_VIDC_OUTPUT_PAUSE = BIT(5),
|
||||
MSM_VIDC_FIRST_IPSC = BIT(6),
|
||||
};
|
||||
|
||||
enum msm_vidc_event FOREACH_EVENT(GENERATE_MSM_VIDC_ENUM);
|
||||
|
||||
/* core statemachine functions */
|
||||
enum msm_vidc_allow
|
||||
msm_vidc_allow_core_state_change(struct msm_vidc_core *core,
|
||||
enum msm_vidc_core_state req_state);
|
||||
int msm_vidc_update_core_state(struct msm_vidc_core *core,
|
||||
enum msm_vidc_core_state request_state,
|
||||
const char *func);
|
||||
bool core_in_valid_state(struct msm_vidc_core *core);
|
||||
bool is_core_state(struct msm_vidc_core *core, enum msm_vidc_core_state state);
|
||||
bool is_core_sub_state(struct msm_vidc_core *core,
|
||||
enum msm_vidc_core_sub_state sub_state);
|
||||
const char *core_state_name(enum msm_vidc_core_state state);
|
||||
const char *core_sub_state_name(enum msm_vidc_core_sub_state sub_state);
|
||||
|
||||
/* inst statemachine functions */
|
||||
bool is_drc_pending(struct msm_vidc_inst *inst);
|
||||
bool is_drain_pending(struct msm_vidc_inst *inst);
|
||||
int msm_vidc_update_state(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_state request_state,
|
||||
const char *func);
|
||||
int msm_vidc_change_state(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_state request_state,
|
||||
const char *func);
|
||||
int msm_vidc_change_sub_state(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_sub_state clear_sub_state,
|
||||
enum msm_vidc_sub_state set_sub_state,
|
||||
const char *func);
|
||||
const char *state_name(enum msm_vidc_state state);
|
||||
const char *sub_state_name(enum msm_vidc_sub_state sub_state);
|
||||
bool is_state(struct msm_vidc_inst *inst, enum msm_vidc_state state);
|
||||
bool is_sub_state(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_sub_state sub_state);
|
||||
|
||||
#endif // _MSM_VIDC_STATE_H_
|
13
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_synx.h
Normal file
13
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_synx.h
Normal file
@ -0,0 +1,13 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _H_MSM_VIDC_SYNX_H_
|
||||
#define _H_MSM_VIDC_SYNX_H_
|
||||
|
||||
#include "msm_vidc_fence.h"
|
||||
|
||||
const struct msm_vidc_fence_ops *get_synx_fence_ops(void);
|
||||
|
||||
#endif //_H_MSM_VIDC_SYNX_H_
|
79
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_v4l2.h
Normal file
79
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_v4l2.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_V4L2_H_
|
||||
#define _MSM_VIDC_V4L2_H_
|
||||
|
||||
#include <linux/poll.h>
|
||||
#include <linux/fs.h>
|
||||
#include <media/v4l2-dev.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
|
||||
int msm_v4l2_open(struct file *filp);
|
||||
int msm_v4l2_close(struct file *filp);
|
||||
int msm_v4l2_querycap(struct file *filp, void *fh,
|
||||
struct v4l2_capability *cap);
|
||||
int msm_v4l2_enum_fmt(struct file *file, void *fh,
|
||||
struct v4l2_fmtdesc *f);
|
||||
int msm_v4l2_try_fmt(struct file *file, void *fh,
|
||||
struct v4l2_format *f);
|
||||
int msm_v4l2_s_fmt(struct file *file, void *fh,
|
||||
struct v4l2_format *f);
|
||||
int msm_v4l2_g_fmt(struct file *file, void *fh,
|
||||
struct v4l2_format *f);
|
||||
int msm_v4l2_s_selection(struct file *file, void *fh,
|
||||
struct v4l2_selection *s);
|
||||
int msm_v4l2_g_selection(struct file *file, void *fh,
|
||||
struct v4l2_selection *s);
|
||||
int msm_v4l2_s_parm(struct file *file, void *fh,
|
||||
struct v4l2_streamparm *a);
|
||||
int msm_v4l2_g_parm(struct file *file, void *fh,
|
||||
struct v4l2_streamparm *a);
|
||||
int msm_v4l2_reqbufs(struct file *file, void *fh,
|
||||
struct v4l2_requestbuffers *b);
|
||||
int msm_v4l2_querybuf(struct file *file, void *fh,
|
||||
struct v4l2_buffer *b);
|
||||
int msm_v4l2_create_bufs(struct file *filp, void *fh,
|
||||
struct v4l2_create_buffers *b);
|
||||
int msm_v4l2_prepare_buf(struct file *filp, void *fh,
|
||||
struct v4l2_buffer *b);
|
||||
int msm_v4l2_qbuf(struct file *file, void *fh,
|
||||
struct v4l2_buffer *b);
|
||||
int msm_v4l2_dqbuf(struct file *file, void *fh,
|
||||
struct v4l2_buffer *b);
|
||||
int msm_v4l2_streamon(struct file *file, void *fh,
|
||||
enum v4l2_buf_type i);
|
||||
int msm_v4l2_streamoff(struct file *file, void *fh,
|
||||
enum v4l2_buf_type i);
|
||||
int msm_v4l2_subscribe_event(struct v4l2_fh *fh,
|
||||
const struct v4l2_event_subscription *sub);
|
||||
int msm_v4l2_unsubscribe_event(struct v4l2_fh *fh,
|
||||
const struct v4l2_event_subscription *sub);
|
||||
int msm_v4l2_try_decoder_cmd(struct file *file, void *fh,
|
||||
struct v4l2_decoder_cmd *enc);
|
||||
int msm_v4l2_decoder_cmd(struct file *file, void *fh,
|
||||
struct v4l2_decoder_cmd *dec);
|
||||
int msm_v4l2_try_encoder_cmd(struct file *file, void *fh,
|
||||
struct v4l2_encoder_cmd *enc);
|
||||
int msm_v4l2_encoder_cmd(struct file *file, void *fh,
|
||||
struct v4l2_encoder_cmd *enc);
|
||||
int msm_v4l2_enum_framesizes(struct file *file, void *fh,
|
||||
struct v4l2_frmsizeenum *fsize);
|
||||
int msm_v4l2_enum_frameintervals(struct file *file, void *fh,
|
||||
struct v4l2_frmivalenum *fival);
|
||||
int msm_v4l2_queryctrl(struct file *file, void *fh,
|
||||
struct v4l2_queryctrl *ctrl);
|
||||
int msm_v4l2_querymenu(struct file *file, void *fh,
|
||||
struct v4l2_querymenu *qmenu);
|
||||
unsigned int msm_v4l2_poll(struct file *filp,
|
||||
struct poll_table_struct *pt);
|
||||
int msm_v4l2_request_validate(struct media_request *req);
|
||||
void msm_v4l2_request_queue(struct media_request *req);
|
||||
void msm_v4l2_m2m_device_run(void *priv);
|
||||
void msm_v4l2_m2m_job_abort(void *priv);
|
||||
|
||||
#endif // _MSM_VIDC_V4L2_H_
|
52
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_vb2.h
Normal file
52
qcom/opensource/video-driver/driver/vidc/inc/msm_vidc_vb2.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_VB2_H_
|
||||
#define _MSM_VIDC_VB2_H_
|
||||
|
||||
#include <media/videobuf2-core.h>
|
||||
#include <media/videobuf2-v4l2.h>
|
||||
#include "msm_vidc_inst.h"
|
||||
|
||||
struct vb2_queue *msm_vidc_get_vb2q(struct msm_vidc_inst *inst,
|
||||
u32 type, const char *func);
|
||||
|
||||
/* vb2_mem_ops */
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0))
|
||||
void *msm_vb2_alloc(struct device *dev, unsigned long attrs,
|
||||
unsigned long size, enum dma_data_direction dma_dir,
|
||||
gfp_t gfp_flags);
|
||||
void *msm_vb2_attach_dmabuf(struct device *dev,
|
||||
struct dma_buf *dbuf,
|
||||
unsigned long size,
|
||||
enum dma_data_direction dma_dir);
|
||||
#else
|
||||
void *msm_vb2_alloc(struct vb2_buffer *vb, struct device *dev,
|
||||
unsigned long size);
|
||||
void *msm_vb2_attach_dmabuf(struct vb2_buffer *vb, struct device *dev,
|
||||
struct dma_buf *dbuf, unsigned long size);
|
||||
#endif
|
||||
|
||||
void msm_vb2_put(void *buf_priv);
|
||||
int msm_vb2_mmap(void *buf_priv, struct vm_area_struct *vma);
|
||||
void msm_vb2_detach_dmabuf(void *buf_priv);
|
||||
int msm_vb2_map_dmabuf(void *buf_priv);
|
||||
void msm_vb2_unmap_dmabuf(void *buf_priv);
|
||||
|
||||
/* vb2_ops */
|
||||
int msm_vb2_queue_setup(struct vb2_queue *q,
|
||||
unsigned int *num_buffers,
|
||||
unsigned int *num_planes,
|
||||
unsigned int sizes[],
|
||||
struct device *alloc_devs[]);
|
||||
int msm_vidc_start_streaming(struct msm_vidc_inst *inst, struct vb2_queue *q);
|
||||
int msm_vidc_stop_streaming(struct msm_vidc_inst *inst, struct vb2_queue *q);
|
||||
int msm_vb2_start_streaming(struct vb2_queue *q, unsigned int count);
|
||||
void msm_vb2_stop_streaming(struct vb2_queue *q);
|
||||
void msm_vb2_buf_queue(struct vb2_buffer *vb2);
|
||||
int msm_vb2_buf_out_validate(struct vb2_buffer *vb);
|
||||
void msm_vb2_request_complete(struct vb2_buffer *vb);
|
||||
#endif // _MSM_VIDC_VB2_H_
|
293
qcom/opensource/video-driver/driver/vidc/inc/resources.h
Normal file
293
qcom/opensource/video-driver/driver/vidc/inc/resources.h
Normal file
@ -0,0 +1,293 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_VIDC_RESOURCES_H_
|
||||
#define _MSM_VIDC_RESOURCES_H_
|
||||
|
||||
struct icc_path;
|
||||
struct regulator;
|
||||
struct clk;
|
||||
struct reset_control;
|
||||
struct llcc_slice_desc;
|
||||
struct iommu_domain;
|
||||
struct device;
|
||||
struct msm_vidc_core;
|
||||
|
||||
/*
|
||||
* These are helper macros to iterate over various lists within
|
||||
* msm_vidc_core->resource. The intention is to cut down on a lot
|
||||
* of boiler-plate code
|
||||
*/
|
||||
|
||||
/* Read as "for each 'thing' in a set of 'thingies'" */
|
||||
#define venus_hfi_for_each_thing(__device, __thing, __thingy) \
|
||||
venus_hfi_for_each_thing_continue(__device, __thing, __thingy, 0)
|
||||
|
||||
#define venus_hfi_for_each_thing_reverse(__device, __thing, __thingy) \
|
||||
venus_hfi_for_each_thing_reverse_continue(__device, __thing, __thingy, \
|
||||
(__device)->resource->__thingy##_set.count - 1)
|
||||
|
||||
/* TODO: the __from parameter technically not required since we can figure it
|
||||
* out with some pointer magic (i.e. __thing - __thing##_tbl[0]). If this macro
|
||||
* sees extensive use, probably worth cleaning it up but for now omitting it
|
||||
* since it introduces unnecessary complexity.
|
||||
*/
|
||||
#define venus_hfi_for_each_thing_continue(__device, __thing, __thingy, __from) \
|
||||
for (__thing = &(__device)->resource->\
|
||||
__thingy##_set.__thingy##_tbl[__from]; \
|
||||
__thing < &(__device)->resource->__thingy##_set.__thingy##_tbl[0] + \
|
||||
((__device)->resource->__thingy##_set.count - __from); \
|
||||
++__thing)
|
||||
|
||||
#define venus_hfi_for_each_thing_reverse_continue(__device, __thing, __thingy, \
|
||||
__from) \
|
||||
for (__thing = &(__device)->resource->\
|
||||
__thingy##_set.__thingy##_tbl[__from]; \
|
||||
__thing >= &(__device)->resource->__thingy##_set.__thingy##_tbl[0]; \
|
||||
--__thing)
|
||||
|
||||
/* Bus set helpers */
|
||||
#define venus_hfi_for_each_bus(__device, __binfo) \
|
||||
venus_hfi_for_each_thing(__device, __binfo, bus)
|
||||
#define venus_hfi_for_each_bus_reverse(__device, __binfo) \
|
||||
venus_hfi_for_each_thing_reverse(__device, __binfo, bus)
|
||||
|
||||
/* Regular set helpers */
|
||||
#define venus_hfi_for_each_regulator(__device, __rinfo) \
|
||||
venus_hfi_for_each_thing(__device, __rinfo, regulator)
|
||||
#define venus_hfi_for_each_regulator_reverse(__device, __rinfo) \
|
||||
venus_hfi_for_each_thing_reverse(__device, __rinfo, regulator)
|
||||
#define venus_hfi_for_each_regulator_reverse_continue(__device, __rinfo, \
|
||||
__from) \
|
||||
venus_hfi_for_each_thing_reverse_continue(__device, __rinfo, \
|
||||
regulator, __from)
|
||||
|
||||
/* Power domain set helpers */
|
||||
#define venus_hfi_for_each_power_domain(__device, __pdinfo) \
|
||||
venus_hfi_for_each_thing(__device, __pdinfo, power_domain)
|
||||
|
||||
/* Clock set helpers */
|
||||
#define venus_hfi_for_each_clock(__device, __cinfo) \
|
||||
venus_hfi_for_each_thing(__device, __cinfo, clock)
|
||||
#define venus_hfi_for_each_clock_reverse(__device, __cinfo) \
|
||||
venus_hfi_for_each_thing_reverse(__device, __cinfo, clock)
|
||||
|
||||
/* Reset clock set helpers */
|
||||
#define venus_hfi_for_each_reset_clock(__device, __rcinfo) \
|
||||
venus_hfi_for_each_thing(__device, __rcinfo, reset)
|
||||
#define venus_hfi_for_each_reset_clock_reverse(__device, __rcinfo) \
|
||||
venus_hfi_for_each_thing_reverse(__device, __rcinfo, reset)
|
||||
#define venus_hfi_for_each_reset_clock_reverse_continue(__device, __rinfo, \
|
||||
__from) \
|
||||
venus_hfi_for_each_thing_reverse_continue(__device, __rinfo, \
|
||||
reset, __from)
|
||||
|
||||
/* Subcache set helpers */
|
||||
#define venus_hfi_for_each_subcache(__device, __sinfo) \
|
||||
venus_hfi_for_each_thing(__device, __sinfo, subcache)
|
||||
#define venus_hfi_for_each_subcache_reverse(__device, __sinfo) \
|
||||
venus_hfi_for_each_thing_reverse(__device, __sinfo, subcache)
|
||||
|
||||
/* Contextbank set helpers */
|
||||
#define venus_hfi_for_each_context_bank(__device, __sinfo) \
|
||||
venus_hfi_for_each_thing(__device, __sinfo, context_bank)
|
||||
#define venus_hfi_for_each_context_bank_reverse(__device, __sinfo) \
|
||||
venus_hfi_for_each_thing_reverse(__device, __sinfo, context_bank)
|
||||
|
||||
/* Device region set helper */
|
||||
#define venus_hfi_for_each_device_region(__device, __sinfo) \
|
||||
venus_hfi_for_each_thing(__device, __sinfo, device_region)
|
||||
|
||||
enum msm_vidc_branch_mem_flags {
|
||||
MSM_VIDC_CLKFLAG_RETAIN_PERIPH,
|
||||
MSM_VIDC_CLKFLAG_NORETAIN_PERIPH,
|
||||
MSM_VIDC_CLKFLAG_RETAIN_MEM,
|
||||
MSM_VIDC_CLKFLAG_NORETAIN_MEM,
|
||||
MSM_VIDC_CLKFLAG_PERIPH_OFF_SET,
|
||||
MSM_VIDC_CLKFLAG_PERIPH_OFF_CLEAR,
|
||||
};
|
||||
|
||||
struct bus_info {
|
||||
struct icc_path *icc;
|
||||
const char *name;
|
||||
u32 min_kbps;
|
||||
u32 max_kbps;
|
||||
};
|
||||
|
||||
struct bus_set {
|
||||
struct bus_info *bus_tbl;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct regulator_info {
|
||||
struct regulator *regulator;
|
||||
const char *name;
|
||||
bool hw_power_collapse;
|
||||
};
|
||||
|
||||
struct regulator_set {
|
||||
struct regulator_info *regulator_tbl;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct power_domain_info {
|
||||
struct device *genpd_dev;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct power_domain_set {
|
||||
struct power_domain_info *power_domain_tbl;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct clock_residency {
|
||||
struct list_head list;
|
||||
u64 rate;
|
||||
u64 start_time_us;
|
||||
u64 total_time_us;
|
||||
};
|
||||
|
||||
struct clock_info {
|
||||
struct clk *clk;
|
||||
const char *name;
|
||||
u32 clk_id;
|
||||
bool has_scaling;
|
||||
u64 prev;
|
||||
#ifdef CONFIG_MSM_MMRM
|
||||
struct mmrm_client *mmrm_client;
|
||||
#endif
|
||||
struct list_head residency_list; /* list of struct clock_residency */
|
||||
};
|
||||
|
||||
struct clock_set {
|
||||
struct clock_info *clock_tbl;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct reset_info {
|
||||
struct reset_control *rst;
|
||||
const char *name;
|
||||
bool exclusive_release;
|
||||
};
|
||||
|
||||
struct reset_set {
|
||||
struct reset_info *reset_tbl;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct subcache_info {
|
||||
struct llcc_slice_desc *subcache;
|
||||
const char *name;
|
||||
u32 llcc_id;
|
||||
bool isactive;
|
||||
};
|
||||
|
||||
struct subcache_set {
|
||||
struct subcache_info *subcache_tbl;
|
||||
u32 count;
|
||||
bool set_to_fw;
|
||||
};
|
||||
|
||||
struct addr_range {
|
||||
u32 start;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct context_bank_info {
|
||||
const char *name;
|
||||
struct addr_range addr_range;
|
||||
bool secure;
|
||||
bool dma_coherant;
|
||||
struct device *dev;
|
||||
struct iommu_domain *domain;
|
||||
u32 region;
|
||||
u64 dma_mask;
|
||||
};
|
||||
|
||||
struct context_bank_set {
|
||||
struct context_bank_info *context_bank_tbl;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct frequency_table {
|
||||
unsigned long freq;
|
||||
};
|
||||
|
||||
struct freq_set {
|
||||
struct frequency_table *freq_tbl;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct device_region_info {
|
||||
const char *name;
|
||||
phys_addr_t phy_addr;
|
||||
u32 size;
|
||||
u32 dev_addr;
|
||||
u32 region;
|
||||
};
|
||||
|
||||
struct device_region_set {
|
||||
struct device_region_info *device_region_tbl;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct msm_vidc_resource {
|
||||
u8 __iomem *register_base_addr;
|
||||
u32 irq;
|
||||
struct bus_set bus_set;
|
||||
struct regulator_set regulator_set;
|
||||
struct power_domain_set power_domain_set;
|
||||
struct clock_set clock_set;
|
||||
struct reset_set reset_set;
|
||||
struct subcache_set subcache_set;
|
||||
struct context_bank_set context_bank_set;
|
||||
struct freq_set freq_set;
|
||||
struct device_region_set device_region_set;
|
||||
int fw_cookie;
|
||||
};
|
||||
|
||||
#define call_res_op(c, op, ...) \
|
||||
(((c) && (c)->res_ops && (c)->res_ops->op) ? \
|
||||
((c)->res_ops->op(__VA_ARGS__)) : 0)
|
||||
|
||||
struct msm_vidc_resources_ops {
|
||||
int (*init)(struct msm_vidc_core *core);
|
||||
|
||||
int (*reset_bridge)(struct msm_vidc_core *core);
|
||||
int (*reset_control_acquire)(struct msm_vidc_core *core,
|
||||
const char *name);
|
||||
int (*reset_control_release)(struct msm_vidc_core *core,
|
||||
const char *name);
|
||||
int (*reset_control_assert)(struct msm_vidc_core *core,
|
||||
const char *name);
|
||||
int (*reset_control_deassert)(struct msm_vidc_core *core,
|
||||
const char *name);
|
||||
|
||||
int (*gdsc_init)(struct msm_vidc_core *core);
|
||||
int (*gdsc_on)(struct msm_vidc_core *core, const char *name);
|
||||
int (*gdsc_off)(struct msm_vidc_core *core, const char *name);
|
||||
int (*gdsc_hw_ctrl)(struct msm_vidc_core *core);
|
||||
int (*gdsc_sw_ctrl)(struct msm_vidc_core *core);
|
||||
|
||||
int (*llcc)(struct msm_vidc_core *core, bool enable);
|
||||
int (*set_bw)(struct msm_vidc_core *core, unsigned long bw_ddr,
|
||||
unsigned long bw_llcc);
|
||||
int (*set_clks)(struct msm_vidc_core *core, u64 rate);
|
||||
|
||||
int (*clk_disable)(struct msm_vidc_core *core, const char *name);
|
||||
int (*clk_enable)(struct msm_vidc_core *core, const char *name);
|
||||
int (*clk_set_flag)(struct msm_vidc_core *core,
|
||||
const char *name,
|
||||
enum msm_vidc_branch_mem_flags flag);
|
||||
int (*clk_print_residency_stats)(struct msm_vidc_core *core);
|
||||
int (*clk_reset_residency_stats)(struct msm_vidc_core *core);
|
||||
int (*clk_update_residency_stats)(struct msm_vidc_core *core,
|
||||
struct clock_info *cl, u64 rate);
|
||||
};
|
||||
|
||||
const struct msm_vidc_resources_ops *get_resources_ops(void);
|
||||
|
||||
#endif
|
13
qcom/opensource/video-driver/driver/vidc/inc/resources_ext.h
Normal file
13
qcom/opensource/video-driver/driver/vidc/inc/resources_ext.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _RESOURCES_EXT_H_
|
||||
#define _RESOURCES_EXT_H_
|
||||
|
||||
struct msm_vidc_resources_ops;
|
||||
|
||||
const struct msm_vidc_resources_ops *get_res_ops_ext(void);
|
||||
|
||||
#endif // _RESOURCES_EXT_H_
|
85
qcom/opensource/video-driver/driver/vidc/inc/venus_hfi.h
Normal file
85
qcom/opensource/video-driver/driver/vidc/inc/venus_hfi.h
Normal file
@ -0,0 +1,85 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _VENUS_HFI_H_
|
||||
#define _VENUS_HFI_H_
|
||||
|
||||
#include <linux/irqreturn.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_core.h"
|
||||
|
||||
#define VIDC_MAX_PC_SKIP_COUNT 10
|
||||
|
||||
struct vidc_buffer_addr_info {
|
||||
enum msm_vidc_buffer_type buffer_type;
|
||||
u32 buffer_size;
|
||||
u32 num_buffers;
|
||||
u32 align_device_addr;
|
||||
u32 extradata_addr;
|
||||
u32 extradata_size;
|
||||
u32 response_required;
|
||||
};
|
||||
|
||||
struct hfi_pending_packet {
|
||||
struct list_head list;
|
||||
void *data;
|
||||
};
|
||||
|
||||
int __strict_check(struct msm_vidc_core *core,
|
||||
const char *function);
|
||||
int venus_hfi_session_property(struct msm_vidc_inst *inst,
|
||||
u32 pkt_type, u32 flags, u32 port,
|
||||
u32 payload_type, void *payload,
|
||||
u32 payload_size);
|
||||
int venus_hfi_session_command(struct msm_vidc_inst *inst,
|
||||
u32 cmd, enum msm_vidc_port_type port,
|
||||
u32 payload_type,
|
||||
void *payload, u32 payload_size);
|
||||
int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_buffer *buffer,
|
||||
struct msm_vidc_buffer *metabuf);
|
||||
int venus_hfi_queue_super_buffer(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_buffer *buffer,
|
||||
struct msm_vidc_buffer *metabuf);
|
||||
int venus_hfi_release_buffer(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_buffer *buffer);
|
||||
int venus_hfi_start(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
|
||||
int venus_hfi_stop(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
|
||||
int venus_hfi_session_close(struct msm_vidc_inst *inst);
|
||||
int venus_hfi_session_open(struct msm_vidc_inst *inst);
|
||||
int venus_hfi_session_pause(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
|
||||
int venus_hfi_session_resume(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_port_type port, u32 payload);
|
||||
int venus_hfi_session_drain(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
|
||||
int venus_hfi_session_set_codec(struct msm_vidc_inst *inst);
|
||||
int venus_hfi_session_set_secure_mode(struct msm_vidc_inst *inst);
|
||||
int venus_hfi_core_init(struct msm_vidc_core *core);
|
||||
int venus_hfi_core_deinit(struct msm_vidc_core *core, bool force);
|
||||
int venus_hfi_noc_error_info(struct msm_vidc_core *core);
|
||||
int venus_hfi_suspend(struct msm_vidc_core *core);
|
||||
int venus_hfi_trigger_ssr(struct msm_vidc_core *core, u32 type,
|
||||
u32 client_id, u32 addr);
|
||||
int venus_hfi_trigger_stability(struct msm_vidc_inst *inst, u32 type,
|
||||
u32 client_id, u32 val);
|
||||
int venus_hfi_reserve_hardware(struct msm_vidc_inst *inst, u32 duration);
|
||||
int venus_hfi_scale_clocks(struct msm_vidc_inst *inst, u64 freq);
|
||||
int venus_hfi_scale_buses(struct msm_vidc_inst *inst, u64 bw_ddr, u64 bw_llcc);
|
||||
int venus_hfi_set_ir_period(struct msm_vidc_inst *inst, u32 ir_type,
|
||||
enum msm_vidc_inst_capability_type cap_id);
|
||||
void venus_hfi_pm_work_handler(struct work_struct *work);
|
||||
irqreturn_t venus_hfi_isr(int irq, void *data);
|
||||
irqreturn_t venus_hfi_isr_handler(int irq, void *data);
|
||||
int __prepare_pc(struct msm_vidc_core *core);
|
||||
struct device_region_info
|
||||
*venus_hfi_get_device_region_info(struct msm_vidc_core *core,
|
||||
enum msm_vidc_device_region region);
|
||||
|
||||
#endif // _VENUS_HFI_H_
|
@ -0,0 +1,96 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _VENUS_HFI_QUEUE_H_
|
||||
#define _VENUS_HFI_QUEUE_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "msm_vidc_internal.h"
|
||||
|
||||
#define HFI_MASK_QHDR_TX_TYPE 0xff000000
|
||||
#define HFI_MASK_QHDR_RX_TYPE 0x00ff0000
|
||||
#define HFI_MASK_QHDR_PRI_TYPE 0x0000ff00
|
||||
#define HFI_MASK_QHDR_Q_ID_TYPE 0x000000ff
|
||||
#define HFI_Q_ID_HOST_TO_CTRL_CMD_Q 0
|
||||
#define HFI_Q_ID_CTRL_TO_HOST_MSG_Q 1
|
||||
#define HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q 2
|
||||
#define HFI_MASK_QHDR_STATUS 0x000000ff
|
||||
|
||||
#define VIDC_IFACEQ_NUMQ 3
|
||||
#define VIDC_IFACEQ_CMDQ_IDX 0
|
||||
#define VIDC_IFACEQ_MSGQ_IDX 1
|
||||
#define VIDC_IFACEQ_DBGQ_IDX 2
|
||||
#define VIDC_IFACEQ_MAX_BUF_COUNT 50
|
||||
#define VIDC_IFACE_MAX_PARALLEL_CLNTS 16
|
||||
#define VIDC_IFACEQ_DFLT_QHDR 0x01010000
|
||||
|
||||
struct hfi_queue_table_header {
|
||||
u32 qtbl_version;
|
||||
u32 qtbl_size;
|
||||
u32 qtbl_qhdr0_offset;
|
||||
u32 qtbl_qhdr_size;
|
||||
u32 qtbl_num_q;
|
||||
u32 qtbl_num_active_q;
|
||||
void *device_addr;
|
||||
char name[256];
|
||||
};
|
||||
|
||||
struct hfi_queue_header {
|
||||
u32 qhdr_status;
|
||||
u32 qhdr_start_addr;
|
||||
u32 qhdr_type;
|
||||
u32 qhdr_q_size;
|
||||
u32 qhdr_pkt_size;
|
||||
u32 qhdr_pkt_drop_cnt;
|
||||
u32 qhdr_rx_wm;
|
||||
u32 qhdr_tx_wm;
|
||||
u32 qhdr_rx_req;
|
||||
u32 qhdr_tx_req;
|
||||
u32 qhdr_rx_irq_status;
|
||||
u32 qhdr_tx_irq_status;
|
||||
u32 qhdr_read_idx;
|
||||
u32 qhdr_write_idx;
|
||||
};
|
||||
|
||||
#define VIDC_IFACEQ_TABLE_SIZE (sizeof(struct hfi_queue_table_header) + \
|
||||
sizeof(struct hfi_queue_header) * VIDC_IFACEQ_NUMQ)
|
||||
|
||||
#define VIDC_IFACEQ_QUEUE_SIZE (VIDC_IFACEQ_MAX_PKT_SIZE * \
|
||||
VIDC_IFACEQ_MAX_BUF_COUNT * VIDC_IFACE_MAX_PARALLEL_CLNTS)
|
||||
|
||||
#define VIDC_IFACEQ_GET_QHDR_START_ADDR(ptr, i) \
|
||||
((void *)((ptr + sizeof(struct hfi_queue_table_header)) + \
|
||||
(i * sizeof(struct hfi_queue_header))))
|
||||
|
||||
#define QDSS_SIZE 4096
|
||||
#define SFR_SIZE 4096
|
||||
#define MMAP_BUF_SIZE 4096
|
||||
|
||||
#define QUEUE_SIZE (VIDC_IFACEQ_TABLE_SIZE + \
|
||||
(VIDC_IFACEQ_QUEUE_SIZE * VIDC_IFACEQ_NUMQ))
|
||||
|
||||
#define ALIGNED_QDSS_SIZE ALIGN(QDSS_SIZE, SZ_4K)
|
||||
#define ALIGNED_SFR_SIZE ALIGN(SFR_SIZE, SZ_4K)
|
||||
#define ALIGNED_MMAP_BUF_SIZE ALIGN(MMAP_BUF_SIZE, SZ_4K)
|
||||
#define ALIGNED_QUEUE_SIZE ALIGN(QUEUE_SIZE, SZ_4K)
|
||||
#define SHARED_QSIZE ALIGN(ALIGNED_SFR_SIZE + ALIGNED_QUEUE_SIZE + \
|
||||
ALIGNED_QDSS_SIZE + ALIGNED_MMAP_BUF_SIZE, SZ_1M)
|
||||
#define TOTAL_QSIZE (SHARED_QSIZE - ALIGNED_SFR_SIZE - ALIGNED_QDSS_SIZE - \
|
||||
ALIGNED_MMAP_BUF_SIZE)
|
||||
|
||||
struct msm_vidc_core;
|
||||
|
||||
int venus_hfi_queue_cmd_write(struct msm_vidc_core *core, void *pkt);
|
||||
int venus_hfi_queue_cmd_write_intr(struct msm_vidc_core *core, void *pkt,
|
||||
bool allow_intr);
|
||||
int venus_hfi_queue_msg_read(struct msm_vidc_core *core, void *pkt);
|
||||
int venus_hfi_queue_dbg_read(struct msm_vidc_core *core, void *pkt);
|
||||
void venus_hfi_queue_deinit(struct msm_vidc_core *core);
|
||||
int venus_hfi_queue_init(struct msm_vidc_core *core);
|
||||
int venus_hfi_reset_queue_header(struct msm_vidc_core *core);
|
||||
|
||||
#endif
|
@ -0,0 +1,25 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __VENUS_HFI_RESPONSE_H__
|
||||
#define __VENUS_HFI_RESPONSE_H__
|
||||
|
||||
#include "hfi_packet.h"
|
||||
|
||||
int handle_response(struct msm_vidc_core *core,
|
||||
void *response);
|
||||
int validate_packet(u8 *response_pkt, u8 *core_resp_pkt,
|
||||
u32 core_resp_pkt_size, const char *func);
|
||||
bool is_valid_port(struct msm_vidc_inst *inst, u32 port,
|
||||
const char *func);
|
||||
bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst,
|
||||
u32 buffer_type, const char *func);
|
||||
int handle_system_error(struct msm_vidc_core *core,
|
||||
struct hfi_packet *pkt);
|
||||
int handle_release_output_buffer(struct msm_vidc_inst *inst,
|
||||
struct hfi_buffer *buffer);
|
||||
|
||||
#endif // __VENUS_HFI_RESPONSE_H__
|
294
qcom/opensource/video-driver/driver/vidc/src/firmware.c
Normal file
294
qcom/opensource/video-driver/driver/vidc/src/firmware.c
Normal file
@ -0,0 +1,294 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/devcoredump.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/qcom_scm.h>
|
||||
#include <linux/soc/qcom/mdt_loader.h>
|
||||
#include <linux/soc/qcom/smem.h>
|
||||
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
#include "msm_vidc_events.h"
|
||||
#include "msm_vidc_platform.h"
|
||||
#include "firmware.h"
|
||||
|
||||
#define MAX_FIRMWARE_NAME_SIZE 128
|
||||
|
||||
struct tzbsp_memprot {
|
||||
u32 cp_start;
|
||||
u32 cp_size;
|
||||
u32 cp_nonpixel_start;
|
||||
u32 cp_nonpixel_size;
|
||||
};
|
||||
|
||||
enum tzbsp_video_state {
|
||||
TZBSP_VIDEO_STATE_SUSPEND = 0,
|
||||
TZBSP_VIDEO_STATE_RESUME = 1,
|
||||
TZBSP_VIDEO_STATE_RESTORE_THRESHOLD = 2,
|
||||
};
|
||||
|
||||
static int protect_cp_mem(struct msm_vidc_core *core)
|
||||
{
|
||||
struct tzbsp_memprot memprot;
|
||||
int rc = 0;
|
||||
struct context_bank_info *cb;
|
||||
|
||||
memprot.cp_start = 0x0;
|
||||
memprot.cp_size = 0x0;
|
||||
memprot.cp_nonpixel_start = 0x0;
|
||||
memprot.cp_nonpixel_size = 0x0;
|
||||
|
||||
venus_hfi_for_each_context_bank(core, cb) {
|
||||
if (cb->region == MSM_VIDC_NON_SECURE) {
|
||||
memprot.cp_size = cb->addr_range.start;
|
||||
|
||||
d_vpr_h("%s: memprot.cp_size: %#x\n",
|
||||
__func__, memprot.cp_size);
|
||||
}
|
||||
|
||||
if (cb->region == MSM_VIDC_SECURE_NONPIXEL) {
|
||||
memprot.cp_nonpixel_start = cb->addr_range.start;
|
||||
memprot.cp_nonpixel_size = cb->addr_range.size;
|
||||
|
||||
d_vpr_h("%s: cp_nonpixel_start: %#x size: %#x\n",
|
||||
__func__, memprot.cp_nonpixel_start,
|
||||
memprot.cp_nonpixel_size);
|
||||
}
|
||||
}
|
||||
|
||||
rc = qcom_scm_mem_protect_video_var(memprot.cp_start, memprot.cp_size,
|
||||
memprot.cp_nonpixel_start, memprot.cp_nonpixel_size);
|
||||
if (rc)
|
||||
d_vpr_e("Failed to protect memory(%d)\n", rc);
|
||||
|
||||
trace_venus_hfi_var_done(memprot.cp_start, memprot.cp_size,
|
||||
memprot.cp_nonpixel_start, memprot.cp_nonpixel_size);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __load_fw_to_memory(struct platform_device *pdev,
|
||||
const char *fw_name)
|
||||
{
|
||||
int rc = 0;
|
||||
const struct firmware *firmware = NULL;
|
||||
struct msm_vidc_core *core;
|
||||
char firmware_name[MAX_FIRMWARE_NAME_SIZE] = { 0 };
|
||||
struct device_node *node = NULL;
|
||||
struct resource res = { 0 };
|
||||
phys_addr_t phys = 0;
|
||||
size_t res_size = 0;
|
||||
ssize_t fw_size = 0;
|
||||
void *virt = NULL;
|
||||
int pas_id = 0;
|
||||
|
||||
if (!fw_name || !(*fw_name) || !pdev) {
|
||||
d_vpr_e("%s: Invalid inputs\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4) {
|
||||
d_vpr_e("%s: Invalid fw name\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
core = dev_get_drvdata(&pdev->dev);
|
||||
if (!core) {
|
||||
d_vpr_e("%s: core not found in device %s",
|
||||
__func__, dev_name(&pdev->dev));
|
||||
return -EINVAL;
|
||||
}
|
||||
scnprintf(firmware_name, ARRAY_SIZE(firmware_name), "%s.mbn", fw_name);
|
||||
|
||||
pas_id = core->platform->data.pas_id;
|
||||
|
||||
node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
|
||||
if (!node) {
|
||||
d_vpr_e("%s: failed to read \"memory-region\"\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = of_address_to_resource(node, 0, &res);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: failed to read \"memory-region\", error %d\n",
|
||||
__func__, rc);
|
||||
goto exit;
|
||||
}
|
||||
phys = res.start;
|
||||
res_size = (size_t)resource_size(&res);
|
||||
|
||||
rc = request_firmware(&firmware, firmware_name, &pdev->dev);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: failed to request fw \"%s\", error %d\n",
|
||||
__func__, firmware_name, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
fw_size = qcom_mdt_get_size(firmware);
|
||||
if (fw_size < 0 || res_size < (size_t)fw_size) {
|
||||
rc = -EINVAL;
|
||||
d_vpr_e("%s: out of bound fw image fw size: %ld, res_size: %lu",
|
||||
__func__, fw_size, res_size);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
virt = memremap(phys, res_size, MEMREMAP_WC);
|
||||
if (!virt) {
|
||||
d_vpr_e("%s: failed to remap fw memory phys %pa[p]\n",
|
||||
__func__, &phys);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* prevent system suspend during fw_load */
|
||||
pm_stay_awake(pdev->dev.parent);
|
||||
rc = qcom_mdt_load(&pdev->dev, firmware, firmware_name,
|
||||
pas_id, virt, phys, res_size, NULL);
|
||||
pm_relax(pdev->dev.parent);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: error %d loading fw \"%s\"\n",
|
||||
__func__, rc, firmware_name);
|
||||
goto exit;
|
||||
}
|
||||
rc = qcom_scm_pas_auth_and_reset(pas_id);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: error %d authenticating fw \"%s\"\n",
|
||||
__func__, rc, firmware_name);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memunmap(virt);
|
||||
release_firmware(firmware);
|
||||
d_vpr_h("%s: firmware \"%s\" loaded successfully\n",
|
||||
__func__, firmware_name);
|
||||
|
||||
return pas_id;
|
||||
|
||||
exit:
|
||||
if (virt)
|
||||
memunmap(virt);
|
||||
if (firmware)
|
||||
release_firmware(firmware);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int fw_load(struct msm_vidc_core *core)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!core->resource->fw_cookie) {
|
||||
core->resource->fw_cookie = __load_fw_to_memory(core->pdev,
|
||||
core->platform->data.fwname);
|
||||
if (core->resource->fw_cookie <= 0) {
|
||||
d_vpr_e("%s: firmware download failed %d\n",
|
||||
__func__, core->resource->fw_cookie);
|
||||
core->resource->fw_cookie = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
rc = protect_cp_mem(core);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: protect memory failed\n", __func__);
|
||||
goto fail_protect_mem;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
fail_protect_mem:
|
||||
if (core->resource->fw_cookie)
|
||||
qcom_scm_pas_shutdown(core->resource->fw_cookie);
|
||||
core->resource->fw_cookie = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int fw_unload(struct msm_vidc_core *core)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!core->resource->fw_cookie)
|
||||
return -EINVAL;
|
||||
|
||||
ret = qcom_scm_pas_shutdown(core->resource->fw_cookie);
|
||||
if (ret)
|
||||
d_vpr_e("Firmware unload failed rc=%d\n", ret);
|
||||
|
||||
core->resource->fw_cookie = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fw_suspend(struct msm_vidc_core *core)
|
||||
{
|
||||
return qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0);
|
||||
}
|
||||
|
||||
int fw_resume(struct msm_vidc_core *core)
|
||||
{
|
||||
return qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_RESUME, 0);
|
||||
}
|
||||
|
||||
void fw_coredump(struct msm_vidc_core *core)
|
||||
{
|
||||
int rc = 0;
|
||||
struct platform_device *pdev;
|
||||
struct device_node *node = NULL;
|
||||
struct resource res = {0};
|
||||
phys_addr_t mem_phys = 0;
|
||||
size_t res_size = 0;
|
||||
void *mem_va = NULL;
|
||||
char *data = NULL, *dump = NULL;
|
||||
u64 total_size;
|
||||
|
||||
pdev = core->pdev;
|
||||
|
||||
node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
|
||||
if (!node) {
|
||||
d_vpr_e("%s: DT error getting \"memory-region\" property\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = of_address_to_resource(node, 0, &res);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: error %d while getting \"memory-region\" resource\n",
|
||||
__func__, rc);
|
||||
return;
|
||||
}
|
||||
|
||||
mem_phys = res.start;
|
||||
res_size = (size_t)resource_size(&res);
|
||||
|
||||
mem_va = memremap(mem_phys, res_size, MEMREMAP_WC);
|
||||
if (!mem_va) {
|
||||
d_vpr_e("%s: unable to remap firmware memory\n", __func__);
|
||||
return;
|
||||
}
|
||||
total_size = res_size + TOTAL_QSIZE + ALIGNED_SFR_SIZE;
|
||||
|
||||
data = vmalloc(total_size);
|
||||
if (!data) {
|
||||
memunmap(mem_va);
|
||||
return;
|
||||
}
|
||||
dump = data;
|
||||
|
||||
/* copy firmware dump */
|
||||
memcpy(data, mem_va, res_size);
|
||||
memunmap(mem_va);
|
||||
|
||||
/* copy queues(cmd, msg, dbg) dump(along with headers) */
|
||||
data += res_size;
|
||||
memcpy(data, (char *)core->iface_q_table.align_virtual_addr, TOTAL_QSIZE);
|
||||
|
||||
/* copy sfr dump */
|
||||
data += TOTAL_QSIZE;
|
||||
memcpy(data, (char *)core->sfr.align_virtual_addr, ALIGNED_SFR_SIZE);
|
||||
|
||||
dev_coredumpv(&pdev->dev, dump, total_size, GFP_KERNEL);
|
||||
}
|
708
qcom/opensource/video-driver/driver/vidc/src/hfi_packet.c
Normal file
708
qcom/opensource/video-driver/driver/vidc/src/hfi_packet.c
Normal file
@ -0,0 +1,708 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "hfi_packet.h"
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vidc_platform.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
|
||||
u32 get_hfi_port(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_port_type port)
|
||||
{
|
||||
u32 hfi_port = HFI_PORT_NONE;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
switch (port) {
|
||||
case INPUT_PORT:
|
||||
case INPUT_META_PORT:
|
||||
hfi_port = HFI_PORT_BITSTREAM;
|
||||
break;
|
||||
case OUTPUT_PORT:
|
||||
case OUTPUT_META_PORT:
|
||||
hfi_port = HFI_PORT_RAW;
|
||||
break;
|
||||
default:
|
||||
i_vpr_e(inst, "%s: invalid port type %d\n",
|
||||
__func__, port);
|
||||
break;
|
||||
}
|
||||
} else if (is_encode_session(inst)) {
|
||||
switch (port) {
|
||||
case INPUT_PORT:
|
||||
case INPUT_META_PORT:
|
||||
hfi_port = HFI_PORT_RAW;
|
||||
break;
|
||||
case OUTPUT_PORT:
|
||||
case OUTPUT_META_PORT:
|
||||
hfi_port = HFI_PORT_BITSTREAM;
|
||||
break;
|
||||
default:
|
||||
i_vpr_e(inst, "%s: invalid port type %d\n",
|
||||
__func__, port);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: invalid domain %#x\n",
|
||||
__func__, inst->domain);
|
||||
}
|
||||
|
||||
return hfi_port;
|
||||
}
|
||||
|
||||
u32 get_hfi_port_from_buffer_type(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
u32 hfi_port = HFI_PORT_NONE;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
switch (buffer_type) {
|
||||
case MSM_VIDC_BUF_INPUT:
|
||||
case MSM_VIDC_BUF_INPUT_META:
|
||||
case MSM_VIDC_BUF_BIN:
|
||||
case MSM_VIDC_BUF_COMV:
|
||||
case MSM_VIDC_BUF_NON_COMV:
|
||||
case MSM_VIDC_BUF_LINE:
|
||||
case MSM_VIDC_BUF_PARTIAL_DATA:
|
||||
hfi_port = HFI_PORT_BITSTREAM;
|
||||
break;
|
||||
case MSM_VIDC_BUF_OUTPUT:
|
||||
case MSM_VIDC_BUF_OUTPUT_META:
|
||||
case MSM_VIDC_BUF_DPB:
|
||||
hfi_port = HFI_PORT_RAW;
|
||||
break;
|
||||
case MSM_VIDC_BUF_PERSIST:
|
||||
hfi_port = HFI_PORT_NONE;
|
||||
break;
|
||||
default:
|
||||
i_vpr_e(inst, "%s: invalid buffer type %d\n",
|
||||
__func__, buffer_type);
|
||||
break;
|
||||
}
|
||||
} else if (is_encode_session(inst)) {
|
||||
switch (buffer_type) {
|
||||
case MSM_VIDC_BUF_INPUT:
|
||||
case MSM_VIDC_BUF_INPUT_META:
|
||||
case MSM_VIDC_BUF_VPSS:
|
||||
hfi_port = HFI_PORT_RAW;
|
||||
break;
|
||||
case MSM_VIDC_BUF_OUTPUT:
|
||||
case MSM_VIDC_BUF_OUTPUT_META:
|
||||
case MSM_VIDC_BUF_BIN:
|
||||
case MSM_VIDC_BUF_COMV:
|
||||
case MSM_VIDC_BUF_NON_COMV:
|
||||
case MSM_VIDC_BUF_LINE:
|
||||
case MSM_VIDC_BUF_DPB:
|
||||
hfi_port = HFI_PORT_BITSTREAM;
|
||||
break;
|
||||
case MSM_VIDC_BUF_ARP:
|
||||
hfi_port = HFI_PORT_NONE;
|
||||
break;
|
||||
default:
|
||||
i_vpr_e(inst, "%s: invalid buffer type %d\n",
|
||||
__func__, buffer_type);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: invalid domain %#x\n",
|
||||
__func__, inst->domain);
|
||||
}
|
||||
|
||||
return hfi_port;
|
||||
}
|
||||
|
||||
u32 hfi_buf_type_from_driver(enum msm_vidc_domain_type domain,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
switch (buffer_type) {
|
||||
case MSM_VIDC_BUF_INPUT:
|
||||
if (domain == MSM_VIDC_DECODER)
|
||||
return HFI_BUFFER_BITSTREAM;
|
||||
else
|
||||
return HFI_BUFFER_RAW;
|
||||
case MSM_VIDC_BUF_OUTPUT:
|
||||
if (domain == MSM_VIDC_DECODER)
|
||||
return HFI_BUFFER_RAW;
|
||||
else
|
||||
return HFI_BUFFER_BITSTREAM;
|
||||
case MSM_VIDC_BUF_INPUT_META:
|
||||
case MSM_VIDC_BUF_OUTPUT_META:
|
||||
return HFI_BUFFER_METADATA;
|
||||
case MSM_VIDC_BUF_BIN:
|
||||
return HFI_BUFFER_BIN;
|
||||
case MSM_VIDC_BUF_ARP:
|
||||
return HFI_BUFFER_ARP;
|
||||
case MSM_VIDC_BUF_COMV:
|
||||
return HFI_BUFFER_COMV;
|
||||
case MSM_VIDC_BUF_NON_COMV:
|
||||
return HFI_BUFFER_NON_COMV;
|
||||
case MSM_VIDC_BUF_LINE:
|
||||
return HFI_BUFFER_LINE;
|
||||
case MSM_VIDC_BUF_DPB:
|
||||
return HFI_BUFFER_DPB;
|
||||
case MSM_VIDC_BUF_PERSIST:
|
||||
return HFI_BUFFER_PERSIST;
|
||||
case MSM_VIDC_BUF_VPSS:
|
||||
return HFI_BUFFER_VPSS;
|
||||
case MSM_VIDC_BUF_PARTIAL_DATA:
|
||||
return HFI_BUFFER_PARTIAL_DATA;
|
||||
default:
|
||||
d_vpr_e("invalid buffer type %d\n",
|
||||
buffer_type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 hfi_buf_type_to_driver(enum msm_vidc_domain_type domain,
|
||||
enum hfi_buffer_type buffer_type, enum hfi_packet_port_type port_type)
|
||||
{
|
||||
switch (buffer_type) {
|
||||
case HFI_BUFFER_BITSTREAM:
|
||||
if (domain == MSM_VIDC_DECODER)
|
||||
return MSM_VIDC_BUF_INPUT;
|
||||
else
|
||||
return MSM_VIDC_BUF_OUTPUT;
|
||||
case HFI_BUFFER_RAW:
|
||||
if (domain == MSM_VIDC_DECODER)
|
||||
return MSM_VIDC_BUF_OUTPUT;
|
||||
else
|
||||
return MSM_VIDC_BUF_INPUT;
|
||||
case HFI_BUFFER_METADATA:
|
||||
if (domain == MSM_VIDC_DECODER)
|
||||
if (port_type == HFI_PORT_BITSTREAM)
|
||||
return MSM_VIDC_BUF_INPUT_META;
|
||||
else
|
||||
return MSM_VIDC_BUF_OUTPUT_META;
|
||||
else
|
||||
if (port_type == HFI_PORT_BITSTREAM)
|
||||
return MSM_VIDC_BUF_OUTPUT_META;
|
||||
else
|
||||
return MSM_VIDC_BUF_INPUT_META;
|
||||
case HFI_BUFFER_BIN:
|
||||
return MSM_VIDC_BUF_BIN;
|
||||
case HFI_BUFFER_ARP:
|
||||
return MSM_VIDC_BUF_ARP;
|
||||
case HFI_BUFFER_COMV:
|
||||
return MSM_VIDC_BUF_COMV;
|
||||
case HFI_BUFFER_NON_COMV:
|
||||
return MSM_VIDC_BUF_NON_COMV;
|
||||
case HFI_BUFFER_LINE:
|
||||
return MSM_VIDC_BUF_LINE;
|
||||
case HFI_BUFFER_DPB:
|
||||
return MSM_VIDC_BUF_DPB;
|
||||
case HFI_BUFFER_PERSIST:
|
||||
return MSM_VIDC_BUF_PERSIST;
|
||||
case HFI_BUFFER_VPSS:
|
||||
return MSM_VIDC_BUF_VPSS;
|
||||
case HFI_BUFFER_PARTIAL_DATA:
|
||||
return MSM_VIDC_BUF_PARTIAL_DATA;
|
||||
default:
|
||||
d_vpr_e("invalid buffer type %d\n",
|
||||
buffer_type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 get_hfi_codec(struct msm_vidc_inst *inst)
|
||||
{
|
||||
switch (inst->codec) {
|
||||
case MSM_VIDC_H264:
|
||||
if (is_encode_session(inst))
|
||||
return HFI_CODEC_ENCODE_AVC;
|
||||
else
|
||||
return HFI_CODEC_DECODE_AVC;
|
||||
case MSM_VIDC_HEVC:
|
||||
case MSM_VIDC_HEIC:
|
||||
if (is_encode_session(inst))
|
||||
return HFI_CODEC_ENCODE_HEVC;
|
||||
else
|
||||
return HFI_CODEC_DECODE_HEVC;
|
||||
case MSM_VIDC_VP9:
|
||||
return HFI_CODEC_DECODE_VP9;
|
||||
case MSM_VIDC_AV1:
|
||||
return HFI_CODEC_DECODE_AV1;
|
||||
default:
|
||||
i_vpr_e(inst, "invalid codec %d, domain %d\n",
|
||||
inst->codec, inst->domain);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 get_hfi_colorformat(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_colorformat_type colorformat)
|
||||
{
|
||||
u32 hfi_colorformat = HFI_COLOR_FMT_NV12_UBWC;
|
||||
|
||||
switch (colorformat) {
|
||||
case MSM_VIDC_FMT_NV12:
|
||||
hfi_colorformat = HFI_COLOR_FMT_NV12;
|
||||
break;
|
||||
case MSM_VIDC_FMT_NV12C:
|
||||
hfi_colorformat = HFI_COLOR_FMT_NV12_UBWC;
|
||||
break;
|
||||
case MSM_VIDC_FMT_P010:
|
||||
hfi_colorformat = HFI_COLOR_FMT_P010;
|
||||
break;
|
||||
case MSM_VIDC_FMT_TP10C:
|
||||
hfi_colorformat = HFI_COLOR_FMT_TP10_UBWC;
|
||||
break;
|
||||
case MSM_VIDC_FMT_RGBA8888:
|
||||
hfi_colorformat = HFI_COLOR_FMT_RGBA8888;
|
||||
break;
|
||||
case MSM_VIDC_FMT_RGBA8888C:
|
||||
hfi_colorformat = HFI_COLOR_FMT_RGBA8888_UBWC;
|
||||
break;
|
||||
case MSM_VIDC_FMT_NV21:
|
||||
hfi_colorformat = HFI_COLOR_FMT_NV21;
|
||||
break;
|
||||
default:
|
||||
i_vpr_e(inst, "%s: invalid colorformat %d\n",
|
||||
__func__, colorformat);
|
||||
break;
|
||||
}
|
||||
|
||||
return hfi_colorformat;
|
||||
}
|
||||
|
||||
static u32 get_hfi_region_flag(enum msm_vidc_buffer_region region)
|
||||
{
|
||||
switch (region) {
|
||||
case MSM_VIDC_NON_SECURE:
|
||||
return HFI_BUF_HOST_FLAGS_CB_NON_SECURE;
|
||||
case MSM_VIDC_NON_SECURE_PIXEL:
|
||||
return HFI_BUF_HOST_FLAGS_CB_NON_SECURE_PIXEL;
|
||||
case MSM_VIDC_SECURE_PIXEL:
|
||||
return HFI_BUF_HOST_FLAGS_CB_SECURE_PIXEL;
|
||||
case MSM_VIDC_SECURE_NONPIXEL:
|
||||
return HFI_BUF_HOST_FLAGS_CB_SECURE_NON_PIXEL;
|
||||
case MSM_VIDC_SECURE_BITSTREAM:
|
||||
return HFI_BUF_HOST_FLAGS_CB_SECURE_BITSTREAM;
|
||||
case MSM_VIDC_REGION_MAX:
|
||||
case MSM_VIDC_REGION_NONE:
|
||||
default:
|
||||
return HFI_BUF_HOST_FLAG_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
int get_hfi_buffer(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_buffer *buffer, struct hfi_buffer *buf)
|
||||
{
|
||||
memset(buf, 0, sizeof(struct hfi_buffer));
|
||||
buf->type = hfi_buf_type_from_driver(inst->domain, buffer->type);
|
||||
buf->index = buffer->index;
|
||||
buf->base_address = buffer->device_addr;
|
||||
buf->addr_offset = 0;
|
||||
buf->buffer_size = buffer->buffer_size;
|
||||
/*
|
||||
* for decoder input buffers, firmware (BSE HW) needs 256 aligned
|
||||
* buffer size otherwise it will truncate or ignore the data after 256
|
||||
* aligned size which may lead to error concealment
|
||||
*/
|
||||
if (is_decode_session(inst) && is_input_buffer(buffer->type))
|
||||
buf->buffer_size = ALIGN(buffer->buffer_size, 256);
|
||||
buf->data_offset = buffer->data_offset;
|
||||
buf->data_size = buffer->data_size;
|
||||
if (buffer->attr & MSM_VIDC_ATTR_READ_ONLY)
|
||||
buf->flags |= HFI_BUF_HOST_FLAG_READONLY;
|
||||
if (buffer->attr & MSM_VIDC_ATTR_PENDING_RELEASE)
|
||||
buf->flags |= HFI_BUF_HOST_FLAG_RELEASE;
|
||||
if (buffer->flags & MSM_VIDC_BUF_FLAG_CODECCONFIG)
|
||||
buf->flags |= HFI_BUF_HOST_FLAG_CODEC_CONFIG;
|
||||
buf->flags |= get_hfi_region_flag(buffer->region);
|
||||
buf->timestamp = buffer->timestamp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hfi_create_header(u8 *packet, u32 packet_size, u32 session_id,
|
||||
u32 header_id)
|
||||
{
|
||||
struct hfi_header *hdr = (struct hfi_header *)packet;
|
||||
|
||||
if (!packet || packet_size < sizeof(struct hfi_header)) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(hdr, 0, sizeof(struct hfi_header));
|
||||
|
||||
hdr->size = sizeof(struct hfi_header);
|
||||
hdr->session_id = session_id;
|
||||
hdr->header_id = header_id;
|
||||
hdr->num_packets = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hfi_create_packet(u8 *packet, u32 packet_size,
|
||||
u32 pkt_type, u32 pkt_flags, u32 payload_type, u32 port,
|
||||
u32 packet_id, void *payload, u32 payload_size)
|
||||
{
|
||||
struct hfi_header *hdr;
|
||||
struct hfi_packet *pkt;
|
||||
u32 pkt_size;
|
||||
|
||||
if (!packet) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
hdr = (struct hfi_header *)packet;
|
||||
if (hdr->size < sizeof(struct hfi_header)) {
|
||||
d_vpr_e("%s: invalid hdr size %d\n", __func__, hdr->size);
|
||||
return -EINVAL;
|
||||
}
|
||||
pkt = (struct hfi_packet *)(packet + hdr->size);
|
||||
pkt_size = sizeof(struct hfi_packet) + payload_size;
|
||||
if (packet_size < hdr->size + pkt_size) {
|
||||
d_vpr_e("%s: invalid packet_size %d, %d %d\n",
|
||||
__func__, packet_size, hdr->size, pkt_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
memset(pkt, 0, pkt_size);
|
||||
pkt->size = pkt_size;
|
||||
pkt->type = pkt_type;
|
||||
pkt->flags = pkt_flags;
|
||||
pkt->payload_info = payload_type;
|
||||
pkt->port = port;
|
||||
pkt->packet_id = packet_id;
|
||||
if (payload_size)
|
||||
memcpy((u8 *)pkt + sizeof(struct hfi_packet),
|
||||
payload, payload_size);
|
||||
|
||||
hdr->num_packets++;
|
||||
hdr->size += pkt->size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hfi_packet_sys_init(struct msm_vidc_core *core,
|
||||
u8 *pkt, u32 pkt_size)
|
||||
{
|
||||
int rc = 0;
|
||||
u32 payload = 0;
|
||||
u32 synx_client_data[2];
|
||||
|
||||
rc = hfi_create_header(pkt, pkt_size,
|
||||
0 /*session_id*/,
|
||||
core->header_id++);
|
||||
if (rc)
|
||||
goto err_sys_init;
|
||||
|
||||
/* HFI_CMD_SYSTEM_INIT */
|
||||
payload = HFI_VIDEO_ARCH_LX;
|
||||
d_vpr_h("%s: arch %d\n", __func__, payload);
|
||||
core->sys_init_id = core->packet_id++;
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_CMD_INIT,
|
||||
(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
|
||||
HFI_HOST_FLAGS_INTR_REQUIRED |
|
||||
HFI_HOST_FLAGS_NON_DISCARDABLE),
|
||||
HFI_PAYLOAD_U32,
|
||||
HFI_PORT_NONE,
|
||||
core->sys_init_id,
|
||||
&payload,
|
||||
sizeof(u32));
|
||||
if (rc)
|
||||
goto err_sys_init;
|
||||
|
||||
/* HFI_PROP_UBWC_MAX_CHANNELS */
|
||||
payload = core->platform->data.ubwc_config->max_channels;
|
||||
d_vpr_h("%s: ubwc max channels %d\n", __func__, payload);
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_PROP_UBWC_MAX_CHANNELS,
|
||||
HFI_HOST_FLAGS_NONE,
|
||||
HFI_PAYLOAD_U32,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
&payload,
|
||||
sizeof(u32));
|
||||
if (rc)
|
||||
goto err_sys_init;
|
||||
|
||||
/* HFI_PROP_UBWC_MAL_LENGTH */
|
||||
payload = core->platform->data.ubwc_config->mal_length;
|
||||
d_vpr_h("%s: ubwc mal length %d\n", __func__, payload);
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_PROP_UBWC_MAL_LENGTH,
|
||||
HFI_HOST_FLAGS_NONE,
|
||||
HFI_PAYLOAD_U32,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
&payload,
|
||||
sizeof(u32));
|
||||
if (rc)
|
||||
goto err_sys_init;
|
||||
|
||||
/* HFI_PROP_UBWC_HBB */
|
||||
payload = core->platform->data.ubwc_config->highest_bank_bit;
|
||||
d_vpr_h("%s: ubwc hbb %d\n", __func__, payload);
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_PROP_UBWC_HBB,
|
||||
HFI_HOST_FLAGS_NONE,
|
||||
HFI_PAYLOAD_U32,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
&payload,
|
||||
sizeof(u32));
|
||||
if (rc)
|
||||
goto err_sys_init;
|
||||
|
||||
/* HFI_PROP_UBWC_BANK_SWZL_LEVEL1 */
|
||||
payload = core->platform->data.ubwc_config->bank_swzl_level;
|
||||
d_vpr_h("%s: ubwc swzl1 %d\n", __func__, payload);
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_PROP_UBWC_BANK_SWZL_LEVEL1,
|
||||
HFI_HOST_FLAGS_NONE,
|
||||
HFI_PAYLOAD_U32,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
&payload,
|
||||
sizeof(u32));
|
||||
if (rc)
|
||||
goto err_sys_init;
|
||||
|
||||
/* HFI_PROP_UBWC_BANK_SWZL_LEVEL2 */
|
||||
payload = core->platform->data.ubwc_config->bank_swz2_level;
|
||||
d_vpr_h("%s: ubwc swzl2 %d\n", __func__, payload);
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_PROP_UBWC_BANK_SWZL_LEVEL2,
|
||||
HFI_HOST_FLAGS_NONE,
|
||||
HFI_PAYLOAD_U32,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
&payload,
|
||||
sizeof(u32));
|
||||
if (rc)
|
||||
goto err_sys_init;
|
||||
|
||||
/* HFI_PROP_UBWC_BANK_SWZL_LEVEL3 */
|
||||
payload = core->platform->data.ubwc_config->bank_swz3_level;
|
||||
d_vpr_h("%s: ubwc swzl3 %d\n", __func__, payload);
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_PROP_UBWC_BANK_SWZL_LEVEL3,
|
||||
HFI_HOST_FLAGS_NONE,
|
||||
HFI_PAYLOAD_U32,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
&payload,
|
||||
sizeof(u32));
|
||||
if (rc)
|
||||
goto err_sys_init;
|
||||
|
||||
/* HFI_PROP_UBWC_BANK_SPREADING */
|
||||
payload = core->platform->data.ubwc_config->bank_spreading;
|
||||
d_vpr_h("%s: ubwc bank spreading %d\n", __func__, payload);
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_PROP_UBWC_BANK_SPREADING,
|
||||
HFI_HOST_FLAGS_NONE,
|
||||
HFI_PAYLOAD_U32,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
&payload,
|
||||
sizeof(u32));
|
||||
if (rc)
|
||||
goto err_sys_init;
|
||||
|
||||
/* HFI_PROP_FENCE_CLIENT_DATA */
|
||||
if (core->capabilities[SUPPORTS_SYNX_FENCE].value) {
|
||||
synx_client_data[0] = core->synx_fence_data.client_id;
|
||||
synx_client_data[1] = core->synx_fence_data.client_flags;
|
||||
d_vpr_h("%s: synx fence client id: %u client flags: %u\n",
|
||||
__func__, synx_client_data[0], synx_client_data[1]);
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_PROP_FENCE_CLIENT_DATA,
|
||||
HFI_HOST_FLAGS_NONE,
|
||||
HFI_PAYLOAD_U32_ARRAY,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
synx_client_data,
|
||||
sizeof(u32) * 2);
|
||||
if (rc)
|
||||
goto err_sys_init;
|
||||
}
|
||||
|
||||
d_vpr_h("System init packet created\n");
|
||||
return rc;
|
||||
|
||||
err_sys_init:
|
||||
d_vpr_e("%s: create packet failed\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int hfi_packet_image_version(struct msm_vidc_core *core,
|
||||
u8 *pkt, u32 pkt_size)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = hfi_create_header(pkt, pkt_size,
|
||||
0 /*session_id*/,
|
||||
core->header_id++);
|
||||
if (rc)
|
||||
goto err_img_version;
|
||||
|
||||
/* HFI_PROP_IMAGE_VERSION */
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_PROP_IMAGE_VERSION,
|
||||
(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
|
||||
HFI_HOST_FLAGS_INTR_REQUIRED |
|
||||
HFI_HOST_FLAGS_GET_PROPERTY),
|
||||
HFI_PAYLOAD_NONE,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
NULL, 0);
|
||||
if (rc)
|
||||
goto err_img_version;
|
||||
|
||||
d_vpr_h("Image version packet created\n");
|
||||
return rc;
|
||||
|
||||
err_img_version:
|
||||
d_vpr_e("%s: create packet failed\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int hfi_packet_sys_pc_prep(struct msm_vidc_core *core,
|
||||
u8 *pkt, u32 pkt_size)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = hfi_create_header(pkt, pkt_size,
|
||||
0 /*session_id*/,
|
||||
core->header_id++);
|
||||
if (rc)
|
||||
goto err_sys_pc;
|
||||
|
||||
/* HFI_CMD_POWER_COLLAPSE */
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_CMD_POWER_COLLAPSE,
|
||||
HFI_HOST_FLAGS_NONE,
|
||||
HFI_PAYLOAD_NONE,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
NULL, 0);
|
||||
if (rc)
|
||||
goto err_sys_pc;
|
||||
|
||||
d_vpr_h("Power collapse packet created\n");
|
||||
return rc;
|
||||
|
||||
err_sys_pc:
|
||||
d_vpr_e("%s: create packet failed\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int hfi_packet_sys_debug_config(struct msm_vidc_core *core,
|
||||
u8 *pkt, u32 pkt_size, u32 debug_config)
|
||||
{
|
||||
int rc = 0;
|
||||
u32 payload = 0;
|
||||
|
||||
rc = hfi_create_header(pkt, pkt_size,
|
||||
0 /*session_id*/,
|
||||
core->header_id++);
|
||||
if (rc)
|
||||
goto err_debug;
|
||||
|
||||
/* HFI_PROP_DEBUG_CONFIG */
|
||||
payload = 0; /*TODO:Change later*/
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_PROP_DEBUG_CONFIG,
|
||||
HFI_HOST_FLAGS_NONE,
|
||||
HFI_PAYLOAD_U32_ENUM,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
&payload,
|
||||
sizeof(u32));
|
||||
if (rc)
|
||||
goto err_debug;
|
||||
|
||||
/* HFI_PROP_DEBUG_LOG_LEVEL */
|
||||
payload = debug_config; /*TODO:Change later*/
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_PROP_DEBUG_LOG_LEVEL,
|
||||
HFI_HOST_FLAGS_NONE,
|
||||
HFI_PAYLOAD_U32_ENUM,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
&payload,
|
||||
sizeof(u32));
|
||||
if (rc)
|
||||
goto err_debug;
|
||||
|
||||
err_debug:
|
||||
if (rc)
|
||||
d_vpr_e("%s: create packet failed\n", __func__);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int hfi_packet_session_command(struct msm_vidc_inst *inst,
|
||||
u32 pkt_type, u32 flags, u32 port, u32 session_id,
|
||||
u32 payload_type, void *payload, u32 payload_size)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_vidc_core *core;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
rc = hfi_create_header(inst->packet, inst->packet_size,
|
||||
session_id,
|
||||
core->header_id++);
|
||||
if (rc)
|
||||
goto err_cmd;
|
||||
|
||||
rc = hfi_create_packet(inst->packet,
|
||||
inst->packet_size,
|
||||
pkt_type,
|
||||
flags,
|
||||
payload_type,
|
||||
port,
|
||||
core->packet_id++,
|
||||
payload,
|
||||
payload_size);
|
||||
if (rc)
|
||||
goto err_cmd;
|
||||
|
||||
i_vpr_h(inst, "Command packet 0x%x created\n", pkt_type);
|
||||
return rc;
|
||||
|
||||
err_cmd:
|
||||
i_vpr_e(inst, "%s: create packet failed\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int hfi_packet_sys_intraframe_powercollapse(struct msm_vidc_core *core,
|
||||
u8 *pkt, u32 pkt_size, u32 enable)
|
||||
{
|
||||
int rc = 0;
|
||||
u32 payload = 0;
|
||||
|
||||
rc = hfi_create_header(pkt, pkt_size,
|
||||
0 /*session_id*/,
|
||||
core->header_id++);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
/* HFI_PROP_INTRA_FRAME_POWER_COLLAPSE */
|
||||
payload = enable;
|
||||
d_vpr_h("%s: intra frame power collapse %d\n", __func__, payload);
|
||||
rc = hfi_create_packet(pkt, pkt_size,
|
||||
HFI_PROP_INTRA_FRAME_POWER_COLLAPSE,
|
||||
HFI_HOST_FLAGS_NONE,
|
||||
HFI_PAYLOAD_U32,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
&payload,
|
||||
sizeof(u32));
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
d_vpr_h("IFPC packet created\n");
|
||||
return rc;
|
||||
|
||||
err:
|
||||
d_vpr_e("%s: create packet failed\n", __func__);
|
||||
return rc;
|
||||
}
|
2704
qcom/opensource/video-driver/driver/vidc/src/msm_vdec.c
Normal file
2704
qcom/opensource/video-driver/driver/vidc/src/msm_vdec.c
Normal file
File diff suppressed because it is too large
Load Diff
1874
qcom/opensource/video-driver/driver/vidc/src/msm_venc.c
Normal file
1874
qcom/opensource/video-driver/driver/vidc/src/msm_venc.c
Normal file
File diff suppressed because it is too large
Load Diff
890
qcom/opensource/video-driver/driver/vidc/src/msm_vidc.c
Normal file
890
qcom/opensource/video-driver/driver/vidc/src/msm_vidc.c
Normal file
@ -0,0 +1,890 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/hash.h>
|
||||
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vdec.h"
|
||||
#include "msm_venc.h"
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vidc_vb2.h"
|
||||
#include "msm_vidc_v4l2.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
#include "msm_vidc_control.h"
|
||||
#include "msm_vidc_power.h"
|
||||
#include "msm_vidc_fence.h"
|
||||
#include "msm_vidc_memory.h"
|
||||
#include "venus_hfi_response.h"
|
||||
#include "msm_vidc.h"
|
||||
|
||||
extern const char video_banner[];
|
||||
|
||||
#define MSM_VIDC_DRV_NAME "msm_vidc_driver"
|
||||
#define MSM_VIDC_BUS_NAME "platform:msm_vidc_bus"
|
||||
|
||||
/* kernel/msm-4.19 */
|
||||
#define MSM_VIDC_VERSION ((5 << 16) + (10 << 8) + 0)
|
||||
|
||||
static inline bool valid_v4l2_buffer(struct v4l2_buffer *b,
|
||||
struct msm_vidc_inst *inst)
|
||||
{
|
||||
if (b->type == INPUT_MPLANE || b->type == OUTPUT_MPLANE)
|
||||
return b->length > 0;
|
||||
else if (b->type == INPUT_META_PLANE || b->type == OUTPUT_META_PLANE)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int get_poll_flags(struct msm_vidc_inst *inst, u32 port)
|
||||
{
|
||||
int poll = 0;
|
||||
struct vb2_queue *q = NULL;
|
||||
struct vb2_buffer *vb = NULL;
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (port >= MAX_PORT) {
|
||||
d_vpr_e("%s: invalid params, inst %pK, port %d\n",
|
||||
__func__, inst, port);
|
||||
return poll;
|
||||
}
|
||||
q = inst->bufq[port].vb2q;
|
||||
|
||||
spin_lock_irqsave(&q->done_lock, flags);
|
||||
if (!list_empty(&q->done_list))
|
||||
vb = list_first_entry(&q->done_list, struct vb2_buffer,
|
||||
done_entry);
|
||||
if (vb && (vb->state == VB2_BUF_STATE_DONE ||
|
||||
vb->state == VB2_BUF_STATE_ERROR)) {
|
||||
if (port == OUTPUT_PORT || port == OUTPUT_META_PORT)
|
||||
poll |= POLLIN | POLLRDNORM;
|
||||
else if (port == INPUT_PORT || port == INPUT_META_PORT)
|
||||
poll |= POLLOUT | POLLWRNORM;
|
||||
}
|
||||
spin_unlock_irqrestore(&q->done_lock, flags);
|
||||
|
||||
return poll;
|
||||
}
|
||||
|
||||
int msm_vidc_poll(struct msm_vidc_inst *inst, struct file *filp,
|
||||
struct poll_table_struct *wait)
|
||||
{
|
||||
int poll = 0;
|
||||
|
||||
poll_wait(filp, &inst->fh.wait, wait);
|
||||
poll_wait(filp, &inst->bufq[INPUT_META_PORT].vb2q->done_wq, wait);
|
||||
poll_wait(filp, &inst->bufq[OUTPUT_META_PORT].vb2q->done_wq, wait);
|
||||
poll_wait(filp, &inst->bufq[INPUT_PORT].vb2q->done_wq, wait);
|
||||
poll_wait(filp, &inst->bufq[OUTPUT_PORT].vb2q->done_wq, wait);
|
||||
|
||||
if (v4l2_event_pending(&inst->fh))
|
||||
poll |= POLLPRI;
|
||||
|
||||
poll |= get_poll_flags(inst, INPUT_META_PORT);
|
||||
poll |= get_poll_flags(inst, OUTPUT_META_PORT);
|
||||
poll |= get_poll_flags(inst, INPUT_PORT);
|
||||
poll |= get_poll_flags(inst, OUTPUT_PORT);
|
||||
|
||||
return poll;
|
||||
}
|
||||
|
||||
int msm_vidc_querycap(struct msm_vidc_inst *inst, struct v4l2_capability *cap)
|
||||
{
|
||||
strlcpy(cap->driver, MSM_VIDC_DRV_NAME, sizeof(cap->driver));
|
||||
strlcpy(cap->bus_info, MSM_VIDC_BUS_NAME, sizeof(cap->bus_info));
|
||||
cap->version = MSM_VIDC_VERSION;
|
||||
|
||||
memset(cap->reserved, 0, sizeof(cap->reserved));
|
||||
|
||||
if (is_decode_session(inst))
|
||||
strlcpy(cap->card, "msm_vidc_decoder", sizeof(cap->card));
|
||||
else if (is_encode_session(inst))
|
||||
strlcpy(cap->card, "msm_vidc_encoder", sizeof(cap->card));
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f)
|
||||
{
|
||||
if (is_decode_session(inst))
|
||||
return msm_vdec_enum_fmt(inst, f);
|
||||
if (is_encode_session(inst))
|
||||
return msm_venc_enum_fmt(inst, f);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int msm_vidc_query_ctrl(struct msm_vidc_inst *inst, struct v4l2_queryctrl *q_ctrl)
|
||||
{
|
||||
int rc = 0;
|
||||
struct v4l2_ctrl *ctrl;
|
||||
|
||||
ctrl = v4l2_ctrl_find(&inst->ctrl_handler, q_ctrl->id);
|
||||
if (!ctrl) {
|
||||
i_vpr_e(inst, "%s: get_ctrl failed for id %d\n",
|
||||
__func__, q_ctrl->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
q_ctrl->minimum = ctrl->minimum;
|
||||
q_ctrl->maximum = ctrl->maximum;
|
||||
q_ctrl->default_value = ctrl->default_value;
|
||||
q_ctrl->flags = 0;
|
||||
q_ctrl->step = ctrl->step;
|
||||
i_vpr_h(inst,
|
||||
"query ctrl: %s: min %d, max %d, default %d step %d flags %#x\n",
|
||||
ctrl->name, q_ctrl->minimum, q_ctrl->maximum,
|
||||
q_ctrl->default_value, q_ctrl->step, q_ctrl->flags);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_query_menu(struct msm_vidc_inst *inst, struct v4l2_querymenu *qmenu)
|
||||
{
|
||||
int rc = 0;
|
||||
struct v4l2_ctrl *ctrl;
|
||||
|
||||
ctrl = v4l2_ctrl_find(&inst->ctrl_handler, qmenu->id);
|
||||
if (!ctrl) {
|
||||
i_vpr_e(inst, "%s: get_ctrl failed for id %d\n",
|
||||
__func__, qmenu->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ctrl->type != V4L2_CTRL_TYPE_MENU) {
|
||||
i_vpr_e(inst, "%s: ctrl: %s: type (%d) is not MENU type\n",
|
||||
__func__, ctrl->name, ctrl->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (qmenu->index < ctrl->minimum || qmenu->index > ctrl->maximum)
|
||||
return -EINVAL;
|
||||
|
||||
if (ctrl->menu_skip_mask & (1 << qmenu->index))
|
||||
rc = -EINVAL;
|
||||
|
||||
i_vpr_h(inst,
|
||||
"%s: ctrl: %s: min %lld, max %lld, menu_skip_mask %lld, qmenu: id %u, index %d, %s\n",
|
||||
__func__, ctrl->name, ctrl->minimum, ctrl->maximum,
|
||||
ctrl->menu_skip_mask, qmenu->id, qmenu->index,
|
||||
rc ? "not supported" : "supported");
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_try_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (is_decode_session(inst))
|
||||
rc = msm_vdec_try_fmt(inst, f);
|
||||
if (is_encode_session(inst))
|
||||
rc = msm_venc_try_fmt(inst, f);
|
||||
|
||||
if (rc)
|
||||
i_vpr_e(inst, "%s: try_fmt(%d) failed %d\n",
|
||||
__func__, f->type, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (is_decode_session(inst))
|
||||
rc = msm_vdec_s_fmt(inst, f);
|
||||
if (is_encode_session(inst))
|
||||
rc = msm_venc_s_fmt(inst, f);
|
||||
|
||||
if (rc)
|
||||
i_vpr_e(inst, "%s: s_fmt(%d) failed %d\n",
|
||||
__func__, f->type, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (is_decode_session(inst))
|
||||
rc = msm_vdec_g_fmt(inst, f);
|
||||
if (is_encode_session(inst))
|
||||
rc = msm_venc_g_fmt(inst, f);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (f->type == INPUT_MPLANE || f->type == OUTPUT_MPLANE)
|
||||
i_vpr_h(inst, "%s: type %s format %s width %d height %d size %d\n",
|
||||
__func__, v4l2_type_name(f->type),
|
||||
v4l2_pixelfmt_name(inst, f->fmt.pix_mp.pixelformat),
|
||||
f->fmt.pix_mp.width, f->fmt.pix_mp.height,
|
||||
f->fmt.pix_mp.plane_fmt[0].sizeimage);
|
||||
else if (f->type == INPUT_META_PLANE || f->type == OUTPUT_META_PLANE)
|
||||
i_vpr_h(inst, "%s: type %s size %d\n",
|
||||
__func__, v4l2_type_name(f->type), f->fmt.meta.buffersize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_s_selection(struct msm_vidc_inst *inst, struct v4l2_selection *s)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (is_decode_session(inst))
|
||||
rc = msm_vdec_s_selection(inst, s);
|
||||
if (is_encode_session(inst))
|
||||
rc = msm_venc_s_selection(inst, s);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_g_selection(struct msm_vidc_inst *inst, struct v4l2_selection *s)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (is_decode_session(inst))
|
||||
rc = msm_vdec_g_selection(inst, s);
|
||||
if (is_encode_session(inst))
|
||||
rc = msm_venc_g_selection(inst, s);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_s_param(struct msm_vidc_inst *inst, struct v4l2_streamparm *param)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
|
||||
param->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
|
||||
return -EINVAL;
|
||||
|
||||
if (is_encode_session(inst)) {
|
||||
rc = msm_venc_s_param(inst, param);
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: invalid domain %#x\n",
|
||||
__func__, inst->domain);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_g_param(struct msm_vidc_inst *inst, struct v4l2_streamparm *param)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
|
||||
param->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
|
||||
return -EINVAL;
|
||||
|
||||
if (is_encode_session(inst)) {
|
||||
rc = msm_venc_g_param(inst, param);
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: invalid domain %#x\n",
|
||||
__func__, inst->domain);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_reqbufs(struct msm_vidc_inst *inst, struct v4l2_requestbuffers *b)
|
||||
{
|
||||
int rc = 0;
|
||||
int port;
|
||||
|
||||
port = v4l2_type_to_driver_port(inst, b->type, __func__);
|
||||
if (port < 0) {
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = vb2_reqbufs(inst->bufq[port].vb2q, b);
|
||||
if (rc) {
|
||||
i_vpr_e(inst, "%s: vb2_reqbufs(%d) failed, %d\n",
|
||||
__func__, b->type, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_querybuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
|
||||
{
|
||||
int rc = 0;
|
||||
int port;
|
||||
|
||||
port = v4l2_type_to_driver_port(inst, b->type, __func__);
|
||||
if (port < 0) {
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = vb2_querybuf(inst->bufq[port].vb2q, b);
|
||||
if (rc) {
|
||||
i_vpr_e(inst, "%s: vb2_querybuf(%d) failed, %d\n",
|
||||
__func__, b->type, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_create_bufs(struct msm_vidc_inst *inst, struct v4l2_create_buffers *b)
|
||||
{
|
||||
int rc = 0;
|
||||
int port;
|
||||
struct v4l2_format *f;
|
||||
|
||||
f = &b->format;
|
||||
port = v4l2_type_to_driver_port(inst, f->type, __func__);
|
||||
if (port < 0) {
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = vb2_create_bufs(inst->bufq[port].vb2q, b);
|
||||
if (rc) {
|
||||
i_vpr_e(inst, "%s: vb2_create_bufs(%d) failed, %d\n",
|
||||
__func__, f->type, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_prepare_buf(struct msm_vidc_inst *inst, struct media_device *mdev,
|
||||
struct v4l2_buffer *b)
|
||||
{
|
||||
int rc = 0;
|
||||
struct vb2_queue *q;
|
||||
|
||||
if (!valid_v4l2_buffer(b, inst)) {
|
||||
d_vpr_e("%s: invalid params %pK %pK\n", __func__, inst, b);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
q = msm_vidc_get_vb2q(inst, b->type, __func__);
|
||||
if (!q) {
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = vb2_prepare_buf(q, mdev, b);
|
||||
if (rc) {
|
||||
i_vpr_e(inst, "%s: failed with %d\n", __func__, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_qbuf(struct msm_vidc_inst *inst, struct media_device *mdev,
|
||||
struct v4l2_buffer *b)
|
||||
{
|
||||
int rc = 0;
|
||||
struct vb2_queue *q;
|
||||
|
||||
if (!valid_v4l2_buffer(b, inst)) {
|
||||
d_vpr_e("%s: invalid params %pK %pK\n", __func__, inst, b);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
q = msm_vidc_get_vb2q(inst, b->type, __func__);
|
||||
if (!q) {
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = vb2_qbuf(q, mdev, b);
|
||||
if (rc)
|
||||
i_vpr_e(inst, "%s: failed with %d\n", __func__, rc);
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_dqbuf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
|
||||
{
|
||||
int rc = 0;
|
||||
struct vb2_queue *q;
|
||||
|
||||
if (!valid_v4l2_buffer(b, inst)) {
|
||||
d_vpr_e("%s: invalid params %pK %pK\n", __func__, inst, b);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
q = msm_vidc_get_vb2q(inst, b->type, __func__);
|
||||
if (!q) {
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = vb2_dqbuf(q, b, true);
|
||||
if (rc == -EAGAIN) {
|
||||
goto exit;
|
||||
} else if (rc) {
|
||||
i_vpr_l(inst, "%s: failed with %d\n", __func__, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_streamon(struct msm_vidc_inst *inst, enum v4l2_buf_type type)
|
||||
{
|
||||
int rc = 0;
|
||||
int port;
|
||||
|
||||
port = v4l2_type_to_driver_port(inst, type, __func__);
|
||||
if (port < 0) {
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = vb2_streamon(inst->bufq[port].vb2q, type);
|
||||
if (rc) {
|
||||
i_vpr_e(inst, "%s: vb2_streamon(%d) failed, %d\n",
|
||||
__func__, type, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_streamoff(struct msm_vidc_inst *inst, enum v4l2_buf_type type)
|
||||
{
|
||||
int rc = 0;
|
||||
int port;
|
||||
|
||||
port = v4l2_type_to_driver_port(inst, type, __func__);
|
||||
if (port < 0) {
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = vb2_streamoff(inst->bufq[port].vb2q, type);
|
||||
if (rc) {
|
||||
i_vpr_e(inst, "%s: vb2_streamoff(%d) failed, %d\n",
|
||||
__func__, type, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_try_cmd(struct msm_vidc_inst *inst, union msm_v4l2_cmd *cmd)
|
||||
{
|
||||
int rc = 0;
|
||||
struct v4l2_decoder_cmd *dec = NULL;
|
||||
struct v4l2_encoder_cmd *enc = NULL;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
dec = (struct v4l2_decoder_cmd *)cmd;
|
||||
i_vpr_h(inst, "%s: cmd %d\n", __func__, dec->cmd);
|
||||
if (dec->cmd != V4L2_DEC_CMD_STOP && dec->cmd != V4L2_DEC_CMD_START)
|
||||
return -EINVAL;
|
||||
dec->flags = 0;
|
||||
if (dec->cmd == V4L2_DEC_CMD_STOP) {
|
||||
dec->stop.pts = 0;
|
||||
} else if (dec->cmd == V4L2_DEC_CMD_START) {
|
||||
dec->start.speed = 0;
|
||||
dec->start.format = V4L2_DEC_START_FMT_NONE;
|
||||
}
|
||||
} else if (is_encode_session(inst)) {
|
||||
enc = (struct v4l2_encoder_cmd *)cmd;
|
||||
i_vpr_h(inst, "%s: cmd %d\n", __func__, enc->cmd);
|
||||
if (enc->cmd != V4L2_ENC_CMD_STOP && enc->cmd != V4L2_ENC_CMD_START)
|
||||
return -EINVAL;
|
||||
enc->flags = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_start_cmd(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!is_decode_session(inst) && !is_encode_session(inst)) {
|
||||
i_vpr_e(inst, "%s: invalid session %d\n", __func__, inst->domain);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
rc = msm_vdec_start_cmd(inst);
|
||||
if (rc)
|
||||
return rc;
|
||||
} else if (is_encode_session(inst)) {
|
||||
rc = msm_venc_start_cmd(inst);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_stop_cmd(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!is_decode_session(inst) && !is_encode_session(inst)) {
|
||||
i_vpr_e(inst, "%s: invalid session %d\n", __func__, inst->domain);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
rc = msm_vdec_stop_cmd(inst);
|
||||
if (rc)
|
||||
return rc;
|
||||
} else if (is_encode_session(inst)) {
|
||||
rc = msm_venc_stop_cmd(inst);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_enum_framesizes(struct msm_vidc_inst *inst, struct v4l2_frmsizeenum *fsize)
|
||||
{
|
||||
enum msm_vidc_colorformat_type colorfmt;
|
||||
enum msm_vidc_codec_type codec;
|
||||
u32 meta_fmt;
|
||||
|
||||
/* only index 0 allowed as per v4l2 spec */
|
||||
if (fsize->index)
|
||||
return -EINVAL;
|
||||
|
||||
meta_fmt = v4l2_colorformat_from_driver(inst, MSM_VIDC_FMT_META, __func__);
|
||||
if (fsize->pixel_format != meta_fmt) {
|
||||
/* validate pixel format */
|
||||
codec = v4l2_codec_to_driver(inst, fsize->pixel_format, __func__);
|
||||
if (!codec) {
|
||||
colorfmt = v4l2_colorformat_to_driver(inst, fsize->pixel_format,
|
||||
__func__);
|
||||
if (colorfmt == MSM_VIDC_FMT_NONE) {
|
||||
i_vpr_e(inst, "%s: unsupported pix fmt %#x\n",
|
||||
__func__, fsize->pixel_format);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
|
||||
fsize->stepwise.min_width = inst->capabilities[FRAME_WIDTH].min;
|
||||
fsize->stepwise.max_width = inst->capabilities[FRAME_WIDTH].max;
|
||||
fsize->stepwise.step_width =
|
||||
inst->capabilities[FRAME_WIDTH].step_or_mask;
|
||||
fsize->stepwise.min_height = inst->capabilities[FRAME_HEIGHT].min;
|
||||
fsize->stepwise.max_height = inst->capabilities[FRAME_HEIGHT].max;
|
||||
fsize->stepwise.step_height =
|
||||
inst->capabilities[FRAME_HEIGHT].step_or_mask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_enum_frameintervals(struct msm_vidc_inst *inst, struct v4l2_frmivalenum *fival)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
enum msm_vidc_colorformat_type colorfmt;
|
||||
u32 fps, mbpf;
|
||||
u32 meta_fmt;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
i_vpr_e(inst, "%s: not supported by decoder\n", __func__);
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
core = inst->core;
|
||||
|
||||
|
||||
/* only index 0 allowed as per v4l2 spec */
|
||||
if (fival->index)
|
||||
return -EINVAL;
|
||||
|
||||
meta_fmt = v4l2_colorformat_from_driver(inst, MSM_VIDC_FMT_META, __func__);
|
||||
if (fival->pixel_format != meta_fmt) {
|
||||
/* validate pixel format */
|
||||
colorfmt = v4l2_colorformat_to_driver(inst, fival->pixel_format, __func__);
|
||||
if (colorfmt == MSM_VIDC_FMT_NONE) {
|
||||
i_vpr_e(inst, "%s: unsupported pix fmt %#x\n",
|
||||
__func__, fival->pixel_format);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* validate resolution */
|
||||
if (fival->width > inst->capabilities[FRAME_WIDTH].max ||
|
||||
fival->width < inst->capabilities[FRAME_WIDTH].min ||
|
||||
fival->height > inst->capabilities[FRAME_HEIGHT].max ||
|
||||
fival->height < inst->capabilities[FRAME_HEIGHT].min) {
|
||||
i_vpr_e(inst, "%s: unsupported resolution %u x %u\n", __func__,
|
||||
fival->width, fival->height);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* calculate max supported fps for a given resolution */
|
||||
mbpf = NUM_MBS_PER_FRAME(fival->height, fival->width);
|
||||
fps = core->capabilities[MAX_MBPS].value / mbpf;
|
||||
|
||||
fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
|
||||
fival->stepwise.min.numerator = 1;
|
||||
fival->stepwise.min.denominator =
|
||||
min_t(u32, fps, inst->capabilities[FRAME_RATE].max);
|
||||
fival->stepwise.max.numerator = 1;
|
||||
fival->stepwise.max.denominator = 1;
|
||||
fival->stepwise.step.numerator = 1;
|
||||
fival->stepwise.step.denominator = inst->capabilities[FRAME_RATE].max;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_subscribe_event(struct msm_vidc_inst *inst,
|
||||
const struct v4l2_event_subscription *sub)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
i_vpr_h(inst, "%s: type %d id %d\n", __func__, sub->type, sub->id);
|
||||
|
||||
if (is_decode_session(inst))
|
||||
rc = msm_vdec_subscribe_event(inst, sub);
|
||||
if (is_encode_session(inst))
|
||||
rc = msm_venc_subscribe_event(inst, sub);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_unsubscribe_event(struct msm_vidc_inst *inst,
|
||||
const struct v4l2_event_subscription *sub)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
i_vpr_h(inst, "%s: type %d id %d\n", __func__, sub->type, sub->id);
|
||||
rc = v4l2_event_unsubscribe(&inst->fh, sub);
|
||||
if (rc)
|
||||
i_vpr_e(inst, "%s: failed, type %d id %d\n",
|
||||
__func__, sub->type, sub->id);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_dqevent(struct msm_vidc_inst *inst, struct v4l2_event *event)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = v4l2_event_dequeue(&inst->fh, event, false);
|
||||
if (rc)
|
||||
i_vpr_e(inst, "%s: fialed\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void *msm_vidc_open(struct msm_vidc_core *core, u32 session_type)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_vidc_inst *inst = NULL;
|
||||
int i = 0;
|
||||
|
||||
d_vpr_h("%s: %s\n", __func__, video_banner);
|
||||
|
||||
if (session_type != MSM_VIDC_DECODER &&
|
||||
session_type != MSM_VIDC_ENCODER) {
|
||||
d_vpr_e("%s: invalid session_type %d\n",
|
||||
__func__, session_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = msm_vidc_core_init(core);
|
||||
if (rc)
|
||||
return NULL;
|
||||
|
||||
rc = msm_vidc_core_init_wait(core);
|
||||
if (rc)
|
||||
return NULL;
|
||||
|
||||
inst = vzalloc(sizeof(*inst));
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: allocation failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inst->core = core;
|
||||
inst->domain = session_type;
|
||||
inst->session_id = hash32_ptr(inst);
|
||||
msm_vidc_update_state(inst, MSM_VIDC_OPEN, __func__);
|
||||
inst->sub_state = MSM_VIDC_SUB_STATE_NONE;
|
||||
strlcpy(inst->sub_state_name, "SUB_STATE_NONE", sizeof(inst->sub_state_name));
|
||||
inst->active = true;
|
||||
inst->request = false;
|
||||
inst->ipsc_properties_set = false;
|
||||
inst->opsc_properties_set = false;
|
||||
inst->caps_list_prepared = false;
|
||||
inst->has_bframe = false;
|
||||
inst->iframe = false;
|
||||
inst->auto_framerate = DEFAULT_FPS << 16;
|
||||
inst->initial_time_us = ktime_get_ns() / 1000;
|
||||
kref_init(&inst->kref);
|
||||
mutex_init(&inst->lock);
|
||||
mutex_init(&inst->ctx_q_lock);
|
||||
mutex_init(&inst->client_lock);
|
||||
msm_vidc_update_debug_str(inst);
|
||||
i_vpr_h(inst, "Opening video instance: %d\n", session_type);
|
||||
|
||||
rc = msm_vidc_add_session(inst);
|
||||
if (rc) {
|
||||
i_vpr_e(inst, "%s: failed to add session\n", __func__);
|
||||
goto fail_add_session;
|
||||
}
|
||||
|
||||
rc = msm_vidc_pools_init(inst);
|
||||
if (rc) {
|
||||
i_vpr_e(inst, "%s: failed to init pool buffers\n", __func__);
|
||||
goto fail_pools_init;
|
||||
}
|
||||
INIT_LIST_HEAD(&inst->caps_list);
|
||||
INIT_LIST_HEAD(&inst->timestamps.list);
|
||||
INIT_LIST_HEAD(&inst->ts_reorder.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.input.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.input_meta.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.output.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.output_meta.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.read_only.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.bin.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.arp.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.comv.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.non_comv.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.line.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.dpb.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.persist.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.vpss.list);
|
||||
INIT_LIST_HEAD(&inst->buffers.partial_data.list);
|
||||
INIT_LIST_HEAD(&inst->mem_info.bin.list);
|
||||
INIT_LIST_HEAD(&inst->mem_info.arp.list);
|
||||
INIT_LIST_HEAD(&inst->mem_info.comv.list);
|
||||
INIT_LIST_HEAD(&inst->mem_info.non_comv.list);
|
||||
INIT_LIST_HEAD(&inst->mem_info.line.list);
|
||||
INIT_LIST_HEAD(&inst->mem_info.dpb.list);
|
||||
INIT_LIST_HEAD(&inst->mem_info.persist.list);
|
||||
INIT_LIST_HEAD(&inst->mem_info.vpss.list);
|
||||
INIT_LIST_HEAD(&inst->mem_info.partial_data.list);
|
||||
INIT_LIST_HEAD(&inst->children_list);
|
||||
INIT_LIST_HEAD(&inst->firmware_list);
|
||||
INIT_LIST_HEAD(&inst->enc_input_crs);
|
||||
INIT_LIST_HEAD(&inst->dmabuf_tracker);
|
||||
INIT_LIST_HEAD(&inst->input_timer_list);
|
||||
INIT_LIST_HEAD(&inst->pending_pkts);
|
||||
INIT_LIST_HEAD(&inst->fence_list);
|
||||
INIT_LIST_HEAD(&inst->buffer_stats_list);
|
||||
for (i = 0; i < MAX_SIGNAL; i++)
|
||||
init_completion(&inst->completions[i]);
|
||||
|
||||
inst->workq = create_singlethread_workqueue("workq");
|
||||
if (!inst->workq) {
|
||||
i_vpr_e(inst, "%s: create workq failed\n", __func__);
|
||||
goto fail_create_workq;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&inst->stats_work, msm_vidc_stats_handler);
|
||||
INIT_WORK(&inst->stability_work, msm_vidc_stability_handler);
|
||||
|
||||
rc = msm_vidc_v4l2_fh_init(inst);
|
||||
if (rc)
|
||||
goto fail_eventq_init;
|
||||
|
||||
rc = msm_vidc_vb2_queue_init(inst);
|
||||
if (rc)
|
||||
goto fail_vb2q_init;
|
||||
|
||||
if (is_decode_session(inst))
|
||||
rc = msm_vdec_inst_init(inst);
|
||||
else if (is_encode_session(inst))
|
||||
rc = msm_venc_inst_init(inst);
|
||||
if (rc)
|
||||
goto fail_inst_init;
|
||||
|
||||
rc = msm_vidc_fence_init(inst);
|
||||
if (rc)
|
||||
goto fail_fence_init;
|
||||
|
||||
/* reset clock residency stats */
|
||||
msm_vidc_reset_residency_stats(core);
|
||||
|
||||
msm_vidc_scale_power(inst, true);
|
||||
|
||||
rc = msm_vidc_session_open(inst);
|
||||
if (rc) {
|
||||
msm_vidc_core_deinit(core, true);
|
||||
goto fail_session_open;
|
||||
}
|
||||
|
||||
inst->debugfs_root =
|
||||
msm_vidc_debugfs_init_inst(inst, core->debugfs_root);
|
||||
if (!inst->debugfs_root)
|
||||
i_vpr_h(inst, "%s: debugfs not available\n", __func__);
|
||||
|
||||
return inst;
|
||||
|
||||
fail_session_open:
|
||||
msm_vidc_fence_deinit(inst);
|
||||
fail_fence_init:
|
||||
if (is_decode_session(inst))
|
||||
msm_vdec_inst_deinit(inst);
|
||||
else if (is_encode_session(inst))
|
||||
msm_venc_inst_deinit(inst);
|
||||
fail_inst_init:
|
||||
msm_vidc_vb2_queue_deinit(inst);
|
||||
fail_vb2q_init:
|
||||
msm_vidc_v4l2_fh_deinit(inst);
|
||||
fail_eventq_init:
|
||||
destroy_workqueue(inst->workq);
|
||||
fail_create_workq:
|
||||
msm_vidc_pools_deinit(inst);
|
||||
fail_pools_init:
|
||||
msm_vidc_remove_session(inst);
|
||||
msm_vidc_remove_dangling_session(inst);
|
||||
fail_add_session:
|
||||
mutex_destroy(&inst->client_lock);
|
||||
mutex_destroy(&inst->ctx_q_lock);
|
||||
mutex_destroy(&inst->lock);
|
||||
vfree(inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int msm_vidc_close(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_vidc_core *core;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
i_vpr_h(inst, "%s()\n", __func__);
|
||||
client_lock(inst, __func__);
|
||||
inst_lock(inst, __func__);
|
||||
/* print final stats */
|
||||
msm_vidc_print_stats(inst);
|
||||
/* print internal buffer memory usage stats */
|
||||
msm_vidc_print_memory_stats(inst);
|
||||
msm_vidc_print_residency_stats(core);
|
||||
msm_vidc_session_close(inst);
|
||||
msm_vidc_change_state(inst, MSM_VIDC_CLOSE, __func__);
|
||||
inst->sub_state = MSM_VIDC_SUB_STATE_NONE;
|
||||
strscpy(inst->sub_state_name, "SUB_STATE_NONE", sizeof(inst->sub_state_name));
|
||||
inst_unlock(inst, __func__);
|
||||
client_unlock(inst, __func__);
|
||||
cancel_stability_work_sync(inst);
|
||||
cancel_stats_work_sync(inst);
|
||||
msm_vidc_show_stats(inst);
|
||||
put_inst(inst);
|
||||
msm_vidc_schedule_core_deinit(core);
|
||||
|
||||
return rc;
|
||||
}
|
453
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_buffer.c
Normal file
453
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_buffer.c
Normal file
@ -0,0 +1,453 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "msm_media_info.h"
|
||||
#include "msm_vidc_buffer.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
|
||||
/* Generic function for all targets. Not being used for iris2 */
|
||||
u32 msm_vidc_input_min_count(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 input_min_count = 0;
|
||||
u32 hb_enh_layer = 0;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
input_min_count = MIN_DEC_INPUT_BUFFERS;
|
||||
} else if (is_encode_session(inst)) {
|
||||
input_min_count = MIN_ENC_INPUT_BUFFERS;
|
||||
if (is_hierb_type_requested(inst)) {
|
||||
hb_enh_layer =
|
||||
inst->capabilities[ENH_LAYER_COUNT].value;
|
||||
if (inst->codec == MSM_VIDC_H264 &&
|
||||
!inst->capabilities[LAYER_ENABLE].value) {
|
||||
hb_enh_layer = 0;
|
||||
}
|
||||
if (hb_enh_layer)
|
||||
input_min_count = (1 << hb_enh_layer) + 2;
|
||||
}
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: invalid domain %d\n",
|
||||
__func__, inst->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_thumbnail_session(inst) || is_image_session(inst))
|
||||
input_min_count = 1;
|
||||
|
||||
return input_min_count;
|
||||
}
|
||||
|
||||
u32 msm_vidc_output_min_count(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 output_min_count;
|
||||
|
||||
if (!is_decode_session(inst) && !is_encode_session(inst))
|
||||
return 0;
|
||||
|
||||
if (is_thumbnail_session(inst))
|
||||
return 1;
|
||||
|
||||
if (is_encode_session(inst))
|
||||
return MIN_ENC_OUTPUT_BUFFERS;
|
||||
|
||||
/* decoder handling below */
|
||||
/* fw_min_count > 0 indicates reconfig event has already arrived */
|
||||
if (inst->fw_min_count) {
|
||||
/* TODO: need to update condition to include AVC/HEVC as well */
|
||||
if (is_split_mode_enabled(inst) &&
|
||||
(inst->codec == MSM_VIDC_AV1 ||
|
||||
inst->codec == MSM_VIDC_VP9)) {
|
||||
/*
|
||||
* return opb min buffer count as min(4, fw_min_count)
|
||||
* fw min count is used for dpb min count
|
||||
*/
|
||||
return min_t(u32, 4, inst->fw_min_count);
|
||||
} else {
|
||||
return inst->fw_min_count;
|
||||
}
|
||||
}
|
||||
|
||||
/* initial handling before reconfig event arrived */
|
||||
switch (inst->codec) {
|
||||
case MSM_VIDC_H264:
|
||||
case MSM_VIDC_HEVC:
|
||||
output_min_count = 4;
|
||||
break;
|
||||
case MSM_VIDC_VP9:
|
||||
output_min_count = 9;
|
||||
break;
|
||||
case MSM_VIDC_AV1:
|
||||
output_min_count = 11;
|
||||
break;
|
||||
case MSM_VIDC_HEIC:
|
||||
output_min_count = 3;
|
||||
break;
|
||||
default:
|
||||
output_min_count = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
return output_min_count;
|
||||
}
|
||||
|
||||
u32 msm_vidc_input_extra_count(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 count = 0;
|
||||
struct msm_vidc_core *core;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
/*
|
||||
* no extra buffers for thumbnail session because
|
||||
* neither dcvs nor batching will be enabled
|
||||
*/
|
||||
if (is_thumbnail_session(inst) || is_image_session(inst))
|
||||
return 0;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
/*
|
||||
* if decode batching enabled, ensure minimum batch size
|
||||
* count of input buffers present on input port
|
||||
*/
|
||||
if (core->capabilities[DECODE_BATCH].value &&
|
||||
inst->decode_batch.enable) {
|
||||
if (inst->buffers.input.min_count < inst->decode_batch.size) {
|
||||
count = inst->decode_batch.size -
|
||||
inst->buffers.input.min_count;
|
||||
}
|
||||
}
|
||||
} else if (is_encode_session(inst)) {
|
||||
/* add dcvs buffers, if platform supports dcvs */
|
||||
if (core->capabilities[DCVS].value)
|
||||
count = DCVS_ENC_EXTRA_INPUT_BUFFERS;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
u32 msm_vidc_output_extra_count(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 count = 0;
|
||||
struct msm_vidc_core *core;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
/*
|
||||
* no extra buffers for thumbnail session because
|
||||
* neither dcvs nor batching will be enabled
|
||||
*/
|
||||
if (is_thumbnail_session(inst) || is_image_session(inst))
|
||||
return 0;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
/* add dcvs buffers, if platform supports dcvs */
|
||||
if (core->capabilities[DCVS].value)
|
||||
count = DCVS_DEC_EXTRA_OUTPUT_BUFFERS;
|
||||
/*
|
||||
* if decode batching enabled, ensure minimum batch size
|
||||
* count of extra output buffers added on output port
|
||||
*/
|
||||
if (core->capabilities[DECODE_BATCH].value &&
|
||||
inst->decode_batch.enable &&
|
||||
count < inst->decode_batch.size)
|
||||
count = inst->decode_batch.size;
|
||||
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
u32 msm_vidc_internal_buffer_count(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
u32 count = 0;
|
||||
|
||||
if (is_encode_session(inst))
|
||||
return 1;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
if (buffer_type == MSM_VIDC_BUF_BIN ||
|
||||
buffer_type == MSM_VIDC_BUF_LINE ||
|
||||
buffer_type == MSM_VIDC_BUF_PERSIST ||
|
||||
buffer_type == MSM_VIDC_BUF_PARTIAL_DATA) {
|
||||
count = 1;
|
||||
} else if (buffer_type == MSM_VIDC_BUF_COMV ||
|
||||
buffer_type == MSM_VIDC_BUF_NON_COMV) {
|
||||
if (inst->codec == MSM_VIDC_H264 ||
|
||||
inst->codec == MSM_VIDC_HEVC ||
|
||||
inst->codec == MSM_VIDC_HEIC ||
|
||||
inst->codec == MSM_VIDC_AV1)
|
||||
count = 1;
|
||||
else
|
||||
count = 0;
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: unsupported buffer type %s\n",
|
||||
__func__, buf_name(buffer_type));
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
u32 msm_vidc_decoder_input_size(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 frame_size, num_mbs;
|
||||
u32 div_factor = 1;
|
||||
u32 base_res_mbs = NUM_MBS_4k;
|
||||
struct v4l2_format *f;
|
||||
u32 bitstream_size_overwrite = 0;
|
||||
enum msm_vidc_codec_type codec;
|
||||
|
||||
bitstream_size_overwrite =
|
||||
inst->capabilities[BITSTREAM_SIZE_OVERWRITE].value;
|
||||
if (bitstream_size_overwrite) {
|
||||
frame_size = bitstream_size_overwrite;
|
||||
i_vpr_h(inst, "client configured bitstream buffer size %d\n",
|
||||
frame_size);
|
||||
return frame_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decoder input size calculation:
|
||||
* For 8k resolution, buffer size is calculated as 8k mbs / 4 and
|
||||
* for 8k cases we expect width/height to be set always.
|
||||
* In all other cases, buffer size is calculated as
|
||||
* 4k mbs for VP8/VP9 and 4k / 2 for remaining codecs.
|
||||
*/
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
codec = v4l2_codec_to_driver(inst, f->fmt.pix_mp.pixelformat, __func__);
|
||||
num_mbs = msm_vidc_get_mbs_per_frame(inst);
|
||||
if (num_mbs > NUM_MBS_4k) {
|
||||
div_factor = 4;
|
||||
base_res_mbs = inst->capabilities[MBPF].value;
|
||||
} else {
|
||||
base_res_mbs = NUM_MBS_4k;
|
||||
if (codec == MSM_VIDC_VP9)
|
||||
div_factor = 1;
|
||||
else
|
||||
div_factor = 2;
|
||||
}
|
||||
|
||||
if (is_secure_session(inst))
|
||||
div_factor = div_factor << 1;
|
||||
|
||||
/* For image session, use the actual resolution to calc buffer size */
|
||||
if (is_image_session(inst)) {
|
||||
base_res_mbs = num_mbs;
|
||||
div_factor = 1;
|
||||
}
|
||||
|
||||
frame_size = base_res_mbs * MB_SIZE_IN_PIXEL * 3 / 2 / div_factor;
|
||||
|
||||
/* multiply by 10/8 (1.25) to get size for 10 bit case */
|
||||
if (codec == MSM_VIDC_VP9 || codec == MSM_VIDC_AV1 ||
|
||||
codec == MSM_VIDC_HEVC || codec == MSM_VIDC_HEIC)
|
||||
frame_size = frame_size + (frame_size >> 2);
|
||||
|
||||
i_vpr_h(inst, "set input buffer size to %d\n", frame_size);
|
||||
|
||||
return ALIGN(frame_size, SZ_4K);
|
||||
}
|
||||
|
||||
u32 msm_vidc_decoder_output_size(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size;
|
||||
struct v4l2_format *f;
|
||||
enum msm_vidc_colorformat_type colorformat;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
colorformat = v4l2_colorformat_to_driver(inst, f->fmt.pix_mp.pixelformat,
|
||||
__func__);
|
||||
size = video_buffer_size(colorformat, f->fmt.pix_mp.width,
|
||||
f->fmt.pix_mp.height, true);
|
||||
return size;
|
||||
}
|
||||
|
||||
u32 msm_vidc_decoder_input_meta_size(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return MSM_VIDC_METADATA_SIZE;
|
||||
}
|
||||
|
||||
u32 msm_vidc_decoder_output_meta_size(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = MSM_VIDC_METADATA_SIZE;
|
||||
|
||||
if (inst->capabilities[META_DOLBY_RPU].value)
|
||||
size += MSM_VIDC_METADATA_DOLBY_RPU_SIZE;
|
||||
|
||||
return ALIGN(size, SZ_4K);
|
||||
}
|
||||
|
||||
u32 msm_vidc_encoder_input_size(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size;
|
||||
struct v4l2_format *f;
|
||||
u32 width, height;
|
||||
enum msm_vidc_colorformat_type colorformat;
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
colorformat = v4l2_colorformat_to_driver(inst, f->fmt.pix_mp.pixelformat,
|
||||
__func__);
|
||||
if (is_image_session(inst)) {
|
||||
width = ALIGN(width, inst->capabilities[GRID_SIZE].value);
|
||||
height = ALIGN(height, inst->capabilities[GRID_SIZE].value);
|
||||
}
|
||||
size = video_buffer_size(colorformat, width, height, true);
|
||||
return size;
|
||||
}
|
||||
|
||||
u32 msm_vidc_enc_delivery_mode_based_output_buf_size(struct msm_vidc_inst *inst,
|
||||
u32 frame_size)
|
||||
{
|
||||
u32 slice_size;
|
||||
u32 width, height;
|
||||
u32 width_in_lcus, height_in_lcus, lcu_size;
|
||||
u32 total_mb_count;
|
||||
struct v4l2_format *f;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
|
||||
if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_HEVC &&
|
||||
f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_H264)
|
||||
return frame_size;
|
||||
|
||||
if (inst->capabilities[SLICE_MODE].value != V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB)
|
||||
return frame_size;
|
||||
|
||||
if (!is_enc_slice_delivery_mode(inst))
|
||||
return frame_size;
|
||||
|
||||
lcu_size = (f->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_HEVC) ? 32 : 16;
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
width_in_lcus = (width + lcu_size - 1) / lcu_size;
|
||||
height_in_lcus = (height + lcu_size - 1) / lcu_size;
|
||||
total_mb_count = width_in_lcus * height_in_lcus;
|
||||
|
||||
slice_size = ((frame_size * inst->capabilities[SLICE_MAX_MB].value)
|
||||
+ total_mb_count - 1) / total_mb_count;
|
||||
|
||||
slice_size = ALIGN(slice_size, SZ_4K);
|
||||
return slice_size;
|
||||
}
|
||||
|
||||
u32 msm_vidc_encoder_output_size(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 frame_size;
|
||||
u32 mbs_per_frame;
|
||||
u32 width, height;
|
||||
struct v4l2_format *f;
|
||||
enum msm_vidc_codec_type codec;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
codec = v4l2_codec_to_driver(inst, f->fmt.pix_mp.pixelformat, __func__);
|
||||
/*
|
||||
* Encoder output size calculation: 32 Align width/height
|
||||
* For heic session : YUVsize * 2
|
||||
* For resolution <= 480x360p : YUVsize * 2
|
||||
* For resolution > 360p & <= 4K : YUVsize / 2
|
||||
* For resolution > 4k : YUVsize / 4
|
||||
* Initially frame_size = YUVsize * 2;
|
||||
*/
|
||||
|
||||
width = ALIGN(f->fmt.pix_mp.width, BUFFER_ALIGNMENT_SIZE(32));
|
||||
height = ALIGN(f->fmt.pix_mp.height, BUFFER_ALIGNMENT_SIZE(32));
|
||||
mbs_per_frame = NUM_MBS_PER_FRAME(width, height);
|
||||
frame_size = (width * height * 3);
|
||||
|
||||
/* Image session: 2 x yuv size */
|
||||
if (is_image_session(inst) ||
|
||||
inst->capabilities[BITRATE_MODE].value == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
|
||||
goto skip_calc;
|
||||
|
||||
if (mbs_per_frame <= NUM_MBS_360P)
|
||||
(void)frame_size; /* Default frame_size = YUVsize * 2 */
|
||||
else if (mbs_per_frame <= NUM_MBS_4k)
|
||||
frame_size = frame_size >> 2;
|
||||
else
|
||||
frame_size = frame_size >> 3;
|
||||
|
||||
/*if ((inst->rc_type == RATE_CONTROL_OFF) ||
|
||||
(inst->rc_type == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ))
|
||||
frame_size = frame_size << 1;
|
||||
|
||||
if (inst->rc_type == RATE_CONTROL_LOSSLESS)
|
||||
frame_size = (width * height * 9) >> 2;
|
||||
*/
|
||||
|
||||
skip_calc:
|
||||
/* multiply by 10/8 (1.25) to get size for 10 bit case
|
||||
*/
|
||||
if (codec == MSM_VIDC_HEVC || codec == MSM_VIDC_HEIC)
|
||||
frame_size = frame_size + (frame_size >> 2);
|
||||
|
||||
frame_size = ALIGN(frame_size, SZ_4K);
|
||||
frame_size = msm_vidc_enc_delivery_mode_based_output_buf_size(inst, frame_size);
|
||||
|
||||
return frame_size;
|
||||
}
|
||||
|
||||
static inline u32 ROI_METADATA_SIZE(
|
||||
u32 width, u32 height, u32 lcu_size) {
|
||||
u32 lcu_width = 0;
|
||||
u32 lcu_height = 0;
|
||||
u32 n_shift = 0;
|
||||
|
||||
while (lcu_size && !(lcu_size & 0x1)) {
|
||||
n_shift++;
|
||||
lcu_size = lcu_size >> 1;
|
||||
}
|
||||
lcu_width = (width + (lcu_size - 1)) >> n_shift;
|
||||
lcu_height = (height + (lcu_size - 1)) >> n_shift;
|
||||
|
||||
return (((lcu_width + 7) >> 3) << 3) * lcu_height * 2;
|
||||
}
|
||||
|
||||
u32 msm_vidc_encoder_input_meta_size(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 size = 0;
|
||||
u32 lcu_size = 0;
|
||||
struct v4l2_format *f;
|
||||
u32 width, height;
|
||||
|
||||
size = MSM_VIDC_METADATA_SIZE;
|
||||
|
||||
if (inst->capabilities[META_ROI_INFO].value) {
|
||||
lcu_size = 16;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
if (f->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_HEVC)
|
||||
lcu_size = 32;
|
||||
|
||||
f = &inst->fmts[INPUT_PORT];
|
||||
width = f->fmt.pix_mp.width;
|
||||
height = f->fmt.pix_mp.height;
|
||||
if (is_image_session(inst)) {
|
||||
width = ALIGN(width, inst->capabilities[GRID_SIZE].value);
|
||||
height = ALIGN(height, inst->capabilities[GRID_SIZE].value);
|
||||
}
|
||||
size += ROI_METADATA_SIZE(width, height, lcu_size);
|
||||
size = ALIGN(size, SZ_4K);
|
||||
}
|
||||
|
||||
if (inst->capabilities[META_DOLBY_RPU].value) {
|
||||
size += MSM_VIDC_METADATA_DOLBY_RPU_SIZE;
|
||||
size = ALIGN(size, SZ_4K);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
u32 msm_vidc_encoder_output_meta_size(struct msm_vidc_inst *inst)
|
||||
{
|
||||
return MSM_VIDC_METADATA_SIZE;
|
||||
}
|
1078
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_control.c
Normal file
1078
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_control.c
Normal file
File diff suppressed because it is too large
Load Diff
816
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_debug.c
Normal file
816
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_debug.c
Normal file
@ -0,0 +1,816 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include "msm_vidc_debug.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vidc.h"
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_events.h"
|
||||
|
||||
extern struct msm_vidc_core *g_core;
|
||||
|
||||
#define MAX_SSR_STRING_LEN 64
|
||||
#define MAX_STABILITY_STRING_LEN 64
|
||||
#define MAX_DEBUG_LEVEL_STRING_LEN 15
|
||||
#define MSM_VIDC_MIN_STATS_DELAY_MS 200
|
||||
#define MSM_VIDC_MAX_STATS_DELAY_MS 10000
|
||||
|
||||
unsigned int msm_vidc_debug = DRV_LOG;
|
||||
unsigned int msm_fw_debug = FW_LOG;
|
||||
|
||||
/* disabled synx fence by default temporarily */
|
||||
bool msm_vidc_synx_fence_enable = false;
|
||||
|
||||
static int debug_level_set_drv(const char *val,
|
||||
const struct kernel_param *kp)
|
||||
{
|
||||
struct msm_vidc_core *core = NULL;
|
||||
unsigned int dvalue;
|
||||
int ret;
|
||||
|
||||
if (!kp || !kp->arg || !val) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = kstrtouint(val, 0, &dvalue);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
msm_vidc_debug = dvalue;
|
||||
|
||||
core = *(struct msm_vidc_core **)kp->arg;
|
||||
|
||||
if (!core) {
|
||||
d_vpr_e("%s: Invalid core/capabilities\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check if driver is more than default level */
|
||||
if ((dvalue & DRV_LOGMASK) & ~(DRV_LOG)) {
|
||||
core->capabilities[HW_RESPONSE_TIMEOUT].value = 4 * HW_RESPONSE_TIMEOUT_VALUE;
|
||||
core->capabilities[SW_PC_DELAY].value = 4 * SW_PC_DELAY_VALUE;
|
||||
core->capabilities[FW_UNLOAD_DELAY].value = 4 * FW_UNLOAD_DELAY_VALUE;
|
||||
} else {
|
||||
/* reset timeout values, if user reduces the logging */
|
||||
core->capabilities[HW_RESPONSE_TIMEOUT].value = HW_RESPONSE_TIMEOUT_VALUE;
|
||||
core->capabilities[SW_PC_DELAY].value = SW_PC_DELAY_VALUE;
|
||||
core->capabilities[FW_UNLOAD_DELAY].value = FW_UNLOAD_DELAY_VALUE;
|
||||
}
|
||||
|
||||
d_vpr_h(
|
||||
"timeout updated for driver: hw_response %u, sw_pc %u, fw_unload %u, debug_level %#x\n",
|
||||
core->capabilities[HW_RESPONSE_TIMEOUT].value,
|
||||
core->capabilities[SW_PC_DELAY].value,
|
||||
core->capabilities[FW_UNLOAD_DELAY].value,
|
||||
msm_vidc_debug);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int debug_level_set_fw(const char *val,
|
||||
const struct kernel_param *kp)
|
||||
{
|
||||
struct msm_vidc_core *core = NULL;
|
||||
unsigned int dvalue;
|
||||
int ret;
|
||||
|
||||
if (!kp || !kp->arg || !val) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = kstrtouint(val, 0, &dvalue);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
msm_fw_debug = dvalue;
|
||||
|
||||
core = *(struct msm_vidc_core **)kp->arg;
|
||||
|
||||
if (!core) {
|
||||
d_vpr_e("%s: Invalid core/capabilities\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check if firmware is more than default level */
|
||||
if ((dvalue & FW_LOGMASK) & ~(FW_LOG)) {
|
||||
core->capabilities[HW_RESPONSE_TIMEOUT].value = 4 * HW_RESPONSE_TIMEOUT_VALUE;
|
||||
core->capabilities[SW_PC_DELAY].value = 4 * SW_PC_DELAY_VALUE;
|
||||
core->capabilities[FW_UNLOAD_DELAY].value = 4 * FW_UNLOAD_DELAY_VALUE;
|
||||
} else {
|
||||
/* reset timeout values, if user reduces the logging */
|
||||
core->capabilities[HW_RESPONSE_TIMEOUT].value = HW_RESPONSE_TIMEOUT_VALUE;
|
||||
core->capabilities[SW_PC_DELAY].value = SW_PC_DELAY_VALUE;
|
||||
core->capabilities[FW_UNLOAD_DELAY].value = FW_UNLOAD_DELAY_VALUE;
|
||||
}
|
||||
|
||||
d_vpr_h(
|
||||
"timeout updated for firmware: hw_response %u, sw_pc %u, fw_unload %u, debug_level %#x\n",
|
||||
core->capabilities[HW_RESPONSE_TIMEOUT].value,
|
||||
core->capabilities[SW_PC_DELAY].value,
|
||||
core->capabilities[FW_UNLOAD_DELAY].value,
|
||||
msm_fw_debug);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int debug_level_get_drv(char *buffer, const struct kernel_param *kp)
|
||||
{
|
||||
return scnprintf(buffer, PAGE_SIZE, "%#x", msm_vidc_debug);
|
||||
}
|
||||
|
||||
static int debug_level_get_fw(char *buffer, const struct kernel_param *kp)
|
||||
{
|
||||
return scnprintf(buffer, PAGE_SIZE, "%#x", msm_fw_debug);
|
||||
}
|
||||
|
||||
static const struct kernel_param_ops msm_vidc_debug_fops = {
|
||||
.set = debug_level_set_drv,
|
||||
.get = debug_level_get_drv,
|
||||
};
|
||||
|
||||
static const struct kernel_param_ops msm_fw_debug_fops = {
|
||||
.set = debug_level_set_fw,
|
||||
.get = debug_level_get_fw,
|
||||
};
|
||||
|
||||
static int fw_dump_set(const char *val,
|
||||
const struct kernel_param *kp)
|
||||
{
|
||||
unsigned int dvalue;
|
||||
int ret;
|
||||
|
||||
if (!kp || !kp->arg || !val) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = kstrtouint(val, 0, &dvalue);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
msm_vidc_fw_dump = dvalue;
|
||||
|
||||
d_vpr_h("fw dump %s\n", msm_vidc_fw_dump ? "Enabled" : "Disabled");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fw_dump_get(char *buffer, const struct kernel_param *kp)
|
||||
{
|
||||
return scnprintf(buffer, PAGE_SIZE, "%#x", msm_vidc_fw_dump);
|
||||
}
|
||||
|
||||
static const struct kernel_param_ops msm_vidc_fw_dump_fops = {
|
||||
.set = fw_dump_set,
|
||||
.get = fw_dump_get,
|
||||
};
|
||||
|
||||
static int synx_fence_set(const char *val,
|
||||
const struct kernel_param *kp)
|
||||
{
|
||||
unsigned int dvalue;
|
||||
int ret;
|
||||
|
||||
if (!kp || !kp->arg || !val) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = kstrtouint(val, 0, &dvalue);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
msm_vidc_synx_fence_enable = dvalue;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int synx_fence_get(char *buffer, const struct kernel_param *kp)
|
||||
{
|
||||
return scnprintf(buffer, PAGE_SIZE, "%#x", msm_vidc_synx_fence_enable);
|
||||
}
|
||||
|
||||
static const struct kernel_param_ops msm_vidc_synx_fence_debug_fops = {
|
||||
.set = synx_fence_set,
|
||||
.get = synx_fence_get,
|
||||
};
|
||||
|
||||
module_param_cb(msm_vidc_debug, &msm_vidc_debug_fops, &g_core, 0644);
|
||||
module_param_cb(msm_fw_debug, &msm_fw_debug_fops, &g_core, 0644);
|
||||
module_param_cb(msm_vidc_fw_dump, &msm_vidc_fw_dump_fops, &g_core, 0644);
|
||||
module_param_cb(msm_vidc_synx_fence_enable,
|
||||
&msm_vidc_synx_fence_debug_fops, &g_core, 0644);
|
||||
|
||||
bool msm_vidc_lossless_encode = !true;
|
||||
EXPORT_SYMBOL(msm_vidc_lossless_encode);
|
||||
|
||||
bool msm_vidc_syscache_disable = !true;
|
||||
EXPORT_SYMBOL(msm_vidc_syscache_disable);
|
||||
|
||||
int msm_vidc_clock_voting = !1;
|
||||
int msm_vidc_ddr_bw = !1;
|
||||
int msm_vidc_llc_bw = !1;
|
||||
|
||||
bool msm_vidc_fw_dump = !true;
|
||||
EXPORT_SYMBOL(msm_vidc_fw_dump);
|
||||
|
||||
unsigned int msm_vidc_enable_bugon = !1;
|
||||
EXPORT_SYMBOL(msm_vidc_enable_bugon);
|
||||
|
||||
#define MAX_DBG_BUF_SIZE 4096
|
||||
|
||||
struct core_inst_pair {
|
||||
struct msm_vidc_core *core;
|
||||
struct msm_vidc_inst *inst;
|
||||
};
|
||||
|
||||
/* debug fs support */
|
||||
static inline void tic(struct msm_vidc_inst *inst, enum profiling_points p,
|
||||
char *b)
|
||||
{
|
||||
if (!inst->debug.pdata[p].name[0])
|
||||
memcpy(inst->debug.pdata[p].name, b, 64);
|
||||
if (inst->debug.pdata[p].sampling) {
|
||||
inst->debug.pdata[p].start = ktime_get_ns() / 1000 / 1000;
|
||||
inst->debug.pdata[p].sampling = false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void toc(struct msm_vidc_inst *inst, enum profiling_points p)
|
||||
{
|
||||
if (!inst->debug.pdata[p].sampling) {
|
||||
inst->debug.pdata[p].stop = ktime_get_ns() / 1000 / 1000;
|
||||
inst->debug.pdata[p].cumulative += inst->debug.pdata[p].stop -
|
||||
inst->debug.pdata[p].start;
|
||||
inst->debug.pdata[p].sampling = true;
|
||||
}
|
||||
}
|
||||
|
||||
void msm_vidc_show_stats(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; x < MAX_PROFILING_POINTS; x++) {
|
||||
if (inst->debug.pdata[x].name[0]) {
|
||||
if (inst->debug.samples) {
|
||||
i_vpr_p(inst, "%s averaged %llu ms/sample\n",
|
||||
inst->debug.pdata[x].name,
|
||||
inst->debug.pdata[x].cumulative /
|
||||
inst->debug.samples);
|
||||
}
|
||||
|
||||
i_vpr_p(inst, "%s Samples: %d\n",
|
||||
inst->debug.pdata[x].name, inst->debug.samples);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static u32 write_str(char *buffer,
|
||||
size_t size, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
u32 len;
|
||||
|
||||
va_start(args, fmt);
|
||||
len = vscnprintf(buffer, size, fmt, args);
|
||||
va_end(args);
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t core_info_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct msm_vidc_core *core = file->private_data;
|
||||
char *cur, *end, *dbuf = NULL;
|
||||
ssize_t len = 0;
|
||||
|
||||
if (!core) {
|
||||
d_vpr_e("%s: invalid params %pK\n", __func__, core);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dbuf = vzalloc(MAX_DBG_BUF_SIZE);
|
||||
if (!dbuf) {
|
||||
d_vpr_e("%s: allocation failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cur = dbuf;
|
||||
end = cur + MAX_DBG_BUF_SIZE;
|
||||
|
||||
cur += write_str(cur, end - cur, "Core state: %d\n", core->state);
|
||||
|
||||
cur += write_str(cur, end - cur,
|
||||
"FW version : %s\n", core->fw_version);
|
||||
cur += write_str(cur, end - cur,
|
||||
"register_base: 0x%x\n", core->resource->register_base_addr);
|
||||
cur += write_str(cur, end - cur, "irq: %u\n", core->resource->irq);
|
||||
|
||||
len = simple_read_from_buffer(buf, count, ppos,
|
||||
dbuf, cur - dbuf);
|
||||
|
||||
vfree(dbuf);
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct file_operations core_info_fops = {
|
||||
.open = simple_open,
|
||||
.read = core_info_read,
|
||||
};
|
||||
|
||||
static ssize_t stats_delay_write_ms(struct file *filp, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_vidc_core *core = filp->private_data;
|
||||
char kbuf[MAX_DEBUG_LEVEL_STRING_LEN] = {0};
|
||||
u32 delay_ms = 0;
|
||||
|
||||
if (!core) {
|
||||
d_vpr_e("%s: invalid params %pK\n", __func__, core);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* filter partial writes and invalid commands */
|
||||
if (*ppos != 0 || count >= sizeof(kbuf) || count == 0) {
|
||||
d_vpr_e("returning error - pos %lld, count %lu\n", *ppos, count);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
rc = simple_write_to_buffer(kbuf, sizeof(kbuf) - 1, ppos, buf, count);
|
||||
if (rc < 0) {
|
||||
d_vpr_e("%s: User memory fault\n", __func__);
|
||||
rc = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = kstrtoint(kbuf, 0, &delay_ms);
|
||||
if (rc) {
|
||||
d_vpr_e("returning error err %d\n", rc);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
delay_ms = clamp_t(u32, delay_ms, MSM_VIDC_MIN_STATS_DELAY_MS, MSM_VIDC_MAX_STATS_DELAY_MS);
|
||||
core->capabilities[STATS_TIMEOUT_MS].value = delay_ms;
|
||||
d_vpr_h("Stats delay is updated to - %d ms\n", delay_ms);
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t stats_delay_read_ms(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
size_t len;
|
||||
char kbuf[MAX_DEBUG_LEVEL_STRING_LEN];
|
||||
struct msm_vidc_core *core = file->private_data;
|
||||
|
||||
if (!core) {
|
||||
d_vpr_e("%s: invalid params %pK\n", __func__, core);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = scnprintf(kbuf, sizeof(kbuf), "%u\n", core->capabilities[STATS_TIMEOUT_MS].value);
|
||||
return simple_read_from_buffer(buf, count, ppos, kbuf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations stats_delay_fops = {
|
||||
.open = simple_open,
|
||||
.write = stats_delay_write_ms,
|
||||
.read = stats_delay_read_ms,
|
||||
};
|
||||
|
||||
static ssize_t trigger_ssr_write(struct file *filp, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
unsigned long ssr_trigger_val = 0;
|
||||
int rc = 0;
|
||||
struct msm_vidc_core *core = filp->private_data;
|
||||
size_t size = MAX_SSR_STRING_LEN;
|
||||
char kbuf[MAX_SSR_STRING_LEN + 1] = { 0 };
|
||||
|
||||
if (!core) {
|
||||
d_vpr_e("%s: invalid params %pK\n", __func__, core);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
return -EINVAL;
|
||||
|
||||
if (!count)
|
||||
goto exit;
|
||||
|
||||
if (count < size)
|
||||
size = count;
|
||||
|
||||
if (copy_from_user(kbuf, buf, size)) {
|
||||
d_vpr_e("%s: User memory fault\n", __func__);
|
||||
rc = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = kstrtoul(kbuf, 0, &ssr_trigger_val);
|
||||
if (rc) {
|
||||
d_vpr_e("returning error err %d\n", rc);
|
||||
rc = -EINVAL;
|
||||
} else {
|
||||
msm_vidc_trigger_ssr(core, ssr_trigger_val);
|
||||
rc = count;
|
||||
}
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct file_operations ssr_fops = {
|
||||
.open = simple_open,
|
||||
.write = trigger_ssr_write,
|
||||
};
|
||||
|
||||
static ssize_t trigger_stability_write(struct file *filp, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
unsigned long stability_trigger_val = 0;
|
||||
int rc = 0;
|
||||
struct msm_vidc_core *core = filp->private_data;
|
||||
size_t size = MAX_STABILITY_STRING_LEN;
|
||||
char kbuf[MAX_STABILITY_STRING_LEN + 1] = { 0 };
|
||||
|
||||
if (!core) {
|
||||
d_vpr_e("%s: invalid params %pK\n", __func__, core);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
return -EINVAL;
|
||||
|
||||
if (!count)
|
||||
goto exit;
|
||||
|
||||
if (count < size)
|
||||
size = count;
|
||||
|
||||
if (copy_from_user(kbuf, buf, size)) {
|
||||
d_vpr_e("%s: User memory fault\n", __func__);
|
||||
rc = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = kstrtoul(kbuf, 0, &stability_trigger_val);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: returning error err %d\n", __func__, rc);
|
||||
rc = -EINVAL;
|
||||
} else {
|
||||
msm_vidc_trigger_stability(core, stability_trigger_val);
|
||||
rc = count;
|
||||
}
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct file_operations stability_fops = {
|
||||
.open = simple_open,
|
||||
.write = trigger_stability_write,
|
||||
};
|
||||
|
||||
struct dentry *msm_vidc_debugfs_init_drv(void)
|
||||
{
|
||||
struct dentry *dir = NULL;
|
||||
|
||||
dir = debugfs_create_dir("msm_vidc", NULL);
|
||||
if (IS_ERR_OR_NULL(dir)) {
|
||||
dir = NULL;
|
||||
goto failed_create_dir;
|
||||
}
|
||||
|
||||
debugfs_create_u32("core_clock_voting", 0644, dir,
|
||||
&msm_vidc_clock_voting);
|
||||
debugfs_create_u32("ddr_bw_kbps", 0644, dir,
|
||||
&msm_vidc_ddr_bw);
|
||||
debugfs_create_u32("llc_bw_kbps", 0644, dir,
|
||||
&msm_vidc_llc_bw);
|
||||
debugfs_create_bool("disable_video_syscache", 0644, dir,
|
||||
&msm_vidc_syscache_disable);
|
||||
debugfs_create_bool("lossless_encoding", 0644, dir,
|
||||
&msm_vidc_lossless_encode);
|
||||
debugfs_create_u32("enable_bugon", 0644, dir,
|
||||
&msm_vidc_enable_bugon);
|
||||
|
||||
return dir;
|
||||
|
||||
failed_create_dir:
|
||||
if (dir)
|
||||
debugfs_remove_recursive(dir);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dentry *msm_vidc_debugfs_init_core(struct msm_vidc_core *core)
|
||||
{
|
||||
struct dentry *dir = NULL;
|
||||
char debugfs_name[MAX_DEBUGFS_NAME];
|
||||
struct dentry *parent;
|
||||
|
||||
if (!core->debugfs_parent) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
goto failed_create_dir;
|
||||
}
|
||||
parent = core->debugfs_parent;
|
||||
|
||||
snprintf(debugfs_name, MAX_DEBUGFS_NAME, "core");
|
||||
dir = debugfs_create_dir(debugfs_name, parent);
|
||||
if (IS_ERR_OR_NULL(dir)) {
|
||||
dir = NULL;
|
||||
d_vpr_e("Failed to create debugfs for msm_vidc\n");
|
||||
goto failed_create_dir;
|
||||
}
|
||||
if (!debugfs_create_file("info", 0444, dir, core, &core_info_fops)) {
|
||||
d_vpr_e("debugfs_create_file: fail\n");
|
||||
goto failed_create_dir;
|
||||
}
|
||||
if (!debugfs_create_file("trigger_ssr", 0200,
|
||||
dir, core, &ssr_fops)) {
|
||||
d_vpr_e("debugfs_create_file: fail\n");
|
||||
goto failed_create_dir;
|
||||
}
|
||||
if (!debugfs_create_file("trigger_stability", 0200, dir, core, &stability_fops)) {
|
||||
d_vpr_e("trigger_stability debugfs_create_file: fail\n");
|
||||
goto failed_create_dir;
|
||||
}
|
||||
if (!debugfs_create_file("stats_delay_ms", 0644, dir, core, &stats_delay_fops)) {
|
||||
d_vpr_e("debugfs_create_file: fail\n");
|
||||
goto failed_create_dir;
|
||||
}
|
||||
failed_create_dir:
|
||||
return dir;
|
||||
}
|
||||
|
||||
static int inst_info_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
d_vpr_l("Open inode ptr: %pK\n", inode->i_private);
|
||||
file->private_data = inode->i_private;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int publish_unreleased_reference(struct msm_vidc_inst *inst,
|
||||
char **dbuf, char *end)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t inst_info_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct core_inst_pair *idata = file->private_data;
|
||||
struct msm_vidc_core *core;
|
||||
struct msm_vidc_inst *inst;
|
||||
char *cur, *end, *dbuf = NULL;
|
||||
int i, j;
|
||||
ssize_t len = 0;
|
||||
struct v4l2_format *f;
|
||||
|
||||
if (!idata || !idata->core || !idata->inst) {
|
||||
d_vpr_e("%s: invalid params %pK\n", __func__, idata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
core = idata->core;
|
||||
inst = idata->inst;
|
||||
|
||||
inst = get_inst(core, inst->session_id);
|
||||
if (!inst) {
|
||||
d_vpr_h("%s: instance has become obsolete", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dbuf = vzalloc(MAX_DBG_BUF_SIZE);
|
||||
if (!dbuf) {
|
||||
i_vpr_e(inst, "%s: allocation failed\n", __func__);
|
||||
len = -ENOMEM;
|
||||
goto failed_alloc;
|
||||
}
|
||||
|
||||
cur = dbuf;
|
||||
end = cur + MAX_DBG_BUF_SIZE;
|
||||
|
||||
f = &inst->fmts[OUTPUT_PORT];
|
||||
cur += write_str(cur, end - cur, "==============================\n");
|
||||
cur += write_str(cur, end - cur, "INSTANCE: %pK (%s)\n", inst,
|
||||
is_encode_session(inst) ? "Encoder" : "Decoder");
|
||||
cur += write_str(cur, end - cur, "==============================\n");
|
||||
cur += write_str(cur, end - cur, "core: %pK\n", inst->core);
|
||||
cur += write_str(cur, end - cur, "height: %d\n", f->fmt.pix_mp.height);
|
||||
cur += write_str(cur, end - cur, "width: %d\n", f->fmt.pix_mp.width);
|
||||
cur += write_str(cur, end - cur, "fps: %d\n",
|
||||
inst->capabilities[FRAME_RATE].value >> 16);
|
||||
cur += write_str(cur, end - cur, "state: %d\n", inst->state);
|
||||
cur += write_str(cur, end - cur, "secure: %d\n",
|
||||
is_secure_session(inst));
|
||||
cur += write_str(cur, end - cur, "-----------Formats-------------\n");
|
||||
for (i = 0; i < MAX_PORT; i++) {
|
||||
if (i != INPUT_PORT && i != OUTPUT_PORT)
|
||||
continue;
|
||||
f = &inst->fmts[i];
|
||||
cur += write_str(cur, end - cur, "capability: %s\n",
|
||||
i == INPUT_PORT ? "Output" : "Capture");
|
||||
cur += write_str(cur, end - cur, "planes : %d\n",
|
||||
f->fmt.pix_mp.num_planes);
|
||||
cur += write_str(cur, end - cur,
|
||||
"type: %s\n", i == INPUT_PORT ?
|
||||
"Output" : "Capture");
|
||||
cur += write_str(cur, end - cur, "count: %u\n",
|
||||
inst->bufq[i].vb2q->num_buffers);
|
||||
|
||||
for (j = 0; j < f->fmt.pix_mp.num_planes; j++)
|
||||
cur += write_str(cur, end - cur,
|
||||
"size for plane %d: %u\n",
|
||||
j, f->fmt.pix_mp.plane_fmt[j].sizeimage);
|
||||
|
||||
cur += write_str(cur, end - cur, "\n");
|
||||
}
|
||||
cur += write_str(cur, end - cur, "-------------------------------\n");
|
||||
cur += write_str(cur, end - cur, "ETB Count: %d\n",
|
||||
inst->debug_count.etb);
|
||||
cur += write_str(cur, end - cur, "EBD Count: %d\n",
|
||||
inst->debug_count.ebd);
|
||||
cur += write_str(cur, end - cur, "FTB Count: %d\n",
|
||||
inst->debug_count.ftb);
|
||||
cur += write_str(cur, end - cur, "FBD Count: %d\n",
|
||||
inst->debug_count.fbd);
|
||||
|
||||
publish_unreleased_reference(inst, &cur, end);
|
||||
len = simple_read_from_buffer(buf, count, ppos,
|
||||
dbuf, cur - dbuf);
|
||||
|
||||
vfree(dbuf);
|
||||
failed_alloc:
|
||||
put_inst(inst);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int inst_info_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
d_vpr_l("Release inode ptr: %pK\n", inode->i_private);
|
||||
file->private_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations inst_info_fops = {
|
||||
.open = inst_info_open,
|
||||
.read = inst_info_read,
|
||||
.release = inst_info_release,
|
||||
};
|
||||
|
||||
struct dentry *msm_vidc_debugfs_init_inst(struct msm_vidc_inst *inst, struct dentry *parent)
|
||||
{
|
||||
struct dentry *dir = NULL, *info = NULL;
|
||||
char debugfs_name[MAX_DEBUGFS_NAME];
|
||||
struct core_inst_pair *idata = NULL;
|
||||
|
||||
snprintf(debugfs_name, MAX_DEBUGFS_NAME, "inst_%d", inst->session_id);
|
||||
|
||||
idata = vzalloc(sizeof(*idata));
|
||||
if (!idata) {
|
||||
i_vpr_e(inst, "%s: allocation failed\n", __func__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
idata->core = inst->core;
|
||||
idata->inst = inst;
|
||||
|
||||
dir = debugfs_create_dir(debugfs_name, parent);
|
||||
if (IS_ERR_OR_NULL(dir)) {
|
||||
dir = NULL;
|
||||
i_vpr_e(inst,
|
||||
"%s: Failed to create debugfs for msm_vidc\n",
|
||||
__func__);
|
||||
goto failed_create_dir;
|
||||
}
|
||||
|
||||
info = debugfs_create_file("info", 0444, dir,
|
||||
idata, &inst_info_fops);
|
||||
if (IS_ERR_OR_NULL(info)) {
|
||||
i_vpr_e(inst, "%s: debugfs_create_file: fail\n",
|
||||
__func__);
|
||||
goto failed_create_file;
|
||||
}
|
||||
|
||||
dir->d_inode->i_private = info->d_inode->i_private;
|
||||
inst->debug.pdata[FRAME_PROCESSING].sampling = true;
|
||||
return dir;
|
||||
|
||||
failed_create_file:
|
||||
debugfs_remove_recursive(dir);
|
||||
dir = NULL;
|
||||
failed_create_dir:
|
||||
vfree(idata);
|
||||
exit:
|
||||
return dir;
|
||||
}
|
||||
|
||||
void msm_vidc_debugfs_deinit_inst(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct dentry *dentry = NULL;
|
||||
|
||||
if (!inst->debugfs_root)
|
||||
return;
|
||||
|
||||
dentry = inst->debugfs_root;
|
||||
if (dentry->d_inode) {
|
||||
i_vpr_l(inst, "%s: Destroy %pK\n",
|
||||
__func__, dentry->d_inode->i_private);
|
||||
vfree(dentry->d_inode->i_private);
|
||||
dentry->d_inode->i_private = NULL;
|
||||
}
|
||||
debugfs_remove_recursive(dentry);
|
||||
inst->debugfs_root = NULL;
|
||||
}
|
||||
|
||||
void msm_vidc_debugfs_update(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_debugfs_event e)
|
||||
{
|
||||
struct msm_vidc_debug *d;
|
||||
char a[64] = "Frame processing";
|
||||
|
||||
d = &inst->debug;
|
||||
|
||||
switch (e) {
|
||||
case MSM_VIDC_DEBUGFS_EVENT_ETB:
|
||||
inst->debug_count.etb++;
|
||||
if (inst->debug_count.ebd &&
|
||||
inst->debug_count.ftb > inst->debug_count.fbd) {
|
||||
d->pdata[FRAME_PROCESSING].name[0] = '\0';
|
||||
tic(inst, FRAME_PROCESSING, a);
|
||||
}
|
||||
break;
|
||||
case MSM_VIDC_DEBUGFS_EVENT_EBD:
|
||||
inst->debug_count.ebd++;
|
||||
/*
|
||||
* Host needs to ensure FW atleast have 2 buffers available always
|
||||
* one for HW processing and another for fw processing in parallel
|
||||
* to avoid FW starving for buffers
|
||||
*/
|
||||
if (inst->debug_count.etb < (inst->debug_count.ebd + 2)) {
|
||||
toc(inst, FRAME_PROCESSING);
|
||||
i_vpr_p(inst,
|
||||
"EBD: FW needs input buffers. Processed etb %llu ebd %llu ftb %llu fbd %llu\n",
|
||||
inst->debug_count.etb, inst->debug_count.ebd,
|
||||
inst->debug_count.ftb, inst->debug_count.fbd);
|
||||
}
|
||||
if (inst->debug_count.fbd &&
|
||||
inst->debug_count.ftb < (inst->debug_count.fbd + 2))
|
||||
i_vpr_p(inst,
|
||||
"EBD: FW needs output buffers. Processed etb %llu ebd %llu ftb %llu fbd %llu\n",
|
||||
inst->debug_count.etb, inst->debug_count.ebd,
|
||||
inst->debug_count.ftb, inst->debug_count.fbd);
|
||||
break;
|
||||
case MSM_VIDC_DEBUGFS_EVENT_FTB:
|
||||
inst->debug_count.ftb++;
|
||||
if (inst->debug_count.ebd &&
|
||||
inst->debug_count.etb > inst->debug_count.ebd) {
|
||||
d->pdata[FRAME_PROCESSING].name[0] = '\0';
|
||||
tic(inst, FRAME_PROCESSING, a);
|
||||
}
|
||||
break;
|
||||
case MSM_VIDC_DEBUGFS_EVENT_FBD:
|
||||
inst->debug_count.fbd++;
|
||||
inst->debug.samples++;
|
||||
/*
|
||||
* Host needs to ensure FW atleast have 2 buffers available always
|
||||
* one for HW processing and another for fw processing in parallel
|
||||
* to avoid FW starving for buffers
|
||||
*/
|
||||
if (inst->debug_count.ftb < (inst->debug_count.fbd + 2)) {
|
||||
toc(inst, FRAME_PROCESSING);
|
||||
i_vpr_p(inst,
|
||||
"FBD: FW needs output buffers. Processed etb %llu ebd %llu ftb %llu fbd %llu\n",
|
||||
inst->debug_count.etb, inst->debug_count.ebd,
|
||||
inst->debug_count.ftb, inst->debug_count.fbd);
|
||||
}
|
||||
if (inst->debug_count.ebd &&
|
||||
inst->debug_count.etb < (inst->debug_count.ebd + 2))
|
||||
i_vpr_p(inst,
|
||||
"FBD: FW needs input buffers. Processed etb %llu ebd %llu ftb %llu fbd %llu\n",
|
||||
inst->debug_count.etb, inst->debug_count.ebd,
|
||||
inst->debug_count.ftb, inst->debug_count.fbd);
|
||||
break;
|
||||
default:
|
||||
i_vpr_e(inst, "invalid event in debugfs: %d\n", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int msm_vidc_check_ratelimit(void)
|
||||
{
|
||||
static DEFINE_RATELIMIT_STATE(_rs,
|
||||
VIDC_DBG_SESSION_RATELIMIT_INTERVAL,
|
||||
VIDC_DBG_SESSION_RATELIMIT_BURST);
|
||||
return __ratelimit(&_rs);
|
||||
}
|
5487
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_driver.c
Normal file
5487
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_driver.c
Normal file
File diff suppressed because it is too large
Load Diff
205
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_fence.c
Normal file
205
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_fence.c
Normal file
@ -0,0 +1,205 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "msm_vidc_fence.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
|
||||
static const char *msm_vidc_dma_fence_get_driver_name(struct dma_fence *df)
|
||||
{
|
||||
struct msm_vidc_fence *fence;
|
||||
|
||||
if (df) {
|
||||
fence = container_of(df, struct msm_vidc_fence, dma_fence);
|
||||
return fence->name;
|
||||
}
|
||||
return "msm_vidc_dma_fence_get_driver_name: invalid fence";
|
||||
}
|
||||
|
||||
static const char *msm_vidc_dma_fence_get_timeline_name(struct dma_fence *df)
|
||||
{
|
||||
struct msm_vidc_fence *fence;
|
||||
|
||||
if (df) {
|
||||
fence = container_of(df, struct msm_vidc_fence, dma_fence);
|
||||
return fence->name;
|
||||
}
|
||||
return "msm_vidc_dma_fence_get_timeline_name: invalid fence";
|
||||
}
|
||||
|
||||
static void msm_vidc_dma_fence_release(struct dma_fence *df)
|
||||
{
|
||||
struct msm_vidc_fence *fence;
|
||||
|
||||
if (df) {
|
||||
fence = container_of(df, struct msm_vidc_fence, dma_fence);
|
||||
d_vpr_l("%s: name %s\n", __func__, fence->name);
|
||||
vfree(fence);
|
||||
} else {
|
||||
d_vpr_e("%s: invalid fence\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct dma_fence_ops msm_vidc_dma_fence_ops = {
|
||||
.get_driver_name = msm_vidc_dma_fence_get_driver_name,
|
||||
.get_timeline_name = msm_vidc_dma_fence_get_timeline_name,
|
||||
.release = msm_vidc_dma_fence_release,
|
||||
};
|
||||
|
||||
struct msm_vidc_fence *msm_vidc_fence_create(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_fence *fence = NULL;
|
||||
|
||||
fence = vzalloc(sizeof(*fence));
|
||||
if (!fence) {
|
||||
i_vpr_e(inst, "%s: allocation failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fence->fd = INVALID_FD;
|
||||
spin_lock_init(&fence->lock);
|
||||
dma_fence_init(&fence->dma_fence, &msm_vidc_dma_fence_ops,
|
||||
&fence->lock, inst->fence_context.ctx_num,
|
||||
++inst->fence_context.seq_num);
|
||||
snprintf(fence->name, sizeof(fence->name), "%s: %llu",
|
||||
inst->fence_context.name, inst->fence_context.seq_num);
|
||||
|
||||
/* reset seqno to avoid going beyond INT_MAX */
|
||||
if (inst->fence_context.seq_num >= INT_MAX)
|
||||
inst->fence_context.seq_num = 0;
|
||||
|
||||
fence->fence_id = fence->dma_fence.seqno;
|
||||
|
||||
INIT_LIST_HEAD(&fence->list);
|
||||
list_add_tail(&fence->list, &inst->fence_list);
|
||||
i_vpr_l(inst, "%s: created %s\n", __func__, fence->name);
|
||||
|
||||
return fence;
|
||||
}
|
||||
|
||||
int msm_vidc_dma_fence_create_fd(struct msm_vidc_inst *inst,
|
||||
struct msm_vidc_fence *fence)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
fence->fd = get_unused_fd_flags(0);
|
||||
if (fence->fd < 0) {
|
||||
i_vpr_e(inst, "%s: getting fd (%d) failed\n", __func__,
|
||||
fence->fd);
|
||||
rc = -EINVAL;
|
||||
goto err_fd;
|
||||
}
|
||||
fence->sync_file = sync_file_create(&fence->dma_fence);
|
||||
if (!fence->sync_file) {
|
||||
i_vpr_e(inst, "%s: sync_file_create failed\n", __func__);
|
||||
rc = -EINVAL;
|
||||
goto err_sync_file;
|
||||
}
|
||||
fd_install(fence->fd, fence->sync_file->file);
|
||||
|
||||
i_vpr_l(inst, "%s: created fd %d for fence %s\n", __func__,
|
||||
fence->fd, fence->name);
|
||||
|
||||
return 0;
|
||||
|
||||
err_sync_file:
|
||||
put_unused_fd(fence->fd);
|
||||
err_fd:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct msm_vidc_fence *msm_vidc_get_dma_fence_from_id(
|
||||
struct msm_vidc_inst *inst, u64 fence_id)
|
||||
{
|
||||
struct msm_vidc_fence *fence, *dummy_fence;
|
||||
bool found = false;
|
||||
|
||||
list_for_each_entry_safe(fence, dummy_fence, &inst->fence_list, list) {
|
||||
if (fence->fence_id == fence_id) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
i_vpr_l(inst, "%s: no fence available for id: %u\n",
|
||||
__func__, fence_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return fence;
|
||||
}
|
||||
|
||||
static int msm_vidc_fence_signal(struct msm_vidc_inst *inst, u64 fence_id)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_vidc_fence *fence;
|
||||
|
||||
fence = msm_vidc_get_dma_fence_from_id(inst, fence_id);
|
||||
if (!fence) {
|
||||
i_vpr_e(inst, "%s: no fence available to signal with id: %u\n",
|
||||
__func__, fence_id);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
i_vpr_l(inst, "%s: fence %s\n", __func__, fence->name);
|
||||
list_del_init(&fence->list);
|
||||
|
||||
dma_fence_signal(&fence->dma_fence);
|
||||
dma_fence_put(&fence->dma_fence);
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static void msm_vidc_fence_destroy(struct msm_vidc_inst *inst, u64 fence_id)
|
||||
{
|
||||
struct msm_vidc_fence *fence;
|
||||
|
||||
fence = msm_vidc_get_dma_fence_from_id(inst, fence_id);
|
||||
if (!fence)
|
||||
return;
|
||||
|
||||
i_vpr_l(inst, "%s: fence %s\n", __func__, fence->name);
|
||||
list_del_init(&fence->list);
|
||||
dma_fence_set_error(&fence->dma_fence, -EINVAL);
|
||||
dma_fence_signal(&fence->dma_fence);
|
||||
dma_fence_put(&fence->dma_fence);
|
||||
}
|
||||
|
||||
int msm_vidc_fence_init(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
inst->fence_context.ctx_num = dma_fence_context_alloc(1);
|
||||
snprintf(inst->fence_context.name, sizeof(inst->fence_context.name),
|
||||
"msm_vidc_fence: %s: %llu", inst->debug_str,
|
||||
inst->fence_context.ctx_num);
|
||||
i_vpr_h(inst, "%s: %s\n", __func__, inst->fence_context.name);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void msm_vidc_fence_deinit(struct msm_vidc_inst *inst)
|
||||
{
|
||||
i_vpr_h(inst, "%s: %s\n", __func__, inst->fence_context.name);
|
||||
inst->fence_context.ctx_num = 0;
|
||||
snprintf(inst->fence_context.name, sizeof(inst->fence_context.name),
|
||||
"%s", "");
|
||||
}
|
||||
|
||||
static const struct msm_vidc_fence_ops msm_dma_fence_ops = {
|
||||
.fence_create = msm_vidc_fence_create,
|
||||
.fence_destroy = msm_vidc_fence_destroy,
|
||||
.fence_signal = msm_vidc_fence_signal,
|
||||
.fence_create_fd = msm_vidc_dma_fence_create_fd,
|
||||
};
|
||||
|
||||
const struct msm_vidc_fence_ops *get_dma_fence_ops(void)
|
||||
{
|
||||
return &msm_dma_fence_ops;
|
||||
}
|
616
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_memory.c
Normal file
616
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_memory.c
Normal file
@ -0,0 +1,616 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/dma-heap.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include "msm_vidc_memory.h"
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_events.h"
|
||||
#include "msm_vidc_platform.h"
|
||||
#include "venus_hfi.h"
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0))
|
||||
MODULE_IMPORT_NS(DMA_BUF);
|
||||
#endif
|
||||
|
||||
struct msm_vidc_type_size_name {
|
||||
enum msm_memory_pool_type type;
|
||||
u32 size;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const struct msm_vidc_type_size_name buftype_size_name_arr[] = {
|
||||
{MSM_MEM_POOL_BUFFER, sizeof(struct msm_vidc_buffer), "MSM_MEM_POOL_BUFFER" },
|
||||
{MSM_MEM_POOL_ALLOC_MAP, sizeof(struct msm_vidc_mem), "MSM_MEM_POOL_ALLOC_MAP" },
|
||||
{MSM_MEM_POOL_TIMESTAMP, sizeof(struct msm_vidc_timestamp), "MSM_MEM_POOL_TIMESTAMP" },
|
||||
{MSM_MEM_POOL_DMABUF, sizeof(struct msm_memory_dmabuf), "MSM_MEM_POOL_DMABUF" },
|
||||
{MSM_MEM_POOL_PACKET, sizeof(struct hfi_pending_packet) + MSM_MEM_POOL_PACKET_SIZE,
|
||||
"MSM_MEM_POOL_PACKET"},
|
||||
{MSM_MEM_POOL_BUF_TIMER, sizeof(struct msm_vidc_input_timer), "MSM_MEM_POOL_BUF_TIMER" },
|
||||
{MSM_MEM_POOL_BUF_STATS, sizeof(struct msm_vidc_buffer_stats), "MSM_MEM_POOL_BUF_STATS"},
|
||||
};
|
||||
|
||||
void *msm_vidc_pool_alloc(struct msm_vidc_inst *inst, enum msm_memory_pool_type type)
|
||||
{
|
||||
struct msm_memory_alloc_header *hdr = NULL;
|
||||
struct msm_memory_pool *pool;
|
||||
|
||||
if (type < 0 || type >= MSM_MEM_POOL_MAX) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
pool = &inst->pool[type];
|
||||
|
||||
if (!list_empty(&pool->free_pool)) {
|
||||
/* get 1st node from free pool */
|
||||
hdr = list_first_entry(&pool->free_pool,
|
||||
struct msm_memory_alloc_header, list);
|
||||
|
||||
/* move node from free pool to busy pool */
|
||||
list_move_tail(&hdr->list, &pool->busy_pool);
|
||||
|
||||
/* reset existing data */
|
||||
memset((char *)hdr->buf, 0, pool->size);
|
||||
|
||||
/* set busy flag to true. This is to catch double free request */
|
||||
hdr->busy = true;
|
||||
|
||||
return hdr->buf;
|
||||
}
|
||||
|
||||
hdr = vzalloc(pool->size + sizeof(struct msm_memory_alloc_header));
|
||||
if (!hdr) {
|
||||
i_vpr_e(inst, "%s: allocation failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&hdr->list);
|
||||
hdr->type = type;
|
||||
hdr->busy = true;
|
||||
hdr->buf = (void *)(hdr + 1);
|
||||
list_add_tail(&hdr->list, &pool->busy_pool);
|
||||
|
||||
return hdr->buf;
|
||||
}
|
||||
|
||||
void msm_vidc_pool_free(struct msm_vidc_inst *inst, void *vidc_buf)
|
||||
{
|
||||
struct msm_memory_alloc_header *hdr;
|
||||
struct msm_memory_pool *pool;
|
||||
|
||||
if (!vidc_buf) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return;
|
||||
}
|
||||
hdr = (struct msm_memory_alloc_header *)vidc_buf - 1;
|
||||
|
||||
/* sanitize buffer addr */
|
||||
if (hdr->buf != vidc_buf) {
|
||||
i_vpr_e(inst, "%s: invalid buf addr %p\n", __func__, vidc_buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* sanitize pool type */
|
||||
if (hdr->type < 0 || hdr->type >= MSM_MEM_POOL_MAX) {
|
||||
i_vpr_e(inst, "%s: invalid pool type %#x\n", __func__, hdr->type);
|
||||
return;
|
||||
}
|
||||
pool = &inst->pool[hdr->type];
|
||||
|
||||
/* catch double-free request */
|
||||
if (!hdr->busy) {
|
||||
i_vpr_e(inst, "%s: double free request. type %s, addr %p\n", __func__,
|
||||
pool->name, vidc_buf);
|
||||
return;
|
||||
}
|
||||
hdr->busy = false;
|
||||
|
||||
/* move node from busy pool to free pool */
|
||||
list_move_tail(&hdr->list, &pool->free_pool);
|
||||
}
|
||||
|
||||
static void msm_vidc_destroy_pool_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_memory_pool_type type)
|
||||
{
|
||||
struct msm_memory_alloc_header *hdr, *dummy;
|
||||
struct msm_memory_pool *pool;
|
||||
u32 fcount = 0, bcount = 0;
|
||||
|
||||
if (type < 0 || type >= MSM_MEM_POOL_MAX) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return;
|
||||
}
|
||||
pool = &inst->pool[type];
|
||||
|
||||
/* detect memleak: busy pool is expected to be empty here */
|
||||
if (!list_empty(&pool->busy_pool))
|
||||
i_vpr_e(inst, "%s: destroy request on active buffer. type %s\n",
|
||||
__func__, pool->name);
|
||||
|
||||
/* destroy all free buffers */
|
||||
list_for_each_entry_safe(hdr, dummy, &pool->free_pool, list) {
|
||||
list_del(&hdr->list);
|
||||
vfree(hdr);
|
||||
fcount++;
|
||||
}
|
||||
|
||||
/* destroy all busy buffers */
|
||||
list_for_each_entry_safe(hdr, dummy, &pool->busy_pool, list) {
|
||||
list_del(&hdr->list);
|
||||
vfree(hdr);
|
||||
bcount++;
|
||||
}
|
||||
|
||||
i_vpr_h(inst, "%s: type: %23s, count: free %2u, busy %2u\n",
|
||||
__func__, pool->name, fcount, bcount);
|
||||
}
|
||||
|
||||
int msm_vidc_pools_init(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
if (ARRAY_SIZE(buftype_size_name_arr) != MSM_MEM_POOL_MAX) {
|
||||
i_vpr_e(inst, "%s: num elements mismatch %lu %u\n", __func__,
|
||||
ARRAY_SIZE(buftype_size_name_arr), MSM_MEM_POOL_MAX);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < MSM_MEM_POOL_MAX; i++) {
|
||||
if (i != buftype_size_name_arr[i].type) {
|
||||
i_vpr_e(inst, "%s: type mismatch %u %u\n", __func__,
|
||||
i, buftype_size_name_arr[i].type);
|
||||
return -EINVAL;
|
||||
}
|
||||
inst->pool[i].size = buftype_size_name_arr[i].size;
|
||||
inst->pool[i].name = buftype_size_name_arr[i].name;
|
||||
INIT_LIST_HEAD(&inst->pool[i].free_pool);
|
||||
INIT_LIST_HEAD(&inst->pool[i].busy_pool);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void msm_vidc_pools_deinit(struct msm_vidc_inst *inst)
|
||||
{
|
||||
u32 i = 0;
|
||||
|
||||
/* destroy all buffers from all pool types */
|
||||
for (i = 0; i < MSM_MEM_POOL_MAX; i++)
|
||||
msm_vidc_destroy_pool_buffers(inst, i);
|
||||
}
|
||||
|
||||
static struct dma_buf *msm_vidc_dma_buf_get(struct msm_vidc_inst *inst, int fd)
|
||||
{
|
||||
struct msm_memory_dmabuf *buf = NULL;
|
||||
struct dma_buf *dmabuf = NULL;
|
||||
bool found = false;
|
||||
|
||||
/* get local dmabuf ref for tracking */
|
||||
dmabuf = dma_buf_get(fd);
|
||||
if (IS_ERR_OR_NULL(dmabuf)) {
|
||||
d_vpr_e("Failed to get dmabuf for %d, error %ld\n",
|
||||
fd, PTR_ERR(dmabuf));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* track dmabuf - inc refcount if already present */
|
||||
list_for_each_entry(buf, &inst->dmabuf_tracker, list) {
|
||||
if (buf->dmabuf == dmabuf) {
|
||||
buf->refcount++;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
/* put local dmabuf ref */
|
||||
dma_buf_put(dmabuf);
|
||||
return dmabuf;
|
||||
}
|
||||
|
||||
/* get tracker instance from pool */
|
||||
buf = msm_vidc_pool_alloc(inst, MSM_MEM_POOL_DMABUF);
|
||||
if (!buf) {
|
||||
i_vpr_e(inst, "%s: dmabuf alloc failed\n", __func__);
|
||||
dma_buf_put(dmabuf);
|
||||
return NULL;
|
||||
}
|
||||
/* hold dmabuf strong ref in tracker */
|
||||
buf->dmabuf = dmabuf;
|
||||
buf->refcount = 1;
|
||||
INIT_LIST_HEAD(&buf->list);
|
||||
|
||||
/* add new dmabuf entry to tracker */
|
||||
list_add_tail(&buf->list, &inst->dmabuf_tracker);
|
||||
|
||||
return dmabuf;
|
||||
}
|
||||
|
||||
static void msm_vidc_dma_buf_put(struct msm_vidc_inst *inst, struct dma_buf *dmabuf)
|
||||
{
|
||||
struct msm_memory_dmabuf *buf = NULL;
|
||||
bool found = false;
|
||||
|
||||
if (!dmabuf) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* track dmabuf - dec refcount if already present */
|
||||
list_for_each_entry(buf, &inst->dmabuf_tracker, list) {
|
||||
if (buf->dmabuf == dmabuf) {
|
||||
buf->refcount--;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
i_vpr_e(inst, "%s: invalid dmabuf %p\n", __func__, dmabuf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* non-zero refcount - do nothing */
|
||||
if (buf->refcount)
|
||||
return;
|
||||
|
||||
/* remove dmabuf entry from tracker */
|
||||
list_del(&buf->list);
|
||||
|
||||
/* release dmabuf strong ref from tracker */
|
||||
dma_buf_put(buf->dmabuf);
|
||||
|
||||
/* put tracker instance back to pool */
|
||||
msm_vidc_pool_free(inst, buf);
|
||||
}
|
||||
|
||||
static void msm_vidc_dma_buf_put_completely(struct msm_vidc_inst *inst,
|
||||
struct msm_memory_dmabuf *buf)
|
||||
{
|
||||
if (!buf) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
while (buf->refcount) {
|
||||
buf->refcount--;
|
||||
if (!buf->refcount) {
|
||||
/* remove dmabuf entry from tracker */
|
||||
list_del(&buf->list);
|
||||
|
||||
/* release dmabuf strong ref from tracker */
|
||||
dma_buf_put(buf->dmabuf);
|
||||
|
||||
/* put tracker instance back to pool */
|
||||
msm_vidc_pool_free(inst, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct dma_buf_attachment *msm_vidc_dma_buf_attach(struct msm_vidc_core *core,
|
||||
struct dma_buf *dbuf, struct device *dev)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dma_buf_attachment *attach = NULL;
|
||||
|
||||
if (!dbuf || !dev) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
attach = dma_buf_attach(dbuf, dev);
|
||||
if (IS_ERR_OR_NULL(attach)) {
|
||||
rc = PTR_ERR(attach) ? PTR_ERR(attach) : -1;
|
||||
d_vpr_e("Failed to attach dmabuf, error %d\n", rc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return attach;
|
||||
}
|
||||
|
||||
static int msm_vidc_dma_buf_detach(struct msm_vidc_core *core,
|
||||
struct dma_buf *dbuf, struct dma_buf_attachment *attach)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!dbuf || !attach) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dma_buf_detach(dbuf, attach);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_vidc_dma_buf_unmap_attachment(struct msm_vidc_core *core,
|
||||
struct dma_buf_attachment *attach, struct sg_table *table)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!attach || !table) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dma_buf_unmap_attachment(attach, table, DMA_BIDIRECTIONAL);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct sg_table *msm_vidc_dma_buf_map_attachment(
|
||||
struct msm_vidc_core *core, struct dma_buf_attachment *attach)
|
||||
{
|
||||
int rc = 0;
|
||||
struct sg_table *table = NULL;
|
||||
|
||||
if (!attach) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
table = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
|
||||
if (IS_ERR_OR_NULL(table)) {
|
||||
rc = PTR_ERR(table) ? PTR_ERR(table) : -1;
|
||||
d_vpr_e("Failed to map table, error %d\n", rc);
|
||||
return NULL;
|
||||
}
|
||||
if (!table->sgl) {
|
||||
d_vpr_e("%s: sgl is NULL\n", __func__);
|
||||
msm_vidc_dma_buf_unmap_attachment(core, attach, table);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
static int msm_vidc_memory_alloc_map(struct msm_vidc_core *core, struct msm_vidc_mem *mem)
|
||||
{
|
||||
int size = 0;
|
||||
struct context_bank_info *cb = NULL;
|
||||
|
||||
if (!mem) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
size = ALIGN(mem->size, SZ_4K);
|
||||
mem->attrs = DMA_ATTR_WRITE_COMBINE;
|
||||
|
||||
cb = msm_vidc_get_context_bank_for_region(core, mem->region);
|
||||
if (!cb) {
|
||||
d_vpr_e("%s: failed to get context bank device\n", __func__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mem->kvaddr = dma_alloc_attrs(cb->dev, size, &mem->device_addr, GFP_KERNEL,
|
||||
mem->attrs);
|
||||
if (!mem->kvaddr) {
|
||||
d_vpr_e("%s: dma_alloc_attrs returned NULL\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
d_vpr_h(
|
||||
"%s: dmabuf %pK, size %d, buffer_type %s, secure %d, region %d\n",
|
||||
__func__, mem->kvaddr, mem->size, buf_name(mem->type),
|
||||
mem->secure, mem->region);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_vidc_memory_unmap_free(struct msm_vidc_core *core, struct msm_vidc_mem *mem)
|
||||
{
|
||||
int rc = 0;
|
||||
struct context_bank_info *cb = NULL;
|
||||
|
||||
if (!mem || !mem->device_addr || !mem->kvaddr) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
d_vpr_h(
|
||||
"%s: dmabuf %pK, size %d, kvaddr %pK, buffer_type %s, secure %d, region %d\n",
|
||||
__func__, mem->device_addr, mem->size, mem->kvaddr,
|
||||
buf_name(mem->type), mem->secure, mem->region);
|
||||
|
||||
cb = msm_vidc_get_context_bank_for_region(core, mem->region);
|
||||
if (!cb) {
|
||||
d_vpr_e("%s: failed to get context bank device\n", __func__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
dma_free_attrs(cb->dev, mem->size, mem->kvaddr, mem->device_addr,
|
||||
mem->attrs);
|
||||
|
||||
mem->kvaddr = NULL;
|
||||
mem->device_addr = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_vidc_dma_map_page(struct msm_vidc_core *core,
|
||||
struct msm_vidc_mem *mem)
|
||||
{
|
||||
int rc = 0;
|
||||
struct context_bank_info *cb = NULL;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
if (!mem) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mem->refcount) {
|
||||
mem->refcount++;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
cb = msm_vidc_get_context_bank_for_region(core, mem->region);
|
||||
if (!cb) {
|
||||
d_vpr_e("%s: Failed to get context bank device\n",
|
||||
__func__);
|
||||
rc = -EIO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* map and obtain dma address for physically contiguous memory */
|
||||
dma_addr = dma_map_page(cb->dev, phys_to_page(mem->phys_addr),
|
||||
0, (size_t)mem->size, mem->direction);
|
||||
|
||||
rc = dma_mapping_error(cb->dev, dma_addr);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: Failed to map memory\n", __func__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
mem->device_addr = dma_addr;
|
||||
mem->refcount++;
|
||||
|
||||
exit:
|
||||
d_vpr_l(
|
||||
"%s: type %11s, device_addr %#llx, size %u region %d, refcount %d\n",
|
||||
__func__, buf_name(mem->type), mem->device_addr,
|
||||
mem->size, mem->region, mem->refcount);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_vidc_dma_unmap_page(struct msm_vidc_core *core,
|
||||
struct msm_vidc_mem *mem)
|
||||
{
|
||||
int rc = 0;
|
||||
struct context_bank_info *cb = NULL;
|
||||
|
||||
if (!mem) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mem->refcount) {
|
||||
mem->refcount--;
|
||||
} else {
|
||||
d_vpr_e("unmap called while refcount is zero already\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cb = msm_vidc_get_context_bank_for_region(core, mem->region);
|
||||
if (!cb) {
|
||||
d_vpr_e("%s: Failed to get context bank device\n",
|
||||
__func__);
|
||||
rc = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
d_vpr_l(
|
||||
"%s: type %11s, device_addr %#x, refcount %d, region %d\n",
|
||||
__func__, buf_name(mem->type), mem->device_addr,
|
||||
mem->refcount, mem->region);
|
||||
|
||||
if (mem->refcount)
|
||||
goto exit;
|
||||
|
||||
dma_unmap_page(cb->dev, (dma_addr_t)(mem->device_addr),
|
||||
mem->size, mem->direction);
|
||||
|
||||
mem->device_addr = 0x0;
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_buffer_region(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
return MSM_VIDC_NON_SECURE;
|
||||
}
|
||||
|
||||
static int msm_vidc_iommu_map(struct msm_vidc_core *core, struct msm_vidc_mem *mem)
|
||||
{
|
||||
int rc = 0;
|
||||
struct context_bank_info *cb = NULL;
|
||||
|
||||
if (!mem) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cb = msm_vidc_get_context_bank_for_region(core, mem->region);
|
||||
if (!cb) {
|
||||
d_vpr_e("%s: failed to get context bank device for region: %d\n",
|
||||
__func__, mem->region);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = iommu_map(cb->domain, mem->device_addr, mem->phys_addr,
|
||||
mem->size, IOMMU_READ | IOMMU_WRITE | IOMMU_MMIO);
|
||||
if (rc) {
|
||||
d_vpr_e("iommu_map failed for device_addr 0x%x, size %d, rc:%d\n",
|
||||
mem->device_addr, mem->size, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
d_vpr_h("%s: phys_addr %#x size %#x device_addr %#x, mem_region %d\n",
|
||||
__func__, mem->phys_addr, mem->size, mem->device_addr, mem->region);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_vidc_iommu_unmap(struct msm_vidc_core *core, struct msm_vidc_mem *mem)
|
||||
{
|
||||
int rc = 0;
|
||||
struct context_bank_info *cb = NULL;
|
||||
|
||||
if (!mem) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cb = msm_vidc_get_context_bank_for_region(core, mem->region);
|
||||
if (!cb) {
|
||||
d_vpr_e("%s: failed to get context bank device for region: %d\n",
|
||||
__func__, mem->region);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
d_vpr_h("%s: phys_addr %#x size %#x device_addr %#x, mem_region %d\n",
|
||||
__func__, mem->phys_addr, mem->size, mem->device_addr, mem->region);
|
||||
|
||||
iommu_unmap(cb->domain, mem->device_addr, mem->size);
|
||||
mem->device_addr = 0x0;
|
||||
mem->phys_addr = 0x0;
|
||||
mem->size = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct msm_vidc_memory_ops msm_mem_ops = {
|
||||
.dma_buf_get = msm_vidc_dma_buf_get,
|
||||
.dma_buf_put = msm_vidc_dma_buf_put,
|
||||
.dma_buf_put_completely = msm_vidc_dma_buf_put_completely,
|
||||
.dma_buf_attach = msm_vidc_dma_buf_attach,
|
||||
.dma_buf_detach = msm_vidc_dma_buf_detach,
|
||||
.dma_buf_map_attachment = msm_vidc_dma_buf_map_attachment,
|
||||
.dma_buf_unmap_attachment = msm_vidc_dma_buf_unmap_attachment,
|
||||
.memory_alloc_map = msm_vidc_memory_alloc_map,
|
||||
.memory_unmap_free = msm_vidc_memory_unmap_free,
|
||||
.mem_dma_map_page = msm_vidc_dma_map_page,
|
||||
.mem_dma_unmap_page = msm_vidc_dma_unmap_page,
|
||||
.buffer_region = msm_vidc_buffer_region,
|
||||
.iommu_map = msm_vidc_iommu_map,
|
||||
.iommu_unmap = msm_vidc_iommu_unmap,
|
||||
};
|
||||
|
||||
const struct msm_vidc_memory_ops *get_mem_ops(void)
|
||||
{
|
||||
return &msm_mem_ops;
|
||||
}
|
@ -0,0 +1,472 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/dma-heap.h>
|
||||
#include <linux/qcom-dma-mapping.h>
|
||||
#include <linux/mem-buf.h>
|
||||
#include <soc/qcom/secure_buffer.h>
|
||||
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
#include "msm_vidc_events.h"
|
||||
#include "msm_vidc_platform.h"
|
||||
#include "msm_vidc_memory.h"
|
||||
|
||||
static bool is_non_secure_buffer(struct dma_buf *dmabuf)
|
||||
{
|
||||
return mem_buf_dma_buf_exclusive_owner(dmabuf);
|
||||
}
|
||||
|
||||
static struct dma_buf_attachment *msm_vidc_dma_buf_attach_ext(struct msm_vidc_core *core,
|
||||
struct dma_buf *dbuf, struct device *dev)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dma_buf_attachment *attach = NULL;
|
||||
struct context_bank_info *cb = NULL;
|
||||
|
||||
if (!dbuf || !dev) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cb = msm_vidc_get_context_bank_for_device(core, dev);
|
||||
if (!cb) {
|
||||
d_vpr_e("%s: Failed to get context bank device for %s\n",
|
||||
__func__, dev_name(dev));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* reject non-secure mapping request for a secure buffer(or vice versa) */
|
||||
if (cb->region == MSM_VIDC_NON_SECURE || cb->region == MSM_VIDC_NON_SECURE_PIXEL) {
|
||||
if (!is_non_secure_buffer(dbuf)) {
|
||||
d_vpr_e("%s: secure buffer mapping to non-secure region %d not allowed\n",
|
||||
__func__, cb->region);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (is_non_secure_buffer(dbuf)) {
|
||||
d_vpr_e("%s: non-secure buffer mapping to secure region %d not allowed\n",
|
||||
__func__, cb->region);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
attach = dma_buf_attach(dbuf, dev);
|
||||
if (IS_ERR_OR_NULL(attach)) {
|
||||
rc = PTR_ERR(attach) ? PTR_ERR(attach) : -1;
|
||||
d_vpr_e("Failed to attach dmabuf, error %d\n", rc);
|
||||
return NULL;;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do not need dma_map function to perform cache operations
|
||||
* on the whole buffer size and hence pass skip sync flag.
|
||||
*/
|
||||
attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC;
|
||||
/*
|
||||
* Get the scatterlist for the given attachment
|
||||
* Mapping of sg is taken care by map attachment
|
||||
*/
|
||||
attach->dma_map_attrs |= DMA_ATTR_DELAYED_UNMAP;
|
||||
if (is_sys_cache_present(core))
|
||||
attach->dma_map_attrs |= DMA_ATTR_IOMMU_USE_UPSTREAM_HINT;
|
||||
|
||||
return attach;
|
||||
}
|
||||
|
||||
static int msm_vidc_memory_free_ext(struct msm_vidc_core *core, struct msm_vidc_mem *mem)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!mem || !mem->dmabuf) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
d_vpr_h(
|
||||
"%s: dmabuf %pK, size %d, kvaddr %pK, buffer_type %s, secure %d, region %d\n",
|
||||
__func__, mem->dmabuf, mem->size, mem->kvaddr, buf_name(mem->type),
|
||||
mem->secure, mem->region);
|
||||
|
||||
trace_msm_vidc_dma_buffer("FREE", mem->dmabuf, mem->size, mem->kvaddr,
|
||||
buf_name(mem->type), mem->secure, mem->region);
|
||||
|
||||
if (mem->kvaddr) {
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0))
|
||||
dma_buf_vunmap(mem->dmabuf, mem->kvaddr);
|
||||
#else
|
||||
dma_buf_vunmap(mem->dmabuf, &mem->dmabuf_map);
|
||||
#endif
|
||||
mem->kvaddr = NULL;
|
||||
dma_buf_end_cpu_access(mem->dmabuf, DMA_BIDIRECTIONAL);
|
||||
}
|
||||
|
||||
if (mem->dmabuf) {
|
||||
dma_heap_buffer_free(mem->dmabuf);
|
||||
mem->dmabuf = NULL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_vidc_memory_alloc_ext(struct msm_vidc_core *core, struct msm_vidc_mem *mem)
|
||||
{
|
||||
int rc = 0;
|
||||
int size = 0;
|
||||
struct dma_heap *heap;
|
||||
char *heap_name = NULL;
|
||||
struct mem_buf_lend_kernel_arg lend_arg;
|
||||
int vmids[1];
|
||||
int perms[1];
|
||||
|
||||
if (!mem) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
size = ALIGN(mem->size, SZ_4K);
|
||||
|
||||
if (mem->secure) {
|
||||
switch (mem->region) {
|
||||
case MSM_VIDC_SECURE_PIXEL:
|
||||
heap_name = "qcom,secure-pixel";
|
||||
break;
|
||||
case MSM_VIDC_SECURE_NONPIXEL:
|
||||
heap_name = "qcom,secure-non-pixel";
|
||||
break;
|
||||
case MSM_VIDC_SECURE_BITSTREAM:
|
||||
heap_name = "qcom,system";
|
||||
break;
|
||||
default:
|
||||
d_vpr_e("invalid secure region : %#x\n", mem->region);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
heap_name = "qcom,system";
|
||||
}
|
||||
|
||||
heap = dma_heap_find(heap_name);
|
||||
if (IS_ERR_OR_NULL(heap)) {
|
||||
d_vpr_e("%s: dma heap %s find failed\n", __func__, heap_name);
|
||||
heap = NULL;
|
||||
rc = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
mem->dmabuf = dma_heap_buffer_alloc(heap, size, 0, 0);
|
||||
if (IS_ERR_OR_NULL(mem->dmabuf)) {
|
||||
d_vpr_e("%s: dma heap %s alloc failed\n", __func__, heap_name);
|
||||
mem->dmabuf = NULL;
|
||||
rc = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (mem->secure && mem->type == MSM_VIDC_BUF_BIN) {
|
||||
vmids[0] = VMID_CP_BITSTREAM;
|
||||
perms[0] = PERM_READ | PERM_WRITE;
|
||||
|
||||
lend_arg.nr_acl_entries = ARRAY_SIZE(vmids);
|
||||
lend_arg.vmids = vmids;
|
||||
lend_arg.perms = perms;
|
||||
|
||||
rc = mem_buf_lend(mem->dmabuf, &lend_arg);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: BIN dmabuf %pK LEND failed, rc %d heap %s\n",
|
||||
__func__, mem->dmabuf, rc, heap_name);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (mem->map_kernel) {
|
||||
dma_buf_begin_cpu_access(mem->dmabuf, DMA_BIDIRECTIONAL);
|
||||
|
||||
/*
|
||||
* Waipio uses Kernel version 5.10.x,
|
||||
* Kalama uses Kernel Version 5.15.x,
|
||||
* Pineapple uses Kernel Version 5.18.x
|
||||
*/
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0))
|
||||
mem->kvaddr = dma_buf_vmap(mem->dmabuf);
|
||||
if (!mem->kvaddr) {
|
||||
d_vpr_e("%s: kernel map failed\n", __func__);
|
||||
rc = -EIO;
|
||||
goto error;
|
||||
}
|
||||
#elif (LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0))
|
||||
rc = dma_buf_vmap(mem->dmabuf, &mem->dmabuf_map);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: kernel map failed\n", __func__);
|
||||
rc = -EIO;
|
||||
goto error;
|
||||
}
|
||||
mem->kvaddr = mem->dmabuf_map.vaddr;
|
||||
#else
|
||||
rc = dma_buf_vmap(mem->dmabuf, &mem->dmabuf_map);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: kernel map failed\n", __func__);
|
||||
rc = -EIO;
|
||||
goto error;
|
||||
}
|
||||
mem->kvaddr = mem->dmabuf_map.vaddr;
|
||||
#endif
|
||||
}
|
||||
|
||||
d_vpr_h(
|
||||
"%s: dmabuf %pK, size %d, kvaddr %pK, buffer_type %s, secure %d, region %d\n",
|
||||
__func__, mem->dmabuf, mem->size, mem->kvaddr, buf_name(mem->type),
|
||||
mem->secure, mem->region);
|
||||
trace_msm_vidc_dma_buffer("ALLOC", mem->dmabuf, mem->size, mem->kvaddr,
|
||||
buf_name(mem->type), mem->secure, mem->region);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
msm_vidc_memory_free_ext(core, mem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_vidc_memory_map_ext(struct msm_vidc_core *core, struct msm_vidc_mem *mem)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dma_buf_attachment *attach = NULL;
|
||||
struct sg_table *table = NULL;
|
||||
struct context_bank_info *cb = NULL;
|
||||
|
||||
if (!mem) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mem->refcount) {
|
||||
mem->refcount++;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* reject non-secure mapping request for a secure buffer(or vice versa) */
|
||||
if (mem->region == MSM_VIDC_NON_SECURE || mem->region == MSM_VIDC_NON_SECURE_PIXEL) {
|
||||
if (!is_non_secure_buffer(mem->dmabuf)) {
|
||||
d_vpr_e("%s: secure buffer mapping to non-secure region %d not allowed\n",
|
||||
__func__, mem->region);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
if (is_non_secure_buffer(mem->dmabuf)) {
|
||||
d_vpr_e("%s: non-secure buffer mapping to secure region %d not allowed\n",
|
||||
__func__, mem->region);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
cb = msm_vidc_get_context_bank_for_region(core, mem->region);
|
||||
if (!cb || !cb->dev) {
|
||||
d_vpr_e("%s: Failed to get context bank device\n",
|
||||
__func__);
|
||||
rc = -EIO;
|
||||
goto error_cb;
|
||||
}
|
||||
|
||||
/* Prepare a dma buf for dma on the given device */
|
||||
attach = msm_vidc_dma_buf_attach_ext(core, mem->dmabuf, cb->dev);
|
||||
if (IS_ERR_OR_NULL(attach)) {
|
||||
rc = PTR_ERR(attach) ? PTR_ERR(attach) : -ENOMEM;
|
||||
d_vpr_e("Failed to attach dmabuf\n");
|
||||
goto error_attach;
|
||||
}
|
||||
|
||||
table = call_mem_op(core, dma_buf_map_attachment, core, attach);
|
||||
if (IS_ERR_OR_NULL(table)) {
|
||||
rc = PTR_ERR(table) ? PTR_ERR(table) : -ENOMEM;
|
||||
d_vpr_e("Failed to map table\n");
|
||||
goto error_table;
|
||||
}
|
||||
|
||||
mem->device_addr = sg_dma_address(table->sgl);
|
||||
mem->table = table;
|
||||
mem->attach = attach;
|
||||
mem->refcount++;
|
||||
|
||||
exit:
|
||||
d_vpr_l("%s: type %11s, device_addr %#llx, refcount %d, region %d\n",
|
||||
__func__, buf_name(mem->type), mem->device_addr, mem->refcount, mem->region);
|
||||
|
||||
return 0;
|
||||
|
||||
error_table:
|
||||
call_mem_op(core, dma_buf_detach, core, mem->dmabuf, attach);
|
||||
error_attach:
|
||||
error_cb:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_vidc_memory_unmap_ext(struct msm_vidc_core *core,
|
||||
struct msm_vidc_mem *mem)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!mem) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mem->refcount) {
|
||||
mem->refcount--;
|
||||
} else {
|
||||
d_vpr_e("unmap called while refcount is zero already\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
d_vpr_l(
|
||||
"%s: type %11s, device_addr %#llx, refcount %d, region %d\n",
|
||||
__func__, buf_name(mem->type), mem->device_addr, mem->refcount, mem->region);
|
||||
|
||||
if (mem->refcount)
|
||||
goto exit;
|
||||
|
||||
call_mem_op(core, dma_buf_unmap_attachment, core, mem->attach, mem->table);
|
||||
call_mem_op(core, dma_buf_detach, core, mem->dmabuf, mem->attach);
|
||||
|
||||
mem->device_addr = 0x0;
|
||||
mem->attach = NULL;
|
||||
mem->table = NULL;
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static u32 msm_vidc_buffer_region_ext(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
u32 region = MSM_VIDC_NON_SECURE;
|
||||
|
||||
if (!is_secure_session(inst)) {
|
||||
switch (buffer_type) {
|
||||
case MSM_VIDC_BUF_ARP:
|
||||
region = MSM_VIDC_NON_SECURE;
|
||||
break;
|
||||
case MSM_VIDC_BUF_INPUT:
|
||||
if (is_encode_session(inst))
|
||||
region = MSM_VIDC_NON_SECURE_PIXEL;
|
||||
else
|
||||
region = MSM_VIDC_NON_SECURE;
|
||||
break;
|
||||
case MSM_VIDC_BUF_OUTPUT:
|
||||
if (is_encode_session(inst))
|
||||
region = MSM_VIDC_NON_SECURE;
|
||||
else
|
||||
region = MSM_VIDC_NON_SECURE_PIXEL;
|
||||
break;
|
||||
case MSM_VIDC_BUF_DPB:
|
||||
case MSM_VIDC_BUF_VPSS:
|
||||
case MSM_VIDC_BUF_PARTIAL_DATA:
|
||||
region = MSM_VIDC_NON_SECURE_PIXEL;
|
||||
break;
|
||||
case MSM_VIDC_BUF_INPUT_META:
|
||||
case MSM_VIDC_BUF_OUTPUT_META:
|
||||
case MSM_VIDC_BUF_BIN:
|
||||
case MSM_VIDC_BUF_COMV:
|
||||
case MSM_VIDC_BUF_NON_COMV:
|
||||
case MSM_VIDC_BUF_LINE:
|
||||
case MSM_VIDC_BUF_PERSIST:
|
||||
region = MSM_VIDC_NON_SECURE;
|
||||
break;
|
||||
default:
|
||||
i_vpr_e(inst, "%s: invalid driver buffer type %d\n",
|
||||
__func__, buffer_type);
|
||||
}
|
||||
} else {
|
||||
switch (buffer_type) {
|
||||
case MSM_VIDC_BUF_INPUT:
|
||||
if (is_encode_session(inst))
|
||||
region = MSM_VIDC_SECURE_PIXEL;
|
||||
else
|
||||
region = MSM_VIDC_SECURE_BITSTREAM;
|
||||
break;
|
||||
case MSM_VIDC_BUF_OUTPUT:
|
||||
if (is_encode_session(inst))
|
||||
region = MSM_VIDC_SECURE_BITSTREAM;
|
||||
else
|
||||
region = MSM_VIDC_SECURE_PIXEL;
|
||||
break;
|
||||
case MSM_VIDC_BUF_INPUT_META:
|
||||
case MSM_VIDC_BUF_OUTPUT_META:
|
||||
region = MSM_VIDC_NON_SECURE;
|
||||
break;
|
||||
case MSM_VIDC_BUF_DPB:
|
||||
case MSM_VIDC_BUF_VPSS:
|
||||
case MSM_VIDC_BUF_PARTIAL_DATA:
|
||||
region = MSM_VIDC_SECURE_PIXEL;
|
||||
break;
|
||||
case MSM_VIDC_BUF_BIN:
|
||||
region = MSM_VIDC_SECURE_BITSTREAM;
|
||||
break;
|
||||
case MSM_VIDC_BUF_ARP:
|
||||
case MSM_VIDC_BUF_COMV:
|
||||
case MSM_VIDC_BUF_NON_COMV:
|
||||
case MSM_VIDC_BUF_LINE:
|
||||
case MSM_VIDC_BUF_PERSIST:
|
||||
region = MSM_VIDC_SECURE_NONPIXEL;
|
||||
break;
|
||||
default:
|
||||
i_vpr_e(inst, "%s: invalid driver buffer type %d\n",
|
||||
__func__, buffer_type);
|
||||
}
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
static int msm_vidc_memory_alloc_map_ext(struct msm_vidc_core *core, struct msm_vidc_mem *mem)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = msm_vidc_memory_alloc_ext(core, mem);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: memory_alloc failed\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = msm_vidc_memory_map_ext(core, mem);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: memory_map failed\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_vidc_memory_unmap_free_ext(struct msm_vidc_core *core, struct msm_vidc_mem *mem)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = msm_vidc_memory_unmap_ext(core, mem);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: memory_unmap failed\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = msm_vidc_memory_free_ext(core, mem);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: memory_free failed\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
const struct msm_vidc_memory_ops *get_mem_ops_ext(void)
|
||||
{
|
||||
const struct msm_vidc_memory_ops *mem_ops = get_mem_ops();
|
||||
static struct msm_vidc_memory_ops mem_ops_ext;
|
||||
|
||||
memcpy(&mem_ops_ext, mem_ops, sizeof(struct msm_vidc_memory_ops));
|
||||
mem_ops_ext.dma_buf_attach = msm_vidc_dma_buf_attach_ext;
|
||||
mem_ops_ext.memory_alloc_map = msm_vidc_memory_alloc_map_ext;
|
||||
mem_ops_ext.memory_unmap_free = msm_vidc_memory_unmap_free_ext;
|
||||
mem_ops_ext.buffer_region = msm_vidc_buffer_region_ext;
|
||||
|
||||
return &mem_ops_ext;
|
||||
}
|
660
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_power.c
Normal file
660
qcom/opensource/video-driver/driver/vidc/src/msm_vidc_power.c
Normal file
@ -0,0 +1,660 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "msm_vidc_power.h"
|
||||
#include "msm_vidc_internal.h"
|
||||
#include "msm_vidc_debug.h"
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_core.h"
|
||||
#include "msm_vidc_driver.h"
|
||||
#include "msm_vidc_platform.h"
|
||||
#include "msm_vidc_buffer.h"
|
||||
#include "venus_hfi.h"
|
||||
#include "msm_vidc_events.h"
|
||||
|
||||
/* Q16 Format */
|
||||
#define MSM_VIDC_MIN_UBWC_COMPLEXITY_FACTOR (1 << 16)
|
||||
#define MSM_VIDC_MAX_UBWC_COMPLEXITY_FACTOR (4 << 16)
|
||||
#define MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO (1 << 16)
|
||||
#define MSM_VIDC_MAX_UBWC_COMPRESSION_RATIO (5 << 16)
|
||||
#define PASSIVE_VOTE 1000
|
||||
|
||||
/**
|
||||
* Utility function to enforce some of our assumptions. Spam calls to this
|
||||
* in hotspots in code to double check some of the assumptions that we hold.
|
||||
*/
|
||||
struct lut const *__lut(int width, int height, int fps)
|
||||
{
|
||||
int frame_size = height * width, c = 0;
|
||||
|
||||
do {
|
||||
if (LUT[c].frame_size >= frame_size && LUT[c].frame_rate >= fps)
|
||||
return &LUT[c];
|
||||
} while (++c < ARRAY_SIZE(LUT));
|
||||
|
||||
return &LUT[ARRAY_SIZE(LUT) - 1];
|
||||
}
|
||||
|
||||
fp_t __compression_ratio(struct lut const *entry, int bpp)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
for (c = 0; c < COMPRESSION_RATIO_MAX; ++c) {
|
||||
if (entry->compression_ratio[c].bpp == bpp)
|
||||
return entry->compression_ratio[c].ratio;
|
||||
}
|
||||
|
||||
WARN(true, "Shouldn't be here, LUT possibly corrupted?\n");
|
||||
return FP_ZERO; /* impossible */
|
||||
}
|
||||
|
||||
|
||||
void __dump(struct dump dump[], int len)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
for (c = 0; c < len; ++c) {
|
||||
char format_line[128] = "", formatted_line[128] = "";
|
||||
|
||||
if (dump[c].val == DUMP_HEADER_MAGIC) {
|
||||
snprintf(formatted_line, sizeof(formatted_line), "%s\n",
|
||||
dump[c].key);
|
||||
} else {
|
||||
bool fp_format = !strcmp(dump[c].format, DUMP_FP_FMT);
|
||||
|
||||
if (!fp_format) {
|
||||
snprintf(format_line, sizeof(format_line),
|
||||
" %-35s: %s\n", dump[c].key,
|
||||
dump[c].format);
|
||||
snprintf(formatted_line, sizeof(formatted_line),
|
||||
format_line, dump[c].val);
|
||||
} else {
|
||||
size_t integer_part, fractional_part;
|
||||
|
||||
integer_part = fp_int(dump[c].val);
|
||||
fractional_part = fp_frac(dump[c].val);
|
||||
snprintf(formatted_line, sizeof(formatted_line),
|
||||
" %-35s: %zd + %zd/%zd\n",
|
||||
dump[c].key, integer_part,
|
||||
fractional_part,
|
||||
fp_frac_base());
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
d_vpr_b("%s", formatted_line);
|
||||
}
|
||||
}
|
||||
|
||||
u64 msm_vidc_max_freq(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
struct frequency_table *freq_tbl;
|
||||
u64 freq = 0;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
if (!core->resource || !core->resource->freq_set.freq_tbl ||
|
||||
!core->resource->freq_set.count) {
|
||||
i_vpr_e(inst, "%s: invalid frequency table\n", __func__);
|
||||
return freq;
|
||||
}
|
||||
freq_tbl = core->resource->freq_set.freq_tbl;
|
||||
freq = freq_tbl[0].freq;
|
||||
|
||||
i_vpr_l(inst, "%s: rate = %llu\n", __func__, freq);
|
||||
return freq;
|
||||
}
|
||||
|
||||
static int fill_dynamic_stats(struct msm_vidc_inst *inst,
|
||||
struct vidc_bus_vote_data *vote_data)
|
||||
{
|
||||
struct msm_vidc_input_cr_data *temp, *next;
|
||||
u32 cf = MSM_VIDC_MAX_UBWC_COMPLEXITY_FACTOR;
|
||||
u32 cr = MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO;
|
||||
u32 input_cr = MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO;
|
||||
u32 frame_size;
|
||||
|
||||
if (inst->power.fw_cr)
|
||||
cr = inst->power.fw_cr;
|
||||
|
||||
if (inst->power.fw_cf) {
|
||||
cf = inst->power.fw_cf;
|
||||
frame_size = (msm_vidc_get_mbs_per_frame(inst) / (32 * 8) * 3) / 2;
|
||||
if (frame_size)
|
||||
cf = cf / frame_size;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(temp, next, &inst->enc_input_crs, list)
|
||||
input_cr = min(input_cr, temp->input_cr);
|
||||
|
||||
vote_data->compression_ratio = cr;
|
||||
vote_data->complexity_factor = cf;
|
||||
vote_data->input_cr = input_cr;
|
||||
|
||||
/* Sanitize CF values from HW */
|
||||
cf = clamp_t(u32, cf, MSM_VIDC_MIN_UBWC_COMPLEXITY_FACTOR,
|
||||
MSM_VIDC_MAX_UBWC_COMPLEXITY_FACTOR);
|
||||
cr = clamp_t(u32, cr, MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO,
|
||||
MSM_VIDC_MAX_UBWC_COMPRESSION_RATIO);
|
||||
input_cr = clamp_t(u32, input_cr, MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO,
|
||||
MSM_VIDC_MAX_UBWC_COMPRESSION_RATIO);
|
||||
|
||||
vote_data->compression_ratio = cr;
|
||||
vote_data->complexity_factor = cf;
|
||||
vote_data->input_cr = input_cr;
|
||||
|
||||
i_vpr_l(inst,
|
||||
"Input CR = %d Recon CR = %d Complexity Factor = %d\n",
|
||||
vote_data->input_cr, vote_data->compression_ratio,
|
||||
vote_data->complexity_factor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_vidc_set_buses(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_vidc_core *core;
|
||||
struct msm_vidc_inst *temp;
|
||||
u64 total_bw_ddr = 0, total_bw_llcc = 0;
|
||||
u64 curr_time_ns;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
curr_time_ns = ktime_get_ns();
|
||||
list_for_each_entry(temp, &core->instances, list) {
|
||||
/* skip for session where no input is there to process */
|
||||
if (!temp->max_input_data_size)
|
||||
continue;
|
||||
|
||||
/* skip inactive session bus bandwidth */
|
||||
if (!is_active_session(temp->last_qbuf_time_ns, curr_time_ns)) {
|
||||
temp->active = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (temp->power.power_mode == VIDC_POWER_TURBO) {
|
||||
total_bw_ddr = total_bw_llcc = INT_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
total_bw_ddr += temp->power.ddr_bw;
|
||||
total_bw_llcc += temp->power.sys_cache_bw;
|
||||
}
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
/* Incase of no video frames to process ensure min passive voting for Tensilica */
|
||||
if (!total_bw_ddr)
|
||||
total_bw_ddr = PASSIVE_VOTE;
|
||||
|
||||
if (msm_vidc_ddr_bw) {
|
||||
d_vpr_l("msm_vidc_ddr_bw %d\n", msm_vidc_ddr_bw);
|
||||
total_bw_ddr = msm_vidc_ddr_bw;
|
||||
}
|
||||
|
||||
if (msm_vidc_llc_bw) {
|
||||
d_vpr_l("msm_vidc_llc_bw %d\n", msm_vidc_llc_bw);
|
||||
total_bw_llcc = msm_vidc_llc_bw;
|
||||
}
|
||||
|
||||
rc = venus_hfi_scale_buses(inst, total_bw_ddr, total_bw_llcc);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_scale_buses(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_vidc_core *core;
|
||||
struct vidc_bus_vote_data *vote_data;
|
||||
struct v4l2_format *out_f;
|
||||
struct v4l2_format *inp_f;
|
||||
u32 operating_rate, frame_rate;
|
||||
|
||||
core = inst->core;
|
||||
if (!core->resource) {
|
||||
i_vpr_e(inst, "%s: invalid resource params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
vote_data = &inst->bus_data;
|
||||
|
||||
vote_data->power_mode = VIDC_POWER_NORMAL;
|
||||
if (inst->power.buffer_counter < DCVS_WINDOW || is_image_session(inst))
|
||||
vote_data->power_mode = VIDC_POWER_TURBO;
|
||||
|
||||
if (vote_data->power_mode == VIDC_POWER_TURBO)
|
||||
goto set_buses;
|
||||
|
||||
out_f = &inst->fmts[OUTPUT_PORT];
|
||||
inp_f = &inst->fmts[INPUT_PORT];
|
||||
|
||||
vote_data->codec = inst->codec;
|
||||
vote_data->input_width = inp_f->fmt.pix_mp.width;
|
||||
vote_data->input_height = inp_f->fmt.pix_mp.height;
|
||||
vote_data->output_width = out_f->fmt.pix_mp.width;
|
||||
vote_data->output_height = out_f->fmt.pix_mp.height;
|
||||
vote_data->lcu_size = (inst->codec == MSM_VIDC_HEVC ||
|
||||
inst->codec == MSM_VIDC_VP9) ? 32 : 16;
|
||||
if (inst->codec == MSM_VIDC_AV1)
|
||||
vote_data->lcu_size =
|
||||
inst->capabilities[SUPER_BLOCK].value ? 128 : 64;
|
||||
vote_data->fps = inst->max_rate;
|
||||
|
||||
if (is_encode_session(inst)) {
|
||||
vote_data->domain = MSM_VIDC_ENCODER;
|
||||
vote_data->bitrate = inst->capabilities[BIT_RATE].value;
|
||||
vote_data->rotation = inst->capabilities[ROTATION].value;
|
||||
vote_data->b_frames_enabled =
|
||||
inst->capabilities[B_FRAME].value > 0;
|
||||
|
||||
/* scale bitrate if operating rate is larger than frame rate */
|
||||
frame_rate = msm_vidc_get_frame_rate(inst);
|
||||
operating_rate = inst->max_rate;
|
||||
if (frame_rate && operating_rate && operating_rate > frame_rate)
|
||||
vote_data->bitrate = (vote_data->bitrate / frame_rate) * operating_rate;
|
||||
|
||||
vote_data->num_formats = 1;
|
||||
vote_data->color_formats[0] = v4l2_colorformat_to_driver(inst,
|
||||
inst->fmts[INPUT_PORT].fmt.pix_mp.pixelformat, __func__);
|
||||
vote_data->vpss_preprocessing_enabled =
|
||||
inst->capabilities[REQUEST_PREPROCESS].value;
|
||||
} else if (is_decode_session(inst)) {
|
||||
u32 color_format;
|
||||
|
||||
vote_data->domain = MSM_VIDC_DECODER;
|
||||
vote_data->bitrate = inst->max_input_data_size * vote_data->fps * 8;
|
||||
color_format = v4l2_colorformat_to_driver(inst,
|
||||
inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat, __func__);
|
||||
if (is_linear_colorformat(color_format)) {
|
||||
vote_data->num_formats = 2;
|
||||
/*
|
||||
* 0 index - dpb colorformat
|
||||
* 1 index - opb colorformat
|
||||
*/
|
||||
if (is_10bit_colorformat(color_format))
|
||||
vote_data->color_formats[0] = MSM_VIDC_FMT_TP10C;
|
||||
else
|
||||
vote_data->color_formats[0] = MSM_VIDC_FMT_NV12;
|
||||
|
||||
vote_data->color_formats[1] = color_format;
|
||||
} else if (inst->codec == MSM_VIDC_AV1 &&
|
||||
inst->capabilities[FILM_GRAIN].value) {
|
||||
/*
|
||||
* UBWC formats with AV1 film grain requires dpb-opb
|
||||
* split mode
|
||||
*/
|
||||
vote_data->num_formats = 2;
|
||||
vote_data->color_formats[0] =
|
||||
vote_data->color_formats[1] = color_format;
|
||||
} else {
|
||||
vote_data->num_formats = 1;
|
||||
vote_data->color_formats[0] = color_format;
|
||||
}
|
||||
}
|
||||
vote_data->work_mode = inst->capabilities[STAGE].value;
|
||||
if (core->resource->subcache_set.set_to_fw)
|
||||
vote_data->use_sys_cache = true;
|
||||
vote_data->num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
|
||||
fill_dynamic_stats(inst, vote_data);
|
||||
|
||||
call_session_op(core, calc_bw, inst, vote_data);
|
||||
|
||||
inst->power.ddr_bw = vote_data->calc_bw_ddr;
|
||||
inst->power.sys_cache_bw = vote_data->calc_bw_llcc;
|
||||
|
||||
if (!inst->stats.avg_bw_llcc)
|
||||
inst->stats.avg_bw_llcc = inst->power.sys_cache_bw;
|
||||
else
|
||||
inst->stats.avg_bw_llcc =
|
||||
(inst->stats.avg_bw_llcc + inst->power.sys_cache_bw) / 2;
|
||||
|
||||
if (!inst->stats.avg_bw_ddr)
|
||||
inst->stats.avg_bw_ddr = inst->power.ddr_bw;
|
||||
else
|
||||
inst->stats.avg_bw_ddr =
|
||||
(inst->stats.avg_bw_ddr + inst->power.ddr_bw) / 2;
|
||||
|
||||
set_buses:
|
||||
inst->power.power_mode = vote_data->power_mode;
|
||||
rc = msm_vidc_set_buses(inst);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_set_clocks(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_vidc_core *core;
|
||||
struct msm_vidc_inst *temp;
|
||||
u64 freq;
|
||||
u64 rate = 0;
|
||||
bool increment, decrement;
|
||||
u64 curr_time_ns;
|
||||
int i = 0;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
if (!core->resource || !core->resource->freq_set.freq_tbl ||
|
||||
!core->resource->freq_set.count) {
|
||||
d_vpr_e("%s: invalid frequency table\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
increment = false;
|
||||
decrement = true;
|
||||
freq = 0;
|
||||
curr_time_ns = ktime_get_ns();
|
||||
list_for_each_entry(temp, &core->instances, list) {
|
||||
/* skip for session where no input is there to process */
|
||||
if (!temp->max_input_data_size)
|
||||
continue;
|
||||
|
||||
/* skip inactive session clock rate */
|
||||
if (!is_active_session(temp->last_qbuf_time_ns, curr_time_ns)) {
|
||||
temp->active = false;
|
||||
continue;
|
||||
}
|
||||
freq += temp->power.min_freq;
|
||||
|
||||
if (msm_vidc_clock_voting) {
|
||||
d_vpr_l("msm_vidc_clock_voting %d\n", msm_vidc_clock_voting);
|
||||
freq = msm_vidc_clock_voting;
|
||||
decrement = false;
|
||||
break;
|
||||
}
|
||||
/* increment even if one session requested for it */
|
||||
if (temp->power.dcvs_flags & MSM_VIDC_DCVS_INCR)
|
||||
increment = true;
|
||||
/* decrement only if all sessions requested for it */
|
||||
if (!(temp->power.dcvs_flags & MSM_VIDC_DCVS_DECR))
|
||||
decrement = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* keep checking from lowest to highest rate until
|
||||
* table rate >= requested rate
|
||||
*/
|
||||
for (i = core->resource->freq_set.count - 1; i >= 0; i--) {
|
||||
rate = core->resource->freq_set.freq_tbl[i].freq;
|
||||
if (rate >= freq)
|
||||
break;
|
||||
}
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
if (increment) {
|
||||
if (i > 0)
|
||||
rate = core->resource->freq_set.freq_tbl[i - 1].freq;
|
||||
} else if (decrement) {
|
||||
if (i < (int)(core->platform->data.freq_tbl_size - 1))
|
||||
rate = core->resource->freq_set.freq_tbl[i + 1].freq;
|
||||
}
|
||||
core->power.clk_freq = (u32)rate;
|
||||
|
||||
i_vpr_p(inst, "%s: clock rate %llu requested %llu increment %d decrement %d\n",
|
||||
__func__, rate, freq, increment, decrement);
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
rc = venus_hfi_scale_clocks(inst, rate);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_vidc_apply_dcvs(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int rc = 0;
|
||||
int bufs_with_fw = 0;
|
||||
struct msm_vidc_power *power;
|
||||
|
||||
/* skip dcvs */
|
||||
if (!inst->power.dcvs_mode)
|
||||
return 0;
|
||||
|
||||
power = &inst->power;
|
||||
|
||||
if (is_decode_session(inst)) {
|
||||
bufs_with_fw = msm_vidc_num_buffers(inst,
|
||||
MSM_VIDC_BUF_OUTPUT, MSM_VIDC_ATTR_QUEUED);
|
||||
} else {
|
||||
bufs_with_fw = msm_vidc_num_buffers(inst,
|
||||
MSM_VIDC_BUF_INPUT, MSM_VIDC_ATTR_QUEUED);
|
||||
}
|
||||
|
||||
/* +1 as one buffer is going to be queued after the function */
|
||||
bufs_with_fw += 1;
|
||||
|
||||
/*
|
||||
* DCVS decides clock level based on below algorithm
|
||||
*
|
||||
* Limits :
|
||||
* min_threshold : Buffers required for reference by FW.
|
||||
* nom_threshold : Midpoint of Min and Max thresholds
|
||||
* max_threshold : Min Threshold + DCVS extra buffers, allocated
|
||||
* for smooth flow.
|
||||
* 1) When buffers outside FW are reaching client's extra buffers,
|
||||
* FW is slow and will impact pipeline, Increase clock.
|
||||
* 2) When pending buffers with FW are less than FW requested,
|
||||
* pipeline has cushion to absorb FW slowness, Decrease clocks.
|
||||
* 3) When DCVS has engaged(Inc or Dec):
|
||||
* For decode:
|
||||
* - Pending buffers with FW transitions past the nom_threshold,
|
||||
* switch to calculated load, this smoothens the clock transitions.
|
||||
* For encode:
|
||||
* - Always switch to calculated load.
|
||||
* 4) Otherwise maintain previous Load config.
|
||||
*/
|
||||
if (bufs_with_fw >= power->max_threshold) {
|
||||
power->dcvs_flags = MSM_VIDC_DCVS_INCR;
|
||||
goto exit;
|
||||
} else if (bufs_with_fw < power->min_threshold) {
|
||||
power->dcvs_flags = MSM_VIDC_DCVS_DECR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* encoder: dcvs window handling */
|
||||
if (is_encode_session(inst)) {
|
||||
power->dcvs_flags = 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* decoder: dcvs window handling */
|
||||
if ((power->dcvs_flags & MSM_VIDC_DCVS_DECR && bufs_with_fw >= power->nom_threshold) ||
|
||||
(power->dcvs_flags & MSM_VIDC_DCVS_INCR && bufs_with_fw <= power->nom_threshold)) {
|
||||
power->dcvs_flags = 0;
|
||||
}
|
||||
|
||||
exit:
|
||||
i_vpr_p(inst, "dcvs: bufs_with_fw %d th[%d %d %d] flags %#x\n",
|
||||
bufs_with_fw, power->min_threshold,
|
||||
power->nom_threshold, power->max_threshold,
|
||||
power->dcvs_flags);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_vidc_scale_clocks(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
if (inst->power.buffer_counter < DCVS_WINDOW ||
|
||||
is_image_session(inst) ||
|
||||
is_sub_state(inst, MSM_VIDC_DRC) ||
|
||||
is_sub_state(inst, MSM_VIDC_DRAIN)) {
|
||||
inst->power.min_freq = msm_vidc_max_freq(inst);
|
||||
inst->power.dcvs_flags = 0;
|
||||
} else if (msm_vidc_clock_voting) {
|
||||
inst->power.min_freq = msm_vidc_clock_voting;
|
||||
inst->power.dcvs_flags = 0;
|
||||
} else {
|
||||
inst->power.min_freq =
|
||||
call_session_op(core, calc_freq, inst, inst->max_input_data_size);
|
||||
msm_vidc_apply_dcvs(inst);
|
||||
}
|
||||
inst->power.curr_freq = inst->power.min_freq;
|
||||
msm_vidc_set_clocks(inst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_scale_power(struct msm_vidc_inst *inst, bool scale_buses)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
struct msm_vidc_buffer *vbuf;
|
||||
u32 data_size = 0;
|
||||
u32 cnt = 0;
|
||||
u32 fps;
|
||||
u32 frame_rate, operating_rate;
|
||||
u32 timestamp_rate = 0, input_rate = 0;
|
||||
|
||||
core = inst->core;
|
||||
|
||||
if (!inst->active) {
|
||||
/* scale buses for inactive -> active session */
|
||||
scale_buses = true;
|
||||
inst->active = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* consider avg. filled length in decode batching case
|
||||
* to avoid overvoting for the entire batch due to single
|
||||
* frame with huge filled length
|
||||
*/
|
||||
if (inst->decode_batch.enable) {
|
||||
list_for_each_entry(vbuf, &inst->buffers.input.list, list) {
|
||||
if (vbuf->attr & MSM_VIDC_ATTR_DEFERRED ||
|
||||
vbuf->attr & MSM_VIDC_ATTR_QUEUED) {
|
||||
data_size += vbuf->data_size;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
if (cnt)
|
||||
data_size /= cnt;
|
||||
} else {
|
||||
list_for_each_entry(vbuf, &inst->buffers.input.list, list)
|
||||
data_size = max(data_size, vbuf->data_size);
|
||||
}
|
||||
inst->max_input_data_size = data_size;
|
||||
|
||||
frame_rate = msm_vidc_get_frame_rate(inst);
|
||||
operating_rate = msm_vidc_get_operating_rate(inst);
|
||||
fps = max(frame_rate, operating_rate);
|
||||
/*
|
||||
* Consider input queuing rate power scaling in below scenarios
|
||||
* decoder: non-realtime and realtime as well because client
|
||||
* may not set the frame rate / operating rate and
|
||||
* we need to rely on input queue rate
|
||||
* encoder: non-realtime only, for realtime client is expected to
|
||||
* queue input buffers at the set frame rate / operating rate
|
||||
*/
|
||||
if (is_decode_session(inst) ||
|
||||
(is_encode_session(inst) && !is_realtime_session(inst))) {
|
||||
/*
|
||||
* when buffer detected fps is more than client set value by 12.5%,
|
||||
* utilize buffer detected fps to scale clock.
|
||||
*/
|
||||
timestamp_rate = msm_vidc_get_timestamp_rate(inst);
|
||||
input_rate = msm_vidc_get_input_rate(inst);
|
||||
if (timestamp_rate > (fps + fps / 8))
|
||||
fps = timestamp_rate;
|
||||
|
||||
if (input_rate > fps) {
|
||||
fps = input_rate;
|
||||
/*
|
||||
* add 6.25% more fps for NRT session to increase power to make
|
||||
* firmware processing little faster than client queuing rate
|
||||
*/
|
||||
if (!is_realtime_session(inst))
|
||||
fps = fps + fps / 16;
|
||||
}
|
||||
}
|
||||
inst->max_rate = fps;
|
||||
|
||||
/* no pending inputs - skip scale power */
|
||||
if (!inst->max_input_data_size)
|
||||
return 0;
|
||||
|
||||
if (msm_vidc_scale_clocks(inst))
|
||||
i_vpr_e(inst, "failed to scale clock\n");
|
||||
|
||||
if (scale_buses) {
|
||||
if (msm_vidc_scale_buses(inst))
|
||||
i_vpr_e(inst, "failed to scale bus\n");
|
||||
}
|
||||
|
||||
i_vpr_hp(inst,
|
||||
"power: inst: clk %lld ddr %d llcc %d dcvs flags %#x fps %u (%u %u %u %u) core: clk %lld ddr %lld llcc %lld\n",
|
||||
inst->power.curr_freq, inst->power.ddr_bw,
|
||||
inst->power.sys_cache_bw, inst->power.dcvs_flags,
|
||||
inst->max_rate, frame_rate, operating_rate, timestamp_rate,
|
||||
input_rate, core->power.clk_freq, core->power.bw_ddr,
|
||||
core->power.bw_llcc);
|
||||
|
||||
trace_msm_vidc_perf_power_scale(inst, core->power.clk_freq,
|
||||
core->power.bw_ddr, core->power.bw_llcc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void msm_vidc_dcvs_data_reset(struct msm_vidc_inst *inst)
|
||||
{
|
||||
struct msm_vidc_power *dcvs;
|
||||
u32 min_count, actual_count, max_count;
|
||||
|
||||
dcvs = &inst->power;
|
||||
if (is_encode_session(inst)) {
|
||||
min_count = inst->buffers.input.min_count;
|
||||
actual_count = inst->buffers.input.actual_count;
|
||||
max_count = min((min_count + DCVS_ENC_EXTRA_INPUT_BUFFERS), actual_count);
|
||||
} else if (is_decode_session(inst)) {
|
||||
min_count = inst->buffers.output.min_count;
|
||||
actual_count = inst->buffers.output.actual_count;
|
||||
max_count = min((min_count + DCVS_DEC_EXTRA_OUTPUT_BUFFERS), actual_count);
|
||||
} else {
|
||||
i_vpr_e(inst, "%s: invalid domain type %d\n",
|
||||
__func__, inst->domain);
|
||||
return;
|
||||
}
|
||||
|
||||
dcvs->min_threshold = min_count;
|
||||
dcvs->max_threshold = max_count;
|
||||
dcvs->dcvs_window = min_count < max_count ? max_count - min_count : 0;
|
||||
dcvs->nom_threshold = dcvs->min_threshold + (dcvs->dcvs_window / 2);
|
||||
dcvs->dcvs_flags = 0;
|
||||
|
||||
i_vpr_p(inst, "%s: dcvs: thresholds [%d %d %d] flags %#x\n",
|
||||
__func__, dcvs->min_threshold,
|
||||
dcvs->nom_threshold, dcvs->max_threshold,
|
||||
dcvs->dcvs_flags);
|
||||
}
|
||||
|
||||
void msm_vidc_power_data_reset(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
i_vpr_hp(inst, "%s\n", __func__);
|
||||
|
||||
msm_vidc_dcvs_data_reset(inst);
|
||||
|
||||
inst->power.buffer_counter = 0;
|
||||
inst->power.fw_cr = 0;
|
||||
inst->power.fw_cf = INT_MAX;
|
||||
inst->power.fw_av1_tile_rows = 1;
|
||||
inst->power.fw_av1_tile_columns = 1;
|
||||
|
||||
rc = msm_vidc_scale_power(inst, true);
|
||||
if (rc)
|
||||
i_vpr_e(inst, "%s: failed to scale power\n", __func__);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user