Commit 8a58e25b authored by Wenjing Liu's avatar Wenjing Liu Committed by Alex Deucher
Browse files

drm/amd/display: dp mst detection code refactor



[why]
Move mst start top mgr in dc_link_detect layer.
Remove unused same_dpcd variable.
Move PEAK_FACTOR_X1000 and LINK_TRAINING_MAX_VERIFY_RETRY
to the proper header for defining dc link internal constant.

Signed-off-by: default avatarWenjing Liu <wenjing.liu@amd.com>
Reviewed-by: default avatarGeorge Shen <George.Shen@amd.com>
Acked-by: default avatarAnson Jacob <Anson.Jacob@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent a161f8cb
Loading
Loading
Loading
Loading
+61 −95
Original line number Diff line number Diff line
@@ -59,20 +59,6 @@
#define RETIMER_REDRIVER_INFO(...) \
	DC_LOG_RETIMER_REDRIVER(  \
		__VA_ARGS__)
/*******************************************************************************
 * Private structures
 ******************************************************************************/

enum {
	PEAK_FACTOR_X1000 = 1006,
	/*
	 * Some receivers fail to train on first try and are good
	 * on subsequent tries. 2 retries should be plenty. If we
	 * don't have a successful training then we don't expect to
	 * ever get one.
	 */
	LINK_TRAINING_MAX_VERIFY_RETRY = 2
};

/*******************************************************************************
 * Private functions
@@ -718,11 +704,9 @@ static void read_current_link_settings_on_detect(struct dc_link *link)

static bool detect_dp(struct dc_link *link,
		      struct display_sink_capability *sink_caps,
		      bool *converter_disable_audio,
		      struct audio_support *audio_support,
		      enum dc_detect_reason reason)
{
	bool boot = false;
	struct audio_support *audio_support = &link->dc->res_pool->audio_support;

	sink_caps->signal = link_detect_sink(link, reason);
	sink_caps->transaction_type =
@@ -745,60 +729,12 @@ static bool detect_dp(struct dc_link *link,
			 * of this function). */
			query_hdcp_capability(SIGNAL_TYPE_DISPLAY_PORT_MST, link);
