diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display')
38 files changed, 970 insertions, 327 deletions
| diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c index 8f78e62b28b7..48005def1164 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c @@ -741,7 +741,7 @@ void vg_clk_mgr_construct(  				sizeof(struct watermarks),  				&clk_mgr->smu_wm_set.mc_address.quad_part); -	if (clk_mgr->smu_wm_set.wm_set == 0) { +	if (!clk_mgr->smu_wm_set.wm_set) {  		clk_mgr->smu_wm_set.wm_set = &dummy_wms;  		clk_mgr->smu_wm_set.mc_address.quad_part = 0;  	} diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 412cc6a716f7..4162ce40089b 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -158,6 +158,7 @@ void dcn31_update_clocks(struct clk_mgr *clk_mgr_base,  				union display_idle_optimization_u idle_info = { 0 };  				idle_info.idle_info.df_request_disabled = 1;  				idle_info.idle_info.phy_ref_clk_off = 1; +				idle_info.idle_info.s0i2_rdy = 1;  				dcn31_smu_set_display_idle_optimization(clk_mgr, idle_info.data);  				/* update power state */  				clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c250f6de5136..91c4874473d6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -274,24 +274,6 @@ static bool create_links(  			goto failed_alloc;  		} -#if defined(CONFIG_DRM_AMD_DC_DCN) -		if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) && -				dc->caps.dp_hpo && -				link->dc->res_pool->res_cap->num_hpo_dp_link_encoder > 0) { -			/* FPGA case - Allocate HPO DP link encoder */ -			if (i < link->dc->res_pool->res_cap->num_hpo_dp_link_encoder) { -				link->hpo_dp_link_enc = link->dc->res_pool->hpo_dp_link_enc[i]; - -				if (link->hpo_dp_link_enc == NULL) { -					BREAK_TO_DEBUGGER(); -					goto failed_alloc; -				} -				link->hpo_dp_link_enc->hpd_source = link->link_enc->hpd_source; -				link->hpo_dp_link_enc->transmitter = link->link_enc->transmitter; -			} -		} -#endif -  		link->link_status.dpcd_caps = &link->dpcd_caps;  		enc_init.ctx = dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c index 21be2a684393..643762542e4d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_debug.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_debug.c @@ -422,6 +422,8 @@ char *dc_status_to_str(enum dc_status status)  		return "The operation is not supported.";  	case DC_UNSUPPORTED_VALUE:  		return "The value specified is not supported."; +	case DC_NO_LINK_ENC_RESOURCE: +		return "No link encoder resource";  	case DC_ERROR_UNEXPECTED:  		return "Unexpected error";  	} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 3d75f56a939c..dc1380b6c5e0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -66,31 +66,6 @@  /*******************************************************************************   * Private functions   ******************************************************************************/ -#if defined(CONFIG_DRM_AMD_DC_DCN) -static bool add_dp_hpo_link_encoder_to_link(struct dc_link *link) -{ -	struct hpo_dp_link_encoder *enc = resource_get_unused_hpo_dp_link_encoder( -					link->dc->res_pool); - -	if (!link->hpo_dp_link_enc && enc) { -		link->hpo_dp_link_enc = enc; -		link->hpo_dp_link_enc->transmitter = link->link_enc->transmitter; -		link->hpo_dp_link_enc->hpd_source = link->link_enc->hpd_source; -	} - -	return (link->hpo_dp_link_enc != NULL); -} - -static void remove_dp_hpo_link_encoder_from_link(struct dc_link *link) -{ -	if (link->hpo_dp_link_enc) { -		link->hpo_dp_link_enc->hpd_source = HPD_SOURCEID_UNKNOWN; -		link->hpo_dp_link_enc->transmitter = TRANSMITTER_UNKNOWN; -		link->hpo_dp_link_enc = NULL; -	} -} -#endif -  static void dc_link_destruct(struct dc_link *link)  {  	int i; @@ -118,12 +93,6 @@ static void dc_link_destruct(struct dc_link *link)  		link->link_enc->funcs->destroy(&link->link_enc);  	} -#if defined(CONFIG_DRM_AMD_DC_DCN) -	if (link->hpo_dp_link_enc) { -		remove_dp_hpo_link_encoder_from_link(link); -	} -#endif -  	if (link->local_sink)  		dc_sink_release(link->local_sink); @@ -881,6 +850,7 @@ static bool dc_link_detect_helper(struct dc_link *link,  	enum dc_connection_type pre_connection_type = dc_connection_none;  	bool perform_dp_seamless_boot = false;  	const uint32_t post_oui_delay = 30; // 30ms +	struct link_resource link_res = { 0 };  	DC_LOGGER_INIT(link->ctx->logger); @@ -975,7 +945,10 @@ static bool dc_link_detect_helper(struct dc_link *link,  #if defined(CONFIG_DRM_AMD_DC_DCN)  			if (dp_get_link_encoding_format(&link->reported_link_cap) == DP_128b_132b_ENCODING) -				add_dp_hpo_link_encoder_to_link(link); +				link_res.hpo_dp_link_enc = resource_get_hpo_dp_link_enc_for_det_lt( +						&link->dc->current_state->res_ctx, +						link->dc->res_pool, +						link);  #endif  			if (link->type == dc_connection_mst_branch) { @@ -986,7 +959,7 @@ static bool dc_link_detect_helper(struct dc_link *link,  				 * empty which leads to allocate_mst_payload() has "0"  				 * pbn_per_slot value leading to exception on dc_fixpt_div()  				 */ -				dp_verify_mst_link_cap(link); +				dp_verify_mst_link_cap(link, &link_res);  				/*  				 * This call will initiate MST topology discovery. Which @@ -1150,6 +1123,7 @@ static bool dc_link_detect_helper(struct dc_link *link,  			// verify link cap for SST non-seamless boot  			if (!perform_dp_seamless_boot)  				dp_verify_link_cap_with_retries(link, +								&link_res,  								&link->reported_link_cap,  								LINK_TRAINING_MAX_VERIFY_RETRY);  		} else { @@ -1844,6 +1818,8 @@ static void enable_stream_features(struct pipe_ctx *pipe_ctx)  		union down_spread_ctrl old_downspread;  		union down_spread_ctrl new_downspread; +		memset(&old_downspread, 0, sizeof(old_downspread)); +  		core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL,  				&old_downspread.raw, sizeof(old_downspread)); @@ -2503,7 +2479,8 @@ static void write_i2c_redriver_setting(  		DC_LOG_DEBUG("Set redriver failed");  } -static void disable_link(struct dc_link *link, enum signal_type signal) +static void disable_link(struct dc_link *link, const struct link_resource *link_res, +		enum signal_type signal)  {  	/*  	 * TODO: implement call for dp_set_hw_test_pattern @@ -2522,20 +2499,20 @@ static void disable_link(struct dc_link *link, enum signal_type signal)  		struct dc_link_settings link_settings = link->cur_link_settings;  #endif  		if (dc_is_dp_sst_signal(signal)) -			dp_disable_link_phy(link, signal); +			dp_disable_link_phy(link, link_res, signal);  		else -			dp_disable_link_phy_mst(link, signal); +			dp_disable_link_phy_mst(link, link_res, signal);  		if (dc_is_dp_sst_signal(signal) ||  				link->mst_stream_alloc_table.stream_count == 0) {  #if defined(CONFIG_DRM_AMD_DC_DCN)  			if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING) {  				dp_set_fec_enable(link, false); -				dp_set_fec_ready(link, false); +				dp_set_fec_ready(link, link_res, false);  			}  #else  			dp_set_fec_enable(link, false); -			dp_set_fec_ready(link, false); +			dp_set_fec_ready(link, link_res, false);  #endif  		}  	} else { @@ -2646,7 +2623,7 @@ static enum dc_status enable_link(  	 * new link settings.  	 */  	if (link->link_status.link_active) { -		disable_link(link, pipe_ctx->stream->signal); +		disable_link(link, &pipe_ctx->link_res, pipe_ctx->stream->signal);  	}  	switch (pipe_ctx->stream->signal) { @@ -3421,7 +3398,7 @@ static enum dc_status dc_link_update_sst_payload(struct pipe_ctx *pipe_ctx,  {  	struct dc_stream_state *stream = pipe_ctx->stream;  	struct dc_link *link = stream->link; -	struct hpo_dp_link_encoder *hpo_dp_link_encoder = link->hpo_dp_link_enc; +	struct hpo_dp_link_encoder *hpo_dp_link_encoder = pipe_ctx->link_res.hpo_dp_link_enc;  	struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc;  	struct link_mst_stream_allocation_table proposed_table = {0};  	struct fixed31_32 avg_time_slots_per_mtp; @@ -3503,7 +3480,7 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)  	struct link_encoder *link_encoder = NULL;  	struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;  #if defined(CONFIG_DRM_AMD_DC_DCN) -	struct hpo_dp_link_encoder *hpo_dp_link_encoder = link->hpo_dp_link_enc; +	struct hpo_dp_link_encoder *hpo_dp_link_encoder = pipe_ctx->link_res.hpo_dp_link_enc;  	struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc;  #endif  	struct dp_mst_stream_allocation_table proposed_table = {0}; @@ -3833,7 +3810,7 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)  	struct link_encoder *link_encoder = NULL;  	struct stream_encoder *stream_encoder = pipe_ctx->stream_res.stream_enc;  #if defined(CONFIG_DRM_AMD_DC_DCN) -	struct hpo_dp_link_encoder *hpo_dp_link_encoder = link->hpo_dp_link_enc; +	struct hpo_dp_link_encoder *hpo_dp_link_encoder = pipe_ctx->link_res.hpo_dp_link_enc;  	struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc;  #endif  	struct dp_mst_stream_allocation_table proposed_table = {0}; @@ -4009,12 +3986,9 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)  		config.dig_be = pipe_ctx->stream->link->link_enc_hw_inst;  #if defined(CONFIG_DRM_AMD_DC_DCN)  		config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA; -		 +  		if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_PHY ||  				pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) { -			link_enc = pipe_ctx->stream->link->link_enc; -			config.dio_output_type = pipe_ctx->stream->link->ep_type; -			config.dio_output_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;  			if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_PHY)  				link_enc = pipe_ctx->stream->link->link_enc;  			else if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) @@ -4081,7 +4055,8 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)  			config.link_enc_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;  		if (is_dp_128b_132b_signal(pipe_ctx)) {  			config.stream_enc_idx = pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0; -			config.link_enc_idx = pipe_ctx->stream->link->hpo_dp_link_enc->inst; + +			config.link_enc_idx = pipe_ctx->link_res.hpo_dp_link_enc->inst;  			config.dp2_enabled = 1;  		}  #endif @@ -4112,7 +4087,7 @@ static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pi  	stream->link->cur_link_settings = link_settings;  	/*  Enable clock, Configure lane count, and Enable Link Encoder*/ -	enable_dp_hpo_output(stream->link, &stream->link->cur_link_settings); +	enable_dp_hpo_output(stream->link, &pipe_ctx->link_res, &stream->link->cur_link_settings);  #ifdef DIAGS_BUILD  	/* Workaround for FPGA HPO capture DP link data: @@ -4162,12 +4137,12 @@ static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pi  		proposed_table.stream_allocations[0].hpo_dp_stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;  	} -	stream->link->hpo_dp_link_enc->funcs->update_stream_allocation_table( -			stream->link->hpo_dp_link_enc, +	pipe_ctx->link_res.hpo_dp_link_enc->funcs->update_stream_allocation_table( +			pipe_ctx->link_res.hpo_dp_link_enc,  			&proposed_table); -	stream->link->hpo_dp_link_enc->funcs->set_throttled_vcp_size( -			stream->link->hpo_dp_link_enc, +	pipe_ctx->link_res.hpo_dp_link_enc->funcs->set_throttled_vcp_size( +			pipe_ctx->link_res.hpo_dp_link_enc,  			pipe_ctx->stream_res.hpo_dp_stream_enc->inst,  			avg_time_slots_per_mtp); @@ -4356,7 +4331,8 @@ void core_link_enable_stream(  			if (status != DC_FAIL_DP_LINK_TRAINING ||  					pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {  				if (false == stream->link->link_status.link_active) -					disable_link(stream->link, pipe_ctx->stream->signal); +					disable_link(stream->link, &pipe_ctx->link_res, +							pipe_ctx->stream->signal);  				BREAK_TO_DEBUGGER();  				return;  			} @@ -4505,14 +4481,14 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx)  		 * state machine.  		 * In DP2 or MST mode, our encoder will stay video active  		 */ -		disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal); +		disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);  		dc->hwss.disable_stream(pipe_ctx);  	} else {  		dc->hwss.disable_stream(pipe_ctx); -		disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal); +		disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);  	}  #else -	disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal); +	disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);  	dc->hwss.disable_stream(pipe_ctx);  #endif @@ -4595,16 +4571,22 @@ void dc_link_set_drive_settings(struct dc *dc,  {  	int i; +	struct pipe_ctx *pipe = NULL; +	const struct link_resource *link_res; -	for (i = 0; i < dc->link_count; i++) { -		if (dc->links[i] == link) -			break; -	} +	link_res = dc_link_get_cur_link_res(link); -	if (i >= dc->link_count) +	for (i = 0; i < MAX_PIPES; i++) { +		pipe = &dc->current_state->res_ctx.pipe_ctx[i]; +		if (pipe->stream && pipe->stream->link) { +			if (pipe->stream->link == link) +				break; +		} +	} +	if (pipe && link_res) +		dc_link_dp_set_drive_settings(pipe->stream->link, link_res, lt_settings); +	else  		ASSERT_CRITICAL(false); - -	dc_link_dp_set_drive_settings(dc->links[i], lt_settings);  }  void dc_link_set_preferred_link_settings(struct dc *dc, @@ -4665,11 +4647,9 @@ void dc_link_set_preferred_training_settings(struct dc *dc,  	if (link_setting != NULL) {  		link->preferred_link_setting = *link_setting;  #if defined(CONFIG_DRM_AMD_DC_DCN) -		if (dp_get_link_encoding_format(link_setting) == -				DP_128b_132b_ENCODING && !link->hpo_dp_link_enc) { -			if (!add_dp_hpo_link_encoder_to_link(link)) -				memset(&link->preferred_link_setting, 0, sizeof(link->preferred_link_setting)); -		} +		if (dp_get_link_encoding_format(link_setting) == DP_128b_132b_ENCODING) +			/* TODO: add dc update for acquiring link res  */ +			skip_immediate_retrain = true;  #endif  	} else {  		link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN; @@ -4796,6 +4776,9 @@ void dc_link_overwrite_extended_receiver_cap(  bool dc_link_is_fec_supported(const struct dc_link *link)  { +	/* TODO - use asic cap instead of link_enc->features +	 * we no longer know which link enc to use for this link before commit +	 */  	struct link_encoder *link_enc = NULL;  	/* Links supporting dynamically assigned link encoder will be assigned next @@ -4890,3 +4873,125 @@ uint32_t dc_bandwidth_in_kbps_from_timing(  	return kbps;  } + +const struct link_resource *dc_link_get_cur_link_res(const struct dc_link *link) +{ +	int i; +	struct pipe_ctx *pipe = NULL; +	const struct link_resource *link_res = NULL; + +	for (i = 0; i < MAX_PIPES; i++) { +		pipe = &link->dc->current_state->res_ctx.pipe_ctx[i]; +		if (pipe->stream && pipe->stream->link && pipe->top_pipe == NULL) { +			if (pipe->stream->link == link) { +				link_res = &pipe->link_res; +				break; +			} +		} +	} + +	return link_res; +} + +/** + * dc_get_cur_link_res_map() - take a snapshot of current link resource allocation state + * @dc: pointer to dc of the dm calling this + * @map: a dc link resource snapshot defined internally to dc. + * + * DM needs to capture a snapshot of current link resource allocation mapping + * and store it in its persistent storage. + * + * Some of the link resource is using first come first serve policy. + * The allocation mapping depends on original hotplug order. This information + * is lost after driver is loaded next time. The snapshot is used in order to + * restore link resource to its previous state so user will get consistent + * link capability allocation across reboot. + * + * Return: none (void function) + * + */ +void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map) +{ +#if defined(CONFIG_DRM_AMD_DC_DCN) +	struct dc_link *link; +	uint8_t i; +	uint32_t hpo_dp_recycle_map = 0; + +	*map = 0; + +	if (dc->caps.dp_hpo) { +		for (i = 0; i < dc->caps.max_links; i++) { +			link = dc->links[i]; +			if (link->link_status.link_active && +					dp_get_link_encoding_format(&link->reported_link_cap) == DP_128b_132b_ENCODING && +					dp_get_link_encoding_format(&link->cur_link_settings) != DP_128b_132b_ENCODING) +				/* hpo dp link encoder is considered as recycled, when RX reports 128b/132b encoding capability +				 * but current link doesn't use it. +				 */ +				hpo_dp_recycle_map |= (1 << i); +		} +		*map |= (hpo_dp_recycle_map << LINK_RES_HPO_DP_REC_MAP__SHIFT); +	} +#endif +} + +/** + * dc_restore_link_res_map() - restore link resource allocation state from a snapshot + * @dc: pointer to dc of the dm calling this + * @map: a dc link resource snapshot defined internally to dc. + * + * DM needs to call this function after initial link detection on boot and + * before first commit streams to restore link resource allocation state + * from previous boot session. + * + * Some of the link resource is using first come first serve policy. + * The allocation mapping depends on original hotplug order. This information + * is lost after driver is loaded next time. The snapshot is used in order to + * restore link resource to its previous state so user will get consistent + * link capability allocation across reboot. + * + * Return: none (void function) + * + */ +void dc_restore_link_res_map(const struct dc *dc, uint32_t *map) +{ +#if defined(CONFIG_DRM_AMD_DC_DCN) +	struct dc_link *link; +	uint8_t i; +	unsigned int available_hpo_dp_count; +	uint32_t hpo_dp_recycle_map = (*map & LINK_RES_HPO_DP_REC_MAP__MASK) +			>> LINK_RES_HPO_DP_REC_MAP__SHIFT; + +	if (dc->caps.dp_hpo) { +		available_hpo_dp_count = dc->res_pool->hpo_dp_link_enc_count; +		/* remove excess 128b/132b encoding support for not recycled links */ +		for (i = 0; i < dc->caps.max_links; i++) { +			if ((hpo_dp_recycle_map & (1 << i)) == 0) { +				link = dc->links[i]; +				if (link->type != dc_connection_none && +						dp_get_link_encoding_format(&link->verified_link_cap) == DP_128b_132b_ENCODING) { +					if (available_hpo_dp_count > 0) +						available_hpo_dp_count--; +					else +						/* remove 128b/132b encoding capability by limiting verified link rate to HBR3 */ +						link->verified_link_cap.link_rate = LINK_RATE_HIGH3; +				} +			} +		} +		/* remove excess 128b/132b encoding support for recycled links */ +		for (i = 0; i < dc->caps.max_links; i++) { +			if ((hpo_dp_recycle_map & (1 << i)) != 0) { +				link = dc->links[i]; +				if (link->type != dc_connection_none && +						dp_get_link_encoding_format(&link->verified_link_cap) == DP_128b_132b_ENCODING) { +					if (available_hpo_dp_count > 0) +						available_hpo_dp_count--; +					else +						/* remove 128b/132b encoding capability by limiting verified link rate to HBR3 */ +						link->verified_link_cap.link_rate = LINK_RATE_HIGH3; +				} +			} +		} +	} +#endif +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 8a35370da867..05e216524370 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1251,6 +1251,7 @@ bool dp_is_max_vs_reached(  static bool perform_post_lt_adj_req_sequence(  	struct dc_link *link, +	const struct link_resource *link_res,  	struct link_training_settings *lt_settings)  {  	enum dc_lane_count lane_count = @@ -1314,6 +1315,7 @@ static bool perform_post_lt_adj_req_sequence(  						lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);  				dc_link_dp_set_drive_settings(link, +						link_res,  						lt_settings);  				break;  			} @@ -1388,6 +1390,7 @@ enum link_training_result dp_get_cr_failure(enum dc_lane_count ln_count,  static enum link_training_result perform_channel_equalization_sequence(  	struct dc_link *link, +	const struct link_resource *link_res,  	struct link_training_settings *lt_settings,  	uint32_t offset)  { @@ -1410,12 +1413,12 @@ static enum link_training_result perform_channel_equalization_sequence(  		tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;  #endif -	dp_set_hw_training_pattern(link, tr_pattern, offset); +	dp_set_hw_training_pattern(link, link_res, tr_pattern, offset);  	for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;  		retries_ch_eq++) { -		dp_set_hw_lane_settings(link, lt_settings, offset); +		dp_set_hw_lane_settings(link, link_res, lt_settings, offset);  		/* 2. update DPCD*/  		if (!retries_ch_eq) @@ -1479,18 +1482,20 @@ static enum link_training_result perform_channel_equalization_sequence(  }  static void start_clock_recovery_pattern_early(struct dc_link *link, +		const struct link_resource *link_res,  		struct link_training_settings *lt_settings,  		uint32_t offset)  {  	DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS1. Wait 400us.\n",  			__func__); -	dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, offset); -	dp_set_hw_lane_settings(link, lt_settings, offset); +	dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset); +	dp_set_hw_lane_settings(link, link_res, lt_settings, offset);  	udelay(400);  }  static enum link_training_result perform_clock_recovery_sequence(  	struct dc_link *link, +	const struct link_resource *link_res,  	struct link_training_settings *lt_settings,  	uint32_t offset)  { @@ -1506,7 +1511,7 @@ static enum link_training_result perform_clock_recovery_sequence(  	retry_count = 0;  	if (!link->ctx->dc->work_arounds.lt_early_cr_pattern) -		dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, offset); +		dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset);  	/* najeeb - The synaptics MST hub can put the LT in  	* infinite loop by switching the VS @@ -1523,6 +1528,7 @@ static enum link_training_result perform_clock_recovery_sequence(  		/* 1. call HWSS to set lane settings*/  		dp_set_hw_lane_settings(  				link, +				link_res,  				lt_settings,  				offset); @@ -1544,9 +1550,6 @@ static enum link_training_result perform_clock_recovery_sequence(  		/* 3. wait receiver to lock-on*/  		wait_time_microsec = lt_settings->cr_pattern_time; -		if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) -			wait_time_microsec = TRAINING_AUX_RD_INTERVAL; -  		if (link->dc->debug.apply_vendor_specific_lttpr_wa &&  				(link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN)) {  			wait_time_microsec = 16000; @@ -1624,13 +1627,14 @@ static enum link_training_result perform_clock_recovery_sequence(  static inline enum link_training_result dp_transition_to_video_idle(  	struct dc_link *link, +	const struct link_resource *link_res,  	struct link_training_settings *lt_settings,  	enum link_training_result status)  {  	union lane_count_set lane_count_set = {0};  	/* 4. mainlink output idle pattern*/ -	dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0); +	dp_set_hw_test_pattern(link, link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);  	/*  	 * 5. post training adjust if required @@ -1654,7 +1658,7 @@ static inline enum link_training_result dp_transition_to_video_idle(  	}  	if (status == LINK_TRAINING_SUCCESS && -		perform_post_lt_adj_req_sequence(link, lt_settings) == false) +		perform_post_lt_adj_req_sequence(link, link_res, lt_settings) == false)  		status = LINK_TRAINING_LQA_FAIL;  	lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count; @@ -2097,10 +2101,11 @@ static void print_status_message(  void dc_link_dp_set_drive_settings(  	struct dc_link *link, +	const struct link_resource *link_res,  	struct link_training_settings *lt_settings)  {  	/* program ASIC PHY settings*/ -	dp_set_hw_lane_settings(link, lt_settings, DPRX); +	dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);  	dp_hw_to_dpcd_lane_settings(lt_settings,  			lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); @@ -2111,6 +2116,7 @@ void dc_link_dp_set_drive_settings(  bool dc_link_dp_perform_link_training_skip_aux(  	struct dc_link *link, +	const struct link_resource *link_res,  	const struct dc_link_settings *link_setting)  {  	struct link_training_settings lt_settings = {0}; @@ -2127,10 +2133,10 @@ bool dc_link_dp_perform_link_training_skip_aux(  	/* 1. Perform_clock_recovery_sequence. */  	/* transmit training pattern for clock recovery */ -	dp_set_hw_training_pattern(link, lt_settings.pattern_for_cr, DPRX); +	dp_set_hw_training_pattern(link, link_res, lt_settings.pattern_for_cr, DPRX);  	/* call HWSS to set lane settings*/ -	dp_set_hw_lane_settings(link, <_settings, DPRX); +	dp_set_hw_lane_settings(link, link_res, <_settings, DPRX);  	/* wait receiver to lock-on*/  	dp_wait_for_training_aux_rd_interval(link, lt_settings.cr_pattern_time); @@ -2138,10 +2144,10 @@ bool dc_link_dp_perform_link_training_skip_aux(  	/* 2. Perform_channel_equalization_sequence. */  	/* transmit training pattern for channel equalization. */ -	dp_set_hw_training_pattern(link, lt_settings.pattern_for_eq, DPRX); +	dp_set_hw_training_pattern(link, link_res, lt_settings.pattern_for_eq, DPRX);  	/* call HWSS to set lane settings*/ -	dp_set_hw_lane_settings(link, <_settings, DPRX); +	dp_set_hw_lane_settings(link, link_res, <_settings, DPRX);  	/* wait receiver to lock-on. */  	dp_wait_for_training_aux_rd_interval(link, lt_settings.eq_pattern_time); @@ -2149,7 +2155,7 @@ bool dc_link_dp_perform_link_training_skip_aux(  	/* 3. Perform_link_training_int. */  	/* Mainlink output idle pattern. */ -	dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0); +	dp_set_hw_test_pattern(link, link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);  	print_status_message(link, <_settings, LINK_TRAINING_SUCCESS); @@ -2230,6 +2236,7 @@ static void dpcd_128b_132b_get_aux_rd_interval(struct dc_link *link,  static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(  		struct dc_link *link, +		const struct link_resource *link_res,  		struct link_training_settings *lt_settings)  {  	uint8_t loop_count; @@ -2241,7 +2248,7 @@ static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(  	union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};  	/* Transmit 128b/132b_TPS1 over Main-Link */ -	dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, DPRX); +	dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, DPRX);  	/* Set TRAINING_PATTERN_SET to 01h */  	dpcd_set_training_pattern(link, lt_settings->pattern_for_cr); @@ -2251,8 +2258,8 @@ static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(  			&dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);  	dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,  			lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); -	dp_set_hw_lane_settings(link, lt_settings, DPRX); -	dp_set_hw_training_pattern(link, lt_settings->pattern_for_eq, DPRX); +	dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX); +	dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_eq, DPRX);  	/* Set loop counter to start from 1 */  	loop_count = 1; @@ -2279,7 +2286,7 @@ static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(  		} else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {  			status = DP_128b_132b_LT_FAILED;  		} else { -			dp_set_hw_lane_settings(link, lt_settings, DPRX); +			dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);  			dpcd_set_lane_settings(link, lt_settings, DPRX);  		}  		loop_count++; @@ -2308,6 +2315,7 @@ static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(  static enum link_training_result dp_perform_128b_132b_cds_done_sequence(  		struct dc_link *link, +		const struct link_resource *link_res,  		struct link_training_settings *lt_settings)  {  	/* Assumption: assume hardware has transmitted eq pattern */ @@ -2344,6 +2352,7 @@ static enum link_training_result dp_perform_128b_132b_cds_done_sequence(  static enum link_training_result dp_perform_8b_10b_link_training(  		struct dc_link *link, +		const struct link_resource *link_res,  		struct link_training_settings *lt_settings)  {  	enum link_training_result status = LINK_TRAINING_SUCCESS; @@ -2353,7 +2362,7 @@ static enum link_training_result dp_perform_8b_10b_link_training(  	uint8_t lane = 0;  	if (link->ctx->dc->work_arounds.lt_early_cr_pattern) -		start_clock_recovery_pattern_early(link, lt_settings, DPRX); +		start_clock_recovery_pattern_early(link, link_res, lt_settings, DPRX);  	/* 1. set link rate, lane count and spread. */  	dpcd_set_link_settings(link, lt_settings); @@ -2367,12 +2376,13 @@ static enum link_training_result dp_perform_8b_10b_link_training(  		for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);  				repeater_id--) { -			status = perform_clock_recovery_sequence(link, lt_settings, repeater_id); +			status = perform_clock_recovery_sequence(link, link_res, lt_settings, repeater_id);  			if (status != LINK_TRAINING_SUCCESS)  				break;  			status = perform_channel_equalization_sequence(link, +					link_res,  					lt_settings,  					repeater_id); @@ -2387,9 +2397,10 @@ static enum link_training_result dp_perform_8b_10b_link_training(  	}  	if (status == LINK_TRAINING_SUCCESS) { -		status = perform_clock_recovery_sequence(link, lt_settings, DPRX); +		status = perform_clock_recovery_sequence(link, link_res, lt_settings, DPRX);  	if (status == LINK_TRAINING_SUCCESS) {  		status = perform_channel_equalization_sequence(link, +					link_res,  					lt_settings,  					DPRX);  		} @@ -2401,6 +2412,7 @@ static enum link_training_result dp_perform_8b_10b_link_training(  #if defined(CONFIG_DRM_AMD_DC_DCN)  static enum link_training_result dp_perform_128b_132b_link_training(  		struct dc_link *link, +		const struct link_resource *link_res,  		struct link_training_settings *lt_settings)  {  	enum link_training_result result = LINK_TRAINING_SUCCESS; @@ -2412,23 +2424,358 @@ static enum link_training_result dp_perform_128b_132b_link_training(  		decide_8b_10b_training_settings(link,  				<_settings->link_settings,  				&legacy_settings); -		return dp_perform_8b_10b_link_training(link, &legacy_settings); +		return dp_perform_8b_10b_link_training(link, link_res, &legacy_settings);  	}  	dpcd_set_link_settings(link, lt_settings);  	if (result == LINK_TRAINING_SUCCESS) -		result = dp_perform_128b_132b_channel_eq_done_sequence(link, lt_settings); +		result = dp_perform_128b_132b_channel_eq_done_sequence(link, link_res, lt_settings);  	if (result == LINK_TRAINING_SUCCESS) -		result = dp_perform_128b_132b_cds_done_sequence(link, lt_settings); +		result = dp_perform_128b_132b_cds_done_sequence(link, link_res, lt_settings);  	return result;  }  #endif +static enum link_training_result dc_link_dp_perform_fixed_vs_pe_training_sequence( +	struct dc_link *link, +	const struct link_resource *link_res, +	struct link_training_settings *lt_settings) +{ +	const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF}; +	const uint8_t offset = dp_convert_to_count( +			link->dpcd_caps.lttpr_caps.phy_repeater_cnt); +	const uint8_t vendor_lttpr_write_data_intercept_en[4] = {0x1, 0x55, 0x63, 0x0}; +	const uint8_t vendor_lttpr_write_data_intercept_dis[4] = {0x1, 0x55, 0x63, 0x68}; +	uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0}; +	uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0}; +	uint32_t vendor_lttpr_write_address = 0xF004F; +	enum link_training_result status = LINK_TRAINING_SUCCESS; +	uint8_t lane = 0; +	union down_spread_ctrl downspread = {0}; +	union lane_count_set lane_count_set = {0}; +	uint8_t toggle_rate; +	uint8_t rate; + +	/* Only 8b/10b is supported */ +	ASSERT(dp_get_link_encoding_format(<_settings->link_settings) == +			DP_8b_10b_ENCODING); + +	if (offset != 0xFF) { +		vendor_lttpr_write_address += +				((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE) * (offset - 1)); +	} + +	/* Vendor specific: Reset lane settings */ +	core_link_write_dpcd( +			link, +			vendor_lttpr_write_address, +			&vendor_lttpr_write_data_reset[0], +			sizeof(vendor_lttpr_write_data_reset)); +	core_link_write_dpcd( +			link, +			vendor_lttpr_write_address, +			&vendor_lttpr_write_data_vs[0], +			sizeof(vendor_lttpr_write_data_vs)); +	core_link_write_dpcd( +			link, +			vendor_lttpr_write_address, +			&vendor_lttpr_write_data_pe[0], +			sizeof(vendor_lttpr_write_data_pe)); + +	/* Vendor specific: Enable intercept */ +	core_link_write_dpcd( +			link, +			vendor_lttpr_write_address, +			&vendor_lttpr_write_data_intercept_en[0], +			sizeof(vendor_lttpr_write_data_intercept_en)); + +	/* 1. set link rate, lane count and spread. */ + +	downspread.raw = (uint8_t)(lt_settings->link_settings.link_spread); + +	lane_count_set.bits.LANE_COUNT_SET = +	lt_settings->link_settings.lane_count; + +	lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing; +	lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0; + + +	if (lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) { +		lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = +				link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED; +	} + +	core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL, +		&downspread.raw, sizeof(downspread)); + +	core_link_write_dpcd(link, DP_LANE_COUNT_SET, +		&lane_count_set.raw, 1); + +#if defined(CONFIG_DRM_AMD_DC_DCN) +	rate = get_dpcd_link_rate(<_settings->link_settings); +#else +	rate = (uint8_t) (lt_settings->link_settings.link_rate); +#endif + +	/* Vendor specific: Toggle link rate */ +	toggle_rate = (rate == 0x6) ? 0xA : 0x6; + +	if (link->vendor_specific_lttpr_link_rate_wa == rate) { +		core_link_write_dpcd( +				link, +				DP_LINK_BW_SET, +				&toggle_rate, +				1); +	} + +	link->vendor_specific_lttpr_link_rate_wa = rate; + +	core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1); + +	DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n", +		__func__, +		DP_LINK_BW_SET, +		lt_settings->link_settings.link_rate, +		DP_LANE_COUNT_SET, +		lt_settings->link_settings.lane_count, +		lt_settings->enhanced_framing, +		DP_DOWNSPREAD_CTRL, +		lt_settings->link_settings.link_spread); + +	/* 2. Perform link training */ + +	/* Perform Clock Recovery Sequence */ +	if (status == LINK_TRAINING_SUCCESS) { +		uint32_t retries_cr; +		uint32_t retry_count; +		uint32_t wait_time_microsec; +		enum dc_lane_count lane_count = lt_settings->link_settings.lane_count; +		union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX]; +		union lane_align_status_updated dpcd_lane_status_updated; +		union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0}; + +		retries_cr = 0; +		retry_count = 0; + +		while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) && +			(retry_count < LINK_TRAINING_MAX_CR_RETRY)) { + +			memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status)); +			memset(&dpcd_lane_status_updated, '\0', +			sizeof(dpcd_lane_status_updated)); + +			/* 1. call HWSS to set lane settings */ +			dp_set_hw_lane_settings( +					link, +					link_res, +					lt_settings, +					0); + +			/* 2. update DPCD of the receiver */ +			if (!retry_count) { +				/* EPR #361076 - write as a 5-byte burst, +				 * but only for the 1-st iteration. +				 */ +				dpcd_set_lt_pattern_and_lane_settings( +						link, +						lt_settings, +						lt_settings->pattern_for_cr, +						0); +				/* Vendor specific: Disable intercept */ +				core_link_write_dpcd( +						link, +						vendor_lttpr_write_address, +						&vendor_lttpr_write_data_intercept_dis[0], +						sizeof(vendor_lttpr_write_data_intercept_dis)); +			} else { +				vendor_lttpr_write_data_vs[3] = 0; +				vendor_lttpr_write_data_pe[3] = 0; + +				for (lane = 0; lane < lane_count; lane++) { +					vendor_lttpr_write_data_vs[3] |= +							lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane); +					vendor_lttpr_write_data_pe[3] |= +							lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane); +				} + +				/* Vendor specific: Update VS and PE to DPRX requested value */ +				core_link_write_dpcd( +						link, +						vendor_lttpr_write_address, +						&vendor_lttpr_write_data_vs[0], +						sizeof(vendor_lttpr_write_data_vs)); +				core_link_write_dpcd( +						link, +						vendor_lttpr_write_address, +						&vendor_lttpr_write_data_pe[0], +						sizeof(vendor_lttpr_write_data_pe)); + +				dpcd_set_lane_settings( +						link, +						lt_settings, +						0); +			} + +			/* 3. wait receiver to lock-on*/ +			wait_time_microsec = lt_settings->cr_pattern_time; + +			dp_wait_for_training_aux_rd_interval( +					link, +					wait_time_microsec); + +			/* 4. Read lane status and requested drive +			 * settings as set by the sink +			 */ +			dp_get_lane_status_and_lane_adjust( +					link, +					lt_settings, +					dpcd_lane_status, +					&dpcd_lane_status_updated, +					dpcd_lane_adjust, +					0); + +			/* 5. check CR done*/ +			if (dp_is_cr_done(lane_count, dpcd_lane_status)) { +				status = LINK_TRAINING_SUCCESS; +				break; +			} + +			/* 6. max VS reached*/ +			if (dp_is_max_vs_reached(lt_settings)) +				break; + +			/* 7. same lane settings */ +			/* Note: settings are the same for all lanes, +			 * so comparing first lane is sufficient +			 */ +			if (lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET == +					dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE) +				retries_cr++; +			else +				retries_cr = 0; + +			/* 8. update VS/PE/PC2 in lt_settings*/ +			dp_decide_lane_settings(lt_settings, dpcd_lane_adjust, +					lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); +			retry_count++; +		} + +		if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) { +			ASSERT(0); +			DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue", +				__func__, +				LINK_TRAINING_MAX_CR_RETRY); + +		} + +		status = dp_get_cr_failure(lane_count, dpcd_lane_status); +	} + +	/* Perform Channel EQ Sequence */ +	if (status == LINK_TRAINING_SUCCESS) { +		enum dc_dp_training_pattern tr_pattern; +		uint32_t retries_ch_eq; +		uint32_t wait_time_microsec; +		enum dc_lane_count lane_count = lt_settings->link_settings.lane_count; +		union lane_align_status_updated dpcd_lane_status_updated = {0}; +		union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0}; +		union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0}; + +		/* Note: also check that TPS4 is a supported feature*/ +		tr_pattern = lt_settings->pattern_for_eq; + +		dp_set_hw_training_pattern(link, link_res, tr_pattern, 0); + +		status = LINK_TRAINING_EQ_FAIL_EQ; + +		for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT; +			retries_ch_eq++) { + +			dp_set_hw_lane_settings(link, link_res, lt_settings, 0); + +			vendor_lttpr_write_data_vs[3] = 0; +			vendor_lttpr_write_data_pe[3] = 0; + +			for (lane = 0; lane < lane_count; lane++) { +				vendor_lttpr_write_data_vs[3] |= +						lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane); +				vendor_lttpr_write_data_pe[3] |= +						lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane); +			} + +			/* Vendor specific: Update VS and PE to DPRX requested value */ +			core_link_write_dpcd( +					link, +					vendor_lttpr_write_address, +					&vendor_lttpr_write_data_vs[0], +					sizeof(vendor_lttpr_write_data_vs)); +			core_link_write_dpcd( +					link, +					vendor_lttpr_write_address, +					&vendor_lttpr_write_data_pe[0], +					sizeof(vendor_lttpr_write_data_pe)); + +			/* 2. update DPCD*/ +			if (!retries_ch_eq) +				/* EPR #361076 - write as a 5-byte burst, +				 * but only for the 1-st iteration +				 */ + +				dpcd_set_lt_pattern_and_lane_settings( +					link, +					lt_settings, +					tr_pattern, 0); +			else +				dpcd_set_lane_settings(link, lt_settings, 0); + +			/* 3. wait for receiver to lock-on*/ +			wait_time_microsec = lt_settings->eq_pattern_time; + +			dp_wait_for_training_aux_rd_interval( +					link, +					wait_time_microsec); + +			/* 4. Read lane status and requested +			 * drive settings as set by the sink +			 */ +			dp_get_lane_status_and_lane_adjust( +				link, +				lt_settings, +				dpcd_lane_status, +				&dpcd_lane_status_updated, +				dpcd_lane_adjust, +				0); + +			/* 5. check CR done*/ +			if (!dp_is_cr_done(lane_count, dpcd_lane_status)) { +				status = LINK_TRAINING_EQ_FAIL_CR; +				break; +			} + +			/* 6. check CHEQ done*/ +			if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) && +					dp_is_symbol_locked(lane_count, dpcd_lane_status) && +					dp_is_interlane_aligned(dpcd_lane_status_updated)) { +				status = LINK_TRAINING_SUCCESS; +				break; +			} + +			/* 7. update VS/PE/PC2 in lt_settings*/ +			dp_decide_lane_settings(lt_settings, dpcd_lane_adjust, +					lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings); +		} +	} + +	return status; +} + +  enum link_training_result dc_link_dp_perform_link_training(  	struct dc_link *link, +	const struct link_resource *link_res,  	const struct dc_link_settings *link_settings,  	bool skip_video_pattern)  { @@ -2459,18 +2806,22 @@ enum link_training_result dc_link_dp_perform_link_training(  	/* configure link prior to entering training mode */  	dpcd_configure_lttpr_mode(link, <_settings); -	dp_set_fec_ready(link, lt_settings.should_set_fec_ready); +	dp_set_fec_ready(link, link_res, lt_settings.should_set_fec_ready);  	dpcd_configure_channel_coding(link, <_settings);  	/* enter training mode:  	 * Per DP specs starting from here, DPTX device shall not issue  	 * Non-LT AUX transactions inside training mode.  	 */ -	if (encoding == DP_8b_10b_ENCODING) -		status = dp_perform_8b_10b_link_training(link, <_settings); +	if (!link->dc->debug.apply_vendor_specific_lttpr_wa && +			(link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && +			link->lttpr_mode == LTTPR_MODE_TRANSPARENT) +		status = dc_link_dp_perform_fixed_vs_pe_training_sequence(link, link_res, <_settings); +	else if (encoding == DP_8b_10b_ENCODING) +		status = dp_perform_8b_10b_link_training(link, link_res, <_settings);  #if defined(CONFIG_DRM_AMD_DC_DCN)  	else if (encoding == DP_128b_132b_ENCODING) -		status = dp_perform_128b_132b_link_training(link, <_settings); +		status = dp_perform_128b_132b_link_training(link, link_res, <_settings);  #endif  	else  		ASSERT(0); @@ -2488,6 +2839,7 @@ enum link_training_result dc_link_dp_perform_link_training(  	/* switch to video idle */  	if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern)  		status = dp_transition_to_video_idle(link, +				link_res,  				<_settings,  				status); @@ -2539,6 +2891,7 @@ bool perform_link_training_with_retries(  		dp_enable_link_phy(  			link, +			&pipe_ctx->link_res,  			signal,  			pipe_ctx->clock_source->id,  			¤t_setting); @@ -2566,23 +2919,24 @@ bool perform_link_training_with_retries(  		dp_set_panel_mode(link, panel_mode);  		if (link->aux_access_disabled) { -			dc_link_dp_perform_link_training_skip_aux(link, ¤t_setting); +			dc_link_dp_perform_link_training_skip_aux(link, &pipe_ctx->link_res, ¤t_setting);  			return true;  		} else {  			/** @todo Consolidate USB4 DP and DPx.x training. */  			if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {  				status = dc_link_dpia_perform_link_training(link, -									    ¤t_setting, -									    skip_video_pattern); +						&pipe_ctx->link_res, +						¤t_setting, +						skip_video_pattern);  				/* Transmit idle pattern once training successful. */  				if (status == LINK_TRAINING_SUCCESS) -					dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, -							       NULL, 0); +					dp_set_hw_test_pattern(link, &pipe_ctx->link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);  			} else {  				status = dc_link_dp_perform_link_training(link, -									  ¤t_setting, -									  skip_video_pattern); +						&pipe_ctx->link_res, +						¤t_setting, +						skip_video_pattern);  			}  			if (status == LINK_TRAINING_SUCCESS) @@ -2597,7 +2951,7 @@ bool perform_link_training_with_retries(  		DC_LOG_WARNING("%s: Link training attempt %u of %d failed\n",  			__func__, (unsigned int)j + 1, attempts); -		dp_disable_link_phy(link, signal); +		dp_disable_link_phy(link, &pipe_ctx->link_res, signal);  		/* Abort link training if failure due to sink being unplugged. */  		if (status == LINK_TRAINING_ABORT) { @@ -2646,12 +3000,13 @@ static enum clock_source_id get_clock_source_id(struct dc_link *link)  	return dp_cs_id;  } -static void set_dp_mst_mode(struct dc_link *link, bool mst_enable) +static void set_dp_mst_mode(struct dc_link *link, const struct link_resource *link_res, +		bool mst_enable)  {  	if (mst_enable == false &&  		link->type == dc_connection_mst_branch) {  		/* Disable MST on link. Use only local sink. */ -		dp_disable_link_phy_mst(link, link->connector_signal); +		dp_disable_link_phy_mst(link, link_res, link->connector_signal);  		link->type = dc_connection_single;  		link->local_sink = link->remote_sinks[0]; @@ -2662,7 +3017,7 @@ static void set_dp_mst_mode(struct dc_link *link, bool mst_enable)  			link->type == dc_connection_single &&  			link->remote_sinks[0] != NULL) {  		/* Re-enable MST on link. */ -		dp_disable_link_phy(link, link->connector_signal); +		dp_disable_link_phy(link, link_res, link->connector_signal);  		dp_enable_mst_on_sink(link, true);  		link->type = dc_connection_mst_branch; @@ -2688,6 +3043,7 @@ bool dc_link_dp_sync_lt_begin(struct dc_link *link)  enum link_training_result dc_link_dp_sync_lt_attempt(      struct dc_link *link, +    const struct link_resource *link_res,      struct dc_link_settings *link_settings,      struct dc_link_training_overrides *lt_overrides)  { @@ -2707,14 +3063,14 @@ enum link_training_result dc_link_dp_sync_lt_attempt(  			<_settings);  	/* Setup MST Mode */  	if (lt_overrides->mst_enable) -		set_dp_mst_mode(link, *lt_overrides->mst_enable); +		set_dp_mst_mode(link, link_res, *lt_overrides->mst_enable);  	/* Disable link */ -	dp_disable_link_phy(link, link->connector_signal); +	dp_disable_link_phy(link, link_res, link->connector_signal);  	/* Enable link */  	dp_cs_id = get_clock_source_id(link); -	dp_enable_link_phy(link, link->connector_signal, +	dp_enable_link_phy(link, link_res, link->connector_signal,  		dp_cs_id, link_settings);  	/* Set FEC enable */ @@ -2722,7 +3078,7 @@ enum link_training_result dc_link_dp_sync_lt_attempt(  	if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {  #endif  		fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable; -		dp_set_fec_ready(link, fec_enable); +		dp_set_fec_ready(link, NULL, fec_enable);  #if defined(CONFIG_DRM_AMD_DC_DCN)  	}  #endif @@ -2739,7 +3095,7 @@ enum link_training_result dc_link_dp_sync_lt_attempt(  	/* Attempt to train with given link training settings */  	if (link->ctx->dc->work_arounds.lt_early_cr_pattern) -		start_clock_recovery_pattern_early(link, <_settings, DPRX); +		start_clock_recovery_pattern_early(link, link_res, <_settings, DPRX);  	/* Set link rate, lane count and spread. */  	dpcd_set_link_settings(link, <_settings); @@ -2747,9 +3103,10 @@ enum link_training_result dc_link_dp_sync_lt_attempt(  	/* 2. perform link training (set link training done  	 *  to false is done as well)  	 */ -	lt_status = perform_clock_recovery_sequence(link, <_settings, DPRX); +	lt_status = perform_clock_recovery_sequence(link, link_res, <_settings, DPRX);  	if (lt_status == LINK_TRAINING_SUCCESS) {  		lt_status = perform_channel_equalization_sequence(link, +						link_res,  						<_settings,  						DPRX);  	} @@ -2770,11 +3127,11 @@ bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down)  #if defined(CONFIG_DRM_AMD_DC_DCN)  		struct dc_link_settings link_settings = link->cur_link_settings;  #endif -		dp_disable_link_phy(link, link->connector_signal); +		dp_disable_link_phy(link, NULL, link->connector_signal);  #if defined(CONFIG_DRM_AMD_DC_DCN)  		if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING)  #endif -			dp_set_fec_ready(link, false); +			dp_set_fec_ready(link, NULL, false);  	}  	link->sync_lt_in_progress = false; @@ -2829,7 +3186,8 @@ bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_  	return false;  } -static struct dc_link_settings get_max_link_cap(struct dc_link *link) +static struct dc_link_settings get_max_link_cap(struct dc_link *link, +		const struct link_resource *link_res)  {  	struct dc_link_settings max_link_cap = {0};  #if defined(CONFIG_DRM_AMD_DC_DCN) @@ -2853,9 +3211,11 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link)  	if (link_enc)  		link_enc->funcs->get_max_link_cap(link_enc, &max_link_cap);  #if defined(CONFIG_DRM_AMD_DC_DCN) -	if (max_link_cap.link_rate >= LINK_RATE_UHBR10 && -			!link->hpo_dp_link_enc) -		max_link_cap.link_rate = LINK_RATE_HIGH3; +	if (max_link_cap.link_rate >= LINK_RATE_UHBR10) { +		if (!link_res->hpo_dp_link_enc || +				link->dc->debug.disable_uhbr) +			max_link_cap.link_rate = LINK_RATE_HIGH3; +	}  #endif  	/* Lower link settings based on sink's link cap */ @@ -2873,7 +3233,7 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link)  	 * account for lttpr repeaters cap  	 * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3).  	 */ -	if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) { +	if (link->lttpr_mode != LTTPR_MODE_NON_LTTPR) {  		if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count)  			max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count; @@ -3012,6 +3372,7 @@ bool hpd_rx_irq_check_link_loss_status(  bool dp_verify_link_cap(  	struct dc_link *link, +	const struct link_resource *link_res,  	struct dc_link_settings *known_limit_link_setting,  	int *fail_count)  { @@ -3029,7 +3390,7 @@ bool dp_verify_link_cap(  	/* link training starts with the maximum common settings  	 * supported by both sink and ASIC.  	 */ -	max_link_cap = get_max_link_cap(link); +	max_link_cap = get_max_link_cap(link, link_res);  	initial_link_settings = get_common_supported_link_settings(  			*known_limit_link_setting,  			max_link_cap); @@ -3069,7 +3430,7 @@ bool dp_verify_link_cap(  	 * find the physical link capability  	 */  	/* disable PHY done possible by BIOS, will be done by driver itself */ -	dp_disable_link_phy(link, link->connector_signal); +	dp_disable_link_phy(link, link_res, link->connector_signal);  	dp_cs_id = get_clock_source_id(link); @@ -3081,8 +3442,8 @@ bool dp_verify_link_cap(  	 */  	if (link->link_enc && link->link_enc->features.flags.bits.DP_IS_USB_C &&  			link->dc->debug.usbc_combo_phy_reset_wa) { -		dp_enable_link_phy(link, link->connector_signal, dp_cs_id, cur); -		dp_disable_link_phy(link, link->connector_signal); +		dp_enable_link_phy(link, link_res, link->connector_signal, dp_cs_id, cur); +		dp_disable_link_phy(link, link_res, link->connector_signal);  	}  	do { @@ -3093,6 +3454,7 @@ bool dp_verify_link_cap(  		dp_enable_link_phy(  				link, +				link_res,  				link->connector_signal,  				dp_cs_id,  				cur); @@ -3103,6 +3465,7 @@ bool dp_verify_link_cap(  		else {  			status = dc_link_dp_perform_link_training(  							link, +							link_res,  							cur,  							skip_video_pattern);  			if (status == LINK_TRAINING_SUCCESS) @@ -3124,7 +3487,7 @@ bool dp_verify_link_cap(  		 * setting or before returning we'll enable it later  		 * based on the actual mode we're driving  		 */ -		dp_disable_link_phy(link, link->connector_signal); +		dp_disable_link_phy(link, link_res, link->connector_signal);  	} while (!success && decide_fallback_link_setting(link,  			initial_link_settings, cur, status)); @@ -3148,6 +3511,7 @@ bool dp_verify_link_cap(  bool dp_verify_link_cap_with_retries(  	struct dc_link *link, +	const struct link_resource *link_res,  	struct dc_link_settings *known_limit_link_setting,  	int attempts)  { @@ -3165,7 +3529,7 @@ bool dp_verify_link_cap_with_retries(  			link->verified_link_cap.link_rate = LINK_RATE_LOW;  			link->verified_link_cap.link_spread = LINK_SPREAD_DISABLED;  			break; -		} else if (dp_verify_link_cap(link, +		} else if (dp_verify_link_cap(link, link_res,  				known_limit_link_setting,  				&fail_count) && fail_count == 0) {  			success = true; @@ -3177,13 +3541,13 @@ bool dp_verify_link_cap_with_retries(  }  bool dp_verify_mst_link_cap( -	struct dc_link *link) +	struct dc_link *link, const struct link_resource *link_res)  {  	struct dc_link_settings max_link_cap = {0};  	if (dp_get_link_encoding_format(&link->reported_link_cap) ==  			DP_8b_10b_ENCODING) { -		max_link_cap = get_max_link_cap(link); +		max_link_cap = get_max_link_cap(link, link_res);  		link->verified_link_cap = get_common_supported_link_settings(  				link->reported_link_cap,  				max_link_cap); @@ -3192,6 +3556,7 @@ bool dp_verify_mst_link_cap(  	else if (dp_get_link_encoding_format(&link->reported_link_cap) ==  			DP_128b_132b_ENCODING) {  		dp_verify_link_cap_with_retries(link, +				link_res,  				&link->reported_link_cap,  				LINK_TRAINING_MAX_VERIFY_RETRY);  	} @@ -5720,7 +6085,7 @@ bool dc_link_dp_set_test_pattern(  			DP_TEST_PATTERN_VIDEO_MODE) {  		/* Set CRTC Test Pattern */  		set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space); -		dp_set_hw_test_pattern(link, test_pattern, +		dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,  				(uint8_t *)p_custom_pattern,  				(uint32_t)cust_pattern_size); @@ -5751,7 +6116,7 @@ bool dc_link_dp_set_test_pattern(  						p_link_settings->dpcd_lane_settings,  						p_link_settings->link_settings.lane_count);  			} else { -				dp_set_hw_lane_settings(link, p_link_settings, DPRX); +				dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX);  				dpcd_set_lane_settings(link, p_link_settings, DPRX);  			}  		} @@ -5766,7 +6131,7 @@ bool dc_link_dp_set_test_pattern(  			pipes->stream_res.stream_enc->funcs->dp_blank(link, pipe_ctx->stream_res.stream_enc);  		} -		dp_set_hw_test_pattern(link, test_pattern, +		dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,  				(uint8_t *)p_custom_pattern,  				(uint32_t)cust_pattern_size); @@ -6086,7 +6451,7 @@ enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)  	return DP_PANEL_MODE_DEFAULT;  } -enum dc_status dp_set_fec_ready(struct dc_link *link, bool ready) +enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready)  {  	/* FEC has to be "set ready" before the link training.  	 * The policy is to always train with FEC @@ -6653,8 +7018,10 @@ struct fixed31_32 calculate_sst_avg_time_slots_per_mtp(  bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx)  { +	/* If this assert is hit then we have a link encoder dynamic management issue */ +	ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true);  	return (pipe_ctx->stream_res.hpo_dp_stream_enc && -			pipe_ctx->stream->link->hpo_dp_link_enc && +			pipe_ctx->link_res.hpo_dp_link_enc &&  			dc_is_dp_signal(pipe_ctx->stream->signal));  }  #endif diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c index d72122593959..0e95bc5df4e7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c @@ -77,7 +77,9 @@ enum dc_status dpcd_get_tunneling_device_data(struct dc_link *link)   * @param[in] link_setting Lane count, link rate and downspread control.   * @param[out] lt_settings Link settings and drive settings (voltage swing and pre-emphasis).   */ -static enum link_training_result dpia_configure_link(struct dc_link *link, +static enum link_training_result dpia_configure_link( +		struct dc_link *link, +		const struct link_resource *link_res,  		const struct dc_link_settings *link_setting,  		struct link_training_settings *lt_settings)  { @@ -111,7 +113,7 @@ static enum link_training_result dpia_configure_link(struct dc_link *link,  		fec_enable = *link->preferred_training_settings.fec_enable;  	else  		fec_enable = true; -	status = dp_set_fec_ready(link, fec_enable); +	status = dp_set_fec_ready(link, link_res, fec_enable);  	if (status != DC_OK && link->is_hpd_pending)  		return LINK_TRAINING_ABORT; @@ -252,7 +254,9 @@ static enum dc_status dpcd_set_lt_pattern(struct dc_link *link,   * @param lt_settings link_setting and drive settings (voltage swing and pre-emphasis).   * @param hop The Hop in display path. DPRX = 0.   */ -static enum link_training_result dpia_training_cr_non_transparent(struct dc_link *link, +static enum link_training_result dpia_training_cr_non_transparent( +		struct dc_link *link, +		const struct link_resource *link_res,  		struct link_training_settings *lt_settings,  		uint32_t hop)  { @@ -411,7 +415,9 @@ static enum link_training_result dpia_training_cr_non_transparent(struct dc_link   * @param link DPIA link being trained.   * @param lt_settings link_setting and drive settings (voltage swing and pre-emphasis).   */ -static enum link_training_result dpia_training_cr_transparent(struct dc_link *link, +static enum link_training_result dpia_training_cr_transparent( +		struct dc_link *link, +		const struct link_resource *link_res,  		struct link_training_settings *lt_settings)  {  	enum link_training_result result = LINK_TRAINING_CR_FAIL_LANE0; @@ -511,16 +517,18 @@ static enum link_training_result dpia_training_cr_transparent(struct dc_link *li   * @param lt_settings link_setting and drive settings (voltage swing and pre-emphasis).   * @param hop The Hop in display path. DPRX = 0.   */ -static enum link_training_result dpia_training_cr_phase(struct dc_link *link, +static enum link_training_result dpia_training_cr_phase( +		struct dc_link *link, +		const struct link_resource *link_res,  		struct link_training_settings *lt_settings,  		uint32_t hop)  {  	enum link_training_result result = LINK_TRAINING_CR_FAIL_LANE0;  	if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) -		result = dpia_training_cr_non_transparent(link, lt_settings, hop); +		result = dpia_training_cr_non_transparent(link, link_res, lt_settings, hop);  	else -		result = dpia_training_cr_transparent(link, lt_settings); +		result = dpia_training_cr_transparent(link, link_res, lt_settings);  	return result;  } @@ -561,7 +569,9 @@ static uint32_t dpia_get_eq_aux_rd_interval(const struct dc_link *link,   * @param lt_settings link_setting and drive settings (voltage swing and pre-emphasis).   * @param hop The Hop in display path. DPRX = 0.   */ -static enum link_training_result dpia_training_eq_non_transparent(struct dc_link *link, +static enum link_training_result dpia_training_eq_non_transparent( +		struct dc_link *link, +		const struct link_resource *link_res,  		struct link_training_settings *lt_settings,  		uint32_t hop)  { @@ -700,7 +710,9 @@ static enum link_training_result dpia_training_eq_non_transparent(struct dc_link   * @param lt_settings link_setting and drive settings (voltage swing and pre-emphasis).   * @param hop The Hop in display path. DPRX = 0.   */ -static enum link_training_result dpia_training_eq_transparent(struct dc_link *link, +static enum link_training_result dpia_training_eq_transparent( +		struct dc_link *link, +		const struct link_resource *link_res,  		struct link_training_settings *lt_settings)  {  	enum link_training_result result = LINK_TRAINING_EQ_FAIL_EQ; @@ -779,16 +791,18 @@ static enum link_training_result dpia_training_eq_transparent(struct dc_link *li   * @param lt_settings link_setting and drive settings (voltage swing and pre-emphasis).   * @param hop The Hop in display path. DPRX = 0.   */ -static enum link_training_result dpia_training_eq_phase(struct dc_link *link, +static enum link_training_result dpia_training_eq_phase( +		struct dc_link *link, +		const struct link_resource *link_res,  		struct link_training_settings *lt_settings,  		uint32_t hop)  {  	enum link_training_result result;  	if (link->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) -		result = dpia_training_eq_non_transparent(link, lt_settings, hop); +		result = dpia_training_eq_non_transparent(link, link_res, lt_settings, hop);  	else -		result = dpia_training_eq_transparent(link, lt_settings); +		result = dpia_training_eq_transparent(link, link_res, lt_settings);  	return result;  } @@ -908,7 +922,9 @@ static void dpia_training_abort(struct dc_link *link, uint32_t hop)  	core_link_send_set_config(link, DPIA_SET_CFG_SET_LINK, data);  } -enum link_training_result dc_link_dpia_perform_link_training(struct dc_link *link, +enum link_training_result dc_link_dpia_perform_link_training( +	struct dc_link *link, +	const struct link_resource *link_res,  	const struct dc_link_settings *link_setting,  	bool skip_video_pattern)  { @@ -918,7 +934,7 @@ enum link_training_result dc_link_dpia_perform_link_training(struct dc_link *lin  	int8_t repeater_id; /* Current hop. */  	/* Configure link as prescribed in link_setting and set LTTPR mode. */ -	result = dpia_configure_link(link, link_setting, <_settings); +	result = dpia_configure_link(link, link_res, link_setting, <_settings);  	if (result != LINK_TRAINING_SUCCESS)  		return result; @@ -930,12 +946,12 @@ enum link_training_result dc_link_dpia_perform_link_training(struct dc_link *lin  	 */  	for (repeater_id = repeater_cnt; repeater_id >= 0; repeater_id--) {  		/* Clock recovery. */ -		result = dpia_training_cr_phase(link, <_settings, repeater_id); +		result = dpia_training_cr_phase(link, link_res, <_settings, repeater_id);  		if (result != LINK_TRAINING_SUCCESS)  			break;  		/* Equalization. */ -		result = dpia_training_eq_phase(link, <_settings, repeater_id); +		result = dpia_training_eq_phase(link, link_res, <_settings, repeater_id);  		if (result != LINK_TRAINING_SUCCESS)  			break; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 368e834c6809..45d03d3a95c3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -71,6 +71,7 @@ void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode)  void dp_enable_link_phy(  	struct dc_link *link, +	const struct link_resource *link_res,  	enum signal_type signal,  	enum clock_source_id clock_source,  	const struct dc_link_settings *link_settings) @@ -135,7 +136,7 @@ void dp_enable_link_phy(  #if defined(CONFIG_DRM_AMD_DC_DCN)  	if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) { -		enable_dp_hpo_output(link, link_settings); +		enable_dp_hpo_output(link, link_res, link_settings);  	} else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {  		if (dc_is_dp_sst_signal(signal)) {  			link_enc->funcs->enable_dp_output( @@ -236,12 +237,13 @@ bool edp_receiver_ready_T7(struct dc_link *link)  	return result;  } -void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) +void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_res, +		enum signal_type signal)  {  	struct dc  *dc = link->ctx->dc;  	struct dmcu *dmcu = dc->res_pool->dmcu;  #if defined(CONFIG_DRM_AMD_DC_DCN) -	struct hpo_dp_link_encoder *hpo_link_enc = link->hpo_dp_link_enc; +	struct hpo_dp_link_encoder *hpo_link_enc = link_res->hpo_dp_link_enc;  #endif  	struct link_encoder *link_enc; @@ -260,7 +262,7 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)  			link->dc->hwss.edp_backlight_control(link, false);  #if defined(CONFIG_DRM_AMD_DC_DCN)  		if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING) -			disable_dp_hpo_output(link, signal); +			disable_dp_hpo_output(link, link_res, signal);  		else  			link_enc->funcs->disable_output(link_enc, signal);  #else @@ -274,7 +276,7 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)  #if defined(CONFIG_DRM_AMD_DC_DCN)  		if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING &&  				hpo_link_enc) -			disable_dp_hpo_output(link, signal); +			disable_dp_hpo_output(link, link_res, signal);  		else  			link_enc->funcs->disable_output(link_enc, signal);  #else @@ -294,13 +296,14 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)  		dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link);  } -void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal) +void dp_disable_link_phy_mst(struct dc_link *link, const struct link_resource *link_res, +		enum signal_type signal)  {  	/* MST disable link only when no stream use the link */  	if (link->mst_stream_alloc_table.stream_count > 0)  		return; -	dp_disable_link_phy(link, signal); +	dp_disable_link_phy(link, link_res, signal);  	/* set the sink to SST mode after disabling the link */  	dp_enable_mst_on_sink(link, false); @@ -308,6 +311,7 @@ void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal)  bool dp_set_hw_training_pattern(  	struct dc_link *link, +	const struct link_resource *link_res,  	enum dc_dp_training_pattern pattern,  	uint32_t offset)  { @@ -338,7 +342,7 @@ bool dp_set_hw_training_pattern(  		break;  	} -	dp_set_hw_test_pattern(link, test_pattern, NULL, 0); +	dp_set_hw_test_pattern(link, link_res, test_pattern, NULL, 0);  	return true;  } @@ -349,6 +353,7 @@ bool dp_set_hw_training_pattern(  #endif  void dp_set_hw_lane_settings(  	struct dc_link *link, +	const struct link_resource *link_res,  	const struct link_training_settings *link_settings,  	uint32_t offset)  { @@ -361,8 +366,8 @@ void dp_set_hw_lane_settings(  #if defined(CONFIG_DRM_AMD_DC_DCN)  	if (dp_get_link_encoding_format(&link_settings->link_settings) ==  			DP_128b_132b_ENCODING) { -		link->hpo_dp_link_enc->funcs->set_ffe( -				link->hpo_dp_link_enc, +		link_res->hpo_dp_link_enc->funcs->set_ffe( +				link_res->hpo_dp_link_enc,  				&link_settings->link_settings,  				link_settings->lane_settings[0].FFE_PRESET.raw);  	} else if (dp_get_link_encoding_format(&link_settings->link_settings) @@ -379,6 +384,7 @@ void dp_set_hw_lane_settings(  void dp_set_hw_test_pattern(  	struct dc_link *link, +	const struct link_resource *link_res,  	enum dp_test_pattern test_pattern,  	uint8_t *custom_pattern,  	uint32_t custom_pattern_size) @@ -406,8 +412,8 @@ void dp_set_hw_test_pattern(  #if defined(CONFIG_DRM_AMD_DC_DCN)  	switch (link_encoding_format) {  	case DP_128b_132b_ENCODING: -		link->hpo_dp_link_enc->funcs->set_link_test_pattern( -				link->hpo_dp_link_enc, &pattern_param); +		link_res->hpo_dp_link_enc->funcs->set_link_test_pattern( +				link_res->hpo_dp_link_enc, &pattern_param);  		break;  	case DP_8b_10b_ENCODING:  		ASSERT(encoder); @@ -446,7 +452,7 @@ void dp_retrain_link_dp_test(struct dc_link *link,  					pipes[i].stream_res.stream_enc);  			/* disable any test pattern that might be active */ -			dp_set_hw_test_pattern(link, +			dp_set_hw_test_pattern(link, &pipes[i].link_res,  					DP_TEST_PATTERN_VIDEO_MODE, NULL, 0);  			dp_receiver_power_ctrl(link, false); @@ -763,7 +769,9 @@ static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link)  	}  } -void enable_dp_hpo_output(struct dc_link *link, const struct dc_link_settings *link_settings) +void enable_dp_hpo_output(struct dc_link *link, +		const struct link_resource *link_res, +		const struct dc_link_settings *link_settings)  {  	const struct dc *dc = link->dc;  	enum phyd32clk_clock_source phyd32clk; @@ -789,10 +797,11 @@ void enable_dp_hpo_output(struct dc_link *link, const struct dc_link_settings *l  		}  	} else {  		/* DP2.0 HW: call transmitter control to enable PHY */ -		link->hpo_dp_link_enc->funcs->enable_link_phy( -				link->hpo_dp_link_enc, +		link_res->hpo_dp_link_enc->funcs->enable_link_phy( +				link_res->hpo_dp_link_enc,  				link_settings, -				link->link_enc->transmitter); +				link->link_enc->transmitter, +				link->link_enc->hpd_source);  	}  	/* DCCG muxing and DTBCLK DTO */ @@ -806,24 +815,26 @@ void enable_dp_hpo_output(struct dc_link *link, const struct dc_link_settings *l  		phyd32clk = get_phyd32clk_src(link);  		dc->res_pool->dccg->funcs->enable_symclk32_le(  				dc->res_pool->dccg, -				link->hpo_dp_link_enc->inst, +				link_res->hpo_dp_link_enc->inst,  				phyd32clk); -		link->hpo_dp_link_enc->funcs->link_enable( -					link->hpo_dp_link_enc, -					link_settings->lane_count); +		link_res->hpo_dp_link_enc->funcs->link_enable( +				link_res->hpo_dp_link_enc, +				link_settings->lane_count);  	}  } -void disable_dp_hpo_output(struct dc_link *link, enum signal_type signal) +void disable_dp_hpo_output(struct dc_link *link, +		const struct link_resource *link_res, +		enum signal_type signal)  {  	const struct dc *dc = link->dc; -	link->hpo_dp_link_enc->funcs->link_disable(link->hpo_dp_link_enc); +	link_res->hpo_dp_link_enc->funcs->link_disable(link_res->hpo_dp_link_enc);  	if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {  		dc->res_pool->dccg->funcs->disable_symclk32_le(  					dc->res_pool->dccg, -					link->hpo_dp_link_enc->inst); +					link_res->hpo_dp_link_enc->inst);  		dc->res_pool->dccg->funcs->set_physymclk(  					dc->res_pool->dccg, @@ -834,8 +845,8 @@ void disable_dp_hpo_output(struct dc_link *link, enum signal_type signal)  		dm_set_phyd32clk(dc->ctx, 0);  	} else {  		/* DP2.0 HW: call transmitter control to disable PHY */ -		link->hpo_dp_link_enc->funcs->disable_link_phy( -				link->hpo_dp_link_enc, +		link_res->hpo_dp_link_enc->funcs->disable_link_phy( +				link_res->hpo_dp_link_enc,  				signal);  	}  } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 8b6b035bfa9c..eaeef72773f6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -734,10 +734,6 @@ static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *spli  			(*split_idx)++;  			split_pipe = split_pipe->top_pipe;  		} - -		/* MPO window on right side of ODM split */ -		if (split_pipe && split_pipe->prev_odm_pipe && !pipe_ctx->prev_odm_pipe) -			(*split_idx)++;  	} else {  		/*Get odm split index*/  		struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe; @@ -784,11 +780,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx)  	/*  	 * Only the leftmost ODM pipe should be offset by a nonzero distance  	 */ -	if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->prev_odm_pipe && !pipe_ctx->prev_odm_pipe) { -		/* MPO window on right side of ODM split */ -		data->recout.x = stream->dst.x + (surf_clip.x - stream->dst.width/2) * -				stream->dst.width / stream->src.width; -	} else if (!pipe_ctx->prev_odm_pipe || split_idx == split_count) { +	if (!pipe_ctx->prev_odm_pipe || split_idx == split_count) {  		data->recout.x = stream->dst.x;  		if (stream->src.x < surf_clip.x)  			data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width @@ -986,8 +978,6 @@ static void calculate_inits_and_viewports(struct pipe_ctx *pipe_ctx)  			* stream->dst.height / stream->src.height;  	if (pipe_ctx->prev_odm_pipe && split_idx)  		ro_lb = data->h_active * split_idx - recout_full_x; -	else if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->prev_odm_pipe) -		ro_lb = data->h_active * split_idx - recout_full_x + data->recout.x;  	else  		ro_lb = data->recout.x - recout_full_x;  	ro_tb = data->recout.y - recout_full_y; @@ -1086,9 +1076,6 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)  		timing->v_border_top + timing->v_border_bottom;  	if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe)  		pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1; -	/* ODM + windows MPO, where window is on either right or left ODM half */ -	else if (pipe_ctx->top_pipe && (pipe_ctx->top_pipe->next_odm_pipe || pipe_ctx->top_pipe->prev_odm_pipe)) -		pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx->top_pipe) + 1;  	/* depends on h_active */  	calculate_recout(pipe_ctx); @@ -1097,6 +1084,11 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)  	/* depends on scaling ratios and recout, does not calculate offset yet */  	calculate_viewport_size(pipe_ctx); +	/* Stopgap for validation of ODM + MPO on one side of screen case */ +	if (pipe_ctx->plane_res.scl_data.viewport.height < 1 || +			pipe_ctx->plane_res.scl_data.viewport.width < 1) +		return false; +  	/*  	 * LB calculations depend on vp size, h/v_active and scaling ratios  	 * Setting line buffer pixel depth to 24bpp yields banding @@ -1445,54 +1437,23 @@ bool dc_add_plane_to_context(  		if (head_pipe != free_pipe) {  			tail_pipe = resource_get_tail_pipe(&context->res_ctx, head_pipe);  			ASSERT(tail_pipe); - -			/* ODM + window MPO, where MPO window is on right half only */ -			if (free_pipe->plane_state && -					(free_pipe->plane_state->clip_rect.x >= free_pipe->stream->src.width/2) && -					tail_pipe->next_odm_pipe) { -				free_pipe->stream_res.tg = tail_pipe->next_odm_pipe->stream_res.tg; -				free_pipe->stream_res.abm = tail_pipe->next_odm_pipe->stream_res.abm; -				free_pipe->stream_res.opp = tail_pipe->next_odm_pipe->stream_res.opp; -				free_pipe->stream_res.stream_enc = tail_pipe->next_odm_pipe->stream_res.stream_enc; -				free_pipe->stream_res.audio = tail_pipe->next_odm_pipe->stream_res.audio; -				free_pipe->clock_source = tail_pipe->next_odm_pipe->clock_source; - -				free_pipe->top_pipe = tail_pipe->next_odm_pipe; -				tail_pipe->next_odm_pipe->bottom_pipe = free_pipe; -			} else { -				free_pipe->stream_res.tg = tail_pipe->stream_res.tg; -				free_pipe->stream_res.abm = tail_pipe->stream_res.abm; -				free_pipe->stream_res.opp = tail_pipe->stream_res.opp; -				free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; -				free_pipe->stream_res.audio = tail_pipe->stream_res.audio; -				free_pipe->clock_source = tail_pipe->clock_source; - -				free_pipe->top_pipe = tail_pipe; -				tail_pipe->bottom_pipe = free_pipe; - -				if (!free_pipe->next_odm_pipe && tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) { -					free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe; -					tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe; -				} -				if (!free_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) { -					free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe; -					tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe; -				} +			free_pipe->stream_res.tg = tail_pipe->stream_res.tg; +			free_pipe->stream_res.abm = tail_pipe->stream_res.abm; +			free_pipe->stream_res.opp = tail_pipe->stream_res.opp; +			free_pipe->stream_res.stream_enc = tail_pipe->stream_res.stream_enc; +			free_pipe->stream_res.audio = tail_pipe->stream_res.audio; +			free_pipe->clock_source = tail_pipe->clock_source; +			free_pipe->top_pipe = tail_pipe; +			tail_pipe->bottom_pipe = free_pipe; +			if (!free_pipe->next_odm_pipe && tail_pipe->next_odm_pipe && tail_pipe->next_odm_pipe->bottom_pipe) { +				free_pipe->next_odm_pipe = tail_pipe->next_odm_pipe->bottom_pipe; +				tail_pipe->next_odm_pipe->bottom_pipe->prev_odm_pipe = free_pipe; +			} +			if (!free_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe && tail_pipe->prev_odm_pipe->bottom_pipe) { +				free_pipe->prev_odm_pipe = tail_pipe->prev_odm_pipe->bottom_pipe; +				tail_pipe->prev_odm_pipe->bottom_pipe->next_odm_pipe = free_pipe;  			}  		} - -		/* ODM + window MPO, where MPO window is on left half only */ -		if (free_pipe->plane_state && -				(free_pipe->plane_state->clip_rect.x + free_pipe->plane_state->clip_rect.width <= -				free_pipe->stream->src.x + free_pipe->stream->src.width/2)) { -			break; -		} -		/* ODM + window MPO, where MPO window is on right half only */ -		if (free_pipe->plane_state && -				(free_pipe->plane_state->clip_rect.x >= free_pipe->stream->src.width/2)) { -			break; -		} -  		head_pipe = head_pipe->next_odm_pipe;  	}  	/* assign new surfaces*/ @@ -1763,6 +1724,94 @@ static void update_hpo_dp_stream_engine_usage(  			res_ctx->is_hpo_dp_stream_enc_acquired[i] = acquired;  	}  } + +static inline int find_acquired_hpo_dp_link_enc_for_link( +		const struct resource_context *res_ctx, +		const struct dc_link *link) +{ +	int i; + +	for (i = 0; i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_to_link_idx); i++) +		if (res_ctx->hpo_dp_link_enc_ref_cnts[i] > 0 && +				res_ctx->hpo_dp_link_enc_to_link_idx[i] == link->link_index) +			return i; + +	return -1; +} + +static inline int find_free_hpo_dp_link_enc(const struct resource_context *res_ctx, +		const struct resource_pool *pool) +{ +	int i; + +	for (i = 0; i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_ref_cnts); i++) +		if (res_ctx->hpo_dp_link_enc_ref_cnts[i] == 0) +			break; + +	return (i < ARRAY_SIZE(res_ctx->hpo_dp_link_enc_ref_cnts) && +			i < pool->hpo_dp_link_enc_count) ? i : -1; +} + +static inline void acquire_hpo_dp_link_enc( +		struct resource_context *res_ctx, +		unsigned int link_index, +		int enc_index) +{ +	res_ctx->hpo_dp_link_enc_to_link_idx[enc_index] = link_index; +	res_ctx->hpo_dp_link_enc_ref_cnts[enc_index] = 1; +} + +static inline void retain_hpo_dp_link_enc( +		struct resource_context *res_ctx, +		int enc_index) +{ +	res_ctx->hpo_dp_link_enc_ref_cnts[enc_index]++; +} + +static inline void release_hpo_dp_link_enc( +		struct resource_context *res_ctx, +		int enc_index) +{ +	ASSERT(res_ctx->hpo_dp_link_enc_ref_cnts[enc_index] > 0); +	res_ctx->hpo_dp_link_enc_ref_cnts[enc_index]--; +} + +static bool add_hpo_dp_link_enc_to_ctx(struct resource_context *res_ctx, +		const struct resource_pool *pool, +		struct pipe_ctx *pipe_ctx, +		struct dc_stream_state *stream) +{ +	int enc_index; + +	enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, stream->link); + +	if (enc_index >= 0) { +		retain_hpo_dp_link_enc(res_ctx, enc_index); +	} else { +		enc_index = find_free_hpo_dp_link_enc(res_ctx, pool); +		if (enc_index >= 0) +			acquire_hpo_dp_link_enc(res_ctx, stream->link->link_index, enc_index); +	} + +	if (enc_index >= 0) +		pipe_ctx->link_res.hpo_dp_link_enc = pool->hpo_dp_link_enc[enc_index]; + +	return pipe_ctx->link_res.hpo_dp_link_enc != NULL; +} + +static void remove_hpo_dp_link_enc_from_ctx(struct resource_context *res_ctx, +		struct pipe_ctx *pipe_ctx, +		struct dc_stream_state *stream) +{ +	int enc_index; + +	enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, stream->link); + +	if (enc_index >= 0) { +		release_hpo_dp_link_enc(res_ctx, enc_index); +		pipe_ctx->link_res.hpo_dp_link_enc = NULL; +	} +}  #endif  /* TODO: release audio object */ @@ -1925,6 +1974,7 @@ enum dc_status dc_remove_stream_from_ctx(  			&new_ctx->res_ctx, dc->res_pool,  			del_pipe->stream_res.hpo_dp_stream_enc,  			false); +		remove_hpo_dp_link_enc_from_ctx(&new_ctx->res_ctx, del_pipe, del_pipe->stream);  	}  #endif @@ -2200,6 +2250,8 @@ enum dc_status resource_map_pool_resources(  					&context->res_ctx, pool,  					pipe_ctx->stream_res.hpo_dp_stream_enc,  					true); +			if (!add_hpo_dp_link_enc_to_ctx(&context->res_ctx, pool, pipe_ctx, stream)) +				return DC_NO_LINK_ENC_RESOURCE;  		}  	}  #endif @@ -2875,6 +2927,8 @@ bool pipe_need_reprogram(  #if defined(CONFIG_DRM_AMD_DC_DCN)  	if (pipe_ctx_old->stream_res.hpo_dp_stream_enc != pipe_ctx->stream_res.hpo_dp_stream_enc)  		return true; +	if (pipe_ctx_old->link_res.hpo_dp_link_enc != pipe_ctx->link_res.hpo_dp_link_enc) +		return true;  #endif  	/* DIG link encoder resource assignment for stream changed. */ @@ -3143,22 +3197,23 @@ void get_audio_check(struct audio_info *aud_modes,  }  #if defined(CONFIG_DRM_AMD_DC_DCN) -struct hpo_dp_link_encoder *resource_get_unused_hpo_dp_link_encoder( -		const struct resource_pool *pool) +struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt( +		const struct resource_context *res_ctx, +		const struct resource_pool *pool, +		const struct dc_link *link)  { -	uint8_t i; -	struct hpo_dp_link_encoder *enc = NULL; +	struct hpo_dp_link_encoder *hpo_dp_link_enc = NULL; +	int enc_index; -	ASSERT(pool->hpo_dp_link_enc_count <= MAX_HPO_DP2_LINK_ENCODERS); +	enc_index = find_acquired_hpo_dp_link_enc_for_link(res_ctx, link); -	for (i = 0; i < pool->hpo_dp_link_enc_count; i++) { -		if (pool->hpo_dp_link_enc[i]->transmitter == TRANSMITTER_UNKNOWN) { -			enc = pool->hpo_dp_link_enc[i]; -			break; -		} -	} +	if (enc_index < 0) +		enc_index = find_free_hpo_dp_link_enc(res_ctx, pool); + +	if (enc_index >= 0) +		hpo_dp_link_enc = pool->hpo_dp_link_enc[enc_index]; -	return enc; +	return hpo_dp_link_enc;  }  #endif diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 18e59d635ca2..288e7b01f561 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload;  struct set_config_cmd_payload;  struct dmub_notification; -#define DC_VER "3.2.166" +#define DC_VER "3.2.167"  #define MAX_SURFACES 3  #define MAX_PLANES 6 @@ -691,6 +691,7 @@ struct dc_debug_options {  	/* TODO - remove once tested */  	bool legacy_dp2_lt;  	bool set_mst_en_for_sst; +	bool disable_uhbr;  	bool force_dp2_lt_fallback_method;  #endif  	union mem_low_power_enable_options enable_mem_low_power; diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 4ebba641538b..c0e37ad0e26c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -30,6 +30,8 @@  #include "dc_types.h"  #include "grph_object_defs.h" +struct link_resource; +  enum dc_link_fec_state {  	dc_link_fec_not_ready,  	dc_link_fec_ready, @@ -160,9 +162,6 @@ struct dc_link {  	struct panel_cntl *panel_cntl;  	struct link_encoder *link_enc; -#if defined(CONFIG_DRM_AMD_DC_DCN) -	struct hpo_dp_link_encoder *hpo_dp_link_enc; -#endif  	struct graphics_object_id link_id;  	/* Endpoint type distinguishes display endpoints which do not have entries  	 * in the BIOS connector table from those that do. Helps when tracking link @@ -359,14 +358,17 @@ void dc_link_remove_remote_sink(  void dc_link_dp_set_drive_settings(  	struct dc_link *link, +	const struct link_resource *link_res,  	struct link_training_settings *lt_settings);  bool dc_link_dp_perform_link_training_skip_aux(  	struct dc_link *link, +	const struct link_resource *link_res,  	const struct dc_link_settings *link_setting);  enum link_training_result dc_link_dp_perform_link_training(  	struct dc_link *link, +	const struct link_resource *link_res,  	const struct dc_link_settings *link_settings,  	bool skip_video_pattern); @@ -374,6 +376,7 @@ bool dc_link_dp_sync_lt_begin(struct dc_link *link);  enum link_training_result dc_link_dp_sync_lt_attempt(  	struct dc_link *link, +	const struct link_resource *link_res,  	struct dc_link_settings *link_setting,  	struct dc_link_training_overrides *lt_settings); @@ -454,4 +457,10 @@ bool dc_link_should_enable_fec(const struct dc_link *link);  uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw);  enum dp_link_encoding dc_link_dp_mst_decide_link_encoding_format(const struct dc_link *link);  #endif + +const struct link_resource *dc_link_get_cur_link_res(const struct dc_link *link); +/* take a snapshot of current link resource allocation state */ +void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map); +/* restore link resource allocation state from a snapshot */ +void dc_restore_link_res_map(const struct dc *dc, uint32_t *map);  #endif /* DC_LINK_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 2d470f524367..f19015413ce3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -468,8 +468,6 @@ void dcn10_log_hw_state(struct dc *dc,  	log_mpc_crc(dc, log_ctx);  	{ -		int hpo_dp_link_enc_count = 0; -  		if (pool->hpo_dp_stream_enc_count > 0) {  			DTN_INFO("DP HPO S_ENC:  Enabled  OTG   Format   Depth   Vid   SDP   Compressed  Link\n");  			for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) { @@ -500,18 +498,14 @@ void dcn10_log_hw_state(struct dc *dc,  		}  		/* log DP HPO L_ENC section if any hpo_dp_link_enc exists */ -		for (i = 0; i < dc->link_count; i++) -			if (dc->links[i]->hpo_dp_link_enc) -				hpo_dp_link_enc_count++; - -		if (hpo_dp_link_enc_count) { +		if (pool->hpo_dp_link_enc_count) {  			DTN_INFO("DP HPO L_ENC:  Enabled  Mode   Lanes   Stream  Slots   VC Rate X    VC Rate Y\n"); -			for (i = 0; i < dc->link_count; i++) { -				struct hpo_dp_link_encoder *hpo_dp_link_enc = dc->links[i]->hpo_dp_link_enc; +			for (i = 0; i < pool->hpo_dp_link_enc_count; i++) { +				struct hpo_dp_link_encoder *hpo_dp_link_enc = pool->hpo_dp_link_enc[i];  				struct hpo_dp_link_enc_state hpo_dp_le_state = {0}; -				if (hpo_dp_link_enc && hpo_dp_link_enc->funcs->read_state) { +				if (hpo_dp_link_enc->funcs->read_state) {  					hpo_dp_link_enc->funcs->read_state(hpo_dp_link_enc, &hpo_dp_le_state);  					DTN_INFO("[%d]:                 %d  %6s     %d        %d      %d     %d     %d\n",  							hpo_dp_link_enc->inst, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c index 34001a30d449..10e613ec7d24 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c @@ -78,6 +78,7 @@ static const struct hw_sequencer_funcs dcn10_funcs = {  	.get_clock = dcn10_get_clock,  	.get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync,  	.calc_vupdate_position = dcn10_calc_vupdate_position, +	.power_down = dce110_power_down,  	.set_backlight_level = dce110_set_backlight_level,  	.set_abm_immediate_disable = dce110_set_abm_immediate_disable,  	.set_pipe = dce110_set_pipe, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index a17fe8ab2904..4991e93e5308 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -2414,7 +2414,7 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)  		pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->map_stream_to_link(  				pipe_ctx->stream_res.hpo_dp_stream_enc,  				pipe_ctx->stream_res.hpo_dp_stream_enc->inst, -				link->hpo_dp_link_enc->inst); +				pipe_ctx->link_res.hpo_dp_link_enc->inst);  	}  	if (!is_dp_128b_132b_signal(pipe_ctx) && link_enc) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 40b122a708ef..2bc93df023ad 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -1069,7 +1069,7 @@ static const struct dc_debug_options debug_defaults_drv = {  		.timing_trace = false,  		.clock_trace = true,  		.disable_pplib_clock_request = true, -		.pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, +		.pipe_split_policy = MPC_SPLIT_DYNAMIC,  		.force_single_disp_pipe_split = false,  		.disable_dcc = DCC_ENABLE,  		.vsr_support = true, @@ -3093,8 +3093,7 @@ static enum dcn_zstate_support_state  decide_zstate_support(struct dc *dc, struc  	else if (context->stream_count == 1 &&  context->streams[0]->signal == SIGNAL_TYPE_EDP) {  		struct dc_link *link = context->streams[0]->sink->link; -		if ((link->link_index == 0 && link->psr_settings.psr_feature_enabled) -				|| context->bw_ctx.dml.vba.StutterPeriod > 5000.0) +		if (link->link_index == 0 && context->bw_ctx.dml.vba.StutterPeriod > 5000.0)  			return DCN_ZSTATE_SUPPORT_ALLOW;  		else  			return DCN_ZSTATE_SUPPORT_DISALLOW; diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c index cfd09b3f705e..fe22530242d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hwseq.c @@ -134,11 +134,12 @@ void dcn201_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)  	PHYSICAL_ADDRESS_LOC addr;  	struct dc_plane_state *plane_state = pipe_ctx->plane_state;  	struct dce_hwseq *hws = dc->hwseq; -	struct dc_plane_address uma = plane_state->address; +	struct dc_plane_address uma;  	if (plane_state == NULL)  		return; +	uma = plane_state->address;  	addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);  	plane_address_in_gpu_space_to_uma(hws, &uma); diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c index d6acf9a8590a..0bb7d3dd53fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_resource.c @@ -603,7 +603,7 @@ static const struct dc_debug_options debug_defaults_drv = {  		.timing_trace = false,  		.clock_trace = true,  		.disable_pplib_clock_request = true, -		.pipe_split_policy = MPC_SPLIT_AVOID, +		.pipe_split_policy = MPC_SPLIT_DYNAMIC,  		.force_single_disp_pipe_split = false,  		.disable_dcc = DCC_ENABLE,  		.vsr_support = true, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index ca1bbc942fd4..e5cc6bf45743 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -873,7 +873,7 @@ static const struct dc_debug_options debug_defaults_drv = {  		.clock_trace = true,  		.disable_pplib_clock_request = true,  		.min_disp_clk_khz = 100000, -		.pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, +		.pipe_split_policy = MPC_SPLIT_DYNAMIC,  		.force_single_disp_pipe_split = false,  		.disable_dcc = DCC_ENABLE,  		.vsr_support = true, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 369ceeeddc7e..602ec9a08549 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -840,7 +840,7 @@ static const struct dc_debug_options debug_defaults_drv = {  	.timing_trace = false,  	.clock_trace = true,  	.disable_pplib_clock_request = true, -	.pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, +	.pipe_split_policy = MPC_SPLIT_DYNAMIC,  	.force_single_disp_pipe_split = false,  	.disable_dcc = DCC_ENABLE,  	.vsr_support = true, @@ -1761,17 +1761,6 @@ static bool dcn30_split_stream_for_mpc_or_odm(  	int pipe_idx = sec_pipe->pipe_idx;  	const struct resource_pool *pool = dc->res_pool; -	if (pri_pipe->plane_state) { -		/* ODM + window MPO, where MPO window is on left half only */ -		if (pri_pipe->plane_state->clip_rect.x + pri_pipe->plane_state->clip_rect.width <= -				pri_pipe->stream->src.x + pri_pipe->stream->src.width/2) -			return true; - -		/* ODM + window MPO, where MPO window is on right half only */ -		if (pri_pipe->plane_state->clip_rect.x >= pri_pipe->stream->src.width/2) -			return true; -	} -  	*sec_pipe = *pri_pipe;  	sec_pipe->pipe_idx = pipe_idx; diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c index b4001233867c..c1c6e602b06c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c @@ -686,7 +686,7 @@ static const struct dc_debug_options debug_defaults_drv = {  	.disable_clock_gate = true,  	.disable_pplib_clock_request = true,  	.disable_pplib_wm_range = true, -	.pipe_split_policy = MPC_SPLIT_AVOID, +	.pipe_split_policy = MPC_SPLIT_DYNAMIC,  	.force_single_disp_pipe_split = false,  	.disable_dcc = DCC_ENABLE,  	.vsr_support = true, diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c index 003e95368672..2e9cbfa7663b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c @@ -211,7 +211,7 @@ static const struct dc_debug_options debug_defaults_drv = {  		.timing_trace = false,  		.clock_trace = true,  		.disable_pplib_clock_request = true, -		.pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, +		.pipe_split_policy = MPC_SPLIT_DYNAMIC,  		.force_single_disp_pipe_split = false,  		.disable_dcc = DCC_ENABLE,  		.vsr_support = true, diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_dccg.h index a79c54bbc899..294bd757bcb5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_dccg.h @@ -15,7 +15,11 @@  	SR(DPPCLK_DTO_CTRL),\  	DCCG_SRII(DTO_PARAM, DPPCLK, 0),\  	DCCG_SRII(DTO_PARAM, DPPCLK, 1),\ -	SR(REFCLK_CNTL) +	SR(REFCLK_CNTL),\ +	SR(DISPCLK_FREQ_CHANGE_CNTL),\ +	DCCG_SRII(PIXEL_RATE_CNTL, OTG, 0),\ +	DCCG_SRII(PIXEL_RATE_CNTL, OTG, 1) +  #define DCCG_MASK_SH_LIST_DCN3_03(mask_sh) \  		DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 0, mask_sh),\ @@ -25,6 +29,18 @@  		DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_PHASE, mask_sh),\  		DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_MODULO, mask_sh),\  		DCCG_SF(REFCLK_CNTL, REFCLK_CLOCK_EN, mask_sh),\ -		DCCG_SF(REFCLK_CNTL, REFCLK_SRC_SEL, mask_sh) +		DCCG_SF(REFCLK_CNTL, REFCLK_SRC_SEL, mask_sh),\ +		DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_STEP_DELAY, mask_sh),\ +		DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_STEP_SIZE, mask_sh),\ +		DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_FREQ_RAMP_DONE, mask_sh),\ +		DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_MAX_ERRDET_CYCLES, mask_sh),\ +		DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_RESET, mask_sh),\ +		DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_STATE, mask_sh),\ +		DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_OVR_EN, mask_sh),\ +		DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_CHG_FWD_CORR_DISABLE, mask_sh),\ +		DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, ADD_PIXEL, 0, mask_sh),\ +		DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, ADD_PIXEL, 1, mask_sh),\ +		DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, DROP_PIXEL, 0, mask_sh),\ +		DCCG_SFII(OTG, PIXEL_RATE_CNTL, OTG, DROP_PIXEL, 1, mask_sh)  #endif //__DCN303_DCCG_H__ diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c index 01ba9d656c72..2de687f64cf6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c @@ -193,7 +193,7 @@ static const struct dc_debug_options debug_defaults_drv = {  		.timing_trace = false,  		.clock_trace = true,  		.disable_pplib_clock_request = true, -		.pipe_split_policy = MPC_SPLIT_AVOID_MULT_DISP, +		.pipe_split_policy = MPC_SPLIT_DYNAMIC,  		.force_single_disp_pipe_split = false,  		.disable_dcc = DCC_ENABLE,  		.vsr_support = true, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c index 6c08e21bb708..80dfaa4d4d81 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c @@ -499,7 +499,8 @@ static enum bp_result link_transmitter_control(  void dcn31_hpo_dp_link_enc_enable_dp_output(  	struct hpo_dp_link_encoder *enc,  	const struct dc_link_settings *link_settings, -	enum transmitter transmitter) +	enum transmitter transmitter, +	enum hpd_source_id hpd_source)  {  	struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);  	struct bp_transmitter_control cntl = { 0 }; @@ -508,6 +509,9 @@ void dcn31_hpo_dp_link_enc_enable_dp_output(  	/* Set the transmitter */  	enc3->base.transmitter = transmitter; +	/* Set the hpd source */ +	enc3->base.hpd_source = hpd_source; +  	/* Enable the PHY */  	cntl.action = TRANSMITTER_CONTROL_ENABLE;  	cntl.engine_id = ENGINE_ID_UNKNOWN; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h index 0706ccaf6fec..e324e9b83136 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h @@ -184,7 +184,8 @@ void hpo_dp_link_encoder31_construct(struct dcn31_hpo_dp_link_encoder *enc31,  void dcn31_hpo_dp_link_enc_enable_dp_output(  	struct hpo_dp_link_encoder *enc,  	const struct dc_link_settings *link_settings, -	enum transmitter transmitter); +	enum transmitter transmitter, +	enum hpd_source_id hpd_source);  void dcn31_hpo_dp_link_enc_disable_output(  	struct hpo_dp_link_encoder *enc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c index 7a7a8c5edabd..d7559e5a99ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c @@ -103,6 +103,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = {  	.z10_restore = dcn31_z10_restore,  	.z10_save_init = dcn31_z10_save_init,  	.set_disp_pattern_generator = dcn30_set_disp_pattern_generator, +	.optimize_pwr_state = dcn21_optimize_pwr_state,  	.exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state,  	.update_visual_confirm_color = dcn20_update_visual_confirm_color,  }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 29ee3c22b0ab..ba4c33500a6d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -355,6 +355,14 @@ static const struct dce110_clk_src_regs clk_src_regs[] = {  	clk_src_regs(3, D),  	clk_src_regs(4, E)  }; +/*pll_id being rempped in dmub, in driver it is logical instance*/ +static const struct dce110_clk_src_regs clk_src_regs_b0[] = { +	clk_src_regs(0, A), +	clk_src_regs(1, B), +	clk_src_regs(2, F), +	clk_src_regs(3, G), +	clk_src_regs(4, E) +};  static const struct dce110_clk_src_shift cs_shift = {  		CS_COMMON_MASK_SH_LIST_DCN2_0(__SHIFT) @@ -995,7 +1003,7 @@ static const struct dc_debug_options debug_defaults_drv = {  	.timing_trace = false,  	.clock_trace = true,  	.disable_pplib_clock_request = false, -	.pipe_split_policy = MPC_SPLIT_AVOID, +	.pipe_split_policy = MPC_SPLIT_DYNAMIC,  	.force_single_disp_pipe_split = false,  	.disable_dcc = DCC_ENABLE,  	.vsr_support = true, @@ -2294,14 +2302,27 @@ static bool dcn31_resource_construct(  			dcn30_clock_source_create(ctx, ctx->dc_bios,  				CLOCK_SOURCE_COMBO_PHY_PLL1,  				&clk_src_regs[1], false); -	pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = +	/*move phypllx_pixclk_resync to dmub next*/ +	if (dc->ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) { +		pool->base.clock_sources[DCN31_CLK_SRC_PLL2] = +			dcn30_clock_source_create(ctx, ctx->dc_bios, +				CLOCK_SOURCE_COMBO_PHY_PLL2, +				&clk_src_regs_b0[2], false); +		pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = +			dcn30_clock_source_create(ctx, ctx->dc_bios, +				CLOCK_SOURCE_COMBO_PHY_PLL3, +				&clk_src_regs_b0[3], false); +	} else { +		pool->base.clock_sources[DCN31_CLK_SRC_PLL2] =  			dcn30_clock_source_create(ctx, ctx->dc_bios,  				CLOCK_SOURCE_COMBO_PHY_PLL2,  				&clk_src_regs[2], false); -	pool->base.clock_sources[DCN31_CLK_SRC_PLL3] = +		pool->base.clock_sources[DCN31_CLK_SRC_PLL3] =  			dcn30_clock_source_create(ctx, ctx->dc_bios,  				CLOCK_SOURCE_COMBO_PHY_PLL3,  				&clk_src_regs[3], false); +	} +  	pool->base.clock_sources[DCN31_CLK_SRC_PLL4] =  			dcn30_clock_source_create(ctx, ctx->dc_bios,  				CLOCK_SOURCE_COMBO_PHY_PLL4, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h index 416fe7a721d8..a513363b3326 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h @@ -49,4 +49,35 @@ struct resource_pool *dcn31_create_resource_pool(  		const struct dc_init_data *init_data,  		struct dc *dc); +/*temp: B0 specific before switch to dcn313 headers*/ +#ifndef regPHYPLLF_PIXCLK_RESYNC_CNTL +#define regPHYPLLF_PIXCLK_RESYNC_CNTL 0x007e +#define regPHYPLLF_PIXCLK_RESYNC_CNTL_BASE_IDX 1 +#define regPHYPLLG_PIXCLK_RESYNC_CNTL 0x005f +#define regPHYPLLG_PIXCLK_RESYNC_CNTL_BASE_IDX 1 + +//PHYPLLF_PIXCLK_RESYNC_CNTL +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_RESYNC_ENABLE__SHIFT 0x0 +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DEEP_COLOR_DTO_ENABLE_STATUS__SHIFT 0x1 +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4 +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_ENABLE__SHIFT 0x8 +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9 +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_RESYNC_ENABLE_MASK 0x00000001L +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DEEP_COLOR_DTO_ENABLE_STATUS_MASK 0x00000002L +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_DCCG_DEEP_COLOR_CNTL_MASK 0x00000030L +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_ENABLE_MASK 0x00000100L +#define PHYPLLF_PIXCLK_RESYNC_CNTL__PHYPLLF_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x00000200L + +//PHYPLLG_PIXCLK_RESYNC_CNTL +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_RESYNC_ENABLE__SHIFT 0x0 +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DEEP_COLOR_DTO_ENABLE_STATUS__SHIFT 0x1 +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DCCG_DEEP_COLOR_CNTL__SHIFT 0x4 +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_ENABLE__SHIFT 0x8 +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_DOUBLE_RATE_ENABLE__SHIFT 0x9 +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_RESYNC_ENABLE_MASK 0x00000001L +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DEEP_COLOR_DTO_ENABLE_STATUS_MASK 0x00000002L +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_DCCG_DEEP_COLOR_CNTL_MASK 0x00000030L +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_ENABLE_MASK 0x00000100L +#define PHYPLLG_PIXCLK_RESYNC_CNTL__PHYPLLG_PIXCLK_DOUBLE_RATE_ENABLE_MASK 0x00000200L +#endif  #endif /* _DCN31_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper.c index 91810aaee5a3..789f7562cdc7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml_wrapper.c @@ -1274,7 +1274,7 @@ static void dcn20_adjust_adaptive_sync_v_startup(  static bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx)  {  	return (pipe_ctx->stream_res.hpo_dp_stream_enc && -			pipe_ctx->stream->link->hpo_dp_link_enc && +			pipe_ctx->link_res.hpo_dp_link_enc &&  			dc_is_dp_signal(pipe_ctx->stream->signal));  } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_status.h b/drivers/gpu/drm/amd/display/dc/inc/core_status.h index d34b0b0eea65..444182a97e6e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_status.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_status.h @@ -53,6 +53,8 @@ enum dc_status {  	DC_NOT_SUPPORTED = 24,  	DC_UNSUPPORTED_VALUE = 25, +	DC_NO_LINK_ENC_RESOURCE = 26, +  	DC_ERROR_UNEXPECTED = -1  }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index f3c0e70073da..943240e2809e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -334,6 +334,20 @@ struct plane_resource {  	struct dcn_fe_bandwidth bw;  }; +#if defined(CONFIG_DRM_AMD_DC_DCN) +#define LINK_RES_HPO_DP_REC_MAP__MASK 0xFFFF +#define LINK_RES_HPO_DP_REC_MAP__SHIFT 0 +#endif + +/* all mappable hardware resources used to enable a link */ +struct link_resource { +#if defined(CONFIG_DRM_AMD_DC_DCN) +	struct hpo_dp_link_encoder *hpo_dp_link_enc; +#else +	void *dummy; +#endif +}; +  union pipe_update_flags {  	struct {  		uint32_t enable : 1; @@ -361,6 +375,7 @@ struct pipe_ctx {  	struct plane_resource plane_res;  	struct stream_resource stream_res; +	struct link_resource link_res;  	struct clock_source *clock_source; @@ -412,6 +427,8 @@ struct resource_context {  	struct link_enc_cfg_context link_enc_cfg_ctx;  #if defined(CONFIG_DRM_AMD_DC_DCN)  	bool is_hpo_dp_stream_enc_acquired[MAX_HPO_DP2_ENCODERS]; +	unsigned int hpo_dp_link_enc_to_link_idx[MAX_HPO_DP2_LINK_ENCODERS]; +	int hpo_dp_link_enc_ref_cnts[MAX_HPO_DP2_LINK_ENCODERS];  #endif  #if defined(CONFIG_DRM_AMD_DC_DCN)  	bool is_mpc_3dlut_acquired[MAX_PIPES]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 52bdfea7897b..cd52813a8432 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -56,16 +56,19 @@ enum {  bool dp_verify_link_cap(  	struct dc_link *link, +	const struct link_resource *link_res,  	struct dc_link_settings *known_limit_link_setting,  	int *fail_count);  bool dp_verify_link_cap_with_retries(  	struct dc_link *link, +	const struct link_resource *link_res,  	struct dc_link_settings *known_limit_link_setting,  	int attempts);  bool dp_verify_mst_link_cap( -	struct dc_link *link); +	struct dc_link *link, +	const struct link_resource *link_res);  bool dp_validate_mode_timing(  	struct dc_link *link, @@ -168,7 +171,7 @@ uint8_t dc_dp_initialize_scrambling_data_symbols(  	struct dc_link *link,  	enum dc_dp_training_pattern pattern); -enum dc_status dp_set_fec_ready(struct dc_link *link, bool ready); +enum dc_status dp_set_fec_ready(struct dc_link *link, const struct link_resource *link_res, bool ready);  void dp_set_fec_enable(struct dc_link *link, bool enable);  struct link_encoder *dp_get_link_enc(struct dc_link *link);  bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable); @@ -211,8 +214,12 @@ bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link);  struct fixed31_32 calculate_sst_avg_time_slots_per_mtp(  		const struct dc_stream_state *stream,  		const struct dc_link *link); -void enable_dp_hpo_output(struct dc_link *link, const struct dc_link_settings *link_settings); -void disable_dp_hpo_output(struct dc_link *link, enum signal_type signal); +void enable_dp_hpo_output(struct dc_link *link, +		const struct link_resource *link_res, +		const struct dc_link_settings *link_settings); +void disable_dp_hpo_output(struct dc_link *link, +		const struct link_resource *link_res, +		enum signal_type signal);  void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable);  bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx);  void reset_dp_hpo_stream_encoders_for_link(struct dc_link *link); diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dpia.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dpia.h index 974d703e3771..74dafd0f9d3d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dpia.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dpia.h @@ -91,8 +91,9 @@ enum dc_status dpcd_get_tunneling_device_data(struct dc_link *link);   * DPIA equivalent of dc_link_dp_perfrorm_link_training.   * Aborts link training upon detection of sink unplug.   */ -enum link_training_result -dc_link_dpia_perform_link_training(struct dc_link *link, +enum link_training_result dc_link_dpia_perform_link_training( +	struct dc_link *link, +	const struct link_resource *link_res,  	const struct dc_link_settings *link_setting,  	bool skip_video_pattern); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index bb0e91756ddd..2ce15cd10d80 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -268,7 +268,8 @@ struct hpo_dp_link_encoder_funcs {  	void (*enable_link_phy)(struct hpo_dp_link_encoder *enc,  		const struct dc_link_settings *link_settings, -		enum transmitter transmitter); +		enum transmitter transmitter, +		enum hpd_source_id hpd_source);  	void (*disable_link_phy)(struct hpo_dp_link_encoder *link_enc,  		enum signal_type signal); diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index ba664bc49595..69d63763a10e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -32,6 +32,7 @@ struct gpio *get_hpd_gpio(struct dc_bios *dcb,  void dp_enable_link_phy(  	struct dc_link *link, +	const struct link_resource *link_res,  	enum signal_type signal,  	enum clock_source_id clock_source,  	const struct dc_link_settings *link_settings); @@ -42,22 +43,27 @@ void edp_add_delay_for_T9(struct dc_link *link);  bool edp_receiver_ready_T9(struct dc_link *link);  bool edp_receiver_ready_T7(struct dc_link *link); -void dp_disable_link_phy(struct dc_link *link, enum signal_type signal); +void dp_disable_link_phy(struct dc_link *link, const struct link_resource *link_res, +		enum signal_type signal); -void dp_disable_link_phy_mst(struct dc_link *link, enum signal_type signal); +void dp_disable_link_phy_mst(struct dc_link *link, const struct link_resource *link_res, +		enum signal_type signal);  bool dp_set_hw_training_pattern(  	struct dc_link *link, +	const struct link_resource *link_res,  	enum dc_dp_training_pattern pattern,  	uint32_t offset);  void dp_set_hw_lane_settings(  	struct dc_link *link, +	const struct link_resource *link_res,  	const struct link_training_settings *link_settings,  	uint32_t offset);  void dp_set_hw_test_pattern(  	struct dc_link *link, +	const struct link_resource *link_res,  	enum dp_test_pattern test_pattern,  	uint8_t *custom_pattern,  	uint32_t custom_pattern_size); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index c208925f8247..ee4a5df428e3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -206,8 +206,10 @@ int get_num_mpc_splits(struct pipe_ctx *pipe);  int get_num_odm_splits(struct pipe_ctx *pipe);  #if defined(CONFIG_DRM_AMD_DC_DCN) -struct hpo_dp_link_encoder *resource_get_unused_hpo_dp_link_encoder( -		const struct resource_pool *pool); +struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt( +		const struct resource_context *res_ctx, +		const struct resource_pool *pool, +		const struct dc_link *link);  #endif  void reset_syncd_pipes_from_disabled_pipes(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index afe9bc839b45..873ecd04e01d 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -46,10 +46,10 @@  /* Firmware versioning. */  #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0xc99a4517 +#define DMUB_FW_VERSION_GIT_HASH 0xbaf06b95  #define DMUB_FW_VERSION_MAJOR 0  #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 97 +#define DMUB_FW_VERSION_REVISION 98  #define DMUB_FW_VERSION_TEST 0  #define DMUB_FW_VERSION_VBIOS 0  #define DMUB_FW_VERSION_HOTFIX 0 diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index f673a1c1777a..9280f2abd973 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -852,7 +852,7 @@ bool dmub_srv_should_detect(struct dmub_srv *dmub)  enum dmub_status dmub_srv_clear_inbox0_ack(struct dmub_srv *dmub)  { -	if (!dmub->hw_init || dmub->hw_funcs.clear_inbox0_ack_register) +	if (!dmub->hw_init || !dmub->hw_funcs.clear_inbox0_ack_register)  		return DMUB_STATUS_INVALID;  	dmub->hw_funcs.clear_inbox0_ack_register(dmub); @@ -878,7 +878,7 @@ enum dmub_status dmub_srv_wait_for_inbox0_ack(struct dmub_srv *dmub, uint32_t ti  enum dmub_status dmub_srv_send_inbox0_cmd(struct dmub_srv *dmub,  		union dmub_inbox0_data_register data)  { -	if (!dmub->hw_init || dmub->hw_funcs.send_inbox0_cmd) +	if (!dmub->hw_init || !dmub->hw_funcs.send_inbox0_cmd)  		return DMUB_STATUS_INVALID;  	dmub->hw_funcs.send_inbox0_cmd(dmub, data); |