Blob Blame History Raw
From: Sylvia Tsai <sylvia.tsai@amd.com>
Date: Fri, 21 Apr 2017 15:29:55 -0400
Subject: drm/amd/display: PSR Refactor
Git-commit: 94267b3df7ee00f21fa0ff7d618ca7e0574db5ed
Patch-mainline: v4.15-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

- Refacotr PSR to follow correct module pattern
- fix eDP only working on sink index 0.

Signed-off-by: Sylvia Tsai <sylvia.tsai@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c                        |   74 +++-------
 drivers/gpu/drm/amd/display/dc/core/dc_link.c                   |   22 +-
 drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c                |   53 -------
 drivers/gpu/drm/amd/display/dc/core/dc_resource.c               |    2 
 drivers/gpu/drm/amd/display/dc/dc.h                             |   17 +-
 drivers/gpu/drm/amd/display/dc/dc_types.h                       |   24 +--
 drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c     |   18 ++
 drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c |   16 --
 drivers/gpu/drm/amd/display/dc/inc/core_types.h                 |    1 
 drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h               |    2 
 drivers/gpu/drm/amd/display/modules/freesync/freesync.c         |   14 +
 11 files changed, 93 insertions(+), 150 deletions(-)

--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -199,6 +199,32 @@ static bool set_gamut_remap(struct dc *d
 	return ret;
 }
 
+static void set_static_screen_events(struct dc *dc,
+		const struct dc_stream **stream,
+		int num_streams,
+		const struct dc_static_screen_events *events)
+{
+	struct core_dc *core_dc = DC_TO_CORE(dc);
+	int i = 0;
+	int j = 0;
+	struct pipe_ctx *pipes_affected[MAX_PIPES];
+	int num_pipes_affected = 0;
+
+	for (i = 0; i < num_streams; i++) {
+		struct core_stream *core_stream = DC_STREAM_TO_CORE(stream[i]);
+
+		for (j = 0; j < MAX_PIPES; j++) {
+			if (core_dc->current_context->res_ctx.pipe_ctx[j].stream
+					== core_stream) {
+				pipes_affected[num_pipes_affected++] =
+						&core_dc->current_context->res_ctx.pipe_ctx[j];
+			}
+		}
+	}
+
+	core_dc->hwss.set_static_screen_control(pipes_affected, num_pipes_affected, events);
+}
+
 /* This function is not expected to fail, proper implementation of
  * validation will prevent this from ever being called for unsupported
  * configurations.
@@ -240,45 +266,6 @@ static void stream_update_scaling(
 	}
 }
 
-static bool set_psr_enable(struct dc *dc, bool enable)
-{
-	struct core_dc *core_dc = DC_TO_CORE(dc);
-	int i;
-
-	for (i = 0; i < core_dc->link_count; i++)
-		dc_link_set_psr_enable(&core_dc->links[i]->public,
-				enable);
-
-	return true;
-}
-
-
-static bool setup_psr(struct dc *dc, const struct dc_stream *stream)
-{
-	struct core_dc *core_dc = DC_TO_CORE(dc);
-	struct core_stream *core_stream = DC_STREAM_TO_CORE(stream);
-	struct pipe_ctx *pipes;
-	int i;
-	unsigned int underlay_idx = core_dc->res_pool->underlay_pipe_index;
-
-	for (i = 0; i < core_dc->link_count; i++) {
-		if (core_stream->sink->link == core_dc->links[i])
-			dc_link_setup_psr(&core_dc->links[i]->public,
-					stream);
-	}
-
-	for (i = 0; i < MAX_PIPES; i++) {
-		if (core_dc->current_context->res_ctx.pipe_ctx[i].stream
-				== core_stream && i != underlay_idx) {
-			pipes = &core_dc->current_context->res_ctx.pipe_ctx[i];
-			core_dc->hwss.set_static_screen_control(&pipes, 1,
-					0x182);
-		}
-	}
-
-	return true;
-}
-
 static void set_drive_settings(struct dc *dc,
 		struct link_training_settings *lt_settings,
 		const struct dc_link *link)
@@ -359,15 +346,12 @@ static void allocate_dc_stream_funcs(str
 				stream_adjust_vmin_vmax;
 	}
 
+	core_dc->public.stream_funcs.set_static_screen_events =
+			set_static_screen_events;
+
 	core_dc->public.stream_funcs.set_gamut_remap =
 			set_gamut_remap;
 
-	core_dc->public.stream_funcs.set_psr_enable =
-			set_psr_enable;
-
-	core_dc->public.stream_funcs.setup_psr =
-			setup_psr;
-
 	core_dc->public.link_funcs.set_drive_settings =
 			set_drive_settings;
 
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -1430,14 +1430,14 @@ bool dc_link_set_psr_enable(const struct
 	struct core_dc *core_dc = DC_TO_CORE(ctx->dc);
 	struct dmcu *dmcu = core_dc->res_pool->dmcu;
 
-	if (dmcu != NULL && dc_link->psr_caps.psr_version > 0)
+	if (dmcu != NULL && link->psr_enabled)
 		dmcu->funcs->set_psr_enable(dmcu, enable);
 
 	return true;
 }
 
 bool dc_link_setup_psr(const struct dc_link *dc_link,
-		const struct dc_stream *stream)
+		const struct dc_stream *stream, struct psr_config *psr_config)
 {
 	struct core_link *link = DC_LINK_TO_CORE(dc_link);
 	struct dc_context *ctx = link->ctx;
@@ -1449,10 +1449,8 @@ bool dc_link_setup_psr(const struct dc_l
 
 	psr_context.controllerId = CONTROLLER_ID_UNDEFINED;
 
-
 	if (dc_link != NULL &&
-		dmcu != NULL &&
-		dc_link->psr_caps.psr_version > 0) {
+		dmcu != NULL) {
 		/* updateSinkPsrDpcdConfig*/
 		union dpcd_psr_configuration psr_configuration;
 
@@ -1461,10 +1459,10 @@ bool dc_link_setup_psr(const struct dc_l
 		psr_configuration.bits.ENABLE                    = 1;
 		psr_configuration.bits.CRC_VERIFICATION          = 1;
 		psr_configuration.bits.FRAME_CAPTURE_INDICATION  =
-			dc_link->psr_caps.psr_frame_capture_indication_req;
+				psr_config->psr_frame_capture_indication_req;
 
 		/* Check for PSR v2*/
-		if (dc_link->psr_caps.psr_version == 0x2) {
+		if (psr_config->psr_version == 0x2) {
 			/* For PSR v2 selective update.
 			 * Indicates whether sink should start capturing
 			 * immediately following active scan line,
@@ -1512,14 +1510,13 @@ bool dc_link_setup_psr(const struct dc_l
 						stream->timing.v_total),
 						stream->timing.h_total);
 
-		psr_context.psrSupportedDisplayConfig =
-			(dc_link->psr_caps.psr_version > 0) ? true : false;
+		psr_context.psrSupportedDisplayConfig = true;
 		psr_context.psrExitLinkTrainingRequired =
-			dc_link->psr_caps.psr_exit_link_training_required;
+			psr_config->psr_exit_link_training_required;
 		psr_context.sdpTransmitLineNumDeadline =
-			dc_link->psr_caps.psr_sdp_transmit_line_num_deadline;
+			psr_config->psr_sdp_transmit_line_num_deadline;
 		psr_context.psrFrameCaptureIndicationReq =
-			dc_link->psr_caps.psr_frame_capture_indication_req;
+			psr_config->psr_frame_capture_indication_req;
 
 		psr_context.skipPsrWaitForPllLock = 0; /* only = 1 in KV */
 
@@ -1550,6 +1547,7 @@ bool dc_link_setup_psr(const struct dc_l
 		 */
 		psr_context.frame_delay = 0;
 
+		link->psr_enabled = true;
 		dmcu->funcs->setup_psr(dmcu, link, &psr_context);
 		return true;
 	} else
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -1478,7 +1478,7 @@ static bool handle_hpd_irq_psr_sink(cons
 {
 	union dpcd_psr_configuration psr_configuration;
 
-	if (link->public.psr_caps.psr_version == 0)
+	if (!link->psr_enabled)
 		return false;
 
 	dm_helpers_dp_read_dpcd(
@@ -2060,36 +2060,6 @@ static void dp_wa_power_up_0010FA(struct
 		link->wa_flags.dp_keep_receiver_powered = false;
 }
 
-static void retrieve_psr_link_cap(struct core_link *link,
-		enum edp_revision edp_revision)
-{
-	if (edp_revision >= EDP_REVISION_13) {
-		core_link_read_dpcd(link,
-				DP_PSR_SUPPORT,
-				(uint8_t *)(&link->public.psr_caps),
-				sizeof(link->public.psr_caps));
-		if (link->public.psr_caps.psr_version != 0) {
-			unsigned char psr_capability = 0;
-
-			core_link_read_dpcd(link,
-					    DP_PSR_CAPS,
-						&psr_capability,
-						sizeof(psr_capability));
-			/* Bit 0 determines whether fast link training is
-			 * required on PSR exit. If set to 0, link training
-			 * is required. If set to 1, sink must lock within
-			 * five Idle Patterns after Main Link is turned on.
-			 */
-			link->public.psr_caps.psr_exit_link_training_required
-						= !(psr_capability & 0x1);
-
-			psr_capability = (psr_capability >> 1) & 0x7;
-			link->public.psr_caps.psr_rfb_setup_time =
-					55 * (6 - psr_capability);
-		}
-	}
-}
-
 static void retrieve_link_cap(struct core_link *link)
 {
 	uint8_t dpcd_data[DP_TRAINING_AUX_RD_INTERVAL - DP_DPCD_REV + 1];
@@ -2157,38 +2127,17 @@ static void retrieve_link_cap(struct cor
 	link->dpcd_caps.panel_mode_edp =
 		edp_config_cap.bits.ALT_SCRAMBLER_RESET;
 
-	link->edp_revision = EDP_REVISION_11;
-
 	link->public.test_pattern_enabled = false;
 	link->public.compliance_test_state.raw = 0;
 
-	link->public.psr_caps.psr_exit_link_training_required = false;
-	link->public.psr_caps.psr_frame_capture_indication_req = false;
-	link->public.psr_caps.psr_rfb_setup_time = 0;
-	link->public.psr_caps.psr_sdp_transmit_line_num_deadline = 0;
-	link->public.psr_caps.psr_version = 0;
-
 	/* read sink count */
 	core_link_read_dpcd(link,
 			DP_SINK_COUNT,
 			&link->dpcd_caps.sink_count.raw,
 			sizeof(link->dpcd_caps.sink_count.raw));
 
-	/* Display control registers starting at DPCD 700h are only valid and
-	 * enabled if this eDP config cap bit is set. */
-	if (edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE) {
-		/* Read the Panel's eDP revision at DPCD 700h. */
-		core_link_read_dpcd(link,
-			DP_EDP_DPCD_REV,
-			(uint8_t *)(&link->edp_revision),
-			sizeof(link->edp_revision));
-	}
-
 	/* Connectivity log: detection */
 	CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ");
-
-	/* TODO: Confirm if need retrieve_psr_link_cap */
-	retrieve_psr_link_cap(link, link->edp_revision);
 }
 
 void detect_dp_sink_caps(struct core_link *link)
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -2015,7 +2015,7 @@ static void set_vsc_info_packet(
 	unsigned int vscPacketRevision = 0;
 	unsigned int i;
 
-	if (stream->sink->link->public.psr_caps.psr_version != 0) {
+	if (stream->sink->link->psr_enabled) {
 		vscPacketRevision = 2;
 	}
 
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -82,6 +82,12 @@ struct dc_surface_dcc_cap {
 	};
 };
 
+struct dc_static_screen_events {
+	bool cursor_update;
+	bool surface_update;
+	bool overlay_update;
+};
+
 /* Forward declaration*/
 struct dc;
 struct dc_surface;
@@ -102,10 +108,14 @@ struct dc_stream_funcs {
 			const struct dc_stream *dc_stream,
 			const struct rect *src,
 			const struct rect *dst);
+
 	bool (*set_gamut_remap)(struct dc *dc,
 			const struct dc_stream **stream, int num_streams);
-	bool (*set_psr_enable)(struct dc *dc, bool enable);
-	bool (*setup_psr)(struct dc *dc, const struct dc_stream *stream);
+
+	void (*set_static_screen_events)(struct dc *dc,
+			const struct dc_stream **stream,
+			int num_streams,
+			const struct dc_static_screen_events *events);
 };
 
 struct link_training_settings;
@@ -604,7 +614,6 @@ struct dc_link {
 	uint8_t ddc_hw_inst;
 	uint8_t link_enc_hw_inst;
 
-	struct psr_caps psr_caps;
 	bool test_pattern_enabled;
 	union compliance_test_state compliance_test_state;
 
@@ -657,7 +666,7 @@ bool dc_link_set_backlight_level(const s
 bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable);
 
 bool dc_link_setup_psr(const struct dc_link *dc_link,
-		const struct dc_stream *stream);
+		const struct dc_stream *stream, struct psr_config *psr_config);
 
 /* Request DC to detect if there is a Panel connected.
  * boot - If this call is during initial boot.
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -484,6 +484,15 @@ struct freesync_context {
 	unsigned int nominal_refresh_in_micro_hz;
 };
 
+struct psr_config {
+	unsigned char psr_version;
+	unsigned int psr_rfb_setup_time;
+	bool psr_exit_link_training_required;
+
+	bool psr_frame_capture_indication_req;
+	unsigned int psr_sdp_transmit_line_num_deadline;
+};
+
 struct colorspace_transform {
 	struct fixed31_32 matrix[12];
 	bool enable_remap;
@@ -494,21 +503,6 @@ struct csc_transform {
 	bool enable_adjustment;
 };
 
-struct psr_caps {
-	/* These parameters are from PSR capabilities reported by Sink DPCD */
-	unsigned char psr_version;
-	unsigned int psr_rfb_setup_time;
-	bool psr_exit_link_training_required;
-
-	/* These parameters are calculated in Driver,
-	 * based on display timing and Sink capabilities.
-	 * If VBLANK region is too small and Sink takes a long time
-	 * to set up RFB, it may take an extra frame to enter PSR state.
-	 */
-	bool psr_frame_capture_indication_req;
-	unsigned int psr_sdp_transmit_line_num_deadline;
-};
-
 enum i2c_mot_mode {
 	I2C_MOT_UNDEF,
 	I2C_MOT_TRUE,
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -1005,6 +1005,10 @@ static enum dc_status dce110_prog_pixclk
 				pipe_ctx->tg,
 				&stream->public.timing,
 				true);
+
+		pipe_ctx->tg->funcs->set_static_screen_control(
+				pipe_ctx->tg,
+				0x182);
 	}
 
 	if (!pipe_ctx_old->stream) {
@@ -1015,6 +1019,8 @@ static enum dc_status dce110_prog_pixclk
 		}
 	}
 
+
+
 	return DC_OK;
 }
 
@@ -1114,6 +1120,8 @@ static enum dc_status apply_single_contr
 					stream->public.timing.pix_clk_khz,
 					context->stream_count);
 
+	pipe_ctx->stream->sink->link->psr_enabled = false;
+
 	return DC_OK;
 }
 
@@ -1355,9 +1363,17 @@ static void set_drr(struct pipe_ctx **pi
 }
 
 static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
-		int num_pipes, int value)
+		int num_pipes, const struct dc_static_screen_events *events)
 {
 	unsigned int i;
+	unsigned int value = 0;
+
+	if (events->overlay_update)
+		value |= 0x100;
+	if (events->surface_update)
+		value |= 0x80;
+	if (events->cursor_update)
+		value |= 0x2;
 
 	for (i = 0; i < num_pipes; i++)
 		pipe_ctx[i]->tg->funcs->
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
@@ -371,7 +371,6 @@ void dce110_timing_generator_set_drr(
 	uint32_t v_total_min = 0;
 	uint32_t v_total_max = 0;
 	uint32_t v_total_cntl = 0;
-	uint32_t static_screen_cntl = 0;
 	struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
 
 	uint32_t addr = 0;
@@ -385,9 +384,6 @@ void dce110_timing_generator_set_drr(
 	addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
 	v_total_cntl = dm_read_reg(tg->ctx, addr);
 
-	addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
-	static_screen_cntl = dm_read_reg(tg->ctx, addr);
-
 	if (params != NULL &&
 		params->vertical_total_max > 0 &&
 		params->vertical_total_min > 0) {
@@ -430,20 +426,11 @@ void dce110_timing_generator_set_drr(
 				0,
 				CRTC_V_TOTAL_CONTROL,
 				CRTC_SET_V_TOTAL_MIN_MASK);
-
-		set_reg_field_value(static_screen_cntl,
-				0x180,
-			CRTC_STATIC_SCREEN_CONTROL,
-			CRTC_STATIC_SCREEN_EVENT_MASK);
 	} else {
 		set_reg_field_value(v_total_cntl,
 			0,
 			CRTC_V_TOTAL_CONTROL,
 			CRTC_SET_V_TOTAL_MIN_MASK);
-		set_reg_field_value(static_screen_cntl,
-			0,
-			CRTC_STATIC_SCREEN_CONTROL,
-			CRTC_STATIC_SCREEN_EVENT_MASK);
 		set_reg_field_value(v_total_min,
 				0,
 				CRTC_V_TOTAL_MIN,
@@ -478,9 +465,6 @@ void dce110_timing_generator_set_drr(
 
 	addr = CRTC_REG(mmCRTC_V_TOTAL_CONTROL);
 	dm_write_reg(tg->ctx, addr, v_total_cntl);
-
-	addr = CRTC_REG(mmCRTC_STATIC_SCREEN_CONTROL);
-	dm_write_reg(tg->ctx, addr, static_screen_cntl);
 }
 
 void dce110_timing_generator_set_static_screen_control(
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -156,6 +156,7 @@ struct core_link {
 	unsigned int dpcd_sink_count;
 
 	enum edp_revision edp_revision;
+	bool psr_enabled;
 
 	/* MST record stream using this link */
 	struct link_flags {
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -132,7 +132,7 @@ struct hw_sequencer_funcs {
 			int vmin, int vmax);
 
 	void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx,
-			int num_pipes, int value);
+			int num_pipes, const struct dc_static_screen_events *events);
 
 	enum dc_status (*prog_pixclk_crtc_otg)(
 			struct pipe_ctx *pipe_ctx,
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -264,10 +264,10 @@ bool mod_freesync_add_stream(struct mod_
 					enable_for_video = false;
 		}
 
-		temp = core_stream->public.timing.pix_clk_khz;
+		temp = stream->timing.pix_clk_khz;
 		temp *= 1000ULL * 1000ULL * 1000ULL;
-		temp = div_u64(temp, core_stream->public.timing.h_total);
-		temp = div_u64(temp, core_stream->public.timing.v_total);
+		temp = div_u64(temp, stream->timing.h_total);
+		temp = div_u64(temp, stream->timing.v_total);
 
 		nom_refresh_rate_micro_hz = (unsigned int) temp;
 
@@ -657,6 +657,7 @@ void mod_freesync_handle_v_update(struct
 	unsigned int min_frame_duration_in_ns, vmax, vmin = 0;
 	struct freesync_state *state;
 	struct core_freesync *core_freesync = NULL;
+	struct dc_static_screen_events triggers = {0};
 
 	if (mod_freesync == NULL)
 		return;
@@ -749,6 +750,13 @@ void mod_freesync_handle_v_update(struct
 					core_freesync->dc, streams,
 					num_streams, v_total,
 					v_total);
+
+		triggers.overlay_update = true;
+		triggers.surface_update = true;
+
+		core_freesync->dc->stream_funcs.set_static_screen_events(
+					core_freesync->dc, streams,	num_streams,
+					&triggers);
 	}
 }