video: driver: Add support for lanai/iris3.3 platform

Add the required config and platform files to enable
lanai platform with iris3.3 VPU.

Change-Id: I441d631b9876705342e34097feff3e5d355d6b71
Signed-off-by: Deepa Guthyappa Madivalara <quic_dmadival@quicinc.com>
This commit is contained in:
Deepa Guthyappa Madivalara
2022-08-30 11:54:44 -07:00
parent 908892519f
commit 3d9c6f17f9
14 changed files with 9508 additions and 2 deletions

17
Kbuild
View File

@@ -14,6 +14,12 @@ LINUXINCLUDE += -include $(VIDEO_ROOT)/config/kalama_video.h \
-I$(VIDEO_ROOT)/driver/platform/kalama/inc -I$(VIDEO_ROOT)/driver/platform/kalama/inc
endif endif
ifeq ($(CONFIG_ARCH_PINEAPPLE), y)
include $(VIDEO_ROOT)/config/pineapple_video.conf
LINUXINCLUDE += -include $(VIDEO_ROOT)/config/pineapple_video.h \
-I$(VIDEO_ROOT)/driver/platform/pineapple/inc
endif
ifeq ($(CONFIG_ARCH_ANORAK), y) ifeq ($(CONFIG_ARCH_ANORAK), y)
include $(VIDEO_ROOT)/config/anorak_video.conf include $(VIDEO_ROOT)/config/anorak_video.conf
LINUXINCLUDE += -include $(VIDEO_ROOT)/config/anorak_video.h \ LINUXINCLUDE += -include $(VIDEO_ROOT)/config/anorak_video.h \
@@ -38,6 +44,10 @@ ifeq ($(CONFIG_MSM_VIDC_KALAMA), y)
msm_video-objs += driver/platform/kalama/src/msm_vidc_kalama.o msm_video-objs += driver/platform/kalama/src/msm_vidc_kalama.o
endif endif
ifeq ($(CONFIG_MSM_VIDC_PINEAPPLE), y)
msm_video-objs += driver/platform/pineapple/src/msm_vidc_pineapple.o
endif
ifeq ($(CONFIG_MSM_VIDC_ANORAK), y) ifeq ($(CONFIG_MSM_VIDC_ANORAK), y)
msm_video-objs += driver/platform/anorak/src/msm_vidc_anorak.o msm_video-objs += driver/platform/anorak/src/msm_vidc_anorak.o
endif endif
@@ -56,6 +66,13 @@ msm_video-objs += driver/variant/iris3/src/msm_vidc_buffer_iris3.o \
driver/variant/iris3/src/msm_vidc_iris3.o driver/variant/iris3/src/msm_vidc_iris3.o
endif endif
ifeq ($(CONFIG_MSM_VIDC_IRIS33), y)
LINUXINCLUDE += -I$(VIDEO_ROOT)/driver/variant/iris33/inc
msm_video-objs += driver/variant/iris33/src/msm_vidc_buffer_iris33.o \
driver/variant/iris33/src/msm_vidc_power_iris33.o \
driver/variant/iris33/src/msm_vidc_iris33.o
endif
msm_video-objs += driver/vidc/src/msm_vidc_v4l2.o \ msm_video-objs += driver/vidc/src/msm_vidc_v4l2.o \
driver/vidc/src/msm_vidc_vb2.o \ driver/vidc/src/msm_vidc_vb2.o \
driver/vidc/src/msm_vidc.o \ driver/vidc/src/msm_vidc.o \

View File

@@ -0,0 +1,2 @@
export CONFIG_MSM_VIDC_PINEAPPLE=y
export CONFIG_MSM_VIDC_IRIS33=y

8
config/pineapple_video.h Normal file
View File

@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define CONFIG_MSM_VIDC_PINEAPPLE 1
#define CONFIG_MSM_VIDC_IRIS33 1

View File

@@ -23,6 +23,12 @@
#if defined(CONFIG_MSM_VIDC_KALAMA) #if defined(CONFIG_MSM_VIDC_KALAMA)
#include "msm_vidc_kalama.h" #include "msm_vidc_kalama.h"
#endif #endif
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
#include "msm_vidc_pineapple.h"
#endif
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
#include "msm_vidc_pineapple.h"
#endif
#if defined(CONFIG_MSM_VIDC_ANORAK) #if defined(CONFIG_MSM_VIDC_ANORAK)
#include "msm_vidc_anorak.h" #include "msm_vidc_anorak.h"
#endif #endif
@@ -32,7 +38,9 @@
#if defined(CONFIG_MSM_VIDC_IRIS3) #if defined(CONFIG_MSM_VIDC_IRIS3)
#include "msm_vidc_iris3.h" #include "msm_vidc_iris3.h"
#endif #endif
#if defined(CONFIG_MSM_VIDC_IRIS33)
#include "msm_vidc_iris33.h"
#endif
/* /*
* Custom conversion coefficients for resolution: 176x144 negative * Custom conversion coefficients for resolution: 176x144 negative
* coeffs are converted to s4.9 format * coeffs are converted to s4.9 format
@@ -229,6 +237,14 @@ static int msm_vidc_deinit_platform_variant(struct msm_vidc_core *core, struct d
return rc; return rc;
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-pineapple")) {
rc = msm_vidc_deinit_platform_pineapple(core, dev);
if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc);
return rc;
}
#endif
#if defined(CONFIG_MSM_VIDC_ANORAK) #if defined(CONFIG_MSM_VIDC_ANORAK)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-anorak")) { if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-anorak")) {
rc = msm_vidc_deinit_platform_anorak(core, dev); rc = msm_vidc_deinit_platform_anorak(core, dev);
@@ -268,6 +284,14 @@ static int msm_vidc_init_platform_variant(struct msm_vidc_core *core, struct dev
return rc; return rc;
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_PINEAPPLE)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-pineapple")) {
rc = msm_vidc_init_platform_pineapple(core, dev);
if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc);
return rc;
}
#endif
#if defined(CONFIG_MSM_VIDC_ANORAK) #if defined(CONFIG_MSM_VIDC_ANORAK)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-anorak")) { if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-anorak")) {
rc = msm_vidc_init_platform_anorak(core, dev); rc = msm_vidc_init_platform_anorak(core, dev);
@@ -307,7 +331,14 @@ static int msm_vidc_deinit_vpu(struct msm_vidc_core *core, struct device *dev)
return rc; return rc;
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_IRIS33)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris33")) {
rc = msm_vidc_deinit_iris33(core);
if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc);
return rc;
}
#endif
return rc; return rc;
} }
@@ -336,6 +367,14 @@ static int msm_vidc_init_vpu(struct msm_vidc_core *core, struct device *dev)
return rc; return rc;
} }
#endif #endif
#if defined(CONFIG_MSM_VIDC_IRIS33)
if (of_device_is_compatible(dev->of_node, "qcom,msm-vidc-iris33")) {
rc = msm_vidc_init_iris33(core);
if (rc)
d_vpr_e("%s: failed with %d\n", __func__, rc);
return rc;
}
#endif
return rc; return rc;
} }

View File

@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 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, struct device *dev);
int msm_vidc_deinit_platform_pineapple(struct msm_vidc_core *core, struct device *dev);
#else
int msm_vidc_init_platform_pineapple(struct msm_vidc_core *core, struct device *dev)
{
return -EINVAL;
}
int msm_vidc_deinit_platform_pineapple(struct msm_vidc_core *core, struct device *dev)
{
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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 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__

View File

@@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 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_IRIS33)
int msm_vidc_init_iris33(struct msm_vidc_core *core);
int msm_vidc_deinit_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_deinit_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_

View File

@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 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_power.h"
#include "msm_vidc_inst.h"
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

View File

@@ -0,0 +1,837 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "hfi_property.h"
#include "hfi_buffer_iris33.h"
#include "msm_vidc_buffer_iris33.h"
#include "msm_vidc_buffer.h"
#include "msm_vidc_inst.h"
#include "msm_vidc_core.h"
#include "msm_vidc_platform.h"
#include "msm_vidc_driver.h"
#include "msm_vidc_debug.h"
#include "msm_media_info.h"
#include "msm_vidc_control.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;
if (!inst || !inst->core || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return size;
}
core = inst->core;
if (!core->capabilities) {
i_vpr_e(inst, "%s: invalid capabilities\n", __func__);
return size;
}
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->cap[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;
if (!inst || !inst->core || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return size;
}
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->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->cap[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;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return size;
}
core = inst->core;
if (!core->capabilities) {
i_vpr_e(inst, "%s: invalid core capabilities\n", __func__);
return size;
}
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;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return size;
}
core = inst->core;
if (!core->capabilities) {
i_vpr_e(inst, "%s: invalid capabilities\n", __func__);
return size;
}
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;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return size;
}
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) {
d_vpr_e("%s: invalid params\n", __func__);
return size;
}
if (inst->capabilities->cap[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->cap[DRAP].value)
HFI_BUFFER_PERSIST_AV1D(size,
inst->capabilities->cap[FRAME_WIDTH].max,
inst->capabilities->cap[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;
struct v4l2_format *f;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return size;
}
/*
* 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->cap[PIX_FMTS].value;
if (!is_linear_colorformat(color_fmt) &&
inst->codec != MSM_VIDC_AV1)
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_iris33(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;
if (!inst || !inst->core || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return size;
}
core = inst->core;
if (!core->capabilities) {
i_vpr_e(inst, "%s: invalid core capabilities\n", __func__);
return size;
}
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
stage = inst->capabilities->cap[STAGE].value;
f = &inst->fmts[OUTPUT_PORT];
width = f->fmt.pix_mp.width;
height = f->fmt.pix_mp.height;
profile = inst->capabilities->cap[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->cap[B_FRAME].value;
ltr_count = inst->capabilities->cap[LTR_COUNT].value;
if (inst->hfi_layer_type == HFI_HIER_B) {
hb_layers = inst->capabilities->cap[ENH_LAYER_COUNT].value + 1;
} else {
hp_layers = inst->capabilities->cap[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;
if (!inst || !inst->core || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return size;
}
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;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return size;
}
core = inst->core;
if (!core->capabilities) {
i_vpr_e(inst, "%s: invalid core capabilities\n", __func__);
return size;
}
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;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return size;
}
core = inst->core;
if (!core->capabilities || !inst->capabilities) {
i_vpr_e(inst, "%s: invalid capabilities\n", __func__);
return size;
}
num_vpp_pipes = core->capabilities[NUM_VPP_PIPE].value;
pixfmt = inst->capabilities->cap[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;
if (!inst || !inst->core || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return 0;
}
f = &inst->fmts[OUTPUT_PORT];
width = f->fmt.pix_mp.width;
height = f->fmt.pix_mp.height;
pixfmt = inst->capabilities->cap[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;
if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__);
return 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;
if (!inst || !inst->core || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return 0;
}
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->cap[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;
if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
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->cap[BITRATE_MODE].value;
frame_rc = inst->capabilities->cap[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 (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return 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->cap[ENH_LAYER_COUNT].value + 1 : 0;
if (inst->codec == MSM_VIDC_H264 &&
!inst->capabilities->cap[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;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return 0;
}
/* decoder dpb buffer count */
if (is_decode_session(inst)) {
color_fmt = inst->capabilities->cap[PIX_FMTS].value;
if (is_linear_colorformat(color_fmt) ||
(inst->codec == MSM_VIDC_AV1 &&
(inst->capabilities->cap[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_iris33(struct msm_vidc_inst *inst,
uint32_t count)
{
struct v4l2_format *f;
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;
if (!inst || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return count;
}
slice_mode = inst->capabilities->cap[SLICE_MODE].value;
delivery_mode = inst->capabilities->cap[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->cap[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;
HFI_IRIS3_ENC_MB_BASED_MULTI_SLICE_COUNT(total_num_slices, width, height,
hfi_codec, max_mbs_per_slice);
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;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return 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;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return 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

View File

@@ -0,0 +1,803 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020-2022, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "msm_vidc_power_iris33.h"
#include "msm_vidc_inst.h"
#include "msm_vidc_core.h"
#include "msm_vidc_driver.h"
#include "msm_vidc_debug.h"
#include "msm_vidc_dt.h"
u64 msm_vidc_calc_freq_iris33(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;
if (!inst || !inst->core || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return freq;
}
core = inst->core;
if (!core->dt || !core->dt->allowed_clks_tbl) {
d_vpr_e("%s: invalid params\n", __func__);
return freq;
}
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->cap[MB_CYCLES_FW].value;
fw_vpp_cycles = fps * inst->capabilities->cap[MB_CYCLES_FW_VPP].value;
if (inst->domain == MSM_VIDC_ENCODER) {
vpp_cycles_per_mb = is_low_power_session(inst) ?
inst->capabilities->cap[MB_CYCLES_LP].value :
inst->capabilities->cap[MB_CYCLES_VPP].value;
vpp_cycles = mbs_per_second * vpp_cycles_per_mb /
inst->capabilities->cap[PIPE].value;
/* Factor 1.25 for IbP and 1.375 for I1B2b1P GOP structure */
if (inst->capabilities->cap[B_FRAME].value > 1)
vpp_cycles += (vpp_cycles / 4) + (vpp_cycles / 8);
else if (inst->capabilities->cap[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->cap[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);
/* increase vpp_cycles by 50% for preprocessing */
if (inst->capabilities->cap[REQUEST_PREPROCESS].value)
vpp_cycles = vpp_cycles + vpp_cycles / 2;
/* VSP */
/* bitrate is based on fps, scale it using operating rate */
operating_rate = inst->capabilities->cap[OPERATING_RATE].value >> 16;
if (operating_rate >
(inst->capabilities->cap[FRAME_RATE].value >> 16) &&
(inst->capabilities->cap[FRAME_RATE].value >> 16)) {
vsp_factor_num = operating_rate;
vsp_factor_den = inst->capabilities->cap[FRAME_RATE].value >> 16;
}
vsp_cycles = div_u64(((u64)inst->capabilities->cap[BIT_RATE].value *
vsp_factor_num), vsp_factor_den);
base_cycles = inst->capabilities->cap[MB_CYCLES_VSP].value;
if (inst->codec == MSM_VIDC_VP9) {
vsp_cycles = div_u64(vsp_cycles * 170, 100);
} else if (inst->capabilities->cap[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->cap[STAGE].value == MSM_VIDC_STAGE_1)
vsp_cycles = vsp_cycles * 3;
vsp_cycles += mbs_per_second * base_cycles;
} else if (inst->domain == MSM_VIDC_DECODER) {
/* VPP */
vpp_cycles = mbs_per_second * inst->capabilities->cap[MB_CYCLES_VPP].value /
inst->capabilities->cap[PIPE].value;
/* 21 / 20 is minimum overhead factor */
vpp_cycles += max(vpp_cycles / 20, fw_vpp_cycles);
if (inst->capabilities->cap[PIPE].value > 1) {
if (inst->codec == MSM_VIDC_AV1) {
/*
* Additional vpp_cycles are required for bitstreams with
* 128x128 superblock and non-recommended tile settings.
* recommended tiles: 1080P_V2XH1, UHD_V2X2, 8KUHD_V8X2
* non-recommended tiles: 1080P_V4XH2_V4X1, UHD_V8X4_V8X1,
* 8KUHD_V8X8_V8X1
*/
if (inst->capabilities->cap[SUPER_BLOCK].value)
vpp_cycles += div_u64(vpp_cycles * 1464, 1000);
else
vpp_cycles += div_u64(vpp_cycles * 410, 1000);
} else {
/* 1.059 is multi-pipe overhead */
vpp_cycles += div_u64(vpp_cycles * 59, 1000);
}
}
/* VSP */
if (inst->codec == MSM_VIDC_AV1) {
/*
* For AV1: Use VSP calculations from Kalama perf model.
* For legacy codecs, use vsp_cycles based on legacy MB_CYCLES_VSP.
*/
u32 decoder_vsp_fw_overhead = 105;
u32 fw_sw_vsp_offset = 1055;
u64 vsp_hw_min_frequency = 0;
u32 input_bitrate_mbps = 0;
u32 bitrate_2stage[2] = {130, 120};
u32 bitrate_1stage = 100;
u32 width, height;
u32 bitrate_entry, freq_entry, frequency_table_value;
struct allowed_clock_rates_table *allowed_clks_tbl;
struct v4l2_format *out_f = &inst->fmts[OUTPUT_PORT];
width = out_f->fmt.pix_mp.width;
height = out_f->fmt.pix_mp.height;
bitrate_entry = 1;
/* 8KUHD60, UHD240, 1080p960 */
if (width * height * fps >= 3840 * 2160 * 240)
bitrate_entry = 0;
freq_entry = bitrate_entry;
allowed_clks_tbl = core->dt->allowed_clks_tbl;
frequency_table_value = allowed_clks_tbl[freq_entry].clock_rate / 1000000;
input_bitrate_mbps = fps * data_size * 8 / (1024 * 1024);
vsp_hw_min_frequency = frequency_table_value * 1000 * input_bitrate_mbps;
if (inst->capabilities->cap[STAGE].value == MSM_VIDC_STAGE_2) {
vsp_hw_min_frequency +=
(bitrate_2stage[bitrate_entry] * fw_sw_vsp_offset - 1);
vsp_hw_min_frequency = div_u64(vsp_hw_min_frequency,
(bitrate_2stage[bitrate_entry] * fw_sw_vsp_offset));
/* VSP fw overhead 1.05 */
vsp_hw_min_frequency = div_u64(vsp_hw_min_frequency *
decoder_vsp_fw_overhead + 99, 100);
} else {
vsp_hw_min_frequency += (bitrate_1stage * fw_sw_vsp_offset - 1);
vsp_hw_min_frequency = div_u64(vsp_hw_min_frequency,
(bitrate_1stage * fw_sw_vsp_offset));
}
vsp_cycles = vsp_hw_min_frequency * 1000000;
} else {
base_cycles = inst->has_bframe ?
80 : inst->capabilities->cap[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->cap[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->cap[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->cap[STAGE].value ==
MSM_VIDC_STAGE_2 &&
inst->capabilities->cap[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);
if (inst->codec != MSM_VIDC_AV1) {
/*
* for non-AV1 codecs limit the frequency to NOM only
* index 0 is TURBO, index 1 is NOM clock rate
*/
if (core->dt->allowed_clks_tbl_size >= 2 &&
freq > core->dt->allowed_clks_tbl[1].clock_rate)
freq = core->dt->allowed_clks_tbl[1].clock_rate;
}
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 = (d->codec == MSM_VIDC_H264) ? true : false;
/* 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->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;
if (d->codec == MSM_VIDC_AV1) {
collocated_bytes_per_lcu = 4 * 512; /* lcu_size = 128 */
if (lcu_size == 32) {
collocated_bytes_per_lcu = 4 * 512 / (128 * 128 / 32 / 32);
} else if (lcu_size == 64) {
collocated_bytes_per_lcu = 4 * 512 / (128 * 128 / 64 / 64);
}
}
dpb_factor = FP(1, 50, 100);
dpb_write_factor = FP(1, 5, 100);
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)));
if (is_h264_category)
ddr.line_buffer_write = fp_div(ddr.line_buffer_read,FP_INT(2));
else
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,
vpss_preprocessing_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;
vpss_preprocessing_enabled = d->vpss_preprocessing_enabled;
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);
}
/* double ref_write */
if (vpss_preprocessing_enabled)
ddr.ref_write = ddr.ref_write * 2;
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;
/* double orig_read */
if (vpss_preprocessing_enabled)
ddr.orig_read = ddr.orig_read * 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},
{"VPSS preprocessing", "%d", vpss_preprocessing_enabled},
{"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_iris33(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;
}