Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Ethan Bitnun and committed by
Alex Deucher
bd051aa2 2eb7d4b9

+79 -7
+3
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
··· 43 43 #include "link.h" 44 44 #include "clk_mgr.h" 45 45 #include "dc_state_priv.h" 46 + #include "dc_stream_priv.h" 47 + 46 48 #include "virtual/virtual_link_hwss.h" 47 49 #include "link/hwss/link_hwss_dio.h" 48 50 #include "link/hwss/link_hwss_dpia.h" ··· 5197 5195 dml2_options->callbacks.get_dpp_pipes_for_plane = &resource_get_dpp_pipes_for_plane; 5198 5196 dml2_options->callbacks.get_stream_status = &dc_state_get_stream_status; 5199 5197 dml2_options->callbacks.get_stream_from_id = &dc_state_get_stream_from_id; 5198 + dml2_options->callbacks.get_max_flickerless_instant_vtotal_increase = &dc_stream_get_max_flickerless_instant_vtotal_increase; 5200 5199 5201 5200 dml2_options->svp_pstate.callbacks.dc = dc; 5202 5201 dml2_options->svp_pstate.callbacks.add_phantom_plane = &dc_state_add_phantom_plane;
+58 -6
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
··· 833 833 int index2, 834 834 int refresh_hz) 835 835 { 836 - int slope = 0; 836 + long long slope = 0; 837 837 if (stream->lumin_data.refresh_rate_hz[index2] != stream->lumin_data.refresh_rate_hz[index1]) { 838 838 slope = (stream->lumin_data.luminance_millinits[index2] - stream->lumin_data.luminance_millinits[index1]) / 839 839 (stream->lumin_data.refresh_rate_hz[index2] - stream->lumin_data.refresh_rate_hz[index1]); ··· 852 852 int index2, 853 853 int brightness_millinits) 854 854 { 855 - int slope = 1; 855 + long long slope = 1; 856 856 if (stream->lumin_data.refresh_rate_hz[index2] != stream->lumin_data.refresh_rate_hz[index1]) { 857 857 slope = (stream->lumin_data.luminance_millinits[index2] - stream->lumin_data.luminance_millinits[index1]) / 858 858 (stream->lumin_data.refresh_rate_hz[index2] - stream->lumin_data.refresh_rate_hz[index1]); ··· 860 860 861 861 int y_intercept = stream->lumin_data.luminance_millinits[index2] - slope * stream->lumin_data.refresh_rate_hz[index2]; 862 862 863 - return ((brightness_millinits - y_intercept) / slope); 863 + return ((int)div64_s64((brightness_millinits - y_intercept), slope)); 864 864 } 865 865 866 866 /* ··· 884 884 } 885 885 886 886 /* 887 - * Finds the lowest refresh rate that can be achieved 888 - * from starting_refresh_hz while staying within flicker criteria 887 + * Finds the lowest/highest refresh rate (depending on search_for_max_increase) 888 + * that can be achieved from starting_refresh_hz while staying 889 + * within flicker criteria 889 890 */ 890 891 static int dc_stream_calculate_flickerless_refresh_rate(struct dc_stream_state *stream, 891 892 int current_brightness, ··· 943 942 } 944 943 945 944 if (search_for_max_increase) 946 - return stream->lumin_data.refresh_rate_hz[LUMINANCE_DATA_TABLE_SIZE - 1]; 945 + return (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, stream->timing.v_total*stream->timing.h_total); 947 946 else 948 947 return stream->lumin_data.refresh_rate_hz[0]; 949 948 } ··· 981 980 } 982 981 983 982 return (max - min); 983 + } 984 + 985 + /* 986 + * Determines the max flickerless instant vtotal delta for a stream. 987 + * Determines vtotal increase/decrease based on the bool "increase" 988 + */ 989 + static unsigned int dc_stream_get_max_flickerless_instant_vtotal_delta(struct dc_stream_state *stream, bool is_gaming, bool increase) 990 + { 991 + if (stream->timing.v_total * stream->timing.h_total == 0) 992 + return 0; 993 + 994 + int current_refresh_hz = (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, stream->timing.v_total*stream->timing.h_total); 995 + 996 + int safe_refresh_hz = dc_stream_calculate_flickerless_refresh_rate(stream, 997 + dc_stream_get_brightness_millinits_from_refresh(stream, current_refresh_hz), 998 + current_refresh_hz, 999 + is_gaming, 1000 + increase); 1001 + 1002 + int safe_refresh_v_total = (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, safe_refresh_hz*stream->timing.h_total); 1003 + 1004 + if (increase) 1005 + return ((stream->timing.v_total - safe_refresh_v_total) >= 0) ? (stream->timing.v_total - safe_refresh_v_total) : 0; 1006 + 1007 + return ((safe_refresh_v_total - stream->timing.v_total) >= 0) ? (safe_refresh_v_total - stream->timing.v_total) : 0; 984 1008 } 985 1009 986 1010 /* ··· 1063 1037 stream->lumin_data.flicker_criteria_milli_nits_STATIC; 1064 1038 1065 1039 return (dl <= flicker_criteria_millinits); 1040 + } 1041 + 1042 + /* 1043 + * Determines the max instant vtotal delta increase that can be applied without 1044 + * flickering for a given stream 1045 + */ 1046 + unsigned int dc_stream_get_max_flickerless_instant_vtotal_decrease(struct dc_stream_state *stream, 1047 + bool is_gaming) 1048 + { 1049 + if (!stream->lumin_data.is_valid) 1050 + return 0; 1051 + 1052 + return dc_stream_get_max_flickerless_instant_vtotal_delta(stream, is_gaming, true); 1053 + } 1054 + 1055 + /* 1056 + * Determines the max instant vtotal delta decrease that can be applied without 1057 + * flickering for a given stream 1058 + */ 1059 + unsigned int dc_stream_get_max_flickerless_instant_vtotal_increase(struct dc_stream_state *stream, 1060 + bool is_gaming) 1061 + { 1062 + if (!stream->lumin_data.is_valid) 1063 + return 0; 1064 + 1065 + return dc_stream_get_max_flickerless_instant_vtotal_delta(stream, is_gaming, false); 1066 1066 }
+14
drivers/gpu/drm/amd/display/dc/dc_stream_priv.h
··· 58 58 int hz2, 59 59 bool is_gaming); 60 60 61 + /* 62 + * Determines the max instant vtotal delta increase that can be applied without 63 + * flickering for a given stream 64 + */ 65 + unsigned int dc_stream_get_max_flickerless_instant_vtotal_decrease(struct dc_stream_state *stream, 66 + bool is_gaming); 67 + 68 + /* 69 + * Determines the max instant vtotal delta decrease that can be applied without 70 + * flickering for a given stream 71 + */ 72 + unsigned int dc_stream_get_max_flickerless_instant_vtotal_increase(struct dc_stream_state *stream, 73 + bool is_gaming); 74 + 61 75 #endif // _DC_STREAM_PRIV_H_
+1 -1
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
··· 474 474 if (refresh_rate_max_stretch_100hz < min_refresh_100hz) 475 475 return false; 476 476 477 - if (fpo_candidate_stream->ctx->dc->config.enable_fpo_flicker_detection > 0 && 477 + if (fpo_candidate_stream->ctx->dc->config.enable_fpo_flicker_detection == 1 && 478 478 !dc_stream_is_refresh_rate_range_flickerless(fpo_candidate_stream, (refresh_rate_max_stretch_100hz / 100), current_refresh_rate, false)) 479 479 return false; 480 480
+3
drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
··· 104 104 struct dc_state *state, 105 105 const struct dc_stream_state *stream); 106 106 struct dc_stream_state *(*get_stream_from_id)(const struct dc_state *state, unsigned int id); 107 + unsigned int (*get_max_flickerless_instant_vtotal_increase)( 108 + struct dc_stream_state *stream, 109 + bool is_gaming); 107 110 }; 108 111 109 112 struct dml2_dc_svp_callbacks {