Commit ebd1e719 authored by Leo (Hanghong) Ma's avatar Leo (Hanghong) Ma Committed by Alex Deucher
Browse files

drm/amd/display: Add helper for blanking all dp displays



[Why & How]
1. The code to blank all dp display have been called many times,
so add helpers in dc_link to make it more concise.
2. Add some check to fix the dmesg errors at boot and resume from S3
on dcn3.1 during DQE's promotion test.

Reviewed-by: default avatarAlvin Lee <alvin.lee2@amd.com>
Reviewed-by: default avatarWesley Chalmers <Wesley.Chalmers@amd.com>
Reviewed-by: default avatarAric Cyr <Aric.Cyr@amd.com>
Acked-by: default avatarAnson Jacob <Anson.Jacob@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarLeo (Hanghong) Ma <hanghong.ma@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b97788e5
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
@@ -1999,6 +1999,57 @@ static enum dc_status enable_link_dp_mst(
	return enable_link_dp(state, pipe_ctx);
}

void dc_link_blank_all_dp_displays(struct dc *dc)
{
	unsigned int i;
	uint8_t dpcd_power_state = '\0';
	enum dc_status status = DC_ERROR_UNEXPECTED;

	for (i = 0; i < dc->link_count; i++) {
		if ((dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) ||
			(dc->links[i]->priv == NULL) || (dc->links[i]->local_sink == NULL))
			continue;

		/* DP 2.0 spec requires that we read LTTPR caps first */
		dp_retrieve_lttpr_cap(dc->links[i]);
		/* if any of the displays are lit up turn them off */
		status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,
							&dpcd_power_state, sizeof(dpcd_power_state));

		if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0)
			dc_link_blank_dp_stream(dc->links[i], true);
	}

}

void dc_link_blank_dp_stream(struct dc_link *link, bool hw_init)
{
	unsigned int j;
	struct dc  *dc = link->ctx->dc;
	enum signal_type signal = link->connector_signal;

	if ((signal == SIGNAL_TYPE_EDP) ||
		(signal == SIGNAL_TYPE_DISPLAY_PORT)) {
		if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
			link->link_enc->funcs->get_dig_frontend &&
			link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
			unsigned int fe = link->link_enc->funcs->get_dig_frontend(link->link_enc);

			if (fe != ENGINE_ID_UNKNOWN)
				for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
					if (fe == dc->res_pool->stream_enc[j]->id) {
						dc->res_pool->stream_enc[j]->funcs->dp_blank(link,
									dc->res_pool->stream_enc[j]);
						break;
					}
				}
		}

		if ((!link->wa_flags.dp_keep_receiver_powered) || hw_init)
			dp_receiver_power_ctrl(link, false);
	}
}

static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx,
		enum engine_id eng_id,
		struct ext_hdmi_settings *settings)
+4 −0
Original line number Diff line number Diff line
@@ -287,6 +287,10 @@ bool dc_link_setup_psr(struct dc_link *dc_link,

void dc_link_get_psr_residency(const struct dc_link *link, uint32_t *residency);

void dc_link_blank_all_dp_displays(struct dc *dc);

void dc_link_blank_dp_stream(struct dc_link *link, bool hw_init);

/* Request DC to detect if there is a Panel connected.
 * boot - If this call is during initial boot.
 * Return false for any type of detection failure or MST detection
+2 −20
Original line number Diff line number Diff line
@@ -1655,30 +1655,12 @@ static enum dc_status apply_single_controller_ctx_to_hw(

static void power_down_encoders(struct dc *dc)
{
	int i, j;
	int i;

	for (i = 0; i < dc->link_count; i++) {
		enum signal_type signal = dc->links[i]->connector_signal;

		if ((signal == SIGNAL_TYPE_EDP) ||
			(signal == SIGNAL_TYPE_DISPLAY_PORT)) {
			if (dc->links[i]->link_enc->funcs->get_dig_frontend &&
				dc->links[i]->link_enc->funcs->is_dig_enabled(dc->links[i]->link_enc)) {
				unsigned int fe = dc->links[i]->link_enc->funcs->get_dig_frontend(
									dc->links[i]->link_enc);

				for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
					if (fe == dc->res_pool->stream_enc[j]->id) {
						dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i],
									dc->res_pool->stream_enc[j]);
						break;
					}
				}
			}

			if (!dc->links[i]->wa_flags.dp_keep_receiver_powered)
				dp_receiver_power_ctrl(dc->links[i], false);
		}
		dc_link_blank_dp_stream(dc->links[i], false);

		if (signal != SIGNAL_TYPE_EDP)
			signal = SIGNAL_TYPE_NONE;
+3 −38
Original line number Diff line number Diff line
@@ -1366,7 +1366,7 @@ void dcn10_init_pipes(struct dc *dc, struct dc_state *context)

void dcn10_init_hw(struct dc *dc)
{
	int i, j;
	int i;
	struct abm *abm = dc->res_pool->abm;
	struct dmcu *dmcu = dc->res_pool->dmcu;
	struct dce_hwseq *hws = dc->hwseq;
@@ -1468,43 +1468,8 @@ void dcn10_init_hw(struct dc *dc)
		dmub_enable_outbox_notification(dc);

	/* we want to turn off all dp displays before doing detection */
	if (dc->config.power_down_display_on_boot) {
		uint8_t dpcd_power_state = '\0';
		enum dc_status status = DC_ERROR_UNEXPECTED;

		for (i = 0; i < dc->link_count; i++) {
			if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)
				continue;

			/* DP 2.0 requires that LTTPR Caps be read first */
			dp_retrieve_lttpr_cap(dc->links[i]);

			/*
			 * If any of the displays are lit up turn them off.
			 * The reason is that some MST hubs cannot be turned off
			 * completely until we tell them to do so.
			 * If not turned off, then displays connected to MST hub
			 * won't light up.
			 */
			status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,
							&dpcd_power_state, sizeof(dpcd_power_state));
			if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) {
				/* blank dp stream before power off receiver*/
				if (dc->links[i]->link_enc->funcs->get_dig_frontend) {
					unsigned int fe = dc->links[i]->link_enc->funcs->get_dig_frontend(dc->links[i]->link_enc);

					for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
						if (fe == dc->res_pool->stream_enc[j]->id) {
							dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i],
										dc->res_pool->stream_enc[j]);
							break;
						}
					}
				}
				dp_receiver_power_ctrl(dc->links[i], false);
			}
		}
	}
	if (dc->config.power_down_display_on_boot)
		dc_link_blank_all_dp_displays(dc);

	/* If taking control over from VBIOS, we may want to optimize our first
	 * mode set, so we need to skip powering down pipes until we know which
+3 −36
Original line number Diff line number Diff line
@@ -437,7 +437,7 @@ void dcn30_init_hw(struct dc *dc)
	struct dce_hwseq *hws = dc->hwseq;
	struct dc_bios *dcb = dc->ctx->dc_bios;
	struct resource_pool *res_pool = dc->res_pool;
	int i, j;
	int i;
	int edp_num;
	uint32_t backlight = MAX_BACKLIGHT_LEVEL;

@@ -534,41 +534,8 @@ void dcn30_init_hw(struct dc *dc)
			hws->funcs.dsc_pg_control(hws, res_pool->dscs[i]->inst, false);

	/* we want to turn off all dp displays before doing detection */
	if (dc->config.power_down_display_on_boot) {
		uint8_t dpcd_power_state = '\0';
		enum dc_status status = DC_ERROR_UNEXPECTED;

		for (i = 0; i < dc->link_count; i++) {
			if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)
				continue;
			/* DP 2.0 states that LTTPR regs must be read first */
			dp_retrieve_lttpr_cap(dc->links[i]);

			/* if any of the displays are lit up turn them off */
			status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,
						     &dpcd_power_state, sizeof(dpcd_power_state));
			if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) {
				/* blank dp stream before power off receiver*/
				if (dc->links[i]->link_enc->funcs->get_dig_frontend) {
					unsigned int fe;

					fe = dc->links[i]->link_enc->funcs->get_dig_frontend(
										dc->links[i]->link_enc);
					if (fe == ENGINE_ID_UNKNOWN)
						continue;

					for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
						if (fe == dc->res_pool->stream_enc[j]->id) {
							dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i],
										dc->res_pool->stream_enc[j]);
							break;
						}
					}
				}
				dp_receiver_power_ctrl(dc->links[i], false);
			}
		}
	}
	if (dc->config.power_down_display_on_boot)
		dc_link_blank_all_dp_displays(dc);

	/* If taking control over from VBIOS, we may want to optimize our first
	 * mode set, so we need to skip powering down pipes until we know which
Loading