Commit 79ed7354 authored by Jimmy Kizito's avatar Jimmy Kizito Committed by Alex Deucher
Browse files

drm/amd/display: Update display endpoint control path.



[Why]
Some display endpoints may be dynamically mapped to the link encoders
which drive them.

[How]
Update the code paths for display enabling/disabling to accommodate
the dynamic association between links and link encoders.

Signed-off-by: default avatarJimmy Kizito <Jimmy.Kizito@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarAnson Jacob <Anson.Jacob@amd.com>
Tested-by: default avatarDan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent f42ef862
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -1728,11 +1728,16 @@ bool perform_link_training_with_retries(
		if (link->aux_access_disabled) {
			dc_link_dp_perform_link_training_skip_aux(link, link_setting);
			return true;
		} else if (dc_link_dp_perform_link_training(
		} else {
			enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0;

				status = dc_link_dp_perform_link_training(
										link,
										link_setting,
				skip_video_pattern) == LINK_TRAINING_SUCCESS)
										skip_video_pattern);
			if (status == LINK_TRAINING_SUCCESS)
				return true;
		}

		/* latest link training still fail, skip delay and keep PHY on
		 */
+99 −0
Original line number Diff line number Diff line
@@ -127,6 +127,32 @@ static enum engine_id find_first_avail_link_enc(
	return eng_id;
}

/* Return stream using DIG link encoder resource. NULL if unused. */
static struct dc_stream_state *get_stream_using_link_enc(
		struct dc_state *state,
		enum engine_id eng_id)
{
	struct dc_stream_state *stream = NULL;
	int stream_idx = -1;
	int i;

	for (i = 0; i < state->stream_count; i++) {
		struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i];

		if (assignment.valid && (assignment.eng_id == eng_id)) {
			stream_idx = i;
			break;
		}
	}

	if (stream_idx != -1)
		stream = state->streams[stream_idx];
	else
		dm_output_to_console("%s: No stream using DIG(%d).\n", __func__, eng_id);

	return stream;
}

void link_enc_cfg_init(
		struct dc *dc,
		struct dc_state *state)
@@ -202,3 +228,76 @@ void link_enc_cfg_link_enc_unassign(

	update_link_enc_assignment(state, stream, eng_id, false);
}

bool link_enc_cfg_is_transmitter_mappable(
		struct dc_state *state,
		struct link_encoder *link_enc)
{
	bool is_mappable = false;
	enum engine_id eng_id = link_enc->preferred_engine;
	struct dc_stream_state *stream = get_stream_using_link_enc(state, eng_id);

	if (stream)
		is_mappable = stream->link->is_dig_mapping_flexible;

	return is_mappable;
}

struct dc_link *link_enc_cfg_get_link_using_link_enc(
		struct dc_state *state,
		enum engine_id eng_id)
{
	struct dc_link *link = NULL;
	int stream_idx = -1;
	int i;

	for (i = 0; i < state->stream_count; i++) {
		struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i];

		if (assignment.valid && (assignment.eng_id == eng_id)) {
			stream_idx = i;
			break;
		}
	}

	if (stream_idx != -1)
		link = state->streams[stream_idx]->link;
	else
		dm_output_to_console("%s: No link using DIG(%d).\n", __func__, eng_id);

	return link;
}

struct link_encoder *link_enc_cfg_get_link_enc_used_by_link(
		struct dc_state *state,
		struct dc_link *link)
{
	struct link_encoder *link_enc = NULL;
	struct display_endpoint_id ep_id;
	int stream_idx = -1;
	int i;

	ep_id = (struct display_endpoint_id) {
		.link_id = link->link_id,
		.ep_type = link->ep_type};

	for (i = 0; i < state->stream_count; i++) {
		struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i];

		if (assignment.valid &&
				assignment.ep_id.link_id.id == ep_id.link_id.id &&
				assignment.ep_id.link_id.enum_id == ep_id.link_id.enum_id &&
				assignment.ep_id.link_id.type == ep_id.link_id.type &&
				assignment.ep_id.ep_type == ep_id.ep_type) {
			stream_idx = i;
			break;
		}
	}

	if (stream_idx != -1)
		link_enc = state->streams[stream_idx]->link_enc;
	else
		dm_output_to_console("%s: No link encoder used by link(%d).\n", __func__, link->link_index);

	return link_enc;
}
+19 −3
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include "dpcd_defs.h"
#include "dsc.h"
#include "resource.h"
#include "link_enc_cfg.h"
#include "clk_mgr.h"

static uint8_t convert_to_count(uint8_t lttpr_repeater_count)
@@ -95,7 +96,7 @@ void dp_enable_link_phy(
	enum clock_source_id clock_source,
	const struct dc_link_settings *link_settings)
{
	struct link_encoder *link_enc = link->link_enc;
	struct link_encoder *link_enc;
	struct dc  *dc = link->ctx->dc;
	struct dmcu *dmcu = dc->res_pool->dmcu;

@@ -105,6 +106,13 @@ void dp_enable_link_phy(
			link->dc->res_pool->dp_clock_source;
	unsigned int i;

	/* Link should always be assigned encoder when en-/disabling. */
	if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign)
		link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
	else
		link_enc = link->link_enc;
	ASSERT(link_enc);

	if (link->connector_signal == SIGNAL_TYPE_EDP) {
		link->dc->hwss.edp_power_control(link, true);
		link->dc->hwss.edp_wait_for_hpd_ready(link, true);
@@ -227,6 +235,14 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
{
	struct dc  *dc = link->ctx->dc;
	struct dmcu *dmcu = dc->res_pool->dmcu;
	struct link_encoder *link_enc;

	/* Link should always be assigned encoder when en-/disabling. */
	if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign)
		link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link);
	else
		link_enc = link->link_enc;
	ASSERT(link_enc);

	if (!link->wa_flags.dp_keep_receiver_powered)
		dp_receiver_power_ctrl(link, false);
@@ -234,13 +250,13 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal)
	if (signal == SIGNAL_TYPE_EDP) {
		if (link->dc->hwss.edp_backlight_control)
			link->dc->hwss.edp_backlight_control(link, false);
		link->link_enc->funcs->disable_output(link->link_enc, signal);
		link_enc->funcs->disable_output(link_enc, signal);
		link->dc->hwss.edp_power_control(link, false);
	} else {
		if (dmcu != NULL && dmcu->funcs->lock_phy)
			dmcu->funcs->lock_phy(dmcu);

		link->link_enc->funcs->disable_output(link->link_enc, signal);
		link_enc->funcs->disable_output(link_enc, signal);

		if (dmcu != NULL && dmcu->funcs->unlock_phy)
			dmcu->funcs->unlock_phy(dmcu);
+18 −0
Original line number Diff line number Diff line
@@ -65,4 +65,22 @@ void link_enc_cfg_link_enc_unassign(
		struct dc_state *state,
		struct dc_stream_state *stream);

/*
 * Check whether the transmitter driven by a link encoder is a mappable
 * endpoint.
 */
bool link_enc_cfg_is_transmitter_mappable(
		struct dc_state *state,
		struct link_encoder *link_enc);

/* Return link using DIG link encoder resource. NULL if unused. */
struct dc_link *link_enc_cfg_get_link_using_link_enc(
		struct dc_state *state,
		enum engine_id eng_id);

/* Return DIG link encoder used by link. NULL if unused. */
struct link_encoder *link_enc_cfg_get_link_enc_used_by_link(
		struct dc_state *state,
		struct dc_link *link);

#endif /* DC_INC_LINK_ENC_CFG_H_ */