OSDN Git Service

drm/amd/display: Enable SubVP for high refresh rate displays
authorAlvin Lee <Alvin.Lee2@amd.com>
Mon, 17 Apr 2023 14:23:05 +0000 (10:23 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 24 Apr 2023 22:36:46 +0000 (18:36 -0400)
[Description]
- Add debug option to enable SubVP for high refresh rate displays
- For now limit the enabled modes based on a table in debug options
- Currently disabled by default

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@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/dcn32/dcn32_resource.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c

index 5268d98..e411070 100644 (file)
@@ -881,6 +881,7 @@ struct dc_debug_options {
        bool disable_boot_optimizations;
        bool override_odm_optimization;
        bool minimize_dispclk_using_odm;
+       bool disable_subvp_high_refresh;
 };
 
 struct gpu_info_soc_bounding_box_v1_0;
index 0085ea7..7feeba7 100644 (file)
@@ -728,6 +728,7 @@ static const struct dc_debug_options debug_defaults_drv = {
        .fpo_vactive_margin_us = 2000, // 2000us
        .disable_fpo_vactive = false,
        .disable_boot_optimizations = false,
+       .disable_subvp_high_refresh = true,
 };
 
 static const struct dc_debug_options debug_defaults_diags = {
index 3937dbc..04be01a 100644 (file)
@@ -40,6 +40,7 @@
 #define DCN3_2_VMIN_DISPCLK_HZ 717000000
 #define DCN3_2_DCFCLK_DS_INIT_KHZ 10000 // Choose 10Mhz for init DCFCLK DS freq
 #define DCN3_2_MIN_ACTIVE_SWITCH_MARGIN_FPO_US 100 // Only allow FPO + Vactive if active margin >= 100
+#define SUBVP_HIGH_REFRESH_LIST_LEN 3
 
 #define TO_DCN32_RES_POOL(pool)\
        container_of(pool, struct dcn32_resource_pool, base)
 extern struct _vcs_dpi_ip_params_st dcn3_2_ip;
 extern struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc;
 
+struct subvp_high_refresh_list {
+       int min_refresh;
+       int max_refresh;
+       struct resolution {
+               int width;
+               int height;
+       } res[SUBVP_HIGH_REFRESH_LIST_LEN];
+};
+
 struct dcn32_resource_pool {
        struct resource_pool base;
 };
@@ -151,10 +161,14 @@ struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stre
 
 bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe);
 
+bool dcn32_allow_subvp_high_refresh_rate(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe);
+
 unsigned int dcn32_calc_num_avail_chans_for_mall(struct dc *dc, int num_chans);
 
 double dcn32_determine_max_vratio_prefetch(struct dc *dc, struct dc_state *context);
 
+bool dcn32_check_native_scaling_for_res(struct pipe_ctx *pipe, unsigned int width, unsigned int height);
+
 /* definitions for run time init of reg offsets */
 
 /* CLK SRC */
index eeca16f..df912c3 100644 (file)
@@ -656,3 +656,18 @@ struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stre
 
        return fpo_candidate_stream;
 }
+
+bool dcn32_check_native_scaling_for_res(struct pipe_ctx *pipe, unsigned int width, unsigned int height)
+{
+       bool is_native_scaling = false;
+
+       if (pipe->stream->timing.h_addressable == width &&
+                       pipe->stream->timing.v_addressable == height &&
+                       pipe->plane_state->src_rect.width == width &&
+                       pipe->plane_state->src_rect.height == height &&
+                       pipe->plane_state->dst_rect.width == width &&
+                       pipe->plane_state->dst_rect.height == height)
+               is_native_scaling = true;
+
+       return is_native_scaling;
+}
index 138657c..63bd692 100644 (file)
@@ -727,6 +727,7 @@ static const struct dc_debug_options debug_defaults_drv = {
        .fpo_vactive_margin_us = 2000, // 2000us
        .disable_fpo_vactive = false,
        .disable_boot_optimizations = false,
+       .disable_subvp_high_refresh = true,
 };
 
 static const struct dc_debug_options debug_defaults_diags = {
index 2624236..9cc0e60 100644 (file)
 
 #define DC_LOGGER_INIT(logger)
 
+static const struct subvp_high_refresh_list subvp_high_refresh_list = {
+                       .min_refresh = 120,
+                       .max_refresh = 165,
+                       .res = {
+                               {.width = 3840, .height = 2160, },
+                               {.width = 3440, .height = 1440, },
+                               {.width = 2560, .height = 1440, }},
+};
+
 struct _vcs_dpi_ip_params_st dcn3_2_ip = {
        .gpuvm_enable = 0,
        .gpuvm_max_page_table_levels = 4,
@@ -694,7 +703,9 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc,
                 */
                if (pipe->plane_state && !pipe->top_pipe && !dcn32_is_center_timing(pipe) &&
                                (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) &&
-                               pipe->stream->mall_stream_config.type == SUBVP_NONE && refresh_rate < 120 && !pipe->plane_state->address.tmz_surface &&
+                               pipe->stream->mall_stream_config.type == SUBVP_NONE &&
+                               (refresh_rate < 120 || dcn32_allow_subvp_high_refresh_rate(dc, context, pipe)) &&
+                               !pipe->plane_state->address.tmz_surface &&
                                (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] <= 0 ||
                                (vba->ActiveDRAMClockChangeLatencyMarginPerState[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]] > 0 &&
                                                dcn32_allow_subvp_with_active_margin(pipe)))) {
@@ -2790,6 +2801,55 @@ bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe)
 }
 
 /**
+ * ************************************************************************************************
+ * dcn32_allow_subvp_high_refresh_rate: Determine if the high refresh rate config will allow subvp
+ *
+ * @param [in]: dc: Current DC state
+ * @param [in]: context: New DC state to be programmed
+ * @param [in]: pipe: Pipe to be considered for use in subvp
+ *
+ * On high refresh rate display configs, we will allow subvp under the following conditions:
+ * 1. Resolution is 3840x2160, 3440x1440, or 2560x1440
+ * 2. Refresh rate is between 120hz - 165hz
+ * 3. No scaling
+ * 4. Freesync is inactive
+ * 5. For single display cases, freesync must be disabled
+ *
+ * @return: True if pipe can be used for subvp, false otherwise
+ *
+ * ************************************************************************************************
+ */
+bool dcn32_allow_subvp_high_refresh_rate(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe)
+{
+       bool allow = false;
+       uint32_t refresh_rate = 0;
+       uint32_t min_refresh = subvp_high_refresh_list.min_refresh;
+       uint32_t max_refresh = subvp_high_refresh_list.max_refresh;
+       uint32_t i;
+
+       if (!dc->debug.disable_subvp_high_refresh && pipe->stream &&
+                       pipe->plane_state && !pipe->stream->vrr_active_variable) {
+               refresh_rate = (pipe->stream->timing.pix_clk_100hz * 100 +
+                                               pipe->stream->timing.v_total * pipe->stream->timing.h_total - 1)
+                                               / (double)(pipe->stream->timing.v_total * pipe->stream->timing.h_total);
+               if (refresh_rate >= min_refresh && refresh_rate <= max_refresh) {
+                       for (i = 0; i < SUBVP_HIGH_REFRESH_LIST_LEN; i++) {
+                               uint32_t width = subvp_high_refresh_list.res[i].width;
+                               uint32_t height = subvp_high_refresh_list.res[i].height;
+
+                               if (dcn32_check_native_scaling_for_res(pipe, width, height)) {
+                                       if ((context->stream_count == 1 && !pipe->stream->allow_freesync) || context->stream_count > 1) {
+                                               allow = true;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+       return allow;
+}
+
+/**
  * *******************************************************************************************
  * dcn32_determine_max_vratio_prefetch: Determine max Vratio for prefetch by driver policy
  *
index 13c7e73..66f44a0 100644 (file)
@@ -2322,10 +2322,14 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
                mode_lib->vba.LinkCapacitySupport[i] = true;
                for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) {
                        if (mode_lib->vba.BlendingAndTiming[k] == k
-                                       && (mode_lib->vba.Output[k] == dm_dp || mode_lib->vba.Output[k] == dm_dp2p0
-                                                       || mode_lib->vba.Output[k] == dm_edp
-                                                       || mode_lib->vba.Output[k] == dm_hdmi)
-                                       && mode_lib->vba.OutputBppPerState[i][k] == 0) {
+                               && (mode_lib->vba.Output[k] == dm_dp || mode_lib->vba.Output[k] == dm_dp2p0
+                                       || mode_lib->vba.Output[k] == dm_edp
+                                       || mode_lib->vba.Output[k] == dm_hdmi)
+                               && mode_lib->vba.OutputBppPerState[i][k] == 0 &&
+                               (mode_lib->vba.UsesMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe)) {
+                               /* Phantom pipes don't consider DSC in DML, so it could fail link check.
+                                * However, we don't care about the link for phantom pipes.
+                                */
                                mode_lib->vba.LinkCapacitySupport[i] = false;
                        }
                }