13515Sache// SPDX-License-Identifier: MIT
23515Sache/*
33515Sache * Copyright 2022 Advanced Micro Devices, Inc.
43515Sache *
53515Sache * Permission is hereby granted, free of charge, to any person obtaining a
612983Sjkh * copy of this software and associated documentation files (the "Software"),
712983Sjkh * to deal in the Software without restriction, including without limitation
83515Sache * the rights to use, copy, modify, merge, publish, distribute, sublicense,
93515Sache * and/or sell copies of the Software, and to permit persons to whom the
103515Sache * Software is furnished to do so, subject to the following conditions:
113515Sache *
123515Sache * The above copyright notice and this permission notice shall be included in
133515Sache * all copies or substantial portions of the Software.
143515Sache *
153515Sache * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
163515Sache * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
173515Sache * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
183515Sache * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
193515Sache * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
203515Sache * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2154585Sjkh * OTHER DEALINGS IN THE SOFTWARE.
223515Sache *
233515Sache * Authors: AMD
2454585Sjkh *
2554585Sjkh */
2654585Sjkh
273515Sache#include "reg_helper.h"
283740Sache#include "core_types.h"
293515Sache
303515Sache#include "dcn31/dcn31_dccg.h"
313515Sache#include "dcn314_dccg.h"
3230333Sjkh
333515Sache#define TO_DCN_DCCG(dccg)\
3412983Sjkh	container_of(dccg, struct dcn_dccg, base)
353515Sache
363515Sache#define REG(reg) \
373515Sache	(dccg_dcn->regs->reg)
383515Sache
3913135Sjkh#undef FN
4013135Sjkh#define FN(reg_name, field_name) \
4115322Sjkh	dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name
423515Sache
4321790Sjkh#define CTX \
4421790Sjkh	dccg_dcn->base.ctx
4515273Sjkh#define DC_LOGGER \
4621790Sjkh	dccg->ctx->logger
4715273Sjkh
4815289Sjkhstatic void dccg314_trigger_dio_fifo_resync(
4915322Sjkh	struct dccg *dccg)
5015273Sjkh{
5130333Sjkh	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
5230333Sjkh	uint32_t dispclk_rdivider_value = 0;
5315273Sjkh
5415376Sjkh	REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, &dispclk_rdivider_value);
5515273Sjkh	REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_rdivider_value);
5615273Sjkh}
5715273Sjkh
5815273Sjkhstatic void dccg314_get_pixel_rate_div(
5915273Sjkh		struct dccg *dccg,
6015322Sjkh		uint32_t otg_inst,
6121790Sjkh		enum pixel_rate_div *k1,
6215273Sjkh		enum pixel_rate_div *k2)
6315322Sjkh{
6415273Sjkh	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
6515273Sjkh	uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
6615322Sjkh
6715273Sjkh	*k1 = PIXEL_RATE_DIV_NA;
6815273Sjkh	*k2 = PIXEL_RATE_DIV_NA;
6915273Sjkh
7015273Sjkh	switch (otg_inst) {
7115273Sjkh	case 0:
7215273Sjkh		REG_GET_2(OTG_PIXEL_RATE_DIV,
7315322Sjkh			OTG0_PIXEL_RATE_DIVK1, &val_k1,
7415273Sjkh			OTG0_PIXEL_RATE_DIVK2, &val_k2);
7515322Sjkh		break;
7615322Sjkh	case 1:
7715273Sjkh		REG_GET_2(OTG_PIXEL_RATE_DIV,
7815273Sjkh			OTG1_PIXEL_RATE_DIVK1, &val_k1,
7915273Sjkh			OTG1_PIXEL_RATE_DIVK2, &val_k2);
8015273Sjkh		break;
8115273Sjkh	case 2:
8215273Sjkh		REG_GET_2(OTG_PIXEL_RATE_DIV,
8315273Sjkh			OTG2_PIXEL_RATE_DIVK1, &val_k1,
8415273Sjkh			OTG2_PIXEL_RATE_DIVK2, &val_k2);
8515273Sjkh		break;
8615273Sjkh	case 3:
8715273Sjkh		REG_GET_2(OTG_PIXEL_RATE_DIV,
8815273Sjkh			OTG3_PIXEL_RATE_DIVK1, &val_k1,
8915273Sjkh			OTG3_PIXEL_RATE_DIVK2, &val_k2);
9015273Sjkh		break;
9112983Sjkh	default:
9215273Sjkh		BREAK_TO_DEBUGGER();
9315273Sjkh		return;
9415273Sjkh	}
9515273Sjkh
9615273Sjkh	*k1 = (enum pixel_rate_div)val_k1;
9715273Sjkh	*k2 = (enum pixel_rate_div)val_k2;
9812983Sjkh}
9915273Sjkh
10015273Sjkhstatic void dccg314_set_pixel_rate_div(
10115273Sjkh		struct dccg *dccg,
10215273Sjkh		uint32_t otg_inst,
10315273Sjkh		enum pixel_rate_div k1,
10415273Sjkh		enum pixel_rate_div k2)
10515273Sjkh{
1064565Sache	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
10715273Sjkh	enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
10815273Sjkh
10915273Sjkh	// Don't program 0xF into the register field. Not valid since
11015273Sjkh	// K1 / K2 field is only 1 / 2 bits wide
11115273Sjkh	if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA) {
11215273Sjkh		BREAK_TO_DEBUGGER();
11315273Sjkh		return;
11415273Sjkh	}
11515273Sjkh
1164527Sache	dccg314_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);
1173515Sache	if (k1 == cur_k1 && k2 == cur_k2)
11815273Sjkh		return;
11915273Sjkh
1203515Sache	switch (otg_inst) {
12115273Sjkh	case 0:
12215273Sjkh		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
12315273Sjkh				OTG0_PIXEL_RATE_DIVK1, k1,
12415273Sjkh				OTG0_PIXEL_RATE_DIVK2, k2);
12515273Sjkh		break;
12615273Sjkh	case 1:
12715273Sjkh		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
12815273Sjkh				OTG1_PIXEL_RATE_DIVK1, k1,
12915273Sjkh				OTG1_PIXEL_RATE_DIVK2, k2);
13015273Sjkh		break;
13115273Sjkh	case 2:
13215273Sjkh		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
13315273Sjkh				OTG2_PIXEL_RATE_DIVK1, k1,
13415273Sjkh				OTG2_PIXEL_RATE_DIVK2, k2);
13515273Sjkh		break;
13615273Sjkh	case 3:
13715273Sjkh		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,
13815273Sjkh				OTG3_PIXEL_RATE_DIVK1, k1,
13915273Sjkh				OTG3_PIXEL_RATE_DIVK2, k2);
14015273Sjkh		break;
14115273Sjkh	default:
14215273Sjkh		BREAK_TO_DEBUGGER();
14315273Sjkh		return;
14415273Sjkh	}
14515273Sjkh}
14615273Sjkh
14715273Sjkhstatic void dccg314_set_dtbclk_p_src(
14815273Sjkh		struct dccg *dccg,
14915273Sjkh		enum streamclk_source src,
15015273Sjkh		uint32_t otg_inst)
15115273Sjkh{
15215273Sjkh	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
15315273Sjkh
15415273Sjkh	uint32_t p_src_sel = 0; /* selects dprefclk */
15515273Sjkh
15615273Sjkh	if (src == DTBCLK0)
15715273Sjkh		p_src_sel = 2;  /* selects dtbclk0 */
15815273Sjkh
15915273Sjkh	switch (otg_inst) {
16012983Sjkh	case 0:
16115273Sjkh		if (src == REFCLK)
16215273Sjkh			REG_UPDATE(DTBCLK_P_CNTL,
16315273Sjkh					DTBCLK_P0_EN, 0);
16415273Sjkh		else
16512983Sjkh			REG_UPDATE_2(DTBCLK_P_CNTL,
16615273Sjkh					DTBCLK_P0_SRC_SEL, p_src_sel,
16715273Sjkh					DTBCLK_P0_EN, 1);
16815273Sjkh		break;
16915273Sjkh	case 1:
17015273Sjkh		if (src == REFCLK)
17115273Sjkh			REG_UPDATE(DTBCLK_P_CNTL,
17215273Sjkh					DTBCLK_P1_EN, 0);
17315273Sjkh		else
17415273Sjkh			REG_UPDATE_2(DTBCLK_P_CNTL,
17515273Sjkh					DTBCLK_P1_SRC_SEL, p_src_sel,
17630333Sjkh					DTBCLK_P1_EN, 1);
17715273Sjkh		break;
17815273Sjkh	case 2:
17915273Sjkh		if (src == REFCLK)
18021790Sjkh			REG_UPDATE(DTBCLK_P_CNTL,
18115273Sjkh					DTBCLK_P2_EN, 0);
18221790Sjkh		else
18321790Sjkh			REG_UPDATE_2(DTBCLK_P_CNTL,
18415273Sjkh					DTBCLK_P2_SRC_SEL, p_src_sel,
18515273Sjkh					DTBCLK_P2_EN, 1);
18615273Sjkh		break;
18715273Sjkh	case 3:
18815273Sjkh		if (src == REFCLK)
18915273Sjkh			REG_UPDATE(DTBCLK_P_CNTL,
19015273Sjkh					DTBCLK_P3_EN, 0);
19115273Sjkh		else
19215273Sjkh			REG_UPDATE_2(DTBCLK_P_CNTL,
19315273Sjkh					DTBCLK_P3_SRC_SEL, p_src_sel,
19415273Sjkh					DTBCLK_P3_EN, 1);
19515273Sjkh		break;
19615273Sjkh	default:
19715273Sjkh		BREAK_TO_DEBUGGER();
19815273Sjkh		return;
19915273Sjkh	}
20015273Sjkh
20115273Sjkh}
20215273Sjkh
20315273Sjkh/* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */
20415273Sjkhstatic void dccg314_set_dtbclk_dto(
20515273Sjkh		struct dccg *dccg,
20615273Sjkh		const struct dtbclk_dto_params *params)
20715273Sjkh{
20817092Sjkh	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
20917092Sjkh	/* DTO Output Rate / Pixel Rate = 1/4 */
21017092Sjkh	int req_dtbclk_khz = params->pixclk_khz / 4;
21117092Sjkh
21215289Sjkh	if (params->ref_dtbclk_khz && req_dtbclk_khz) {
21317092Sjkh		uint32_t modulo, phase;
21417092Sjkh
21517092Sjkh		// phase / modulo = dtbclk / dtbclk ref
21617092Sjkh		modulo = params->ref_dtbclk_khz * 1000;
21717092Sjkh		phase = req_dtbclk_khz * 1000;
21817092Sjkh
21917092Sjkh		REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);
22015273Sjkh		REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);
22115273Sjkh
22215418Sjkh		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
22315273Sjkh				DTBCLK_DTO_ENABLE[params->otg_inst], 1);
22415273Sjkh
22515273Sjkh		REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],
22615273Sjkh				DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,
22715273Sjkh				1, 100);
22815273Sjkh
22915273Sjkh		/* program OTG_PIXEL_RATE_DIV for DIVK1 and DIVK2 fields */
23015273Sjkh		dccg314_set_pixel_rate_div(dccg, params->otg_inst, PIXEL_RATE_DIV_BY_1, PIXEL_RATE_DIV_BY_1);
23121790Sjkh
23221790Sjkh		/* The recommended programming sequence to enable DTBCLK DTO to generate
23321790Sjkh		 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
23415142Sjkh		 * be set only after DTO is enabled
23521790Sjkh		 */
23615273Sjkh		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
23721790Sjkh				PIPE_DTO_SRC_SEL[params->otg_inst], 2);
23815273Sjkh	} else {
23915273Sjkh		REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],
24015289Sjkh				DTBCLK_DTO_ENABLE[params->otg_inst], 0,
24112983Sjkh				PIPE_DTO_SRC_SEL[params->otg_inst], 1);
24215289Sjkh
24315273Sjkh		REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
24415289Sjkh		REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
24515273Sjkh	}
24615273Sjkh}
24715354Sjkh
24815273Sjkhvoid dccg314_set_dpstreamclk(
24915289Sjkh		struct dccg *dccg,
25015273Sjkh		enum streamclk_source src,
25121790Sjkh		int otg_inst,
25221790Sjkh		int dp_hpo_inst)
25321790Sjkh{
25415273Sjkh	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
25515273Sjkh
25615273Sjkh	/* set the dtbclk_p source */
25715273Sjkh	dccg314_set_dtbclk_p_src(dccg, src, otg_inst);
25854720Sjkh
25915273Sjkh	/* enabled to select one of the DTBCLKs for pipe */
26054585Sjkh	switch (dp_hpo_inst) {
26121790Sjkh	case 0:
26221790Sjkh		REG_UPDATE_2(DPSTREAMCLK_CNTL,
26312983Sjkh					DPSTREAMCLK0_EN, (src == REFCLK) ? 0 : 1,
26415273Sjkh					DPSTREAMCLK0_SRC_SEL, otg_inst);
26515273Sjkh		break;
26615273Sjkh	case 1:
26721790Sjkh		REG_UPDATE_2(DPSTREAMCLK_CNTL,
26815273Sjkh					DPSTREAMCLK1_EN, (src == REFCLK) ? 0 : 1,
26915273Sjkh					DPSTREAMCLK1_SRC_SEL, otg_inst);
27015273Sjkh		break;
27115273Sjkh	case 2:
27215273Sjkh		REG_UPDATE_2(DPSTREAMCLK_CNTL,
27315273Sjkh					DPSTREAMCLK2_EN, (src == REFCLK) ? 0 : 1,
27421790Sjkh					DPSTREAMCLK2_SRC_SEL, otg_inst);
27530333Sjkh		break;
27615273Sjkh	case 3:
27715273Sjkh		REG_UPDATE_2(DPSTREAMCLK_CNTL,
27815273Sjkh					DPSTREAMCLK3_EN, (src == REFCLK) ? 0 : 1,
27915273Sjkh					DPSTREAMCLK3_SRC_SEL, otg_inst);
28015273Sjkh		break;
28121790Sjkh	default:
28230333Sjkh		BREAK_TO_DEBUGGER();
28315273Sjkh		return;
28415273Sjkh	}
28515273Sjkh}
28615273Sjkh
28715273Sjkhstatic void dccg314_init(struct dccg *dccg)
28815273Sjkh{
28915273Sjkh	int otg_inst;
29015273Sjkh
29115273Sjkh	/* Set HPO stream encoder to use refclk to avoid case where PHY is
29221790Sjkh	 * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
29315273Sjkh	 * will cause DCN to hang.
29421790Sjkh	 */
29515273Sjkh	for (otg_inst = 0; otg_inst < 4; otg_inst++)
29615273Sjkh		dccg31_disable_symclk32_se(dccg, otg_inst);
29715273Sjkh
29815273Sjkh	if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le)
29921790Sjkh		for (otg_inst = 0; otg_inst < 2; otg_inst++)
30021790Sjkh			dccg31_disable_symclk32_le(dccg, otg_inst);
30121790Sjkh
30230333Sjkh	if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
30315273Sjkh		for (otg_inst = 0; otg_inst < 4; otg_inst++)
30415273Sjkh			dccg314_set_dpstreamclk(dccg, REFCLK, otg_inst,
30515273Sjkh						otg_inst);
30615273Sjkh
30715273Sjkh	if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk)
30821790Sjkh		for (otg_inst = 0; otg_inst < 5; otg_inst++)
30921790Sjkh			dccg31_set_physymclk(dccg, otg_inst,
31021790Sjkh					     PHYSYMCLK_FORCE_SRC_SYMCLK, false);
31130333Sjkh}
31215273Sjkh
31315273Sjkhstatic void dccg314_set_valid_pixel_rate(
31415273Sjkh		struct dccg *dccg,
31515273Sjkh		int ref_dtbclk_khz,
31615273Sjkh		int otg_inst,
31715273Sjkh		int pixclk_khz)
31815273Sjkh{
31915273Sjkh	struct dtbclk_dto_params dto_params = {0};
32015273Sjkh
32115273Sjkh	dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
32215273Sjkh	dto_params.otg_inst = otg_inst;
32315273Sjkh	dto_params.pixclk_khz = pixclk_khz;
32415273Sjkh
32515289Sjkh	dccg314_set_dtbclk_dto(dccg, &dto_params);
32615289Sjkh}
32715289Sjkh
32812983Sjkhstatic void dccg314_dpp_root_clock_control(
32915289Sjkh		struct dccg *dccg,
33021790Sjkh		unsigned int dpp_inst,
33115380Sjkh		bool clock_on)
33215380Sjkh{
33315380Sjkh	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
33415380Sjkh
33521790Sjkh	if (dccg->dpp_clock_gated[dpp_inst] != clock_on)
33615273Sjkh		return;
33721790Sjkh
33815323Sjkh	if (clock_on) {
33915323Sjkh		/* turn off the DTO and leave phase/modulo at max */
34015289Sjkh		REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_ENABLE[dpp_inst], 0);
34115289Sjkh		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
34230333Sjkh			  DPPCLK0_DTO_PHASE, 0xFF,
34315289Sjkh			  DPPCLK0_DTO_MODULO, 0xFF);
34415273Sjkh	} else {
34515289Sjkh		/* turn on the DTO to generate a 0hz clock */
34615289Sjkh		REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_ENABLE[dpp_inst], 1);
34715273Sjkh		REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0,
34815273Sjkh			  DPPCLK0_DTO_PHASE, 0,
34915289Sjkh			  DPPCLK0_DTO_MODULO, 1);
35015273Sjkh	}
35115273Sjkh
35221790Sjkh	dccg->dpp_clock_gated[dpp_inst] = !clock_on;
35315273Sjkh}
35415273Sjkh
35515382Sjkhstatic const struct dccg_funcs dccg314_funcs = {
35615382Sjkh	.update_dpp_dto = dccg31_update_dpp_dto,
35715382Sjkh	.dpp_root_clock_control = dccg314_dpp_root_clock_control,
35816973Sjkh	.get_dccg_ref_freq = dccg31_get_dccg_ref_freq,
35915382Sjkh	.dccg_init = dccg314_init,
36015382Sjkh	.set_dpstreamclk = dccg314_set_dpstreamclk,
36115273Sjkh	.enable_symclk32_se = dccg31_enable_symclk32_se,
36215306Sjkh	.disable_symclk32_se = dccg31_disable_symclk32_se,
36315306Sjkh	.enable_symclk32_le = dccg31_enable_symclk32_le,
36415306Sjkh	.disable_symclk32_le = dccg31_disable_symclk32_le,
36515306Sjkh	.set_symclk32_le_root_clock_gating = dccg31_set_symclk32_le_root_clock_gating,
36615306Sjkh	.set_physymclk = dccg31_set_physymclk,
36715273Sjkh	.set_dtbclk_dto = dccg314_set_dtbclk_dto,
36815273Sjkh	.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
36915306Sjkh	.set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
37015273Sjkh	.otg_add_pixel = dccg31_otg_add_pixel,
37115273Sjkh	.otg_drop_pixel = dccg31_otg_drop_pixel,
37215273Sjkh	.set_dispclk_change_mode = dccg31_set_dispclk_change_mode,
37315273Sjkh	.disable_dsc = dccg31_disable_dscclk,
37415273Sjkh	.enable_dsc = dccg31_enable_dscclk,
37515273Sjkh	.set_pixel_rate_div = dccg314_set_pixel_rate_div,
37615273Sjkh	.trigger_dio_fifo_resync = dccg314_trigger_dio_fifo_resync,
37715273Sjkh	.set_valid_pixel_rate = dccg314_set_valid_pixel_rate,
37815273Sjkh	.set_dtbclk_p_src = dccg314_set_dtbclk_p_src
37921790Sjkh};
38015273Sjkh
38115273Sjkhstruct dccg *dccg314_create(
38215273Sjkh	struct dc_context *ctx,
38315273Sjkh	const struct dccg_registers *regs,
38412983Sjkh	const struct dccg_shift *dccg_shift,
38515273Sjkh	const struct dccg_mask *dccg_mask)
38615273Sjkh{
38715273Sjkh	struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
38815273Sjkh	struct dccg *base;
38921790Sjkh
39030333Sjkh	if (dccg_dcn == NULL) {
39115273Sjkh		BREAK_TO_DEBUGGER();
39215273Sjkh		return NULL;
39315273Sjkh	}
39430333Sjkh
39515273Sjkh	base = &dccg_dcn->base;
39615273Sjkh	base->ctx = ctx;
39715273Sjkh	base->funcs = &dccg314_funcs;
39815142Sjkh
39915273Sjkh	dccg_dcn->regs = regs;
40015273Sjkh	dccg_dcn->dccg_shift = dccg_shift;
40115273Sjkh	dccg_dcn->dccg_mask = dccg_mask;
40215273Sjkh
40315273Sjkh	return &dccg_dcn->base;
40415273Sjkh}
40515273Sjkh