Blob Blame History Raw
From: Amy Zhang <Amy.Zhang@amd.com>
Date: Fri, 2 Jun 2017 16:33:47 -0400
Subject: drm/amd/display: Fix DRR Enable on Desktop
Git-commit: fc82c5cb306d6f201cdee2c4c092ff49c6929634
Patch-mainline: v4.15-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

- Block PSR in Full screen apps to prevent incorrect static screen curser events
- Reprogram static screen events when update freesync state
- Program static ramp variable active after other values are programmed
- Correct wrong assigning of the nominal and current vcount

Signed-off-by: Amy Zhang <Amy.Zhang@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/amd/display/modules/freesync/freesync.c |   89 ++++++++++------
 drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h  |    3 
 2 files changed, 61 insertions(+), 31 deletions(-)

--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -257,8 +257,10 @@ bool mod_freesync_add_stream(struct mod_
 		nom_refresh_rate_micro_hz = (unsigned int) temp;
 
 		if (core_freesync->opts.min_refresh_from_edid != 0 &&
-				dc_is_embedded_signal(
-					stream->sink->sink_signal)) {
+				dc_is_embedded_signal(stream->sink->sink_signal)
+				&& (nom_refresh_rate_micro_hz -
+				core_freesync->opts.min_refresh_from_edid *
+				1000000) >= 10000000) {
 			caps->supported = true;
 			caps->min_refresh_in_micro_hz =
 				core_freesync->opts.min_refresh_from_edid *
@@ -683,44 +685,47 @@ static void set_static_ramp_variables(st
 		unsigned int index, bool enable_static_screen)
 {
 	unsigned int frame_duration = 0;
-
+	unsigned int nominal_refresh_rate = core_freesync->map[index].state.
+			nominal_refresh_rate_in_micro_hz;
+	unsigned int min_refresh_rate= core_freesync->map[index].caps->
+			min_refresh_in_micro_hz;
 	struct gradual_static_ramp *static_ramp_variables =
 			&core_freesync->map[index].state.static_ramp;
 
+	/* If we are ENABLING static screen, refresh rate should go DOWN.
+	 * If we are DISABLING static screen, refresh rate should go UP.
+	 */
+	if (enable_static_screen)
+		static_ramp_variables->ramp_direction_is_up = false;
+	else
+		static_ramp_variables->ramp_direction_is_up = true;
+
 	/* If ramp is not active, set initial frame duration depending on
 	 * whether we are enabling/disabling static screen mode. If the ramp is
 	 * already active, ramp should continue in the opposite direction
 	 * starting with the current frame duration
 	 */
 	if (!static_ramp_variables->ramp_is_active) {
-
-		static_ramp_variables->ramp_is_active = true;
-
 		if (enable_static_screen == true) {
 			/* Going to lower refresh rate, so start from max
 			 * refresh rate (min frame duration)
 			 */
 			frame_duration = ((unsigned int) (div64_u64(
 				(1000000000ULL * 1000000),
-				core_freesync->map[index].state.
-				nominal_refresh_rate_in_micro_hz)));
+				nominal_refresh_rate)));
 		} else {
 			/* Going to higher refresh rate, so start from min
 			 * refresh rate (max frame duration)
 			 */
 			frame_duration = ((unsigned int) (div64_u64(
 				(1000000000ULL * 1000000),
-				core_freesync->map[index].caps->min_refresh_in_micro_hz)));
+				min_refresh_rate)));
 		}
-
 		static_ramp_variables->
 			ramp_current_frame_duration_in_ns = frame_duration;
-	}
 
