Commit cf4cebce authored by Peichen Huang's avatar Peichen Huang Committed by Alex Deucher
Browse files

drm/amd/display: Restructure dpia link training



[WHY]
We intend to consolidate dp tunneling and conventional dp link training.

[HOW]
1. Use the same link training entry for both dp and dpia
2. Move SET_CONFIG of non-transparent mode to dmub side
3. Add set_tps_notification dmub_cmd to notify tps request for
   non-transparent dpia link training
4. Check dpcd request result and abort link training early if dpia
   aux tunneling fails
5. Add option to avoid affect old product
6. Separately handle wait_time_microsec for dpia

Reviewed-by: default avatarCruise Hung <cruise.hung@amd.com>
Reviewed-by: default avatarGeorge Shen <george.shen@amd.com>
Reviewed-by: default avatarMeenakshikumar Somasundaram <meenakshikumar.somasundaram@amd.com>
Signed-off-by: default avatarPeichen Huang <PeiChen.Huang@amd.com>
Signed-off-by: default avatarAlex Hung <alex.hung@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ae510080
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -5755,6 +5755,27 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
	return DC_OK;
}

/**
 * dc_process_dmub_dpia_set_tps_notification - Submits tps notification
 *
 * @dc: [in] dc structure
 * @link_index: [in] link index
 * @ts: [in] request tps
 *
 * Submits set_tps_notification command to dmub via inbox message
 */
void dc_process_dmub_dpia_set_tps_notification(const struct dc *dc, uint32_t link_index, uint8_t tps)
{
	union dmub_rb_cmd cmd = {0};

	cmd.set_tps_notification.header.type = DMUB_CMD__DPIA;
	cmd.set_tps_notification.header.sub_type = DMUB_CMD__DPIA_SET_TPS_NOTIFICATION;
	cmd.set_tps_notification.tps_notification.instance = dc->links[link_index]->ddc_hw_inst;
	cmd.set_tps_notification.tps_notification.tps = tps;

	dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}

/**
 * dc_process_dmub_dpia_hpd_int_enable - Submits DPIA DPD interruption
 *
+5 −1
Original line number Diff line number Diff line
@@ -462,6 +462,7 @@ struct dc_config {
	bool support_edp0_on_dp1;
	unsigned int enable_fpo_flicker_detection;
	bool disable_hbr_audio_dp2;
	bool consolidated_dpia_dp_lt;
};

enum visual_confirm {
@@ -762,7 +763,8 @@ union dpia_debug_options {
		uint32_t disable_mst_dsc_work_around:1; /* bit 3 */
		uint32_t enable_force_tbt3_work_around:1; /* bit 4 */
		uint32_t disable_usb4_pm_support:1; /* bit 5 */
		uint32_t reserved:26;
		uint32_t enable_consolidated_dpia_dp_lt:1; /* bit 6 */
		uint32_t reserved:25;
	} bits;
	uint32_t raw;
};
@@ -2525,6 +2527,8 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
				uint8_t mst_alloc_slots,
				uint8_t *mst_slots_in_use);

void dc_process_dmub_dpia_set_tps_notification(const struct dc *dc, uint32_t link_index, uint8_t tps);

void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc,
				uint32_t hpd_int_enable);

+27 −4
Original line number Diff line number Diff line
@@ -50,10 +50,33 @@ static void update_dpia_stream_allocation_table(struct dc_link *link,
	DC_LOG_MST("dpia : status[%d]: alloc_slots[%d]: used_slots[%d]\n",
			status, mst_alloc_slots, prev_mst_slots_in_use);

	ASSERT(link_enc);
	if (link_enc)
		link_enc->funcs->update_mst_stream_allocation_table(link_enc, table);
}

static void set_dio_dpia_link_test_pattern(struct dc_link *link,
		const struct link_resource *link_res,
		struct encoder_set_dp_phy_pattern_param *tp_params)
{
	if (tp_params->dp_phy_pattern != DP_TEST_PATTERN_VIDEO_MODE)
		return;

	struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link);

	if (!link_enc)
		return;

	link_enc->funcs->dp_set_phy_pattern(link_enc, tp_params);
	link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
}

