drm/amd/display: Enable dc mode clock switching for DCN32x
authorAlvin Lee <alvin.lee2@amd.com>
Sat, 10 Jun 2023 00:32:57 +0000 (20:32 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 23 Jun 2023 19:45:57 +0000 (15:45 -0400)
- DC mode clock switch interface was previously only executed
  for DCN303. Enable it for DCN32x so that the interface is called
  correctly
- Assign function pointers for DCN32x that are used in the dc mode
  interface
- Update the dc mode interface to work generically for each ASIC
- In update_clocks, make sure to consider softmax if we're in DC mode

Reviewed-by: Jun Lei <jun.lei@amd.com>
Acked-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
Signed-off-by: Alvin Lee <alvin.lee2@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubp.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h

index 6a811755e2e6f4fa01763f6dd66d1ee02da69efb..cb992aca760dc4690da4b6c348a045be6cd0733e 100644 (file)
@@ -541,9 +541,18 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
                        clk_mgr_base->clks.p_state_change_support = p_state_change_support;
 
                        /* to disable P-State switching, set UCLK min = max */
-                       if (!clk_mgr_base->clks.p_state_change_support)
-                               dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
-                                               clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels - 1].memclk_mhz);
+                       if (!clk_mgr_base->clks.p_state_change_support) {
+                               if (dc->clk_mgr->dc_mode_softmax_enabled) {
+                                       /* On DCN32x we will never have the functional UCLK min above the softmax
+                                        * since we calculate mode support based on softmax being the max UCLK
+                                        * frequency.
+                                        */
+                                       dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+                                                       dc->clk_mgr->bw_params->dc_mode_softmax_memclk);
+                               } else {
+                                       dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz);
+                               }
+                       }
                }
 
                /* Always update saved value, even if new value not set due to P-State switching unsupported. Also check safe_to_lower for FCLK */
@@ -808,8 +817,7 @@ static void dcn32_set_hard_max_memclk(struct clk_mgr *clk_mgr_base)
        if (!clk_mgr->smu_present)
                return;
 
-       dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK,
-                       clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels - 1].memclk_mhz);
+       dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, clk_mgr_base->bw_params->max_memclk_mhz);
 }
 
 /* Get current memclk states, update bounding box */
@@ -827,6 +835,7 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
                        &clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz,
                        &num_entries_per_clk->num_memclk_levels);
        clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_UCLK);
+       clk_mgr_base->bw_params->dc_mode_softmax_memclk = clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz;
 
        /* memclk must have at least one level */
        num_entries_per_clk->num_memclk_levels = num_entries_per_clk->num_memclk_levels ? num_entries_per_clk->num_memclk_levels : 1;
@@ -841,7 +850,8 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
        } else {
                num_levels = num_entries_per_clk->num_fclk_levels;
        }
-
+       clk_mgr_base->bw_params->max_memclk_mhz =
+                       clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_memclk_levels - 1].memclk_mhz;
        clk_mgr_base->bw_params->clk_table.num_entries = num_levels ? num_levels : 1;
 
        if (clk_mgr->dpm_present && !num_levels)
@@ -894,6 +904,25 @@ static bool dcn32_is_smu_present(struct clk_mgr *clk_mgr_base)
        return clk_mgr->smu_present;
 }
 
+static void dcn32_set_max_memclk(struct clk_mgr *clk_mgr_base, unsigned int memclk_mhz)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+       if (!clk_mgr->smu_present)
+               return;
+
+       dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, memclk_mhz);
+}
+
+static void dcn32_set_min_memclk(struct clk_mgr *clk_mgr_base, unsigned int memclk_mhz)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+       if (!clk_mgr->smu_present)
+               return;
+
+       dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, memclk_mhz);
+}
 
 static struct clk_mgr_funcs dcn32_funcs = {
                .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
@@ -904,6 +933,8 @@ static struct clk_mgr_funcs dcn32_funcs = {
                .notify_wm_ranges = dcn32_notify_wm_ranges,
                .set_hard_min_memclk = dcn32_set_hard_min_memclk,
                .set_hard_max_memclk = dcn32_set_hard_max_memclk,
+               .set_max_memclk = dcn32_set_max_memclk,
+               .set_min_memclk = dcn32_set_min_memclk,
                .get_memclk_states_from_smu = dcn32_get_memclk_states_from_smu,
                .are_clock_states_equal = dcn32_are_clock_states_equal,
                .enable_pme_wa = dcn32_enable_pme_wa,
index 99a14c2f05cf01d44c7f9acbf947d4445f350c90..f413998ff2535e6c3c33a19a5d478c4b4b28b284 100644 (file)
@@ -4763,15 +4763,17 @@ static void blank_and_force_memclk(struct dc *dc, bool apply, unsigned int memcl
  */
 void dc_enable_dcmode_clk_limit(struct dc *dc, bool enable)
 {
-       uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev;
-       unsigned int softMax, maxDPM, funcMin;
+       unsigned int softMax = 0, maxDPM = 0, funcMin = 0, i;
        bool p_state_change_support;
 
-       if (!ASICREV_IS_BEIGE_GOBY_P(hw_internal_rev))
+       if (!dc->config.dc_mode_clk_limit_support)
                return;
 
        softMax = dc->clk_mgr->bw_params->dc_mode_softmax_memclk;
-       maxDPM = dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz;
+       for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries; i++) {
+               if (dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz > maxDPM)
+                       maxDPM = dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz;
+       }
        funcMin = (dc->clk_mgr->clks.dramclk_khz + 999) / 1000;
        p_state_change_support = dc->clk_mgr->clks.p_state_change_support;
 
index 26d05e2250888f8df3603d14330734eba8484259..812f3922323882718b6a1cc9b6a4f8888876e1bc 100644 (file)
@@ -416,7 +416,7 @@ struct dc_config {
        uint8_t force_bios_fixed_vs;
        int sdpif_request_limit_words_per_umc;
        bool use_old_fixed_vs_sequence;
-       bool disable_subvp_drr;
+       bool dc_mode_clk_limit_support;
 };
 
 enum visual_confirm {
index 6d9761395288db268ca69df92c8ce9a7a557885e..45956ef6f3f9dd2b4ede34a40a7077051f4e4ebc 100644 (file)
@@ -1190,6 +1190,7 @@ static bool dcn303_resource_construct(
 
        dc->caps.dp_hdmi21_pcon_support = true;
 
+       dc->config.dc_mode_clk_limit_support = true;
        /* read VBIOS LTTPR caps */
        if (ctx->dc_bios->funcs->get_lttpr_caps) {
                enum bp_result bp_query_result;
index 2d604f7ee7824da021677c6e3e203e5e020e6f0b..ca5b4b28a66441bca370578d11d4e05097db9d4c 100644 (file)
@@ -179,6 +179,7 @@ static struct hubp_funcs dcn32_hubp_funcs = {
        .hubp_setup_interdependent = hubp2_setup_interdependent,
        .hubp_set_vm_system_aperture_settings = hubp3_set_vm_system_aperture_settings,
        .set_blank = hubp2_set_blank,
+       .set_blank_regs = hubp2_set_blank_regs,
        .dcc_control = hubp3_dcc_control,
        .mem_program_viewport = min_set_viewport,
        .set_cursor_attributes  = hubp32_cursor_set_attributes,
index c2490e16a66a6c99cfb268226ee9acae54607e68..777b2fac20c4efa8a65f71131967ba603b4c04be 100644 (file)
@@ -56,6 +56,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
        .enable_audio_stream = dce110_enable_audio_stream,
        .disable_audio_stream = dce110_disable_audio_stream,
        .disable_plane = dcn20_disable_plane,
+       .disable_pixel_data = dcn20_disable_pixel_data,
        .pipe_control_lock = dcn20_pipe_control_lock,
        .interdependent_update_lock = dcn10_lock_all_pipes,
        .cursor_lock = dcn10_cursor_lock,
index c94dec042cc3742e84d865e7b3a3bcd2818e4d33..1cc09799f92d386ca338fa5a1cd77d63dfc28c7a 100644 (file)
@@ -2215,6 +2215,7 @@ static bool dcn32_resource_construct(
        /* Use pipe context based otg sync logic */
        dc->config.use_pipe_ctx_sync_logic = true;
 
+       dc->config.dc_mode_clk_limit_support = true;
        /* read VBIOS LTTPR caps */
        {
                if (ctx->dc_bios->funcs->get_lttpr_caps) {
index ca409a441953d800789a14c342f05a7ed23cb5c4..a53478e15ce3a899aae7289db9fb949f72f595a7 100644 (file)
@@ -1756,6 +1756,7 @@ static bool dcn321_resource_construct(
        dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
        dc->caps.color.mpc.ocsc = 1;
 
+       dc->config.dc_mode_clk_limit_support = true;
        /* read VBIOS LTTPR caps */
        {
                if (ctx->dc_bios->funcs->get_lttpr_caps) {
index 6faf40fa5c695ecef2dc295b5cc04d684be7febf..ecb7bcc3946935e1a901c41ba1d822cc0639b21c 100644 (file)
@@ -230,6 +230,7 @@ struct clk_bw_params {
        unsigned int dram_channel_width_bytes;
        unsigned int dispclk_vco_khz;
        unsigned int dc_mode_softmax_memclk;
+       unsigned int max_memclk_mhz;
        struct clk_limit_table clk_table;
        struct wm_table wm_table;
        struct dummy_pstate_entry dummy_pstate_table[4];