drm/amd/display: Add missing enable and disable symclk_se functions for dcn401
authorWenjing Liu <wenjing.liu@amd.com>
Wed, 17 Apr 2024 21:18:55 +0000 (17:18 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 20 May 2024 20:19:34 +0000 (16:19 -0400)
The functions are missing. These two functions are required to support
MST.

Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h
drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h

index 72cbff8632dd445c4b69e8a694d53a7ba35133df..a496a250f8924808185511d018f3bd47c259d7a1 100644 (file)
@@ -785,6 +785,163 @@ static void dccg401_set_ref_dscclk(struct dccg *dccg,
        }
 }
 
+static void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       switch (link_enc_inst) {
+       case 0:
+               REG_UPDATE(SYMCLKA_CLOCK_ENABLE,
+                               SYMCLKA_CLOCK_ENABLE, 1);
+               if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, 1);
+               break;
+       case 1:
+               REG_UPDATE(SYMCLKB_CLOCK_ENABLE,
+                               SYMCLKB_CLOCK_ENABLE, 1);
+               if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, 1);
+               break;
+       case 2:
+               REG_UPDATE(SYMCLKC_CLOCK_ENABLE,
+                               SYMCLKC_CLOCK_ENABLE, 1);
+               if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, 1);
+               break;
+       case 3:
+               REG_UPDATE(SYMCLKD_CLOCK_ENABLE,
+                               SYMCLKD_CLOCK_ENABLE, 1);
+               if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, 1);
+               break;
+       }
+
+       switch (stream_enc_inst) {
+       case 0:
+               REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE,
+                               SYMCLKA_FE_EN, 1,
+                               SYMCLKA_FE_SRC_SEL, link_enc_inst);
+               if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, 1);
+               break;
+       case 1:
+               REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE,
+                               SYMCLKB_FE_EN, 1,
+                               SYMCLKB_FE_SRC_SEL, link_enc_inst);
+               if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, 1);
+               break;
+       case 2:
+               REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE,
+                               SYMCLKC_FE_EN, 1,
+                               SYMCLKC_FE_SRC_SEL, link_enc_inst);
+               if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, 1);
+               break;
+       case 3:
+               REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE,
+                               SYMCLKD_FE_EN, 1,
+                               SYMCLKD_FE_SRC_SEL, link_enc_inst);
+               if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, 1);
+               break;
+       }
+}
+
+/*get other front end connected to this backend*/
+static uint8_t dccg401_get_other_enabled_symclk_fe(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
+{
+       uint8_t num_enabled_symclk_fe = 0;
+       uint32_t be_clk_en = 0, fe_clk_en[4] = {0}, be_clk_sel[4] = {0};
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       switch (link_enc_inst) {
+       case 0:
+               REG_GET_3(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, &be_clk_en,
+                               SYMCLKA_FE_EN, &fe_clk_en[0],
+                               SYMCLKA_FE_SRC_SEL, &be_clk_sel[0]);
+                               break;
+       case 1:
+               REG_GET_3(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, &be_clk_en,
+                               SYMCLKB_FE_EN, &fe_clk_en[1],
+                               SYMCLKB_FE_SRC_SEL, &be_clk_sel[1]);
+                               break;
+       case 2:
+                       REG_GET_3(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, &be_clk_en,
+                               SYMCLKC_FE_EN, &fe_clk_en[2],
+                               SYMCLKC_FE_SRC_SEL, &be_clk_sel[2]);
+                               break;
+       case 3:
+                       REG_GET_3(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, &be_clk_en,
+                               SYMCLKD_FE_EN, &fe_clk_en[3],
+                               SYMCLKD_FE_SRC_SEL, &be_clk_sel[3]);
+                               break;
+       }
+       if (be_clk_en) {
+       /* for DPMST, this backend could be used by multiple front end.
+       only disable the backend if this stream_enc_ins is the last active stream enc connected to this back_end*/
+               uint8_t i;
+               for (i = 0; i != link_enc_inst && i < sizeof(fe_clk_en); i++) {
+                       if (fe_clk_en[i] && be_clk_sel[i] == link_enc_inst)
+                               num_enabled_symclk_fe++;
+               }
+       }
+       return num_enabled_symclk_fe;
+}
+
+static void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
+{
+       uint8_t num_enabled_symclk_fe = 0;
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       switch (stream_enc_inst) {
+       case 0:
+               REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE,
+                               SYMCLKA_FE_EN, 0,
+                               SYMCLKA_FE_SRC_SEL, 0);
+               break;
+       case 1:
+               REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE,
+                               SYMCLKB_FE_EN, 0,
+                               SYMCLKB_FE_SRC_SEL, 0);
+               break;
+       case 2:
+               REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE,
+                               SYMCLKC_FE_EN, 0,
+                               SYMCLKC_FE_SRC_SEL, 0);
+               break;
+       case 3:
+               REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE,
+                               SYMCLKD_FE_EN, 0,
+                               SYMCLKD_FE_SRC_SEL, 0);
+               break;
+       }
+
+       /*check other enabled symclk fe */
+       num_enabled_symclk_fe = dccg401_get_other_enabled_symclk_fe(dccg, stream_enc_inst, link_enc_inst);
+       /*only turn off backend clk if other front end attachecd to this backend are all off,
+        for mst, only turn off the backend if this is the last front end*/
+       if (num_enabled_symclk_fe == 0) {
+               switch (link_enc_inst) {
+               case 0:
+                       REG_UPDATE(SYMCLKA_CLOCK_ENABLE,
+                                       SYMCLKA_CLOCK_ENABLE, 0);
+                       break;
+               case 1:
+                       REG_UPDATE(SYMCLKB_CLOCK_ENABLE,
+                                       SYMCLKB_CLOCK_ENABLE, 0);
+                       break;
+               case 2:
+                       REG_UPDATE(SYMCLKC_CLOCK_ENABLE,
+                                       SYMCLKC_CLOCK_ENABLE, 0);
+                       break;
+               case 3:
+                       REG_UPDATE(SYMCLKD_CLOCK_ENABLE,
+                                       SYMCLKD_CLOCK_ENABLE, 0);
+                       break;
+               }
+       }
+}
 
 static const struct dccg_funcs dccg401_funcs = {
        .update_dpp_dto = dccg401_update_dpp_dto,
@@ -806,6 +963,8 @@ static const struct dccg_funcs dccg401_funcs = {
        .otg_drop_pixel = dccg401_otg_drop_pixel,
        .set_pixel_rate_div = dccg401_set_pixel_rate_div,
        .set_dp_dto = dccg401_set_dp_dto,
+       .enable_symclk_se = dccg401_enable_symclk_se,
+       .disable_symclk_se = dccg401_disable_symclk_se,
        .set_dtbclk_p_src = dccg401_set_dtbclk_p_src,
 };
 
index 8d9e26a760a33430798776f22ef6d8b28ae86e3e..8bcddc8363472b9ae87334202144698533bbc59d 100644 (file)
        DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, mask_sh),\
        DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, mask_sh),\
        DCCG_SF(DCCG_GATE_DISABLE_CNTL6, HDMISTREAMCLK0_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, mask_sh),\
