]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
drm/amd/display: Implement DTBCLK ref switching on dcn32
authorAlvin Lee <Alvin.Lee2@amd.com>
Sat, 30 Apr 2022 00:41:10 +0000 (20:41 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 3 Jun 2022 20:45:01 +0000 (16:45 -0400)
[WHY & HOW]
Implements DTB ref clock switching with reg key default to OFF.
Refactors dccg DTBCLK logic to not store redundant state information
dccg. Also removes duplicated functions that should be inherited from
other dcn versions.

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/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.h
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.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/dccg.h

index 6a1d7c86e6b716cdca2a9ad909a03e071a35fe35..1db61029481ba9e1fd1b8b6506033232ec258423 100644 (file)
 #include "dcn32/dcn32_clk_mgr_smu_msg.h"
 #include "dcn20/dcn20_clk_mgr.h"
 #include "dce100/dce_clk_mgr.h"
+#include "dcn31/dcn31_clk_mgr.h"
 #include "reg_helper.h"
 #include "core_types.h"
 #include "dm_helpers.h"
+#include "dc_link_dp.h"
 
 #include "atomfirmware.h"
 #include "smu13_driver_if.h"
@@ -253,9 +255,10 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
                                        &clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz,
                                        &num_levels);
        /* DTBCLK */
-       dcn32_init_single_clock(clk_mgr, PPCLK_DTBCLK,
-                       &clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz,
-                       &num_levels);
+       if (!clk_mgr->base.ctx->dc->debug.disable_dtb_ref_clk_switch)
+               dcn32_init_single_clock(clk_mgr, PPCLK_DTBCLK,
+                               &clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz,
+                               &num_levels);
 
        /* DISPCLK */
        dcn32_init_single_clock(clk_mgr, PPCLK_DISPCLK,
@@ -270,6 +273,39 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
        dcn32_build_wm_range_table(clk_mgr);
 }
 
+static void dcn32_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
+                       struct dc_state *context,
+                       int ref_dtbclk_khz)
+{
+       struct dccg *dccg = clk_mgr->dccg;
+       uint32_t tg_mask = 0;
+       int i;
+
+       for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+               struct dtbclk_dto_params dto_params = {0};
+
+               /* use mask to program DTO once per tg */
+               if (pipe_ctx->stream_res.tg &&
+                               !(tg_mask & (1 << pipe_ctx->stream_res.tg->inst))) {
+                       tg_mask |= (1 << pipe_ctx->stream_res.tg->inst);
+
+                       dto_params.otg_inst = pipe_ctx->stream_res.tg->inst;
+                       dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
+
+                       if (is_dp_128b_132b_signal(pipe_ctx)) {
+                               dto_params.pixclk_khz = pipe_ctx->stream->phy_pix_clk;
+
+                               if (pipe_ctx->stream_res.audio != NULL)
+                                       dto_params.req_audio_dtbclk_khz = 24000;
+                       }
+
+                       dccg->funcs->set_dtbclk_dto(clk_mgr->dccg, &dto_params);
+                       //dccg->funcs->set_audio_dtbclk_dto(clk_mgr->dccg, &dto_params);
+               }
+       }
+}
+
 static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
                        struct dc_state *context,
                        bool safe_to_lower)
@@ -320,7 +356,7 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
 
                if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) {
                        clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
-                       dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DCFCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_khz));
+                       dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DCFCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_khz));
                }
 
                if (should_set_clock(safe_to_lower, new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) {
@@ -350,7 +386,7 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
 
                        /* to disable P-State switching, set UCLK min = max */
                        if (!clk_mgr_base->clks.p_state_change_support)
-                               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+                               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 - 1].memclk_mhz);
                }
 
@@ -379,7 +415,7 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
                /* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */
                if (clk_mgr_base->clks.p_state_change_support &&
                                (update_uclk || !clk_mgr_base->clks.prev_p_state_change_support))
-                       dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
+                       dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
 
                if (clk_mgr_base->ctx->dce_version != DCN_VERSION_3_21 && clk_mgr_base->clks.fclk_p_state_change_support && update_fclk) {
                        /* Handle the code for sending a message to PMFW that FCLK P-state change is supported */
@@ -400,7 +436,7 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
                clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz;
 
                if (clk_mgr->smu_present)
-                       dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DPPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dppclk_khz));
+                       dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DPPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dppclk_khz));
 
                update_dppclk = true;
        }
@@ -409,11 +445,25 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
                clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
 
                if (clk_mgr->smu_present)
