From: Charlene Liu <[email protected]>

[why]
ensure dtbclk is enabled before hdmistreamclk_en

pmfw could stop dtbclk on idle.
driver needs to ensure dtbclk enabled is enabled before hdmistreamclk_en
also disable debounce timer on dcn42.

Reviewed-by: Chris Park <[email protected]>
Reviewed-by: Leo Chen <[email protected]>
Signed-off-by: Charlene Liu <[email protected]>
Signed-off-by: Roman Li <[email protected]>
---
 .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c  | 28 +++++++++++++++++--
 .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h  |  1 +
 .../drm/amd/display/dc/dce/dce_clock_source.c |  4 +++
 .../gpu/drm/amd/display/dc/inc/hw/clk_mgr.h   |  1 +
 .../display/dc/link/protocols/link_hdmi_frl.c | 18 ++++++++++--
 5 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c 
b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c
index c7b9bad93a93..19ef0b92e8e6 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c
@@ -220,6 +220,7 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
        bool update_dispclk = false;
        bool dpp_clock_lowered = false;
        bool has_active_display;
+       int actual_dtbclk = 0;
 
        if (dc->work_arounds.skip_clock_update)
                return;
@@ -260,8 +261,9 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
                 * For dcn42b (no dtbclk hardware), init_clk_states sets 
dtbclk_en=false and
                 * new_clocks->dtbclk_en should always be false, so this block 
never executes.
                 */
-               if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) {
-                       int actual_dtbclk = 0;
+               actual_dtbclk = dcn42_get_clock_freq_from_clkip(clk_mgr_base, 
clock_type_dtbclk);
+
+               if (new_clocks->dtbclk_en && actual_dtbclk < 590000) {
 
                        dcn42_update_clocks_update_dtb_dto(clk_mgr, context, 
new_clocks->ref_dtbclk_khz);
                        dcn42_smu_set_dtbclk(clk_mgr, true);
@@ -343,7 +345,6 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
                dcn42_update_clocks_update_dtb_dto(clk_mgr, context, 
new_clocks->ref_dtbclk_khz);
                clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz;
        }
-
        if (dpp_clock_lowered) {
                // increase per DPP DTO before lowering global dppclk
                dcn42_update_clocks_update_dpp_dto(clk_mgr, context, 
safe_to_lower);
@@ -1051,7 +1052,27 @@ void dcn42_get_smu_clocks(struct clk_mgr_internal 
*clk_mgr_int)
                dm_helpers_free_gpu_mem(clk_mgr_base->ctx, 
DC_MEM_ALLOC_TYPE_GART,
                                smu_dpm_clks.dpm_clks);
 }
+void dcn42_request_dtbclk(struct clk_mgr *clk_mgr_base, bool enable)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+       /*pmfw might turn off dtblck based on allow_dtbstop*/
+       clk_mgr_base->clks.dtbclk_en = false;
 
+       if (enable) {
+               int actual_dtbclk = 0;
+
+               dcn42_smu_set_dtbclk(clk_mgr, true);
+               actual_dtbclk = dcn42_get_clock_freq_from_clkip(clk_mgr_base, 
clock_type_dtbclk);
+               if (actual_dtbclk > 590000) {
+                       clk_mgr_base->clks.ref_dtbclk_khz = actual_dtbclk;
+                       clk_mgr_base->clks.dtbclk_en = true;
+               }
+       } else {
+               clk_mgr_base->clks.dtbclk_en = false;
+               dcn42_smu_set_dtbclk(clk_mgr, false);
+       }
+}
 static struct clk_mgr_funcs dcn42_funcs = {
        .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
        .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz,
@@ -1065,6 +1086,7 @@ static struct clk_mgr_funcs dcn42_funcs = {
        .get_max_clock_khz = dcn42_get_max_clock_khz,
        .get_dispclk_from_dentist = dcn42_get_dispclk_from_dentist,
        .is_smu_present = dcn42_is_smu_present,
+       .request_dtbclk = dcn42_request_dtbclk,
        .notify_cstate_disable = dcn42_notify_cstate_disable,
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h 
b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h
index 330242747fff..f90c6e2e85c2 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h
@@ -84,4 +84,5 @@ void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal 
*clk_mgr, struct dcn42
 void dcn42_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int);
 void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr, struct dc_state 
*context, bool safe_to_lower);
 int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base);
+void dcn42_request_dtbclk(struct clk_mgr *clk_mgr_base, bool enable);
 #endif //__DCN42_CLK_MGR_H__
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c 
b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index e52fb7248a88..47ec08071ceb 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -1118,6 +1118,10 @@ static bool dcn401_program_pix_clk(
                if (clock_source->ctx->dc->caps.is_apu &&
                        pix_clk_params->requested_pix_clk_100hz &&
                        dc_is_hdmi_frl_signal(pix_clk_params->signal_type)) {
+                       //make sure dtbclk is enabled
+                       if 
(clock_source->ctx->dc->clk_mgr->funcs->request_dtbclk)
+                               
clock_source->ctx->dc->clk_mgr->funcs->request_dtbclk(
+                                       clock_source->ctx->dc->clk_mgr, true);
                        /*need hdmistreamclk before vpg block register access*/
                        
clock_source->ctx->dc->res_pool->dccg->funcs->set_hdmistreamclk(
                                clock_source->ctx->dc->res_pool->dccg,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
index ec678bd249ef..614beb5924fd 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
@@ -427,6 +427,7 @@ struct clk_mgr_funcs {
                        struct block_sequence_state *seq_state);
 
        void (*execute_clk_mgr_block_sequence)(struct clk_mgr *clk_mgr);
+       void (*request_dtbclk)(struct clk_mgr *clk_mgr_base, bool enable);
 };
 
 struct clk_mgr {
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c 
b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
index 75ec3b701d81..714168e1ece6 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
@@ -415,6 +415,18 @@ void hdmi_frl_LTS_clear_Link_Setting(struct ddc_service 
*ddc_service)
 
 }
 
+static uint8_t hdmi_frl_get_max_ffe_level(struct dc_link *link,
+               struct dc_hdmi_frl_link_settings *link_settings)
+{
+       uint8_t max_ffe_level =
+                       (link_settings->frl_link_rate > 
HDMI_FRL_LINK_RATE_12GBPS) ? 7 : 3;
+
+       if ((uint8_t)link->dc->debug.limit_ffe < max_ffe_level)
+               max_ffe_level = (uint8_t)link->dc->debug.limit_ffe;
+
+       return max_ffe_level;
+}
+
 static enum link_result hdmi_frl_perform_link_training(struct ddc_service 
*ddc_service,
                struct dc_hdmi_frl_link_settings *link_settings)
 {
@@ -436,7 +448,7 @@ static enum link_result 
hdmi_frl_perform_link_training(struct ddc_service *ddc_s
        struct hpo_frl_link_encoder *hpo_frl_link_enc = 
ddc_service->link->hpo_frl_link_enc;
        struct link_encoder *dio_link_enc = ddc_service->link->link_enc;
        uint8_t sink_version = 0;
-       uint8_t FFE_Levels = (uint8_t)ddc_service->link->dc->debug.limit_ffe;
+       uint8_t FFE_Levels = hdmi_frl_get_max_ffe_level(ddc_service->link, 
link_settings);
        uint8_t current_FFE = 0;
        bool override_FFE = false;
        bool flt_no_timeout = false;
@@ -616,7 +628,7 @@ static enum link_result 
hdmi_frl_perform_link_training(struct ddc_service *ddc_s
                                                }
                                                current_FFE++;
                                                override_FFE = true;
-                                               if (current_FFE > 3)
+                                               if (current_FFE > FFE_Levels)
                                                        current_FFE = 0;
                                                if (flt_no_timeout)
                                                        current_FFE = 0;
@@ -642,7 +654,7 @@ static enum link_result 
hdmi_frl_perform_link_training(struct ddc_service *ddc_s
                                                }
                                                current_FFE++;
                                                override_FFE = true;
-                                               if (current_FFE > 3)
+                                               if (current_FFE > FFE_Levels)
                                                        current_FFE = 0;
                                                if (flt_no_timeout)
                                                        current_FFE = 0;
-- 
2.34.1

Reply via email to