Commit d76b12da authored by Fangzhi Zuo's avatar Fangzhi Zuo Committed by Alex Deucher
Browse files

drm/amd/display: Add DP 2.0 DCCG



HW Blocks:

        +--------+  +-----+  +------+
        |  OPTC  |  | HDA |  | HUBP |
        +--------+  +-----+  +------+
            |          |        |
            |          |        |
    HPO ====|==========|========|====
     |      |          v        |
     |      |       +-----+     |
     |      |       | APG |     |
     |      |       +-----+     |
     |      |          |        |
     |      v          v        v
     |     +---------------------+
     |     |  HPO Stream Encoder |
     |     +---------------------+
     |                 |
     |                 v
     |      +--------------------+
     |      |  HPO Link Encoder  |
     |      +--------------------+
     |                 |
     v  ===============|=============
                       v
              +------------------+
              |  DIO Output Mux  |
              +------------------+
                       |
                       v
                    +-----+
                    | PHY |
                    +-----+
                       | PHYD32CLK[0]
                       v
                    +------+
                    | DCCG |
                    +------+
                       |
                       v
                   SYMCLK32

Signed-off-by: default avatarFangzhi Zuo <Jerry.Zuo@amd.com>
Reviewed-by: default avatarNicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 3bc8d921
Loading
Loading
Loading
Loading
+162 −0
Original line number Diff line number Diff line
@@ -42,6 +42,155 @@
#define DC_LOGGER \
	dccg->ctx->logger

void dccg31_set_dpstreamclk(
		struct dccg *dccg,
		enum hdmistreamclk_source src,
		int otg_inst)
{
	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);

	/* enabled to select one of the DTBCLKs for pipe */
	switch (otg_inst) {
	case 0:
		REG_UPDATE(DPSTREAMCLK_CNTL,
				DPSTREAMCLK_PIPE0_EN, (src == REFCLK) ? 0 : 1);
		break;
	case 1:
		REG_UPDATE(DPSTREAMCLK_CNTL,
				DPSTREAMCLK_PIPE1_EN, (src == REFCLK) ? 0 : 1);
		break;
	case 2:
		REG_UPDATE(DPSTREAMCLK_CNTL,
				DPSTREAMCLK_PIPE2_EN, (src == REFCLK) ? 0 : 1);
		break;
	case 3:
		REG_UPDATE(DPSTREAMCLK_CNTL,
				DPSTREAMCLK_PIPE3_EN, (src == REFCLK) ? 0 : 1);
		break;
	default:
		BREAK_TO_DEBUGGER();
		return;
	}
}

void dccg31_enable_symclk32_se(
		struct dccg *dccg,
		int hpo_se_inst,
		enum phyd32clk_clock_source phyd32clk)
{
	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);

	/* select one of the PHYD32CLKs as the source for symclk32_se */
	switch (hpo_se_inst) {
	case 0:
		REG_UPDATE_2(SYMCLK32_SE_CNTL,
				SYMCLK32_SE0_SRC_SEL, phyd32clk,
				SYMCLK32_SE0_EN, 1);
		break;
	case 1:
		REG_UPDATE_2(SYMCLK32_SE_CNTL,
				SYMCLK32_SE1_SRC_SEL, phyd32clk,
				SYMCLK32_SE1_EN, 1);
		break;
	case 2:
		REG_UPDATE_2(SYMCLK32_SE_CNTL,
				SYMCLK32_SE2_SRC_SEL, phyd32clk,
				SYMCLK32_SE2_EN, 1);
		break;
	case 3:
		REG_UPDATE_2(SYMCLK32_SE_CNTL,
				SYMCLK32_SE3_SRC_SEL, phyd32clk,
				SYMCLK32_SE3_EN, 1);
		break;
	default:
		BREAK_TO_DEBUGGER();
		return;
	}
}

void dccg31_disable_symclk32_se(
		struct dccg *dccg,
		int hpo_se_inst)
{
	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);

	/* set refclk as the source for symclk32_se */
	switch (hpo_se_inst) {
	case 0:
		REG_UPDATE_2(SYMCLK32_SE_CNTL,
				SYMCLK32_SE0_SRC_SEL, 0,
				SYMCLK32_SE0_EN, 0);
		break;
	case 1:
		REG_UPDATE_2(SYMCLK32_SE_CNTL,
				SYMCLK32_SE1_SRC_SEL, 0,
				SYMCLK32_SE1_EN, 0);
		break;
	case 2:
		REG_UPDATE_2(SYMCLK32_SE_CNTL,
				SYMCLK32_SE2_SRC_SEL, 0,
				SYMCLK32_SE2_EN, 0);
		break;
	case 3:
		REG_UPDATE_2(SYMCLK32_SE_CNTL,
				SYMCLK32_SE3_SRC_SEL, 0,
				SYMCLK32_SE3_EN, 0);
		break;
	default:
		BREAK_TO_DEBUGGER();
		return;
	}
}

void dccg31_enable_symclk32_le(
		struct dccg *dccg,
		int hpo_le_inst,
		enum phyd32clk_clock_source phyd32clk)
{
	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);

	/* select one of the PHYD32CLKs as the source for symclk32_le */
	switch (hpo_le_inst) {
	case 0:
		REG_UPDATE_2(SYMCLK32_LE_CNTL,
				SYMCLK32_LE0_SRC_SEL, phyd32clk,
				SYMCLK32_LE0_EN, 1);
		break;
	case 1:
		REG_UPDATE_2(SYMCLK32_LE_CNTL,
				SYMCLK32_LE1_SRC_SEL, phyd32clk,
				SYMCLK32_LE1_EN, 1);
		break;
	default:
		BREAK_TO_DEBUGGER();
		return;
	}
}

void dccg31_disable_symclk32_le(
		struct dccg *dccg,
		int hpo_le_inst)
{
	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);

	/* set refclk as the source for symclk32_le */
	switch (hpo_le_inst) {
	case 0:
		REG_UPDATE_2(SYMCLK32_LE_CNTL,
				SYMCLK32_LE0_SRC_SEL, 0,
				SYMCLK32_LE0_EN, 0);
		break;
	case 1:
		REG_UPDATE_2(SYMCLK32_LE_CNTL,
				SYMCLK32_LE1_SRC_SEL, 0,
				SYMCLK32_LE1_EN, 0);
		break;
	default:
		BREAK_TO_DEBUGGER();
		return;
	}
}

void dccg31_set_physymclk(
		struct dccg *dccg,
		int phy_inst,
@@ -241,12 +390,25 @@ static void dccg31_set_dispclk_change_mode(

void dccg31_init(struct dccg *dccg)
{
	/* Set HPO stream encoder to use refclk to avoid case where PHY is
	 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
	 * will cause DCN to hang.
	 */
	dccg31_disable_symclk32_se(dccg, 0);
	dccg31_disable_symclk32_se(dccg, 1);
	dccg31_disable_symclk32_se(dccg, 2);
	dccg31_disable_symclk32_se(dccg, 3);
}

static const struct dccg_funcs dccg31_funcs = {
	.update_dpp_dto = dccg2_update_dpp_dto,
	.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
	.dccg_init = dccg31_init,
	.set_dpstreamclk = dccg31_set_dpstreamclk,
	.enable_symclk32_se = dccg31_enable_symclk32_se,
	.disable_symclk32_se = dccg31_disable_symclk32_se,
	.enable_symclk32_le = dccg31_enable_symclk32_le,
	.disable_symclk32_le = dccg31_disable_symclk32_le,
	.set_physymclk = dccg31_set_physymclk,
	.set_dtbclk_dto = dccg31_set_dtbclk_dto,
	.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
+18 −0
Original line number Diff line number Diff line
@@ -130,6 +130,24 @@ struct dccg *dccg31_create(

void dccg31_init(struct dccg *dccg);

void dccg31_enable_symclk32_se(
		struct dccg *dccg,
		int hpo_se_inst,
		enum phyd32clk_clock_source phyd32clk);

void dccg31_disable_symclk32_se(
		struct dccg *dccg,
		int hpo_se_inst);

void dccg31_enable_symclk32_le(
		struct dccg *dccg,
		int hpo_le_inst,
		enum phyd32clk_clock_source phyd32clk);

void dccg31_disable_symclk32_le(
		struct dccg *dccg,
		int hpo_le_inst);

void dccg31_set_physymclk(
		struct dccg *dccg,
		int phy_inst,
+23 −0
Original line number Diff line number Diff line
@@ -79,7 +79,30 @@ struct dccg_funcs {
	void (*otg_drop_pixel)(struct dccg *dccg,
			uint32_t otg_inst);
	void (*dccg_init)(struct dccg *dccg);
#if defined(CONFIG_DRM_AMD_DC_DCN)
	void (*set_dpstreamclk)(
			struct dccg *dccg,
			enum hdmistreamclk_source src,
			int otg_inst);

	void (*enable_symclk32_se)(
			struct dccg *dccg,
			int hpo_se_inst,
			enum phyd32clk_clock_source phyd32clk);

	void (*disable_symclk32_se)(
			struct dccg *dccg,
			int hpo_se_inst);

	void (*enable_symclk32_le)(
			struct dccg *dccg,
			int hpo_le_inst,
			enum phyd32clk_clock_source phyd32clk);

	void (*disable_symclk32_le)(
			struct dccg *dccg,
			int hpo_le_inst);
#endif
	void (*set_physymclk)(
			struct dccg *dccg,
			int phy_inst,
+3 −0
Original line number Diff line number Diff line
@@ -100,6 +100,9 @@ enum crc_selection {

enum otg_out_mux_dest {
	OUT_MUX_DIO = 0,
#if defined(CONFIG_DRM_AMD_DC_DCN)
	OUT_MUX_HPO_DP = 2,
#endif
};

enum h_timing_div_mode {