mirror of
https://github.com/torvalds/linux.git
synced 2026-04-21 08:13:56 -04:00
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: Alvin Lee <alvin.lee2@amd.com> Acked-by: Alex Hung <alex.hung@amd.com> Signed-off-by: Ethan Bitnun <etbitnun@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Alex Deucher
parent
2eb7d4b987
commit
bd051aa2fc
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user