-                       dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dispclk_khz));
+                       dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dispclk_khz));
 
                update_dispclk = true;
        }
 
+       if (!new_clocks->dtbclk_en) {
+               new_clocks->ref_dtbclk_khz = 0;
+       }
+
+       /* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */
+       if (!dc->debug.disable_dtb_ref_clk_switch &&
+                       should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000, clk_mgr_base->clks.ref_dtbclk_khz / 1000)) {
+               /* DCCG requires KHz precision for DTBCLK */
+               clk_mgr_base->clks.ref_dtbclk_khz =
+                               dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DTBCLK, khz_to_mhz_ceil(new_clocks->ref_dtbclk_khz));
+
+               dcn32_update_clocks_update_dtb_dto(clk_mgr, context, clk_mgr_base->clks.ref_dtbclk_khz);
+       }
+
        if (dc->config.forced_clocks == false || (force_reset && safe_to_lower)) {
                if (dpp_clock_lowered) {
                        /* if clock is being lowered, increase DTO before lowering refclk */
@@ -502,13 +552,13 @@ static void dcn32_set_hard_min_memclk(struct clk_mgr *clk_mgr_base, bool current
 
        if (current_mode) {
                if (clk_mgr_base->clks.p_state_change_support)
-                       dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+                       dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
                                        khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
                else
-                       dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+                       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 - 1].memclk_mhz);
        } else {
-               dcn30_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+               dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
                                clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz);
        }
 }
@@ -584,7 +634,7 @@ static bool dcn32_is_smu_present(struct clk_mgr *clk_mgr_base)
 
 
 static struct clk_mgr_funcs dcn32_funcs = {
-               .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
+               .get_dp_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz,
                .update_clocks = dcn32_update_clocks,
                .init_clocks = dcn32_init_clocks,
                .notify_wm_ranges = dcn32_notify_wm_ranges,
@@ -627,7 +677,13 @@ void dcn32_clk_mgr_construct(
         * dprefclk DID divider
         */
        clk_mgr->base.dprefclk_khz = 716666;
-       clk_mgr->dccg->ref_dtbclk_khz = 268750;
+       if (ctx->dc->debug.disable_dtb_ref_clk_switch) {
+               //initialize DTB ref clock value if DPM disabled
+               if (ctx->dce_version == DCN_VERSION_3_21)
+                       clk_mgr->base.clks.ref_dtbclk_khz = 477800;
+               else
+                       clk_mgr->base.clks.ref_dtbclk_khz = 268750;
+       }
 
        /* integer part is now VCO frequency in kHz */
        clk_mgr->base.dentist_vco_freq_khz = 4300000;//dcn32_get_vco_frequency_from_reg(clk_mgr);
@@ -635,8 +691,9 @@ void dcn32_clk_mgr_construct(
        if (clk_mgr->base.dentist_vco_freq_khz == 0)
                clk_mgr->base.dentist_vco_freq_khz = 4300000; /* Updated as per HW docs */
 
-       if (clk_mgr->dccg->ref_dtbclk_khz != clk_mgr->base.boot_snapshot.dtbclk) {
-               clk_mgr->dccg->ref_dtbclk_khz = clk_mgr->base.boot_snapshot.dtbclk;
+       if (ctx->dc->debug.disable_dtb_ref_clk_switch &&
+                       clk_mgr->base.clks.ref_dtbclk_khz != clk_mgr->base.boot_snapshot.dtbclk) {
+               clk_mgr->base.clks.ref_dtbclk_khz = clk_mgr->base.boot_snapshot.dtbclk;
        }
 
        if (clk_mgr->base.boot_snapshot.dprefclk != 0) {
index 95ab268e91795eb1d075d09592edd660362967a3..d7c99e9179be5b96b00e7d336ea5e34b196c85fe 100644 (file)
@@ -114,3 +114,21 @@ void dcn32_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr)
        dcn32_smu_send_msg_with_param(clk_mgr,
                        DALSMC_MSG_TransferTableDram2Smu, TABLE_WATERMARKS, NULL);
 }
+
+/* Returns the actual frequency that was set in MHz, 0 on failure */
+unsigned int dcn32_smu_set_hard_min_by_freq(struct clk_mgr_internal *clk_mgr, uint32_t clk, uint16_t freq_mhz)
+{
+       uint32_t response = 0;
+
+       /* bits 23:16 for clock type, lower 16 bits for frequency in MHz */
+       uint32_t param = (clk << 16) | freq_mhz;
+
+       smu_print("SMU Set hard min by freq: clk = %d, freq_mhz = %d MHz\n", clk, freq_mhz);
+
+       dcn32_smu_send_msg_with_param(clk_mgr,
+                       DALSMC_MSG_SetHardMinByFreq, param, &response);
+
+       smu_print("SMU Frequency set = %d KHz\n", response);
+
+       return response;
+}
index 5f69cdcb98855509bf91b0c5fd8816e5da17b381..352435edbd79a17960a0538420811f33ae60d607 100644 (file)
@@ -41,5 +41,6 @@ dcn32_smu_send_fclk_pstate_message(struct clk_mgr_internal *clk_mgr, bool enable
 void dcn32_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr);
 void dcn32_smu_send_cab_for_uclk_message(struct clk_mgr_internal *clk_mgr, unsigned int num_ways);
 void dcn32_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr);
+unsigned int dcn32_smu_set_hard_min_by_freq(struct clk_mgr_internal *clk_mgr, uint32_t clk, uint16_t freq_mhz);
 
 #endif /* __DCN32_CLK_MGR_SMU_MSG_H_ */
index 691654653ebb110fa76c3686c1e2239f8ead32a1..7bb67ab979e1a327e686b485e369334b322a6a5c 100644 (file)
@@ -432,7 +432,6 @@ struct dc_clocks {
        enum dcn_zstate_support_state zstate_support;
        bool dtbclk_en;
        int ref_dtbclk_khz;
-       int dtbclk_khz;
        bool fclk_p_state_change_support;
        enum dcn_pwr_state pwr_state;
        /*
@@ -740,11 +739,11 @@ struct dc_debug_options {
        bool force_disable_subvp;
        bool force_subvp_mclk_switch;
        bool force_usr_allow;
+       /* uses value at boot and disables switch */
+       bool disable_dtb_ref_clk_switch;
        bool apply_vendor_specific_lttpr_wa;
        bool extended_blank_optimization;
        union aux_wake_wa_options aux_wake_wa;
-       /* uses value at boot and disables switch */
-       bool disable_dtb_ref_clk_switch;
        uint8_t psr_power_use_phy_fsm;
        enum dml_hostvm_override_opts dml_hostvm_override;
 };
index a76523c95ab2669ce4df8c18a8c1ba8d9364da0f..631a8a2f9fc379f3e543be8937561388ed1e9a61 100644 (file)
@@ -2191,18 +2191,15 @@ static void dce110_setup_audio_dto(
                        build_audio_output(context, pipe_ctx, &audio_output);
 
                        if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->set_audio_dtbclk_dto) {
-                               struct dtbclk_dto_params dto_params = {0};
+                               /* disable audio DTBCLK DTO */
+                               dc->res_pool->dccg->funcs->set_audio_dtbclk_dto(
+                                       dc->res_pool->dccg, 0);
 
                                pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
                                                pipe_ctx->stream_res.audio,
                                                pipe_ctx->stream->signal,
                                                &audio_output.crtc_info,
                                                &audio_output.pll_info);
-
-                               dc->res_pool->dccg->funcs->set_audio_dtbclk_dto(
-                                       dc->res_pool->dccg,
-                                       &dto_params);
-
                        } else
                                pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
                                        pipe_ctx->stream_res.audio,
index 13dbf99af2205a5e576e6de987658f0c8c2e3345..8eeb3b69b5b931aac9411a59631f281bf533ec51 100644 (file)
@@ -590,6 +590,7 @@ void dccg31_set_audio_dtbclk_dto(
                phase = div_u64((((unsigned long long)modulo * params->req_audio_dtbclk_khz) + params->ref_dtbclk_khz - 1),
                        params->ref_dtbclk_khz);
 
+
                REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_MODULO, modulo);
                REG_WRITE(DCCG_AUDIO_DTBCLK_DTO_PHASE, phase);
 
index 070be7e8ad0dbab97887d09c9c1472b8721e74da..08232d05d894340a6f58858c8063b391dc61535b 100644 (file)
@@ -179,11 +179,13 @@ void dccg32_set_dtbclk_dto(
 
 void dccg32_set_valid_pixel_rate(
                struct dccg *dccg,
+               int ref_dtbclk_khz,
                int otg_inst,
                int pixclk_khz)
 {
        struct dtbclk_dto_params dto_params = {0};
 
+       dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
        dto_params.otg_inst = otg_inst;
        dto_params.pixclk_khz = pixclk_khz;
 
index b492eb424d1936a9e8349229e20cbbb07e99d2fe..1ea6d258a20d40391be159d86ed76cdd26af3d57 100644 (file)
@@ -3306,6 +3306,7 @@ void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context, display
        // context->bw_ctx.bw.dcn.clk.p_state_change_support |= context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching;
        context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
        context->bw_ctx.bw.dcn.clk.dtbclk_en = is_dtbclk_required(dc, context);
+       context->bw_ctx.bw.dcn.clk.ref_dtbclk_khz = context->bw_ctx.dml.vba.DTBCLKPerState[vlevel] * 1000;
        if (context->bw_ctx.dml.vba.FCLKChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] == dm_fclock_change_unsupported)
                context->bw_ctx.bw.dcn.clk.fclk_p_state_change_support = false;
        else
@@ -3560,10 +3561,15 @@ static void dcn32_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw
                        dcn3_2_soc.clock_limits[i].dscclk_mhz  = max_dispclk_mhz / 3;
 
                        /* Populate from bw_params for DTBCLK, SOCCLK */
-                       if (!bw_params->clk_table.entries[i].dtbclk_mhz && i > 0)
-                               dcn3_2_soc.clock_limits[i].dtbclk_mhz  = dcn3_2_soc.clock_limits[i-1].dtbclk_mhz;
-                       else
+                       if (i > 0) {
+                               if (!bw_params->clk_table.entries[i].dtbclk_mhz) {
+                                       dcn3_2_soc.clock_limits[i].dtbclk_mhz  = dcn3_2_soc.clock_limits[i-1].dtbclk_mhz;
+                               } else {
+                                       dcn3_2_soc.clock_limits[i].dtbclk_mhz  = bw_params->clk_table.entries[i].dtbclk_mhz;
+                               }
+                       } else if (bw_params->clk_table.entries[i].dtbclk_mhz) {
                                dcn3_2_soc.clock_limits[i].dtbclk_mhz  = bw_params->clk_table.entries[i].dtbclk_mhz;
+                       }
 
                        if (!bw_params->clk_table.entries[i].socclk_mhz && i > 0)
                                dcn3_2_soc.clock_limits[i].socclk_mhz = dcn3_2_soc.clock_limits[i-1].socclk_mhz;
index 780409eb0e98196c58784b038d31318b0f7e433e..48af91affb0c0440d27df1a1d9bfd2587c257173 100644 (file)
@@ -1910,10 +1910,15 @@ static void dcn321_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b
                        dcn3_21_soc.clock_limits[i].dscclk_mhz  = max_dispclk_mhz / 3;
 
                        /* Populate from bw_params for DTBCLK, SOCCLK */
-                       if (!bw_params->clk_table.entries[i].dtbclk_mhz && i > 0)
-                               dcn3_21_soc.clock_limits[i].dtbclk_mhz  = dcn3_21_soc.clock_limits[i-1].dtbclk_mhz;
-                       else
+                       if (i > 0) {
+                               if (!bw_params->clk_table.entries[i].dtbclk_mhz) {
+                                       dcn3_21_soc.clock_limits[i].dtbclk_mhz = dcn3_21_soc.clock_limits[i-1].dtbclk_mhz;
+                               } else {
+                                       dcn3_21_soc.clock_limits[i].dtbclk_mhz = bw_params->clk_table.entries[i].dtbclk_mhz;
+                               }
+                       } else if (bw_params->clk_table.entries[i].dtbclk_mhz) {
                                dcn3_21_soc.clock_limits[i].dtbclk_mhz  = bw_params->clk_table.entries[i].dtbclk_mhz;
+                       }
 
                        if (!bw_params->clk_table.entries[i].socclk_mhz && i > 0)
                                dcn3_21_soc.clock_limits[i].socclk_mhz = dcn3_21_soc.clock_limits[i-1].socclk_mhz;
index e0dd04626eb584177fcf823bf9b7b978502fd3ce..025169457cc863c78d86dc948aaa6ab2c05e4173 100644 (file)
@@ -70,7 +70,7 @@ struct dccg {
        int ref_dppclk;
        //int dtbclk_khz[MAX_PIPES];/* TODO needs to be removed */
        //int audio_dtbclk_khz;/* TODO needs to be removed */
-       int ref_dtbclk_khz;/* TODO needs to be removed */
+       //int ref_dtbclk_khz;/* TODO needs to be removed */
 };
 
 struct dtbclk_dto_params {
@@ -154,6 +154,7 @@ void (*set_pixel_rate_div)(
 
 void (*set_valid_pixel_rate)(
         struct dccg *dccg,
+       int ref_dtbclk_khz,
         int otg_inst,
         int pixclk_khz);