mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
drm/amd/display: Move FPU Guards From DML To DC - Part 2
[Why] FPU guards (DC_FP_START/DC_FP_END) are required to wrap around code that can manipulates floats. To do this properly, the FPU guards must be used in a file that is not compiled as a FPU unit. If the guards are used in a file that is a FPU unit, other sections in the file that aren't guarded may be end up being compiled to use FPU operations. [How] Removed DC_FP_START and DC_FP_END. Reviewed-by: Dillon Varone <dillon.varone@amd.com> Signed-off-by: Rafal Ostrowski <rafal.ostrowski@amd.com> Signed-off-by: Alex Hung <alex.hung@amd.com> Signed-off-by: Chuanyu Tseng <Chuanyu.Tseng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
3539437f35
commit
4bb2f0721e
|
|
@ -53,25 +53,29 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/src/inc
|
|||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/inc
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/
|
||||
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_util.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper_fpu.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_utils.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_policy.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_translation_helper.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_mall_phantom.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml_display_rq_dlg_calc.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_dc_resource_mgmt.o := $(dml2_ccflags)
|
||||
# Add FPU flags to all dml2 files by default, remove NO_FPU flags.
|
||||
# FPU flags step 1: Find all .c files in dal/dc/dml2_0 and it's subfolders
|
||||
DML2_ABS_PATH := $(FULL_AMD_DISPLAY_PATH)/dc/dml2_0
|
||||
DML2_C_FILES := $(shell find $(DML2_ABS_PATH) -name '*.c' -type f)
|
||||
|
||||
# FPU flags step 2: Convert to .o and make paths relative to $(AMDDALPATH)/dc/dml2_0/
|
||||
DML2_RELATIVE_O_FILES := $(patsubst $(DML2_ABS_PATH)/%,dc/dml2_0/%,$(patsubst %.c,%.o,$(DML2_C_FILES)))
|
||||
|
||||
# FPU flags step 3: Apply FPU flags to all .o files from dal/dc/dml2_0 and it's subfolders
|
||||
$(foreach obj,$(DML2_RELATIVE_O_FILES),$(eval CFLAGS_$(AMDDALPATH)/$(obj) := $(dml2_ccflags)))
|
||||
$(foreach obj,$(DML2_RELATIVE_O_FILES),$(eval CFLAGS_REMOVE_$(AMDDALPATH)/$(obj) := $(dml2_rcflags)))
|
||||
|
||||
# FPU flags step 4: Replace CFLAGS per file for files with additional flags beyond dml2_ccflags and dml2_rcflags
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_ccflags) $(frame_warn_flag)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_ccflags) $(frame_warn_flag)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper.o := $(dml2_rcflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_wrapper.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/display_mode_util.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper_fpu.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_utils.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_policy.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_translation_helper.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_mall_phantom.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml_display_rq_dlg_calc.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_dc_resource_mgmt.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper.o := $(dml2_ccflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_wrapper.o := $(dml2_ccflags)
|
||||
|
||||
DML2 = display_mode_core.o display_mode_util.o dml2_wrapper_fpu.o dml2_wrapper.o \
|
||||
dml2_utils.o dml2_policy.o dml2_translation_helper.o dml2_dc_resource_mgmt.o dml2_mall_phantom.o \
|
||||
|
|
@ -81,42 +85,6 @@ AMD_DAL_DML2 = $(addprefix $(AMDDALPATH)/dc/dml2_0/,$(DML2))
|
|||
|
||||
AMD_DISPLAY_FILES += $(AMD_DAL_DML2)
|
||||
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_ccflags) $(frame_warn_flag)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_ccflags) $(frame_warn_flag)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_standalone_libraries/lib_float_math.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_translation_helper.o := $(dml2_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_utils.o := $(dml2_ccflags)
|
||||
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_standalone_libraries/lib_float_math.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_translation_helper.o := $(dml2_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_utils.o := $(dml2_rcflags)
|
||||
|
||||
DML21 := src/dml2_top/dml2_top_interfaces.o
|
||||
DML21 += src/dml2_top/dml2_top_soc15.o
|
||||
DML21 += src/dml2_core/dml2_core_dcn4.o
|
||||
|
|
@ -134,6 +102,7 @@ DML21 += src/dml2_pmo/dml2_pmo_dcn4_fams2.o
|
|||
DML21 += src/dml2_standalone_libraries/lib_float_math.o
|
||||
DML21 += dml21_translation_helper.o
|
||||
DML21 += dml21_wrapper.o
|
||||
DML21 += dml21_wrapper_fpu.o
|
||||
DML21 += dml21_utils.o
|
||||
|
||||
AMD_DAL_DML21 = $(addprefix $(AMDDALPATH)/dc/dml2_0/dml21/,$(DML21))
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@
|
|||
#include "dml21_utils.h"
|
||||
#include "dml21_translation_helper.h"
|
||||
#include "dml2_dc_resource_mgmt.h"
|
||||
#include "dml2_wrapper.h"
|
||||
#include "dml2_wrapper_fpu.h"
|
||||
#include "dml21_wrapper.h"
|
||||
#include "dml21_wrapper_fpu.h"
|
||||
#include "dc_fpu.h"
|
||||
|
||||
#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED)
|
||||
|
|
@ -40,44 +44,11 @@ static bool dml21_allocate_memory(struct dml2_context **dml_ctx)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void dml21_populate_configuration_options(const struct dc *in_dc,
|
||||
struct dml2_context *dml_ctx,
|
||||
const struct dml2_configuration_options *config)
|
||||
{
|
||||
dml_ctx->config = *config;
|
||||
|
||||
/* UCLK P-State options */
|
||||
if (in_dc->debug.dml21_force_pstate_method) {
|
||||
dml_ctx->config.pmo.force_pstate_method_enable = true;
|
||||
for (int i = 0; i < MAX_PIPES; i++)
|
||||
dml_ctx->config.pmo.force_pstate_method_values[i] = in_dc->debug.dml21_force_pstate_method_values[i];
|
||||
} else {
|
||||
dml_ctx->config.pmo.force_pstate_method_enable = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void dml21_init(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config)
|
||||
{
|
||||
|
||||
dml_ctx->architecture = dml2_architecture_21;
|
||||
|
||||
dml21_populate_configuration_options(in_dc, dml_ctx, config);
|
||||
|
||||
DC_FP_START();
|
||||
|
||||
dml21_populate_dml_init_params(&dml_ctx->v21.dml_init, &dml_ctx->config, in_dc);
|
||||
|
||||
dml2_initialize_instance(&dml_ctx->v21.dml_init);
|
||||
|
||||
DC_FP_END();
|
||||
}
|
||||
|
||||
bool dml21_create(const struct dc *in_dc, struct dml2_context **dml_ctx, const struct dml2_configuration_options *config)
|
||||
{
|
||||
/* Allocate memory for initializing DML21 instance */
|
||||
if (!dml21_allocate_memory(dml_ctx)) {
|
||||
if (!dml21_allocate_memory(dml_ctx))
|
||||
return false;
|
||||
}
|
||||
|
||||
dml21_init(in_dc, *dml_ctx, config);
|
||||
|
||||
|
|
@ -90,337 +61,6 @@ void dml21_destroy(struct dml2_context *dml2)
|
|||
vfree(dml2->v21.mode_programming.programming);
|
||||
}
|
||||
|
||||
static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *context, struct resource_context *out_new_hw_state,
|
||||
struct dml2_context *in_ctx, unsigned int pipe_cnt)
|
||||
{
|
||||
unsigned int dml_prog_idx = 0, dc_pipe_index = 0, num_dpps_required = 0;
|
||||
struct dml2_per_plane_programming *pln_prog = NULL;
|
||||
struct dml2_per_stream_programming *stream_prog = NULL;
|
||||
struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
|
||||
struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
|
||||
int num_pipes;
|
||||
unsigned int dml_phantom_prog_idx;
|
||||
|
||||
context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
|
||||
|
||||
/* copy global DCHUBBUB arbiter registers */
|
||||
memcpy(&context->bw_ctx.bw.dcn.arb_regs, &in_ctx->v21.mode_programming.programming->global_regs.arb_regs, sizeof(struct dml2_display_arb_regs));
|
||||
|
||||
/* legacy only */
|
||||
context->bw_ctx.bw.dcn.compbuf_size_kb = (int)in_ctx->v21.mode_programming.programming->global_regs.arb_regs.compbuf_size * 64;
|
||||
|
||||
context->bw_ctx.bw.dcn.mall_ss_size_bytes = 0;
|
||||
context->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes = 0;
|
||||
context->bw_ctx.bw.dcn.mall_subvp_size_bytes = 0;
|
||||
|
||||
/* phantom's start after main planes */
|
||||
dml_phantom_prog_idx = in_ctx->v21.mode_programming.programming->display_config.num_planes;
|
||||
|
||||
for (dml_prog_idx = 0; dml_prog_idx < DML2_MAX_PLANES; dml_prog_idx++) {
|
||||
pln_prog = &in_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
|
||||
|
||||
if (!pln_prog->plane_descriptor)
|
||||
continue;
|
||||
|
||||
stream_prog = &in_ctx->v21.mode_programming.programming->stream_programming[pln_prog->plane_descriptor->stream_index];
|
||||
num_dpps_required = pln_prog->num_dpps_required;
|
||||
|
||||
if (num_dpps_required == 0) {
|
||||
continue;
|
||||
}
|
||||
num_pipes = dml21_find_dc_pipes_for_plane(dc, context, in_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
|
||||
|
||||
if (num_pipes <= 0)
|
||||
continue;
|
||||
|
||||
/* program each pipe */
|
||||
for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
|
||||
dml21_program_dc_pipe(in_ctx, context, dc_main_pipes[dc_pipe_index], pln_prog, stream_prog);
|
||||
|
||||
if (pln_prog->phantom_plane.valid && dc_phantom_pipes[dc_pipe_index]) {
|
||||
dml21_program_dc_pipe(in_ctx, context, dc_phantom_pipes[dc_pipe_index], pln_prog, stream_prog);
|
||||
}
|
||||
}
|
||||
|
||||
/* copy per plane mcache allocation */
|
||||
memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx], &pln_prog->mcache_allocation, sizeof(struct dml2_mcache_surface_allocation));
|
||||
if (pln_prog->phantom_plane.valid) {
|
||||
memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx],
|
||||
&pln_prog->phantom_plane.mcache_allocation,
|
||||
sizeof(struct dml2_mcache_surface_allocation));
|
||||
|
||||
dml_phantom_prog_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
/* assign global clocks */
|
||||
context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
|
||||
context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
|
||||
if (in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values > 1) {
|
||||
context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz =
|
||||
in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values] * 1000;
|
||||
} else {
|
||||
context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[0] * 1000;
|
||||
}
|
||||
|
||||
if (in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values > 1) {
|
||||
context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz =
|
||||
in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values] * 1000;
|
||||
} else {
|
||||
context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[0] * 1000;
|
||||
}
|
||||
|
||||
/* get global mall allocation */
|
||||
if (dc->res_pool->funcs->calculate_mall_ways_from_bytes) {
|
||||
context->bw_ctx.bw.dcn.clk.num_ways = dc->res_pool->funcs->calculate_mall_ways_from_bytes(dc, context->bw_ctx.bw.dcn.mall_subvp_size_bytes);
|
||||
} else {
|
||||
context->bw_ctx.bw.dcn.clk.num_ways = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void dml21_prepare_mcache_params(struct dml2_context *dml_ctx, struct dc_state *context, struct dc_mcache_params *mcache_params)
|
||||
{
|
||||
int dc_plane_idx = 0;
|
||||
int dml_prog_idx, stream_idx, plane_idx;
|
||||
struct dml2_per_plane_programming *pln_prog = NULL;
|
||||
|
||||
for (stream_idx = 0; stream_idx < context->stream_count; stream_idx++) {
|
||||
for (plane_idx = 0; plane_idx < context->stream_status[stream_idx].plane_count; plane_idx++) {
|
||||
dml_prog_idx = map_plane_to_dml21_display_cfg(dml_ctx, context->streams[stream_idx]->stream_id, context->stream_status[stream_idx].plane_states[plane_idx], context);
|
||||
if (dml_prog_idx == INVALID) {
|
||||
continue;
|
||||
}
|
||||
pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
|
||||
mcache_params[dc_plane_idx].valid = pln_prog->mcache_allocation.valid;
|
||||
mcache_params[dc_plane_idx].num_mcaches_plane0 = pln_prog->mcache_allocation.num_mcaches_plane0;
|
||||
mcache_params[dc_plane_idx].num_mcaches_plane1 = pln_prog->mcache_allocation.num_mcaches_plane1;
|
||||
mcache_params[dc_plane_idx].requires_dedicated_mall_mcache = pln_prog->mcache_allocation.requires_dedicated_mall_mcache;
|
||||
mcache_params[dc_plane_idx].last_slice_sharing.plane0_plane1 = pln_prog->mcache_allocation.last_slice_sharing.plane0_plane1;
|
||||
memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane0,
|
||||
pln_prog->mcache_allocation.mcache_x_offsets_plane0,
|
||||
sizeof(int) * (DML2_MAX_MCACHES + 1));
|
||||
memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane1,
|
||||
pln_prog->mcache_allocation.mcache_x_offsets_plane1,
|
||||
sizeof(int) * (DML2_MAX_MCACHES + 1));
|
||||
dc_plane_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
|
||||
{
|
||||
bool result = false;
|
||||
struct dml2_build_mode_programming_in_out *mode_programming = &dml_ctx->v21.mode_programming;
|
||||
struct dc_mcache_params mcache_params[MAX_PLANES] = {0};
|
||||
|
||||
memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
|
||||
memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
|
||||
memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params, 0, sizeof(struct dml2_core_mode_programming_in_out));
|
||||
|
||||
if (!context)
|
||||
return true;
|
||||
|
||||
if (context->stream_count == 0) {
|
||||
dml21_init_min_clocks_for_dc_state(dml_ctx, context);
|
||||
dml21_build_fams2_programming(in_dc, context, dml_ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* scrub phantom's from current dc_state */
|
||||
dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
|
||||
dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
|
||||
|
||||
/* Populate stream, plane mappings and other fields in display config. */
|
||||
result = dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
DC_FP_START();
|
||||
result = dml2_build_mode_programming(mode_programming);
|
||||
DC_FP_END();
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
/* Check and map HW resources */
|
||||
if (result && !dml_ctx->config.skip_hw_state_mapping) {
|
||||
dml21_map_hw_resources(dml_ctx);
|
||||
dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, in_dc->current_state);
|
||||
/* if subvp phantoms are present, expand them into dc context */
|
||||
dml21_handle_phantom_streams_planes(in_dc, context, dml_ctx);
|
||||
|
||||
if (in_dc->res_pool->funcs->program_mcache_pipe_config) {
|
||||
//Prepare mcache params for each plane based on mcache output from DML
|
||||
dml21_prepare_mcache_params(dml_ctx, context, mcache_params);
|
||||
|
||||
//populate mcache regs to each pipe
|
||||
dml_ctx->config.callbacks.allocate_mcache(context, mcache_params);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy DML CLK, WM and REG outputs to bandwidth context */
|
||||
if (result && !dml_ctx->config.skip_hw_state_mapping) {
|
||||
dml21_calculate_rq_and_dlg_params(in_dc, context, &context->res_ctx, dml_ctx, in_dc->res_pool->pipe_count);
|
||||
dml21_copy_clocks_to_dc_state(dml_ctx, context);
|
||||
dml21_extract_watermark_sets(in_dc, &context->bw_ctx.bw.dcn.watermarks, dml_ctx);
|
||||
dml21_build_fams2_programming(in_dc, context, dml_ctx);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
|
||||
{
|
||||
bool is_supported = false;
|
||||
struct dml2_initialize_instance_in_out *dml_init = &dml_ctx->v21.dml_init;
|
||||
struct dml2_check_mode_supported_in_out *mode_support = &dml_ctx->v21.mode_support;
|
||||
|
||||
memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
|
||||
memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
|
||||
memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.check_mode_supported_locals.mode_support_params, 0, sizeof(struct dml2_core_mode_support_in_out));
|
||||
|
||||
if (!context || context->stream_count == 0)
|
||||
return true;
|
||||
|
||||
/* Scrub phantom's from current dc_state */
|
||||
dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
|
||||
dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
|
||||
|
||||
mode_support->dml2_instance = dml_init->dml2_instance;
|
||||
dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
|
||||
dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming;
|
||||
DC_FP_START();
|
||||
is_supported = dml2_check_mode_supported(mode_support);
|
||||
DC_FP_END();
|
||||
if (!is_supported)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx,
|
||||
enum dc_validate_mode validate_mode)
|
||||
{
|
||||
bool out = false;
|
||||
|
||||
/* Use dml21_check_mode_support for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */
|
||||
if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
|
||||
out = dml21_check_mode_support(in_dc, context, dml_ctx);
|
||||
else
|
||||
out = dml21_mode_check_and_programming(in_dc, context, dml_ctx);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
|
||||
{
|
||||
unsigned int dml_prog_idx, dml_phantom_prog_idx, dc_pipe_index;
|
||||
int num_pipes;
|
||||
struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
|
||||
struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
|
||||
|
||||
struct dml2_per_plane_programming *pln_prog = NULL;
|
||||
struct dml2_plane_mcache_configuration_descriptor *mcache_config = NULL;
|
||||
struct prepare_mcache_programming_locals *l = &dml_ctx->v21.scratch.prepare_mcache_locals;
|
||||
|
||||
if (context->stream_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&l->build_mcache_programming_params, 0, sizeof(struct dml2_build_mcache_programming_in_out));
|
||||
l->build_mcache_programming_params.dml2_instance = dml_ctx->v21.dml_init.dml2_instance;
|
||||
|
||||
/* phantom's start after main planes */
|
||||
dml_phantom_prog_idx = dml_ctx->v21.mode_programming.programming->display_config.num_planes;
|
||||
|
||||
/* Build mcache programming parameters per plane per pipe */
|
||||
for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
|
||||
pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
|
||||
|
||||
mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_prog_idx];
|
||||
memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
|
||||
mcache_config->plane_descriptor = pln_prog->plane_descriptor;
|
||||
mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx];
|
||||
mcache_config->num_pipes = pln_prog->num_dpps_required;
|
||||
l->build_mcache_programming_params.num_configurations++;
|
||||
|
||||
if (pln_prog->num_dpps_required == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
|
||||
if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
|
||||
dc_main_pipes[0]->plane_state == NULL)
|
||||
continue;
|
||||
|
||||
/* get config for each pipe */
|
||||
for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
|
||||
ASSERT(dc_main_pipes[dc_pipe_index]);
|
||||
dml21_get_pipe_mcache_config(context, dc_main_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
|
||||
}
|
||||
|
||||
/* get config for each phantom pipe */
|
||||
if (pln_prog->phantom_plane.valid &&
|
||||
dc_phantom_pipes[0] &&
|
||||
dc_main_pipes[0]->stream &&
|
||||
dc_phantom_pipes[0]->plane_state) {
|
||||
mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_phantom_prog_idx];
|
||||
memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
|
||||
mcache_config->plane_descriptor = pln_prog->plane_descriptor;
|
||||
mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx];
|
||||
mcache_config->num_pipes = pln_prog->num_dpps_required;
|
||||
l->build_mcache_programming_params.num_configurations++;
|
||||
|
||||
for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
|
||||
ASSERT(dc_phantom_pipes[dc_pipe_index]);
|
||||
dml21_get_pipe_mcache_config(context, dc_phantom_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
|
||||
}
|
||||
|
||||
/* increment phantom index */
|
||||
dml_phantom_prog_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call to generate mcache programming per plane per pipe for the given display configuration */
|
||||
dml2_build_mcache_programming(&l->build_mcache_programming_params);
|
||||
|
||||
/* get per plane per pipe mcache programming */
|
||||
for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
|
||||
pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
|
||||
|
||||
num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
|
||||
if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
|
||||
dc_main_pipes[0]->plane_state == NULL)
|
||||
continue;
|
||||
|
||||
/* get config for each pipe */
|
||||
for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
|
||||
ASSERT(dc_main_pipes[dc_pipe_index]);
|
||||
if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index]) {
|
||||
memcpy(&dc_main_pipes[dc_pipe_index]->mcache_regs,
|
||||
l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index],
|
||||
sizeof(struct dml2_hubp_pipe_mcache_regs));
|
||||
}
|
||||
}
|
||||
|
||||
/* get config for each phantom pipe */
|
||||
if (pln_prog->phantom_plane.valid &&
|
||||
dc_phantom_pipes[0] &&
|
||||
dc_main_pipes[0]->stream &&
|
||||
dc_phantom_pipes[0]->plane_state) {
|
||||
for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
|
||||
ASSERT(dc_phantom_pipes[dc_pipe_index]);
|
||||
if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index]) {
|
||||
memcpy(&dc_phantom_pipes[dc_pipe_index]->mcache_regs,
|
||||
l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index],
|
||||
sizeof(struct dml2_hubp_pipe_mcache_regs));
|
||||
}
|
||||
}
|
||||
/* increment phantom index */
|
||||
dml_phantom_prog_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dml21_copy(struct dml2_context *dst_dml_ctx,
|
||||
struct dml2_context *src_dml_ctx)
|
||||
{
|
||||
|
|
@ -446,12 +86,8 @@ void dml21_copy(struct dml2_context *dst_dml_ctx,
|
|||
|
||||
dst_dml_ctx->v21.mode_programming.programming = dst_dml2_programming;
|
||||
|
||||
DC_FP_START();
|
||||
|
||||
/* need to initialize copied instance for internal references to be correct */
|
||||
dml2_initialize_instance(&dst_dml_ctx->v21.dml_init);
|
||||
|
||||
DC_FP_END();
|
||||
}
|
||||
|
||||
bool dml21_create_copy(struct dml2_context **dst_dml_ctx,
|
||||
|
|
@ -466,8 +102,3 @@ bool dml21_create_copy(struct dml2_context **dst_dml_ctx,
|
|||
return true;
|
||||
}
|
||||
|
||||
void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config)
|
||||
{
|
||||
dml21_init(in_dc, dml_ctx, config);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,36 +34,6 @@ void dml21_copy(struct dml2_context *dst_dml_ctx,
|
|||
struct dml2_context *src_dml_ctx);
|
||||
bool dml21_create_copy(struct dml2_context **dst_dml_ctx,
|
||||
struct dml2_context *src_dml_ctx);
|
||||
void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config);
|
||||
|
||||
/**
|
||||
* dml21_validate - Determines if a display configuration is supported or not.
|
||||
* @in_dc: dc.
|
||||
* @context: dc_state to be validated.
|
||||
* @dml_ctx: dml21 context.
|
||||
* @validate_mode: DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX
|
||||
* will not populate context.res_ctx.
|
||||
*
|
||||
* Based on fast_validate option internally would call:
|
||||
*
|
||||
* -dml21_mode_check_and_programming - for DC_VALIDATE_MODE_AND_PROGRAMMING option
|
||||
* Calculates if dc_state can be supported on the input display
|
||||
* configuration. If supported, generates the necessary HW
|
||||
* programming for the new dc_state.
|
||||
*
|
||||
* -dml21_check_mode_support - for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX option
|
||||
* Calculates if dc_state can be supported for the input display
|
||||
* config.
|
||||
*
|
||||
* Context: Two threads may not invoke this function concurrently unless they reference
|
||||
* separate dc_states for validation.
|
||||
* Return: True if mode is supported, false otherwise.
|
||||
*/
|
||||
bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx,
|
||||
enum dc_validate_mode validate_mode);
|
||||
|
||||
/* Prepare hubp mcache_regs for hubp mcache ID and split coordinate programming */
|
||||
void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx);
|
||||
|
||||
/* Structure for inputting external SOCBB and DCNIP values for tool based debugging. */
|
||||
struct socbb_ip_params_external {
|
||||
|
|
|
|||
381
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c
Normal file
381
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c
Normal file
|
|
@ -0,0 +1,381 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
#include "dml2_internal_types.h"
|
||||
#include "dml_top.h"
|
||||
#include "dml2_core_dcn4_calcs.h"
|
||||
#include "dml2_internal_shared_types.h"
|
||||
#include "dml21_utils.h"
|
||||
#include "dml21_translation_helper.h"
|
||||
#include "dml2_dc_resource_mgmt.h"
|
||||
#include "dml2_wrapper.h"
|
||||
#include "dml2_wrapper_fpu.h"
|
||||
#include "dml21_wrapper.h"
|
||||
#include "dml21_wrapper_fpu.h"
|
||||
|
||||
#define INVALID -1
|
||||
|
||||
static void dml21_populate_configuration_options(const struct dc *in_dc,
|
||||
struct dml2_context *dml_ctx,
|
||||
const struct dml2_configuration_options *config)
|
||||
{
|
||||
dml_ctx->config = *config;
|
||||
|
||||
/* UCLK P-State options */
|
||||
if (in_dc->debug.dml21_force_pstate_method) {
|
||||
dml_ctx->config.pmo.force_pstate_method_enable = true;
|
||||
for (int i = 0; i < MAX_PIPES; i++)
|
||||
dml_ctx->config.pmo.force_pstate_method_values[i] = in_dc->debug.dml21_force_pstate_method_values[i];
|
||||
} else {
|
||||
dml_ctx->config.pmo.force_pstate_method_enable = false;
|
||||
}
|
||||
}
|
||||
|
||||
void dml21_init(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config)
|
||||
{
|
||||
dml_ctx->architecture = dml2_architecture_21;
|
||||
|
||||
dml21_populate_configuration_options(in_dc, dml_ctx, config);
|
||||
|
||||
dml21_populate_dml_init_params(&dml_ctx->v21.dml_init, &dml_ctx->config, in_dc);
|
||||
|
||||
dml2_initialize_instance(&dml_ctx->v21.dml_init);
|
||||
}
|
||||
|
||||
void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config)
|
||||
{
|
||||
dml21_init(in_dc, dml_ctx, config);
|
||||
}
|
||||
|
||||
static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *context, struct resource_context *out_new_hw_state,
|
||||
struct dml2_context *in_ctx, unsigned int pipe_cnt)
|
||||
{
|
||||
unsigned int dml_prog_idx = 0, dc_pipe_index = 0, num_dpps_required = 0;
|
||||
struct dml2_per_plane_programming *pln_prog = NULL;
|
||||
struct dml2_per_stream_programming *stream_prog = NULL;
|
||||
struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
|
||||
struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
|
||||
int num_pipes;
|
||||
unsigned int dml_phantom_prog_idx;
|
||||
|
||||
context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
|
||||
|
||||
/* copy global DCHUBBUB arbiter registers */
|
||||
memcpy(&context->bw_ctx.bw.dcn.arb_regs, &in_ctx->v21.mode_programming.programming->global_regs.arb_regs, sizeof(struct dml2_display_arb_regs));
|
||||
|
||||
/* legacy only */
|
||||
context->bw_ctx.bw.dcn.compbuf_size_kb = (int)in_ctx->v21.mode_programming.programming->global_regs.arb_regs.compbuf_size * 64;
|
||||
|
||||
context->bw_ctx.bw.dcn.mall_ss_size_bytes = 0;
|
||||
context->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes = 0;
|
||||
context->bw_ctx.bw.dcn.mall_subvp_size_bytes = 0;
|
||||
|
||||
/* phantom's start after main planes */
|
||||
dml_phantom_prog_idx = in_ctx->v21.mode_programming.programming->display_config.num_planes;
|
||||
|
||||
for (dml_prog_idx = 0; dml_prog_idx < DML2_MAX_PLANES; dml_prog_idx++) {
|
||||
pln_prog = &in_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
|
||||
|
||||
if (!pln_prog->plane_descriptor)
|
||||
continue;
|
||||
|
||||
stream_prog = &in_ctx->v21.mode_programming.programming->stream_programming[pln_prog->plane_descriptor->stream_index];
|
||||
num_dpps_required = pln_prog->num_dpps_required;
|
||||
|
||||
if (num_dpps_required == 0) {
|
||||
continue;
|
||||
}
|
||||
num_pipes = dml21_find_dc_pipes_for_plane(dc, context, in_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
|
||||
|
||||
if (num_pipes <= 0)
|
||||
continue;
|
||||
|
||||
/* program each pipe */
|
||||
for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
|
||||
dml21_program_dc_pipe(in_ctx, context, dc_main_pipes[dc_pipe_index], pln_prog, stream_prog);
|
||||
|
||||
if (pln_prog->phantom_plane.valid && dc_phantom_pipes[dc_pipe_index]) {
|
||||
dml21_program_dc_pipe(in_ctx, context, dc_phantom_pipes[dc_pipe_index], pln_prog, stream_prog);
|
||||
}
|
||||
}
|
||||
|
||||
/* copy per plane mcache allocation */
|
||||
memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx], &pln_prog->mcache_allocation, sizeof(struct dml2_mcache_surface_allocation));
|
||||
if (pln_prog->phantom_plane.valid) {
|
||||
memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx],
|
||||
&pln_prog->phantom_plane.mcache_allocation,
|
||||
sizeof(struct dml2_mcache_surface_allocation));
|
||||
|
||||
dml_phantom_prog_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
/* assign global clocks */
|
||||
context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
|
||||
context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
|
||||
if (in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values > 1) {
|
||||
context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz =
|
||||
in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values] * 1000;
|
||||
} else {
|
||||
context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[0] * 1000;
|
||||
}
|
||||
|
||||
if (in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values > 1) {
|
||||
context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz =
|
||||
in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values] * 1000;
|
||||
} else {
|
||||
context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[0] * 1000;
|
||||
}
|
||||
|
||||
/* get global mall allocation */
|
||||
if (dc->res_pool->funcs->calculate_mall_ways_from_bytes) {
|
||||
context->bw_ctx.bw.dcn.clk.num_ways = dc->res_pool->funcs->calculate_mall_ways_from_bytes(dc, context->bw_ctx.bw.dcn.mall_subvp_size_bytes);
|
||||
} else {
|
||||
context->bw_ctx.bw.dcn.clk.num_ways = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void dml21_prepare_mcache_params(struct dml2_context *dml_ctx, struct dc_state *context, struct dc_mcache_params *mcache_params)
|
||||
{
|
||||
int dc_plane_idx = 0;
|
||||
int dml_prog_idx, stream_idx, plane_idx;
|
||||
struct dml2_per_plane_programming *pln_prog = NULL;
|
||||
|
||||
for (stream_idx = 0; stream_idx < context->stream_count; stream_idx++) {
|
||||
for (plane_idx = 0; plane_idx < context->stream_status[stream_idx].plane_count; plane_idx++) {
|
||||
dml_prog_idx = map_plane_to_dml21_display_cfg(dml_ctx, context->streams[stream_idx]->stream_id, context->stream_status[stream_idx].plane_states[plane_idx], context);
|
||||
if (dml_prog_idx == INVALID) {
|
||||
continue;
|
||||
}
|
||||
pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
|
||||
mcache_params[dc_plane_idx].valid = pln_prog->mcache_allocation.valid;
|
||||
mcache_params[dc_plane_idx].num_mcaches_plane0 = pln_prog->mcache_allocation.num_mcaches_plane0;
|
||||
mcache_params[dc_plane_idx].num_mcaches_plane1 = pln_prog->mcache_allocation.num_mcaches_plane1;
|
||||
mcache_params[dc_plane_idx].requires_dedicated_mall_mcache = pln_prog->mcache_allocation.requires_dedicated_mall_mcache;
|
||||
mcache_params[dc_plane_idx].last_slice_sharing.plane0_plane1 = pln_prog->mcache_allocation.last_slice_sharing.plane0_plane1;
|
||||
memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane0,
|
||||
pln_prog->mcache_allocation.mcache_x_offsets_plane0,
|
||||
sizeof(int) * (DML2_MAX_MCACHES + 1));
|
||||
memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane1,
|
||||
pln_prog->mcache_allocation.mcache_x_offsets_plane1,
|
||||
sizeof(int) * (DML2_MAX_MCACHES + 1));
|
||||
dc_plane_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
|
||||
{
|
||||
bool is_supported = false;
|
||||
struct dml2_initialize_instance_in_out *dml_init = &dml_ctx->v21.dml_init;
|
||||
struct dml2_check_mode_supported_in_out *mode_support = &dml_ctx->v21.mode_support;
|
||||
|
||||
memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
|
||||
memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
|
||||
memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.check_mode_supported_locals.mode_support_params, 0, sizeof(struct dml2_core_mode_support_in_out));
|
||||
|
||||
if (!context || context->stream_count == 0)
|
||||
return true;
|
||||
|
||||
/* Scrub phantom's from current dc_state */
|
||||
dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
|
||||
dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
|
||||
|
||||
mode_support->dml2_instance = dml_init->dml2_instance;
|
||||
dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
|
||||
dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming;
|
||||
|
||||
is_supported = dml2_check_mode_supported(mode_support);
|
||||
|
||||
if (!is_supported)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
|
||||
{
|
||||
bool result = false;
|
||||
struct dml2_build_mode_programming_in_out *mode_programming = &dml_ctx->v21.mode_programming;
|
||||
struct dc_mcache_params mcache_params[MAX_PLANES] = {0};
|
||||
|
||||
memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
|
||||
memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
|
||||
memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params, 0, sizeof(struct dml2_core_mode_programming_in_out));
|
||||
|
||||
if (!context)
|
||||
return true;
|
||||
|
||||
if (context->stream_count == 0) {
|
||||
dml21_init_min_clocks_for_dc_state(dml_ctx, context);
|
||||
dml21_build_fams2_programming(in_dc, context, dml_ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* scrub phantom's from current dc_state */
|
||||
dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
|
||||
dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
|
||||
|
||||
/* Populate stream, plane mappings and other fields in display config. */
|
||||
result = dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
result = dml2_build_mode_programming(mode_programming);
|
||||
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
/* Check and map HW resources */
|
||||
if (result && !dml_ctx->config.skip_hw_state_mapping) {
|
||||
dml21_map_hw_resources(dml_ctx);
|
||||
dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, in_dc->current_state);
|
||||
/* if subvp phantoms are present, expand them into dc context */
|
||||
dml21_handle_phantom_streams_planes(in_dc, context, dml_ctx);
|
||||
|
||||
if (in_dc->res_pool->funcs->program_mcache_pipe_config) {
|
||||
//Prepare mcache params for each plane based on mcache output from DML
|
||||
dml21_prepare_mcache_params(dml_ctx, context, mcache_params);
|
||||
|
||||
//populate mcache regs to each pipe
|
||||
dml_ctx->config.callbacks.allocate_mcache(context, mcache_params);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy DML CLK, WM and REG outputs to bandwidth context */
|
||||
if (result && !dml_ctx->config.skip_hw_state_mapping) {
|
||||
dml21_calculate_rq_and_dlg_params(in_dc, context, &context->res_ctx, dml_ctx, in_dc->res_pool->pipe_count);
|
||||
dml21_copy_clocks_to_dc_state(dml_ctx, context);
|
||||
dml21_extract_watermark_sets(in_dc, &context->bw_ctx.bw.dcn.watermarks, dml_ctx);
|
||||
dml21_build_fams2_programming(in_dc, context, dml_ctx);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx,
|
||||
enum dc_validate_mode validate_mode)
|
||||
{
|
||||
bool out = false;
|
||||
|
||||
/* Use dml21_check_mode_support for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */
|
||||
if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
|
||||
out = dml21_check_mode_support(in_dc, context, dml_ctx);
|
||||
else
|
||||
out = dml21_mode_check_and_programming(in_dc, context, dml_ctx);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
|
||||
{
|
||||
unsigned int dml_prog_idx, dml_phantom_prog_idx, dc_pipe_index;
|
||||
int num_pipes;
|
||||
struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
|
||||
struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
|
||||
|
||||
struct dml2_per_plane_programming *pln_prog = NULL;
|
||||
struct dml2_plane_mcache_configuration_descriptor *mcache_config = NULL;
|
||||
struct prepare_mcache_programming_locals *l = &dml_ctx->v21.scratch.prepare_mcache_locals;
|
||||
|
||||
if (context->stream_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&l->build_mcache_programming_params, 0, sizeof(struct dml2_build_mcache_programming_in_out));
|
||||
l->build_mcache_programming_params.dml2_instance = dml_ctx->v21.dml_init.dml2_instance;
|
||||
|
||||
/* phantom's start after main planes */
|
||||
dml_phantom_prog_idx = dml_ctx->v21.mode_programming.programming->display_config.num_planes;
|
||||
|
||||
/* Build mcache programming parameters per plane per pipe */
|
||||
for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
|
||||
pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
|
||||
|
||||
mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_prog_idx];
|
||||
memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
|
||||
mcache_config->plane_descriptor = pln_prog->plane_descriptor;
|
||||
mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx];
|
||||
mcache_config->num_pipes = pln_prog->num_dpps_required;
|
||||
l->build_mcache_programming_params.num_configurations++;
|
||||
|
||||
if (pln_prog->num_dpps_required == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
|
||||
if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
|
||||
dc_main_pipes[0]->plane_state == NULL)
|
||||
continue;
|
||||
|
||||
/* get config for each pipe */
|
||||
for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
|
||||
ASSERT(dc_main_pipes[dc_pipe_index]);
|
||||
dml21_get_pipe_mcache_config(context, dc_main_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
|
||||
}
|
||||
|
||||
/* get config for each phantom pipe */
|
||||
if (pln_prog->phantom_plane.valid &&
|
||||
dc_phantom_pipes[0] &&
|
||||
dc_main_pipes[0]->stream &&
|
||||
dc_phantom_pipes[0]->plane_state) {
|
||||
mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_phantom_prog_idx];
|
||||
memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
|
||||
mcache_config->plane_descriptor = pln_prog->plane_descriptor;
|
||||
mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx];
|
||||
mcache_config->num_pipes = pln_prog->num_dpps_required;
|
||||
l->build_mcache_programming_params.num_configurations++;
|
||||
|
||||
for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
|
||||
ASSERT(dc_phantom_pipes[dc_pipe_index]);
|
||||
dml21_get_pipe_mcache_config(context, dc_phantom_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
|
||||
}
|
||||
|
||||
/* increment phantom index */
|
||||
dml_phantom_prog_idx++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call to generate mcache programming per plane per pipe for the given display configuration */
|
||||
dml2_build_mcache_programming(&l->build_mcache_programming_params);
|
||||
|
||||
/* get per plane per pipe mcache programming */
|
||||
for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
|
||||
pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
|
||||
|
||||
num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
|
||||
if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
|
||||
dc_main_pipes[0]->plane_state == NULL)
|
||||
continue;
|
||||
|
||||
/* get config for each pipe */
|
||||
for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
|
||||
ASSERT(dc_main_pipes[dc_pipe_index]);
|
||||
if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index]) {
|
||||
memcpy(&dc_main_pipes[dc_pipe_index]->mcache_regs,
|
||||
l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index],
|
||||
sizeof(struct dml2_hubp_pipe_mcache_regs));
|
||||
}
|
||||
}
|
||||
|
||||
/* get config for each phantom pipe */
|
||||
if (pln_prog->phantom_plane.valid &&
|
||||
dc_phantom_pipes[0] &&
|
||||
dc_main_pipes[0]->stream &&
|
||||
dc_phantom_pipes[0]->plane_state) {
|
||||
for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
|
||||
ASSERT(dc_phantom_pipes[dc_pipe_index]);
|
||||
if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index]) {
|
||||
memcpy(&dc_phantom_pipes[dc_pipe_index]->mcache_regs,
|
||||
l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index],
|
||||
sizeof(struct dml2_hubp_pipe_mcache_regs));
|
||||
}
|
||||
}
|
||||
/* increment phantom index */
|
||||
dml_phantom_prog_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright 2024 Advanced Micro Devices, Inc.
|
||||
|
||||
#ifndef _DML21_WRAPPER_FPU_H_
|
||||
#define _DML21_WRAPPER_FPU_H_
|
||||
|
||||
#include "os_types.h"
|
||||
#include "dml_top_soc_parameter_types.h"
|
||||
#include "dml_top_display_cfg_types.h"
|
||||
|
||||
struct dc;
|
||||
struct dc_state;
|
||||
struct dml2_configuration_options;
|
||||
struct dml2_context;
|
||||
enum dc_validate_mode;
|
||||
|
||||
/**
|
||||
* dml21_init - Initialize DML21 context
|
||||
* @in_dc: dc.
|
||||
* @dml_ctx: DML21 context to initialize.
|
||||
* @config: dml21 configuration options.
|
||||
*
|
||||
* Performs FPU-requiring initialization. Must be called with FPU protection.
|
||||
*/
|
||||
void dml21_init(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config);
|
||||
|
||||
/**
|
||||
* dml21_validate - Determines if a display configuration is supported or not.
|
||||
* @in_dc: dc.
|
||||
* @context: dc_state to be validated.
|
||||
* @dml_ctx: dml21 context.
|
||||
* @validate_mode: DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX
|
||||
* will not populate context.res_ctx.
|
||||
*
|
||||
* Based on fast_validate option internally would call:
|
||||
*
|
||||
* -dml21_mode_check_and_programming - for DC_VALIDATE_MODE_AND_PROGRAMMING option
|
||||
* Calculates if dc_state can be supported on the input display
|
||||
* configuration. If supported, generates the necessary HW
|
||||
* programming for the new dc_state.
|
||||
*
|
||||
* -dml21_check_mode_support - for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX option
|
||||
* Calculates if dc_state can be supported for the input display
|
||||
* config.
|
||||
*
|
||||
* Context: Two threads may not invoke this function concurrently unless they reference
|
||||
* separate dc_states for validation.
|
||||
* Return: True if mode is supported, false otherwise.
|
||||
*/
|
||||
|
||||
void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx,
|
||||
const struct dml2_configuration_options *config);
|
||||
bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx,
|
||||
enum dc_validate_mode validate_mode);
|
||||
|
||||
/* Prepare hubp mcache_regs for hubp mcache ID and split coordinate programming */
|
||||
void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx);
|
||||
|
||||
#endif /* _DML21_WRAPPER_FPU_H_ */
|
||||
|
|
@ -6,7 +6,20 @@
|
|||
*/
|
||||
|
||||
#include "dml2_internal_types.h"
|
||||
#include "dml2_wrapper.h"
|
||||
#include "dml2_wrapper_fpu.h"
|
||||
#include "dml21_wrapper.h"
|
||||
#include "dml21_wrapper_fpu.h"
|
||||
|
||||
#include "dc_fpu.h"
|
||||
|
||||
struct dml2_context *dml2_allocate_memory(void)
|
||||
{
|
||||
struct dml2_context *dml2;
|
||||
|
||||
DC_RUN_WITH_PREEMPTION_ENABLED(dml2 = vzalloc(sizeof(struct dml2_context)));
|
||||
return dml2;
|
||||
}
|
||||
|
||||
bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2,
|
||||
enum dc_validate_mode validate_mode)
|
||||
|
|
@ -23,16 +36,12 @@ bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2
|
|||
return out;
|
||||
}
|
||||
|
||||
DC_FP_START();
|
||||
|
||||
/* Use dml_validate_only for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */
|
||||
if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
|
||||
out = dml2_validate_only(context, validate_mode);
|
||||
else
|
||||
out = dml2_validate_and_build_resource(in_dc, context, validate_mode);
|
||||
|
||||
DC_FP_END();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
@ -70,15 +79,11 @@ static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_op
|
|||
break;
|
||||
}
|
||||
|
||||
DC_FP_START();
|
||||
|
||||
initialize_dml2_ip_params(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.ip);
|
||||
|
||||
initialize_dml2_soc_bbox(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.soc);
|
||||
|
||||
initialize_dml2_soc_states(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.soc, &(*dml2)->v20.dml_core_ctx.states);
|
||||
|
||||
DC_FP_END();
|
||||
}
|
||||
|
||||
bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2)
|
||||
|
|
|
|||
|
|
@ -31,8 +31,10 @@
|
|||
#include "dml2_translation_helper.h"
|
||||
#include "dml2_mall_phantom.h"
|
||||
#include "dml2_dc_resource_mgmt.h"
|
||||
#include "dml21_wrapper.h"
|
||||
#include "dml2_wrapper.h"
|
||||
#include "dml2_wrapper_fpu.h"
|
||||
#include "dml21_wrapper.h"
|
||||
#include "dml21_wrapper_fpu.h"
|
||||
|
||||
void initialize_dml2_ip_params(struct dml2_context *dml2, const struct dc *in_dc, struct ip_params_st *out)
|
||||
{
|
||||
|
|
@ -546,11 +548,6 @@ void dml2_apply_debug_options(const struct dc *dc, struct dml2_context *dml2)
|
|||
}
|
||||
}
|
||||
|
||||
inline struct dml2_context *dml2_allocate_memory(void)
|
||||
{
|
||||
return (struct dml2_context *) vzalloc(sizeof(struct dml2_context));
|
||||
}
|
||||
|
||||
void dml2_destroy(struct dml2_context *dml2)
|
||||
{
|
||||
if (!dml2)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user