brintos

brintos / linux-shallow public Read only

0
0
Text · 26.8 KiB · 0b88900 Raw
999 lines · c
1/*2 * Copyright 2023 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26#include "reg_helper.h"27#include "core_types.h"28#include "dcn401_dccg.h"29#include "dcn31/dcn31_dccg.h"30 31/*32#include "dmub_common.h"33#include "dmcub_reg_access_helper.h"34 35#include "dmub401_common.h"36#include "dmub401_regs.h"37#include "dmub401_dccg.h"38*/39 40#define TO_DCN_DCCG(dccg)\41	container_of(dccg, struct dcn_dccg, base)42 43#define REG(reg) \44	(dccg_dcn->regs->reg)45 46#undef FN47#define FN(reg_name, field_name) \48	dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name49 50#define CTX \51	dccg_dcn->base.ctx52#define DC_LOGGER \53	dccg->ctx->logger54 55static void dcn401_set_dppclk_enable(struct dccg *dccg,56				 uint32_t dpp_inst, uint32_t enable)57{58	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);59 60	switch (dpp_inst) {61	case 0:62		REG_UPDATE(DPPCLK_CTRL, DPPCLK0_EN, enable);63		break;64	case 1:65		REG_UPDATE(DPPCLK_CTRL, DPPCLK1_EN, enable);66		break;67	case 2:68		REG_UPDATE(DPPCLK_CTRL, DPPCLK2_EN, enable);69		break;70	case 3:71		REG_UPDATE(DPPCLK_CTRL, DPPCLK3_EN, enable);72		break;73	default:74		break;75	}76}77void dccg401_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppclk)78{79	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);80 81	if (dccg->ref_dppclk && req_dppclk) {82		int ref_dppclk = dccg->ref_dppclk;83		int modulo, phase;84 85		// phase / modulo = dpp pipe clk / dpp global clk86		modulo = 0xff;   // use FF at the end87		phase = ((modulo * req_dppclk) + ref_dppclk - 1) / ref_dppclk;88 89		if (phase > 0xff) {90			ASSERT(false);91			phase = 0xff;92		}93 94		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,95				DPPCLK0_DTO_PHASE, phase,96				DPPCLK0_DTO_MODULO, modulo);97		dcn401_set_dppclk_enable(dccg, dpp_inst, true);98	} else {99		dcn401_set_dppclk_enable(dccg, dpp_inst, false);100	}101 102	dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk;103}104 105/* This function is a workaround for writing to OTG_PIXEL_RATE_DIV106 * without the probability of causing a DIG FIFO error.107 */108static void dccg401_wait_for_dentist_change_done(109	struct dccg *dccg)110{111	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);112 113	uint32_t dentist_dispclk_value = REG_READ(DENTIST_DISPCLK_CNTL);114 115	REG_WRITE(DENTIST_DISPCLK_CNTL, dentist_dispclk_value);116	REG_WAIT(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, 1, 50, 2000);117}118 119static void dccg401_get_pixel_rate_div(120		struct dccg *dccg,121		uint32_t otg_inst,122		uint32_t *tmds_div,123		uint32_t *dp_dto_int)124{125	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);126	uint32_t val_tmds_div = PIXEL_RATE_DIV_NA;127 128	switch (otg_inst) {129	case 0:130		REG_GET_2(OTG_PIXEL_RATE_DIV,131			OTG0_TMDS_PIXEL_RATE_DIV, &val_tmds_div,132			DPDTO0_INT, dp_dto_int);133		break;134	case 1:135		REG_GET_2(OTG_PIXEL_RATE_DIV,136			OTG1_TMDS_PIXEL_RATE_DIV, &val_tmds_div,137			DPDTO1_INT, dp_dto_int);138		break;139	case 2:140		REG_GET_2(OTG_PIXEL_RATE_DIV,141			OTG2_TMDS_PIXEL_RATE_DIV, &val_tmds_div,142			DPDTO2_INT, dp_dto_int);143		break;144	case 3:145		REG_GET_2(OTG_PIXEL_RATE_DIV,146			OTG3_TMDS_PIXEL_RATE_DIV, &val_tmds_div,147			DPDTO3_INT, dp_dto_int);148		break;149	default:150		BREAK_TO_DEBUGGER();151		return;152	}153 154	*tmds_div = val_tmds_div == 0 ? PIXEL_RATE_DIV_BY_2 : PIXEL_RATE_DIV_BY_4;155}156 157static void dccg401_set_pixel_rate_div(158		struct dccg *dccg,159		uint32_t otg_inst,160		enum pixel_rate_div tmds_div,161		enum pixel_rate_div unused)162{163	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);164	uint32_t cur_tmds_div = PIXEL_RATE_DIV_NA;165	uint32_t dp_dto_int;166	uint32_t reg_val;167 168	// only 2 and 4 are valid on dcn401169	if (tmds_div != PIXEL_RATE_DIV_BY_2 && tmds_div != PIXEL_RATE_DIV_BY_4) {170		return;171	}172 173	dccg401_get_pixel_rate_div(dccg, otg_inst, &cur_tmds_div, &dp_dto_int);174	if (tmds_div == cur_tmds_div)175		return;176 177	// encode enum to register value178	reg_val = tmds_div == PIXEL_RATE_DIV_BY_4 ? 1 : 0;179 180	switch (otg_inst) {181	case 0:182		REG_UPDATE(OTG_PIXEL_RATE_DIV,183				OTG0_TMDS_PIXEL_RATE_DIV, reg_val);184 185		dccg401_wait_for_dentist_change_done(dccg);186		break;187	case 1:188		REG_UPDATE(OTG_PIXEL_RATE_DIV,189				OTG1_TMDS_PIXEL_RATE_DIV, reg_val);190 191		dccg401_wait_for_dentist_change_done(dccg);192		break;193	case 2:194		REG_UPDATE(OTG_PIXEL_RATE_DIV,195				OTG2_TMDS_PIXEL_RATE_DIV, reg_val);196 197		dccg401_wait_for_dentist_change_done(dccg);198		break;199	case 3:200		REG_UPDATE(OTG_PIXEL_RATE_DIV,201				OTG3_TMDS_PIXEL_RATE_DIV, reg_val);202 203		dccg401_wait_for_dentist_change_done(dccg);204		break;205	default:206		BREAK_TO_DEBUGGER();207		return;208	}209}210 211 212static void dccg401_set_dtbclk_p_src(213		struct dccg *dccg,214		enum streamclk_source src,215		uint32_t otg_inst)216{217	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);218 219	uint32_t p_src_sel = 0; /* selects dprefclk */220	if (src == DTBCLK0)221		p_src_sel = 2;  /* selects dtbclk0 */222 223	switch (otg_inst) {224	case 0:225		if (src == REFCLK)226			REG_UPDATE(DTBCLK_P_CNTL,227					DTBCLK_P0_EN, 0);228		else229			REG_UPDATE_2(DTBCLK_P_CNTL,230					DTBCLK_P0_SRC_SEL, p_src_sel,231					DTBCLK_P0_EN, 1);232		break;233	case 1:234		if (src == REFCLK)235			REG_UPDATE(DTBCLK_P_CNTL,236					DTBCLK_P1_EN, 0);237		else238			REG_UPDATE_2(DTBCLK_P_CNTL,239					DTBCLK_P1_SRC_SEL, p_src_sel,240					DTBCLK_P1_EN, 1);241		break;242	case 2:243		if (src == REFCLK)244			REG_UPDATE(DTBCLK_P_CNTL,245					DTBCLK_P2_EN, 0);246		else247			REG_UPDATE_2(DTBCLK_P_CNTL,248					DTBCLK_P2_SRC_SEL, p_src_sel,249					DTBCLK_P2_EN, 1);250		break;251	case 3:252		if (src == REFCLK)253			REG_UPDATE(DTBCLK_P_CNTL,254					DTBCLK_P3_EN, 0);255		else256			REG_UPDATE_2(DTBCLK_P_CNTL,257					DTBCLK_P3_SRC_SEL, p_src_sel,258					DTBCLK_P3_EN, 1);259		break;260	default:261		BREAK_TO_DEBUGGER();262		return;263	}264 265}266 267void dccg401_set_physymclk(268		struct dccg *dccg,269		int phy_inst,270		enum physymclk_clock_source clk_src,271		bool force_enable)272{273	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);274 275	/* Force PHYSYMCLK on and Select phyd32clk as the source of clock which is output to PHY through DCIO */276	switch (phy_inst) {277	case 0:278		if (force_enable) {279			REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,280					PHYASYMCLK_EN, 1,281					PHYASYMCLK_SRC_SEL, clk_src);282			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)283				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,284					PHYASYMCLK_ROOT_GATE_DISABLE, 1);285		} else {286			REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,287					PHYASYMCLK_EN, 0,288					PHYASYMCLK_SRC_SEL, 0);289			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)290				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,291					PHYASYMCLK_ROOT_GATE_DISABLE, 0);292		}293		break;294	case 1:295		if (force_enable) {296			REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,297					PHYBSYMCLK_EN, 1,298					PHYBSYMCLK_SRC_SEL, clk_src);299			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)300				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,301					PHYBSYMCLK_ROOT_GATE_DISABLE, 1);302		} else {303			REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,304					PHYBSYMCLK_EN, 0,305					PHYBSYMCLK_SRC_SEL, 0);306			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)307				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,308					PHYBSYMCLK_ROOT_GATE_DISABLE, 0);309		}310		break;311	case 2:312		if (force_enable) {313			REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,314					PHYCSYMCLK_EN, 1,315					PHYCSYMCLK_SRC_SEL, clk_src);316			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)317				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,318					PHYCSYMCLK_ROOT_GATE_DISABLE, 1);319		} else {320			REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,321					PHYCSYMCLK_EN, 0,322					PHYCSYMCLK_SRC_SEL, 0);323			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)324				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,325					PHYCSYMCLK_ROOT_GATE_DISABLE, 0);326		}327		break;328	case 3:329		if (force_enable) {330			REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,331					PHYDSYMCLK_EN, 1,332					PHYDSYMCLK_SRC_SEL, clk_src);333			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)334				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,335					PHYDSYMCLK_ROOT_GATE_DISABLE, 1);336		} else {337			REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,338					PHYDSYMCLK_EN, 0,339					PHYDSYMCLK_SRC_SEL, 0);340			if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)341				REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,342					PHYDSYMCLK_ROOT_GATE_DISABLE, 0);343		}344		break;345	default:346		BREAK_TO_DEBUGGER();347		return;348	}349}350 351static void dccg401_get_dccg_ref_freq(struct dccg *dccg,352		unsigned int xtalin_freq_inKhz,353		unsigned int *dccg_ref_freq_inKhz)354{355	/*356	 * Assume refclk is sourced from xtalin357	 * expect 100MHz358	 */359	*dccg_ref_freq_inKhz = xtalin_freq_inKhz;360	return;361}362 363static void dccg401_otg_add_pixel(struct dccg *dccg,364		uint32_t otg_inst)365{366	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);367 368	REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],369			OTG_ADD_PIXEL[otg_inst], 1);370}371 372static void dccg401_otg_drop_pixel(struct dccg *dccg,373		uint32_t otg_inst)374{375	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);376 377	REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],378			OTG_DROP_PIXEL[otg_inst], 1);379}380 381static void dccg401_enable_symclk32_le(382		struct dccg *dccg,383		int hpo_le_inst,384		enum phyd32clk_clock_source phyd32clk)385{386	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);387 388	/* select one of the PHYD32CLKs as the source for symclk32_le */389	switch (hpo_le_inst) {390	case 0:391		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)392			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,393					SYMCLK32_LE0_GATE_DISABLE, 1,394					SYMCLK32_ROOT_LE0_GATE_DISABLE, 1);395		REG_UPDATE_2(SYMCLK32_LE_CNTL,396				SYMCLK32_LE0_SRC_SEL, phyd32clk,397				SYMCLK32_LE0_EN, 1);398		break;399	case 1:400		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)401			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,402					SYMCLK32_LE1_GATE_DISABLE, 1,403					SYMCLK32_ROOT_LE1_GATE_DISABLE, 1);404		REG_UPDATE_2(SYMCLK32_LE_CNTL,405				SYMCLK32_LE1_SRC_SEL, phyd32clk,406				SYMCLK32_LE1_EN, 1);407		break;408	case 2:409		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)410			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,411					SYMCLK32_LE2_GATE_DISABLE, 1,412					SYMCLK32_ROOT_LE2_GATE_DISABLE, 1);413		REG_UPDATE_2(SYMCLK32_LE_CNTL,414				SYMCLK32_LE2_SRC_SEL, phyd32clk,415				SYMCLK32_LE2_EN, 1);416		break;417	case 3:418		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)419			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,420					SYMCLK32_LE3_GATE_DISABLE, 1,421					SYMCLK32_ROOT_LE3_GATE_DISABLE, 1);422		REG_UPDATE_2(SYMCLK32_LE_CNTL,423				SYMCLK32_LE3_SRC_SEL, phyd32clk,424				SYMCLK32_LE3_EN, 1);425		break;426	default:427		BREAK_TO_DEBUGGER();428		return;429	}430}431 432static void dccg401_disable_symclk32_le(433		struct dccg *dccg,434		int hpo_le_inst)435{436	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);437 438	/* set refclk as the source for symclk32_le */439	switch (hpo_le_inst) {440	case 0:441		REG_UPDATE_2(SYMCLK32_LE_CNTL,442				SYMCLK32_LE0_SRC_SEL, 0,443				SYMCLK32_LE0_EN, 0);444		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)445			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,446					SYMCLK32_LE0_GATE_DISABLE, 0,447					SYMCLK32_ROOT_LE0_GATE_DISABLE, 0);448		break;449	case 1:450		REG_UPDATE_2(SYMCLK32_LE_CNTL,451				SYMCLK32_LE1_SRC_SEL, 0,452				SYMCLK32_LE1_EN, 0);453		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)454			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,455					SYMCLK32_LE1_GATE_DISABLE, 0,456					SYMCLK32_ROOT_LE1_GATE_DISABLE, 0);457		break;458	case 2:459		REG_UPDATE_2(SYMCLK32_LE_CNTL,460				SYMCLK32_LE2_SRC_SEL, 0,461				SYMCLK32_LE2_EN, 0);462		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)463			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,464					SYMCLK32_LE2_GATE_DISABLE, 0,465					SYMCLK32_ROOT_LE2_GATE_DISABLE, 0);466		break;467	case 3:468		REG_UPDATE_2(SYMCLK32_LE_CNTL,469				SYMCLK32_LE3_SRC_SEL, 0,470				SYMCLK32_LE3_EN, 0);471		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)472			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,473					SYMCLK32_LE3_GATE_DISABLE, 0,474					SYMCLK32_ROOT_LE3_GATE_DISABLE, 0);475		break;476	default:477		BREAK_TO_DEBUGGER();478		return;479	}480}481 482static void dccg401_enable_dpstreamclk(struct dccg *dccg, int otg_inst, int dp_hpo_inst)483{484	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);485 486	/* enabled to select one of the DTBCLKs for pipe */487	switch (dp_hpo_inst) {488	case 0:489		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)490			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,491					DPSTREAMCLK0_ROOT_GATE_DISABLE, 1,492					DPSTREAMCLK0_GATE_DISABLE, 1);493		REG_UPDATE_2(DPSTREAMCLK_CNTL,494				DPSTREAMCLK0_SRC_SEL, otg_inst,495				DPSTREAMCLK0_EN, 1);496		break;497	case 1:498		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)499			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,500					DPSTREAMCLK1_ROOT_GATE_DISABLE, 1,501					DPSTREAMCLK1_GATE_DISABLE, 1);502		REG_UPDATE_2(DPSTREAMCLK_CNTL,503				DPSTREAMCLK1_SRC_SEL, otg_inst,504				DPSTREAMCLK1_EN, 1);505		break;506	case 2:507		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)508			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,509					DPSTREAMCLK2_ROOT_GATE_DISABLE, 1,510					DPSTREAMCLK2_GATE_DISABLE, 1);511		REG_UPDATE_2(DPSTREAMCLK_CNTL,512				DPSTREAMCLK2_SRC_SEL, otg_inst,513				DPSTREAMCLK2_EN, 1);514		break;515	case 3:516		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)517			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,518					DPSTREAMCLK3_ROOT_GATE_DISABLE, 1,519					DPSTREAMCLK3_GATE_DISABLE, 1);520		REG_UPDATE_2(DPSTREAMCLK_CNTL,521				DPSTREAMCLK3_SRC_SEL, otg_inst,522				DPSTREAMCLK3_EN, 1);523		break;524	default:525		BREAK_TO_DEBUGGER();526		return;527	}528	if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)529		REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,530			DPSTREAMCLK_GATE_DISABLE, 1,531			DPSTREAMCLK_ROOT_GATE_DISABLE, 1);532}533 534static void dccg401_disable_dpstreamclk(struct dccg *dccg, int dp_hpo_inst)535{536	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);537 538	switch (dp_hpo_inst) {539	case 0:540		REG_UPDATE(DPSTREAMCLK_CNTL,541				DPSTREAMCLK0_EN, 0);542		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)543			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,544					DPSTREAMCLK0_ROOT_GATE_DISABLE, 0,545					DPSTREAMCLK0_GATE_DISABLE, 0);546		break;547	case 1:548		REG_UPDATE(DPSTREAMCLK_CNTL,549				DPSTREAMCLK1_EN, 0);550		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)551			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,552					DPSTREAMCLK1_ROOT_GATE_DISABLE, 0,553					DPSTREAMCLK1_GATE_DISABLE, 0);554		break;555	case 2:556		REG_UPDATE(DPSTREAMCLK_CNTL,557				DPSTREAMCLK2_EN, 0);558		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)559			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,560					DPSTREAMCLK2_ROOT_GATE_DISABLE, 0,561					DPSTREAMCLK2_GATE_DISABLE, 0);562		break;563	case 3:564		REG_UPDATE(DPSTREAMCLK_CNTL,565				DPSTREAMCLK3_EN, 0);566		if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)567			REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL5,568					DPSTREAMCLK3_ROOT_GATE_DISABLE, 0,569					DPSTREAMCLK3_GATE_DISABLE, 0);570		break;571	default:572		BREAK_TO_DEBUGGER();573		return;574	}575}576 577static void dccg401_set_dpstreamclk(578		struct dccg *dccg,579		enum streamclk_source src,580		int otg_inst,581		int dp_hpo_inst)582{583	/* set the dtbclk_p source */584	dccg401_set_dtbclk_p_src(dccg, src, otg_inst);585 586	/* enabled to select one of the DTBCLKs for pipe */587	if (src == REFCLK)588		dccg401_disable_dpstreamclk(dccg, dp_hpo_inst);589	else590		dccg401_enable_dpstreamclk(dccg, otg_inst, dp_hpo_inst);591}592 593static void dccg401_set_dp_dto(594		struct dccg *dccg,595		const struct dp_dto_params *params)596{597	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);598 599	bool enable = false;600 601	if (params->otg_inst > 3) {602		/* dcn401 only has 4 instances */603		BREAK_TO_DEBUGGER();604		return;605	}606	if (!params->refclk_hz) {607		BREAK_TO_DEBUGGER();608		return;609	}610 611	if (!dc_is_tmds_signal(params->signal)) {612		uint64_t dto_integer;613		uint64_t dto_phase_hz;614		uint64_t dto_modulo_hz = params->refclk_hz;615 616		enable = true;617 618		/* Set DTO values:619		 * int = target_pix_rate / reference_clock620		 * phase = target_pix_rate - int * reference_clock,621		 * modulo = reference_clock */622		dto_integer = div_u64(params->pixclk_hz, dto_modulo_hz);623		dto_phase_hz = params->pixclk_hz - dto_integer * dto_modulo_hz;624 625		if (dto_phase_hz <= 0) {626			/* negative pixel rate should never happen */627			BREAK_TO_DEBUGGER();628			return;629		}630 631		switch (params->otg_inst) {632		case 0:633			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, 1);634			REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3,635					SYMCLK32_SE0_GATE_DISABLE, 1,636					SYMCLK32_ROOT_SE0_GATE_DISABLE, 1,637					SYMCLK32_LE0_GATE_DISABLE, 1,638					SYMCLK32_ROOT_LE0_GATE_DISABLE, 1);639			break;640		case 1:641			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, 1);642			REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3,643					SYMCLK32_SE1_GATE_DISABLE, 1,644					SYMCLK32_ROOT_SE1_GATE_DISABLE, 1,645					SYMCLK32_LE1_GATE_DISABLE, 1,646					SYMCLK32_ROOT_LE1_GATE_DISABLE, 1);647			break;648		case 2:649			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, 1);650			REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3,651					SYMCLK32_SE2_GATE_DISABLE, 1,652					SYMCLK32_ROOT_SE2_GATE_DISABLE, 1,653					SYMCLK32_LE2_GATE_DISABLE, 1,654					SYMCLK32_ROOT_LE2_GATE_DISABLE, 1);655			break;656		case 3:657			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, 1);658			REG_UPDATE_4(DCCG_GATE_DISABLE_CNTL3,659					SYMCLK32_SE3_GATE_DISABLE, 1,660					SYMCLK32_ROOT_SE3_GATE_DISABLE, 1,661					SYMCLK32_LE3_GATE_DISABLE, 1,662					SYMCLK32_ROOT_LE3_GATE_DISABLE, 1);663			break;664		}665 666		dccg401_set_dtbclk_p_src(dccg, params->clk_src, params->otg_inst);667 668		REG_WRITE(DP_DTO_PHASE[params->otg_inst], dto_phase_hz);669		REG_WRITE(DP_DTO_MODULO[params->otg_inst], dto_modulo_hz);670 671		switch (params->otg_inst) {672		case 0:673			REG_UPDATE(OTG_PIXEL_RATE_DIV,674					DPDTO0_INT, dto_integer);675			break;676		case 1:677			REG_UPDATE(OTG_PIXEL_RATE_DIV,678					DPDTO1_INT, dto_integer);679			break;680		case 2:681			REG_UPDATE(OTG_PIXEL_RATE_DIV,682					DPDTO2_INT, dto_integer);683			break;684		case 3:685			REG_UPDATE(OTG_PIXEL_RATE_DIV,686					DPDTO3_INT, dto_integer);687			break;688		default:689			BREAK_TO_DEBUGGER();690			return;691		}692	}693 694	/* Toggle DTO */695	REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],696			DP_DTO_ENABLE[params->otg_inst], enable,697			PIPE_DTO_SRC_SEL[params->otg_inst], enable);698}699 700void dccg401_init(struct dccg *dccg)701{702	/* Set HPO stream encoder to use refclk to avoid case where PHY is703	 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which704	 * will cause DCN to hang.705	 */706	dccg31_disable_symclk32_se(dccg, 0);707	dccg31_disable_symclk32_se(dccg, 1);708	dccg31_disable_symclk32_se(dccg, 2);709	dccg31_disable_symclk32_se(dccg, 3);710 711	if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) {712		dccg401_disable_symclk32_le(dccg, 0);713		dccg401_disable_symclk32_le(dccg, 1);714		dccg401_disable_symclk32_le(dccg, 2);715		dccg401_disable_symclk32_le(dccg, 3);716	}717 718	if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) {719		dccg401_disable_dpstreamclk(dccg, 0);720		dccg401_disable_dpstreamclk(dccg, 1);721		dccg401_disable_dpstreamclk(dccg, 2);722		dccg401_disable_dpstreamclk(dccg, 3);723	}724 725	if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) {726		dccg401_set_physymclk(dccg, 0, PHYSYMCLK_FORCE_SRC_SYMCLK, false);727		dccg401_set_physymclk(dccg, 1, PHYSYMCLK_FORCE_SRC_SYMCLK, false);728		dccg401_set_physymclk(dccg, 2, PHYSYMCLK_FORCE_SRC_SYMCLK, false);729		dccg401_set_physymclk(dccg, 3, PHYSYMCLK_FORCE_SRC_SYMCLK, false);730	}731}732 733static void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst)734{735	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);736 737	switch (inst) {738	case 0:739		REG_UPDATE_2(DSCCLK0_DTO_PARAM,740				DSCCLK0_DTO_PHASE, 1,741				DSCCLK0_DTO_MODULO, 1);742		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1);743 744		break;745	case 1:746		REG_UPDATE_2(DSCCLK1_DTO_PARAM,747				DSCCLK1_DTO_PHASE, 1,748				DSCCLK1_DTO_MODULO, 1);749		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1);750		break;751	case 2:752		REG_UPDATE_2(DSCCLK2_DTO_PARAM,753				DSCCLK2_DTO_PHASE, 1,754				DSCCLK2_DTO_MODULO, 1);755		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1);756		break;757	case 3:758		REG_UPDATE_2(DSCCLK3_DTO_PARAM,759				DSCCLK3_DTO_PHASE, 1,760				DSCCLK3_DTO_MODULO, 1);761		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 1);762		break;763	default:764		BREAK_TO_DEBUGGER();765		return;766	}767}768 769static void dccg401_set_ref_dscclk(struct dccg *dccg,770				uint32_t dsc_inst)771{772	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);773 774	switch (dsc_inst) {775	case 0:776		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 0);777		REG_UPDATE_2(DSCCLK0_DTO_PARAM,778				DSCCLK0_DTO_PHASE, 0,779				DSCCLK0_DTO_MODULO, 0);780		break;781	case 1:782		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 0);783		REG_UPDATE_2(DSCCLK1_DTO_PARAM,784				DSCCLK1_DTO_PHASE, 0,785				DSCCLK1_DTO_MODULO, 0);786		break;787	case 2:788		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 0);789		REG_UPDATE_2(DSCCLK2_DTO_PARAM,790				DSCCLK2_DTO_PHASE, 0,791				DSCCLK2_DTO_MODULO, 0);792		break;793	case 3:794		REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 0);795		REG_UPDATE_2(DSCCLK3_DTO_PARAM,796				DSCCLK3_DTO_PHASE, 0,797				DSCCLK3_DTO_MODULO, 0);798		break;799	default:800		return;801	}802}803 804static void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)805{806	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);807 808	switch (link_enc_inst) {809	case 0:810		REG_UPDATE(SYMCLKA_CLOCK_ENABLE,811				SYMCLKA_CLOCK_ENABLE, 1);812		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)813			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, 1);814		break;815	case 1:816		REG_UPDATE(SYMCLKB_CLOCK_ENABLE,817				SYMCLKB_CLOCK_ENABLE, 1);818		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)819			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, 1);820		break;821	case 2:822		REG_UPDATE(SYMCLKC_CLOCK_ENABLE,823				SYMCLKC_CLOCK_ENABLE, 1);824		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)825			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, 1);826		break;827	case 3:828		REG_UPDATE(SYMCLKD_CLOCK_ENABLE,829				SYMCLKD_CLOCK_ENABLE, 1);830		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)831			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, 1);832		break;833	}834 835	switch (stream_enc_inst) {836	case 0:837		REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE,838				SYMCLKA_FE_EN, 1,839				SYMCLKA_FE_SRC_SEL, link_enc_inst);840		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)841			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, 1);842		break;843	case 1:844		REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE,845				SYMCLKB_FE_EN, 1,846				SYMCLKB_FE_SRC_SEL, link_enc_inst);847		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)848			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, 1);849		break;850	case 2:851		REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE,852				SYMCLKC_FE_EN, 1,853				SYMCLKC_FE_SRC_SEL, link_enc_inst);854		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)855			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, 1);856		break;857	case 3:858		REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE,859				SYMCLKD_FE_EN, 1,860				SYMCLKD_FE_SRC_SEL, link_enc_inst);861		if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)862			REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, 1);863		break;864	}865}866 867/*get other front end connected to this backend*/868static uint8_t dccg401_get_number_enabled_symclk_fe_connected_to_be(struct dccg *dccg, uint32_t link_enc_inst)869{870	uint8_t num_enabled_symclk_fe = 0;871	uint32_t fe_clk_en[4] = {0}, be_clk_sel[4] = {0};872	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);873	uint8_t i;874 875	REG_GET_2(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, &fe_clk_en[0],876			SYMCLKA_FE_SRC_SEL, &be_clk_sel[0]);877 878	REG_GET_2(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, &fe_clk_en[1],879			SYMCLKB_FE_SRC_SEL, &be_clk_sel[1]);880 881	REG_GET_2(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, &fe_clk_en[2],882			SYMCLKC_FE_SRC_SEL, &be_clk_sel[2]);883 884	REG_GET_2(SYMCLKD_CLOCK_ENABLE,	SYMCLKD_FE_EN, &fe_clk_en[3],885			SYMCLKD_FE_SRC_SEL, &be_clk_sel[3]);886 887	for (i = 0; i < ARRAY_SIZE(fe_clk_en); i++) {888		if (fe_clk_en[i] && be_clk_sel[i] == link_enc_inst)889			num_enabled_symclk_fe++;890	}891 892	return num_enabled_symclk_fe;893}894 895static void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)896{897	uint8_t num_enabled_symclk_fe = 0;898	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);899 900	switch (stream_enc_inst) {901	case 0:902		REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE,903				SYMCLKA_FE_EN, 0,904				SYMCLKA_FE_SRC_SEL, 0);905		break;906	case 1:907		REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE,908				SYMCLKB_FE_EN, 0,909				SYMCLKB_FE_SRC_SEL, 0);910		break;911	case 2:912		REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE,913				SYMCLKC_FE_EN, 0,914				SYMCLKC_FE_SRC_SEL, 0);915		break;916	case 3:917		REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE,918				SYMCLKD_FE_EN, 0,919				SYMCLKD_FE_SRC_SEL, 0);920		break;921	}922 923	/*check other enabled symclk fe connected to this be */924	num_enabled_symclk_fe = dccg401_get_number_enabled_symclk_fe_connected_to_be(dccg, link_enc_inst);925	/*only turn off backend clk if other front ends attached to this backend are all off,926	 for mst, only turn off the backend if this is the last front end*/927	if (num_enabled_symclk_fe == 0) {928		switch (link_enc_inst) {929		case 0:930			REG_UPDATE(SYMCLKA_CLOCK_ENABLE,931					SYMCLKA_CLOCK_ENABLE, 0);932			break;933		case 1:934			REG_UPDATE(SYMCLKB_CLOCK_ENABLE,935					SYMCLKB_CLOCK_ENABLE, 0);936			break;937		case 2:938			REG_UPDATE(SYMCLKC_CLOCK_ENABLE,939					SYMCLKC_CLOCK_ENABLE, 0);940			break;941		case 3:942			REG_UPDATE(SYMCLKD_CLOCK_ENABLE,943					SYMCLKD_CLOCK_ENABLE, 0);944			break;945		}946	}947}948 949static const struct dccg_funcs dccg401_funcs = {950	.update_dpp_dto = dccg401_update_dpp_dto,951	.get_dccg_ref_freq = dccg401_get_dccg_ref_freq,952	.dccg_init = dccg401_init,953	.set_dpstreamclk = dccg401_set_dpstreamclk,954	.enable_symclk32_se = dccg31_enable_symclk32_se,955	.disable_symclk32_se = dccg31_disable_symclk32_se,956	.enable_symclk32_le = dccg401_enable_symclk32_le,957	.disable_symclk32_le = dccg401_disable_symclk32_le,958	.set_physymclk = dccg401_set_physymclk,959	.set_dtbclk_dto = NULL,960	.set_dto_dscclk = dccg401_set_dto_dscclk,961	.set_ref_dscclk = dccg401_set_ref_dscclk,962	.set_valid_pixel_rate = NULL,963	.set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,964	.set_audio_dtbclk_dto = NULL,965	.otg_add_pixel = dccg401_otg_add_pixel,966	.otg_drop_pixel = dccg401_otg_drop_pixel,967	.set_pixel_rate_div = dccg401_set_pixel_rate_div,968	.get_pixel_rate_div = dccg401_get_pixel_rate_div,969	.set_dp_dto = dccg401_set_dp_dto,970	.enable_symclk_se = dccg401_enable_symclk_se,971	.disable_symclk_se = dccg401_disable_symclk_se,972	.set_dtbclk_p_src = dccg401_set_dtbclk_p_src,973};974 975struct dccg *dccg401_create(976	struct dc_context *ctx,977	const struct dccg_registers *regs,978	const struct dccg_shift *dccg_shift,979	const struct dccg_mask *dccg_mask)980{981	struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);982	struct dccg *base;983 984	if (dccg_dcn == NULL) {985		BREAK_TO_DEBUGGER();986		return NULL;987	}988 989	base = &dccg_dcn->base;990	base->ctx = ctx;991	base->funcs = &dccg401_funcs;992 993	dccg_dcn->regs = regs;994	dccg_dcn->dccg_shift = dccg_shift;995	dccg_dcn->dccg_mask = dccg_mask;996 997	return &dccg_dcn->base;998}999