brintos

brintos / linux-shallow public Read only

0
0
Text · 50.6 KiB · 4a9d07c Raw
1817 lines · c
1/*2 * Copyright 2012-15 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 28#include "core_types.h"29#include "link_encoder.h"30#include "dce_link_encoder.h"31#include "stream_encoder.h"32#include "dc_bios_types.h"33 34#include "gpio_service_interface.h"35 36#include "dce/dce_11_0_d.h"37#include "dce/dce_11_0_sh_mask.h"38#include "dce/dce_11_0_enum.h"39 40#ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT41#define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT 0xa42#endif43 44#ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK45#define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK 0x00000400L46#endif47 48#ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK49#define HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK  0x10000000L50#endif51 52#ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT53#define HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT  0x1c54#endif55 56#define CTX \57	enc110->base.ctx58#define DC_LOGGER \59	enc110->base.ctx->logger60 61#define REG(reg)\62	(enc110->link_regs->reg)63 64#define AUX_REG(reg)\65	(enc110->aux_regs->reg)66 67#define HPD_REG(reg)\68	(enc110->hpd_regs->reg)69 70#define DEFAULT_AUX_MAX_DATA_SIZE 1671#define AUX_MAX_DEFER_WRITE_RETRY 2072/*73 * @brief74 * Trigger Source Select75 * ASIC-dependent, actual values for register programming76 */77#define DCE110_DIG_FE_SOURCE_SELECT_INVALID 0x078#define DCE110_DIG_FE_SOURCE_SELECT_DIGA 0x179#define DCE110_DIG_FE_SOURCE_SELECT_DIGB 0x280#define DCE110_DIG_FE_SOURCE_SELECT_DIGC 0x481#define DCE110_DIG_FE_SOURCE_SELECT_DIGD 0x0882#define DCE110_DIG_FE_SOURCE_SELECT_DIGE 0x1083#define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x2084#define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x4085 86enum {87	DP_MST_UPDATE_MAX_RETRY = 5088};89 90#define DIG_REG(reg)\91	(reg + enc110->offsets.dig)92 93#define DP_REG(reg)\94	(reg + enc110->offsets.dp)95 96static const struct link_encoder_funcs dce110_lnk_enc_funcs = {97	.validate_output_with_stream =98		dce110_link_encoder_validate_output_with_stream,99	.hw_init = dce110_link_encoder_hw_init,100	.setup = dce110_link_encoder_setup,101	.enable_tmds_output = dce110_link_encoder_enable_tmds_output,102	.enable_dp_output = dce110_link_encoder_enable_dp_output,103	.enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output,104	.enable_lvds_output = dce110_link_encoder_enable_lvds_output,105	.disable_output = dce110_link_encoder_disable_output,106	.dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,107	.dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern,108	.update_mst_stream_allocation_table =109		dce110_link_encoder_update_mst_stream_allocation_table,110	.psr_program_dp_dphy_fast_training =111			dce110_psr_program_dp_dphy_fast_training,112	.psr_program_secondary_packet = dce110_psr_program_secondary_packet,113	.connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,114	.enable_hpd = dce110_link_encoder_enable_hpd,115	.disable_hpd = dce110_link_encoder_disable_hpd,116	.is_dig_enabled = dce110_is_dig_enabled,117	.destroy = dce110_link_encoder_destroy,118	.get_max_link_cap = dce110_link_encoder_get_max_link_cap,119	.get_dig_frontend = dce110_get_dig_frontend,120};121 122static enum bp_result link_transmitter_control(123	struct dce110_link_encoder *enc110,124	struct bp_transmitter_control *cntl)125{126	enum bp_result result;127	struct dc_bios *bp = enc110->base.ctx->dc_bios;128 129	result = bp->funcs->transmitter_control(bp, cntl);130 131	return result;132}133 134static void enable_phy_bypass_mode(135	struct dce110_link_encoder *enc110,136	bool enable)137{138	/* This register resides in DP back end block;139	 * transmitter is used for the offset */140 141	REG_UPDATE(DP_DPHY_CNTL, DPHY_BYPASS, enable);142 143}144 145static void disable_prbs_symbols(146	struct dce110_link_encoder *enc110,147	bool disable)148{149	/* This register resides in DP back end block;150	 * transmitter is used for the offset */151 152	REG_UPDATE_4(DP_DPHY_CNTL,153			DPHY_ATEST_SEL_LANE0, disable,154			DPHY_ATEST_SEL_LANE1, disable,155			DPHY_ATEST_SEL_LANE2, disable,156			DPHY_ATEST_SEL_LANE3, disable);157}158 159static void disable_prbs_mode(160	struct dce110_link_encoder *enc110)161{162	REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0);163}164 165static void program_pattern_symbols(166	struct dce110_link_encoder *enc110,167	uint16_t pattern_symbols[8])168{169	/* This register resides in DP back end block;170	 * transmitter is used for the offset */171 172	REG_SET_3(DP_DPHY_SYM0, 0,173			DPHY_SYM1, pattern_symbols[0],174			DPHY_SYM2, pattern_symbols[1],175			DPHY_SYM3, pattern_symbols[2]);176 177	/* This register resides in DP back end block;178	 * transmitter is used for the offset */179 180	REG_SET_3(DP_DPHY_SYM1, 0,181			DPHY_SYM4, pattern_symbols[3],182			DPHY_SYM5, pattern_symbols[4],183			DPHY_SYM6, pattern_symbols[5]);184 185	/* This register resides in DP back end block;186	 * transmitter is used for the offset */187 188	REG_SET_2(DP_DPHY_SYM2, 0,189			DPHY_SYM7, pattern_symbols[6],190			DPHY_SYM8, pattern_symbols[7]);191}192 193static void set_dp_phy_pattern_d102(194	struct dce110_link_encoder *enc110)195{196	/* Disable PHY Bypass mode to setup the test pattern */197	enable_phy_bypass_mode(enc110, false);198 199	/* For 10-bit PRBS or debug symbols200	 * please use the following sequence: */201 202	/* Enable debug symbols on the lanes */203 204	disable_prbs_symbols(enc110, true);205 206	/* Disable PRBS mode */207	disable_prbs_mode(enc110);208 209	/* Program debug symbols to be output */210	{211		uint16_t pattern_symbols[8] = {212			0x2AA, 0x2AA, 0x2AA, 0x2AA,213			0x2AA, 0x2AA, 0x2AA, 0x2AA214		};215 216		program_pattern_symbols(enc110, pattern_symbols);217	}218 219	/* Enable phy bypass mode to enable the test pattern */220 221	enable_phy_bypass_mode(enc110, true);222}223 224static void set_link_training_complete(225	struct dce110_link_encoder *enc110,226	bool complete)227{228	/* This register resides in DP back end block;229	 * transmitter is used for the offset */230 231	REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, complete);232 233}234 235unsigned int dce110_get_dig_frontend(struct link_encoder *enc)236{237	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);238	u32 value;239	enum engine_id result;240 241	REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value);242 243	switch (value) {244	case DCE110_DIG_FE_SOURCE_SELECT_DIGA:245		result = ENGINE_ID_DIGA;246		break;247	case DCE110_DIG_FE_SOURCE_SELECT_DIGB:248		result = ENGINE_ID_DIGB;249		break;250	case DCE110_DIG_FE_SOURCE_SELECT_DIGC:251		result = ENGINE_ID_DIGC;252		break;253	case DCE110_DIG_FE_SOURCE_SELECT_DIGD:254		result = ENGINE_ID_DIGD;255		break;256	case DCE110_DIG_FE_SOURCE_SELECT_DIGE:257		result = ENGINE_ID_DIGE;258		break;259	case DCE110_DIG_FE_SOURCE_SELECT_DIGF:260		result = ENGINE_ID_DIGF;261		break;262	case DCE110_DIG_FE_SOURCE_SELECT_DIGG:263		result = ENGINE_ID_DIGG;264		break;265	default:266		// invalid source select DIG267		result = ENGINE_ID_UNKNOWN;268	}269 270	return result;271}272 273void dce110_link_encoder_set_dp_phy_pattern_training_pattern(274	struct link_encoder *enc,275	uint32_t index)276{277	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);278	/* Write Training Pattern */279 280	REG_WRITE(DP_DPHY_TRAINING_PATTERN_SEL, index);281 282	/* Set HW Register Training Complete to false */283 284	set_link_training_complete(enc110, false);285 286	/* Disable PHY Bypass mode to output Training Pattern */287 288	enable_phy_bypass_mode(enc110, false);289 290	/* Disable PRBS mode */291	disable_prbs_mode(enc110);292}293 294static void setup_panel_mode(295	struct dce110_link_encoder *enc110,296	enum dp_panel_mode panel_mode)297{298	uint32_t value;299	struct dc_context *ctx = enc110->base.ctx;300 301	/* if psp set panel mode, dal should be program it */302	if (ctx->dc->caps.psp_setup_panel_mode)303		return;304 305	ASSERT(REG(DP_DPHY_INTERNAL_CTRL));306	value = REG_READ(DP_DPHY_INTERNAL_CTRL);307 308	switch (panel_mode) {309	case DP_PANEL_MODE_EDP:310		value = 0x1;311		break;312	case DP_PANEL_MODE_SPECIAL:313		value = 0x11;314		break;315	default:316		value = 0x0;317		break;318	}319 320	REG_WRITE(DP_DPHY_INTERNAL_CTRL, value);321}322 323static void set_dp_phy_pattern_symbol_error(324	struct dce110_link_encoder *enc110)325{326	/* Disable PHY Bypass mode to setup the test pattern */327	enable_phy_bypass_mode(enc110, false);328 329	/* program correct panel mode*/330	setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);331 332	/* A PRBS23 pattern is used for most DP electrical measurements. */333 334	/* Enable PRBS symbols on the lanes */335	disable_prbs_symbols(enc110, false);336 337	/* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */338	REG_UPDATE_2(DP_DPHY_PRBS_CNTL,339			DPHY_PRBS_SEL, 1,340			DPHY_PRBS_EN, 1);341 342	/* Enable phy bypass mode to enable the test pattern */343	enable_phy_bypass_mode(enc110, true);344}345 346static void set_dp_phy_pattern_prbs7(347	struct dce110_link_encoder *enc110)348{349	/* Disable PHY Bypass mode to setup the test pattern */350	enable_phy_bypass_mode(enc110, false);351 352	/* A PRBS7 pattern is used for most DP electrical measurements. */353 354	/* Enable PRBS symbols on the lanes */355	disable_prbs_symbols(enc110, false);356 357	/* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */358	REG_UPDATE_2(DP_DPHY_PRBS_CNTL,359			DPHY_PRBS_SEL, 0,360			DPHY_PRBS_EN, 1);361 362	/* Enable phy bypass mode to enable the test pattern */363	enable_phy_bypass_mode(enc110, true);364}365 366static void set_dp_phy_pattern_80bit_custom(367	struct dce110_link_encoder *enc110,368	const uint8_t *pattern)369{370	/* Disable PHY Bypass mode to setup the test pattern */371	enable_phy_bypass_mode(enc110, false);372 373	/* Enable debug symbols on the lanes */374 375	disable_prbs_symbols(enc110, true);376 377	/* Enable PHY bypass mode to enable the test pattern */378	/* TODO is it really needed ? */379 380	enable_phy_bypass_mode(enc110, true);381 382	/* Program 80 bit custom pattern */383	{384		uint16_t pattern_symbols[8];385 386		pattern_symbols[0] =387			((pattern[1] & 0x03) << 8) | pattern[0];388		pattern_symbols[1] =389			((pattern[2] & 0x0f) << 6) | ((pattern[1] >> 2) & 0x3f);390		pattern_symbols[2] =391			((pattern[3] & 0x3f) << 4) | ((pattern[2] >> 4) & 0x0f);392		pattern_symbols[3] =393			(pattern[4] << 2) | ((pattern[3] >> 6) & 0x03);394		pattern_symbols[4] =395			((pattern[6] & 0x03) << 8) | pattern[5];396		pattern_symbols[5] =397			((pattern[7] & 0x0f) << 6) | ((pattern[6] >> 2) & 0x3f);398		pattern_symbols[6] =399			((pattern[8] & 0x3f) << 4) | ((pattern[7] >> 4) & 0x0f);400		pattern_symbols[7] =401			(pattern[9] << 2) | ((pattern[8] >> 6) & 0x03);402 403		program_pattern_symbols(enc110, pattern_symbols);404	}405 406	/* Enable phy bypass mode to enable the test pattern */407 408	enable_phy_bypass_mode(enc110, true);409}410 411static void set_dp_phy_pattern_hbr2_compliance_cp2520_2(412	struct dce110_link_encoder *enc110,413	unsigned int cp2520_pattern)414{415 416	/* previously there is a register DP_HBR2_EYE_PATTERN417	 * that is enabled to get the pattern.418	 * But it does not work with the latest spec change,419	 * so we are programming the following registers manually.420	 *421	 * The following settings have been confirmed422	 * by Nick Chorney and Sandra Liu */423 424	/* Disable PHY Bypass mode to setup the test pattern */425 426	enable_phy_bypass_mode(enc110, false);427 428	/* Setup DIG encoder in DP SST mode */429	enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT);430 431	/* ensure normal panel mode. */432	setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);433 434	/* no vbid after BS (SR)435	 * DP_LINK_FRAMING_CNTL changed history Sandra Liu436	 * 11000260 / 11000104 / 110000FC */437	REG_UPDATE_3(DP_LINK_FRAMING_CNTL,438			DP_IDLE_BS_INTERVAL, 0xFC,439			DP_VBID_DISABLE, 1,440			DP_VID_ENHANCED_FRAME_MODE, 1);441 442	/* swap every BS with SR */443	REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0);444 445	/* select cp2520 patterns */446	if (REG(DP_DPHY_HBR2_PATTERN_CONTROL))447		REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL,448				DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern);449	else450		/* pre-DCE11 can only generate CP2520 pattern 2 */451		ASSERT(cp2520_pattern == 2);452 453	/* set link training complete */454	set_link_training_complete(enc110, true);455 456	/* disable video stream */457	REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);458 459	/* Disable PHY Bypass mode to setup the test pattern */460	enable_phy_bypass_mode(enc110, false);461}462 463#if defined(CONFIG_DRM_AMD_DC_SI)464static void dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(465	struct dce110_link_encoder *enc110,466	unsigned int cp2520_pattern)467{468 469	/* previously there is a register DP_HBR2_EYE_PATTERN470	 * that is enabled to get the pattern.471	 * But it does not work with the latest spec change,472	 * so we are programming the following registers manually.473	 *474	 * The following settings have been confirmed475	 * by Nick Chorney and Sandra Liu */476 477	/* Disable PHY Bypass mode to setup the test pattern */478 479	enable_phy_bypass_mode(enc110, false);480 481	/* Setup DIG encoder in DP SST mode */482	enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT);483 484	/* ensure normal panel mode. */485	setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);486 487	/* no vbid after BS (SR)488	 * DP_LINK_FRAMING_CNTL changed history Sandra Liu489	 * 11000260 / 11000104 / 110000FC */490	REG_UPDATE_3(DP_LINK_FRAMING_CNTL,491			DP_IDLE_BS_INTERVAL, 0xFC,492			DP_VBID_DISABLE, 1,493			DP_VID_ENHANCED_FRAME_MODE, 1);494 495	/* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip swap BS with SR */496 497	/* select cp2520 patterns */498	if (REG(DP_DPHY_HBR2_PATTERN_CONTROL))499		REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL,500				DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern);501	else502		/* pre-DCE11 can only generate CP2520 pattern 2 */503		ASSERT(cp2520_pattern == 2);504 505	/* set link training complete */506	set_link_training_complete(enc110, true);507 508	/* disable video stream */509	REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);510 511	/* Disable PHY Bypass mode to setup the test pattern */512	enable_phy_bypass_mode(enc110, false);513}514#endif515 516static void set_dp_phy_pattern_passthrough_mode(517	struct dce110_link_encoder *enc110,518	enum dp_panel_mode panel_mode)519{520	/* program correct panel mode */521	setup_panel_mode(enc110, panel_mode);522 523	/* restore LINK_FRAMING_CNTL and DPHY_SCRAMBLER_BS_COUNT524	 * in case we were doing HBR2 compliance pattern before525	 */526	REG_UPDATE_3(DP_LINK_FRAMING_CNTL,527			DP_IDLE_BS_INTERVAL, 0x2000,528			DP_VBID_DISABLE, 0,529			DP_VID_ENHANCED_FRAME_MODE, 1);530 531	REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF);532 533	/* set link training complete */534	set_link_training_complete(enc110, true);535 536	/* Disable PHY Bypass mode to setup the test pattern */537	enable_phy_bypass_mode(enc110, false);538 539	/* Disable PRBS mode */540	disable_prbs_mode(enc110);541}542 543#if defined(CONFIG_DRM_AMD_DC_SI)544static void dce60_set_dp_phy_pattern_passthrough_mode(545	struct dce110_link_encoder *enc110,546	enum dp_panel_mode panel_mode)547{548	/* program correct panel mode */549	setup_panel_mode(enc110, panel_mode);550 551	/* restore LINK_FRAMING_CNTL552	 * in case we were doing HBR2 compliance pattern before553	 */554	REG_UPDATE_3(DP_LINK_FRAMING_CNTL,555			DP_IDLE_BS_INTERVAL, 0x2000,556			DP_VBID_DISABLE, 0,557			DP_VID_ENHANCED_FRAME_MODE, 1);558 559	/* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip DPHY_SCRAMBLER_BS_COUNT restore */560 561	/* set link training complete */562	set_link_training_complete(enc110, true);563 564	/* Disable PHY Bypass mode to setup the test pattern */565	enable_phy_bypass_mode(enc110, false);566 567	/* Disable PRBS mode */568	disable_prbs_mode(enc110);569}570#endif571 572/* return value is bit-vector */573static uint8_t get_frontend_source(574	enum engine_id engine)575{576	switch (engine) {577	case ENGINE_ID_DIGA:578		return DCE110_DIG_FE_SOURCE_SELECT_DIGA;579	case ENGINE_ID_DIGB:580		return DCE110_DIG_FE_SOURCE_SELECT_DIGB;581	case ENGINE_ID_DIGC:582		return DCE110_DIG_FE_SOURCE_SELECT_DIGC;583	case ENGINE_ID_DIGD:584		return DCE110_DIG_FE_SOURCE_SELECT_DIGD;585	case ENGINE_ID_DIGE:586		return DCE110_DIG_FE_SOURCE_SELECT_DIGE;587	case ENGINE_ID_DIGF:588		return DCE110_DIG_FE_SOURCE_SELECT_DIGF;589	case ENGINE_ID_DIGG:590		return DCE110_DIG_FE_SOURCE_SELECT_DIGG;591	default:592		ASSERT_CRITICAL(false);593		return DCE110_DIG_FE_SOURCE_SELECT_INVALID;594	}595}596 597static void configure_encoder(598	struct dce110_link_encoder *enc110,599	const struct dc_link_settings *link_settings)600{601	/* set number of lanes */602 603	REG_SET(DP_CONFIG, 0,604			DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE);605 606	/* setup scrambler */607	REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1);608}609 610#if defined(CONFIG_DRM_AMD_DC_SI)611static void dce60_configure_encoder(612	struct dce110_link_encoder *enc110,613	const struct dc_link_settings *link_settings)614{615	/* set number of lanes */616 617	REG_SET(DP_CONFIG, 0,618			DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE);619 620	/* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip setup scrambler */621}622#endif623 624static void aux_initialize(625	struct dce110_link_encoder *enc110)626{627	struct dc_context *ctx = enc110->base.ctx;628	enum hpd_source_id hpd_source = enc110->base.hpd_source;629	uint32_t addr = AUX_REG(AUX_CONTROL);630	uint32_t value = dm_read_reg(ctx, addr);631 632	set_reg_field_value(value, hpd_source, AUX_CONTROL, AUX_HPD_SEL);633	set_reg_field_value(value, 0, AUX_CONTROL, AUX_LS_READ_EN);634	dm_write_reg(ctx, addr, value);635 636	addr = AUX_REG(AUX_DPHY_RX_CONTROL0);637	value = dm_read_reg(ctx, addr);638 639	/* 1/4 window (the maximum allowed) */640	set_reg_field_value(value, 1,641			AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW);642	dm_write_reg(ctx, addr, value);643 644}645 646void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc,647			bool exit_link_training_required)648{649	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);650 651	if (exit_link_training_required)652		REG_UPDATE(DP_DPHY_FAST_TRAINING,653				DPHY_RX_FAST_TRAINING_CAPABLE, 1);654	else {655		REG_UPDATE(DP_DPHY_FAST_TRAINING,656				DPHY_RX_FAST_TRAINING_CAPABLE, 0);657		/*In DCE 11, we are able to pre-program a Force SR register658		 * to be able to trigger SR symbol after 5 idle patterns659		 * transmitted. Upon PSR Exit, DMCU can trigger660		 * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to661		 * DPHY_LOAD_BS_COUNT_START and the internal counter662		 * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be663		 * replaced by SR symbol once.664		 */665 666		REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5);667	}668}669 670void dce110_psr_program_secondary_packet(struct link_encoder *enc,671			unsigned int sdp_transmit_line_num_deadline)672{673	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);674 675	REG_UPDATE_2(DP_SEC_CNTL1,676		DP_SEC_GSP0_LINE_NUM, sdp_transmit_line_num_deadline,677		DP_SEC_GSP0_PRIORITY, 1);678}679 680bool dce110_is_dig_enabled(struct link_encoder *enc)681{682	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);683	uint32_t value;684 685	REG_GET(DIG_BE_EN_CNTL, DIG_ENABLE, &value);686	return value;687}688 689static void link_encoder_disable(struct dce110_link_encoder *enc110)690{691	/* reset training pattern */692	REG_SET(DP_DPHY_TRAINING_PATTERN_SEL, 0,693			DPHY_TRAINING_PATTERN_SEL, 0);694 695	/* reset training complete */696	REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0);697 698	/* reset panel mode */699	setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);700}701 702static void hpd_initialize(703	struct dce110_link_encoder *enc110)704{705	/* Associate HPD with DIG_BE */706	enum hpd_source_id hpd_source = enc110->base.hpd_source;707 708	REG_UPDATE(DIG_BE_CNTL, DIG_HPD_SELECT, hpd_source);709}710 711bool dce110_link_encoder_validate_dvi_output(712	const struct dce110_link_encoder *enc110,713	enum signal_type connector_signal,714	enum signal_type signal,715	const struct dc_crtc_timing *crtc_timing)716{717	uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK;718 719	if (signal == SIGNAL_TYPE_DVI_DUAL_LINK)720		max_pixel_clock *= 2;721 722	/* This handles the case of HDMI downgrade to DVI we don't want to723	 * we don't want to cap the pixel clock if the DDI is not DVI.724	 */725	if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK &&726			connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)727		max_pixel_clock = enc110->base.features.max_hdmi_pixel_clock;728 729	/* DVI only support RGB pixel encoding */730	if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB)731		return false;732 733	/*connect DVI via adpater's HDMI connector*/734	if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||735		connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) &&736		signal != SIGNAL_TYPE_HDMI_TYPE_A &&737		crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10))738		return false;739	if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10))740		return false;741 742	if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10))743		return false;744 745	/* DVI supports 6/8bpp single-link and 10/16bpp dual-link */746	switch (crtc_timing->display_color_depth) {747	case COLOR_DEPTH_666:748	case COLOR_DEPTH_888:749	break;750	case COLOR_DEPTH_101010:751	case COLOR_DEPTH_161616:752		if (signal != SIGNAL_TYPE_DVI_DUAL_LINK)753			return false;754	break;755	default:756		return false;757	}758 759	return true;760}761 762static bool dce110_link_encoder_validate_hdmi_output(763	const struct dce110_link_encoder *enc110,764	const struct dc_crtc_timing *crtc_timing,765	int adjusted_pix_clk_khz)766{767	enum dc_color_depth max_deep_color =768			enc110->base.features.max_hdmi_deep_color;769 770	if (max_deep_color < crtc_timing->display_color_depth)771		return false;772 773	if (crtc_timing->display_color_depth < COLOR_DEPTH_888)774		return false;775	if (adjusted_pix_clk_khz < TMDS_MIN_PIXEL_CLOCK)776		return false;777 778	if ((adjusted_pix_clk_khz == 0) ||779		(adjusted_pix_clk_khz > enc110->base.features.max_hdmi_pixel_clock))780		return false;781 782	/* DCE11 HW does not support 420 */783	if (!enc110->base.features.hdmi_ycbcr420_supported &&784			crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)785		return false;786 787	if ((!enc110->base.features.flags.bits.HDMI_6GB_EN ||788			enc110->base.ctx->dc->debug.hdmi20_disable) &&789			adjusted_pix_clk_khz >= 300000)790		return false;791	if (enc110->base.ctx->dc->debug.hdmi20_disable &&792		crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)793		return false;794	return true;795}796 797bool dce110_link_encoder_validate_dp_output(798	const struct dce110_link_encoder *enc110,799	const struct dc_crtc_timing *crtc_timing)800{801	if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)802		return false;803 804	return true;805}806 807void dce110_link_encoder_construct(808	struct dce110_link_encoder *enc110,809	const struct encoder_init_data *init_data,810	const struct encoder_feature_support *enc_features,811	const struct dce110_link_enc_registers *link_regs,812	const struct dce110_link_enc_aux_registers *aux_regs,813	const struct dce110_link_enc_hpd_registers *hpd_regs)814{815	struct bp_encoder_cap_info bp_cap_info = {0};816	const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;817	enum bp_result result = BP_RESULT_OK;818 819	enc110->base.funcs = &dce110_lnk_enc_funcs;820	enc110->base.ctx = init_data->ctx;821	enc110->base.id = init_data->encoder;822 823	enc110->base.hpd_source = init_data->hpd_source;824	enc110->base.connector = init_data->connector;825 826	enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;827 828	enc110->base.features = *enc_features;829 830	enc110->base.transmitter = init_data->transmitter;831 832	/* set the flag to indicate whether driver poll the I2C data pin833	 * while doing the DP sink detect834	 */835 836/*	if (dal_adapter_service_is_feature_supported(as,837		FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))838		enc110->base.features.flags.bits.839			DP_SINK_DETECT_POLL_DATA_PIN = true;*/840 841	enc110->base.output_signals =842		SIGNAL_TYPE_DVI_SINGLE_LINK |843		SIGNAL_TYPE_DVI_DUAL_LINK |844		SIGNAL_TYPE_LVDS |845		SIGNAL_TYPE_DISPLAY_PORT |846		SIGNAL_TYPE_DISPLAY_PORT_MST |847		SIGNAL_TYPE_EDP |848		SIGNAL_TYPE_HDMI_TYPE_A;849 850	/* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE.851	 * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY.852	 * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer853	 * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS.854	 * Prefer DIG assignment is decided by board design.855	 * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design856	 * and VBIOS will filter out 7 UNIPHY for DCE 8.0.857	 * By this, adding DIGG should not hurt DCE 8.0.858	 * This will let DCE 8.1 share DCE 8.0 as much as possible859	 */860 861	enc110->link_regs = link_regs;862	enc110->aux_regs = aux_regs;863	enc110->hpd_regs = hpd_regs;864 865	switch (enc110->base.transmitter) {866	case TRANSMITTER_UNIPHY_A:867		enc110->base.preferred_engine = ENGINE_ID_DIGA;868	break;869	case TRANSMITTER_UNIPHY_B:870		enc110->base.preferred_engine = ENGINE_ID_DIGB;871	break;872	case TRANSMITTER_UNIPHY_C:873		enc110->base.preferred_engine = ENGINE_ID_DIGC;874	break;875	case TRANSMITTER_UNIPHY_D:876		enc110->base.preferred_engine = ENGINE_ID_DIGD;877	break;878	case TRANSMITTER_UNIPHY_E:879		enc110->base.preferred_engine = ENGINE_ID_DIGE;880	break;881	case TRANSMITTER_UNIPHY_F:882		enc110->base.preferred_engine = ENGINE_ID_DIGF;883	break;884	case TRANSMITTER_UNIPHY_G:885		enc110->base.preferred_engine = ENGINE_ID_DIGG;886	break;887	default:888		ASSERT_CRITICAL(false);889		enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;890	}891 892	/* default to one to mirror Windows behavior */893	enc110->base.features.flags.bits.HDMI_6GB_EN = 1;894 895	result = bp_funcs->get_encoder_cap_info(enc110->base.ctx->dc_bios,896						enc110->base.id, &bp_cap_info);897 898	/* Override features with DCE-specific values */899	if (BP_RESULT_OK == result) {900		enc110->base.features.flags.bits.IS_HBR2_CAPABLE =901				bp_cap_info.DP_HBR2_EN;902		enc110->base.features.flags.bits.IS_HBR3_CAPABLE =903				bp_cap_info.DP_HBR3_EN;904		enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;905	} else {906		DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",907				__func__,908				result);909	}910	if (enc110->base.ctx->dc->debug.hdmi20_disable) {911		enc110->base.features.flags.bits.HDMI_6GB_EN = 0;912	}913}914 915bool dce110_link_encoder_validate_output_with_stream(916	struct link_encoder *enc,917	const struct dc_stream_state *stream)918{919	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);920	bool is_valid;921 922	switch (stream->signal) {923	case SIGNAL_TYPE_DVI_SINGLE_LINK:924	case SIGNAL_TYPE_DVI_DUAL_LINK:925		is_valid = dce110_link_encoder_validate_dvi_output(926			enc110,927			stream->link->connector_signal,928			stream->signal,929			&stream->timing);930	break;931	case SIGNAL_TYPE_HDMI_TYPE_A:932		is_valid = dce110_link_encoder_validate_hdmi_output(933				enc110,934				&stream->timing,935				stream->phy_pix_clk);936	break;937	case SIGNAL_TYPE_DISPLAY_PORT:938	case SIGNAL_TYPE_DISPLAY_PORT_MST:939		is_valid = dce110_link_encoder_validate_dp_output(940					enc110, &stream->timing);941	break;942	case SIGNAL_TYPE_EDP:943	case SIGNAL_TYPE_LVDS:944		is_valid = stream->timing.pixel_encoding == PIXEL_ENCODING_RGB;945	break;946	case SIGNAL_TYPE_VIRTUAL:947		is_valid = true;948		break;949	default:950		is_valid = false;951	break;952	}953 954	return is_valid;955}956 957void dce110_link_encoder_hw_init(958	struct link_encoder *enc)959{960	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);961	struct bp_transmitter_control cntl = { 0 };962	enum bp_result result;963 964	cntl.action = TRANSMITTER_CONTROL_INIT;965	cntl.engine_id = ENGINE_ID_UNKNOWN;966	cntl.transmitter = enc110->base.transmitter;967	cntl.connector_obj_id = enc110->base.connector;968	cntl.lanes_number = LANE_COUNT_FOUR;969	cntl.coherent = false;970	cntl.hpd_sel = enc110->base.hpd_source;971 972	if (enc110->base.connector.id == CONNECTOR_ID_EDP)973		cntl.signal = SIGNAL_TYPE_EDP;974 975	result = link_transmitter_control(enc110, &cntl);976 977	if (result != BP_RESULT_OK) {978		DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",979			__func__);980		BREAK_TO_DEBUGGER();981		return;982	}983 984	if (enc110->base.connector.id == CONNECTOR_ID_LVDS) {985		cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS;986 987		result = link_transmitter_control(enc110, &cntl);988 989		ASSERT(result == BP_RESULT_OK);990 991	}992	aux_initialize(enc110);993 994	/* reinitialize HPD.995	 * hpd_initialize() will pass DIG_FE id to HW context.996	 * All other routine within HW context will use fe_engine_offset997	 * as DIG_FE id even caller pass DIG_FE id.998	 * So this routine must be called first. */999	hpd_initialize(enc110);1000}1001 1002void dce110_link_encoder_destroy(struct link_encoder **enc)1003{1004	kfree(TO_DCE110_LINK_ENC(*enc));1005	*enc = NULL;1006}1007 1008void dce110_link_encoder_setup(1009	struct link_encoder *enc,1010	enum signal_type signal)1011{1012	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1013 1014	switch (signal) {1015	case SIGNAL_TYPE_EDP:1016	case SIGNAL_TYPE_DISPLAY_PORT:1017		/* DP SST */1018		REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 0);1019		break;1020	case SIGNAL_TYPE_LVDS:1021		/* LVDS */1022		REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 1);1023		break;1024	case SIGNAL_TYPE_DVI_SINGLE_LINK:1025	case SIGNAL_TYPE_DVI_DUAL_LINK:1026		/* TMDS-DVI */1027		REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 2);1028		break;1029	case SIGNAL_TYPE_HDMI_TYPE_A:1030		/* TMDS-HDMI */1031		REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 3);1032		break;1033	case SIGNAL_TYPE_DISPLAY_PORT_MST:1034		/* DP MST */1035		REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 5);1036		break;1037	default:1038		ASSERT_CRITICAL(false);1039		/* invalid mode ! */1040		break;1041	}1042 1043}1044 1045/* TODO: still need depth or just pass in adjusted pixel clock? */1046void dce110_link_encoder_enable_tmds_output(1047	struct link_encoder *enc,1048	enum clock_source_id clock_source,1049	enum dc_color_depth color_depth,1050	enum signal_type signal,1051	uint32_t pixel_clock)1052{1053	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1054	struct bp_transmitter_control cntl = { 0 };1055	enum bp_result result;1056 1057	/* Enable the PHY */1058	cntl.connector_obj_id = enc110->base.connector;1059	cntl.action = TRANSMITTER_CONTROL_ENABLE;1060	cntl.engine_id = enc->preferred_engine;1061	cntl.transmitter = enc110->base.transmitter;1062	cntl.pll_id = clock_source;1063	cntl.signal = signal;1064	if (cntl.signal == SIGNAL_TYPE_DVI_DUAL_LINK)1065		cntl.lanes_number = 8;1066	else1067		cntl.lanes_number = 4;1068 1069	cntl.hpd_sel = enc110->base.hpd_source;1070 1071	cntl.pixel_clock = pixel_clock;1072	cntl.color_depth = color_depth;1073 1074	result = link_transmitter_control(enc110, &cntl);1075 1076	if (result != BP_RESULT_OK) {1077		DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1078			__func__);1079		BREAK_TO_DEBUGGER();1080	}1081}1082 1083/* TODO: still need depth or just pass in adjusted pixel clock? */1084void dce110_link_encoder_enable_lvds_output(1085	struct link_encoder *enc,1086	enum clock_source_id clock_source,1087	uint32_t pixel_clock)1088{1089	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1090	struct bp_transmitter_control cntl = { 0 };1091	enum bp_result result;1092 1093	/* Enable the PHY */1094	cntl.connector_obj_id = enc110->base.connector;1095	cntl.action = TRANSMITTER_CONTROL_ENABLE;1096	cntl.engine_id = enc->preferred_engine;1097	cntl.transmitter = enc110->base.transmitter;1098	cntl.pll_id = clock_source;1099	cntl.signal = SIGNAL_TYPE_LVDS;1100	cntl.lanes_number = 4;1101 1102	cntl.hpd_sel = enc110->base.hpd_source;1103 1104	cntl.pixel_clock = pixel_clock;1105 1106	result = link_transmitter_control(enc110, &cntl);1107 1108	if (result != BP_RESULT_OK) {1109		DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1110			__func__);1111		BREAK_TO_DEBUGGER();1112	}1113}1114 1115/* enables DP PHY output */1116void dce110_link_encoder_enable_dp_output(1117	struct link_encoder *enc,1118	const struct dc_link_settings *link_settings,1119	enum clock_source_id clock_source)1120{1121	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1122	struct bp_transmitter_control cntl = { 0 };1123	enum bp_result result;1124 1125	/* Enable the PHY */1126 1127	/* number_of_lanes is used for pixel clock adjust,1128	 * but it's not passed to asic_control.1129	 * We need to set number of lanes manually.1130	 */1131	configure_encoder(enc110, link_settings);1132	cntl.connector_obj_id = enc110->base.connector;1133	cntl.action = TRANSMITTER_CONTROL_ENABLE;1134	cntl.engine_id = enc->preferred_engine;1135	cntl.transmitter = enc110->base.transmitter;1136	cntl.pll_id = clock_source;1137	cntl.signal = SIGNAL_TYPE_DISPLAY_PORT;1138	cntl.lanes_number = link_settings->lane_count;1139	cntl.hpd_sel = enc110->base.hpd_source;1140	cntl.pixel_clock = link_settings->link_rate1141						* LINK_RATE_REF_FREQ_IN_KHZ;1142	/* TODO: check if undefined works */1143	cntl.color_depth = COLOR_DEPTH_UNDEFINED;1144 1145	result = link_transmitter_control(enc110, &cntl);1146 1147	if (result != BP_RESULT_OK) {1148		DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1149			__func__);1150		BREAK_TO_DEBUGGER();1151	}1152}1153 1154/* enables DP PHY output in MST mode */1155void dce110_link_encoder_enable_dp_mst_output(1156	struct link_encoder *enc,1157	const struct dc_link_settings *link_settings,1158	enum clock_source_id clock_source)1159{1160	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1161	struct bp_transmitter_control cntl = { 0 };1162	enum bp_result result;1163 1164	/* Enable the PHY */1165 1166	/* number_of_lanes is used for pixel clock adjust,1167	 * but it's not passed to asic_control.1168	 * We need to set number of lanes manually.1169	 */1170	configure_encoder(enc110, link_settings);1171 1172	cntl.action = TRANSMITTER_CONTROL_ENABLE;1173	cntl.engine_id = ENGINE_ID_UNKNOWN;1174	cntl.transmitter = enc110->base.transmitter;1175	cntl.pll_id = clock_source;1176	cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;1177	cntl.lanes_number = link_settings->lane_count;1178	cntl.hpd_sel = enc110->base.hpd_source;1179	cntl.pixel_clock = link_settings->link_rate1180						* LINK_RATE_REF_FREQ_IN_KHZ;1181	/* TODO: check if undefined works */1182	cntl.color_depth = COLOR_DEPTH_UNDEFINED;1183 1184	result = link_transmitter_control(enc110, &cntl);1185 1186	if (result != BP_RESULT_OK) {1187		DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1188			__func__);1189		BREAK_TO_DEBUGGER();1190	}1191}1192 1193#if defined(CONFIG_DRM_AMD_DC_SI)1194/* enables DP PHY output */1195static void dce60_link_encoder_enable_dp_output(1196	struct link_encoder *enc,1197	const struct dc_link_settings *link_settings,1198	enum clock_source_id clock_source)1199{1200	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1201	struct bp_transmitter_control cntl = { 0 };1202	enum bp_result result;1203 1204	/* Enable the PHY */1205 1206	/* number_of_lanes is used for pixel clock adjust,1207	 * but it's not passed to asic_control.1208	 * We need to set number of lanes manually.1209	 */1210	dce60_configure_encoder(enc110, link_settings);1211	cntl.connector_obj_id = enc110->base.connector;1212	cntl.action = TRANSMITTER_CONTROL_ENABLE;1213	cntl.engine_id = enc->preferred_engine;1214	cntl.transmitter = enc110->base.transmitter;1215	cntl.pll_id = clock_source;1216	cntl.signal = SIGNAL_TYPE_DISPLAY_PORT;1217	cntl.lanes_number = link_settings->lane_count;1218	cntl.hpd_sel = enc110->base.hpd_source;1219	cntl.pixel_clock = link_settings->link_rate1220						* LINK_RATE_REF_FREQ_IN_KHZ;1221	/* TODO: check if undefined works */1222	cntl.color_depth = COLOR_DEPTH_UNDEFINED;1223 1224	result = link_transmitter_control(enc110, &cntl);1225 1226	if (result != BP_RESULT_OK) {1227		DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1228			__func__);1229		BREAK_TO_DEBUGGER();1230	}1231}1232 1233/* enables DP PHY output in MST mode */1234static void dce60_link_encoder_enable_dp_mst_output(1235	struct link_encoder *enc,1236	const struct dc_link_settings *link_settings,1237	enum clock_source_id clock_source)1238{1239	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1240	struct bp_transmitter_control cntl = { 0 };1241	enum bp_result result;1242 1243	/* Enable the PHY */1244 1245	/* number_of_lanes is used for pixel clock adjust,1246	 * but it's not passed to asic_control.1247	 * We need to set number of lanes manually.1248	 */1249	dce60_configure_encoder(enc110, link_settings);1250 1251	cntl.action = TRANSMITTER_CONTROL_ENABLE;1252	cntl.engine_id = ENGINE_ID_UNKNOWN;1253	cntl.transmitter = enc110->base.transmitter;1254	cntl.pll_id = clock_source;1255	cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;1256	cntl.lanes_number = link_settings->lane_count;1257	cntl.hpd_sel = enc110->base.hpd_source;1258	cntl.pixel_clock = link_settings->link_rate1259						* LINK_RATE_REF_FREQ_IN_KHZ;1260	/* TODO: check if undefined works */1261	cntl.color_depth = COLOR_DEPTH_UNDEFINED;1262 1263	result = link_transmitter_control(enc110, &cntl);1264 1265	if (result != BP_RESULT_OK) {1266		DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1267			__func__);1268		BREAK_TO_DEBUGGER();1269	}1270}1271#endif1272 1273/*1274 * @brief1275 * Disable transmitter and its encoder1276 */1277void dce110_link_encoder_disable_output(1278	struct link_encoder *enc,1279	enum signal_type signal)1280{1281	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1282	struct bp_transmitter_control cntl = { 0 };1283	enum bp_result result;1284 1285	if (!dce110_is_dig_enabled(enc)) {1286		/* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */1287		return;1288	}1289	/* Power-down RX and disable GPU PHY should be paired.1290	 * Disabling PHY without powering down RX may cause1291	 * symbol lock loss, on which we will get DP Sink interrupt. */1292 1293	/* There is a case for the DP active dongles1294	 * where we want to disable the PHY but keep RX powered,1295	 * for those we need to ignore DP Sink interrupt1296	 * by checking lane count that has been set1297	 * on the last do_enable_output(). */1298 1299	/* disable transmitter */1300	cntl.action = TRANSMITTER_CONTROL_DISABLE;1301	cntl.transmitter = enc110->base.transmitter;1302	cntl.hpd_sel = enc110->base.hpd_source;1303	cntl.signal = signal;1304	cntl.connector_obj_id = enc110->base.connector;1305 1306	result = link_transmitter_control(enc110, &cntl);1307 1308	if (result != BP_RESULT_OK) {1309		DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",1310			__func__);1311		BREAK_TO_DEBUGGER();1312		return;1313	}1314 1315	/* disable encoder */1316	if (dc_is_dp_signal(signal))1317		link_encoder_disable(enc110);1318}1319 1320void dce110_link_encoder_dp_set_lane_settings(1321	struct link_encoder *enc,1322	const struct dc_link_settings *link_settings,1323	const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])1324{1325	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1326	union dpcd_training_lane_set training_lane_set = { { 0 } };1327	int32_t lane = 0;1328	struct bp_transmitter_control cntl = { 0 };1329 1330	if (!link_settings) {1331		BREAK_TO_DEBUGGER();1332		return;1333	}1334 1335	cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS;1336	cntl.transmitter = enc110->base.transmitter;1337	cntl.connector_obj_id = enc110->base.connector;1338	cntl.lanes_number = link_settings->lane_count;1339	cntl.hpd_sel = enc110->base.hpd_source;1340	cntl.pixel_clock = link_settings->link_rate *1341						LINK_RATE_REF_FREQ_IN_KHZ;1342 1343	for (lane = 0; lane < link_settings->lane_count; lane++) {1344		/* translate lane settings */1345 1346		training_lane_set.bits.VOLTAGE_SWING_SET =1347				lane_settings[lane].VOLTAGE_SWING;1348		training_lane_set.bits.PRE_EMPHASIS_SET =1349				lane_settings[lane].PRE_EMPHASIS;1350 1351		/* post cursor 2 setting only applies to HBR2 link rate */1352		if (link_settings->link_rate == LINK_RATE_HIGH2) {1353			/* this is passed to VBIOS1354			 * to program post cursor 2 level */1355 1356			training_lane_set.bits.POST_CURSOR2_SET =1357					lane_settings[lane].POST_CURSOR2;1358		}1359 1360		cntl.lane_select = lane;1361		cntl.lane_settings = training_lane_set.raw;1362 1363		/* call VBIOS table to set voltage swing and pre-emphasis */1364		if (link_transmitter_control(enc110, &cntl) != BP_RESULT_OK) {1365			DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", __func__);1366			BREAK_TO_DEBUGGER();1367		}1368	}1369}1370 1371/* set DP PHY test and training patterns */1372void dce110_link_encoder_dp_set_phy_pattern(1373	struct link_encoder *enc,1374	const struct encoder_set_dp_phy_pattern_param *param)1375{1376	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1377 1378	switch (param->dp_phy_pattern) {1379	case DP_TEST_PATTERN_TRAINING_PATTERN1:1380		dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0);1381		break;1382	case DP_TEST_PATTERN_TRAINING_PATTERN2:1383		dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1);1384		break;1385	case DP_TEST_PATTERN_TRAINING_PATTERN3:1386		dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2);1387		break;1388	case DP_TEST_PATTERN_TRAINING_PATTERN4:1389		dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3);1390		break;1391	case DP_TEST_PATTERN_D102:1392		set_dp_phy_pattern_d102(enc110);1393		break;1394	case DP_TEST_PATTERN_SYMBOL_ERROR:1395		set_dp_phy_pattern_symbol_error(enc110);1396		break;1397	case DP_TEST_PATTERN_PRBS7:1398		set_dp_phy_pattern_prbs7(enc110);1399		break;1400	case DP_TEST_PATTERN_80BIT_CUSTOM:1401		set_dp_phy_pattern_80bit_custom(1402			enc110, param->custom_pattern);1403		break;1404	case DP_TEST_PATTERN_CP2520_1:1405		set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 1);1406		break;1407	case DP_TEST_PATTERN_CP2520_2:1408		set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 2);1409		break;1410	case DP_TEST_PATTERN_CP2520_3:1411		set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 3);1412		break;1413	case DP_TEST_PATTERN_VIDEO_MODE: {1414		set_dp_phy_pattern_passthrough_mode(1415			enc110, param->dp_panel_mode);1416		break;1417	}1418 1419	default:1420		/* invalid phy pattern */1421		ASSERT_CRITICAL(false);1422		break;1423	}1424}1425 1426#if defined(CONFIG_DRM_AMD_DC_SI)1427/* set DP PHY test and training patterns */1428static void dce60_link_encoder_dp_set_phy_pattern(1429	struct link_encoder *enc,1430	const struct encoder_set_dp_phy_pattern_param *param)1431{1432	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1433 1434	switch (param->dp_phy_pattern) {1435	case DP_TEST_PATTERN_TRAINING_PATTERN1:1436		dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0);1437		break;1438	case DP_TEST_PATTERN_TRAINING_PATTERN2:1439		dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1);1440		break;1441	case DP_TEST_PATTERN_TRAINING_PATTERN3:1442		dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2);1443		break;1444	case DP_TEST_PATTERN_TRAINING_PATTERN4:1445		dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3);1446		break;1447	case DP_TEST_PATTERN_D102:1448		set_dp_phy_pattern_d102(enc110);1449		break;1450	case DP_TEST_PATTERN_SYMBOL_ERROR:1451		set_dp_phy_pattern_symbol_error(enc110);1452		break;1453	case DP_TEST_PATTERN_PRBS7:1454		set_dp_phy_pattern_prbs7(enc110);1455		break;1456	case DP_TEST_PATTERN_80BIT_CUSTOM:1457		set_dp_phy_pattern_80bit_custom(1458			enc110, param->custom_pattern);1459		break;1460	case DP_TEST_PATTERN_CP2520_1:1461		dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 1);1462		break;1463	case DP_TEST_PATTERN_CP2520_2:1464		dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 2);1465		break;1466	case DP_TEST_PATTERN_CP2520_3:1467		dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 3);1468		break;1469	case DP_TEST_PATTERN_VIDEO_MODE: {1470		dce60_set_dp_phy_pattern_passthrough_mode(1471			enc110, param->dp_panel_mode);1472		break;1473	}1474 1475	default:1476		/* invalid phy pattern */1477		ASSERT_CRITICAL(false);1478		break;1479	}1480}1481#endif1482 1483static void fill_stream_allocation_row_info(1484	const struct link_mst_stream_allocation *stream_allocation,1485	uint32_t *src,1486	uint32_t *slots)1487{1488	const struct stream_encoder *stream_enc = stream_allocation->stream_enc;1489 1490	if (stream_enc) {1491		*src = stream_enc->id;1492		*slots = stream_allocation->slot_count;1493	} else {1494		*src = 0;1495		*slots = 0;1496	}1497}1498 1499/* programs DP MST VC payload allocation */1500void dce110_link_encoder_update_mst_stream_allocation_table(1501	struct link_encoder *enc,1502	const struct link_mst_stream_allocation_table *table)1503{1504	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1505	uint32_t value1 = 0;1506	uint32_t value2 = 0;1507	uint32_t slots = 0;1508	uint32_t src = 0;1509	uint32_t retries = 0;1510 1511	/* For CZ, there are only 3 pipes. So Virtual channel is up 3.*/1512 1513	/* --- Set MSE Stream Attribute -1514	 * Setup VC Payload Table on Tx Side,1515	 * Issue allocation change trigger1516	 * to commit payload on both tx and rx side */1517 1518	/* we should clean-up table each time */1519 1520	if (table->stream_count >= 1) {1521		fill_stream_allocation_row_info(1522			&table->stream_allocations[0],1523			&src,1524			&slots);1525	} else {1526		src = 0;1527		slots = 0;1528	}1529 1530	REG_UPDATE_2(DP_MSE_SAT0,1531			DP_MSE_SAT_SRC0, src,1532			DP_MSE_SAT_SLOT_COUNT0, slots);1533 1534	if (table->stream_count >= 2) {1535		fill_stream_allocation_row_info(1536			&table->stream_allocations[1],1537			&src,1538			&slots);1539	} else {1540		src = 0;1541		slots = 0;1542	}1543 1544	REG_UPDATE_2(DP_MSE_SAT0,1545			DP_MSE_SAT_SRC1, src,1546			DP_MSE_SAT_SLOT_COUNT1, slots);1547 1548	if (table->stream_count >= 3) {1549		fill_stream_allocation_row_info(1550			&table->stream_allocations[2],1551			&src,1552			&slots);1553	} else {1554		src = 0;1555		slots = 0;1556	}1557 1558	REG_UPDATE_2(DP_MSE_SAT1,1559			DP_MSE_SAT_SRC2, src,1560			DP_MSE_SAT_SLOT_COUNT2, slots);1561 1562	if (table->stream_count >= 4) {1563		fill_stream_allocation_row_info(1564			&table->stream_allocations[3],1565			&src,1566			&slots);1567	} else {1568		src = 0;1569		slots = 0;1570	}1571 1572	REG_UPDATE_2(DP_MSE_SAT1,1573			DP_MSE_SAT_SRC3, src,1574			DP_MSE_SAT_SLOT_COUNT3, slots);1575 1576	/* --- wait for transaction finish */1577 1578	/* send allocation change trigger (ACT) ?1579	 * this step first sends the ACT,1580	 * then double buffers the SAT into the hardware1581	 * making the new allocation active on the DP MST mode link */1582 1583 1584	/* DP_MSE_SAT_UPDATE:1585	 * 0 - No Action1586	 * 1 - Update SAT with trigger1587	 * 2 - Update SAT without trigger */1588 1589	REG_UPDATE(DP_MSE_SAT_UPDATE,1590			DP_MSE_SAT_UPDATE, 1);1591 1592	/* wait for update to complete1593	 * (i.e. DP_MSE_SAT_UPDATE field is reset to 0)1594	 * then wait for the transmission1595	 * of at least 16 MTP headers on immediate local link.1596	 * i.e. DP_MSE_16_MTP_KEEPOUT field (read only) is reset to 01597	 * a value of 1 indicates that DP MST mode1598	 * is in the 16 MTP keepout region after a VC has been added.1599	 * MST stream bandwidth (VC rate) can be configured1600	 * after this bit is cleared */1601 1602	do {1603		udelay(10);1604 1605		REG_READ(DP_MSE_SAT_UPDATE);1606 1607		REG_GET(DP_MSE_SAT_UPDATE,1608				DP_MSE_SAT_UPDATE, &value1);1609 1610		REG_GET(DP_MSE_SAT_UPDATE,1611				DP_MSE_16_MTP_KEEPOUT, &value2);1612 1613		/* bit field DP_MSE_SAT_UPDATE is set to 1 already */1614		if (!value1 && !value2)1615			break;1616		++retries;1617	} while (retries < DP_MST_UPDATE_MAX_RETRY);1618}1619 1620void dce110_link_encoder_connect_dig_be_to_fe(1621	struct link_encoder *enc,1622	enum engine_id engine,1623	bool connect)1624{1625	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1626	uint32_t field;1627 1628	if (engine != ENGINE_ID_UNKNOWN) {1629 1630		REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &field);1631 1632		if (connect)1633			field |= get_frontend_source(engine);1634		else1635			field &= ~get_frontend_source(engine);1636 1637		REG_UPDATE(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, field);1638	}1639}1640 1641void dce110_link_encoder_enable_hpd(struct link_encoder *enc)1642{1643	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1644	struct dc_context *ctx = enc110->base.ctx;1645	uint32_t addr = HPD_REG(DC_HPD_CONTROL);1646	uint32_t hpd_enable = 0;1647	uint32_t value = dm_read_reg(ctx, addr);1648 1649	hpd_enable = get_reg_field_value(hpd_enable, DC_HPD_CONTROL, DC_HPD_EN);1650 1651	if (hpd_enable == 0)1652		set_reg_field_value(value, 1, DC_HPD_CONTROL, DC_HPD_EN);1653}1654 1655void dce110_link_encoder_disable_hpd(struct link_encoder *enc)1656{1657	struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);1658	struct dc_context *ctx = enc110->base.ctx;1659	uint32_t addr = HPD_REG(DC_HPD_CONTROL);1660	uint32_t value = dm_read_reg(ctx, addr);1661 1662	set_reg_field_value(value, 0, DC_HPD_CONTROL, DC_HPD_EN);1663}1664 1665void dce110_link_encoder_get_max_link_cap(struct link_encoder *enc,1666	struct dc_link_settings *link_settings)1667{1668	/* Set Default link settings */1669	struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH,1670			LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0};1671 1672	/* Higher link settings based on feature supported */1673	if (enc->features.flags.bits.IS_HBR2_CAPABLE)1674		max_link_cap.link_rate = LINK_RATE_HIGH2;1675 1676	if (enc->features.flags.bits.IS_HBR3_CAPABLE)1677		max_link_cap.link_rate = LINK_RATE_HIGH3;1678 1679	*link_settings = max_link_cap;1680}1681 1682#if defined(CONFIG_DRM_AMD_DC_SI)1683static const struct link_encoder_funcs dce60_lnk_enc_funcs = {1684	.validate_output_with_stream =1685		dce110_link_encoder_validate_output_with_stream,1686	.hw_init = dce110_link_encoder_hw_init,1687	.setup = dce110_link_encoder_setup,1688	.enable_tmds_output = dce110_link_encoder_enable_tmds_output,1689	.enable_dp_output = dce60_link_encoder_enable_dp_output,1690	.enable_dp_mst_output = dce60_link_encoder_enable_dp_mst_output,1691	.enable_lvds_output = dce110_link_encoder_enable_lvds_output,1692	.disable_output = dce110_link_encoder_disable_output,1693	.dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,1694	.dp_set_phy_pattern = dce60_link_encoder_dp_set_phy_pattern,1695	.update_mst_stream_allocation_table =1696		dce110_link_encoder_update_mst_stream_allocation_table,1697	.psr_program_dp_dphy_fast_training =1698			dce110_psr_program_dp_dphy_fast_training,1699	.psr_program_secondary_packet = dce110_psr_program_secondary_packet,1700	.connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,1701	.enable_hpd = dce110_link_encoder_enable_hpd,1702	.disable_hpd = dce110_link_encoder_disable_hpd,1703	.is_dig_enabled = dce110_is_dig_enabled,1704	.destroy = dce110_link_encoder_destroy,1705	.get_max_link_cap = dce110_link_encoder_get_max_link_cap,1706	.get_dig_frontend = dce110_get_dig_frontend1707};1708 1709void dce60_link_encoder_construct(1710	struct dce110_link_encoder *enc110,1711	const struct encoder_init_data *init_data,1712	const struct encoder_feature_support *enc_features,1713	const struct dce110_link_enc_registers *link_regs,1714	const struct dce110_link_enc_aux_registers *aux_regs,1715	const struct dce110_link_enc_hpd_registers *hpd_regs)1716{1717	struct bp_encoder_cap_info bp_cap_info = {0};1718	const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;1719	enum bp_result result = BP_RESULT_OK;1720 1721	enc110->base.funcs = &dce60_lnk_enc_funcs;1722	enc110->base.ctx = init_data->ctx;1723	enc110->base.id = init_data->encoder;1724 1725	enc110->base.hpd_source = init_data->hpd_source;1726	enc110->base.connector = init_data->connector;1727 1728	enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;1729 1730	enc110->base.features = *enc_features;1731 1732	enc110->base.transmitter = init_data->transmitter;1733 1734	/* set the flag to indicate whether driver poll the I2C data pin1735	 * while doing the DP sink detect1736	 */1737 1738/*	if (dal_adapter_service_is_feature_supported(as,1739		FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))1740		enc110->base.features.flags.bits.1741			DP_SINK_DETECT_POLL_DATA_PIN = true;*/1742 1743	enc110->base.output_signals =1744		SIGNAL_TYPE_DVI_SINGLE_LINK |1745		SIGNAL_TYPE_DVI_DUAL_LINK |1746		SIGNAL_TYPE_LVDS |1747		SIGNAL_TYPE_DISPLAY_PORT |1748		SIGNAL_TYPE_DISPLAY_PORT_MST |1749		SIGNAL_TYPE_EDP |1750		SIGNAL_TYPE_HDMI_TYPE_A;1751 1752	/* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE.1753	 * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY.1754	 * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer1755	 * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS.1756	 * Prefer DIG assignment is decided by board design.1757	 * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design1758	 * and VBIOS will filter out 7 UNIPHY for DCE 8.0.1759	 * By this, adding DIGG should not hurt DCE 8.0.1760	 * This will let DCE 8.1 share DCE 8.0 as much as possible1761	 */1762 1763	enc110->link_regs = link_regs;1764	enc110->aux_regs = aux_regs;1765	enc110->hpd_regs = hpd_regs;1766 1767	switch (enc110->base.transmitter) {1768	case TRANSMITTER_UNIPHY_A:1769		enc110->base.preferred_engine = ENGINE_ID_DIGA;1770	break;1771	case TRANSMITTER_UNIPHY_B:1772		enc110->base.preferred_engine = ENGINE_ID_DIGB;1773	break;1774	case TRANSMITTER_UNIPHY_C:1775		enc110->base.preferred_engine = ENGINE_ID_DIGC;1776	break;1777	case TRANSMITTER_UNIPHY_D:1778		enc110->base.preferred_engine = ENGINE_ID_DIGD;1779	break;1780	case TRANSMITTER_UNIPHY_E:1781		enc110->base.preferred_engine = ENGINE_ID_DIGE;1782	break;1783	case TRANSMITTER_UNIPHY_F:1784		enc110->base.preferred_engine = ENGINE_ID_DIGF;1785	break;1786	case TRANSMITTER_UNIPHY_G:1787		enc110->base.preferred_engine = ENGINE_ID_DIGG;1788	break;1789	default:1790		ASSERT_CRITICAL(false);1791		enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;1792	}1793 1794	/* default to one to mirror Windows behavior */1795	enc110->base.features.flags.bits.HDMI_6GB_EN = 1;1796 1797	result = bp_funcs->get_encoder_cap_info(enc110->base.ctx->dc_bios,1798						enc110->base.id, &bp_cap_info);1799 1800	/* Override features with DCE-specific values */1801	if (BP_RESULT_OK == result) {1802		enc110->base.features.flags.bits.IS_HBR2_CAPABLE =1803				bp_cap_info.DP_HBR2_EN;1804		enc110->base.features.flags.bits.IS_HBR3_CAPABLE =1805				bp_cap_info.DP_HBR3_EN;1806		enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;1807	} else {1808		DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",1809				__func__,1810				result);1811	}1812	if (enc110->base.ctx->dc->debug.hdmi20_disable) {1813		enc110->base.features.flags.bits.HDMI_6GB_EN = 0;1814	}1815}1816#endif1817