static void set_dio_dpia_lane_settings(struct dc_link *link,
		const struct link_resource *link_res,
		const struct dc_link_settings *link_settings,
		const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
{
}

static const struct link_hwss dpia_link_hwss = {
	.setup_stream_encoder = setup_dio_stream_encoder,
	.reset_stream_encoder = reset_dio_stream_encoder,
@@ -65,8 +88,8 @@ static const struct link_hwss dpia_link_hwss = {
	.ext = {
		.set_throttled_vcp_size = set_dio_throttled_vcp_size,
		.enable_dp_link_output = enable_dio_dp_link_output,
		.set_dp_link_test_pattern = set_dio_dp_link_test_pattern,
		.set_dp_lane_settings = set_dio_dp_lane_settings,
		.set_dp_link_test_pattern = set_dio_dpia_link_test_pattern,
		.set_dp_lane_settings = set_dio_dpia_lane_settings,
		.update_stream_allocation_table = update_dpia_stream_allocation_table,
	},
};
+71 −9
Original line number Diff line number Diff line
@@ -515,6 +515,41 @@ bool dp_is_interlane_aligned(union lane_align_status_updated align_status)
	return align_status.bits.INTERLANE_ALIGN_DONE == 1;
}

bool dp_check_interlane_aligned(union lane_align_status_updated align_status,
		struct dc_link *link,
		uint8_t retries)
{
	/* Take into consideration corner case for DP 1.4a LL Compliance CTS as USB4
	 * has to share encoders unlike DP and USBC
	 */
	return (dp_is_interlane_aligned(align_status) ||
			(link->skip_fallback_on_link_loss && retries));
}

uint32_t dp_get_eq_aux_rd_interval(
		const struct dc_link *link,
		const struct link_training_settings *lt_settings,
		uint32_t offset,
		uint8_t retries)
{
	if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
		if (offset == 0 && retries == 1 && lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
			return max(lt_settings->eq_pattern_time, (uint32_t) DPIA_CLK_SYNC_DELAY);
		else
			return dpia_get_eq_aux_rd_interval(link, lt_settings, offset);
	} else if (is_repeater(lt_settings, offset))
		return dp_translate_training_aux_read_interval(
				link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]);
	else
		return lt_settings->eq_pattern_time;
}

bool dp_check_dpcd_reqeust_status(const struct dc_link *link,
		enum dc_status status)
{
	return (status != DC_OK && link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA);
}

enum link_training_result dp_check_link_loss_status(
	struct dc_link *link,
	const struct link_training_settings *link_training_setting)
@@ -973,13 +1008,17 @@ void repeater_training_done(struct dc_link *link, uint32_t offset)
		dpcd_pattern.v1_4.TRAINING_PATTERN_SET);
}

static void dpcd_exit_training_mode(struct dc_link *link, enum dp_link_encoding encoding)
static enum link_training_result dpcd_exit_training_mode(struct dc_link *link, enum dp_link_encoding encoding)
{
	enum dc_status status;
	uint8_t sink_status = 0;
	uint8_t i;

	/* clear training pattern set */
	dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE);
	status = dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE);

	if (dp_check_dpcd_reqeust_status(link, status))
		return LINK_TRAINING_ABORT;

	if (encoding == DP_128b_132b_ENCODING) {
		/* poll for intra-hop disable */
@@ -990,6 +1029,8 @@ static void dpcd_exit_training_mode(struct dc_link *link, enum dp_link_encoding
			fsleep(1000);
		}
	}

	return LINK_TRAINING_SUCCESS;
}

enum dc_status dpcd_configure_channel_coding(struct dc_link *link,
@@ -1013,17 +1054,18 @@ enum dc_status dpcd_configure_channel_coding(struct dc_link *link,
	return status;
}

void dpcd_set_training_pattern(
enum dc_status dpcd_set_training_pattern(
	struct dc_link *link,
	enum dc_dp_training_pattern training_pattern)
{
	enum dc_status status;
	union dpcd_training_pattern dpcd_pattern = {0};

	dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
			dp_training_pattern_to_dpcd_training_pattern(
					link, training_pattern);

	core_link_write_dpcd(
	status = core_link_write_dpcd(
		link,
		DP_TRAINING_PATTERN_SET,
		&dpcd_pattern.raw,
@@ -1033,6 +1075,8 @@ void dpcd_set_training_pattern(
		__func__,
		DP_TRAINING_PATTERN_SET,
		dpcd_pattern.v1_4.TRAINING_PATTERN_SET);

	return status;
}

enum dc_status dpcd_set_link_settings(
@@ -1185,6 +1229,13 @@ void dpcd_set_lt_pattern_and_lane_settings(
	dpcd_lt_buffer[DP_TRAINING_PATTERN_SET - DP_TRAINING_PATTERN_SET]
		= dpcd_pattern.raw;

	if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
		dpia_set_tps_notification(
			link,
			lt_settings,
			dpcd_pattern.v1_4.TRAINING_PATTERN_SET,
			offset);

	if (is_repeater(lt_settings, offset)) {
		DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n 0x%X pattern = %x\n",
			__func__,
@@ -1455,6 +1506,7 @@ static enum link_training_result dp_transition_to_video_idle(
		 */
		if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) {
			msleep(5);
			if (!link->skip_fallback_on_link_loss)
				status = dp_check_link_loss_status(link, lt_settings);
		}
		return status;
@@ -1521,7 +1573,9 @@ enum link_training_result dp_perform_link_training(
		ASSERT(0);

	/* exit training mode */
	dpcd_exit_training_mode(link, encoding);
	if ((dpcd_exit_training_mode(link, encoding) != LINK_TRAINING_SUCCESS || status == LINK_TRAINING_ABORT) &&
			link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
		dpia_training_abort(link, &lt_settings, 0);

	/* switch to video idle */
	if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern)
@@ -1599,8 +1653,7 @@ bool perform_link_training_with_retries(
			dp_perform_link_training_skip_aux(link, &pipe_ctx->link_res, &cur_link_settings);
			return true;
		} else {
			/** @todo Consolidate USB4 DP and DPx.x training. */
			if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
			if (!link->dc->config.consolidated_dpia_dp_lt && link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
				status = dpia_perform_link_training(
						link,
						&pipe_ctx->link_res,
@@ -1629,9 +1682,18 @@ bool perform_link_training_with_retries(
			dp_trace_lt_total_count_increment(link, false);
			dp_trace_lt_result_update(link, status, false);
			dp_trace_set_lt_end_timestamp(link, false);
			if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low)
			if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low) {
				// Update verified link settings to current one
				// Because DPIA LT might fallback to lower link setting.
				if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA &&
						stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
					link->verified_link_cap.link_rate = link->cur_link_settings.link_rate;
					link->verified_link_cap.lane_count = link->cur_link_settings.lane_count;
					dm_helpers_dp_mst_update_branch_bandwidth(link->ctx, link);
				}
				return true;
			}
		}

		fail_count++;
		dp_trace_lt_fail_count_update(link, fail_count, false);
+15 −1
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ void dp_set_hw_test_pattern(
		uint8_t *custom_pattern,
		uint32_t custom_pattern_size);

void dpcd_set_training_pattern(
enum dc_status dpcd_set_training_pattern(
	struct dc_link *link,
	enum dc_dp_training_pattern training_pattern);

@@ -182,4 +182,18 @@ uint32_t dp_translate_training_aux_read_interval(

uint8_t dp_get_nibble_at_index(const uint8_t *buf,
	uint32_t index);

bool dp_check_interlane_aligned(union lane_align_status_updated align_status,
		struct dc_link *link,
		uint8_t retries);

uint32_t dp_get_eq_aux_rd_interval(
		const struct dc_link *link,
		const struct link_training_settings *lt_settings,
		uint32_t offset,
		uint8_t retries);

bool dp_check_dpcd_reqeust_status(const struct dc_link *link,
		enum dc_status status);

#endif /* __DC_LINK_DP_TRAINING_H__ */
Loading