Commit 7f7652ee authored by Martin Leung's avatar Martin Leung Committed by Alex Deucher
Browse files

drm/amd/display: enable single dp seamless boot



[why]
seamless boot didn't work for non edp's before

[how]
removed edp-specific code, made dp read uefi-set link settings. Also fixed
a hubbub code line to be consistent with usage of function.

Signed-off-by: default avatarMartin Leung <martin.leung@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarAnthony Koo <Anthony.Koo@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c84ad0d6
Loading
Loading
Loading
Loading
+17 −13
Original line number Diff line number Diff line
@@ -974,29 +974,33 @@ bool dc_validate_seamless_boot_timing(const struct dc *dc,
{
	struct timing_generator *tg;
	struct dc_link *link = sink->link;
	unsigned int enc_inst, tg_inst;
	unsigned int enc_inst, tg_inst, i;

	// Seamless port only support single DP and EDP so far
	if (sink->sink_signal != SIGNAL_TYPE_DISPLAY_PORT &&
		sink->sink_signal != SIGNAL_TYPE_EDP)
		return false;

	/* Check for enabled DIG to identify enabled display */
	if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
		return false;

	/* Check for which front end is used by this encoder.
	 * Note the inst is 1 indexed, where 0 is undefined.
	 * Note that DIG_FE can source from different OTG but our
	 * current implementation always map 1-to-1, so this code makes
	 * the same assumption and doesn't check OTG source.
	 */
	enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);

	/* Instance should be within the range of the pool */
	if (enc_inst >= dc->res_pool->pipe_count)
	if (enc_inst == ENGINE_ID_UNKNOWN)
		return false;

	if (enc_inst >= dc->res_pool->stream_enc_count)
		return false;
	for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
		if (dc->res_pool->stream_enc[i]->id == enc_inst) {
			tg_inst = dc->res_pool->stream_enc[i]->funcs->dig_source_otg(
				dc->res_pool->stream_enc[i]);
			break;
		}
	}

	tg_inst = dc->res_pool->stream_enc[enc_inst]->funcs->dig_source_otg(
		dc->res_pool->stream_enc[enc_inst]);
	// tg_inst not found
	if (i == dc->res_pool->stream_enc_count)
		return false;

	if (tg_inst >= dc->res_pool->timing_generator_count)
		return false;
+38 −19
Original line number Diff line number Diff line
@@ -519,7 +519,7 @@ static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *lin
}


static void read_edp_current_link_settings_on_detect(struct dc_link *link)
static void read_current_link_settings_on_detect(struct dc_link *link)
{
	union lane_count_set lane_count_set = { {0} };
	uint8_t link_bw_set;
@@ -554,18 +554,24 @@ static void read_edp_current_link_settings_on_detect(struct dc_link *link)
			&link_bw_set, sizeof(link_bw_set));

	if (link_bw_set == 0) {
		if (link->connector_signal == SIGNAL_TYPE_EDP) {
			/* If standard link rates are not being used,
		 * Read DPCD 00115h to find the link rate set used
			 * Read DPCD 00115h to find the edp link rate set used
			 */
			core_link_read_dpcd(link, DP_LINK_RATE_SET,
					&link_rate_set, sizeof(link_rate_set));

			// edp_supported_link_rates_count = 0 for DP
			if (link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
				link->cur_link_settings.link_rate =
						link->dpcd_caps.edp_supported_link_rates[link_rate_set];
				link->cur_link_settings.link_rate_set = link_rate_set;
				link->cur_link_settings.use_link_rate_set = true;
			}
		} else {
			// Link Rate not found. Seamless boot may not work.
			ASSERT(false);
		}
	} else {
		link->cur_link_settings.link_rate = link_bw_set;
		link->cur_link_settings.use_link_rate_set = false;
@@ -752,6 +758,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
	struct dpcd_caps prev_dpcd_caps;
	bool same_dpcd = true;
	enum dc_connection_type new_connection_type = dc_connection_none;
	bool perform_dp_seamless_boot = false;
	DC_LOGGER_INIT(link->ctx->logger);

	if (dc_is_virtual_signal(link->connector_signal))
@@ -808,15 +815,15 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
		}

		case SIGNAL_TYPE_EDP: {
			read_edp_current_link_settings_on_detect(link);
			read_current_link_settings_on_detect(link);
			detect_edp_sink_caps(link);
			sink_caps.transaction_type =
				DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
			sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
			sink_caps.signal = SIGNAL_TYPE_EDP;
			break;
		}

		case SIGNAL_TYPE_DISPLAY_PORT: {

			/* wa HPD high coming too early*/
			if (link->link_enc->features.flags.bits.DP_IS_USB_C == 1) {

@@ -870,6 +877,17 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
				return false;
			}

			// 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 == false &&
					link->link_status.link_active == true)
				perform_dp_seamless_boot = true;

			if (perform_dp_seamless_boot) {
				read_current_link_settings_on_detect(link);
				link->verified_link_cap = link->reported_link_cap;
			}

			break;
		}

@@ -954,7 +972,8 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
			 *  two link trainings
			 */

			/* deal with non-mst cases */
			// verify link cap for SST non-seamless boot
			if (!perform_dp_seamless_boot)
				dp_verify_link_cap_with_retries(link,
						&link->reported_link_cap,
						LINK_TRAINING_MAX_VERIFY_RETRY);
+13 −13
Original line number Diff line number Diff line
@@ -1848,28 +1848,28 @@ static int acquire_resource_from_hw_enabled_state(
		struct dc_stream_state *stream)
{
	struct dc_link *link = stream->link;
	unsigned int inst, tg_inst;
	unsigned int inst, tg_inst, i;

	/* Check for enabled DIG to identify enabled display */
	if (!link->link_enc->funcs->is_dig_enabled(link->link_enc))
		return -1;

	/* Check for which front end is used by this encoder.
	 * Note the inst is 1 indexed, where 0 is undefined.
	 * Note that DIG_FE can source from different OTG but our
	 * current implementation always map 1-to-1, so this code makes
	 * the same assumption and doesn't check OTG source.
	 */
	inst = link->link_enc->funcs->get_dig_frontend(link->link_enc);

	/* Instance should be within the range of the pool */
	if (inst >= pool->pipe_count)
		return -1;
	if (inst == ENGINE_ID_UNKNOWN)
		return false;

	if (inst >= pool->stream_enc_count)
		return -1;
	for (i = 0; i < pool->stream_enc_count; i++) {
		if (pool->stream_enc[i]->id == inst) {
			tg_inst = pool->stream_enc[i]->funcs->dig_source_otg(
				pool->stream_enc[i]);
			break;
		}
	}

	tg_inst = pool->stream_enc[inst]->funcs->dig_source_otg(pool->stream_enc[inst]);
	// tg_inst not found
	if (i == pool->stream_enc_count)
		return false;

	if (tg_inst >= pool->timing_generator_count)
		return false;
+3 −2
Original line number Diff line number Diff line
@@ -588,7 +588,7 @@ static void hubbub2_program_watermarks(
			DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
	REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 180);

	hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
	hubbub->funcs->allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
}

static const struct hubbub_funcs hubbub2_funcs = {
@@ -600,7 +600,8 @@ static const struct hubbub_funcs hubbub2_funcs = {
	.get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,
	.wm_read_state = hubbub2_wm_read_state,
	.get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
	.program_watermarks = hubbub2_program_watermarks
	.program_watermarks = hubbub2_program_watermarks,
	.allow_self_refresh_control = hubbub1_allow_self_refresh_control
};

void hubbub2_construct(struct dcn20_hubbub *hubbub,