#endif
			/*
			 * This call will initiate MST topology discovery. Which
			 * will detect MST ports and add new DRM connector DRM
			 * framework. Then read EDID via remote i2c over aux. In
			 * the end, will notify DRM detect result and save EDID
			 * into DRM framework.
			 *
			 * .detect is called by .fill_modes.
			 * .fill_modes is called by user mode ioctl
			 * DRM_IOCTL_MODE_GETCONNECTOR.
			 *
			 * .get_modes is called by .fill_modes.
			 *
			 * call .get_modes, AMDGPU DM implementation will create
			 * new dc_sink and add to dc_link. For long HPD plug
			 * in/out, MST has its own handle.
			 *
			 * Therefore, just after dc_create, link->sink is not
			 * created for MST until user mode app calls
			 * DRM_IOCTL_MODE_GETCONNECTOR.
			 *
			 * Need check ->sink usages in case ->sink = NULL
			 * TODO: s3 resume check
			 */
			if (reason == DETECT_REASON_BOOT)
				boot = true;

			dm_helpers_dp_update_branch_info(link->ctx, link);

			if (!dm_helpers_dp_mst_start_top_mgr(link->ctx,
							     link, boot)) {
				/* MST not supported */
				link->type = dc_connection_single;
				sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
			}
		}

		if (link->type != dc_connection_mst_branch &&
		    is_dp_branch_device(link)) {
				is_dp_branch_device(link))
			/* DP SST branch */
			link->type = dc_connection_sst_branch;
			if (!link->dpcd_caps.sink_count.bits.SINK_COUNT) {
				/*
				 * SST branch unplug processing for short irq
				 */
				link_disconnect_sink(link);
				return true;
			}

			if (is_dp_active_dongle(link) &&
				(link->dpcd_caps.dongle_type !=
					DISPLAY_DONGLE_DP_HDMI_CONVERTER))
				*converter_disable_audio = true;
		}
	} else {
		/* DP passive dongles */
		sink_caps->signal = dp_passive_dongle_detection(link->ddc,
@@ -893,7 +829,6 @@ static bool dc_link_detect_helper(struct dc_link *link,
	struct dc_sink *sink = NULL;
	struct dc_sink *prev_sink = NULL;
	struct dpcd_caps prev_dpcd_caps;
	bool same_dpcd = true;
	enum dc_connection_type new_connection_type = dc_connection_none;
	enum dc_connection_type pre_connection_type = dc_connection_none;
	bool perform_dp_seamless_boot = false;
@@ -984,35 +919,12 @@ static bool dc_link_detect_helper(struct dc_link *link,
					return false;
			}

			if (!detect_dp(link, &sink_caps,
				       &converter_disable_audio,
				       aud_support, reason)) {
			if (!detect_dp(link, &sink_caps, reason)) {
				if (prev_sink)
					dc_sink_release(prev_sink);
				return false;
			}

			// Check if dpcp block is the same
			if (prev_sink) {
				if (memcmp(&link->dpcd_caps, &prev_dpcd_caps,
					   sizeof(struct dpcd_caps)))
					same_dpcd = false;
			}
			/* Active SST downstream branch device unplug*/
			if (link->type == dc_connection_sst_branch &&
			    link->dpcd_caps.sink_count.bits.SINK_COUNT == 0) {
				if (prev_sink)
					/* Downstream unplug */
					dc_sink_release(prev_sink);
				return true;
			}

			// link switch from MST to non-MST stop topology manager
			if (pre_connection_type == dc_connection_mst_branch &&
				link->type != dc_connection_mst_branch) {
				dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
			}

			if (link->type == dc_connection_mst_branch) {
				LINK_INFO("link=%d, mst branch is now Connected\n",
					  link->link_index);
@@ -1023,11 +935,65 @@ static bool dc_link_detect_helper(struct dc_link *link,
				 */
				dp_verify_mst_link_cap(link);

				/*
				 * This call will initiate MST topology discovery. Which
				 * will detect MST ports and add new DRM connector DRM
				 * framework. Then read EDID via remote i2c over aux. In
				 * the end, will notify DRM detect result and save EDID
				 * into DRM framework.
				 *
				 * .detect is called by .fill_modes.
				 * .fill_modes is called by user mode ioctl
				 * DRM_IOCTL_MODE_GETCONNECTOR.
				 *
				 * .get_modes is called by .fill_modes.
				 *
				 * call .get_modes, AMDGPU DM implementation will create
				 * new dc_sink and add to dc_link. For long HPD plug
				 * in/out, MST has its own handle.
				 *
				 * Therefore, just after dc_create, link->sink is not
				 * created for MST until user mode app calls
				 * DRM_IOCTL_MODE_GETCONNECTOR.
				 *
				 * Need check ->sink usages in case ->sink = NULL
				 * TODO: s3 resume check
				 */

				dm_helpers_dp_update_branch_info(link->ctx, link);
				if (dm_helpers_dp_mst_start_top_mgr(link->ctx,
						link, reason == DETECT_REASON_BOOT)) {
					if (prev_sink)
						dc_sink_release(prev_sink);
					return false;
				} else {
					link->type = dc_connection_sst_branch;
					sink_caps.signal = SIGNAL_TYPE_DISPLAY_PORT;
				}
			}

			/* Active SST downstream branch device unplug*/
			if (link->type == dc_connection_sst_branch &&
			    link->dpcd_caps.sink_count.bits.SINK_COUNT == 0) {
				if (prev_sink)
					/* Downstream unplug */
					dc_sink_release(prev_sink);
				return true;
			}

			/* disable audio for non DP to HDMI active sst converter */
			if (link->type == dc_connection_sst_branch &&
					is_dp_active_dongle(link) &&
					(link->dpcd_caps.dongle_type !=
							DISPLAY_DONGLE_DP_HDMI_CONVERTER))
				converter_disable_audio = true;

			// link switch from MST to non-MST stop topology manager
			if (pre_connection_type == dc_connection_mst_branch &&
					link->type != dc_connection_mst_branch)
				dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);


			// For seamless boot, to skip verify link cap, we read UEFI settings and set them as verified.
			if (reason == DETECT_REASON_BOOT &&
					!dc_ctx->dc->config.power_down_display_on_boot &&
@@ -1214,11 +1180,11 @@ static bool dc_link_detect_helper(struct dc_link *link,
		link->dongle_max_pix_clk = 0;
	}

	LINK_INFO("link=%d, dc_sink_in=%p is now %s prev_sink=%p dpcd same=%d edid same=%d\n",
	LINK_INFO("link=%d, dc_sink_in=%p is now %s prev_sink=%p edid same=%d\n",
		  link->link_index, sink,
		  (sink_caps.signal ==
		   SIGNAL_TYPE_NONE ? "Disconnected" : "Connected"),
		  prev_sink, same_dpcd, same_edid);
		  prev_sink, same_edid);

	if (prev_sink)
		dc_sink_release(prev_sink);
+9 −1
Original line number Diff line number Diff line
@@ -42,7 +42,15 @@ enum {
	/* to avoid infinite loop where-in the receiver
	 * switches between different VS
	 */
	LINK_TRAINING_MAX_CR_RETRY = 100
	LINK_TRAINING_MAX_CR_RETRY = 100,
	/*
	 * Some receivers fail to train on first try and are good
	 * on subsequent tries. 2 retries should be plenty. If we
	 * don't have a successful training then we don't expect to
	 * ever get one.
	 */
	LINK_TRAINING_MAX_VERIFY_RETRY = 2,
	PEAK_FACTOR_X1000 = 1006,
};

bool dp_verify_link_cap(