]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
drm/amd/display: Limit VTotal range to max hw cap minus fp
authorDillon Varone <dillon.varone@amd.com>
Wed, 13 Nov 2024 21:44:15 +0000 (16:44 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 2 Dec 2024 23:35:28 +0000 (18:35 -0500)
[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>
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
drivers/gpu/drm/amd/display/modules/freesync/freesync.c

index 49a31598bb88aa355a9f044c7f7e538d346da5dc..1dda5fc2e2122d9e910ef9fdc2ee3e926bd8cb96 100644 (file)
@@ -290,6 +290,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;
index 138b4b1e42ed7c1409efb07eace902c7f4d4e5d2..f66493528f420ba26d8a02f4d7f5573b43c3bed3 100644 (file)
@@ -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);
index cd31e4f16c14b494ea97195fb613b0ee877d4f58..bfd0eccbed28c8c494ec6b89d183edfb17dc46e3 100644 (file)
@@ -2353,6 +2353,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 */
        {
index 02af8b8f4d277b07ad49ac2e003fc832e10a1d06..7baefc910a3dc7b969d2d95f1e97e0e02bc5d275 100644 (file)
@@ -1233,6 +1233,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;
index 7002a8dd358a555e58a2b1c0d93cf53561f2ec22..8a57d46ad15f8c8a274ce8179fbfa205588b5022 100644 (file)
@@ -1178,6 +1178,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;
index 01d1a11d55455311b8eab32be8dbc528d92cd502..984d23bcbc2791ca4eb0896c573e383f1fa8930e 100644 (file)
@@ -2189,6 +2189,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;
index 5cb74fd9cb7d29052313fc524241338ee849e4dc..06b9479c8bd3a358f4541ceea97eb7a05ad7775c 100644 (file)
@@ -1742,6 +1742,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;
index 09a5a9474903063a860ddb043462764eee3313c1..89e2adcf2a28580fd212e200b5b38454b79dc2e8 100644 (file)
@@ -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;
index fe382f9b6ff26d13bbd6ca60be93dadbfed1a5c4..263a37c1cd3ae8c649a4b6807c04b8eb40a1fe61 100644 (file)
@@ -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;
index db93bac247c0f405c0fa71952ac765fbbf265afc..2a3dabfe3ceac46ce56f7c0e08425e4fd2a5e825 100644 (file)
@@ -1864,6 +1864,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;
index f980a84dceefce82f36c5c3f1a729a3188fc9873..2b3964529539f0855e10f44fb1898d2db2bbb507 100644 (file)
@@ -122,6 +122,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)
@@ -1016,7 +1027,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 ?