diff options
author | Leo Li <sunpeng.li@amd.com> | 2018-11-01 11:10:18 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2019-01-14 15:04:41 -0500 |
commit | 508f5fcb54f0ad3b333a835f45e109feb9edf761 (patch) | |
tree | dbcd50971d2258e2e0133eda1d696dfb201edf6a /drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | |
parent | 09f609c34fc8b9cb560947ab11609259f5d42889 (diff) | |
download | linux-508f5fcb54f0ad3b333a835f45e109feb9edf761.tar.gz |
drm/amd/display: Compensate for XGMI SS downspread on dprefclk
[Why]
When XGMI is enabled, we need to adjust the dprefclk according to the
WAFL link's spread spectrum info. This is for VG20 (DCE121) only.
[How]
dce_clk_mgr already stores SS info, currently being used by audio clock.
Therefore, patch the clk_mgr's SS info with the xGMI SS info, if xGMI
is enabled. For display clock, adjust it during dce12_update_clocks()
before calling set_clock().
Since we rely on a mmhub register to reliably determine if xGMI is
enabled, the patching step needs to happen after resource_construct()
has initialized the hardware sequencer.
Signed-off-by: Leo Li <sunpeng.li@amd.com>
Reviewed-by: Hersen Wu <hersenxs.wu@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c | 81 |
1 files changed, 74 insertions, 7 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c index f12696674eb0..48a210ec975b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c @@ -62,6 +62,8 @@ #include "soc15_hw_ip.h" #include "vega10_ip_offset.h" #include "nbio/nbio_6_1_offset.h" +#include "mmhub/mmhub_9_4_0_offset.h" +#include "mmhub/mmhub_9_4_0_sh_mask.h" #include "reg_helper.h" #include "dce100/dce100_resource.h" @@ -139,6 +141,17 @@ static const struct dce110_timing_generator_offsets dce120_tg_offsets[] = { .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \ mm ## block ## id ## _ ## reg_name +/* MMHUB */ +#define MMHUB_BASE_INNER(seg) \ + MMHUB_BASE__INST0_SEG ## seg + +#define MMHUB_BASE(seg) \ + MMHUB_BASE_INNER(seg) + +#define MMHUB_SR(reg_name)\ + .reg_name = MMHUB_BASE(mm ## reg_name ## _BASE_IDX) + \ + mm ## reg_name + /* macros to expend register list macro defined in HW object header file * end *********************/ @@ -681,6 +694,19 @@ static const struct dce_hwseq_mask hwseq_mask = { HWSEQ_DCE12_MASK_SH_LIST(_MASK) }; +/* HWSEQ regs for VG20 */ +static const struct dce_hwseq_registers dce121_hwseq_reg = { + HWSEQ_VG20_REG_LIST() +}; + +static const struct dce_hwseq_shift dce121_hwseq_shift = { + HWSEQ_VG20_MASK_SH_LIST(__SHIFT) +}; + +static const struct dce_hwseq_mask dce121_hwseq_mask = { + HWSEQ_VG20_MASK_SH_LIST(_MASK) +}; + static struct dce_hwseq *dce120_hwseq_create( struct dc_context *ctx) { @@ -695,6 +721,20 @@ static struct dce_hwseq *dce120_hwseq_create( return hws; } +static struct dce_hwseq *dce121_hwseq_create( + struct dc_context *ctx) +{ + struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL); + + if (hws) { + hws->ctx = ctx; + hws->regs = &dce121_hwseq_reg; + hws->shifts = &dce121_hwseq_shift; + hws->masks = &dce121_hwseq_mask; + } + return hws; +} + static const struct resource_create_funcs res_create_funcs = { .read_dce_straps = read_dce_straps, .create_audio = create_audio, @@ -702,6 +742,14 @@ static const struct resource_create_funcs res_create_funcs = { .create_hwseq = dce120_hwseq_create, }; +static const struct resource_create_funcs dce121_res_create_funcs = { + .read_dce_straps = read_dce_straps, + .create_audio = create_audio, + .create_stream_encoder = dce120_stream_encoder_create, + .create_hwseq = dce121_hwseq_create, +}; + + #define mi_inst_regs(id) { MI_DCE12_REG_LIST(id) } static const struct dce_mem_input_registers mi_regs[] = { mi_inst_regs(0), @@ -911,7 +959,8 @@ static bool construct( int j; struct dc_context *ctx = dc->ctx; struct irq_service_init_data irq_init_data; - bool harvest_enabled = ASICREV_IS_VEGA20_P(ctx->asic_id.hw_internal_rev); + static const struct resource_create_funcs *res_funcs; + bool is_vg20 = ASICREV_IS_VEGA20_P(ctx->asic_id.hw_internal_rev); uint32_t pipe_fuses; ctx->dc_bios->regs = &bios_regs; @@ -975,7 +1024,11 @@ static bool construct( } } - pool->base.clk_mgr = dce120_clk_mgr_create(ctx); + if (is_vg20) + pool->base.clk_mgr = dce121_clk_mgr_create(ctx); + else + pool->base.clk_mgr = dce120_clk_mgr_create(ctx); + if (pool->base.clk_mgr == NULL) { dm_error("DC: failed to create display clock!\n"); BREAK_TO_DEBUGGER(); @@ -1008,14 +1061,14 @@ static bool construct( if (!pool->base.irqs) goto irqs_create_fail; - /* retrieve valid pipe fuses */ - if (harvest_enabled) + /* VG20: Pipe harvesting enabled, retrieve valid pipe fuses */ + if (is_vg20) pipe_fuses = read_pipe_fuses(ctx); /* index to valid pipe resource */ j = 0; for (i = 0; i < pool->base.pipe_count; i++) { - if (harvest_enabled) { + if (is_vg20) { if ((pipe_fuses & (1 << i)) != 0) { dm_error("DC: skip invalid pipe %d!\n", i); continue; @@ -1093,10 +1146,24 @@ static bool construct( pool->base.pipe_count = j; pool->base.timing_generator_count = j; - if (!resource_construct(num_virtual_links, dc, &pool->base, - &res_create_funcs)) + if (is_vg20) + res_funcs = &dce121_res_create_funcs; + else + res_funcs = &res_create_funcs; + + if (!resource_construct(num_virtual_links, dc, &pool->base, res_funcs)) goto res_create_fail; + /* + * This is a bit of a hack. The xGMI enabled info is used to determine + * if audio and display clocks need to be adjusted with the WAFL link's + * SS info. This is a responsiblity of the clk_mgr. But since MMHUB is + * under hwseq, and the relevant register is in MMHUB, we have to do it + * here. + */ + if (is_vg20 && dce121_xgmi_enabled(dc->hwseq)) + dce121_clock_patch_xgmi_ss_info(pool->base.clk_mgr); + /* Create hardware sequencer */ if (!dce120_hw_sequencer_create(dc)) goto controller_create_fail; |