Commit bd051aa2 authored by Ethan Bitnun's avatar Ethan Bitnun Committed by Alex Deucher

drm/amd/display: Find max flickerless instant vtotal delta

[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: default avatarAlvin Lee <alvin.lee2@amd.com>
Acked-by: default avatarAlex Hung <alex.hung@amd.com>
Signed-off-by: default avatarEthan Bitnun <etbitnun@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 2eb7d4b9
......@@ -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;
......
......@@ -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);
}
......@@ -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_
......@@ -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;
......
......@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment