Commit 057fc695 authored by Jun Lei's avatar Jun Lei Committed by Alex Deucher

drm/amd/display: support "dummy pstate"

[why]
Existing support in DC for pstate only accounts for a single latency.  This is sufficient when the
variance of latency is small, or that pstate support isn't necessary for correct ASIC functionality.

Newer ASICs violate both existing assumptions.  PState support is mandatory of correct ASIC
functionality, but not all latencies have to be supported.  Existing code supports a "full p state" which
allows memory clock to change, but is hard for DCN to support (as it requires very large buffers).
New code will now fall back to a "dummy p state" support when "full p state" cannot be support.
This easy p state support should always be allowed.

[how]
Define a new latency in socBB.  Add fallback logic to support it.  Note DML is also updated to ensure
that fallback will always work.
Signed-off-by: default avatarJun Lei <Jun.Lei@amd.com>
Reviewed-by: default avatarDmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 0488a564
...@@ -201,6 +201,7 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, ...@@ -201,6 +201,7 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
} }
if (should_update_pstate_support(safe_to_lower, new_clocks->p_state_change_support, clk_mgr_base->clks.p_state_change_support)) { if (should_update_pstate_support(safe_to_lower, new_clocks->p_state_change_support, clk_mgr_base->clks.p_state_change_support)) {
clk_mgr_base->clks.prev_p_state_change_support = clk_mgr_base->clks.p_state_change_support;
clk_mgr_base->clks.p_state_change_support = new_clocks->p_state_change_support; clk_mgr_base->clks.p_state_change_support = new_clocks->p_state_change_support;
if (pp_smu && pp_smu->set_pstate_handshake_support) if (pp_smu && pp_smu->set_pstate_handshake_support)
pp_smu->set_pstate_handshake_support(&pp_smu->pp_smu, clk_mgr_base->clks.p_state_change_support); pp_smu->set_pstate_handshake_support(&pp_smu->pp_smu, clk_mgr_base->clks.p_state_change_support);
...@@ -308,6 +309,7 @@ void dcn2_init_clocks(struct clk_mgr *clk_mgr) ...@@ -308,6 +309,7 @@ void dcn2_init_clocks(struct clk_mgr *clk_mgr)
memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks)); memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
// Assumption is that boot state always supports pstate // Assumption is that boot state always supports pstate
clk_mgr->clks.p_state_change_support = true; clk_mgr->clks.p_state_change_support = true;
clk_mgr->clks.prev_p_state_change_support = true;
} }
void dcn2_enable_pme_wa(struct clk_mgr *clk_mgr_base) void dcn2_enable_pme_wa(struct clk_mgr *clk_mgr_base)
......
...@@ -121,6 +121,7 @@ struct dc_caps { ...@@ -121,6 +121,7 @@ struct dc_caps {
struct dc_bug_wa { struct dc_bug_wa {
bool no_connect_phy_config; bool no_connect_phy_config;
bool dedcn20_305_wa; bool dedcn20_305_wa;
struct display_mode_lib alternate_dml;
}; };
#endif #endif
...@@ -263,6 +264,12 @@ struct dc_clocks { ...@@ -263,6 +264,12 @@ struct dc_clocks {
int phyclk_khz; int phyclk_khz;
int dramclk_khz; int dramclk_khz;
bool p_state_change_support; bool p_state_change_support;
/*
* Elements below are not compared for the purposes of
* optimization required
*/
bool prev_p_state_change_support;
}; };
struct dc_bw_validation_profile { struct dc_bw_validation_profile {
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "dcn20_hubbub.h" #include "dcn20_hubbub.h"
#include "reg_helper.h" #include "reg_helper.h"
#include "clk_mgr.h"
#define REG(reg)\ #define REG(reg)\
hubbub1->regs->reg hubbub1->regs->reg
...@@ -553,6 +554,16 @@ static void hubbub2_program_watermarks( ...@@ -553,6 +554,16 @@ static void hubbub2_program_watermarks(
*/ */
hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); hubbub1_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); hubbub1_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
/*
* There's a special case when going from p-state support to p-state unsupported
* here we are going to LOWER watermarks to go to dummy p-state only, but this has
* to be done prepare_bandwidth, not optimize
*/
if (hubbub1->base.ctx->dc->clk_mgr->clks.prev_p_state_change_support == true &&
hubbub1->base.ctx->dc->clk_mgr->clks.p_state_change_support == false)
safe_to_lower = true;
hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); hubbub1_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0, REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,
......
...@@ -1443,16 +1443,16 @@ void dcn20_prepare_bandwidth( ...@@ -1443,16 +1443,16 @@ void dcn20_prepare_bandwidth(
{ {
struct hubbub *hubbub = dc->res_pool->hubbub; struct hubbub *hubbub = dc->res_pool->hubbub;
dc->clk_mgr->funcs->update_clocks(
dc->clk_mgr,
context,
false);
/* program dchubbub watermarks */ /* program dchubbub watermarks */
hubbub->funcs->program_watermarks(hubbub, hubbub->funcs->program_watermarks(hubbub,
&context->bw_ctx.bw.dcn.watermarks, &context->bw_ctx.bw.dcn.watermarks,
dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000, dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
false); false);
dc->clk_mgr->funcs->update_clocks(
dc->clk_mgr,
context,
false);
} }
void dcn20_optimize_bandwidth( void dcn20_optimize_bandwidth(
......
...@@ -2427,7 +2427,7 @@ void dcn20_calculate_dlg_params( ...@@ -2427,7 +2427,7 @@ void dcn20_calculate_dlg_params(
} }
} }
bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *context,
bool fast_validate) bool fast_validate)
{ {
bool out = false; bool out = false;
...@@ -2479,6 +2479,62 @@ bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context, ...@@ -2479,6 +2479,62 @@ bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
return out; return out;
} }
bool dcn20_validate_bandwidth(struct dc *dc, struct dc_state *context,
bool fast_validate)
{
bool voltage_supported = false;
bool full_pstate_supported = false;
bool dummy_pstate_supported = false;
double p_state_latency_us = context->bw_ctx.dml.soc.dram_clock_change_latency_us;
if (fast_validate)
return dcn20_validate_bandwidth_internal(dc, context, true);
// Best case, we support full UCLK switch latency
voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false);
full_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support;
if (context->bw_ctx.dml.soc.dummy_pstate_latency_us == 0 ||
(voltage_supported && full_pstate_supported)) {
context->bw_ctx.bw.dcn.clk.p_state_change_support = true;
goto restore_dml_state;
}
// Fallback #1: Try to only support G6 temperature read latency
context->bw_ctx.dml.soc.dram_clock_change_latency_us = context->bw_ctx.dml.soc.dummy_pstate_latency_us;
voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false);
dummy_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support;
if (voltage_supported && dummy_pstate_supported) {
context->bw_ctx.bw.dcn.clk.p_state_change_support = false;
goto restore_dml_state;
}
// Fallback #2: Retry with "new" DCN20 to support G6 temperature read latency
memcpy (&context->bw_ctx.dml, &dc->work_arounds.alternate_dml, sizeof (struct display_mode_lib));
context->bw_ctx.dml.soc.dram_clock_change_latency_us = context->bw_ctx.dml.soc.dummy_pstate_latency_us;
voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false);
dummy_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support;
if (voltage_supported && dummy_pstate_supported) {
context->bw_ctx.bw.dcn.clk.p_state_change_support = false;
goto restore_dml_state;
}
// ERROR: fallback #2 is supposed to always work.
ASSERT(false);
restore_dml_state:
memcpy(&context->bw_ctx.dml, &dc->dml, sizeof(struct display_mode_lib));
context->bw_ctx.dml.soc.dram_clock_change_latency_us = p_state_latency_us;
return voltage_supported;
}
struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer( struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer(
struct dc_state *state, struct dc_state *state,
const struct resource_pool *pool, const struct resource_pool *pool,
...@@ -3085,6 +3141,7 @@ static bool construct( ...@@ -3085,6 +3141,7 @@ static bool construct(
} }
dml_init_instance(&dc->dml, &dcn2_0_soc, &dcn2_0_ip, DML_PROJECT_NAVI10); dml_init_instance(&dc->dml, &dcn2_0_soc, &dcn2_0_ip, DML_PROJECT_NAVI10);
dml_init_instance(&dc->work_arounds.alternate_dml, &dcn2_0_soc, &dcn2_0_ip, DML_PROJECT_NAVI10v2);
if (!dc->debug.disable_pplib_wm_range) { if (!dc->debug.disable_pplib_wm_range) {
struct pp_smu_wm_range_sets ranges = {0}; struct pp_smu_wm_range_sets ranges = {0};
......
...@@ -38,6 +38,8 @@ ifdef CONFIG_DRM_AMD_DC_DCN2_0 ...@@ -38,6 +38,8 @@ ifdef CONFIG_DRM_AMD_DC_DCN2_0
CFLAGS_display_mode_vba.o := $(dml_ccflags) CFLAGS_display_mode_vba.o := $(dml_ccflags)
CFLAGS_display_mode_vba_20.o := $(dml_ccflags) CFLAGS_display_mode_vba_20.o := $(dml_ccflags)
CFLAGS_display_rq_dlg_calc_20.o := $(dml_ccflags) CFLAGS_display_rq_dlg_calc_20.o := $(dml_ccflags)
CFLAGS_display_mode_vba_20v2.o := $(dml_ccflags)
CFLAGS_display_rq_dlg_calc_20v2.o := $(dml_ccflags)
endif endif
ifdef CONFIG_DRM_AMD_DCN3AG ifdef CONFIG_DRM_AMD_DCN3AG
CFLAGS_display_mode_vba_3ag.o := $(dml_ccflags) CFLAGS_display_mode_vba_3ag.o := $(dml_ccflags)
...@@ -51,6 +53,7 @@ DML = display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \ ...@@ -51,6 +53,7 @@ DML = display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \
ifdef CONFIG_DRM_AMD_DC_DCN2_0 ifdef CONFIG_DRM_AMD_DC_DCN2_0
DML += display_mode_vba.o dcn20/display_rq_dlg_calc_20.o dcn20/display_mode_vba_20.o DML += display_mode_vba.o dcn20/display_rq_dlg_calc_20.o dcn20/display_mode_vba_20.o
DML += dcn20/display_rq_dlg_calc_20v2.o dcn20/display_mode_vba_20v2.o
endif endif
AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML)) AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML))
......
/*
* Copyright 2018 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#ifndef _DCN20V2_DISPLAY_MODE_VBA_H_
#define _DCN20V2_DISPLAY_MODE_VBA_H_
void dml20v2_recalculate(struct display_mode_lib *mode_lib);
void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib);
#endif
/*
* Copyright 2018 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#ifndef __DML20V2_DISPLAY_RQ_DLG_CALC_H__
#define __DML20V2_DISPLAY_RQ_DLG_CALC_H__
#include "../dml_common_defs.h"
#include "../display_rq_dlg_helpers.h"
struct display_mode_lib;
// Function: dml_rq_dlg_get_rq_reg
// Main entry point for test to get the register values out of this DML class.
// This function calls <get_rq_param> and <extract_rq_regs> fucntions to calculate
// and then populate the rq_regs struct
// Input:
// pipe_src_param - pipe source configuration (e.g. vp, pitch, etc.)
// Output:
// rq_regs - struct that holds all the RQ registers field value.
// See also: <display_rq_regs_st>
void dml20v2_rq_dlg_get_rq_reg(
struct display_mode_lib *mode_lib,
display_rq_regs_st *rq_regs,
const display_pipe_params_st pipe_param);
// Function: dml_rq_dlg_get_dlg_reg
// Calculate and return DLG and TTU register struct given the system setting
// Output:
// dlg_regs - output DLG register struct
// ttu_regs - output DLG TTU register struct
// Input:
// e2e_pipe_param - "compacted" array of e2e pipe param struct
// num_pipes - num of active "pipe" or "route"
// pipe_idx - index that identifies the e2e_pipe_param that corresponding to this dlg
// cstate - 0: when calculate min_ttu_vblank it is assumed cstate is not required. 1: Normal mode, cstate is considered.
// Added for legacy or unrealistic timing tests.
void dml20v2_rq_dlg_get_dlg_reg(
struct display_mode_lib *mode_lib,
display_dlg_regs_st *dlg_regs,
display_ttu_regs_st *ttu_regs,
display_e2e_pipe_params_st *e2e_pipe_param,
const unsigned int num_pipes,
const unsigned int pipe_idx,
const bool cstate_en,
const bool pstate_en,
const bool vm_en,
const bool ignore_viewport_pos,
const bool immediate_flip_support);
#endif
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#if defined(CONFIG_DRM_AMD_DC_DCN2_0) #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
#include "dcn20/display_mode_vba_20.h" #include "dcn20/display_mode_vba_20.h"
#include "dcn20/display_rq_dlg_calc_20.h" #include "dcn20/display_rq_dlg_calc_20.h"
#include "dcn20/display_mode_vba_20v2.h"
#include "dcn20/display_rq_dlg_calc_20v2.h"
#endif #endif
#if defined(CONFIG_DRM_AMD_DC_DCN2_0) #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
...@@ -37,6 +39,13 @@ const struct dml_funcs dml20_funcs = { ...@@ -37,6 +39,13 @@ const struct dml_funcs dml20_funcs = {
.rq_dlg_get_dlg_reg = dml20_rq_dlg_get_dlg_reg, .rq_dlg_get_dlg_reg = dml20_rq_dlg_get_dlg_reg,
.rq_dlg_get_rq_reg = dml20_rq_dlg_get_rq_reg .rq_dlg_get_rq_reg = dml20_rq_dlg_get_rq_reg
}; };
const struct dml_funcs dml20v2_funcs = {
.validate = dml20v2_ModeSupportAndSystemConfigurationFull,
.recalculate = dml20v2_recalculate,
.rq_dlg_get_dlg_reg = dml20v2_rq_dlg_get_dlg_reg,
.rq_dlg_get_rq_reg = dml20v2_rq_dlg_get_rq_reg
};
#endif #endif
void dml_init_instance(struct display_mode_lib *lib, void dml_init_instance(struct display_mode_lib *lib,
...@@ -52,6 +61,9 @@ void dml_init_instance(struct display_mode_lib *lib, ...@@ -52,6 +61,9 @@ void dml_init_instance(struct display_mode_lib *lib,
case DML_PROJECT_NAVI10: case DML_PROJECT_NAVI10:
lib->funcs = dml20_funcs; lib->funcs = dml20_funcs;
break; break;
case DML_PROJECT_NAVI10v2:
lib->funcs = dml20v2_funcs;
break;
#endif #endif
default: default:
break; break;
......
...@@ -36,6 +36,7 @@ enum dml_project { ...@@ -36,6 +36,7 @@ enum dml_project {
DML_PROJECT_RAVEN1, DML_PROJECT_RAVEN1,
#ifdef CONFIG_DRM_AMD_DC_DCN2_0 #ifdef CONFIG_DRM_AMD_DC_DCN2_0
DML_PROJECT_NAVI10, DML_PROJECT_NAVI10,
DML_PROJECT_NAVI10v2,
#endif #endif
}; };
......
...@@ -100,6 +100,7 @@ struct _vcs_dpi_soc_bounding_box_st { ...@@ -100,6 +100,7 @@ struct _vcs_dpi_soc_bounding_box_st {
unsigned int vmm_page_size_bytes; unsigned int vmm_page_size_bytes;
unsigned int hostvm_min_page_size_bytes; unsigned int hostvm_min_page_size_bytes;
double dram_clock_change_latency_us; double dram_clock_change_latency_us;
double dummy_pstate_latency_us;
double writeback_dram_clock_change_latency_us; double writeback_dram_clock_change_latency_us;
unsigned int return_bus_width_bytes; unsigned int return_bus_width_bytes;
unsigned int voltage_override; unsigned int voltage_override;
......
...@@ -568,6 +568,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) ...@@ -568,6 +568,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
if (src->is_hsplit) { if (src->is_hsplit) {
for (k = j + 1; k < mode_lib->vba.cache_num_pipes; ++k) { for (k = j + 1; k < mode_lib->vba.cache_num_pipes; ++k) {
display_pipe_source_params_st *src_k = &pipes[k].pipe.src; display_pipe_source_params_st *src_k = &pipes[k].pipe.src;
display_pipe_dest_params_st *dst_k = &pipes[k].pipe.dest;
if (src_k->is_hsplit && !visited[k] if (src_k->is_hsplit && !visited[k]
&& src->hsplit_grp == src_k->hsplit_grp) { && src->hsplit_grp == src_k->hsplit_grp) {
...@@ -575,12 +576,15 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) ...@@ -575,12 +576,15 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
mode_lib->vba.NumberOfActivePlanes; mode_lib->vba.NumberOfActivePlanes;
mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes]++; mode_lib->vba.DPPPerPlane[mode_lib->vba.NumberOfActivePlanes]++;
if (mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes] if (mode_lib->vba.SourceScan[mode_lib->vba.NumberOfActivePlanes]
== dm_horz) == dm_horz) {
mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] += mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] +=
src_k->viewport_width; src_k->viewport_width;
else mode_lib->vba.ScalerRecoutWidth[mode_lib->vba.NumberOfActivePlanes] +=
dst_k->recout_width;
} else {
mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] += mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] +=
src_k->viewport_height; src_k->viewport_height;
}
visited[k] = true; visited[k] = true;
} }
......
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