[PATCH 03/24] drm/amd/display: Add missing enable and disable symclk_se functions for dcn401

Roman.Li at amd.com Roman.Li at amd.com
Thu May 16 19:26:26 UTC 2024


From: Wenjing Liu <wenjing.liu at amd.com>

The functions are missing. These two functions are required to support
MST.

Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira at amd.com>
Signed-off-by: Wenjing Liu <wenjing.liu at amd.com>
---
 .../amd/display/dc/dccg/dcn401/dcn401_dccg.c  | 159 ++++++++++++++++++
 .../amd/display/dc/dccg/dcn401/dcn401_dccg.h  |  12 ++
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c |   5 +
 .../dc/resource/dcn401/dcn401_resource.h      |   6 +-
 4 files changed, 181 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
index 72cbff8632dd..a496a250f892 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
@@ -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,
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h
index 8d9e26a760a3..8bcddc836347 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h
@@ -181,6 +181,18 @@
 	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);
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index c01cf2a2f786..c3bed33eb5d6 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -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);
 		}
 	}
 
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
index d4dce2b4b6c1..5d5e01903ca1 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
@@ -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_ */
-- 
2.34.1



More information about the amd-gfx mailing list