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

drm/amd/display: Limit VTotal range to max hw cap minus fp

[WHY & HOW]
Hardware does not support the VTotal to be between fp2 lines of the
maximum possible VTotal, so add a capability flag to track it and apply
where necessary.

Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
Reviewed-by: Jun Lei <jun.lei@amd.com>
Reviewed-by: Anthony Koo <anthony.koo@amd.com>
Signed-off-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Dillon Varone and committed by
Alex Deucher
a29997b7 24d3749c

+46 -3
+1
drivers/gpu/drm/amd/display/dc/dc.h
··· 290 290 uint16_t subvp_vertical_int_margin_us; 291 291 bool seamless_odm; 292 292 uint32_t max_v_total; 293 + bool vtotal_limited_by_fp2; 293 294 uint32_t max_disp_clock_khz_at_vmin; 294 295 uint8_t subvp_drr_vblank_start_margin_us; 295 296 bool cursor_not_scaled;
+25 -2
drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
··· 339 339 // } 340 340 } 341 341 342 + static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream) 343 + { 344 + unsigned int max_hw_v_total = stream->ctx->dc->caps.max_v_total; 345 + 346 + if (stream->ctx->dc->caps.vtotal_limited_by_fp2) { 347 + max_hw_v_total -= stream->timing.v_front_porch + 1; 348 + } 349 + 350 + return max_hw_v_total; 351 + } 352 + 342 353 static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cfg *timing, 343 354 struct dc_stream_state *stream, 344 355 struct dml2_context *dml_ctx) 345 356 { 346 - unsigned int hblank_start, vblank_start; 357 + unsigned int hblank_start, vblank_start, min_hardware_refresh_in_uhz; 347 358 348 359 timing->h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; 349 360 timing->v_active = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top; ··· 382 371 - stream->timing.v_border_top - stream->timing.v_border_bottom; 383 372 384 373 timing->drr_config.enabled = stream->ignore_msa_timing_param; 385 - timing->drr_config.min_refresh_uhz = stream->timing.min_refresh_in_uhz; 386 374 timing->drr_config.drr_active_variable = stream->vrr_active_variable; 387 375 timing->drr_config.drr_active_fixed = stream->vrr_active_fixed; 388 376 timing->drr_config.disallowed = !stream->allow_freesync; 377 + 378 + /* limit min refresh rate to DC cap */ 379 + min_hardware_refresh_in_uhz = stream->timing.min_refresh_in_uhz; 380 + if (stream->ctx->dc->caps.max_v_total != 0) { 381 + min_hardware_refresh_in_uhz = div64_u64((stream->timing.pix_clk_100hz * 100000000ULL), 382 + (stream->timing.h_total * (long long)calc_max_hardware_v_total(stream))); 383 + } 384 + 385 + if (stream->timing.min_refresh_in_uhz > min_hardware_refresh_in_uhz) { 386 + timing->drr_config.min_refresh_uhz = stream->timing.min_refresh_in_uhz; 387 + } else { 388 + timing->drr_config.min_refresh_uhz = min_hardware_refresh_in_uhz; 389 + } 389 390 390 391 if (dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase && 391 392 stream->ctx->dc->config.enable_fpo_flicker_detection == 1)
+1
drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
··· 2353 2353 2354 2354 dc->caps.dp_hdmi21_pcon_support = true; 2355 2355 dc->caps.max_v_total = (1 << 15) - 1; 2356 + dc->caps.vtotal_limited_by_fp2 = true; 2356 2357 2357 2358 /* read VBIOS LTTPR caps */ 2358 2359 {
+1
drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
··· 1233 1233 dc->caps.extended_aux_timeout_support = true; 1234 1234 dc->caps.dmcub_support = true; 1235 1235 dc->caps.max_v_total = (1 << 15) - 1; 1236 + dc->caps.vtotal_limited_by_fp2 = true; 1236 1237 1237 1238 /* Color pipeline capabilities */ 1238 1239 dc->caps.color.dpp.dcn_arch = 1;
+1
drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
··· 1178 1178 dc->caps.extended_aux_timeout_support = true; 1179 1179 dc->caps.dmcub_support = true; 1180 1180 dc->caps.max_v_total = (1 << 15) - 1; 1181 + dc->caps.vtotal_limited_by_fp2 = true; 1181 1182 1182 1183 /* Color pipeline capabilities */ 1183 1184 dc->caps.color.dpp.dcn_arch = 1;
+1
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
··· 2189 2189 dc->caps.dmcub_support = true; 2190 2190 dc->caps.seamless_odm = true; 2191 2191 dc->caps.max_v_total = (1 << 15) - 1; 2192 + dc->caps.vtotal_limited_by_fp2 = true; 2192 2193 2193 2194 /* Color pipeline capabilities */ 2194 2195 dc->caps.color.dpp.dcn_arch = 1;
+1
drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
··· 1742 1742 dc->caps.extended_aux_timeout_support = true; 1743 1743 dc->caps.dmcub_support = true; 1744 1744 dc->caps.max_v_total = (1 << 15) - 1; 1745 + dc->caps.vtotal_limited_by_fp2 = true; 1745 1746 1746 1747 /* Color pipeline capabilities */ 1747 1748 dc->caps.color.dpp.dcn_arch = 1;
+1
drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
··· 1850 1850 dc->caps.zstate_support = true; 1851 1851 dc->caps.ips_support = true; 1852 1852 dc->caps.max_v_total = (1 << 15) - 1; 1853 + dc->caps.vtotal_limited_by_fp2 = true; 1853 1854 1854 1855 /* Color pipeline capabilities */ 1855 1856 dc->caps.color.dpp.dcn_arch = 1;
+1
drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
··· 1829 1829 dc->caps.zstate_support = true; 1830 1830 dc->caps.ips_support = true; 1831 1831 dc->caps.max_v_total = (1 << 15) - 1; 1832 + dc->caps.vtotal_limited_by_fp2 = true; 1832 1833 1833 1834 /* Color pipeline capabilities */ 1834 1835 dc->caps.color.dpp.dcn_arch = 1;
+1
drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
··· 1864 1864 dc->caps.extended_aux_timeout_support = true; 1865 1865 dc->caps.dmcub_support = true; 1866 1866 dc->caps.max_v_total = (1 << 15) - 1; 1867 + dc->caps.vtotal_limited_by_fp2 = true; 1867 1868 1868 1869 if (ASICREV_IS_GC_12_0_1_A0(dc->ctx->asic_id.hw_internal_rev)) 1869 1870 dc->caps.dcc_plane_width_limit = 7680;
+12 -1
drivers/gpu/drm/amd/display/modules/freesync/freesync.c
··· 122 122 return duration_in_us; 123 123 } 124 124 125 + static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream) 126 + { 127 + unsigned int max_hw_v_total = stream->ctx->dc->caps.max_v_total; 128 + 129 + if (stream->ctx->dc->caps.vtotal_limited_by_fp2) { 130 + max_hw_v_total -= stream->timing.v_front_porch + 1; 131 + } 132 + 133 + return max_hw_v_total; 134 + } 135 + 125 136 unsigned int mod_freesync_calc_v_total_from_refresh( 126 137 const struct dc_stream_state *stream, 127 138 unsigned int refresh_in_uhz) ··· 1027 1016 1028 1017 if (stream->ctx->dc->caps.max_v_total != 0 && stream->timing.h_total != 0) { 1029 1018 min_hardware_refresh_in_uhz = div64_u64((stream->timing.pix_clk_100hz * 100000000ULL), 1030 - (stream->timing.h_total * (long long)stream->ctx->dc->caps.max_v_total)); 1019 + (stream->timing.h_total * (long long)calc_max_hardware_v_total(stream))); 1031 1020 } 1032 1021 /* Limit minimum refresh rate to what can be supported by hardware */ 1033 1022 min_refresh_in_uhz = min_hardware_refresh_in_uhz > in_config->min_refresh_in_uhz ?