[PATCH 18/20] drm/amd/display: Find max flickerless instant vtotal delta
Alex Hung
alex.hung at amd.com
Wed May 8 17:13:18 UTC 2024
From: Ethan Bitnun <etbitnun at amd.com>
[WHAT & HOW]
- Populate dml 2 callback with get_max_flickerless_instant_vtotal_increase
- Use long long when necessary to prevent overflow
- Add asic specific default values, currently disabled by
default for every asic
- Use the pre-existing debug option to protect the call to
get_max_flickerless_instant_vtotal_increase
Reviewed-by: Alvin Lee <alvin.lee2 at amd.com>
Acked-by: Alex Hung <alex.hung at amd.com>
Signed-off-by: Ethan Bitnun <etbitnun at amd.com>
---
.../gpu/drm/amd/display/dc/core/dc_resource.c | 3 +
.../gpu/drm/amd/display/dc/core/dc_stream.c | 64 +++++++++++++++++--
.../gpu/drm/amd/display/dc/dc_stream_priv.h | 14 ++++
.../display/dc/dcn32/dcn32_resource_helpers.c | 2 +-
.../drm/amd/display/dc/dml2/dml2_wrapper.h | 3 +
5 files changed, 79 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 8a5cc8b80217..70c39eef99e5 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -43,6 +43,8 @@
#include "link.h"
#include "clk_mgr.h"
#include "dc_state_priv.h"
+#include "dc_stream_priv.h"
+
#include "virtual/virtual_link_hwss.h"
#include "link/hwss/link_hwss_dio.h"
#include "link/hwss/link_hwss_dpia.h"
@@ -5195,6 +5197,7 @@ void resource_init_common_dml2_callbacks(struct dc *dc, struct dml2_configuratio
dml2_options->callbacks.get_dpp_pipes_for_plane = &resource_get_dpp_pipes_for_plane;
dml2_options->callbacks.get_stream_status = &dc_state_get_stream_status;
dml2_options->callbacks.get_stream_from_id = &dc_state_get_stream_from_id;
+ dml2_options->callbacks.get_max_flickerless_instant_vtotal_increase = &dc_stream_get_max_flickerless_instant_vtotal_increase;
dml2_options->svp_pstate.callbacks.dc = dc;
dml2_options->svp_pstate.callbacks.add_phantom_plane = &dc_state_add_phantom_plane;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index b5a89b587d86..de48084eac25 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -833,7 +833,7 @@ static int dc_stream_get_brightness_millinits_linear_interpolation (struct dc_st
int index2,
int refresh_hz)
{
- int slope = 0;
+ long long slope = 0;
if (stream->lumin_data.refresh_rate_hz[index2] != stream->lumin_data.refresh_rate_hz[index1]) {
slope = (stream->lumin_data.luminance_millinits[index2] - stream->lumin_data.luminance_millinits[index1]) /
(stream->lumin_data.refresh_rate_hz[index2] - stream->lumin_data.refresh_rate_hz[index1]);
@@ -852,7 +852,7 @@ static int dc_stream_get_refresh_hz_linear_interpolation (struct dc_stream_state
int index2,
int brightness_millinits)
{
- int slope = 1;
+ long long slope = 1;
if (stream->lumin_data.refresh_rate_hz[index2] != stream->lumin_data.refresh_rate_hz[index1]) {
slope = (stream->lumin_data.luminance_millinits[index2] - stream->lumin_data.luminance_millinits[index1]) /
(stream->lumin_data.refresh_rate_hz[index2] - stream->lumin_data.refresh_rate_hz[index1]);
@@ -860,7 +860,7 @@ static int dc_stream_get_refresh_hz_linear_interpolation (struct dc_stream_state
int y_intercept = stream->lumin_data.luminance_millinits[index2] - slope * stream->lumin_data.refresh_rate_hz[index2];
- return ((brightness_millinits - y_intercept) / slope);
+ return ((int)div64_s64((brightness_millinits - y_intercept), slope));
}
/*
@@ -884,8 +884,9 @@ static int dc_stream_get_brightness_millinits_from_refresh (struct dc_stream_sta
}
/*
- * Finds the lowest refresh rate that can be achieved
- * from starting_refresh_hz while staying within flicker criteria
+ * Finds the lowest/highest refresh rate (depending on search_for_max_increase)
+ * that can be achieved from starting_refresh_hz while staying
+ * within flicker criteria
*/
static int dc_stream_calculate_flickerless_refresh_rate(struct dc_stream_state *stream,
int current_brightness,
@@ -942,7 +943,7 @@ static int dc_stream_calculate_flickerless_refresh_rate(struct dc_stream_state *
}
if (search_for_max_increase)
- return stream->lumin_data.refresh_rate_hz[LUMINANCE_DATA_TABLE_SIZE - 1];
+ return (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, stream->timing.v_total*stream->timing.h_total);
else
return stream->lumin_data.refresh_rate_hz[0];
}
@@ -982,6 +983,31 @@ static int dc_stream_get_max_delta_lumin_millinits(struct dc_stream_state *strea
return (max - min);
}
+/*
+ * Determines the max flickerless instant vtotal delta for a stream.
+ * Determines vtotal increase/decrease based on the bool "increase"
+ */
+static unsigned int dc_stream_get_max_flickerless_instant_vtotal_delta(struct dc_stream_state *stream, bool is_gaming, bool increase)
+{
+ if (stream->timing.v_total * stream->timing.h_total == 0)
+ return 0;
+
+ int current_refresh_hz = (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, stream->timing.v_total*stream->timing.h_total);
+
+ int safe_refresh_hz = dc_stream_calculate_flickerless_refresh_rate(stream,
+ dc_stream_get_brightness_millinits_from_refresh(stream, current_refresh_hz),
+ current_refresh_hz,
+ is_gaming,
+ increase);
+
+ int safe_refresh_v_total = (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, safe_refresh_hz*stream->timing.h_total);
+
+ if (increase)
+ return ((stream->timing.v_total - safe_refresh_v_total) >= 0) ? (stream->timing.v_total - safe_refresh_v_total) : 0;
+
+ return ((safe_refresh_v_total - stream->timing.v_total) >= 0) ? (safe_refresh_v_total - stream->timing.v_total) : 0;
+}
+
/*
* Finds the highest refresh rate that can be achieved
* from starting_refresh_hz while staying within flicker criteria
@@ -1038,3 +1064,29 @@ bool dc_stream_is_refresh_rate_range_flickerless(struct dc_stream_state *stream,
return (dl <= flicker_criteria_millinits);
}
+
+/*
+ * Determines the max instant vtotal delta increase that can be applied without
+ * flickering for a given stream
+ */
+unsigned int dc_stream_get_max_flickerless_instant_vtotal_decrease(struct dc_stream_state *stream,
+ bool is_gaming)
+{
+ if (!stream->lumin_data.is_valid)
+ return 0;
+
+ return dc_stream_get_max_flickerless_instant_vtotal_delta(stream, is_gaming, true);
+}
+
+/*
+ * Determines the max instant vtotal delta decrease that can be applied without
+ * flickering for a given stream
+ */
+unsigned int dc_stream_get_max_flickerless_instant_vtotal_increase(struct dc_stream_state *stream,
+ bool is_gaming)
+{
+ if (!stream->lumin_data.is_valid)
+ return 0;
+
+ return dc_stream_get_max_flickerless_instant_vtotal_delta(stream, is_gaming, false);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream_priv.h b/drivers/gpu/drm/amd/display/dc/dc_stream_priv.h
index ea13804f7b14..ca37eac20986 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream_priv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream_priv.h
@@ -58,4 +58,18 @@ bool dc_stream_is_refresh_rate_range_flickerless(struct dc_stream_state *stream,
int hz2,
bool is_gaming);
+/*
+ * Determines the max instant vtotal delta increase that can be applied without
+ * flickering for a given stream
+ */
+unsigned int dc_stream_get_max_flickerless_instant_vtotal_decrease(struct dc_stream_state *stream,
+ bool is_gaming);
+
+/*
+ * Determines the max instant vtotal delta decrease that can be applied without
+ * flickering for a given stream
+ */
+unsigned int dc_stream_get_max_flickerless_instant_vtotal_increase(struct dc_stream_state *stream,
+ bool is_gaming);
+
#endif // _DC_STREAM_PRIV_H_
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
index eba7bfc7e4af..d184105ce2b3 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
@@ -474,7 +474,7 @@ static bool is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(
if (refresh_rate_max_stretch_100hz < min_refresh_100hz)
return false;
- if (fpo_candidate_stream->ctx->dc->config.enable_fpo_flicker_detection > 0 &&
+ if (fpo_candidate_stream->ctx->dc->config.enable_fpo_flicker_detection == 1 &&
!dc_stream_is_refresh_rate_range_flickerless(fpo_candidate_stream, (refresh_rate_max_stretch_100hz / 100), current_refresh_rate, false))
return false;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
index 4e4ed1678d91..dcb4e6f4d916 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
@@ -104,6 +104,9 @@ struct dml2_dc_callbacks {
struct dc_state *state,
const struct dc_stream_state *stream);
struct dc_stream_state *(*get_stream_from_id)(const struct dc_state *state, unsigned int id);
+ unsigned int (*get_max_flickerless_instant_vtotal_increase)(
+ struct dc_stream_state *stream,
+ bool is_gaming);
};
struct dml2_dc_svp_callbacks {
--
2.34.1
More information about the amd-gfx
mailing list