brintos

brintos / linux-shallow public Read only

0
0
Text · 9.8 KiB · 21a6ca5 Raw
376 lines · c
1/*2 * Copyright 2021 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 "dcn32_dccg.h"29 30#define TO_DCN_DCCG(dccg)\31	container_of(dccg, struct dcn_dccg, base)32 33#define REG(reg) \34	(dccg_dcn->regs->reg)35 36#undef FN37#define FN(reg_name, field_name) \38	dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name39 40#define CTX \41	dccg_dcn->base.ctx42#define DC_LOGGER \43	dccg->ctx->logger44 45static void dccg32_trigger_dio_fifo_resync(46	struct dccg *dccg)47{48	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);49	uint32_t dispclk_rdivider_value = 0;50 51	REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, &dispclk_rdivider_value);52 53	/* Not valid for the WDIVIDER to be set to 0 */54	if (dispclk_rdivider_value != 0)55		REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_rdivider_value);56}57 58static void dccg32_get_pixel_rate_div(59		struct dccg *dccg,60		uint32_t otg_inst,61		uint32_t *k1,62		uint32_t *k2)63{64	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);65	uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;66 67	*k1 = PIXEL_RATE_DIV_NA;68	*k2 = PIXEL_RATE_DIV_NA;69 70	switch (otg_inst) {71	case 0:72		REG_GET_2(OTG_PIXEL_RATE_DIV,73			OTG0_PIXEL_RATE_DIVK1, &val_k1,74			OTG0_PIXEL_RATE_DIVK2, &val_k2);75		break;76	case 1:77		REG_GET_2(OTG_PIXEL_RATE_DIV,78			OTG1_PIXEL_RATE_DIVK1, &val_k1,79			OTG1_PIXEL_RATE_DIVK2, &val_k2);80		break;81	case 2:82		REG_GET_2(OTG_PIXEL_RATE_DIV,83			OTG2_PIXEL_RATE_DIVK1, &val_k1,84			OTG2_PIXEL_RATE_DIVK2, &val_k2);85		break;86	case 3:87		REG_GET_2(OTG_PIXEL_RATE_DIV,88			OTG3_PIXEL_RATE_DIVK1, &val_k1,89			OTG3_PIXEL_RATE_DIVK2, &val_k2);90		break;91	default:92		BREAK_TO_DEBUGGER();93		return;94	}95 96	*k1 = val_k1;97	*k2 = val_k2;98}99 100static void dccg32_set_pixel_rate_div(101		struct dccg *dccg,102		uint32_t otg_inst,103		enum pixel_rate_div k1,104		enum pixel_rate_div k2)105{106	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);107	uint32_t cur_k1 = PIXEL_RATE_DIV_NA;108	uint32_t cur_k2 = PIXEL_RATE_DIV_NA;109 110	// Don't program 0xF into the register field. Not valid since111	// K1 / K2 field is only 1 / 2 bits wide112	if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA) {113		BREAK_TO_DEBUGGER();114		return;115	}116 117	dccg32_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);118	if (k1 == cur_k1 && k2 == cur_k2)119		return;120 121	switch (otg_inst) {122	case 0:123		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,124				OTG0_PIXEL_RATE_DIVK1, k1,125				OTG0_PIXEL_RATE_DIVK2, k2);126		break;127	case 1:128		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,129				OTG1_PIXEL_RATE_DIVK1, k1,130				OTG1_PIXEL_RATE_DIVK2, k2);131		break;132	case 2:133		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,134				OTG2_PIXEL_RATE_DIVK1, k1,135				OTG2_PIXEL_RATE_DIVK2, k2);136		break;137	case 3:138		REG_UPDATE_2(OTG_PIXEL_RATE_DIV,139				OTG3_PIXEL_RATE_DIVK1, k1,140				OTG3_PIXEL_RATE_DIVK2, k2);141		break;142	default:143		BREAK_TO_DEBUGGER();144		return;145	}146}147 148static void dccg32_set_dtbclk_p_src(149		struct dccg *dccg,150		enum streamclk_source src,151		uint32_t otg_inst)152{153	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);154 155	uint32_t p_src_sel = 0; /* selects dprefclk */156	if (src == DTBCLK0)157		p_src_sel = 2;  /* selects dtbclk0 */158 159	switch (otg_inst) {160	case 0:161		if (src == REFCLK)162			REG_UPDATE(DTBCLK_P_CNTL,163					DTBCLK_P0_EN, 0);164		else165			REG_UPDATE_2(DTBCLK_P_CNTL,166					DTBCLK_P0_SRC_SEL, p_src_sel,167					DTBCLK_P0_EN, 1);168		break;169	case 1:170		if (src == REFCLK)171			REG_UPDATE(DTBCLK_P_CNTL,172					DTBCLK_P1_EN, 0);173		else174			REG_UPDATE_2(DTBCLK_P_CNTL,175					DTBCLK_P1_SRC_SEL, p_src_sel,176					DTBCLK_P1_EN, 1);177		break;178	case 2:179		if (src == REFCLK)180			REG_UPDATE(DTBCLK_P_CNTL,181					DTBCLK_P2_EN, 0);182		else183			REG_UPDATE_2(DTBCLK_P_CNTL,184					DTBCLK_P2_SRC_SEL, p_src_sel,185					DTBCLK_P2_EN, 1);186		break;187	case 3:188		if (src == REFCLK)189			REG_UPDATE(DTBCLK_P_CNTL,190					DTBCLK_P3_EN, 0);191		else192			REG_UPDATE_2(DTBCLK_P_CNTL,193					DTBCLK_P3_SRC_SEL, p_src_sel,194					DTBCLK_P3_EN, 1);195		break;196	default:197		BREAK_TO_DEBUGGER();198		return;199	}200 201}202 203/* Controls the generation of pixel valid for OTG in (OTG -> HPO case) */204static void dccg32_set_dtbclk_dto(205		struct dccg *dccg,206		const struct dtbclk_dto_params *params)207{208	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);209	/* DTO Output Rate / Pixel Rate = 1/4 */210	int req_dtbclk_khz = params->pixclk_khz / 4;211 212	if (params->ref_dtbclk_khz && req_dtbclk_khz) {213		uint32_t modulo, phase;214 215		// phase / modulo = dtbclk / dtbclk ref216		modulo = params->ref_dtbclk_khz * 1000;217		phase = req_dtbclk_khz * 1000;218 219		REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], modulo);220		REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], phase);221 222		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],223				DTBCLK_DTO_ENABLE[params->otg_inst], 1);224 225		REG_WAIT(OTG_PIXEL_RATE_CNTL[params->otg_inst],226				DTBCLKDTO_ENABLE_STATUS[params->otg_inst], 1,227				1, 100);228 229		/* program OTG_PIXEL_RATE_DIV for DIVK1 and DIVK2 fields */230		dccg32_set_pixel_rate_div(dccg, params->otg_inst, PIXEL_RATE_DIV_BY_1, PIXEL_RATE_DIV_BY_1);231 232		/* The recommended programming sequence to enable DTBCLK DTO to generate233		 * valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should234		 * be set only after DTO is enabled235		 */236		REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],237				PIPE_DTO_SRC_SEL[params->otg_inst], 2);238	} else {239		REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],240				DTBCLK_DTO_ENABLE[params->otg_inst], 0,241				PIPE_DTO_SRC_SEL[params->otg_inst], params->is_hdmi ? 0 : 1);242		REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);243		REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);244	}245}246 247static void dccg32_set_valid_pixel_rate(248		struct dccg *dccg,249		int ref_dtbclk_khz,250		int otg_inst,251		int pixclk_khz)252{253	struct dtbclk_dto_params dto_params = {0};254 255	dto_params.ref_dtbclk_khz = ref_dtbclk_khz;256	dto_params.otg_inst = otg_inst;257	dto_params.pixclk_khz = pixclk_khz;258	dto_params.is_hdmi = true;259 260	dccg32_set_dtbclk_dto(dccg, &dto_params);261}262 263static void dccg32_get_dccg_ref_freq(struct dccg *dccg,264		unsigned int xtalin_freq_inKhz,265		unsigned int *dccg_ref_freq_inKhz)266{267	/*268	 * Assume refclk is sourced from xtalin269	 * expect 100MHz270	 */271	*dccg_ref_freq_inKhz = xtalin_freq_inKhz;272	return;273}274 275static void dccg32_set_dpstreamclk(276		struct dccg *dccg,277		enum streamclk_source src,278		int otg_inst,279		int dp_hpo_inst)280{281	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);282 283	/* set the dtbclk_p source */284	/* always program refclk as DTBCLK. No use-case expected to require DPREFCLK as refclk */285	dccg32_set_dtbclk_p_src(dccg, DTBCLK0, otg_inst);286 287	/* enabled to select one of the DTBCLKs for pipe */288	switch (dp_hpo_inst) {289	case 0:290		REG_UPDATE_2(DPSTREAMCLK_CNTL,291			     DPSTREAMCLK0_EN,292			     (src == REFCLK) ? 0 : 1, DPSTREAMCLK0_SRC_SEL, otg_inst);293		break;294	case 1:295		REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN,296			     (src == REFCLK) ? 0 : 1, DPSTREAMCLK1_SRC_SEL, otg_inst);297		break;298	case 2:299		REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN,300			     (src == REFCLK) ? 0 : 1, DPSTREAMCLK2_SRC_SEL, otg_inst);301		break;302	case 3:303		REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN,304			     (src == REFCLK) ? 0 : 1, DPSTREAMCLK3_SRC_SEL, otg_inst);305		break;306	default:307		BREAK_TO_DEBUGGER();308		return;309	}310}311 312static void dccg32_otg_add_pixel(struct dccg *dccg,313		uint32_t otg_inst)314{315	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);316 317	REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],318			OTG_ADD_PIXEL[otg_inst], 1);319}320 321static void dccg32_otg_drop_pixel(struct dccg *dccg,322		uint32_t otg_inst)323{324	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);325 326	REG_UPDATE(OTG_PIXEL_RATE_CNTL[otg_inst],327			OTG_DROP_PIXEL[otg_inst], 1);328}329 330static const struct dccg_funcs dccg32_funcs = {331	.update_dpp_dto = dccg2_update_dpp_dto,332	.get_dccg_ref_freq = dccg32_get_dccg_ref_freq,333	.dccg_init = dccg31_init,334	.set_dpstreamclk = dccg32_set_dpstreamclk,335	.enable_symclk32_se = dccg31_enable_symclk32_se,336	.disable_symclk32_se = dccg31_disable_symclk32_se,337	.enable_symclk32_le = dccg31_enable_symclk32_le,338	.disable_symclk32_le = dccg31_disable_symclk32_le,339	.set_physymclk = dccg31_set_physymclk,340	.set_dtbclk_dto = dccg32_set_dtbclk_dto,341	.set_valid_pixel_rate = dccg32_set_valid_pixel_rate,342	.set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,343	.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,344	.otg_add_pixel = dccg32_otg_add_pixel,345	.otg_drop_pixel = dccg32_otg_drop_pixel,346	.set_pixel_rate_div = dccg32_set_pixel_rate_div,347	.get_pixel_rate_div = dccg32_get_pixel_rate_div,348	.trigger_dio_fifo_resync = dccg32_trigger_dio_fifo_resync,349	.set_dtbclk_p_src = dccg32_set_dtbclk_p_src,350};351 352struct dccg *dccg32_create(353	struct dc_context *ctx,354	const struct dccg_registers *regs,355	const struct dccg_shift *dccg_shift,356	const struct dccg_mask *dccg_mask)357{358	struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);359	struct dccg *base;360 361	if (dccg_dcn == NULL) {362		BREAK_TO_DEBUGGER();363		return NULL;364	}365 366	base = &dccg_dcn->base;367	base->ctx = ctx;368	base->funcs = &dccg32_funcs;369 370	dccg_dcn->regs = regs;371	dccg_dcn->dccg_shift = dccg_shift;372	dccg_dcn->dccg_mask = dccg_mask;373 374	return &dccg_dcn->base;375}376