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 {
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;
......
......@@ -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 = {
......
......@@ -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)
......@@ -47,6 +48,15 @@
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 */
......
......@@ -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;
}
......@@ -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 = {
......
......@@ -35,6 +35,15 @@
#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)))) {
......@@ -2789,6 +2800,55 @@ bool dcn32_allow_subvp_with_active_margin(struct pipe_ctx *pipe)
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
......
......@@ -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;
}
}
......
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