+       DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, mask_sh),\
+       DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, mask_sh),\
+       DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, mask_sh),\
+       DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, mask_sh),\
+       DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, mask_sh),\
+       DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, mask_sh),\
+       DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, mask_sh),\
+       DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_SRC_SEL, mask_sh),\
 
 void dccg401_init(struct dccg *dccg);
 
index c01cf2a2f786a95c71d007cb4507895fe277bc05..c3bed33eb5d658643f942ea9ad5226f28264b02b 100644 (file)
@@ -32,6 +32,7 @@
 #include "dcn401_hwseq.h"
 #include "dcn401/dcn401_resource.h"
 #include "dc_state_priv.h"
+#include "link_enc_cfg.h"
 
 #define DC_LOGGER_INIT(logger)
 
@@ -966,6 +967,8 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx)
        int dp_hpo_inst = 0;
        unsigned int tmds_div = PIXEL_RATE_DIV_NA;
        unsigned int unused_div = PIXEL_RATE_DIV_NA;
+       struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link);
+       struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
 
        dcn401_enable_stream_calc(pipe_ctx, &dp_hpo_inst, &phyd32clk,
                                &tmds_div, &early_control);
@@ -978,6 +981,8 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx)
                } else {
                        /* need to set DTBCLK_P source to DPREFCLK for DP8B10B */
                        dccg->funcs->set_dtbclk_p_src(dccg, DPREFCLK, tg->inst);
+                       dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst,
+                                       link_enc->transmitter - TRANSMITTER_UNIPHY_A);
                }
        }
 
index d4dce2b4b6c1cb346b3219b0c48545698b7a9f46..5d5e01903ca1a4e2f6eb7b3c2b0dc0bcdb81fc71 100644 (file)
@@ -576,6 +576,10 @@ bool dcn401_validate_bandwidth(struct dc *dc,
        SR(DCCG_GATE_DISABLE_CNTL3),\
        SR(DCCG_GATE_DISABLE_CNTL4),\
        SR(DCCG_GATE_DISABLE_CNTL5),\
-       SR(DCCG_GATE_DISABLE_CNTL6)
+       SR(DCCG_GATE_DISABLE_CNTL6),\
+       SR(SYMCLKA_CLOCK_ENABLE),\
+       SR(SYMCLKB_CLOCK_ENABLE),\
+       SR(SYMCLKC_CLOCK_ENABLE),\
+       SR(SYMCLKD_CLOCK_ENABLE)
 
 #endif /* _DCN401_RESOURCE_H_ */