drm/amd/display: Limit VTotal range to max hw cap minus fp
commit a29997b7ac1f5c816b543e0c56aa2b5b56baac24 upstream. [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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
a249735619
commit
f443172fbf
@@ -285,6 +285,7 @@ struct dc_caps {
|
||||
uint16_t subvp_vertical_int_margin_us;
|
||||
bool seamless_odm;
|
||||
uint32_t max_v_total;
|
||||
bool vtotal_limited_by_fp2;
|
||||
uint32_t max_disp_clock_khz_at_vmin;
|
||||
uint8_t subvp_drr_vblank_start_margin_us;
|
||||
bool cursor_not_scaled;
|
||||
|
||||
@@ -339,11 +339,22 @@ void dml21_apply_soc_bb_overrides(struct dml2_initialize_instance_in_out *dml_in
|
||||
// }
|
||||
}
|
||||
|
||||
static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream)
|
||||
{
|
||||
unsigned int max_hw_v_total = stream->ctx->dc->caps.max_v_total;
|
||||
|
||||
if (stream->ctx->dc->caps.vtotal_limited_by_fp2) {
|
||||
max_hw_v_total -= stream->timing.v_front_porch + 1;
|
||||
}
|
||||
|
||||
return max_hw_v_total;
|
||||
}
|
||||
|
||||
static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cfg *timing,
|
||||
struct dc_stream_state *stream,
|
||||
struct dml2_context *dml_ctx)
|
||||
{
|
||||
unsigned int hblank_start, vblank_start;
|
||||
unsigned int hblank_start, vblank_start, min_hardware_refresh_in_uhz;
|
||||
|
||||
timing->h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
|
||||
timing->v_active = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
|
||||
@@ -371,11 +382,23 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf
|
||||
- stream->timing.v_border_top - stream->timing.v_border_bottom;
|
||||
|
||||
timing->drr_config.enabled = stream->ignore_msa_timing_param;
|
||||
timing->drr_config.min_refresh_uhz = stream->timing.min_refresh_in_uhz;
|
||||
timing->drr_config.drr_active_variable = stream->vrr_active_variable;
|
||||
timing->drr_config.drr_active_fixed = stream->vrr_active_fixed;
|
||||
timing->drr_config.disallowed = !stream->allow_freesync;
|
||||
|
||||
/* limit min refresh rate to DC cap */
|
||||
min_hardware_refresh_in_uhz = stream->timing.min_refresh_in_uhz;
|
||||
if (stream->ctx->dc->caps.max_v_total != 0) {
|
||||
min_hardware_refresh_in_uhz = div64_u64((stream->timing.pix_clk_100hz * 100000000ULL),
|
||||
(stream->timing.h_total * (long long)calc_max_hardware_v_total(stream)));
|
||||
}
|
||||
|
||||
if (stream->timing.min_refresh_in_uhz > min_hardware_refresh_in_uhz) {
|
||||
timing->drr_config.min_refresh_uhz = stream->timing.min_refresh_in_uhz;
|
||||
} else {
|
||||
timing->drr_config.min_refresh_uhz = min_hardware_refresh_in_uhz;
|
||||
}
|
||||
|
||||
if (dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase &&
|
||||
stream->ctx->dc->config.enable_fpo_flicker_detection == 1)
|
||||
timing->drr_config.max_instant_vtotal_delta = dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase(stream, false);
|
||||
|
||||
@@ -2354,6 +2354,7 @@ static bool dcn30_resource_construct(
|
||||
|
||||
dc->caps.dp_hdmi21_pcon_support = true;
|
||||
dc->caps.max_v_total = (1 << 15) - 1;
|
||||
dc->caps.vtotal_limited_by_fp2 = true;
|
||||
|
||||
/* read VBIOS LTTPR caps */
|
||||
{
|
||||
|
||||
@@ -1234,6 +1234,7 @@ static bool dcn302_resource_construct(
|
||||
dc->caps.extended_aux_timeout_support = true;
|
||||
dc->caps.dmcub_support = true;
|
||||
dc->caps.max_v_total = (1 << 15) - 1;
|
||||
dc->caps.vtotal_limited_by_fp2 = true;
|
||||
|
||||
/* Color pipeline capabilities */
|
||||
dc->caps.color.dpp.dcn_arch = 1;
|
||||
|
||||
@@ -1179,6 +1179,7 @@ static bool dcn303_resource_construct(
|
||||
dc->caps.extended_aux_timeout_support = true;
|
||||
dc->caps.dmcub_support = true;
|
||||
dc->caps.max_v_total = (1 << 15) - 1;
|
||||
dc->caps.vtotal_limited_by_fp2 = true;
|
||||
|
||||
/* Color pipeline capabilities */
|
||||
dc->caps.color.dpp.dcn_arch = 1;
|
||||
|
||||
@@ -2186,6 +2186,7 @@ static bool dcn32_resource_construct(
|
||||
dc->caps.dmcub_support = true;
|
||||
dc->caps.seamless_odm = true;
|
||||
dc->caps.max_v_total = (1 << 15) - 1;
|
||||
dc->caps.vtotal_limited_by_fp2 = true;
|
||||
|
||||
/* Color pipeline capabilities */
|
||||
dc->caps.color.dpp.dcn_arch = 1;
|
||||
|
||||
@@ -1743,6 +1743,7 @@ static bool dcn321_resource_construct(
|
||||
dc->caps.extended_aux_timeout_support = true;
|
||||
dc->caps.dmcub_support = true;
|
||||
dc->caps.max_v_total = (1 << 15) - 1;
|
||||
dc->caps.vtotal_limited_by_fp2 = true;
|
||||
|
||||
/* Color pipeline capabilities */
|
||||
dc->caps.color.dpp.dcn_arch = 1;
|
||||
|
||||
@@ -1850,6 +1850,7 @@ static bool dcn35_resource_construct(
|
||||
dc->caps.zstate_support = true;
|
||||
dc->caps.ips_support = true;
|
||||
dc->caps.max_v_total = (1 << 15) - 1;
|
||||
dc->caps.vtotal_limited_by_fp2 = true;
|
||||
|
||||
/* Color pipeline capabilities */
|
||||
dc->caps.color.dpp.dcn_arch = 1;
|
||||
|
||||
@@ -1829,6 +1829,7 @@ static bool dcn351_resource_construct(
|
||||
dc->caps.zstate_support = true;
|
||||
dc->caps.ips_support = true;
|
||||
dc->caps.max_v_total = (1 << 15) - 1;
|
||||
dc->caps.vtotal_limited_by_fp2 = true;
|
||||
|
||||
/* Color pipeline capabilities */
|
||||
dc->caps.color.dpp.dcn_arch = 1;
|
||||
|
||||
@@ -1826,6 +1826,7 @@ static bool dcn401_resource_construct(
|
||||
dc->caps.extended_aux_timeout_support = true;
|
||||
dc->caps.dmcub_support = true;
|
||||
dc->caps.max_v_total = (1 << 15) - 1;
|
||||
dc->caps.vtotal_limited_by_fp2 = true;
|
||||
|
||||
if (ASICREV_IS_GC_12_0_1_A0(dc->ctx->asic_id.hw_internal_rev))
|
||||
dc->caps.dcc_plane_width_limit = 7680;
|
||||
|
||||
@@ -121,6 +121,17 @@ static unsigned int calc_duration_in_us_from_v_total(
|
||||
return duration_in_us;
|
||||
}
|
||||
|
||||
static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream)
|
||||
{
|
||||
unsigned int max_hw_v_total = stream->ctx->dc->caps.max_v_total;
|
||||
|
||||
if (stream->ctx->dc->caps.vtotal_limited_by_fp2) {
|
||||
max_hw_v_total -= stream->timing.v_front_porch + 1;
|
||||
}
|
||||
|
||||
return max_hw_v_total;
|
||||
}
|
||||
|
||||
unsigned int mod_freesync_calc_v_total_from_refresh(
|
||||
const struct dc_stream_state *stream,
|
||||
unsigned int refresh_in_uhz)
|
||||
@@ -1002,7 +1013,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
|
||||
|
||||
if (stream->ctx->dc->caps.max_v_total != 0 && stream->timing.h_total != 0) {
|
||||
min_hardware_refresh_in_uhz = div64_u64((stream->timing.pix_clk_100hz * 100000000ULL),
|
||||
(stream->timing.h_total * (long long)stream->ctx->dc->caps.max_v_total));
|
||||
(stream->timing.h_total * (long long)calc_max_hardware_v_total(stream)));
|
||||
}
|
||||
/* Limit minimum refresh rate to what can be supported by hardware */
|
||||
min_refresh_in_uhz = min_hardware_refresh_in_uhz > in_config->min_refresh_in_uhz ?
|
||||
|
||||
Reference in New Issue
Block a user