-	/* If we are ENABLING static screen, refresh rate should go DOWN.
-	 * If we are DISABLING static screen, refresh rate should go UP.
-	 */
-	static_ramp_variables->ramp_direction_is_up = !enable_static_screen;
+		static_ramp_variables->ramp_is_active = true;
+	}
 }
 
 void mod_freesync_handle_v_update(struct mod_freesync *mod_freesync,
@@ -841,6 +846,7 @@ void mod_freesync_update_state(struct mo
 	unsigned int stream_index;
 	struct freesync_state *state;
 	struct core_freesync *core_freesync = NULL;
+	struct dc_static_screen_events triggers = {0};
 
 	if (mod_freesync == NULL)
 		return;
@@ -902,6 +908,14 @@ void mod_freesync_update_state(struct mo
 		}
 	}
 
+	/* Update mask */
+	triggers.overlay_update = true;
+	triggers.surface_update = true;
+
+	core_freesync->dc->stream_funcs.set_static_screen_events(
+		core_freesync->dc, streams, num_streams,
+		&triggers);
+
 	if (freesync_program_required)
 		/* Program freesync according to current state*/
 		set_freesync_on_streams(core_freesync, streams, num_streams);
@@ -1017,7 +1031,8 @@ bool mod_freesync_get_user_enable(struct
 bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync,
 		const struct dc_stream *streams,
 		unsigned int min_refresh,
-		unsigned int max_refresh)
+		unsigned int max_refresh,
+		struct mod_freesync_caps *caps)
 {
 	unsigned int index = 0;
 	struct core_freesync *core_freesync;
@@ -1030,7 +1045,10 @@ bool mod_freesync_override_min_max(struc
 	index = map_index_from_stream(core_freesync, streams);
 	state = &core_freesync->map[index].state;
 
-	if (min_refresh == 0 || max_refresh == 0) {
+	if (max_refresh == 0)
+		max_refresh = state->nominal_refresh_rate_in_micro_hz;
+
+	if (min_refresh == 0) {
 		/* Restore defaults */
 		calc_freesync_range(core_freesync, streams, state,
 			core_freesync->map[index].caps->
@@ -1049,6 +1067,17 @@ bool mod_freesync_override_min_max(struc
 			state->freesync_range.vmax);
 	}
 
+	if (min_refresh != 0 &&
+			dc_is_embedded_signal(streams->sink->sink_signal) &&
+			(max_refresh - min_refresh >= 10000000)) {
+		caps->supported = true;
+		caps->min_refresh_in_micro_hz = min_refresh;
+		caps->max_refresh_in_micro_hz = max_refresh;
+	}
+
+	/* Update the stream */
+	update_stream(core_freesync, streams);
+
 	return true;
 }
 
@@ -1115,8 +1144,8 @@ bool mod_freesync_get_v_position(struct
 			core_freesync->dc, &stream, 1,
 			&position.vertical_count, &position.nominal_vcount)) {
 
-		*nom_v_pos = position.vertical_count;
-		*v_pos = position.nominal_vcount;
+		*nom_v_pos = position.nominal_vcount;
+		*v_pos = position.vertical_count;
 
 		return true;
 	}
@@ -1131,6 +1160,7 @@ void mod_freesync_notify_mode_change(str
 	struct freesync_state *state;
 	struct core_freesync *core_freesync = NULL;
 	struct dc_static_screen_events triggers = {0};
+	unsigned long long temp = 0;
 
 	if (mod_freesync == NULL)
 		return;
@@ -1143,22 +1173,21 @@ void mod_freesync_notify_mode_change(str
 
 		state = &core_freesync->map[map_index].state;
 
+		/* Update the field rate for new timing */
+		temp = streams[stream_index]->timing.pix_clk_khz;
+		temp *= 1000ULL * 1000ULL * 1000ULL;
+		temp = div_u64(temp,
+				streams[stream_index]->timing.h_total);
+		temp = div_u64(temp,
+				streams[stream_index]->timing.v_total);
+		state->nominal_refresh_rate_in_micro_hz =
+				(unsigned int) temp;
+
 		if (core_freesync->map[map_index].caps->supported) {
-			/* Update the field rate for new timing */
-			unsigned long long temp;
-			temp = streams[stream_index]->timing.pix_clk_khz;
-			temp *= 1000ULL * 1000ULL * 1000ULL;
-			temp = div_u64(temp,
-					streams[stream_index]->timing.h_total);
-			temp = div_u64(temp,
-					streams[stream_index]->timing.v_total);
-			state->nominal_refresh_rate_in_micro_hz =
-					(unsigned int) temp;
 
 			/* Update the stream */
 			update_stream(core_freesync, streams[stream_index]);
 
-
 			/* Calculate vmin/vmax and refresh rate for
 			 * current mode
 			 */
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
@@ -132,7 +132,8 @@ bool mod_freesync_get_user_enable(struct
 bool mod_freesync_override_min_max(struct mod_freesync *mod_freesync,
 		const struct dc_stream *streams,
 		unsigned int min_refresh,
-		unsigned int max_refresh);
+		unsigned int max_refresh,
+		struct mod_freesync_caps *caps);
 
 bool mod_freesync_get_min_max(struct mod_freesync *mod_freesync,
 		const struct dc_stream *stream,