Commit 87f0c16e authored by Alvin Lee's avatar Alvin Lee Committed by Alex Deucher

drm/amd/display: Enable SubVP for high refresh rate displays

[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: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c8cefb99
...@@ -881,6 +881,7 @@ struct dc_debug_options { ...@@ -881,6 +881,7 @@ struct dc_debug_options {
bool disable_boot_optimizations; bool disable_boot_optimizations;
bool override_odm_optimization; bool override_odm_optimization;
bool minimize_dispclk_using_odm; bool minimize_dispclk_using_odm;
bool disable_subvp_high_refresh;
}; };
struct gpu_info_soc_bounding_box_v1_0; struct gpu_info_soc_bounding_box_v1_0;
......
...@@ -728,6 +728,7 @@ static const struct dc_debug_options debug_defaults_drv = { ...@@ -728,6 +728,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.fpo_vactive_margin_us = 2000, // 2000us .fpo_vactive_margin_us = 2000, // 2000us
.disable_fpo_vactive = false, .disable_fpo_vactive = false,
.disable_boot_optimizations = false, .disable_boot_optimizations = false,
.disable_subvp_high_refresh = true,
}; };
static const struct dc_debug_options debug_defaults_diags = { static const struct dc_debug_options debug_defaults_diags = {
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#define DCN3_2_VMIN_DISPCLK_HZ 717000000 #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_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 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)\ #define TO_DCN32_RES_POOL(pool)\
container_of(pool, struct dcn32_resource_pool, base) container_of(pool, struct dcn32_resource_pool, base)
...@@ -47,6 +48,15 @@ ...@@ -47,6 +48,15 @@
extern struct _vcs_dpi_ip_params_st dcn3_2_ip; extern struct _vcs_dpi_ip_params_st dcn3_2_ip;
extern struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc; 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 dcn32_resource_pool {
struct resource_pool base; struct resource_pool base;
}; };
...@@ -151,10 +161,14 @@ struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stre ...@@ -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_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); 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); 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 */ /* definitions for run time init of reg offsets */
/* CLK SRC */ /* CLK SRC */
......
...@@ -656,3 +656,18 @@ struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stre ...@@ -656,3 +656,18 @@ struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stre
return fpo_candidate_stream; 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;
}
...@@ -727,6 +727,7 @@ static const struct dc_debug_options debug_defaults_drv = { ...@@ -727,6 +727,7 @@ static const struct dc_debug_options debug_defaults_drv = {
.fpo_vactive_margin_us = 2000, // 2000us .fpo_vactive_margin_us = 2000, // 2000us
.disable_fpo_vactive = false, .disable_fpo_vactive = false,
.disable_boot_optimizations = false, .disable_boot_optimizations = false,
.disable_subvp_high_refresh = true,
}; };
static const struct dc_debug_options debug_defaults_diags = { static const struct dc_debug_options debug_defaults_diags = {
......
...@@ -35,6 +35,15 @@ ...@@ -35,6 +35,15 @@
#define DC_LOGGER_INIT(logger) #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 = { struct _vcs_dpi_ip_params_st dcn3_2_ip = {
.gpuvm_enable = 0, .gpuvm_enable = 0,
.gpuvm_max_page_table_levels = 4, .gpuvm_max_page_table_levels = 4,
...@@ -694,7 +703,9 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, ...@@ -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) && 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)) && (!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 ||
(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)))) { dcn32_allow_subvp_with_active_margin(pipe)))) {
...@@ -2789,6 +2800,55 @@ bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe) ...@@ -2789,6 +2800,55 @@ bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe)
return allow; return allow;
} }
/**
* ************************************************************************************************
* 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 * dcn32_determine_max_vratio_prefetch: Determine max Vratio for prefetch by driver policy
......
...@@ -2322,10 +2322,14 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l ...@@ -2322,10 +2322,14 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
mode_lib->vba.LinkCapacitySupport[i] = true; mode_lib->vba.LinkCapacitySupport[i] = true;
for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) { for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) {
if (mode_lib->vba.BlendingAndTiming[k] == 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_dp || mode_lib->vba.Output[k] == dm_dp2p0
|| mode_lib->vba.Output[k] == dm_edp || mode_lib->vba.Output[k] == dm_edp
|| mode_lib->vba.Output[k] == dm_hdmi) || mode_lib->vba.Output[k] == dm_hdmi)
&& mode_lib->vba.OutputBppPerState[i][k] == 0) { && 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; mode_lib->vba.LinkCapacitySupport[i] = false;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment