]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/amd/display: Add DML support for dcn42
authorRoman Li <Roman.Li@amd.com>
Tue, 3 Mar 2026 17:00:55 +0000 (12:00 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 11 Mar 2026 17:58:06 +0000 (13:58 -0400)
DML support for DCN 4.2

Acked-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: Roman Li <Roman.Li@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
13 files changed:
drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.h
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.h
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c
drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c

index 30cfc0848792e0f871b766025a42a22c07da7a33..70d9f2cd0b60180e1b4c419d85593f1f38cbef93 100644 (file)
@@ -90,6 +90,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.o := $(dml2
 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)
@@ -107,6 +108,7 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.o := $(d
 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)
@@ -124,6 +126,7 @@ DML21 += src/dml2_core/dml2_core_dcn4_calcs.o
 DML21 += src/dml2_dpmm/dml2_dpmm_dcn4.o
 DML21 += src/dml2_dpmm/dml2_dpmm_factory.o
 DML21 += src/dml2_mcg/dml2_mcg_dcn4.o
+DML21 += src/dml2_mcg/dml2_mcg_dcn42.o
 DML21 += src/dml2_mcg/dml2_mcg_factory.o
 DML21 += src/dml2_pmo/dml2_pmo_dcn3.o
 DML21 += src/dml2_pmo/dml2_pmo_factory.o
index cd12b7a6da6577a4f9c6152940c5c539da4dbe8d..6cc03391fff6f690a6d19ed1f927b4efe0cc84ac 100644 (file)
@@ -45,6 +45,9 @@ static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(enum dce_versi
        case DCN_VERSION_4_01:
                project_id = dml2_project_dcn4x_stage2_auto_drr_svp;
                break;
+       case DCN_VERSION_4_2:
+               project_id = dml2_project_dcn42;
+               break;
        default:
                project_id = dml2_project_invalid;
                DC_ERR("unsupported dcn version for DML21!");
@@ -615,6 +618,13 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm
                case DC_CM2_GPU_MEM_SIZE_171717:
                        plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube;
                        break;
+               case DC_CM2_GPU_MEM_SIZE_333333:
+                       plane->tdlut.tdlut_width_mode = dml2_tdlut_width_33_cube;
+                       break;
+               // handling when use case and HW support available
+               case DC_CM2_GPU_MEM_SIZE_454545:
+               case DC_CM2_GPU_MEM_SIZE_656565:
+                       break;
                case DC_CM2_GPU_MEM_SIZE_TRANSFORMED:
                default:
                        //plane->tdlut.tdlut_width_mode = dml2_tdlut_width_flatten; // dml2_tdlut_width_flatten undefined
@@ -824,6 +834,9 @@ void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state
        context->bw_ctx.bw.dcn.clk.subvp_prefetch_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.fclk_khz;
        context->bw_ctx.bw.dcn.clk.stutter_efficiency.base_efficiency = in_ctx->v21.mode_programming.programming->stutter.base_percent_efficiency;
        context->bw_ctx.bw.dcn.clk.stutter_efficiency.low_power_efficiency = in_ctx->v21.mode_programming.programming->stutter.low_power_percent_efficiency;
+       context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_efficiency = in_ctx->v21.mode_programming.programming->informative.power_management.z8.stutter_efficiency;
+       context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_period = in_ctx->v21.mode_programming.programming->informative.power_management.z8.stutter_period;
+       context->bw_ctx.bw.dcn.clk.zstate_support = in_ctx->v21.mode_programming.programming->z8_stutter.supported_in_blank; /*ignore meets_eco since it is not used*/
 }
 
 static struct dml2_dchub_watermark_regs *wm_set_index_to_dc_wm_set(union dcn_watermark_set *watermarks, const enum dml2_dchub_watermark_reg_set_index wm_index)
index 943fd3f040c3ae678264fe4f6630c91fb9baa017..c854515b49a32b57a6ff36ebdaebf4e9f07c38b8 100644 (file)
@@ -19,6 +19,7 @@ enum dml2_project_id {
        dml2_project_dcn4x_stage1,
        dml2_project_dcn4x_stage2,
        dml2_project_dcn4x_stage2_auto_drr_svp,
+       dml2_project_dcn42,
 };
 
 enum dml2_pstate_change_support {
index eba948e187c1163648527fbfd1db261d0d1c5e93..608b4a305c656ef6ef229ef6aeef80ff546d2e9d 100644 (file)
@@ -78,6 +78,86 @@ struct dml2_core_ip_params core_dcn4_ip_caps_base = {
        .subvp_swath_height_margin_lines = 16,
 };
 
+struct dml2_core_ip_params core_dcn42_ip_caps_base = {
+       .vblank_nom_default_us = 668,
+       .remote_iommu_outstanding_translations = 256,
+       .rob_buffer_size_kbytes = 64,
+       .config_return_buffer_size_in_kbytes = 1792,
+       .config_return_buffer_segment_size_in_kbytes = 64,
+       .compressed_buffer_segment_size_in_kbytes = 64,
+       .dpte_buffer_size_in_pte_reqs_luma = 68,
+       .dpte_buffer_size_in_pte_reqs_chroma = 36,
+       .pixel_chunk_size_kbytes = 8,
+       .alpha_pixel_chunk_size_kbytes = 4,
+       .min_pixel_chunk_size_bytes = 1024,
+       .writeback_chunk_size_kbytes = 8,
+       .line_buffer_size_bits = 1171920,
+       .max_line_buffer_lines = 32,
+       .writeback_interface_buffer_size_kbytes = 90,
+
+       //Number of pipes after DCN Pipe harvesting
+       .max_num_dpp = 4,
+       .max_num_otg = 4,
+       .max_num_opp = 4,
+       .max_num_wb = 1,
+       .max_dchub_pscl_bw_pix_per_clk = 4,
+       .max_pscl_lb_bw_pix_per_clk = 2,
+       .max_lb_vscl_bw_pix_per_clk = 4,
+       .max_vscl_hscl_bw_pix_per_clk = 4,
+       .max_hscl_ratio = 6,
+       .max_vscl_ratio = 6,
+       .max_hscl_taps = 8,
+       .max_vscl_taps = 8,
+       .dispclk_ramp_margin_percent = 1,
+       .dppclk_delay_subtotal = 47,
+       .dppclk_delay_scl = 50,
+       .dppclk_delay_scl_lb_only = 16,
+       .dppclk_delay_cnvc_formatter = 28,
+       .dppclk_delay_cnvc_cursor = 6,
+       .cursor_buffer_size = 42,
+       .cursor_chunk_size = 2,
+       .dispclk_delay_subtotal = 125,
+       .max_inter_dcn_tile_repeaters = 8,
+       .writeback_max_hscl_ratio = 1,
+       .writeback_max_vscl_ratio = 1,
+       .writeback_min_hscl_ratio = 1,
+       .writeback_min_vscl_ratio = 1,
+       .writeback_max_hscl_taps = 1,
+       .writeback_max_vscl_taps = 1,
+       .writeback_line_buffer_buffer_size = 0,
+       .num_dsc = 4,
+       .maximum_dsc_bits_per_component = 12,
+       .maximum_pixels_per_line_per_dsc_unit = 5760,
+       .dsc422_native_support = true,
+       .dcc_supported = true,
+       .ptoi_supported = false,
+
+       .cursor_64bpp_support = true,
+       .dynamic_metadata_vm_enabled = false,
+
+       .max_num_hdmi_frl_outputs = 0,
+       .max_num_dp2p0_outputs = 2,
+       .max_num_dp2p0_streams = 4,
+       .imall_supported = 1,
+       .max_flip_time_us = 110,
+       .max_flip_time_lines = 50,
+       .words_per_channel = 16,
+
+       .subvp_fw_processing_delay_us = 15,
+       .subvp_pstate_allow_width_us = 20,
+       .subvp_swath_height_margin_lines = 16,
+
+       .dcn_mrq_present = 1,
+       .zero_size_buffer_entries = 512,
+       .compbuf_reserved_space_zs = 64,
+       .dcc_meta_buffer_size_bytes = 6272,
+       .meta_chunk_size_kbytes = 2,
+       .min_meta_chunk_size_bytes = 256,
+
+       .dchub_arb_to_ret_delay = 102,
+       .hostvm_mode = 1,
+};
+
 static void patch_ip_caps_with_explicit_ip_params(struct dml2_ip_capabilities *ip_caps, const struct dml2_core_ip_params *ip_params)
 {
        ip_caps->pipe_count = ip_params->max_num_dpp;
@@ -153,6 +233,37 @@ bool core_dcn4_initialize(struct dml2_core_initialize_in_out *in_out)
        return true;
 }
 
+bool core_dcn42_initialize(struct dml2_core_initialize_in_out *in_out)
+{
+       struct dml2_core_instance *core = in_out->instance;
+
+       if (!in_out->minimum_clock_table)
+               return false;
+       else
+               core->minimum_clock_table = in_out->minimum_clock_table;
+
+       if (in_out->explicit_ip_bb && in_out->explicit_ip_bb_size > 0) {
+               memcpy(&core->clean_me_up.mode_lib.ip, in_out->explicit_ip_bb, in_out->explicit_ip_bb_size);
+
+               // FIXME_STAGE2:
+               // DV still uses stage1 ip_param_st for each variant, need to patch the ip_caps with ip_param info
+               // Should move DV to use ip_caps but need move more overrides to ip_caps
+               patch_ip_caps_with_explicit_ip_params(in_out->ip_caps, in_out->explicit_ip_bb);
+               core->clean_me_up.mode_lib.ip.subvp_pstate_allow_width_us = core_dcn4_ip_caps_base.subvp_pstate_allow_width_us;
+               core->clean_me_up.mode_lib.ip.subvp_fw_processing_delay_us = core_dcn4_ip_caps_base.subvp_pstate_allow_width_us;
+               core->clean_me_up.mode_lib.ip.subvp_swath_height_margin_lines = core_dcn4_ip_caps_base.subvp_swath_height_margin_lines;
+       } else {
+               memcpy(&core->clean_me_up.mode_lib.ip, &core_dcn42_ip_caps_base, sizeof(struct dml2_core_ip_params));
+               patch_ip_params_with_ip_caps(&core->clean_me_up.mode_lib.ip, in_out->ip_caps);
+               core->clean_me_up.mode_lib.ip.imall_supported = false;
+       }
+
+       memcpy(&core->clean_me_up.mode_lib.soc, in_out->soc_bb, sizeof(struct dml2_soc_bb));
+       memcpy(&core->clean_me_up.mode_lib.ip_caps, in_out->ip_caps, sizeof(struct dml2_ip_capabilities));
+
+       return true;
+}
+
 static void create_phantom_stream_from_main_stream(struct dml2_stream_parameters *phantom, const struct dml2_stream_parameters *main,
        const struct dml2_implicit_svp_meta *meta)
 {
index a68bb001a3465a4b408fdce34e85fd7e49e5bbf6..5c26d819a6739f132e7d13e2ec191ba5d3183a7c 100644 (file)
@@ -5,6 +5,7 @@
 #ifndef __DML2_CORE_DCN4_H__
 #define __DML2_CORE_DCN4_H__
 bool core_dcn4_initialize(struct dml2_core_initialize_in_out *in_out);
+bool core_dcn42_initialize(struct dml2_core_initialize_in_out *in_out);
 bool core_dcn4_mode_support(struct dml2_core_mode_support_in_out *in_out);
 bool core_dcn4_mode_programming(struct dml2_core_mode_programming_in_out *in_out);
 bool core_dcn4_populate_informative(struct dml2_core_populate_informative_in_out *in_out);
index cc4f0663c6d6713ac578dc2aad722a5cdb240530..67e307fa43108d8a07360e68588b67c93a9d41fe 100644 (file)
@@ -30,6 +30,14 @@ bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance
                out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation;
                result = true;
                break;
+       case dml2_project_dcn42:
+               out->initialize = &core_dcn42_initialize;
+               out->mode_support = &core_dcn4_mode_support;
+               out->mode_programming = &core_dcn4_mode_programming;
+               out->populate_informative = &core_dcn4_populate_informative;
+               out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation;
+               result = true;
+               break;
        case dml2_project_invalid:
        default:
                break;
index 9d7741fd0adb1d6c27f1ec6db5ff438c3bff733f..037272d2c2e64a3918aef13a3fd48dfb08a15b71 100644 (file)
@@ -802,3 +802,37 @@ bool dpmm_dcn4_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_
 
        return true;
 }
+
+bool dpmm_dcn42_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_out)
+{
+       const struct dml2_display_cfg *display_cfg = &in_out->display_cfg->display_config;
+       const struct dml2_core_internal_display_mode_lib *mode_lib = &in_out->core->clean_me_up.mode_lib;
+       struct dml2_dchub_global_register_set *dchubbub_regs = &in_out->programming->global_regs;
+
+       double refclk_freq_in_mhz = (display_cfg->overrides.hw.dlg_ref_clk_mhz > 0) ? (double)display_cfg->overrides.hw.dlg_ref_clk_mhz : mode_lib->soc.dchub_refclk_mhz;
+
+       /* set A */
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].fclk_pstate = (int unsigned)(mode_lib->mp.Watermark.FCLKChangeWatermark * refclk_freq_in_mhz);
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_enter = (int unsigned)(mode_lib->mp.Watermark.StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_exit = (int unsigned)(mode_lib->mp.Watermark.StutterExitWatermark * refclk_freq_in_mhz);
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_enter_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_exit_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterExitWatermark * refclk_freq_in_mhz);
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].temp_read_or_ppt = (int unsigned)(mode_lib->mp.Watermark.temp_read_or_ppt_watermark_us * refclk_freq_in_mhz);
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].uclk_pstate = (int unsigned)(mode_lib->mp.Watermark.DRAMClockChangeWatermark * refclk_freq_in_mhz);
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].urgent = (int unsigned)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz);
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].usr = (int unsigned)(mode_lib->mp.Watermark.USRRetrainingWatermark * refclk_freq_in_mhz);
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].refcyc_per_trip_to_mem = (unsigned int)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz);
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].refcyc_per_meta_trip_to_mem = (unsigned int)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz);
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].frac_urg_bw_flip = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidthImmediateFlip * 1000);
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].frac_urg_bw_nom = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidth * 1000);
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].frac_urg_bw_mall = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidthMALL * 1000);
+
+       /* set B */
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_B] = dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A];
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_C] = dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A];
+       dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_D] = dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A];
+
+       dchubbub_regs->num_watermark_sets = 4;
+
+       return true;
+}
index e7b58f2efda4bc8c0d7cdff7047f33c201738223..5fbd07e238a8c5d3fcd0f8efe086cd96e0bf884d 100644 (file)
@@ -10,5 +10,6 @@
 bool dpmm_dcn3_map_mode_to_soc_dpm(struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out);
 bool dpmm_dcn4_map_mode_to_soc_dpm(struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out);
 bool dpmm_dcn4_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_out);
+bool dpmm_dcn42_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_out);
 
 #endif
index dfd01440737df7e3d286b20b7fe0bd29cca84c9a..80d4932bf154428f7b70e4db4bfb175f62360783 100644 (file)
@@ -41,6 +41,11 @@ bool dml2_dpmm_create(enum dml2_project_id project_id, struct dml2_dpmm_instance
                out->map_watermarks = &dpmm_dcn4_map_watermarks;
                result = true;
                break;
+       case dml2_project_dcn42:
+               out->map_mode_to_soc_dpm = &dpmm_dcn4_map_mode_to_soc_dpm;
+               out->map_watermarks = &dpmm_dcn42_map_watermarks;
+               result = true;
+               break;
        case dml2_project_invalid:
        default:
                break;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c
new file mode 100644 (file)
index 0000000..1f67cbc
--- /dev/null
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dml2_mcg_dcn42.h"
+#include "dml_top_soc_parameter_types.h"
+
+static unsigned long long uclk_to_dram_bw_kbps(unsigned long uclk_khz, const struct dml2_dram_params *dram_config, unsigned long wck_ratio)
+{
+       unsigned long long bw_kbps = 0;
+
+       bw_kbps = (unsigned long long) uclk_khz * dram_config->channel_count * dram_config->channel_width_bytes * wck_ratio * 2;
+       return bw_kbps;
+}
+
+static bool build_min_clk_table_coarse_grained(const struct dml2_soc_bb *soc_bb, struct dml2_mcg_min_clock_table *min_table)
+{
+       int i;
+
+       for (i = 0; i < soc_bb->clk_table.fclk.num_clk_values; i++) {
+               if (i < soc_bb->clk_table.uclk.num_clk_values) {
+                       min_table->dram_bw_table.entries[i].pre_derate_dram_bw_kbps =
+                                       uclk_to_dram_bw_kbps(soc_bb->clk_table.uclk.clk_values_khz[i], &soc_bb->clk_table.dram_config, soc_bb->clk_table.wck_ratio.clk_values_khz[i]);
+                       min_table->dram_bw_table.entries[i].min_uclk_khz = soc_bb->clk_table.uclk.clk_values_khz[i];
+               } else {
+                       min_table->dram_bw_table.entries[i].pre_derate_dram_bw_kbps = min_table->dram_bw_table.entries[soc_bb->clk_table.uclk.num_clk_values - 1].pre_derate_dram_bw_kbps;
+                       min_table->dram_bw_table.entries[i].min_uclk_khz = soc_bb->clk_table.uclk.clk_values_khz[soc_bb->clk_table.uclk.num_clk_values - 1];
+               }
+
+               min_table->dram_bw_table.entries[i].min_dcfclk_khz = soc_bb->clk_table.dcfclk.clk_values_khz[i];
+               min_table->dram_bw_table.entries[i].min_fclk_khz = soc_bb->clk_table.fclk.clk_values_khz[i];
+       }
+       min_table->dram_bw_table.num_entries = soc_bb->clk_table.fclk.num_clk_values;
+
+       return true;
+}
+
+static bool build_min_clock_table(const struct dml2_soc_bb *soc_bb, struct dml2_mcg_min_clock_table *min_table)
+{
+       bool result;
+
+       if (!soc_bb || !min_table)
+               return false;
+
+
+       if (soc_bb->clk_table.uclk.num_clk_values > DML_MCG_MAX_CLK_TABLE_SIZE)
+               return false;
+
+       min_table->fixed_clocks_khz.amclk = 0;
+       min_table->fixed_clocks_khz.dprefclk = soc_bb->dprefclk_mhz * 1000;
+       min_table->fixed_clocks_khz.pcierefclk = soc_bb->pcie_refclk_mhz * 1000;
+       min_table->fixed_clocks_khz.dchubrefclk = soc_bb->dchub_refclk_mhz * 1000;
+       min_table->fixed_clocks_khz.xtalclk = soc_bb->xtalclk_mhz * 1000;
+
+       min_table->max_clocks_khz.dispclk = soc_bb->clk_table.dispclk.clk_values_khz[soc_bb->clk_table.dispclk.num_clk_values - 1];
+       min_table->max_clocks_khz.dppclk = soc_bb->clk_table.dppclk.clk_values_khz[soc_bb->clk_table.dppclk.num_clk_values - 1];
+       min_table->max_clocks_khz.dscclk = soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1];
+       min_table->max_clocks_khz.dtbclk = soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1];
+       min_table->max_clocks_khz.phyclk = soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1];
+
+       min_table->max_ss_clocks_khz.dispclk = (unsigned int)((double)min_table->max_clocks_khz.dispclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
+       min_table->max_ss_clocks_khz.dppclk = (unsigned int)((double)min_table->max_clocks_khz.dppclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
+       min_table->max_ss_clocks_khz.dtbclk = (unsigned int)((double)min_table->max_clocks_khz.dtbclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
+
+       min_table->max_clocks_khz.dcfclk = soc_bb->clk_table.dcfclk.clk_values_khz[soc_bb->clk_table.dcfclk.num_clk_values - 1];
+       min_table->max_clocks_khz.fclk = soc_bb->clk_table.fclk.clk_values_khz[soc_bb->clk_table.fclk.num_clk_values - 1];
+
+       result = build_min_clk_table_coarse_grained(soc_bb, min_table);
+
+       return result;
+}
+
+bool mcg_dcn42_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out)
+{
+       return build_min_clock_table(in_out->soc_bb, in_out->min_clk_table);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.h
new file mode 100644 (file)
index 0000000..ad8a847
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2026 Advanced Micro Devices, Inc. */
+
+#ifndef __DML2_MCG_DCN42_H__
+#define __DML2_MCG_DCN42_H__
+
+#include "dml2_internal_shared_types.h"
+
+bool mcg_dcn42_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out);
+
+#endif
index c60b8fe90819d9fd8813c607ac70d18704691194..1cff62b63e720df4404d90b2fba24fb4d03bf7c8 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "dml2_mcg_factory.h"
 #include "dml2_mcg_dcn4.h"
+#include "dml2_mcg_dcn42.h"
 #include "dml2_external_lib_deps.h"
 
 static bool dummy_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out)
@@ -30,6 +31,10 @@ bool dml2_mcg_create(enum dml2_project_id project_id, struct dml2_mcg_instance *
                out->build_min_clock_table = &mcg_dcn4_build_min_clock_table;
                result = true;
                break;
+       case dml2_project_dcn42:
+               out->build_min_clock_table = &mcg_dcn42_build_min_clock_table;
+               result = true;
+               break;
        case dml2_project_invalid:
        default:
                break;
index 5a33e2f357f45afff73af806b66f37803d4c5b52..04860b6790df1930317f57d6b38505b3661ef10b 100644 (file)
@@ -17,6 +17,7 @@ bool dml2_initialize_instance(struct dml2_initialize_instance_in_out *in_out)
        case dml2_project_dcn4x_stage1:
        case dml2_project_dcn4x_stage2:
        case dml2_project_dcn4x_stage2_auto_drr_svp:
+       case dml2_project_dcn42:
                return dml2_top_soc15_initialize_instance(in_out);
        case dml2_project_invalid:
        default: