From 61452908a79ec936660494fb4b9f2a35ee42e6e0 Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Wed, 9 Jun 2021 17:36:26 -0400 Subject: [PATCH 001/151] drm/amd/display: Add DP 2.0 Audio Package Generator HW Blocks: +-----+ | HDA | +-----+ | | HPO ===============|============= | v | +-----+ | | APG | v +-----+ Signed-off-by: Fangzhi Zuo Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/Makefile | 3 +- .../gpu/drm/amd/display/dc/dcn31/dcn31_apg.c | 173 ++++++++++++++++++ .../gpu/drm/amd/display/dc/dcn31/dcn31_apg.h | 115 ++++++++++++ .../drm/amd/display/dc/dcn31/dcn31_resource.c | 38 ++++ 4 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile index 4bab97acb1551..bc2087f6dcb27 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile @@ -11,7 +11,8 @@ # Makefile for dcn31. DCN31 = dcn31_resource.o dcn31_hubbub.o dcn31_hwseq.o dcn31_init.o dcn31_hubp.o \ - dcn31_dccg.o dcn31_optc.o dcn31_dio_link_encoder.o dcn31_panel_cntl.o + dcn31_dccg.o dcn31_optc.o dcn31_dio_link_encoder.o dcn31_panel_cntl.o \ + dcn31_apg.o ifdef CONFIG_X86 CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o := -msse diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c new file mode 100644 index 0000000000000..6bd7a06266659 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c @@ -0,0 +1,173 @@ +/* + * Copyright 2019 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 + * + */ + + +#include "dc_bios_types.h" +#include "hw_shared.h" +#include "dcn31_apg.h" +#include "reg_helper.h" + +#define DC_LOGGER \ + apg31->base.ctx->logger + +#define REG(reg)\ + (apg31->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + apg31->apg_shift->field_name, apg31->apg_mask->field_name + + +#define CTX \ + apg31->base.ctx + + +static void apg31_enable( + struct apg *apg) +{ + struct dcn31_apg *apg31 = DCN31_APG_FROM_APG(apg); + + /* Reset APG */ + REG_UPDATE(APG_CONTROL, APG_RESET, 1); + REG_WAIT(APG_CONTROL, + APG_RESET_DONE, 1, + 1, 10); + REG_UPDATE(APG_CONTROL, APG_RESET, 0); + REG_WAIT(APG_CONTROL, + APG_RESET_DONE, 0, + 1, 10); + + /* Enable APG */ + REG_UPDATE(APG_CONTROL2, APG_ENABLE, 1); +} + +static void apg31_disable( + struct apg *apg) +{ + struct dcn31_apg *apg31 = DCN31_APG_FROM_APG(apg); + + /* Disable APG */ + REG_UPDATE(APG_CONTROL2, APG_ENABLE, 0); +} + +static union audio_cea_channels speakers_to_channels( + struct audio_speaker_flags speaker_flags) +{ + union audio_cea_channels cea_channels = {0}; + + /* these are one to one */ + cea_channels.channels.FL = speaker_flags.FL_FR; + cea_channels.channels.FR = speaker_flags.FL_FR; + cea_channels.channels.LFE = speaker_flags.LFE; + cea_channels.channels.FC = speaker_flags.FC; + + /* if Rear Left and Right exist move RC speaker to channel 7 + * otherwise to channel 5 + */ + if (speaker_flags.RL_RR) { + cea_channels.channels.RL_RC = speaker_flags.RL_RR; + cea_channels.channels.RR = speaker_flags.RL_RR; + cea_channels.channels.RC_RLC_FLC = speaker_flags.RC; + } else { + cea_channels.channels.RL_RC = speaker_flags.RC; + } + + /* FRONT Left Right Center and REAR Left Right Center are exclusive */ + if (speaker_flags.FLC_FRC) { + cea_channels.channels.RC_RLC_FLC = speaker_flags.FLC_FRC; + cea_channels.channels.RRC_FRC = speaker_flags.FLC_FRC; + } else { + cea_channels.channels.RC_RLC_FLC = speaker_flags.RLC_RRC; + cea_channels.channels.RRC_FRC = speaker_flags.RLC_RRC; + } + + return cea_channels; +} + +static void apg31_se_audio_setup( + struct apg *apg, + unsigned int az_inst, + struct audio_info *audio_info) +{ + struct dcn31_apg *apg31 = DCN31_APG_FROM_APG(apg); + + uint32_t speakers = 0; + uint32_t channels = 0; + + ASSERT(audio_info); + /* This should not happen.it does so we don't get BSOD*/ + if (audio_info == NULL) + return; + + speakers = audio_info->flags.info.ALLSPEAKERS; + channels = speakers_to_channels(audio_info->flags.speaker_flags).all; + + /* DisplayPort only allows for one audio stream with stream ID 0 */ + REG_UPDATE(APG_CONTROL2, APG_DP_AUDIO_STREAM_ID, 0); + + /* When running in "pair mode", pairs of audio channels have their own enable + * this is for really old audio drivers */ + REG_UPDATE(APG_DBG_GEN_CONTROL, APG_DBG_AUDIO_CHANNEL_ENABLE, 0xF); + // REG_UPDATE(APG_DBG_GEN_CONTROL, APG_DBG_AUDIO_CHANNEL_ENABLE, channels); + + /* Disable forced mem power off */ + REG_UPDATE(APG_MEM_PWR, APG_MEM_PWR_FORCE, 0); + + apg31_enable(apg); +} + +static void apg31_audio_mute_control( + struct apg *apg, + bool mute) +{ + if (mute) + apg31_disable(apg); + else + apg31_enable(apg); +} + +static struct apg_funcs dcn31_apg_funcs = { + .se_audio_setup = apg31_se_audio_setup, + .audio_mute_control = apg31_audio_mute_control, + .enable_apg = apg31_enable, + .disable_apg = apg31_disable, +}; + +void apg31_construct(struct dcn31_apg *apg31, + struct dc_context *ctx, + uint32_t inst, + const struct dcn31_apg_registers *apg_regs, + const struct dcn31_apg_shift *apg_shift, + const struct dcn31_apg_mask *apg_mask) +{ + apg31->base.ctx = ctx; + + apg31->base.inst = inst; + apg31->base.funcs = &dcn31_apg_funcs; + + apg31->regs = apg_regs; + apg31->apg_shift = apg_shift; + apg31->apg_mask = apg_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h new file mode 100644 index 0000000000000..24f568e120d84 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h @@ -0,0 +1,115 @@ +/* + * Copyright 2020 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 __DAL_DCN31_AGP_H__ +#define __DAL_DCN31_AGP_H__ + + +#define DCN31_APG_FROM_APG(apg)\ + container_of(apg, struct dcn31_apg, base) + +#define APG_DCN31_REG_LIST(id) \ + SRI(APG_CONTROL, APG, id), \ + SRI(APG_CONTROL2, APG, id),\ + SRI(APG_MEM_PWR, APG, id),\ + SRI(APG_DBG_GEN_CONTROL, APG, id) + +struct dcn31_apg_registers { + uint32_t APG_CONTROL; + uint32_t APG_CONTROL2; + uint32_t APG_MEM_PWR; + uint32_t APG_DBG_GEN_CONTROL; +}; + + +#define DCN31_APG_MASK_SH_LIST(mask_sh)\ + SE_SF(APG0_APG_CONTROL, APG_RESET, mask_sh),\ + SE_SF(APG0_APG_CONTROL, APG_RESET_DONE, mask_sh),\ + SE_SF(APG0_APG_CONTROL2, APG_ENABLE, mask_sh),\ + SE_SF(APG0_APG_CONTROL2, APG_DP_AUDIO_STREAM_ID, mask_sh),\ + SE_SF(APG0_APG_DBG_GEN_CONTROL, APG_DBG_AUDIO_CHANNEL_ENABLE, mask_sh),\ + SE_SF(APG0_APG_MEM_PWR, APG_MEM_PWR_FORCE, mask_sh) + +#define APG_DCN31_REG_FIELD_LIST(type) \ + type APG_RESET;\ + type APG_RESET_DONE;\ + type APG_ENABLE;\ + type APG_DP_AUDIO_STREAM_ID;\ + type APG_DBG_AUDIO_CHANNEL_ENABLE;\ + type APG_MEM_PWR_FORCE + +struct dcn31_apg_shift { + APG_DCN31_REG_FIELD_LIST(uint8_t); +}; + +struct dcn31_apg_mask { + APG_DCN31_REG_FIELD_LIST(uint32_t); +}; + +struct apg { + const struct apg_funcs *funcs; + struct dc_context *ctx; + int inst; +}; + +struct apg_funcs { + + void (*setup_hdmi_audio)( + struct apg *apg); + + void (*se_audio_setup)( + struct apg *apg, + unsigned int az_inst, + struct audio_info *audio_info); + + void (*audio_mute_control)( + struct apg *apg, + bool mute); + + void (*enable_apg)( + struct apg *apg); + + void (*disable_apg)( + struct apg *apg); +}; + + + +struct dcn31_apg { + struct apg base; + const struct dcn31_apg_registers *regs; + const struct dcn31_apg_shift *apg_shift; + const struct dcn31_apg_mask *apg_mask; +}; + +void apg31_construct(struct dcn31_apg *apg3, + struct dc_context *ctx, + uint32_t inst, + const struct dcn31_apg_registers *apg_regs, + const struct dcn31_apg_shift *apg_shift, + const struct dcn31_apg_mask *apg_mask); + + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index a7702d3c75cdd..7355864117e6e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -52,6 +52,7 @@ #include "dcn30/dcn30_vpg.h" #include "dcn30/dcn30_afmt.h" #include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn31/dcn31_apg.h" #include "dcn31/dcn31_dio_link_encoder.h" #include "dce/dce_clock_source.h" #include "dce/dce_audio.h" @@ -457,6 +458,26 @@ static const struct dcn30_afmt_mask afmt_mask = { DCN3_AFMT_MASK_SH_LIST(_MASK) }; +#define apg_regs(id)\ +[id] = {\ + APG_DCN31_REG_LIST(id)\ +} + +static const struct dcn31_apg_registers apg_regs[] = { + apg_regs(0), + apg_regs(1), + apg_regs(2), + apg_regs(3) +}; + +static const struct dcn31_apg_shift apg_shift = { + DCN31_APG_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_apg_mask apg_mask = { + DCN31_APG_MASK_SH_LIST(_MASK) +}; + #define stream_enc_regs(id)\ [id] = {\ SE_DCN3_REG_LIST(id)\ @@ -1260,6 +1281,23 @@ static struct afmt *dcn31_afmt_create( return &afmt3->base; } +static struct apg *dcn31_apg_create( + struct dc_context *ctx, + uint32_t inst) +{ + struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL); + + if (!apg31) + return NULL; + + apg31_construct(apg31, ctx, inst, + &apg_regs[inst], + &apg_shift, + &apg_mask); + + return &apg31->base; +} + static struct stream_encoder *dcn31_stream_encoder_create( enum engine_id eng_id, struct dc_context *ctx) From 83228ebb82e4fe2e5513f35d9b0b0eded3c44cbc Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Wed, 9 Jun 2021 15:21:35 -0400 Subject: [PATCH 002/151] drm/amd/display: Add DP 2.0 HPO Stream Encoder HW Blocks: +--------+ +-----+ +------+ | OPTC | | HDA | | HUBP | +--------+ +-----+ +------+ | | | | | | HPO ====|==========|========|==== | | v | | | +-----+ | | | | APG | | | | +-----+ | | | | | v v v v +----------------------+ | HPO Stream Encoder | +----------------------+ [squash in warning fixes - Alex] Signed-off-by: Fangzhi Zuo Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 33 + drivers/gpu/drm/amd/display/dc/dcn31/Makefile | 2 +- .../dc/dcn31/dcn31_hpo_dp_stream_encoder.c | 747 ++++++++++++++++++ .../dc/dcn31/dcn31_hpo_dp_stream_encoder.h | 241 ++++++ .../drm/amd/display/dc/dcn31/dcn31_resource.c | 85 ++ .../gpu/drm/amd/display/dc/inc/core_types.h | 10 + .../gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 3 + .../amd/display/dc/inc/hw/stream_encoder.h | 81 ++ drivers/gpu/drm/amd/display/dc/inc/resource.h | 8 + .../amd/display/include/grph_object_defs.h | 12 + .../drm/amd/display/include/grph_object_id.h | 8 + 11 files changed, 1229 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index df8a7718a85fc..be98f5513fe5c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -466,6 +466,39 @@ void dcn10_log_hw_state(struct dc *dc, log_mpc_crc(dc, log_ctx); + { + int hpo_dp_link_enc_count = 0; + + if (pool->hpo_dp_stream_enc_count > 0) { + DTN_INFO("DP HPO S_ENC: Enabled OTG Format Depth Vid SDP Compressed Link\n"); + for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) { + struct hpo_dp_stream_encoder_state hpo_dp_se_state = {0}; + struct hpo_dp_stream_encoder *hpo_dp_stream_enc = pool->hpo_dp_stream_enc[i]; + + if (hpo_dp_stream_enc && hpo_dp_stream_enc->funcs->read_state) { + hpo_dp_stream_enc->funcs->read_state(hpo_dp_stream_enc, &hpo_dp_se_state); + + DTN_INFO("[%d]: %d %d %6s %d %d %d %d %d\n", + hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0, + hpo_dp_se_state.stream_enc_enabled, + hpo_dp_se_state.otg_inst, + (hpo_dp_se_state.pixel_encoding == 0) ? "4:4:4" : + ((hpo_dp_se_state.pixel_encoding == 1) ? "4:2:2" : + (hpo_dp_se_state.pixel_encoding == 2) ? "4:2:0" : "Y-Only"), + (hpo_dp_se_state.component_depth == 0) ? 6 : + ((hpo_dp_se_state.component_depth == 1) ? 8 : + (hpo_dp_se_state.component_depth == 2) ? 10 : 12), + hpo_dp_se_state.vid_stream_enabled, + hpo_dp_se_state.sdp_enabled, + hpo_dp_se_state.compressed_format, + hpo_dp_se_state.mapped_to_link_enc); + } + } + + DTN_INFO("\n"); + } + } + DTN_INFO_END(); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile index bc2087f6dcb27..8b811f589524a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile @@ -12,7 +12,7 @@ DCN31 = dcn31_resource.o dcn31_hubbub.o dcn31_hwseq.o dcn31_init.o dcn31_hubp.o \ dcn31_dccg.o dcn31_optc.o dcn31_dio_link_encoder.o dcn31_panel_cntl.o \ - dcn31_apg.o + dcn31_apg.o dcn31_hpo_dp_stream_encoder.o ifdef CONFIG_X86 CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o := -msse diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c new file mode 100644 index 0000000000000..25e4794eb9ad5 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c @@ -0,0 +1,747 @@ +/* + * Copyright 2019 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 + * + */ + +#include "dc_bios_types.h" +#include "dcn31_hpo_dp_stream_encoder.h" +#include "reg_helper.h" +#include "dc_link.h" + +#define DC_LOGGER \ + enc3->base.ctx->logger + +#define REG(reg)\ + (enc3->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc3->hpo_se_shift->field_name, enc3->hpo_se_mask->field_name + +#define CTX \ + enc3->base.ctx + + +enum dp2_pixel_encoding { + DP_SYM32_ENC_PIXEL_ENCODING_RGB_YCBCR444, + DP_SYM32_ENC_PIXEL_ENCODING_YCBCR422, + DP_SYM32_ENC_PIXEL_ENCODING_YCBCR420, + DP_SYM32_ENC_PIXEL_ENCODING_Y_ONLY +}; + +enum dp2_uncompressed_component_depth { + DP_SYM32_ENC_COMPONENT_DEPTH_6BPC, + DP_SYM32_ENC_COMPONENT_DEPTH_8BPC, + DP_SYM32_ENC_COMPONENT_DEPTH_10BPC, + DP_SYM32_ENC_COMPONENT_DEPTH_12BPC +}; + + +static void dcn31_hpo_dp_stream_enc_enable_stream( + struct hpo_dp_stream_encoder *enc) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + + /* Enable all clocks in the DP_STREAM_ENC */ + REG_UPDATE(DP_STREAM_ENC_CLOCK_CONTROL, + DP_STREAM_ENC_CLOCK_EN, 1); + + /* Assert reset to the DP_SYM32_ENC logic */ + REG_UPDATE(DP_SYM32_ENC_CONTROL, + DP_SYM32_ENC_RESET, 1); + /* Wait for reset to complete (to assert) */ + REG_WAIT(DP_SYM32_ENC_CONTROL, + DP_SYM32_ENC_RESET_DONE, 1, + 1, 10); + + /* De-assert reset to the DP_SYM32_ENC logic */ + REG_UPDATE(DP_SYM32_ENC_CONTROL, + DP_SYM32_ENC_RESET, 0); + /* Wait for reset to de-assert */ + REG_WAIT(DP_SYM32_ENC_CONTROL, + DP_SYM32_ENC_RESET_DONE, 0, + 1, 10); + + /* Enable idle pattern generation */ + REG_UPDATE(DP_SYM32_ENC_CONTROL, + DP_SYM32_ENC_ENABLE, 1); +} + +static void dcn31_hpo_dp_stream_enc_dp_unblank( + struct hpo_dp_stream_encoder *enc, + uint32_t stream_source) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + + /* Set the input mux for video stream source */ + REG_UPDATE(DP_STREAM_ENC_INPUT_MUX_CONTROL, + DP_STREAM_ENC_INPUT_MUX_PIXEL_STREAM_SOURCE_SEL, stream_source); + + /* Enable video transmission in main framer */ + REG_UPDATE(DP_SYM32_ENC_VID_STREAM_CONTROL, + VID_STREAM_ENABLE, 1); + + /* Reset and Enable Pixel to Symbol FIFO */ + REG_UPDATE(DP_SYM32_ENC_VID_FIFO_CONTROL, + PIXEL_TO_SYMBOL_FIFO_RESET, 1); + REG_WAIT(DP_SYM32_ENC_VID_FIFO_CONTROL, + PIXEL_TO_SYMBOL_FIFO_RESET_DONE, 1, + 1, 10); + REG_UPDATE(DP_SYM32_ENC_VID_FIFO_CONTROL, + PIXEL_TO_SYMBOL_FIFO_RESET, 0); + REG_WAIT(DP_SYM32_ENC_VID_FIFO_CONTROL, /* Disable Clock Ramp Adjuster FIFO */ + PIXEL_TO_SYMBOL_FIFO_RESET_DONE, 0, + 1, 10); + REG_UPDATE(DP_SYM32_ENC_VID_FIFO_CONTROL, + PIXEL_TO_SYMBOL_FIFO_ENABLE, 1); + + /* Reset and Enable Clock Ramp Adjuster FIFO */ + REG_UPDATE(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, + FIFO_RESET, 1); + REG_WAIT(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, + FIFO_RESET_DONE, 1, + 1, 10); + REG_UPDATE(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, + FIFO_RESET, 0); + REG_WAIT(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, + FIFO_RESET_DONE, 0, + 1, 10); + + /* For Debug -- Enable CRC */ + REG_UPDATE_2(DP_SYM32_ENC_VID_CRC_CONTROL, + CRC_ENABLE, 1, + CRC_CONT_MODE_ENABLE, 1); + + REG_UPDATE(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, + FIFO_ENABLE, 1); +} + +static void dcn31_hpo_dp_stream_enc_dp_blank( + struct hpo_dp_stream_encoder *enc) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + + /* Disable video transmission */ + REG_UPDATE(DP_SYM32_ENC_VID_STREAM_CONTROL, + VID_STREAM_ENABLE, 0); + + /* Wait for video stream transmission disabled + * Larger delay to wait until VBLANK - use max retry of + * 10us*5000=50ms. This covers 41.7ms of minimum 24 Hz mode + + * a little more because we may not trust delay accuracy. + */ + //REG_WAIT(DP_SYM32_ENC_VID_STREAM_CONTROL, + // VID_STREAM_STATUS, 0, + // 10, 5000); + + /* Disable SDP tranmission */ + REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, + SDP_STREAM_ENABLE, 0); + + /* Disable Pixel to Symbol FIFO */ + REG_UPDATE(DP_SYM32_ENC_VID_FIFO_CONTROL, + PIXEL_TO_SYMBOL_FIFO_ENABLE, 0); + + /* Disable Clock Ramp Adjuster FIFO */ + REG_UPDATE(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, + FIFO_ENABLE, 0); +} + +static void dcn31_hpo_dp_stream_enc_disable( + struct hpo_dp_stream_encoder *enc) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + + /* Disable DP_SYM32_ENC */ + REG_UPDATE(DP_SYM32_ENC_CONTROL, + DP_SYM32_ENC_ENABLE, 0); + + /* Disable clocks in the DP_STREAM_ENC */ + REG_UPDATE(DP_STREAM_ENC_CLOCK_CONTROL, + DP_STREAM_ENC_CLOCK_EN, 0); +} + +static void dcn31_hpo_dp_stream_enc_set_stream_attribute( + struct hpo_dp_stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space, + bool use_vsc_sdp_for_colorimetry, + bool compressed_format, + bool double_buffer_en) +{ + enum dp2_pixel_encoding pixel_encoding; + enum dp2_uncompressed_component_depth component_depth; + uint32_t h_active_start; + uint32_t v_active_start; + uint32_t h_blank; + uint32_t h_back_porch; + uint32_t h_width; + uint32_t v_height; + unsigned long long v_freq; + uint8_t misc0 = 0; + uint8_t misc1 = 0; + uint8_t hsp; + uint8_t vsp; + + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + struct dc_crtc_timing hw_crtc_timing = *crtc_timing; + + /* MISC0[0] = 0 video and link clocks are asynchronous + * MISC1[0] = 0 interlace not supported + * MISC1[2:1] = 0 stereo field is handled by hardware + * MISC1[5:3] = 0 Reserved + */ + + /* Interlaced not supported */ + if (hw_crtc_timing.flags.INTERLACE) { + BREAK_TO_DEBUGGER(); + } + + /* Double buffer enable for MSA and pixel format registers + * Only double buffer for changing stream attributes for active streams + * Do not double buffer when initially enabling a stream + */ + REG_UPDATE(DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, + MSA_DOUBLE_BUFFER_ENABLE, double_buffer_en); + REG_UPDATE(DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, + PIXEL_FORMAT_DOUBLE_BUFFER_ENABLE, double_buffer_en); + + /* Pixel Encoding */ + switch (hw_crtc_timing.pixel_encoding) { + case PIXEL_ENCODING_YCBCR422: + pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_YCBCR422; + misc0 = misc0 | 0x2; // MISC0[2:1] = 01 + break; + case PIXEL_ENCODING_YCBCR444: + pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_RGB_YCBCR444; + misc0 = misc0 | 0x4; // MISC0[2:1] = 10 + + if (hw_crtc_timing.flags.Y_ONLY) { + pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_Y_ONLY; + if (hw_crtc_timing.display_color_depth != COLOR_DEPTH_666) { + /* HW testing only, no use case yet. + * Color depth of Y-only could be + * 8, 10, 12, 16 bits + */ + misc1 = misc1 | 0x80; // MISC1[7] = 1 + } + } + break; + case PIXEL_ENCODING_YCBCR420: + pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_YCBCR420; + misc1 = misc1 | 0x40; // MISC1[6] = 1 + break; + case PIXEL_ENCODING_RGB: + default: + pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_RGB_YCBCR444; + break; + } + + /* For YCbCr420 and BT2020 Colorimetry Formats, VSC SDP shall be used. + * When MISC1, bit 6, is Set to 1, a Source device uses a VSC SDP to indicate the + * Pixel Encoding/Colorimetry Format and that a Sink device shall ignore MISC1, bit 7, + * and MISC0, bits 7:1 (MISC1, bit 7, and MISC0, bits 7:1, become "don't care"). + */ + if (use_vsc_sdp_for_colorimetry) + misc1 = misc1 | 0x40; + else + misc1 = misc1 & ~0x40; + + /* Color depth */ + switch (hw_crtc_timing.display_color_depth) { + case COLOR_DEPTH_666: + component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_6BPC; + // MISC0[7:5] = 000 + break; + case COLOR_DEPTH_888: + component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_8BPC; + misc0 = misc0 | 0x20; // MISC0[7:5] = 001 + break; + case COLOR_DEPTH_101010: + component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_10BPC; + misc0 = misc0 | 0x40; // MISC0[7:5] = 010 + break; + case COLOR_DEPTH_121212: + component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_12BPC; + misc0 = misc0 | 0x60; // MISC0[7:5] = 011 + break; + default: + component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_6BPC; + break; + } + + REG_UPDATE_3(DP_SYM32_ENC_VID_PIXEL_FORMAT, + PIXEL_ENCODING_TYPE, compressed_format, + UNCOMPRESSED_PIXEL_ENCODING, pixel_encoding, + UNCOMPRESSED_COMPONENT_DEPTH, component_depth); + + switch (output_color_space) { + case COLOR_SPACE_SRGB: + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + break; + case COLOR_SPACE_SRGB_LIMITED: + misc0 = misc0 | 0x8; /* bit3=1 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + break; + case COLOR_SPACE_YCBCR601: + case COLOR_SPACE_YCBCR601_LIMITED: + misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ + else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) + misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ + break; + case COLOR_SPACE_YCBCR709: + case COLOR_SPACE_YCBCR709_LIMITED: + misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */ + misc1 = misc1 & ~0x80; /* bit7 = 0*/ + if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) + misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ + else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) + misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ + break; + case COLOR_SPACE_2020_RGB_LIMITEDRANGE: + case COLOR_SPACE_2020_RGB_FULLRANGE: + case COLOR_SPACE_2020_YCBCR: + case COLOR_SPACE_XR_RGB: + case COLOR_SPACE_MSREF_SCRGB: + case COLOR_SPACE_ADOBERGB: + case COLOR_SPACE_DCIP3: + case COLOR_SPACE_XV_YCC_709: + case COLOR_SPACE_XV_YCC_601: + case COLOR_SPACE_DISPLAYNATIVE: + case COLOR_SPACE_DOLBYVISION: + case COLOR_SPACE_APPCTRL: + case COLOR_SPACE_CUSTOMPOINTS: + case COLOR_SPACE_UNKNOWN: + case COLOR_SPACE_YCBCR709_BLACK: + /* do nothing */ + break; + } + + /* calculate from vesa timing parameters + * h_active_start related to leading edge of sync + */ + h_blank = hw_crtc_timing.h_total - hw_crtc_timing.h_border_left - + hw_crtc_timing.h_addressable - hw_crtc_timing.h_border_right; + + h_back_porch = h_blank - hw_crtc_timing.h_front_porch - + hw_crtc_timing.h_sync_width; + + /* start at beginning of left border */ + h_active_start = hw_crtc_timing.h_sync_width + h_back_porch; + + v_active_start = hw_crtc_timing.v_total - hw_crtc_timing.v_border_top - + hw_crtc_timing.v_addressable - hw_crtc_timing.v_border_bottom - + hw_crtc_timing.v_front_porch; + + h_width = hw_crtc_timing.h_border_left + hw_crtc_timing.h_addressable + hw_crtc_timing.h_border_right; + v_height = hw_crtc_timing.v_border_top + hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom; + hsp = hw_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ? 0x80 : 0; + vsp = hw_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? 0x80 : 0; + v_freq = hw_crtc_timing.pix_clk_100hz * 100; + + /* MSA Packet Mapping to 32-bit Link Symbols - DP2 spec, section 2.7.4.1 + * + * Lane 0 Lane 1 Lane 2 Lane 3 + * MSA[0] = { 0, 0, 0, VFREQ[47:40]} + * MSA[1] = { 0, 0, 0, VFREQ[39:32]} + * MSA[2] = { 0, 0, 0, VFREQ[31:24]} + * MSA[3] = { HTotal[15:8], HStart[15:8], HWidth[15:8], VFREQ[23:16]} + * MSA[4] = { HTotal[ 7:0], HStart[ 7:0], HWidth[ 7:0], VFREQ[15: 8]} + * MSA[5] = { VTotal[15:8], VStart[15:8], VHeight[15:8], VFREQ[ 7: 0]} + * MSA[6] = { VTotal[ 7:0], VStart[ 7:0], VHeight[ 7:0], MISC0[ 7: 0]} + * MSA[7] = { HSP|HSW[14:8], VSP|VSW[14:8], 0, MISC1[ 7: 0]} + * MSA[8] = { HSW[ 7:0], VSW[ 7:0], 0, 0} + */ + REG_SET_4(DP_SYM32_ENC_VID_MSA0, 0, + MSA_DATA_LANE_0, 0, + MSA_DATA_LANE_1, 0, + MSA_DATA_LANE_2, 0, + MSA_DATA_LANE_3, v_freq >> 40); + + REG_SET_4(DP_SYM32_ENC_VID_MSA1, 0, + MSA_DATA_LANE_0, 0, + MSA_DATA_LANE_1, 0, + MSA_DATA_LANE_2, 0, + MSA_DATA_LANE_3, (v_freq >> 32) & 0xff); + + REG_SET_4(DP_SYM32_ENC_VID_MSA2, 0, + MSA_DATA_LANE_0, 0, + MSA_DATA_LANE_1, 0, + MSA_DATA_LANE_2, 0, + MSA_DATA_LANE_3, (v_freq >> 24) & 0xff); + + REG_SET_4(DP_SYM32_ENC_VID_MSA3, 0, + MSA_DATA_LANE_0, hw_crtc_timing.h_total >> 8, + MSA_DATA_LANE_1, h_active_start >> 8, + MSA_DATA_LANE_2, h_width >> 8, + MSA_DATA_LANE_3, (v_freq >> 16) & 0xff); + + REG_SET_4(DP_SYM32_ENC_VID_MSA4, 0, + MSA_DATA_LANE_0, hw_crtc_timing.h_total & 0xff, + MSA_DATA_LANE_1, h_active_start & 0xff, + MSA_DATA_LANE_2, h_width & 0xff, + MSA_DATA_LANE_3, (v_freq >> 8) & 0xff); + + REG_SET_4(DP_SYM32_ENC_VID_MSA5, 0, + MSA_DATA_LANE_0, hw_crtc_timing.v_total >> 8, + MSA_DATA_LANE_1, v_active_start >> 8, + MSA_DATA_LANE_2, v_height >> 8, + MSA_DATA_LANE_3, v_freq & 0xff); + + REG_SET_4(DP_SYM32_ENC_VID_MSA6, 0, + MSA_DATA_LANE_0, hw_crtc_timing.v_total & 0xff, + MSA_DATA_LANE_1, v_active_start & 0xff, + MSA_DATA_LANE_2, v_height & 0xff, + MSA_DATA_LANE_3, misc0); + + REG_SET_4(DP_SYM32_ENC_VID_MSA7, 0, + MSA_DATA_LANE_0, hsp | (hw_crtc_timing.h_sync_width >> 8), + MSA_DATA_LANE_1, vsp | (hw_crtc_timing.v_sync_width >> 8), + MSA_DATA_LANE_2, 0, + MSA_DATA_LANE_3, misc1); + + REG_SET_4(DP_SYM32_ENC_VID_MSA8, 0, + MSA_DATA_LANE_0, hw_crtc_timing.h_sync_width & 0xff, + MSA_DATA_LANE_1, hw_crtc_timing.v_sync_width & 0xff, + MSA_DATA_LANE_2, 0, + MSA_DATA_LANE_3, 0); +} + +static void dcn31_hpo_dp_stream_enc_update_dp_info_packets( + struct hpo_dp_stream_encoder *enc, + const struct encoder_info_frame *info_frame) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + uint32_t dmdata_packet_enabled = 0; + bool sdp_stream_enable = false; + + if (info_frame->vsc.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 0, /* packetIndex */ + &info_frame->vsc); + sdp_stream_enable = true; + } + if (info_frame->spd.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 2, /* packetIndex */ + &info_frame->spd); + sdp_stream_enable = true; + } + if (info_frame->hdrsmd.valid) { + enc->vpg->funcs->update_generic_info_packet( + enc->vpg, + 3, /* packetIndex */ + &info_frame->hdrsmd); + sdp_stream_enable = true; + } + /* enable/disable transmission of packet(s). + * If enabled, packet transmission begins on the next frame + */ + REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->vsc.valid); + REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL2, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->spd.valid); + REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL3, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->hdrsmd.valid); + + /* check if dynamic metadata packet transmission is enabled */ + REG_GET(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, + METADATA_PACKET_ENABLE, &dmdata_packet_enabled); + + /* Enable secondary data path */ + REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, + SDP_STREAM_ENABLE, 1); +} + +static void dcn31_hpo_dp_stream_enc_stop_dp_info_packets( + struct hpo_dp_stream_encoder *enc) +{ + /* stop generic packets on DP */ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + uint32_t asp_enable = 0; + uint32_t atp_enable = 0; + uint32_t aip_enable = 0; + uint32_t acm_enable = 0; + + REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 0); + REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL2, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 0); + REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL3, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 0); + + /* Disable secondary data path if audio is also disabled */ + REG_GET_4(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, + ASP_ENABLE, &asp_enable, + ATP_ENABLE, &atp_enable, + AIP_ENABLE, &aip_enable, + ACM_ENABLE, &acm_enable); + if (!(asp_enable || atp_enable || aip_enable || acm_enable)) + REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, + SDP_STREAM_ENABLE, 0); +} + +static uint32_t hpo_dp_is_gsp_enabled( + struct hpo_dp_stream_encoder *enc) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + uint32_t gsp0_enabled = 0; + uint32_t gsp2_enabled = 0; + uint32_t gsp3_enabled = 0; + uint32_t gsp11_enabled = 0; + + REG_GET(DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, &gsp0_enabled); + REG_GET(DP_SYM32_ENC_SDP_GSP_CONTROL2, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, &gsp2_enabled); + REG_GET(DP_SYM32_ENC_SDP_GSP_CONTROL3, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, &gsp3_enabled); + REG_GET(DP_SYM32_ENC_SDP_GSP_CONTROL11, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, &gsp11_enabled); + + return (gsp0_enabled || gsp2_enabled || gsp3_enabled || gsp11_enabled); +} + +static void dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet( + struct hpo_dp_stream_encoder *enc, + bool enable, + uint8_t *dsc_packed_pps) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + + if (enable) { + struct dc_info_packet pps_sdp; + int i; + + /* Configure for PPS packet size (128 bytes) */ + REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL11, + GSP_PAYLOAD_SIZE, 3); + + /* Load PPS into infoframe (SDP) registers */ + pps_sdp.valid = true; + pps_sdp.hb0 = 0; + pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; + pps_sdp.hb2 = 127; + pps_sdp.hb3 = 0; + + for (i = 0; i < 4; i++) { + memcpy(pps_sdp.sb, &dsc_packed_pps[i * 32], 32); + enc3->base.vpg->funcs->update_generic_info_packet( + enc3->base.vpg, + 11 + i, + &pps_sdp); + } + + /* SW should make sure VBID[6] update line number is bigger + * than PPS transmit line number + */ + REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL11, + GSP_TRANSMISSION_LINE_NUMBER, 2); + + REG_UPDATE_2(DP_SYM32_ENC_VID_VBID_CONTROL, + VBID_6_COMPRESSEDSTREAM_FLAG_SOF_REFERENCE, 0, + VBID_6_COMPRESSEDSTREAM_FLAG_LINE_NUMBER, 3); + + /* Send PPS data at the line number specified above. */ + REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL11, + GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 1); + REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, + SDP_STREAM_ENABLE, 1); + } else { + /* Disable Generic Stream Packet 11 (GSP) transmission */ + REG_UPDATE_2(DP_SYM32_ENC_SDP_GSP_CONTROL11, + GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 0, + GSP_PAYLOAD_SIZE, 0); + } +} + +static void dcn31_hpo_dp_stream_enc_map_stream_to_link( + struct hpo_dp_stream_encoder *enc, + uint32_t stream_enc_inst, + uint32_t link_enc_inst) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + + ASSERT(stream_enc_inst < 4 && link_enc_inst < 2); + + switch (stream_enc_inst) { + case 0: + REG_UPDATE(DP_STREAM_MAPPER_CONTROL0, + DP_STREAM_LINK_TARGET, link_enc_inst); + break; + case 1: + REG_UPDATE(DP_STREAM_MAPPER_CONTROL1, + DP_STREAM_LINK_TARGET, link_enc_inst); + break; + case 2: + REG_UPDATE(DP_STREAM_MAPPER_CONTROL2, + DP_STREAM_LINK_TARGET, link_enc_inst); + break; + case 3: + REG_UPDATE(DP_STREAM_MAPPER_CONTROL3, + DP_STREAM_LINK_TARGET, link_enc_inst); + break; + } +} + +static void dcn31_hpo_dp_stream_enc_mute_control( + struct hpo_dp_stream_encoder *enc, + bool mute) +{ + ASSERT(enc->apg); + enc->apg->funcs->audio_mute_control(enc->apg, mute); +} + +static void dcn31_hpo_dp_stream_enc_audio_setup( + struct hpo_dp_stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + + /* Set the input mux for video stream source */ + REG_UPDATE(DP_STREAM_ENC_AUDIO_CONTROL, + DP_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst); + + ASSERT(enc->apg); + enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info); +} + +static void dcn31_hpo_dp_stream_enc_audio_enable( + struct hpo_dp_stream_encoder *enc) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + + /* Enable Audio packets */ + REG_UPDATE(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ASP_ENABLE, 1); + + /* Program the ATP and AIP next */ + REG_UPDATE_2(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, + ATP_ENABLE, 1, + AIP_ENABLE, 1); + + /* Enable secondary data path */ + REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, + SDP_STREAM_ENABLE, 1); + + /* Enable APG block */ + enc->apg->funcs->enable_apg(enc->apg); +} + +static void dcn31_hpo_dp_stream_enc_audio_disable( + struct hpo_dp_stream_encoder *enc) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + + /* Disable Audio packets */ + REG_UPDATE_4(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, + ASP_ENABLE, 0, + ATP_ENABLE, 0, + AIP_ENABLE, 0, + ACM_ENABLE, 0); + + /* Disable STP Stream Enable if other SDP GSP are also disabled */ + if (!(hpo_dp_is_gsp_enabled(enc))) + REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, + SDP_STREAM_ENABLE, 0); + + /* Disable APG block */ + enc->apg->funcs->disable_apg(enc->apg); +} + +static void dcn31_hpo_dp_stream_enc_read_state( + struct hpo_dp_stream_encoder *enc, + struct hpo_dp_stream_encoder_state *s) +{ + struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); + + REG_GET(DP_SYM32_ENC_CONTROL, + DP_SYM32_ENC_ENABLE, &s->stream_enc_enabled); + REG_GET(DP_SYM32_ENC_VID_STREAM_CONTROL, + VID_STREAM_ENABLE, &s->vid_stream_enabled); + REG_GET(DP_STREAM_ENC_INPUT_MUX_CONTROL, + DP_STREAM_ENC_INPUT_MUX_PIXEL_STREAM_SOURCE_SEL, &s->otg_inst); + + REG_GET_3(DP_SYM32_ENC_VID_PIXEL_FORMAT, + PIXEL_ENCODING_TYPE, &s->compressed_format, + UNCOMPRESSED_PIXEL_ENCODING, &s->pixel_encoding, + UNCOMPRESSED_COMPONENT_DEPTH, &s->component_depth); + + REG_GET(DP_SYM32_ENC_SDP_CONTROL, + SDP_STREAM_ENABLE, &s->sdp_enabled); + + switch (enc->inst) { + case 0: + REG_GET(DP_STREAM_MAPPER_CONTROL0, + DP_STREAM_LINK_TARGET, &s->mapped_to_link_enc); + break; + case 1: + REG_GET(DP_STREAM_MAPPER_CONTROL1, + DP_STREAM_LINK_TARGET, &s->mapped_to_link_enc); + break; + case 2: + REG_GET(DP_STREAM_MAPPER_CONTROL2, + DP_STREAM_LINK_TARGET, &s->mapped_to_link_enc); + break; + case 3: + REG_GET(DP_STREAM_MAPPER_CONTROL3, + DP_STREAM_LINK_TARGET, &s->mapped_to_link_enc); + break; + } +} + +static const struct hpo_dp_stream_encoder_funcs dcn30_str_enc_funcs = { + .enable_stream = dcn31_hpo_dp_stream_enc_enable_stream, + .dp_unblank = dcn31_hpo_dp_stream_enc_dp_unblank, + .dp_blank = dcn31_hpo_dp_stream_enc_dp_blank, + .disable = dcn31_hpo_dp_stream_enc_disable, + .set_stream_attribute = dcn31_hpo_dp_stream_enc_set_stream_attribute, + .update_dp_info_packets = dcn31_hpo_dp_stream_enc_update_dp_info_packets, + .stop_dp_info_packets = dcn31_hpo_dp_stream_enc_stop_dp_info_packets, + .dp_set_dsc_pps_info_packet = dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet, + .map_stream_to_link = dcn31_hpo_dp_stream_enc_map_stream_to_link, + .audio_mute_control = dcn31_hpo_dp_stream_enc_mute_control, + .dp_audio_setup = dcn31_hpo_dp_stream_enc_audio_setup, + .dp_audio_enable = dcn31_hpo_dp_stream_enc_audio_enable, + .dp_audio_disable = dcn31_hpo_dp_stream_enc_audio_disable, + .read_state = dcn31_hpo_dp_stream_enc_read_state, +}; + +void dcn31_hpo_dp_stream_encoder_construct( + struct dcn31_hpo_dp_stream_encoder *enc3, + struct dc_context *ctx, + struct dc_bios *bp, + uint32_t inst, + enum engine_id eng_id, + struct vpg *vpg, + struct apg *apg, + const struct dcn31_hpo_dp_stream_encoder_registers *regs, + const struct dcn31_hpo_dp_stream_encoder_shift *hpo_se_shift, + const struct dcn31_hpo_dp_stream_encoder_mask *hpo_se_mask) +{ + enc3->base.funcs = &dcn30_str_enc_funcs; + enc3->base.ctx = ctx; + enc3->base.inst = inst; + enc3->base.id = eng_id; + enc3->base.bp = bp; + enc3->base.vpg = vpg; + enc3->base.apg = apg; + enc3->regs = regs; + enc3->hpo_se_shift = hpo_se_shift; + enc3->hpo_se_mask = hpo_se_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h new file mode 100644 index 0000000000000..70b94fc25304b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.h @@ -0,0 +1,241 @@ +/* + * Copyright 2019 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 __DAL_DCN31_HPO_DP_STREAM_ENCODER_H__ +#define __DAL_DCN31_HPO_DP_STREAM_ENCODER_H__ + +#include "dcn30/dcn30_vpg.h" +#include "dcn31/dcn31_apg.h" +#include "stream_encoder.h" + + +#define DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(hpo_dp_stream_encoder)\ + container_of(hpo_dp_stream_encoder, struct dcn31_hpo_dp_stream_encoder, base) + + +/* Define MSA_DATA_LANE_[0-3] fields to make programming easier */ +#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_0__SHIFT 0x0 +#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_1__SHIFT 0x8 +#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_2__SHIFT 0x10 +#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_3__SHIFT 0x18 +#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_0_MASK 0x000000FFL +#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_1_MASK 0x0000FF00L +#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_2_MASK 0x00FF0000L +#define DP_SYM32_ENC_VID_MSA__MSA_DATA_LANE_3_MASK 0xFF000000L + + +#define DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id) \ + SR(DP_STREAM_MAPPER_CONTROL0),\ + SR(DP_STREAM_MAPPER_CONTROL1),\ + SR(DP_STREAM_MAPPER_CONTROL2),\ + SR(DP_STREAM_MAPPER_CONTROL3),\ + SRI(DP_STREAM_ENC_CLOCK_CONTROL, DP_STREAM_ENC, id),\ + SRI(DP_STREAM_ENC_INPUT_MUX_CONTROL, DP_STREAM_ENC, id),\ + SRI(DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC, id),\ + SRI(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, DP_STREAM_ENC, id),\ + SRI(DP_SYM32_ENC_CONTROL, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_PIXEL_FORMAT, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_MSA0, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_MSA1, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_MSA2, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_MSA3, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_MSA4, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_MSA5, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_MSA6, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_MSA7, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_MSA8, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_MSA_CONTROL, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_FIFO_CONTROL, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_STREAM_CONTROL, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_VBID_CONTROL, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_SDP_CONTROL, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_SDP_GSP_CONTROL0, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_SDP_GSP_CONTROL2, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_SDP_GSP_CONTROL3, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_SDP_GSP_CONTROL5, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_SDP_GSP_CONTROL11, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, DP_SYM32_ENC, id),\ + SRI(DP_SYM32_ENC_VID_CRC_CONTROL, DP_SYM32_ENC, id) + +#define DCN3_1_HPO_DP_STREAM_ENC_REGS \ + uint32_t DP_STREAM_MAPPER_CONTROL0;\ + uint32_t DP_STREAM_MAPPER_CONTROL1;\ + uint32_t DP_STREAM_MAPPER_CONTROL2;\ + uint32_t DP_STREAM_MAPPER_CONTROL3;\ + uint32_t DP_STREAM_ENC_CLOCK_CONTROL;\ + uint32_t DP_STREAM_ENC_INPUT_MUX_CONTROL;\ + uint32_t DP_STREAM_ENC_AUDIO_CONTROL;\ + uint32_t DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0;\ + uint32_t DP_SYM32_ENC_CONTROL;\ + uint32_t DP_SYM32_ENC_VID_PIXEL_FORMAT;\ + uint32_t DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL;\ + uint32_t DP_SYM32_ENC_VID_MSA0;\ + uint32_t DP_SYM32_ENC_VID_MSA1;\ + uint32_t DP_SYM32_ENC_VID_MSA2;\ + uint32_t DP_SYM32_ENC_VID_MSA3;\ + uint32_t DP_SYM32_ENC_VID_MSA4;\ + uint32_t DP_SYM32_ENC_VID_MSA5;\ + uint32_t DP_SYM32_ENC_VID_MSA6;\ + uint32_t DP_SYM32_ENC_VID_MSA7;\ + uint32_t DP_SYM32_ENC_VID_MSA8;\ + uint32_t DP_SYM32_ENC_VID_MSA_CONTROL;\ + uint32_t DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL;\ + uint32_t DP_SYM32_ENC_VID_FIFO_CONTROL;\ + uint32_t DP_SYM32_ENC_VID_STREAM_CONTROL;\ + uint32_t DP_SYM32_ENC_VID_VBID_CONTROL;\ + uint32_t DP_SYM32_ENC_SDP_CONTROL;\ + uint32_t DP_SYM32_ENC_SDP_GSP_CONTROL0;\ + uint32_t DP_SYM32_ENC_SDP_GSP_CONTROL2;\ + uint32_t DP_SYM32_ENC_SDP_GSP_CONTROL3;\ + uint32_t DP_SYM32_ENC_SDP_GSP_CONTROL5;\ + uint32_t DP_SYM32_ENC_SDP_GSP_CONTROL11;\ + uint32_t DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL;\ + uint32_t DP_SYM32_ENC_SDP_AUDIO_CONTROL0;\ + uint32_t DP_SYM32_ENC_VID_CRC_CONTROL + + +#define DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(mask_sh)\ + SE_SF(DP_STREAM_MAPPER_CONTROL0, DP_STREAM_LINK_TARGET, mask_sh),\ + SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_CONTROL, DP_STREAM_ENC_CLOCK_EN, mask_sh),\ + SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_INPUT_MUX_CONTROL, DP_STREAM_ENC_INPUT_MUX_PIXEL_STREAM_SOURCE_SEL, mask_sh),\ + SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, mask_sh),\ + SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET, mask_sh),\ + SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET_DONE, mask_sh),\ + SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_CONTROL, DP_SYM32_ENC_RESET, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_CONTROL, DP_SYM32_ENC_RESET_DONE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_CONTROL, DP_SYM32_ENC_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT, PIXEL_ENCODING_TYPE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT, UNCOMPRESSED_PIXEL_ENCODING, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT, UNCOMPRESSED_COMPONENT_DEPTH, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, PIXEL_FORMAT_DOUBLE_BUFFER_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, MSA_DOUBLE_BUFFER_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_0, mask_sh),\ + SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_1, mask_sh),\ + SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_2, mask_sh),\ + SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_3, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_FIFO_CONTROL, PIXEL_TO_SYMBOL_FIFO_RESET, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_FIFO_CONTROL, PIXEL_TO_SYMBOL_FIFO_RESET_DONE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_FIFO_CONTROL, PIXEL_TO_SYMBOL_FIFO_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_STREAM_CONTROL, VID_STREAM_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_STREAM_CONTROL, VID_STREAM_STATUS, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_VBID_CONTROL, VBID_6_COMPRESSEDSTREAM_FLAG_SOF_REFERENCE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_VBID_CONTROL, VBID_6_COMPRESSEDSTREAM_FLAG_LINE_NUMBER, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_CONTROL, SDP_STREAM_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_PAYLOAD_SIZE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_TRANSMISSION_LINE_NUMBER, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_TRANSMISSION_LINE_NUMBER, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_SOF_REFERENCE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, METADATA_PACKET_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, AUDIO_MUTE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ASP_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ATP_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, AIP_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ACM_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL, CRC_ENABLE, mask_sh),\ + SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL, CRC_CONT_MODE_ENABLE, mask_sh) + + +#define DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(type) \ + type DP_STREAM_LINK_TARGET;\ + type DP_STREAM_ENC_CLOCK_EN;\ + type DP_STREAM_ENC_INPUT_MUX_PIXEL_STREAM_SOURCE_SEL;\ + type DP_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL;\ + type FIFO_RESET;\ + type FIFO_RESET_DONE;\ + type FIFO_ENABLE;\ + type DP_SYM32_ENC_RESET;\ + type DP_SYM32_ENC_RESET_DONE;\ + type DP_SYM32_ENC_ENABLE;\ + type PIXEL_ENCODING_TYPE;\ + type UNCOMPRESSED_PIXEL_ENCODING;\ + type UNCOMPRESSED_COMPONENT_DEPTH;\ + type PIXEL_FORMAT_DOUBLE_BUFFER_ENABLE;\ + type MSA_DOUBLE_BUFFER_ENABLE;\ + type MSA_DATA_LANE_0;\ + type MSA_DATA_LANE_1;\ + type MSA_DATA_LANE_2;\ + type MSA_DATA_LANE_3;\ + type PIXEL_TO_SYMBOL_FIFO_RESET;\ + type PIXEL_TO_SYMBOL_FIFO_RESET_DONE;\ + type PIXEL_TO_SYMBOL_FIFO_ENABLE;\ + type VID_STREAM_ENABLE;\ + type VID_STREAM_STATUS;\ + type VBID_6_COMPRESSEDSTREAM_FLAG_SOF_REFERENCE;\ + type VBID_6_COMPRESSEDSTREAM_FLAG_LINE_NUMBER;\ + type SDP_STREAM_ENABLE;\ + type AUDIO_MUTE;\ + type ASP_ENABLE;\ + type ATP_ENABLE;\ + type AIP_ENABLE;\ + type ACM_ENABLE;\ + type GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE;\ + type GSP_PAYLOAD_SIZE;\ + type GSP_TRANSMISSION_LINE_NUMBER;\ + type GSP_SOF_REFERENCE;\ + type METADATA_PACKET_ENABLE;\ + type CRC_ENABLE;\ + type CRC_CONT_MODE_ENABLE + + +struct dcn31_hpo_dp_stream_encoder_registers { + DCN3_1_HPO_DP_STREAM_ENC_REGS; +}; + +struct dcn31_hpo_dp_stream_encoder_shift { + DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint8_t); +}; + +struct dcn31_hpo_dp_stream_encoder_mask { + DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint32_t); +}; + +struct dcn31_hpo_dp_stream_encoder { + struct hpo_dp_stream_encoder base; + const struct dcn31_hpo_dp_stream_encoder_registers *regs; + const struct dcn31_hpo_dp_stream_encoder_shift *hpo_se_shift; + const struct dcn31_hpo_dp_stream_encoder_mask *hpo_se_mask; +}; + + +void dcn31_hpo_dp_stream_encoder_construct( + struct dcn31_hpo_dp_stream_encoder *enc3, + struct dc_context *ctx, + struct dc_bios *bp, + uint32_t inst, + enum engine_id eng_id, + struct vpg *vpg, + struct apg *apg, + const struct dcn31_hpo_dp_stream_encoder_registers *regs, + const struct dcn31_hpo_dp_stream_encoder_shift *hpo_se_shift, + const struct dcn31_hpo_dp_stream_encoder_mask *hpo_se_mask); + + +#endif // __DAL_DCN31_HPO_STREAM_ENCODER_H__ diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 7355864117e6e..1994a8d3883d8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -52,6 +52,7 @@ #include "dcn30/dcn30_vpg.h" #include "dcn30/dcn30_afmt.h" #include "dcn30/dcn30_dio_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_stream_encoder.h" #include "dcn31/dcn31_apg.h" #include "dcn31/dcn31_dio_link_encoder.h" #include "dce/dce_clock_source.h" @@ -564,6 +565,26 @@ static const struct dcn10_link_enc_mask le_mask = { DPP_REG_LIST_DCN30(id),\ } +#define hpo_dp_stream_encoder_reg_list(id)\ +[id] = {\ + DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\ +} + +static const struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[] = { + hpo_dp_stream_encoder_reg_list(0), + hpo_dp_stream_encoder_reg_list(1), + hpo_dp_stream_encoder_reg_list(2), + hpo_dp_stream_encoder_reg_list(3), +}; + +static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { + DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) +}; + static const struct dcn3_dpp_registers dpp_regs[] = { dpp_regs(0), dpp_regs(1), @@ -900,6 +921,7 @@ static const struct resource_caps res_cap_dcn31 = { .num_audio = 5, .num_stream_encoder = 5, .num_dig_link_enc = 5, + .num_hpo_dp_stream_encoder = 4, .num_pll = 5, .num_dwb = 1, .num_ddc = 5, @@ -1330,6 +1352,52 @@ static struct stream_encoder *dcn31_stream_encoder_create( return &enc1->base; } +static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( + enum engine_id eng_id, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31; + struct vpg *vpg; + struct apg *apg; + uint32_t hpo_dp_inst; + uint32_t vpg_inst; + uint32_t apg_inst; + + ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3)); + hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0; + + /* Mapping of VPG register blocks to HPO DP block instance: + * VPG[6] -> HPO_DP[0] + * VPG[7] -> HPO_DP[1] + * VPG[8] -> HPO_DP[2] + * VPG[9] -> HPO_DP[3] + */ + vpg_inst = hpo_dp_inst + 6; + + /* Mapping of APG register blocks to HPO DP block instance: + * APG[0] -> HPO_DP[0] + * APG[1] -> HPO_DP[1] + * APG[2] -> HPO_DP[2] + * APG[3] -> HPO_DP[3] + */ + apg_inst = hpo_dp_inst; + + /* allocate HPO stream encoder and create VPG sub-block */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL); + vpg = dcn31_vpg_create(ctx, vpg_inst); + apg = dcn31_apg_create(ctx, apg_inst); + + if (!hpo_dp_enc31 || !vpg || !apg) + return NULL; + + dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, + hpo_dp_inst, eng_id, vpg, apg, + &hpo_dp_stream_enc_regs[hpo_dp_inst], + &hpo_dp_se_shift, &hpo_dp_se_mask); + + return &hpo_dp_enc31->base; +} + static struct dce_hwseq *dcn31_hwseq_create( struct dc_context *ctx) { @@ -1347,6 +1415,7 @@ static const struct resource_create_funcs res_create_funcs = { .read_dce_straps = read_dce_straps, .create_audio = dcn31_create_audio, .create_stream_encoder = dcn31_stream_encoder_create, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, .create_hwseq = dcn31_hwseq_create, }; @@ -1354,6 +1423,7 @@ static const struct resource_create_funcs res_create_maximus_funcs = { .read_dce_straps = NULL, .create_audio = NULL, .create_stream_encoder = NULL, + .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, .create_hwseq = dcn31_hwseq_create, }; @@ -1376,6 +1446,21 @@ static void dcn31_resource_destruct(struct dcn31_resource_pool *pool) } } + for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) { + if (pool->base.hpo_dp_stream_enc[i] != NULL) { + if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) { + kfree(DCN30_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg)); + pool->base.hpo_dp_stream_enc[i]->vpg = NULL; + } + if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) { + kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg)); + pool->base.hpo_dp_stream_enc[i]->apg = NULL; + } + kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i])); + pool->base.hpo_dp_stream_enc[i] = NULL; + } + } + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { if (pool->base.dscs[i] != NULL) dcn20_dsc_destroy(&pool->base.dscs[i]); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 45a6216dfa2ad..19dbfc8a44bb2 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -246,6 +246,10 @@ struct resource_pool { */ unsigned int dig_link_enc_count; +#if defined(CONFIG_DRM_AMD_DC_DCN) + unsigned int hpo_dp_stream_enc_count; + struct hpo_dp_stream_encoder *hpo_dp_stream_enc[MAX_HPO_DP2_ENCODERS]; +#endif #if defined(CONFIG_DRM_AMD_DC_DCN) struct dc_3dlut *mpc_lut[MAX_PIPES]; struct dc_transfer_func *mpc_shaper[MAX_PIPES]; @@ -298,6 +302,9 @@ struct stream_resource { struct display_stream_compressor *dsc; struct timing_generator *tg; struct stream_encoder *stream_enc; +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct hpo_dp_stream_encoder *hpo_dp_stream_enc; +#endif struct audio *audio; struct pixel_clk_params pix_clk_params; @@ -388,6 +395,9 @@ struct resource_context { struct link_enc_assignment link_enc_assignments[MAX_PIPES]; /* List of available link encoders. Uses engine ID as encoder identifier. */ enum engine_id link_enc_avail[MAX_DIG_LINK_ENCODERS]; +#if defined(CONFIG_DRM_AMD_DC_DCN) + bool is_hpo_dp_stream_enc_acquired[MAX_HPO_DP2_ENCODERS]; +#endif #if defined(CONFIG_DRM_AMD_DC_DCN) bool is_mpc_3dlut_acquired[MAX_PIPES]; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index 31a1713bb49ff..ad9e9e2d52b02 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -38,6 +38,9 @@ #define MAX_PIPES 6 #define MAX_DIG_LINK_ENCODERS 7 #define MAX_DWB_PIPES 1 +#if defined(CONFIG_DRM_AMD_DC_DCN) +#define MAX_HPO_DP2_ENCODERS 4 +#endif struct gamma_curve { uint32_t offset; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 564ea6a727b08..40a138a9593fe 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -242,4 +242,85 @@ struct stream_encoder_funcs { struct stream_encoder *enc); }; +#if defined(CONFIG_DRM_AMD_DC_DCN) +struct hpo_dp_stream_encoder_state { + uint32_t stream_enc_enabled; + uint32_t vid_stream_enabled; + uint32_t otg_inst; + uint32_t pixel_encoding; + uint32_t component_depth; + uint32_t compressed_format; + uint32_t sdp_enabled; + uint32_t mapped_to_link_enc; +}; + +struct hpo_dp_stream_encoder { + const struct hpo_dp_stream_encoder_funcs *funcs; + struct dc_context *ctx; + struct dc_bios *bp; + uint32_t inst; + enum engine_id id; + struct vpg *vpg; + struct apg *apg; +}; + +struct hpo_dp_stream_encoder_funcs { + void (*enable_stream)( + struct hpo_dp_stream_encoder *enc); + + void (*dp_unblank)( + struct hpo_dp_stream_encoder *enc, + uint32_t stream_source); + + void (*dp_blank)( + struct hpo_dp_stream_encoder *enc); + + void (*disable)( + struct hpo_dp_stream_encoder *enc); + + void (*set_stream_attribute)( + struct hpo_dp_stream_encoder *enc, + struct dc_crtc_timing *crtc_timing, + enum dc_color_space output_color_space, + bool use_vsc_sdp_for_colorimetry, + bool compressed_format, + bool double_buffer_en); + + void (*update_dp_info_packets)( + struct hpo_dp_stream_encoder *enc, + const struct encoder_info_frame *info_frame); + + void (*stop_dp_info_packets)( + struct hpo_dp_stream_encoder *enc); + + void (*dp_set_dsc_pps_info_packet)( + struct hpo_dp_stream_encoder *enc, + bool enable, + uint8_t *dsc_packed_pps); + + void (*map_stream_to_link)( + struct hpo_dp_stream_encoder *enc, + uint32_t stream_enc_inst, + uint32_t link_enc_inst); + + void (*audio_mute_control)( + struct hpo_dp_stream_encoder *enc, bool mute); + + void (*dp_audio_setup)( + struct hpo_dp_stream_encoder *enc, + unsigned int az_inst, + struct audio_info *info); + + void (*dp_audio_enable)( + struct hpo_dp_stream_encoder *enc); + + void (*dp_audio_disable)( + struct hpo_dp_stream_encoder *enc); + + void (*read_state)( + struct hpo_dp_stream_encoder *enc, + struct hpo_dp_stream_encoder_state *state); +}; +#endif + #endif /* STREAM_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index fe1e5833c96a0..5a2cfc8990446 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -49,6 +49,9 @@ struct resource_caps { int num_vmid; int num_dsc; unsigned int num_dig_link_enc; // Total number of DIGs (digital encoders) in DIO (Display Input/Output). +#if defined(CONFIG_DRM_AMD_DC_DCN) + int num_hpo_dp_stream_encoder; +#endif int num_mpc_3dlut; }; @@ -68,6 +71,11 @@ struct resource_create_funcs { struct stream_encoder *(*create_stream_encoder)( enum engine_id eng_id, struct dc_context *ctx); +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct hpo_dp_stream_encoder *(*create_hpo_dp_stream_encoder)( + enum engine_id eng_id, struct dc_context *ctx); +#endif + struct dce_hwseq *(*create_hwseq)( struct dc_context *ctx); }; diff --git a/drivers/gpu/drm/amd/display/include/grph_object_defs.h b/drivers/gpu/drm/amd/display/include/grph_object_defs.h index 58bb42ed85cab..84b299ff500a2 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_defs.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_defs.h @@ -140,6 +140,18 @@ enum sync_source { SYNC_SOURCE_DUAL_GPU_PIN }; +#if defined(CONFIG_DRM_AMD_DC_DCN) +enum tx_ffe_id { + TX_FFE0 = 0, + TX_FFE1, + TX_FFE2, + TX_FFE3, + TX_FFE_DeEmphasis_Only, + TX_FFE_PreShoot_Only, + TX_FFE_No_FFE, +}; +#endif + /* connector sizes in millimeters - from BiosParserTypes.hpp */ #define CONNECTOR_SIZE_DVI 40 #define CONNECTOR_SIZE_VGA 32 diff --git a/drivers/gpu/drm/amd/display/include/grph_object_id.h b/drivers/gpu/drm/amd/display/include/grph_object_id.h index 33b3d755fe655..01775417cf4b6 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_id.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_id.h @@ -184,6 +184,14 @@ enum engine_id { ENGINE_ID_DACA, ENGINE_ID_DACB, ENGINE_ID_VCE, /* wireless display pseudo-encoder */ +#if defined(CONFIG_DRM_AMD_DC_DCN) + ENGINE_ID_HPO_0, + ENGINE_ID_HPO_1, + ENGINE_ID_HPO_DP_0, + ENGINE_ID_HPO_DP_1, + ENGINE_ID_HPO_DP_2, + ENGINE_ID_HPO_DP_3, +#endif ENGINE_ID_VIRTUAL, ENGINE_ID_COUNT, From 3bc8d9214679cc4dbd1dee634bd98a5996adbcfb Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Tue, 3 Aug 2021 13:48:54 -0400 Subject: [PATCH 003/151] drm/amd/display: Add DP 2.0 HPO Link Encoder HW Blocks: +--------+ +-----+ +------+ | OPTC | | HDA | | HUBP | +--------+ +-----+ +------+ | | | | | | HPO ====|==========|========|==== | | v | | | +-----+ | | | | APG | | | | +-----+ | | | | | | v v v | +---------------------+ | | HPO Stream Encoder | | +---------------------+ | | | v | +--------------------+ | | HPO Link Encoder | v +--------------------+ [squash in warning fixes - Alex] Signed-off-by: Fangzhi Zuo Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_link.h | 4 + .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 32 + drivers/gpu/drm/amd/display/dc/dcn31/Makefile | 2 +- .../display/dc/dcn31/dcn31_dio_link_encoder.c | 4 + .../dc/dcn31/dcn31_hpo_dp_link_encoder.c | 616 ++++++++++++++++++ .../dc/dcn31/dcn31_hpo_dp_link_encoder.h | 222 +++++++ .../drm/amd/display/dc/dcn31/dcn31_resource.c | 50 ++ .../gpu/drm/amd/display/dc/inc/core_types.h | 2 + .../gpu/drm/amd/display/dc/inc/hw/hw_shared.h | 1 + .../drm/amd/display/dc/inc/hw/link_encoder.h | 87 +++ drivers/gpu/drm/amd/display/dc/inc/resource.h | 5 + .../amd/display/include/link_service_types.h | 17 + 12 files changed, 1041 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 83845d006c54a..4450078213a27 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -45,6 +45,10 @@ struct dc_link_status { struct link_mst_stream_allocation { /* DIG front */ const struct stream_encoder *stream_enc; +#if defined(CONFIG_DRM_AMD_DC_DCN) + /* HPO DP Stream Encoder */ + const struct hpo_dp_stream_encoder *hpo_dp_stream_enc; +#endif /* associate DRM payload table with DC stream encoder */ uint8_t vcp_id; /* number of slots required for the DP stream in transport packet */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index be98f5513fe5c..70d47773c23c9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -497,6 +497,38 @@ void dcn10_log_hw_state(struct dc *dc, DTN_INFO("\n"); } + + /* log DP HPO L_ENC section if any hpo_dp_link_enc exists */ + for (i = 0; i < dc->link_count; i++) + if (dc->links[i]->hpo_dp_link_enc) + hpo_dp_link_enc_count++; + + if (hpo_dp_link_enc_count) { + DTN_INFO("DP HPO L_ENC: Enabled Mode Lanes Stream Slots VC Rate X VC Rate Y\n"); + + for (i = 0; i < dc->link_count; i++) { + struct hpo_dp_link_encoder *hpo_dp_link_enc = dc->links[i]->hpo_dp_link_enc; + struct hpo_dp_link_enc_state hpo_dp_le_state = {0}; + + if (hpo_dp_link_enc && hpo_dp_link_enc->funcs->read_state) { + hpo_dp_link_enc->funcs->read_state(hpo_dp_link_enc, &hpo_dp_le_state); + DTN_INFO("[%d]: %d %6s %d %d %d %d %d\n", + hpo_dp_link_enc->inst, + hpo_dp_le_state.link_enc_enabled, + (hpo_dp_le_state.link_mode == 0) ? "TPS1" : + (hpo_dp_le_state.link_mode == 1) ? "TPS2" : + (hpo_dp_le_state.link_mode == 2) ? "ACTIVE" : "TEST", + hpo_dp_le_state.lane_count, + hpo_dp_le_state.stream_src[0], + hpo_dp_le_state.slot_count[0], + hpo_dp_le_state.vc_rate_x[0], + hpo_dp_le_state.vc_rate_y[0]); + DTN_INFO("\n"); + } + } + + DTN_INFO("\n"); + } } DTN_INFO_END(); diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile index 8b811f589524a..5197825e79656 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile @@ -12,7 +12,7 @@ DCN31 = dcn31_resource.o dcn31_hubbub.o dcn31_hwseq.o dcn31_init.o dcn31_hubp.o \ dcn31_dccg.o dcn31_optc.o dcn31_dio_link_encoder.o dcn31_panel_cntl.o \ - dcn31_apg.o dcn31_hpo_dp_stream_encoder.o + dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o ifdef CONFIG_X86 CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o := -msse diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c index 90127c1f9e35d..77b81f6c24b9f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c @@ -320,6 +320,10 @@ void dcn31_link_encoder_construct( enc10->base.features.flags.bits.IS_HBR3_CAPABLE = bp_cap_info.DP_HBR3_EN; enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; + enc10->base.features.flags.bits.IS_DP2_CAPABLE = bp_cap_info.IS_DP2_CAPABLE; + enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; + enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; enc10->base.features.flags.bits.DP_IS_USB_C = bp_cap_info.DP_IS_USB_C; } else { diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c new file mode 100644 index 0000000000000..6c08e21bb7080 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c @@ -0,0 +1,616 @@ +/* + * Copyright 2019 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 + * + */ + +#include "dc_bios_types.h" +#include "dcn31_hpo_dp_link_encoder.h" +#include "reg_helper.h" +#include "dc_link.h" +#include "stream_encoder.h" + +#define DC_LOGGER \ + enc3->base.ctx->logger + +#define REG(reg)\ + (enc3->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + enc3->hpo_le_shift->field_name, enc3->hpo_le_mask->field_name + + +#define CTX \ + enc3->base.ctx + +enum { + DP_SAT_UPDATE_MAX_RETRY = 200 +}; + +void dcn31_hpo_dp_link_enc_enable( + struct hpo_dp_link_encoder *enc, + enum dc_lane_count num_lanes) +{ + struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc); + uint32_t dp_link_enabled; + + /* get current status of link enabled */ + REG_GET(DP_DPHY_SYM32_STATUS, + STATUS, &dp_link_enabled); + + /* Enable clocks first */ + REG_UPDATE(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC_CLOCK_EN, 1); + + /* Reset DPHY. Only reset if going from disable to enable */ + if (!dp_link_enabled) { + REG_UPDATE(DP_DPHY_SYM32_CONTROL, DPHY_RESET, 1); + REG_UPDATE(DP_DPHY_SYM32_CONTROL, DPHY_RESET, 0); + } + + /* Configure DPHY settings */ + REG_UPDATE_3(DP_DPHY_SYM32_CONTROL, + DPHY_ENABLE, 1, + PRECODER_ENABLE, 1, + NUM_LANES, num_lanes == LANE_COUNT_ONE ? 0 : num_lanes == LANE_COUNT_TWO ? 1 : 3); +} + +void dcn31_hpo_dp_link_enc_disable( + struct hpo_dp_link_encoder *enc) +{ + struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc); + + /* Configure DPHY settings */ + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + DPHY_ENABLE, 0); + + /* Shut down clock last */ + REG_UPDATE(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC_CLOCK_EN, 0); +} + +void dcn31_hpo_dp_link_enc_set_link_test_pattern( + struct hpo_dp_link_encoder *enc, + struct encoder_set_dp_phy_pattern_param *tp_params) +{ + struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc); + uint32_t tp_custom; + + switch (tp_params->dp_phy_pattern) { + case DP_TEST_PATTERN_VIDEO_MODE: + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + MODE, DP2_LINK_ACTIVE); + break; + case DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE: + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + MODE, DP2_LINK_TRAINING_TPS1); + break; + case DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE: + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + MODE, DP2_LINK_TRAINING_TPS2); + break; + case DP_TEST_PATTERN_128b_132b_TPS1: + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_SELECT0, DP_DPHY_TP_SELECT_TPS1, + TP_SELECT1, DP_DPHY_TP_SELECT_TPS1, + TP_SELECT2, DP_DPHY_TP_SELECT_TPS1, + TP_SELECT3, DP_DPHY_TP_SELECT_TPS1); + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + MODE, DP2_TEST_PATTERN); + break; + case DP_TEST_PATTERN_128b_132b_TPS2: + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_SELECT0, DP_DPHY_TP_SELECT_TPS2, + TP_SELECT1, DP_DPHY_TP_SELECT_TPS2, + TP_SELECT2, DP_DPHY_TP_SELECT_TPS2, + TP_SELECT3, DP_DPHY_TP_SELECT_TPS2); + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + MODE, DP2_TEST_PATTERN); + break; + case DP_TEST_PATTERN_PRBS7: + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_PRBS_SEL0, DP_DPHY_TP_PRBS7, + TP_PRBS_SEL1, DP_DPHY_TP_PRBS7, + TP_PRBS_SEL2, DP_DPHY_TP_PRBS7, + TP_PRBS_SEL3, DP_DPHY_TP_PRBS7); + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_SELECT0, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT1, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT2, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT3, DP_DPHY_TP_SELECT_PRBS); + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + MODE, DP2_TEST_PATTERN); + break; + case DP_TEST_PATTERN_PRBS9: + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_PRBS_SEL0, DP_DPHY_TP_PRBS9, + TP_PRBS_SEL1, DP_DPHY_TP_PRBS9, + TP_PRBS_SEL2, DP_DPHY_TP_PRBS9, + TP_PRBS_SEL3, DP_DPHY_TP_PRBS9); + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_SELECT0, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT1, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT2, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT3, DP_DPHY_TP_SELECT_PRBS); + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + MODE, DP2_TEST_PATTERN); + break; + case DP_TEST_PATTERN_PRBS11: + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_PRBS_SEL0, DP_DPHY_TP_PRBS11, + TP_PRBS_SEL1, DP_DPHY_TP_PRBS11, + TP_PRBS_SEL2, DP_DPHY_TP_PRBS11, + TP_PRBS_SEL3, DP_DPHY_TP_PRBS11); + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_SELECT0, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT1, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT2, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT3, DP_DPHY_TP_SELECT_PRBS); + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + MODE, DP2_TEST_PATTERN); + break; + case DP_TEST_PATTERN_PRBS15: + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_PRBS_SEL0, DP_DPHY_TP_PRBS15, + TP_PRBS_SEL1, DP_DPHY_TP_PRBS15, + TP_PRBS_SEL2, DP_DPHY_TP_PRBS15, + TP_PRBS_SEL3, DP_DPHY_TP_PRBS15); + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_SELECT0, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT1, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT2, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT3, DP_DPHY_TP_SELECT_PRBS); + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + MODE, DP2_TEST_PATTERN); + break; + case DP_TEST_PATTERN_PRBS23: + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_PRBS_SEL0, DP_DPHY_TP_PRBS23, + TP_PRBS_SEL1, DP_DPHY_TP_PRBS23, + TP_PRBS_SEL2, DP_DPHY_TP_PRBS23, + TP_PRBS_SEL3, DP_DPHY_TP_PRBS23); + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_SELECT0, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT1, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT2, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT3, DP_DPHY_TP_SELECT_PRBS); + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + MODE, DP2_TEST_PATTERN); + break; + case DP_TEST_PATTERN_PRBS31: + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_PRBS_SEL0, DP_DPHY_TP_PRBS31, + TP_PRBS_SEL1, DP_DPHY_TP_PRBS31, + TP_PRBS_SEL2, DP_DPHY_TP_PRBS31, + TP_PRBS_SEL3, DP_DPHY_TP_PRBS31); + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_SELECT0, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT1, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT2, DP_DPHY_TP_SELECT_PRBS, + TP_SELECT3, DP_DPHY_TP_SELECT_PRBS); + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + MODE, DP2_TEST_PATTERN); + break; + case DP_TEST_PATTERN_264BIT_CUSTOM: + tp_custom = (tp_params->custom_pattern[2] << 16) | (tp_params->custom_pattern[1] << 8) | tp_params->custom_pattern[0]; + REG_SET(DP_DPHY_SYM32_TP_CUSTOM0, 0, TP_CUSTOM, tp_custom); + tp_custom = (tp_params->custom_pattern[5] << 16) | (tp_params->custom_pattern[4] << 8) | tp_params->custom_pattern[3]; + REG_SET(DP_DPHY_SYM32_TP_CUSTOM1, 0, TP_CUSTOM, tp_custom); + tp_custom = (tp_params->custom_pattern[8] << 16) | (tp_params->custom_pattern[7] << 8) | tp_params->custom_pattern[6]; + REG_SET(DP_DPHY_SYM32_TP_CUSTOM2, 0, TP_CUSTOM, tp_custom); + tp_custom = (tp_params->custom_pattern[11] << 16) | (tp_params->custom_pattern[10] << 8) | tp_params->custom_pattern[9]; + REG_SET(DP_DPHY_SYM32_TP_CUSTOM3, 0, TP_CUSTOM, tp_custom); + tp_custom = (tp_params->custom_pattern[14] << 16) | (tp_params->custom_pattern[13] << 8) | tp_params->custom_pattern[12]; + REG_SET(DP_DPHY_SYM32_TP_CUSTOM4, 0, TP_CUSTOM, tp_custom); + tp_custom = (tp_params->custom_pattern[17] << 16) | (tp_params->custom_pattern[16] << 8) | tp_params->custom_pattern[15]; + REG_SET(DP_DPHY_SYM32_TP_CUSTOM5, 0, TP_CUSTOM, tp_custom); + tp_custom = (tp_params->custom_pattern[20] << 16) | (tp_params->custom_pattern[19] << 8) | tp_params->custom_pattern[18]; + REG_SET(DP_DPHY_SYM32_TP_CUSTOM6, 0, TP_CUSTOM, tp_custom); + tp_custom = (tp_params->custom_pattern[23] << 16) | (tp_params->custom_pattern[22] << 8) | tp_params->custom_pattern[21]; + REG_SET(DP_DPHY_SYM32_TP_CUSTOM7, 0, TP_CUSTOM, tp_custom); + tp_custom = (tp_params->custom_pattern[26] << 16) | (tp_params->custom_pattern[25] << 8) | tp_params->custom_pattern[24]; + REG_SET(DP_DPHY_SYM32_TP_CUSTOM8, 0, TP_CUSTOM, tp_custom); + tp_custom = (tp_params->custom_pattern[29] << 16) | (tp_params->custom_pattern[28] << 8) | tp_params->custom_pattern[27]; + REG_SET(DP_DPHY_SYM32_TP_CUSTOM9, 0, TP_CUSTOM, tp_custom); + tp_custom = (tp_params->custom_pattern[32] << 16) | (tp_params->custom_pattern[31] << 8) | tp_params->custom_pattern[30]; + REG_SET(DP_DPHY_SYM32_TP_CUSTOM10, 0, TP_CUSTOM, tp_custom); + + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_SELECT0, DP_DPHY_TP_SELECT_CUSTOM, + TP_SELECT1, DP_DPHY_TP_SELECT_CUSTOM, + TP_SELECT2, DP_DPHY_TP_SELECT_CUSTOM, + TP_SELECT3, DP_DPHY_TP_SELECT_CUSTOM); + + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + MODE, DP2_TEST_PATTERN); + break; + case DP_TEST_PATTERN_SQUARE_PULSE: + REG_SET(DP_DPHY_SYM32_TP_SQ_PULSE, 0, + TP_SQ_PULSE_WIDTH, tp_params->custom_pattern[0]); + + REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG, + TP_SELECT0, DP_DPHY_TP_SELECT_SQUARE, + TP_SELECT1, DP_DPHY_TP_SELECT_SQUARE, + TP_SELECT2, DP_DPHY_TP_SELECT_SQUARE, + TP_SELECT3, DP_DPHY_TP_SELECT_SQUARE); + + REG_UPDATE(DP_DPHY_SYM32_CONTROL, + MODE, DP2_TEST_PATTERN); + break; + default: + break; + } +} + +static void fill_stream_allocation_row_info( + const struct link_mst_stream_allocation *stream_allocation, + uint32_t *src, + uint32_t *slots) +{ + const struct hpo_dp_stream_encoder *stream_enc = stream_allocation->hpo_dp_stream_enc; + + if (stream_enc && (stream_enc->id >= ENGINE_ID_HPO_DP_0)) { + *src = stream_enc->id - ENGINE_ID_HPO_DP_0; + *slots = stream_allocation->slot_count; + } else { + *src = 0; + *slots = 0; + } +} + +/* programs DP VC payload allocation */ +void dcn31_hpo_dp_link_enc_update_stream_allocation_table( + struct hpo_dp_link_encoder *enc, + const struct link_mst_stream_allocation_table *table) +{ + struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc); + uint32_t slots = 0; + uint32_t src = 0; + + /* --- Set MSE Stream Attribute - + * Setup VC Payload Table on Tx Side, + * Issue allocation change trigger + * to commit payload on both tx and rx side + */ + + /* we should clean-up table each time */ + + if (table->stream_count >= 1) { + fill_stream_allocation_row_info( + &table->stream_allocations[0], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC0, + SAT_STREAM_SOURCE, src, + SAT_SLOT_COUNT, slots); + + if (table->stream_count >= 2) { + fill_stream_allocation_row_info( + &table->stream_allocations[1], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC1, + SAT_STREAM_SOURCE, src, + SAT_SLOT_COUNT, slots); + + if (table->stream_count >= 3) { + fill_stream_allocation_row_info( + &table->stream_allocations[2], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC2, + SAT_STREAM_SOURCE, src, + SAT_SLOT_COUNT, slots); + + if (table->stream_count >= 4) { + fill_stream_allocation_row_info( + &table->stream_allocations[3], + &src, + &slots); + } else { + src = 0; + slots = 0; + } + + REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC3, + SAT_STREAM_SOURCE, src, + SAT_SLOT_COUNT, slots); + + /* --- wait for transaction finish */ + + /* send allocation change trigger (ACT) + * this step first sends the ACT, + * then double buffers the SAT into the hardware + * making the new allocation active on the DP MST mode link + */ + + /* SAT_UPDATE: + * 0 - No Action + * 1 - Update SAT with trigger + * 2 - Update SAT without trigger + */ + REG_UPDATE(DP_DPHY_SYM32_SAT_UPDATE, + SAT_UPDATE, 1); + + /* wait for update to complete + * (i.e. SAT_UPDATE_PENDING field is set to 0) + * No need for HW to enforce keepout. + */ + /* Best case and worst case wait time for SAT_UPDATE_PENDING + * best: 109 us + * worst: 868 us + */ + REG_WAIT(DP_DPHY_SYM32_STATUS, + SAT_UPDATE_PENDING, 0, + 10, DP_SAT_UPDATE_MAX_RETRY); +} + +void dcn31_hpo_dp_link_enc_set_throttled_vcp_size( + struct hpo_dp_link_encoder *enc, + uint32_t stream_encoder_inst, + struct fixed31_32 avg_time_slots_per_mtp) +{ + struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc); + uint32_t x = dc_fixpt_floor( + avg_time_slots_per_mtp); + uint32_t y = dc_fixpt_ceil( + dc_fixpt_shl( + dc_fixpt_sub_int( + avg_time_slots_per_mtp, + x), + 25)); + + switch (stream_encoder_inst) { + case 0: + REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL0, 0, + STREAM_VC_RATE_X, x, + STREAM_VC_RATE_Y, y); + break; + case 1: + REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL1, 0, + STREAM_VC_RATE_X, x, + STREAM_VC_RATE_Y, y); + break; + case 2: + REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL2, 0, + STREAM_VC_RATE_X, x, + STREAM_VC_RATE_Y, y); + break; + case 3: + REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL3, 0, + STREAM_VC_RATE_X, x, + STREAM_VC_RATE_Y, y); + break; + default: + ASSERT(0); + } + + /* Best case and worst case wait time for RATE_UPDATE_PENDING + * best: 116 ns + * worst: 903 ns + */ + /* wait for update to be completed on the link */ + REG_WAIT(DP_DPHY_SYM32_STATUS, + RATE_UPDATE_PENDING, 0, + 1, 10); +} + +static bool dcn31_hpo_dp_link_enc_is_in_alt_mode( + struct hpo_dp_link_encoder *enc) +{ + struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc); + uint32_t dp_alt_mode_disable = 0; + + ASSERT((enc->transmitter >= TRANSMITTER_UNIPHY_A) && (enc->transmitter <= TRANSMITTER_UNIPHY_E)); + + /* if value == 1 alt mode is disabled, otherwise it is enabled */ + REG_GET(RDPCSTX_PHY_CNTL6[enc->transmitter], RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable); + return (dp_alt_mode_disable == 0); +} + +void dcn31_hpo_dp_link_enc_read_state( + struct hpo_dp_link_encoder *enc, + struct hpo_dp_link_enc_state *state) +{ + struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc); + + ASSERT(state); + + REG_GET(DP_DPHY_SYM32_STATUS, + STATUS, &state->link_enc_enabled); + REG_GET(DP_DPHY_SYM32_CONTROL, + NUM_LANES, &state->lane_count); + REG_GET(DP_DPHY_SYM32_CONTROL, + MODE, (uint32_t *)&state->link_mode); + + REG_GET_2(DP_DPHY_SYM32_SAT_VC0, + SAT_STREAM_SOURCE, &state->stream_src[0], + SAT_SLOT_COUNT, &state->slot_count[0]); + REG_GET_2(DP_DPHY_SYM32_SAT_VC1, + SAT_STREAM_SOURCE, &state->stream_src[1], + SAT_SLOT_COUNT, &state->slot_count[1]); + REG_GET_2(DP_DPHY_SYM32_SAT_VC2, + SAT_STREAM_SOURCE, &state->stream_src[2], + SAT_SLOT_COUNT, &state->slot_count[2]); + REG_GET_2(DP_DPHY_SYM32_SAT_VC3, + SAT_STREAM_SOURCE, &state->stream_src[3], + SAT_SLOT_COUNT, &state->slot_count[3]); + + REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL0, + STREAM_VC_RATE_X, &state->vc_rate_x[0], + STREAM_VC_RATE_Y, &state->vc_rate_y[0]); + REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL1, + STREAM_VC_RATE_X, &state->vc_rate_x[1], + STREAM_VC_RATE_Y, &state->vc_rate_y[1]); + REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL2, + STREAM_VC_RATE_X, &state->vc_rate_x[2], + STREAM_VC_RATE_Y, &state->vc_rate_y[2]); + REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL3, + STREAM_VC_RATE_X, &state->vc_rate_x[3], + STREAM_VC_RATE_Y, &state->vc_rate_y[3]); +} + +static enum bp_result link_transmitter_control( + struct dcn31_hpo_dp_link_encoder *enc3, + struct bp_transmitter_control *cntl) +{ + enum bp_result result; + struct dc_bios *bp = enc3->base.ctx->dc_bios; + + result = bp->funcs->transmitter_control(bp, cntl); + + return result; +} + +/* enables DP PHY output for 128b132b encoding */ +void dcn31_hpo_dp_link_enc_enable_dp_output( + struct hpo_dp_link_encoder *enc, + const struct dc_link_settings *link_settings, + enum transmitter transmitter) +{ + struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* Set the transmitter */ + enc3->base.transmitter = transmitter; + + /* Enable the PHY */ + cntl.action = TRANSMITTER_CONTROL_ENABLE; + cntl.engine_id = ENGINE_ID_UNKNOWN; + cntl.transmitter = enc3->base.transmitter; + //cntl.pll_id = clock_source; + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + cntl.lanes_number = link_settings->lane_count; + cntl.hpd_sel = enc3->base.hpd_source; + cntl.pixel_clock = link_settings->link_rate * 1000; + cntl.color_depth = COLOR_DEPTH_UNDEFINED; + cntl.hpo_engine_id = enc->inst + ENGINE_ID_HPO_DP_0; + + result = link_transmitter_control(enc3, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + } +} + +void dcn31_hpo_dp_link_enc_disable_output( + struct hpo_dp_link_encoder *enc, + enum signal_type signal) +{ + struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* disable transmitter */ + cntl.action = TRANSMITTER_CONTROL_DISABLE; + cntl.transmitter = enc3->base.transmitter; + cntl.hpd_sel = enc3->base.hpd_source; + cntl.signal = signal; + + result = link_transmitter_control(enc3, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + return; + } + + /* disable encoder */ + dcn31_hpo_dp_link_enc_disable(enc); +} + +void dcn31_hpo_dp_link_enc_set_ffe( + struct hpo_dp_link_encoder *enc, + const struct dc_link_settings *link_settings, + uint8_t ffe_preset) +{ + struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc); + struct bp_transmitter_control cntl = { 0 }; + enum bp_result result; + + /* disable transmitter */ + cntl.transmitter = enc3->base.transmitter; + cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS; + cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST; + cntl.lanes_number = link_settings->lane_count; + cntl.pixel_clock = link_settings->link_rate * 1000; + cntl.lane_settings = ffe_preset; + + result = link_transmitter_control(enc3, &cntl); + + if (result != BP_RESULT_OK) { + DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n", + __func__); + BREAK_TO_DEBUGGER(); + return; + } +} + +static struct hpo_dp_link_encoder_funcs dcn31_hpo_dp_link_encoder_funcs = { + .enable_link_phy = dcn31_hpo_dp_link_enc_enable_dp_output, + .disable_link_phy = dcn31_hpo_dp_link_enc_disable_output, + .link_enable = dcn31_hpo_dp_link_enc_enable, + .link_disable = dcn31_hpo_dp_link_enc_disable, + .set_link_test_pattern = dcn31_hpo_dp_link_enc_set_link_test_pattern, + .update_stream_allocation_table = dcn31_hpo_dp_link_enc_update_stream_allocation_table, + .set_throttled_vcp_size = dcn31_hpo_dp_link_enc_set_throttled_vcp_size, + .is_in_alt_mode = dcn31_hpo_dp_link_enc_is_in_alt_mode, + .read_state = dcn31_hpo_dp_link_enc_read_state, + .set_ffe = dcn31_hpo_dp_link_enc_set_ffe, +}; + +void hpo_dp_link_encoder31_construct(struct dcn31_hpo_dp_link_encoder *enc31, + struct dc_context *ctx, + uint32_t inst, + const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs, + const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift, + const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask) +{ + enc31->base.ctx = ctx; + + enc31->base.inst = inst; + enc31->base.funcs = &dcn31_hpo_dp_link_encoder_funcs; + enc31->base.hpd_source = HPD_SOURCEID_UNKNOWN; + enc31->base.transmitter = TRANSMITTER_UNKNOWN; + + enc31->regs = hpo_le_regs; + enc31->hpo_le_shift = hpo_le_shift; + enc31->hpo_le_mask = hpo_le_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h new file mode 100644 index 0000000000000..0706ccaf6fec1 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.h @@ -0,0 +1,222 @@ +/* + * Copyright 2019 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 __DAL_DCN31_HPO_DP_LINK_ENCODER_H__ +#define __DAL_DCN31_HPO_DP_LINK_ENCODER_H__ + +#include "link_encoder.h" + + +#define DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(hpo_dp_link_encoder)\ + container_of(hpo_dp_link_encoder, struct dcn31_hpo_dp_link_encoder, base) + + +#define DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id) \ + SRI(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC, id), \ + SRI(DP_DPHY_SYM32_CONTROL, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_STATUS, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_CONFIG, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_PRBS_SEED0, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_PRBS_SEED1, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_PRBS_SEED2, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_PRBS_SEED3, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_SQ_PULSE, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_CUSTOM0, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_CUSTOM1, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_CUSTOM2, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_CUSTOM3, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_CUSTOM4, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_CUSTOM5, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_CUSTOM6, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_CUSTOM7, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_CUSTOM8, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_CUSTOM9, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_TP_CUSTOM10, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_SAT_VC0, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_SAT_VC1, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_SAT_VC2, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_SAT_VC3, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_VC_RATE_CNTL0, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_VC_RATE_CNTL1, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_VC_RATE_CNTL2, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_VC_RATE_CNTL3, DP_DPHY_SYM32, id), \ + SRI(DP_DPHY_SYM32_SAT_UPDATE, DP_DPHY_SYM32, id) + +#define DCN3_1_RDPCSTX_REG_LIST(id) \ + SRII(RDPCSTX_PHY_CNTL6, RDPCSTX, id) + + +#define DCN3_1_HPO_DP_LINK_ENC_REGS \ + uint32_t DP_LINK_ENC_CLOCK_CONTROL;\ + uint32_t DP_DPHY_SYM32_CONTROL;\ + uint32_t DP_DPHY_SYM32_STATUS;\ + uint32_t DP_DPHY_SYM32_TP_CONFIG;\ + uint32_t DP_DPHY_SYM32_TP_PRBS_SEED0;\ + uint32_t DP_DPHY_SYM32_TP_PRBS_SEED1;\ + uint32_t DP_DPHY_SYM32_TP_PRBS_SEED2;\ + uint32_t DP_DPHY_SYM32_TP_PRBS_SEED3;\ + uint32_t DP_DPHY_SYM32_TP_SQ_PULSE;\ + uint32_t DP_DPHY_SYM32_TP_CUSTOM0;\ + uint32_t DP_DPHY_SYM32_TP_CUSTOM1;\ + uint32_t DP_DPHY_SYM32_TP_CUSTOM2;\ + uint32_t DP_DPHY_SYM32_TP_CUSTOM3;\ + uint32_t DP_DPHY_SYM32_TP_CUSTOM4;\ + uint32_t DP_DPHY_SYM32_TP_CUSTOM5;\ + uint32_t DP_DPHY_SYM32_TP_CUSTOM6;\ + uint32_t DP_DPHY_SYM32_TP_CUSTOM7;\ + uint32_t DP_DPHY_SYM32_TP_CUSTOM8;\ + uint32_t DP_DPHY_SYM32_TP_CUSTOM9;\ + uint32_t DP_DPHY_SYM32_TP_CUSTOM10;\ + uint32_t DP_DPHY_SYM32_SAT_VC0;\ + uint32_t DP_DPHY_SYM32_SAT_VC1;\ + uint32_t DP_DPHY_SYM32_SAT_VC2;\ + uint32_t DP_DPHY_SYM32_SAT_VC3;\ + uint32_t DP_DPHY_SYM32_VC_RATE_CNTL0;\ + uint32_t DP_DPHY_SYM32_VC_RATE_CNTL1;\ + uint32_t DP_DPHY_SYM32_VC_RATE_CNTL2;\ + uint32_t DP_DPHY_SYM32_VC_RATE_CNTL3;\ + uint32_t DP_DPHY_SYM32_SAT_UPDATE + +struct dcn31_hpo_dp_link_encoder_registers { + DCN3_1_HPO_DP_LINK_ENC_REGS; + uint32_t RDPCSTX_PHY_CNTL6[5]; +}; + +#define DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(mask_sh)\ + SE_SF(DP_LINK_ENC0_DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC_CLOCK_EN, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, DPHY_RESET, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, DPHY_ENABLE, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, PRECODER_ENABLE, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, MODE, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_CONTROL, NUM_LANES, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_STATUS, STATUS, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_STATUS, SAT_UPDATE_PENDING, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_STATUS, RATE_UPDATE_PENDING, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CUSTOM0, TP_CUSTOM, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT0, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT1, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT2, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_SELECT3, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL0, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL1, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL2, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_CONFIG, TP_PRBS_SEL3, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_TP_SQ_PULSE, TP_SQ_PULSE_WIDTH, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_VC0, SAT_STREAM_SOURCE, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_VC0, SAT_SLOT_COUNT, mask_sh),\ + SE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_VC_RATE_CNTL0, STREAM_VC_RATE_X, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_VC_RATE_CNTL0, STREAM_VC_RATE_Y, mask_sh),\ + SE_SF(DP_DPHY_SYM320_DP_DPHY_SYM32_SAT_UPDATE, SAT_UPDATE, mask_sh) + +#define DCN3_1_HPO_DP_LINK_ENC_REG_FIELD_LIST(type) \ + type DP_LINK_ENC_CLOCK_EN;\ + type DPHY_RESET;\ + type DPHY_ENABLE;\ + type PRECODER_ENABLE;\ + type NUM_LANES;\ + type MODE;\ + type STATUS;\ + type SAT_UPDATE_PENDING;\ + type RATE_UPDATE_PENDING;\ + type TP_CUSTOM;\ + type TP_SELECT0;\ + type TP_SELECT1;\ + type TP_SELECT2;\ + type TP_SELECT3;\ + type TP_PRBS_SEL0;\ + type TP_PRBS_SEL1;\ + type TP_PRBS_SEL2;\ + type TP_PRBS_SEL3;\ + type TP_SQ_PULSE_WIDTH;\ + type SAT_STREAM_SOURCE;\ + type SAT_SLOT_COUNT;\ + type STREAM_VC_RATE_X;\ + type STREAM_VC_RATE_Y;\ + type SAT_UPDATE;\ + type RDPCS_PHY_DPALT_DISABLE + + +struct dcn31_hpo_dp_link_encoder_shift { + DCN3_1_HPO_DP_LINK_ENC_REG_FIELD_LIST(uint8_t); +}; + +struct dcn31_hpo_dp_link_encoder_mask { + DCN3_1_HPO_DP_LINK_ENC_REG_FIELD_LIST(uint32_t); +}; + +struct dcn31_hpo_dp_link_encoder { + struct hpo_dp_link_encoder base; + const struct dcn31_hpo_dp_link_encoder_registers *regs; + const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift; + const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask; +}; + +void hpo_dp_link_encoder31_construct(struct dcn31_hpo_dp_link_encoder *enc31, + struct dc_context *ctx, + uint32_t inst, + const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs, + const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift, + const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask); + +void dcn31_hpo_dp_link_enc_enable_dp_output( + struct hpo_dp_link_encoder *enc, + const struct dc_link_settings *link_settings, + enum transmitter transmitter); + +void dcn31_hpo_dp_link_enc_disable_output( + struct hpo_dp_link_encoder *enc, + enum signal_type signal); + +void dcn31_hpo_dp_link_enc_enable( + struct hpo_dp_link_encoder *enc, + enum dc_lane_count num_lanes); + +void dcn31_hpo_dp_link_enc_disable( + struct hpo_dp_link_encoder *enc); + +void dcn31_hpo_dp_link_enc_set_link_test_pattern( + struct hpo_dp_link_encoder *enc, + struct encoder_set_dp_phy_pattern_param *tp_params); + +void dcn31_hpo_dp_link_enc_update_stream_allocation_table( + struct hpo_dp_link_encoder *enc, + const struct link_mst_stream_allocation_table *table); + +void dcn31_hpo_dp_link_enc_set_throttled_vcp_size( + struct hpo_dp_link_encoder *enc, + uint32_t stream_encoder_inst, + struct fixed31_32 avg_time_slots_per_mtp); + +void dcn31_hpo_dp_link_enc_read_state( + struct hpo_dp_link_encoder *enc, + struct hpo_dp_link_enc_state *state); + +void dcn31_hpo_dp_link_enc_set_ffe( + struct hpo_dp_link_encoder *enc, + const struct dc_link_settings *link_settings, + uint8_t ffe_preset); + +#endif // __DAL_DCN31_HPO_LINK_ENCODER_H__ diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 1994a8d3883d8..f264a32ebade5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -53,6 +53,7 @@ #include "dcn30/dcn30_afmt.h" #include "dcn30/dcn30_dio_stream_encoder.h" #include "dcn31/dcn31_hpo_dp_stream_encoder.h" +#include "dcn31/dcn31_hpo_dp_link_encoder.h" #include "dcn31/dcn31_apg.h" #include "dcn31/dcn31_dio_link_encoder.h" #include "dce/dce_clock_source.h" @@ -585,6 +586,29 @@ static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = { DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK) }; +#define hpo_dp_link_encoder_reg_list(id)\ +[id] = {\ + DCN3_1_HPO_DP_LINK_ENC_REG_LIST(id),\ + DCN3_1_RDPCSTX_REG_LIST(0),\ + DCN3_1_RDPCSTX_REG_LIST(1),\ + DCN3_1_RDPCSTX_REG_LIST(2),\ + DCN3_1_RDPCSTX_REG_LIST(3),\ + DCN3_1_RDPCSTX_REG_LIST(4)\ +} + +static const struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[] = { + hpo_dp_link_encoder_reg_list(0), + hpo_dp_link_encoder_reg_list(1), +}; + +static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT) +}; + +static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { + DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) +}; + static const struct dcn3_dpp_registers dpp_regs[] = { dpp_regs(0), dpp_regs(1), @@ -922,6 +946,7 @@ static const struct resource_caps res_cap_dcn31 = { .num_stream_encoder = 5, .num_dig_link_enc = 5, .num_hpo_dp_stream_encoder = 4, + .num_hpo_dp_link_encoder = 2, .num_pll = 5, .num_dwb = 1, .num_ddc = 5, @@ -1398,6 +1423,22 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( return &hpo_dp_enc31->base; } +static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( + uint8_t inst, + struct dc_context *ctx) +{ + struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31; + + /* allocate HPO link encoder */ + hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + + hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, + &hpo_dp_link_enc_regs[inst], + &hpo_dp_le_shift, &hpo_dp_le_mask); + + return &hpo_dp_enc31->base; +} + static struct dce_hwseq *dcn31_hwseq_create( struct dc_context *ctx) { @@ -1416,6 +1457,7 @@ static const struct resource_create_funcs res_create_funcs = { .create_audio = dcn31_create_audio, .create_stream_encoder = dcn31_stream_encoder_create, .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, .create_hwseq = dcn31_hwseq_create, }; @@ -1424,6 +1466,7 @@ static const struct resource_create_funcs res_create_maximus_funcs = { .create_audio = NULL, .create_stream_encoder = NULL, .create_hpo_dp_stream_encoder = dcn31_hpo_dp_stream_encoder_create, + .create_hpo_dp_link_encoder = dcn31_hpo_dp_link_encoder_create, .create_hwseq = dcn31_hwseq_create, }; @@ -1461,6 +1504,13 @@ static void dcn31_resource_destruct(struct dcn31_resource_pool *pool) } } + for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) { + if (pool->base.hpo_dp_link_enc[i] != NULL) { + kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i])); + pool->base.hpo_dp_link_enc[i] = NULL; + } + } + for (i = 0; i < pool->base.res_cap->num_dsc; i++) { if (pool->base.dscs[i] != NULL) dcn20_dsc_destroy(&pool->base.dscs[i]); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 19dbfc8a44bb2..ed254c2771f08 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -249,6 +249,8 @@ struct resource_pool { #if defined(CONFIG_DRM_AMD_DC_DCN) unsigned int hpo_dp_stream_enc_count; struct hpo_dp_stream_encoder *hpo_dp_stream_enc[MAX_HPO_DP2_ENCODERS]; + unsigned int hpo_dp_link_enc_count; + struct hpo_dp_link_encoder *hpo_dp_link_enc[MAX_HPO_DP2_LINK_ENCODERS]; #endif #if defined(CONFIG_DRM_AMD_DC_DCN) struct dc_3dlut *mpc_lut[MAX_PIPES]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index ad9e9e2d52b02..10ecbc667ffa4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -40,6 +40,7 @@ #define MAX_DWB_PIPES 1 #if defined(CONFIG_DRM_AMD_DC_DCN) #define MAX_HPO_DP2_ENCODERS 4 +#define MAX_HPO_DP2_LINK_ENCODERS 2 #endif struct gamma_curve { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 9eaf345aa2a17..fa3a725e11dcf 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -210,4 +210,91 @@ struct link_enc_assignment { enum engine_id eng_id; }; +#if defined(CONFIG_DRM_AMD_DC_DCN) +enum dp2_link_mode { + DP2_LINK_TRAINING_TPS1, + DP2_LINK_TRAINING_TPS2, + DP2_LINK_ACTIVE, + DP2_TEST_PATTERN +}; + +enum dp2_phy_tp_select { + DP_DPHY_TP_SELECT_TPS1, + DP_DPHY_TP_SELECT_TPS2, + DP_DPHY_TP_SELECT_PRBS, + DP_DPHY_TP_SELECT_CUSTOM, + DP_DPHY_TP_SELECT_SQUARE +}; + +enum dp2_phy_tp_prbs { + DP_DPHY_TP_PRBS7, + DP_DPHY_TP_PRBS9, + DP_DPHY_TP_PRBS11, + DP_DPHY_TP_PRBS15, + DP_DPHY_TP_PRBS23, + DP_DPHY_TP_PRBS31 +}; + +struct hpo_dp_link_enc_state { + uint32_t link_enc_enabled; + uint32_t link_mode; + uint32_t lane_count; + uint32_t slot_count[4]; + uint32_t stream_src[4]; + uint32_t vc_rate_x[4]; + uint32_t vc_rate_y[4]; +}; + +struct hpo_dp_link_encoder { + const struct hpo_dp_link_encoder_funcs *funcs; + struct dc_context *ctx; + int inst; + enum engine_id preferred_engine; + enum transmitter transmitter; + enum hpd_source_id hpd_source; +}; + +struct hpo_dp_link_encoder_funcs { + + void (*enable_link_phy)(struct hpo_dp_link_encoder *enc, + const struct dc_link_settings *link_settings, + enum transmitter transmitter); + + void (*disable_link_phy)(struct hpo_dp_link_encoder *link_enc, + enum signal_type signal); + + void (*link_enable)( + struct hpo_dp_link_encoder *enc, + enum dc_lane_count num_lanes); + + void (*link_disable)( + struct hpo_dp_link_encoder *enc); + + void (*set_link_test_pattern)( + struct hpo_dp_link_encoder *enc, + struct encoder_set_dp_phy_pattern_param *tp_params); + + void (*update_stream_allocation_table)( + struct hpo_dp_link_encoder *enc, + const struct link_mst_stream_allocation_table *table); + + void (*set_throttled_vcp_size)( + struct hpo_dp_link_encoder *enc, + uint32_t stream_encoder_inst, + struct fixed31_32 avg_time_slots_per_mtp); + + bool (*is_in_alt_mode) ( + struct hpo_dp_link_encoder *enc); + + void (*read_state)( + struct hpo_dp_link_encoder *enc, + struct hpo_dp_link_enc_state *state); + + void (*set_ffe)( + struct hpo_dp_link_encoder *enc, + const struct dc_link_settings *link_settings, + uint8_t ffe_preset); +}; +#endif + #endif /* LINK_ENCODER_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 5a2cfc8990446..713f6d5cf3e0e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -51,6 +51,7 @@ struct resource_caps { unsigned int num_dig_link_enc; // Total number of DIGs (digital encoders) in DIO (Display Input/Output). #if defined(CONFIG_DRM_AMD_DC_DCN) int num_hpo_dp_stream_encoder; + int num_hpo_dp_link_encoder; #endif int num_mpc_3dlut; }; @@ -74,6 +75,10 @@ struct resource_create_funcs { #if defined(CONFIG_DRM_AMD_DC_DCN) struct hpo_dp_stream_encoder *(*create_hpo_dp_stream_encoder)( enum engine_id eng_id, struct dc_context *ctx); + + struct hpo_dp_link_encoder *(*create_hpo_dp_link_encoder)( + uint8_t inst, + struct dc_context *ctx); #endif struct dce_hwseq *(*create_hwseq)( diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 32f5274ed34e2..efd9812c13ec2 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -114,13 +114,30 @@ enum dp_test_pattern { DP_TEST_PATTERN_CP2520_2, DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE = DP_TEST_PATTERN_CP2520_2, DP_TEST_PATTERN_CP2520_3, +#if defined(CONFIG_DRM_AMD_DC_DCN) + DP_TEST_PATTERN_128b_132b_TPS1, + DP_TEST_PATTERN_128b_132b_TPS2, + DP_TEST_PATTERN_PRBS9, + DP_TEST_PATTERN_PRBS11, + DP_TEST_PATTERN_PRBS15, + DP_TEST_PATTERN_PRBS23, + DP_TEST_PATTERN_PRBS31, + DP_TEST_PATTERN_264BIT_CUSTOM, + DP_TEST_PATTERN_SQUARE_PULSE, +#endif /* Link Training Patterns */ DP_TEST_PATTERN_TRAINING_PATTERN1, DP_TEST_PATTERN_TRAINING_PATTERN2, DP_TEST_PATTERN_TRAINING_PATTERN3, DP_TEST_PATTERN_TRAINING_PATTERN4, +#if defined(CONFIG_DRM_AMD_DC_DCN) + DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE, + DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE, + DP_TEST_PATTERN_PHY_PATTERN_END = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE, +#else DP_TEST_PATTERN_PHY_PATTERN_END = DP_TEST_PATTERN_TRAINING_PATTERN4, +#endif /* link test patterns*/ DP_TEST_PATTERN_COLOR_SQUARES, From d76b12da98dfb5e0cb0b7c3709372632b87da2e6 Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Mon, 26 Jul 2021 14:23:42 -0400 Subject: [PATCH 004/151] drm/amd/display: Add DP 2.0 DCCG HW Blocks: +--------+ +-----+ +------+ | OPTC | | HDA | | HUBP | +--------+ +-----+ +------+ | | | | | | HPO ====|==========|========|==== | | v | | | +-----+ | | | | APG | | | | +-----+ | | | | | | v v v | +---------------------+ | | HPO Stream Encoder | | +---------------------+ | | | v | +--------------------+ | | HPO Link Encoder | | +--------------------+ | | v ===============|============= v +------------------+ | DIO Output Mux | +------------------+ | v +-----+ | PHY | +-----+ | PHYD32CLK[0] v +------+ | DCCG | +------+ | v SYMCLK32 Signed-off-by: Fangzhi Zuo Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c | 162 ++++++++++++++++++ .../gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h | 18 ++ drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h | 23 +++ .../amd/display/dc/inc/hw/timing_generator.h | 3 + 4 files changed, 206 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c index 696c9307715d1..9896adf674255 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.c @@ -42,6 +42,155 @@ #define DC_LOGGER \ dccg->ctx->logger +void dccg31_set_dpstreamclk( + struct dccg *dccg, + enum hdmistreamclk_source src, + int otg_inst) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + /* enabled to select one of the DTBCLKs for pipe */ + switch (otg_inst) { + case 0: + REG_UPDATE(DPSTREAMCLK_CNTL, + DPSTREAMCLK_PIPE0_EN, (src == REFCLK) ? 0 : 1); + break; + case 1: + REG_UPDATE(DPSTREAMCLK_CNTL, + DPSTREAMCLK_PIPE1_EN, (src == REFCLK) ? 0 : 1); + break; + case 2: + REG_UPDATE(DPSTREAMCLK_CNTL, + DPSTREAMCLK_PIPE2_EN, (src == REFCLK) ? 0 : 1); + break; + case 3: + REG_UPDATE(DPSTREAMCLK_CNTL, + DPSTREAMCLK_PIPE3_EN, (src == REFCLK) ? 0 : 1); + break; + default: + BREAK_TO_DEBUGGER(); + return; + } +} + +void dccg31_enable_symclk32_se( + struct dccg *dccg, + int hpo_se_inst, + enum phyd32clk_clock_source phyd32clk) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + /* select one of the PHYD32CLKs as the source for symclk32_se */ + switch (hpo_se_inst) { + case 0: + REG_UPDATE_2(SYMCLK32_SE_CNTL, + SYMCLK32_SE0_SRC_SEL, phyd32clk, + SYMCLK32_SE0_EN, 1); + break; + case 1: + REG_UPDATE_2(SYMCLK32_SE_CNTL, + SYMCLK32_SE1_SRC_SEL, phyd32clk, + SYMCLK32_SE1_EN, 1); + break; + case 2: + REG_UPDATE_2(SYMCLK32_SE_CNTL, + SYMCLK32_SE2_SRC_SEL, phyd32clk, + SYMCLK32_SE2_EN, 1); + break; + case 3: + REG_UPDATE_2(SYMCLK32_SE_CNTL, + SYMCLK32_SE3_SRC_SEL, phyd32clk, + SYMCLK32_SE3_EN, 1); + break; + default: + BREAK_TO_DEBUGGER(); + return; + } +} + +void dccg31_disable_symclk32_se( + struct dccg *dccg, + int hpo_se_inst) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + /* set refclk as the source for symclk32_se */ + switch (hpo_se_inst) { + case 0: + REG_UPDATE_2(SYMCLK32_SE_CNTL, + SYMCLK32_SE0_SRC_SEL, 0, + SYMCLK32_SE0_EN, 0); + break; + case 1: + REG_UPDATE_2(SYMCLK32_SE_CNTL, + SYMCLK32_SE1_SRC_SEL, 0, + SYMCLK32_SE1_EN, 0); + break; + case 2: + REG_UPDATE_2(SYMCLK32_SE_CNTL, + SYMCLK32_SE2_SRC_SEL, 0, + SYMCLK32_SE2_EN, 0); + break; + case 3: + REG_UPDATE_2(SYMCLK32_SE_CNTL, + SYMCLK32_SE3_SRC_SEL, 0, + SYMCLK32_SE3_EN, 0); + break; + default: + BREAK_TO_DEBUGGER(); + return; + } +} + +void dccg31_enable_symclk32_le( + struct dccg *dccg, + int hpo_le_inst, + enum phyd32clk_clock_source phyd32clk) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + /* select one of the PHYD32CLKs as the source for symclk32_le */ + switch (hpo_le_inst) { + case 0: + REG_UPDATE_2(SYMCLK32_LE_CNTL, + SYMCLK32_LE0_SRC_SEL, phyd32clk, + SYMCLK32_LE0_EN, 1); + break; + case 1: + REG_UPDATE_2(SYMCLK32_LE_CNTL, + SYMCLK32_LE1_SRC_SEL, phyd32clk, + SYMCLK32_LE1_EN, 1); + break; + default: + BREAK_TO_DEBUGGER(); + return; + } +} + +void dccg31_disable_symclk32_le( + struct dccg *dccg, + int hpo_le_inst) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + /* set refclk as the source for symclk32_le */ + switch (hpo_le_inst) { + case 0: + REG_UPDATE_2(SYMCLK32_LE_CNTL, + SYMCLK32_LE0_SRC_SEL, 0, + SYMCLK32_LE0_EN, 0); + break; + case 1: + REG_UPDATE_2(SYMCLK32_LE_CNTL, + SYMCLK32_LE1_SRC_SEL, 0, + SYMCLK32_LE1_EN, 0); + break; + default: + BREAK_TO_DEBUGGER(); + return; + } +} + void dccg31_set_physymclk( struct dccg *dccg, int phy_inst, @@ -241,12 +390,25 @@ static void dccg31_set_dispclk_change_mode( void dccg31_init(struct dccg *dccg) { + /* Set HPO stream encoder to use refclk to avoid case where PHY is + * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which + * will cause DCN to hang. + */ + dccg31_disable_symclk32_se(dccg, 0); + dccg31_disable_symclk32_se(dccg, 1); + dccg31_disable_symclk32_se(dccg, 2); + dccg31_disable_symclk32_se(dccg, 3); } static const struct dccg_funcs dccg31_funcs = { .update_dpp_dto = dccg2_update_dpp_dto, .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, .dccg_init = dccg31_init, + .set_dpstreamclk = dccg31_set_dpstreamclk, + .enable_symclk32_se = dccg31_enable_symclk32_se, + .disable_symclk32_se = dccg31_disable_symclk32_se, + .enable_symclk32_le = dccg31_enable_symclk32_le, + .disable_symclk32_le = dccg31_disable_symclk32_le, .set_physymclk = dccg31_set_physymclk, .set_dtbclk_dto = dccg31_set_dtbclk_dto, .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h index 706ad80ba873e..1e5aabcb7799c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h @@ -130,6 +130,24 @@ struct dccg *dccg31_create( void dccg31_init(struct dccg *dccg); +void dccg31_enable_symclk32_se( + struct dccg *dccg, + int hpo_se_inst, + enum phyd32clk_clock_source phyd32clk); + +void dccg31_disable_symclk32_se( + struct dccg *dccg, + int hpo_se_inst); + +void dccg31_enable_symclk32_le( + struct dccg *dccg, + int hpo_le_inst, + enum phyd32clk_clock_source phyd32clk); + +void dccg31_disable_symclk32_le( + struct dccg *dccg, + int hpo_le_inst); + void dccg31_set_physymclk( struct dccg *dccg, int phy_inst, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h index 0afa2364a986f..09237d5819f47 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h @@ -79,7 +79,30 @@ struct dccg_funcs { void (*otg_drop_pixel)(struct dccg *dccg, uint32_t otg_inst); void (*dccg_init)(struct dccg *dccg); +#if defined(CONFIG_DRM_AMD_DC_DCN) + void (*set_dpstreamclk)( + struct dccg *dccg, + enum hdmistreamclk_source src, + int otg_inst); + + void (*enable_symclk32_se)( + struct dccg *dccg, + int hpo_se_inst, + enum phyd32clk_clock_source phyd32clk); + + void (*disable_symclk32_se)( + struct dccg *dccg, + int hpo_se_inst); + + void (*enable_symclk32_le)( + struct dccg *dccg, + int hpo_le_inst, + enum phyd32clk_clock_source phyd32clk); + void (*disable_symclk32_le)( + struct dccg *dccg, + int hpo_le_inst); +#endif void (*set_physymclk)( struct dccg *dccg, int phy_inst, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index 03f47f23fb652..7390baf916b58 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -100,6 +100,9 @@ enum crc_selection { enum otg_out_mux_dest { OUT_MUX_DIO = 0, +#if defined(CONFIG_DRM_AMD_DC_DCN) + OUT_MUX_HPO_DP = 2, +#endif }; enum h_timing_div_mode { From 5a2730fc1ff659977e4a8eda92d55769551041ac Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Tue, 15 Jun 2021 16:48:17 -0400 Subject: [PATCH 005/151] drm/amd/display: Add DP 2.0 BIOS and DMUB Support Parse DP2 encoder caps and hpo instance from bios Signed-off-by: Fangzhi Zuo Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 10 ++++++++++ drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 10 ++++++++++ .../drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c | 4 ++++ drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h | 4 ++++ drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 2 +- .../gpu/drm/amd/display/include/bios_parser_types.h | 8 ++++++++ drivers/gpu/drm/amd/include/atomfirmware.h | 4 ++++ 7 files changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 6dbde74c1e069..cdb5c027411a6 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1604,6 +1604,16 @@ static enum bp_result bios_parser_get_encoder_cap_info( ATOM_ENCODER_CAP_RECORD_HBR3_EN) ? 1 : 0; info->HDMI_6GB_EN = (record->encodercaps & ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN) ? 1 : 0; +#if defined(CONFIG_DRM_AMD_DC_DCN) + info->IS_DP2_CAPABLE = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_DP2) ? 1 : 0; + info->DP_UHBR10_EN = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_UHBR10_EN) ? 1 : 0; + info->DP_UHBR13_5_EN = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_UHBR13_5_EN) ? 1 : 0; + info->DP_UHBR20_EN = (record->encodercaps & + ATOM_ENCODER_CAP_RECORD_UHBR20_EN) ? 1 : 0; +#endif info->DP_IS_USB_C = (record->encodercaps & ATOM_ENCODER_CAP_RECORD_USB_C_TYPE) ? 1 : 0; diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index f1f672a997d7d..6e333b4af7d66 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -340,6 +340,13 @@ static enum bp_result transmitter_control_v1_7( const struct command_table_helper *cmd = bp->cmd_helper; struct dmub_dig_transmitter_control_data_v1_7 dig_v1_7 = {0}; +#if defined(CONFIG_DRM_AMD_DC_DCN) + uint8_t hpo_instance = (uint8_t)cntl->hpo_engine_id - ENGINE_ID_HPO_0; + + if (dc_is_dp_signal(cntl->signal)) + hpo_instance = (uint8_t)cntl->hpo_engine_id - ENGINE_ID_HPO_DP_0; +#endif + dig_v1_7.phyid = cmd->phy_id_to_atom(cntl->transmitter); dig_v1_7.action = (uint8_t)cntl->action; @@ -353,6 +360,9 @@ static enum bp_result transmitter_control_v1_7( dig_v1_7.hpdsel = cmd->hpd_sel_to_atom(cntl->hpd_sel); dig_v1_7.digfe_sel = cmd->dig_encoder_sel_to_atom(cntl->engine_id); dig_v1_7.connobj_id = (uint8_t)cntl->connector_obj_id.id; +#if defined(CONFIG_DRM_AMD_DC_DCN) + dig_v1_7.HPO_instance = hpo_instance; +#endif dig_v1_7.symclk_units.symclk_10khz = cntl->pixel_clock/10; if (cntl->action == TRANSMITTER_CONTROL_ENABLE || diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c index 46ea39f5ef8d8..6f3c2fb60790e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c @@ -192,6 +192,10 @@ void dcn30_link_encoder_construct( enc10->base.features.flags.bits.IS_HBR3_CAPABLE = bp_cap_info.DP_HBR3_EN; enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN; + enc10->base.features.flags.bits.IS_DP2_CAPABLE = bp_cap_info.IS_DP2_CAPABLE; + enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN; + enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN; + enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN; enc10->base.features.flags.bits.DP_IS_USB_C = bp_cap_info.DP_IS_USB_C; } else { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index fa3a725e11dcf..5084289810e22 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -59,6 +59,10 @@ struct encoder_feature_support { uint32_t IS_TPS3_CAPABLE:1; uint32_t IS_TPS4_CAPABLE:1; uint32_t HDMI_6GB_EN:1; + uint32_t IS_DP2_CAPABLE:1; + uint32_t IS_UHBR10_CAPABLE:1; + uint32_t IS_UHBR13_5_CAPABLE:1; + uint32_t IS_UHBR20_CAPABLE:1; uint32_t DP_IS_USB_C:1; } bits; uint32_t raw; diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 7b684e7f60dfa..13611c94a3bb8 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -974,7 +974,7 @@ struct dmub_dig_transmitter_control_data_v1_7 { uint8_t hpdsel; /**< =1: HPD1, =2: HPD2, ..., =6: HPD6, =0: HPD is not assigned */ uint8_t digfe_sel; /**< DIG front-end selection, bit0 means DIG0 FE is enabled */ uint8_t connobj_id; /**< Connector Object Id defined in ObjectId.h */ - uint8_t reserved0; /**< For future use */ + uint8_t HPO_instance; /**< HPO instance (0: inst0, 1: inst1) */ uint8_t reserved1; /**< For future use */ uint8_t reserved2[3]; /**< For future use */ uint32_t reserved3[11]; /**< For future use */ diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h index 76a87b6828837..b8ffb216ebc47 100644 --- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -152,6 +152,10 @@ struct bp_transmitter_control { enum signal_type signal; enum dc_color_depth color_depth; /* not used for DCE6.0 */ enum hpd_source_id hpd_sel; /* ucHPDSel, used for DCe6.0 */ +#if defined(CONFIG_DRM_AMD_DC_DCN) + enum tx_ffe_id txffe_sel; /* used for DCN3 */ + enum engine_id hpo_engine_id; /* used for DCN3 */ +#endif struct graphics_object_id connector_obj_id; /* symClock; in 10kHz, pixel clock, in HDMI deep color mode, it should * be pixel clock * deep_color_ratio (in KHz) @@ -319,6 +323,10 @@ struct bp_encoder_cap_info { uint32_t DP_HBR2_EN:1; uint32_t DP_HBR3_EN:1; uint32_t HDMI_6GB_EN:1; + uint32_t IS_DP2_CAPABLE:1; + uint32_t DP_UHBR10_EN:1; + uint32_t DP_UHBR13_5_EN:1; + uint32_t DP_UHBR20_EN:1; uint32_t DP_IS_USB_C:1; uint32_t RESERVED:27; }; diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h index 44955458fe381..7bd763361d6e6 100644 --- a/drivers/gpu/drm/amd/include/atomfirmware.h +++ b/drivers/gpu/drm/amd/include/atomfirmware.h @@ -768,6 +768,10 @@ enum atom_encoder_caps_def ATOM_ENCODER_CAP_RECORD_HBR2_EN =0x02, // DP1.2 HBR2 setting is qualified and HBR2 can be enabled ATOM_ENCODER_CAP_RECORD_HDMI6Gbps_EN =0x04, // HDMI2.0 6Gbps enable or not. ATOM_ENCODER_CAP_RECORD_HBR3_EN =0x08, // DP1.3 HBR3 is supported by board. + ATOM_ENCODER_CAP_RECORD_DP2 =0x10, // DP2 is supported by ASIC/board. + ATOM_ENCODER_CAP_RECORD_UHBR10_EN =0x20, // DP2.0 UHBR10 settings is supported by board + ATOM_ENCODER_CAP_RECORD_UHBR13_5_EN =0x40, // DP2.0 UHBR13.5 settings is supported by board + ATOM_ENCODER_CAP_RECORD_UHBR20_EN =0x80, // DP2.0 UHBR20 settings is supported by board ATOM_ENCODER_CAP_RECORD_USB_C_TYPE =0x100, // the DP connector is a USB-C type. }; From f01ee019586220c86f238263a4fbde6e72085e11 Mon Sep 17 00:00:00 2001 From: Fangzhi Zuo Date: Tue, 3 Aug 2021 18:46:00 -0400 Subject: [PATCH 006/151] drm/amd/display: Add DP 2.0 SST DC Support 1. Retrieve 128/132b link cap. 2. 128/132b link training and payload allocation. 3. UHBR10 link rate support. [squash in warning fixes - Alex] Signed-off-by: Fangzhi Zuo Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 8 + drivers/gpu/drm/amd/display/dc/core/dc.c | 18 + drivers/gpu/drm/amd/display/dc/core/dc_link.c | 468 ++++++- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 1163 ++++++++++++++++- .../drm/amd/display/dc/core/dc_link_hwss.c | 315 ++++- .../gpu/drm/amd/display/dc/core/dc_resource.c | 118 ++ drivers/gpu/drm/amd/display/dc/dc.h | 27 +- drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 222 ++++ drivers/gpu/drm/amd/display/dc/dc_link.h | 3 + drivers/gpu/drm/amd/display/dc/dc_types.h | 21 + .../display/dc/dce110/dce110_hw_sequencer.c | 99 +- .../amd/display/dc/dcn10/dcn10_link_encoder.c | 9 + .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 26 +- .../drm/amd/display/dc/dcn20/dcn20_resource.c | 4 + .../drm/amd/display/dc/dcn31/dcn31_resource.c | 18 +- drivers/gpu/drm/amd/display/dc/dm_cp_psp.h | 1 + drivers/gpu/drm/amd/display/dc/dm_helpers.h | 2 + .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 22 + .../amd/display/dc/inc/hw_sequencer_private.h | 3 + drivers/gpu/drm/amd/display/dc/inc/resource.h | 5 + .../gpu/drm/amd/display/include/dpcd_defs.h | 16 + .../amd/display/include/link_service_types.h | 24 +- .../drm/amd/display/include/logger_types.h | 6 + 23 files changed, 2555 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 6fee12c91ef59..22ddd8d71bcf2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -751,3 +751,11 @@ void dm_helpers_mst_enable_stream_features(const struct dc_stream_state *stream) &new_downspread.raw, sizeof(new_downspread)); } + +#if defined(CONFIG_DRM_AMD_DC_DCN) +void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz) +{ + // FPGA programming for this clock in diags framework that + // needs to go through dm layer, therefore leave dummy interace here +} +#endif \ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index c798c65d42765..f58d3956f3e2a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -255,6 +255,24 @@ static bool create_links( goto failed_alloc; } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) && + dc->caps.dp_hpo && + link->dc->res_pool->res_cap->num_hpo_dp_link_encoder > 0) { + /* FPGA case - Allocate HPO DP link encoder */ + if (i < link->dc->res_pool->res_cap->num_hpo_dp_link_encoder) { + link->hpo_dp_link_enc = link->dc->res_pool->hpo_dp_link_enc[i]; + + if (link->hpo_dp_link_enc == NULL) { + BREAK_TO_DEBUGGER(); + goto failed_alloc; + } + link->hpo_dp_link_enc->hpd_source = link->link_enc->hpd_source; + link->hpo_dp_link_enc->transmitter = link->link_enc->transmitter; + } + } +#endif + link->link_status.dpcd_caps = &link->dpcd_caps; enc_init.ctx = dc->ctx; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 8bd7f42a8053f..54ff4fb1ea032 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -64,6 +64,31 @@ /******************************************************************************* * Private functions ******************************************************************************/ +#if defined(CONFIG_DRM_AMD_DC_DCN) +static bool add_dp_hpo_link_encoder_to_link(struct dc_link *link) +{ + struct hpo_dp_link_encoder *enc = resource_get_unused_hpo_dp_link_encoder( + link->dc->res_pool); + + if (!link->hpo_dp_link_enc && enc) { + link->hpo_dp_link_enc = enc; + link->hpo_dp_link_enc->transmitter = link->link_enc->transmitter; + link->hpo_dp_link_enc->hpd_source = link->link_enc->hpd_source; + } + + return (link->hpo_dp_link_enc != NULL); +} + +static void remove_dp_hpo_link_encoder_from_link(struct dc_link *link) +{ + if (link->hpo_dp_link_enc) { + link->hpo_dp_link_enc->hpd_source = HPD_SOURCEID_UNKNOWN; + link->hpo_dp_link_enc->transmitter = TRANSMITTER_UNKNOWN; + link->hpo_dp_link_enc = NULL; + } +} +#endif + static void dc_link_destruct(struct dc_link *link) { int i; @@ -91,6 +116,12 @@ static void dc_link_destruct(struct dc_link *link) link->link_enc->funcs->destroy(&link->link_enc); } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (link->hpo_dp_link_enc) { + remove_dp_hpo_link_encoder_from_link(link); + } +#endif + if (link->local_sink) dc_sink_release(link->local_sink); @@ -928,6 +959,11 @@ static bool dc_link_detect_helper(struct dc_link *link, return false; } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link->reported_link_cap) == DP_128b_132b_ENCODING) + add_dp_hpo_link_encoder_to_link(link); +#endif + if (link->type == dc_connection_mst_branch) { LINK_INFO("link=%d, mst branch is now Connected\n", link->link_index); @@ -1173,6 +1209,11 @@ static bool dc_link_detect_helper(struct dc_link *link, sizeof(link->mst_stream_alloc_table.stream_allocations)); } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING) + reset_dp_hpo_stream_encoders_for_link(link); +#endif + link->type = dc_connection_none; sink_caps.signal = SIGNAL_TYPE_NONE; /* When we unplug a passive DP-HDMI dongle connection, dongle_max_pix_clk @@ -1549,6 +1590,9 @@ static bool dc_link_construct(struct dc_link *link, } DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C); +#if defined(CONFIG_DRM_AMD_DC_DCN) + DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE); +#endif /* Update link encoder tracking variables. These are used for the dynamic * assignment of link encoders to streams. @@ -1741,17 +1785,36 @@ static enum dc_status enable_link_dp(struct dc_state *state, /* get link settings for video mode timing */ decide_link_settings(stream, &link_settings); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link_settings) == DP_128b_132b_ENCODING && + pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) { + dp_enable_mst_on_sink(link, true); + } +#endif + if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) { /*in case it is not on*/ link->dc->hwss.edp_power_control(link, true); link->dc->hwss.edp_wait_for_hpd_ready(link, true); } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link_settings) == DP_128b_132b_ENCODING) { + /* TODO - DP2.0 HW: calculate 32 symbol clock for HPO encoder */ + } else { + pipe_ctx->stream_res.pix_clk_params.requested_sym_clk = + link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ; + if (state->clk_mgr && !apply_seamless_boot_optimization) + state->clk_mgr->funcs->update_clocks(state->clk_mgr, + state, false); + } +#else pipe_ctx->stream_res.pix_clk_params.requested_sym_clk = - link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ; + link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ; if (state->clk_mgr && !apply_seamless_boot_optimization) state->clk_mgr->funcs->update_clocks(state->clk_mgr, - state, false); + state, false); +#endif // during mode switch we do DP_SET_POWER off then on, and OUI is lost dpcd_set_source_specific_data(link); @@ -1780,7 +1843,12 @@ static enum dc_status enable_link_dp(struct dc_state *state, else fec_enable = true; +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING) + dp_set_fec_enable(link, fec_enable); +#else dp_set_fec_enable(link, fec_enable); +#endif // during mode set we do DP_SET_POWER off then on, aux writes are lost if (link->dpcd_sink_ext_caps.bits.oled == 1 || @@ -2284,6 +2352,9 @@ static void disable_link(struct dc_link *link, enum signal_type signal) if (dc_is_dp_signal(signal)) { /* SST DP, eDP */ +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct dc_link_settings link_settings = link->cur_link_settings; +#endif if (dc_is_dp_sst_signal(signal)) dp_disable_link_phy(link, signal); else @@ -2291,8 +2362,15 @@ static void disable_link(struct dc_link *link, enum signal_type signal) if (dc_is_dp_sst_signal(signal) || link->mst_stream_alloc_table.stream_count == 0) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING) { + dp_set_fec_enable(link, false); + dp_set_fec_ready(link, false); + } +#else dp_set_fec_enable(link, false); dp_set_fec_ready(link, false); +#endif } } else { if (signal != SIGNAL_TYPE_VIRTUAL) @@ -2475,9 +2553,14 @@ static bool dp_active_dongle_validate_timing( break; } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dpcd_caps->dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER && + dongle_caps->extendedCapValid == true) { +#else if (dpcd_caps->dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER || dongle_caps->extendedCapValid == false) return true; +#endif /* Check Pixel Encoding */ switch (timing->pixel_encoding) { @@ -2520,6 +2603,87 @@ static bool dp_active_dongle_validate_timing( if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10)) return false; +#if defined(CONFIG_DRM_AMD_DC_DCN) + } + + if (dongle_caps->dfp_cap_ext.supported) { + + if (dongle_caps->dfp_cap_ext.max_pixel_rate_in_mps < (timing->pix_clk_100hz / 10000)) + return false; + + if (dongle_caps->dfp_cap_ext.max_video_h_active_width < timing->h_addressable) + return false; + + if (dongle_caps->dfp_cap_ext.max_video_v_active_height < timing->v_addressable) + return false; + + if (timing->pixel_encoding == PIXEL_ENCODING_RGB) { + if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb) + return false; + if (timing->display_color_depth == COLOR_DEPTH_666 && + !dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_6bpc) + return false; + else if (timing->display_color_depth == COLOR_DEPTH_888 && + !dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_8bpc) + return false; + else if (timing->display_color_depth == COLOR_DEPTH_101010 && + !dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_10bpc) + return false; + else if (timing->display_color_depth == COLOR_DEPTH_121212 && + !dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_12bpc) + return false; + else if (timing->display_color_depth == COLOR_DEPTH_161616 && + !dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_16bpc) + return false; + } else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) { + if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb) + return false; + if (timing->display_color_depth == COLOR_DEPTH_888 && + !dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_8bpc) + return false; + else if (timing->display_color_depth == COLOR_DEPTH_101010 && + !dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_10bpc) + return false; + else if (timing->display_color_depth == COLOR_DEPTH_121212 && + !dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_12bpc) + return false; + else if (timing->display_color_depth == COLOR_DEPTH_161616 && + !dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_16bpc) + return false; + } else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { + if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb) + return false; + if (timing->display_color_depth == COLOR_DEPTH_888 && + !dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_8bpc) + return false; + else if (timing->display_color_depth == COLOR_DEPTH_101010 && + !dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_10bpc) + return false; + else if (timing->display_color_depth == COLOR_DEPTH_121212 && + !dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_12bpc) + return false; + else if (timing->display_color_depth == COLOR_DEPTH_161616 && + !dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_16bpc) + return false; + } else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) { + if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb) + return false; + if (timing->display_color_depth == COLOR_DEPTH_888 && + !dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_8bpc) + return false; + else if (timing->display_color_depth == COLOR_DEPTH_101010 && + !dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_10bpc) + return false; + else if (timing->display_color_depth == COLOR_DEPTH_121212 && + !dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_12bpc) + return false; + else if (timing->display_color_depth == COLOR_DEPTH_161616 && + !dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_16bpc) + return false; + } + } +#endif + return true; } @@ -3016,6 +3180,107 @@ static void update_mst_stream_alloc_table( link->mst_stream_alloc_table.stream_allocations[i] = work_table[i]; } +#if defined(CONFIG_DRM_AMD_DC_DCN) +/* + * Payload allocation/deallocation for SST introduced in DP2.0 + */ +enum dc_status dc_link_update_sst_payload(struct pipe_ctx *pipe_ctx, bool allocate) +{ + struct dc_stream_state *stream = pipe_ctx->stream; + struct dc_link *link = stream->link; + struct hpo_dp_link_encoder *hpo_dp_link_encoder = link->hpo_dp_link_enc; + struct hpo_dp_stream_encoder *hpo_dp_stream_encoder = pipe_ctx->stream_res.hpo_dp_stream_enc; + struct link_mst_stream_allocation_table proposed_table = {0}; + struct fixed31_32 avg_time_slots_per_mtp; + DC_LOGGER_INIT(link->ctx->logger); + + /* slot X.Y for SST payload deallocate */ + if (!allocate) { + avg_time_slots_per_mtp = dc_fixpt_from_int(0); + + DC_LOG_DP2("SST Update Payload: set_throttled_vcp_size slot X.Y for SST stream" + "X: %d " + "Y: %d", + dc_fixpt_floor( + avg_time_slots_per_mtp), + dc_fixpt_ceil( + dc_fixpt_shl( + dc_fixpt_sub_int( + avg_time_slots_per_mtp, + dc_fixpt_floor( + avg_time_slots_per_mtp)), + 26))); + + hpo_dp_link_encoder->funcs->set_throttled_vcp_size( + hpo_dp_link_encoder, + hpo_dp_stream_encoder->inst, + avg_time_slots_per_mtp); + } + + /* calculate VC payload and update branch with new payload allocation table*/ + if (!dpcd_write_128b_132b_sst_payload_allocation_table( + stream, + link, + &proposed_table, + allocate)) { + DC_LOG_ERROR("SST Update Payload: Failed to update " + "allocation table for " + "pipe idx: %d\n", + pipe_ctx->pipe_idx); + } + + proposed_table.stream_allocations[0].hpo_dp_stream_enc = hpo_dp_stream_encoder; + + ASSERT(proposed_table.stream_count == 1); + + //TODO - DP2.0 Logging: Instead of hpo_dp_stream_enc pointer, log instance id + DC_LOG_DP2("SST Update Payload: hpo_dp_stream_enc: %p " + "vcp_id: %d " + "slot_count: %d\n", + (void *) proposed_table.stream_allocations[0].hpo_dp_stream_enc, + proposed_table.stream_allocations[0].vcp_id, + proposed_table.stream_allocations[0].slot_count); + + /* program DP source TX for payload */ + hpo_dp_link_encoder->funcs->update_stream_allocation_table( + hpo_dp_link_encoder, + &proposed_table); + + /* poll for ACT handled */ + if (!dpcd_poll_for_allocation_change_trigger(link)) { + // Failures will result in blackscreen and errors logged + BREAK_TO_DEBUGGER(); + } + + /* slot X.Y for SST payload allocate */ + if (allocate) { + avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, link); + + DC_LOG_DP2("SST Update Payload: " + "slot.X: %d " + "slot.Y: %d", + dc_fixpt_floor( + avg_time_slots_per_mtp), + dc_fixpt_ceil( + dc_fixpt_shl( + dc_fixpt_sub_int( + avg_time_slots_per_mtp, + dc_fixpt_floor( + avg_time_slots_per_mtp)), + 26))); + + hpo_dp_link_encoder->funcs->set_throttled_vcp_size( + hpo_dp_link_encoder, + hpo_dp_stream_encoder->inst, + avg_time_slots_per_mtp); + } + + /* Always return DC_OK. + * If part of sequence fails, log failure(s) and show blackscreen + */ + return DC_OK; +} +#endif /* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table * because stream_encoder is not exposed to dm @@ -3203,6 +3468,11 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA; config.link_enc_idx = pipe_ctx->stream->link->link_enc->transmitter - TRANSMITTER_UNIPHY_A; config.phy_idx = pipe_ctx->stream->link->link_enc->transmitter - TRANSMITTER_UNIPHY_A; + if (is_dp_128b_132b_signal(pipe_ctx)) { + config.stream_enc_idx = pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0; + config.link_enc_idx = pipe_ctx->stream->link->hpo_dp_link_enc->inst; + config.dp2_enabled = 1; + } #endif config.dpms_off = dpms_off; config.dm_stream_ctx = pipe_ctx->stream->dm_stream_context; @@ -3214,6 +3484,88 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) } #endif +#if defined(CONFIG_DRM_AMD_DC_DCN) +static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pipe_ctx *pipe_ctx) +{ + struct dc *dc = pipe_ctx->stream->ctx->dc; + struct dc_stream_state *stream = pipe_ctx->stream; + struct link_mst_stream_allocation_table proposed_table = {0}; + struct fixed31_32 avg_time_slots_per_mtp; + uint8_t req_slot_count = 0; + uint8_t vc_id = 1; /// VC ID always 1 for SST + + struct dc_link_settings link_settings = {0}; + DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); + + decide_link_settings(stream, &link_settings); + stream->link->cur_link_settings = link_settings; + + /* Enable clock, Configure lane count, and Enable Link Encoder*/ + enable_dp_hpo_output(stream->link, &stream->link->cur_link_settings); + +#ifdef DIAGS_BUILD + /* Workaround for FPGA HPO capture DP link data: + * HPO capture will set link to active mode + * This workaround is required to get a capture from start of frame + */ + if (!dc->debug.fpga_hpo_capture_en) { + struct encoder_set_dp_phy_pattern_param params = {0}; + params.dp_phy_pattern = DP_TEST_PATTERN_VIDEO_MODE; + + /* Set link active */ + stream->link->hpo_dp_link_enc->funcs->set_link_test_pattern( + stream->link->hpo_dp_link_enc, + ¶ms); + } +#endif + + /* Enable DP_STREAM_ENC */ + dc->hwss.enable_stream(pipe_ctx); + + /* Set DPS PPS SDP (AKA "info frames") */ + if (pipe_ctx->stream->timing.flags.DSC) { + dp_set_dsc_pps_sdp(pipe_ctx, true); + } + + /* Allocate Payload */ + if ((stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) && (state->stream_count > 1)) { + // MST case + uint8_t i; + + proposed_table.stream_count = state->stream_count; + for (i = 0; i < state->stream_count; i++) { + avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(state->streams[i], state->streams[i]->link); + req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp); + proposed_table.stream_allocations[i].slot_count = req_slot_count; + proposed_table.stream_allocations[i].vcp_id = i+1; + /* NOTE: This makes assumption that pipe_ctx index is same as stream index */ + proposed_table.stream_allocations[i].hpo_dp_stream_enc = state->res_ctx.pipe_ctx[i].stream_res.hpo_dp_stream_enc; + } + } else { + // SST case + avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, stream->link); + req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp); + proposed_table.stream_count = 1; /// Always 1 stream for SST + proposed_table.stream_allocations[0].slot_count = req_slot_count; + proposed_table.stream_allocations[0].vcp_id = vc_id; + proposed_table.stream_allocations[0].hpo_dp_stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc; + } + + stream->link->hpo_dp_link_enc->funcs->update_stream_allocation_table( + stream->link->hpo_dp_link_enc, + &proposed_table); + + stream->link->hpo_dp_link_enc->funcs->set_throttled_vcp_size( + stream->link->hpo_dp_link_enc, + pipe_ctx->stream_res.hpo_dp_stream_enc->inst, + avg_time_slots_per_mtp); + + + + dc->hwss.unblank_stream(pipe_ctx, &stream->link->cur_link_settings); +} +#endif + void core_link_enable_stream( struct dc_state *state, struct pipe_ctx *pipe_ctx) @@ -3230,7 +3582,12 @@ void core_link_enable_stream( dc_is_virtual_signal(pipe_ctx->stream->signal)) return; +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (!dc_is_virtual_signal(pipe_ctx->stream->signal) + && !is_dp_128b_132b_signal(pipe_ctx)) { +#else if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) { +#endif stream->link->link_enc->funcs->setup( stream->link->link_enc, pipe_ctx->stream->signal); @@ -3240,13 +3597,32 @@ void core_link_enable_stream( stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE); } - if (dc_is_dp_signal(pipe_ctx->stream->signal)) +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(pipe_ctx)) { + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->set_stream_attribute( + pipe_ctx->stream_res.hpo_dp_stream_enc, + &stream->timing, + stream->output_color_space, + stream->use_vsc_sdp_for_colorimetry, + stream->timing.flags.DSC, + false); + otg_out_dest = OUT_MUX_HPO_DP; + } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute( + pipe_ctx->stream_res.stream_enc, + &stream->timing, + stream->output_color_space, + stream->use_vsc_sdp_for_colorimetry, + stream->link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP); + } +#else + pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute( pipe_ctx->stream_res.stream_enc, &stream->timing, stream->output_color_space, stream->use_vsc_sdp_for_colorimetry, stream->link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP); +#endif if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->hdmi_set_stream_attribute( @@ -3357,7 +3733,12 @@ void core_link_enable_stream( * as a workaround for the incorrect value being applied * from transmitter control. */ +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (!(dc_is_virtual_signal(pipe_ctx->stream->signal) || + is_dp_128b_132b_signal(pipe_ctx))) +#else if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) +#endif stream->link->link_enc->funcs->setup( stream->link->link_enc, pipe_ctx->stream->signal); @@ -3375,6 +3756,11 @@ void core_link_enable_stream( if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) dc_link_allocate_mst_payload(pipe_ctx); +#if defined(CONFIG_DRM_AMD_DC_DCN) + else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && + is_dp_128b_132b_signal(pipe_ctx)) + dc_link_update_sst_payload(pipe_ctx, true); +#endif dc->hwss.unblank_stream(pipe_ctx, &pipe_ctx->stream->link->cur_link_settings); @@ -3391,6 +3777,11 @@ void core_link_enable_stream( dc->hwss.enable_audio_stream(pipe_ctx); } else { // if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(pipe_ctx)) { + fpga_dp_hpo_enable_link_and_stream(state, pipe_ctx); + } +#endif if (dc_is_dp_signal(pipe_ctx->stream->signal) || dc_is_virtual_signal(pipe_ctx->stream->signal)) dp_set_dsc_enable(pipe_ctx, true); @@ -3426,6 +3817,11 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); +#if defined(CONFIG_DRM_AMD_DC_DCN) + else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && + is_dp_128b_132b_signal(pipe_ctx)) + dc_link_update_sst_payload(pipe_ctx, false); +#endif if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { struct ext_hdmi_settings settings = {0}; @@ -3452,14 +3848,39 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) } } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT && + !is_dp_128b_132b_signal(pipe_ctx)) { + + /* In DP1.x SST mode, our encoder will go to TPS1 + * when link is on but stream is off. + * Disabling link before stream will avoid exposing TPS1 pattern + * during the disable sequence as it will confuse some receivers + * state machine. + * In DP2 or MST mode, our encoder will stay video active + */ + disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal); + dc->hwss.disable_stream(pipe_ctx); + } else { + dc->hwss.disable_stream(pipe_ctx); + disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal); + } +#else disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal); dc->hwss.disable_stream(pipe_ctx); +#endif if (pipe_ctx->stream->timing.flags.DSC) { if (dc_is_dp_signal(pipe_ctx->stream->signal)) dp_set_dsc_enable(pipe_ctx, false); } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(pipe_ctx)) { + if (pipe_ctx->stream_res.tg->funcs->set_out_mux) + pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, OUT_MUX_DIO); + } +#endif } void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) @@ -3592,6 +4013,13 @@ void dc_link_set_preferred_training_settings(struct dc *dc, if (link_setting != NULL) { link->preferred_link_setting = *link_setting; +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(link_setting) == + DP_128b_132b_ENCODING && !link->hpo_dp_link_enc) { + if (!add_dp_hpo_link_encoder_to_link(link)) + memset(&link->preferred_link_setting, 0, sizeof(link->preferred_link_setting)); + } +#endif } else { link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN; link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN; @@ -3633,6 +4061,38 @@ uint32_t dc_link_bandwidth_kbps( const struct dc_link *link, const struct dc_link_settings *link_setting) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + uint32_t total_data_bw_efficiency_x10000 = 0; + uint32_t link_rate_per_lane_kbps = 0; + + switch (dp_get_link_encoding_format(link_setting)) { + case DP_8b_10b_ENCODING: + /* For 8b/10b encoding: + * link rate is defined in the unit of LINK_RATE_REF_FREQ_IN_KHZ per DP byte per lane. + * data bandwidth efficiency is 80% with additional 3% overhead if FEC is supported. + */ + link_rate_per_lane_kbps = link_setting->link_rate * LINK_RATE_REF_FREQ_IN_KHZ * BITS_PER_DP_BYTE; + total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_8b_10b_x10000; + if (dc_link_should_enable_fec(link)) { + total_data_bw_efficiency_x10000 /= 100; + total_data_bw_efficiency_x10000 *= DATA_EFFICIENCY_8b_10b_FEC_EFFICIENCY_x100; + } + break; + case DP_128b_132b_ENCODING: + /* For 128b/132b encoding: + * link rate is defined in the unit of 10mbps per lane. + * total data bandwidth efficiency is always 96.71%. + */ + link_rate_per_lane_kbps = link_setting->link_rate * 10000; + total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_128b_132b_x10000; + break; + default: + break; + } + + /* overall effective link bandwidth = link rate per lane * lane count * total data bandwidth efficiency */ + return link_rate_per_lane_kbps * link_setting->lane_count / 10000 * total_data_bw_efficiency_x10000; +#else uint32_t link_bw_kbps = link_setting->link_rate * LINK_RATE_REF_FREQ_IN_KHZ; /* bytes per sec */ @@ -3663,9 +4123,9 @@ uint32_t dc_link_bandwidth_kbps( long long fec_link_bw_kbps = link_bw_kbps * 970LL; link_bw_kbps = (uint32_t)(div64_s64(fec_link_bw_kbps, 1000LL)); } - return link_bw_kbps; +#endif } const struct dc_link_settings *dc_link_get_link_cap( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 330edd666b7d8..b7531cdc8bfe7 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -39,6 +39,43 @@ enum { POST_LT_ADJ_REQ_TIMEOUT = 200 }; +#if defined(CONFIG_DRM_AMD_DC_DCN) +struct dp_lt_fallback_entry { + enum dc_lane_count lane_count; + enum dc_link_rate link_rate; +}; + +static const struct dp_lt_fallback_entry dp_lt_fallbacks[] = { + /* This link training fallback array is ordered by + * link bandwidth from highest to lowest. + * DP specs makes it a normative policy to always + * choose the next highest link bandwidth during + * link training fallback. + */ + {LANE_COUNT_FOUR, LINK_RATE_UHBR20}, + {LANE_COUNT_FOUR, LINK_RATE_UHBR13_5}, + {LANE_COUNT_TWO, LINK_RATE_UHBR20}, + {LANE_COUNT_FOUR, LINK_RATE_UHBR10}, + {LANE_COUNT_TWO, LINK_RATE_UHBR13_5}, + {LANE_COUNT_FOUR, LINK_RATE_HIGH3}, + {LANE_COUNT_ONE, LINK_RATE_UHBR20}, + {LANE_COUNT_TWO, LINK_RATE_UHBR10}, + {LANE_COUNT_FOUR, LINK_RATE_HIGH2}, + {LANE_COUNT_ONE, LINK_RATE_UHBR13_5}, + {LANE_COUNT_TWO, LINK_RATE_HIGH3}, + {LANE_COUNT_ONE, LINK_RATE_UHBR10}, + {LANE_COUNT_TWO, LINK_RATE_HIGH2}, + {LANE_COUNT_FOUR, LINK_RATE_HIGH}, + {LANE_COUNT_ONE, LINK_RATE_HIGH3}, + {LANE_COUNT_FOUR, LINK_RATE_LOW}, + {LANE_COUNT_ONE, LINK_RATE_HIGH2}, + {LANE_COUNT_TWO, LINK_RATE_HIGH}, + {LANE_COUNT_TWO, LINK_RATE_LOW}, + {LANE_COUNT_ONE, LINK_RATE_HIGH}, + {LANE_COUNT_ONE, LINK_RATE_LOW}, +}; +#endif + static bool decide_fallback_link_setting( struct dc_link_settings initial_link_settings, struct dc_link_settings *current_link_setting, @@ -52,15 +89,27 @@ static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link, { union training_aux_rd_interval training_rd_interval; uint32_t wait_in_micro_secs = 100; - +#if defined(CONFIG_DRM_AMD_DC_DCN) memset(&training_rd_interval, 0, sizeof(training_rd_interval)); + if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING && + link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { + core_link_read_dpcd( + link, + DP_TRAINING_AUX_RD_INTERVAL, + (uint8_t *)&training_rd_interval, + sizeof(training_rd_interval)); + if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) + wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; + } +#else core_link_read_dpcd( link, DP_TRAINING_AUX_RD_INTERVAL, (uint8_t *)&training_rd_interval, sizeof(training_rd_interval)); if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) - wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; + wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000; +#endif return wait_in_micro_secs; } @@ -68,6 +117,36 @@ static uint32_t get_eq_training_aux_rd_interval( struct dc_link *link, const struct dc_link_settings *link_settings) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + union training_aux_rd_interval training_rd_interval; + + memset(&training_rd_interval, 0, sizeof(training_rd_interval)); + if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) { + core_link_read_dpcd( + link, + DP_128b_132b_TRAINING_AUX_RD_INTERVAL, + (uint8_t *)&training_rd_interval, + sizeof(training_rd_interval)); + } else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING && + link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { + core_link_read_dpcd( + link, + DP_TRAINING_AUX_RD_INTERVAL, + (uint8_t *)&training_rd_interval, + sizeof(training_rd_interval)); + } + + switch (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) { + case 0: return 400; + case 1: return 4000; + case 2: return 8000; + case 3: return 12000; + case 4: return 16000; + case 5: return 32000; + case 6: return 64000; + default: return 400; + } +#else union training_aux_rd_interval training_rd_interval; uint32_t wait_in_micro_secs = 400; @@ -87,13 +166,21 @@ static uint32_t get_eq_training_aux_rd_interval( } return wait_in_micro_secs; +#endif } void dp_wait_for_training_aux_rd_interval( struct dc_link *link, uint32_t wait_in_micro_secs) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (wait_in_micro_secs > 16000) + msleep(wait_in_micro_secs/1000); + else + udelay(wait_in_micro_secs); +#else udelay(wait_in_micro_secs); +#endif DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n", __func__, @@ -121,6 +208,17 @@ enum dpcd_training_patterns case DP_TRAINING_PATTERN_SEQUENCE_4: dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4; break; +#if defined(CONFIG_DRM_AMD_DC_DCN) + case DP_128b_132b_TPS1: + dpcd_tr_pattern = DPCD_128b_132b_TPS1; + break; + case DP_128b_132b_TPS2: + dpcd_tr_pattern = DPCD_128b_132b_TPS2; + break; + case DP_128b_132b_TPS2_CDS: + dpcd_tr_pattern = DPCD_128b_132b_TPS2_CDS; + break; +#endif case DP_TRAINING_PATTERN_VIDEOIDLE: dpcd_tr_pattern = DPCD_TRAINING_PATTERN_VIDEOIDLE; break; @@ -159,13 +257,57 @@ static void dpcd_set_training_pattern( static enum dc_dp_training_pattern decide_cr_training_pattern( const struct dc_link_settings *link_settings) { - return DP_TRAINING_PATTERN_SEQUENCE_1; + switch (dp_get_link_encoding_format(link_settings)) { + case DP_8b_10b_ENCODING: + default: + return DP_TRAINING_PATTERN_SEQUENCE_1; +#if defined(CONFIG_DRM_AMD_DC_DCN) + case DP_128b_132b_ENCODING: + return DP_128b_132b_TPS1; +#endif + } } static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link, const struct dc_link_settings *link_settings) { struct link_encoder *link_enc; +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct encoder_feature_support *enc_caps; + struct dpcd_caps *rx_caps = &link->dpcd_caps; + enum dc_dp_training_pattern pattern = DP_TRAINING_PATTERN_SEQUENCE_2; + + /* Access link encoder capability based on whether it is statically + * or dynamically assigned to a link. + */ + if (link->is_dig_mapping_flexible && + link->dc->res_pool->funcs->link_encs_assign) + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + else + link_enc = link->link_enc; + ASSERT(link_enc); + enc_caps = &link_enc->features; + + switch (dp_get_link_encoding_format(link_settings)) { + case DP_8b_10b_ENCODING: + if (enc_caps->flags.bits.IS_TPS4_CAPABLE && + rx_caps->max_down_spread.bits.TPS4_SUPPORTED) + pattern = DP_TRAINING_PATTERN_SEQUENCE_4; + else if (enc_caps->flags.bits.IS_TPS3_CAPABLE && + rx_caps->max_ln_count.bits.TPS3_SUPPORTED) + pattern = DP_TRAINING_PATTERN_SEQUENCE_3; + else + pattern = DP_TRAINING_PATTERN_SEQUENCE_2; + break; + case DP_128b_132b_ENCODING: + pattern = DP_128b_132b_TPS2; + break; + default: + pattern = DP_TRAINING_PATTERN_SEQUENCE_2; + break; + } + return pattern; +#else enum dc_dp_training_pattern highest_tp = DP_TRAINING_PATTERN_SEQUENCE_2; struct encoder_feature_support *features; struct dpcd_caps *dpcd_caps = &link->dpcd_caps; @@ -196,7 +338,38 @@ static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *li return DP_TRAINING_PATTERN_SEQUENCE_3; return DP_TRAINING_PATTERN_SEQUENCE_2; +#endif +} + +#if defined(CONFIG_DRM_AMD_DC_DCN) +static uint8_t get_dpcd_link_rate(const struct dc_link_settings *link_settings) +{ + uint8_t link_rate = 0; + enum dp_link_encoding encoding = dp_get_link_encoding_format(link_settings); + + if (encoding == DP_128b_132b_ENCODING) + switch (link_settings->link_rate) { + case LINK_RATE_UHBR10: + link_rate = 0x1; + break; + case LINK_RATE_UHBR20: + link_rate = 0x2; + break; + case LINK_RATE_UHBR13_5: + link_rate = 0x4; + break; + default: + link_rate = 0; + break; + } + else if (encoding == DP_8b_10b_ENCODING) + link_rate = (uint8_t) link_settings->link_rate; + else + link_rate = 0; + + return link_rate; } +#endif enum dc_status dpcd_set_link_settings( struct dc_link *link, @@ -247,7 +420,11 @@ enum dc_status dpcd_set_link_settings( status = core_link_write_dpcd(link, DP_LINK_RATE_SET, <_settings->link_settings.link_rate_set, 1); } else { +#if defined(CONFIG_DRM_AMD_DC_DCN) + rate = get_dpcd_link_rate(<_settings->link_settings); +#else rate = (uint8_t) (lt_settings->link_settings.link_rate); +#endif status = core_link_write_dpcd(link, DP_LINK_BW_SET, &rate, 1); } @@ -289,6 +466,10 @@ uint8_t dc_dp_initialize_scrambling_data_symbols( disable_scrabled_data_symbols = 1; break; case DP_TRAINING_PATTERN_SEQUENCE_4: +#if defined(CONFIG_DRM_AMD_DC_DCN) + case DP_128b_132b_TPS1: + case DP_128b_132b_TPS2: +#endif disable_scrabled_data_symbols = 0; break; default: @@ -356,6 +537,26 @@ static void dpcd_set_lt_pattern_and_lane_settings( for (lane = 0; lane < (uint32_t)(lt_settings->link_settings.lane_count); lane++) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(<_settings->link_settings) == + DP_128b_132b_ENCODING) { + dpcd_lane[lane].tx_ffe.PRESET_VALUE = + lt_settings->lane_settings[lane].FFE_PRESET.settings.level; + } else if (dp_get_link_encoding_format(<_settings->link_settings) == + DP_8b_10b_ENCODING) { + dpcd_lane[lane].bits.VOLTAGE_SWING_SET = + (uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING); + dpcd_lane[lane].bits.PRE_EMPHASIS_SET = + (uint8_t)(lt_settings->lane_settings[lane].PRE_EMPHASIS); + + dpcd_lane[lane].bits.MAX_SWING_REACHED = + (lt_settings->lane_settings[lane].VOLTAGE_SWING == + VOLTAGE_SWING_MAX_LEVEL ? 1 : 0); + dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED = + (lt_settings->lane_settings[lane].PRE_EMPHASIS == + PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); + } +#else dpcd_lane[lane].bits.VOLTAGE_SWING_SET = (uint8_t)(lt_settings->lane_settings[lane].VOLTAGE_SWING); dpcd_lane[lane].bits.PRE_EMPHASIS_SET = @@ -367,6 +568,7 @@ static void dpcd_set_lt_pattern_and_lane_settings( dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED = (lt_settings->lane_settings[lane].PRE_EMPHASIS == PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); +#endif } /* concatenate everything into one buffer*/ @@ -380,6 +582,18 @@ static void dpcd_set_lt_pattern_and_lane_settings( size_in_bytes); if (is_repeater(link, offset)) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(<_settings->link_settings) == + DP_128b_132b_ENCODING) + DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" + " 0x%X TX_FFE_PRESET_VALUE = %x\n", + __func__, + offset, + dpcd_base_lt_offset, + dpcd_lane[0].tx_ffe.PRESET_VALUE); + else if (dp_get_link_encoding_format(<_settings->link_settings) == + DP_8b_10b_ENCODING) +#endif DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", __func__, @@ -390,6 +604,16 @@ static void dpcd_set_lt_pattern_and_lane_settings( dpcd_lane[0].bits.MAX_SWING_REACHED, dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED); } else { +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(<_settings->link_settings) == + DP_128b_132b_ENCODING) + DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n", + __func__, + dpcd_base_lt_offset, + dpcd_lane[0].tx_ffe.PRESET_VALUE); + else if (dp_get_link_encoding_format(<_settings->link_settings) == + DP_8b_10b_ENCODING) +#endif DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", __func__, dpcd_base_lt_offset, @@ -414,6 +638,15 @@ static void dpcd_set_lt_pattern_and_lane_settings( (uint8_t *)(dpcd_lane), size_in_bytes); +#if defined(CONFIG_DRM_AMD_DC_DCN) + } else if (dp_get_link_encoding_format(<_settings->link_settings) == + DP_128b_132b_ENCODING) { + core_link_write_dpcd( + link, + dpcd_base_lt_offset, + dpcd_lt_buffer, + sizeof(dpcd_lt_buffer)); +#endif } else /* write it all in (1 + number-of-lanes)-byte burst*/ core_link_write_dpcd( @@ -484,6 +717,13 @@ void dp_update_drive_settings( dest->lane_settings[lane].POST_CURSOR2 = src.lane_settings[lane].POST_CURSOR2; else dest->lane_settings[lane].POST_CURSOR2 = *dest->post_cursor2; + +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dest->ffe_preset == NULL) + dest->lane_settings[lane].FFE_PRESET = src.lane_settings[lane].FFE_PRESET; + else + dest->lane_settings[lane].FFE_PRESET = *dest->ffe_preset; +#endif } } @@ -529,6 +769,10 @@ static void find_max_drive_settings( lane_settings[0].PRE_EMPHASIS; /*max_requested.postCursor2 = * link_training_setting->laneSettings[0].postCursor2;*/ +#if defined(CONFIG_DRM_AMD_DC_DCN) + max_requested.FFE_PRESET = + link_training_setting->lane_settings[0].FFE_PRESET; +#endif /* Determine what the maximum of the requested settings are*/ for (lane = 1; lane < link_training_setting->link_settings.lane_count; @@ -554,6 +798,13 @@ static void find_max_drive_settings( link_training_setting->laneSettings[lane].postCursor2; } */ +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (link_training_setting->lane_settings[lane].FFE_PRESET.settings.level > + max_requested.FFE_PRESET.settings.level) + max_requested.FFE_PRESET.settings.level = + link_training_setting-> + lane_settings[lane].FFE_PRESET.settings.level; +#endif } /* make sure the requested settings are @@ -567,6 +818,10 @@ static void find_max_drive_settings( if (max_requested.postCursor2 > PostCursor2_MaxLevel) max_requested.postCursor2 = PostCursor2_MaxLevel; */ +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (max_requested.FFE_PRESET.settings.level > DP_FFE_PRESET_MAX_LEVEL) + max_requested.FFE_PRESET.settings.level = DP_FFE_PRESET_MAX_LEVEL; +#endif /* make sure the pre-emphasis matches the voltage swing*/ if (max_requested.PRE_EMPHASIS > @@ -604,6 +859,10 @@ static void find_max_drive_settings( /*max_lt_setting->laneSettings[lane].postCursor2 = * max_requested.postCursor2; */ +#if defined(CONFIG_DRM_AMD_DC_DCN) + max_lt_setting->lane_settings[lane].FFE_PRESET = + max_requested.FFE_PRESET; +#endif } } @@ -701,12 +960,28 @@ enum dc_status dp_get_lane_status_and_drive_settings( (uint32_t)(link_training_setting->link_settings.lane_count); lane++) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link_training_setting->link_settings) == + DP_128b_132b_ENCODING) { + request_settings.lane_settings[lane].FFE_PRESET.raw = + dpcd_lane_adjust[lane].tx_ffe.PRESET_VALUE; + } else if (dp_get_link_encoding_format(&link_training_setting->link_settings) == + DP_8b_10b_ENCODING) { + request_settings.lane_settings[lane].VOLTAGE_SWING = + (enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits. + VOLTAGE_SWING_LANE); + request_settings.lane_settings[lane].PRE_EMPHASIS = + (enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits. + PRE_EMPHASIS_LANE); + } +#else request_settings.lane_settings[lane].VOLTAGE_SWING = (enum dc_voltage_swing)(dpcd_lane_adjust[lane].bits. VOLTAGE_SWING_LANE); request_settings.lane_settings[lane].PRE_EMPHASIS = (enum dc_pre_emphasis)(dpcd_lane_adjust[lane].bits. PRE_EMPHASIS_LANE); +#endif } /*Note: for postcursor2, read adjusted @@ -745,6 +1020,26 @@ enum dc_status dpcd_set_lane_settings( (uint32_t)(link_training_setting-> link_settings.lane_count); lane++) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link_training_setting->link_settings) == + DP_128b_132b_ENCODING) { + dpcd_lane[lane].tx_ffe.PRESET_VALUE = + link_training_setting->lane_settings[lane].FFE_PRESET.settings.level; + } else if (dp_get_link_encoding_format(&link_training_setting->link_settings) == + DP_8b_10b_ENCODING) { + dpcd_lane[lane].bits.VOLTAGE_SWING_SET = + (uint8_t)(link_training_setting->lane_settings[lane].VOLTAGE_SWING); + dpcd_lane[lane].bits.PRE_EMPHASIS_SET = + (uint8_t)(link_training_setting->lane_settings[lane].PRE_EMPHASIS); + + dpcd_lane[lane].bits.MAX_SWING_REACHED = + (link_training_setting->lane_settings[lane].VOLTAGE_SWING == + VOLTAGE_SWING_MAX_LEVEL ? 1 : 0); + dpcd_lane[lane].bits.MAX_PRE_EMPHASIS_REACHED = + (link_training_setting->lane_settings[lane].PRE_EMPHASIS == + PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); + } +#else dpcd_lane[lane].bits.VOLTAGE_SWING_SET = (uint8_t)(link_training_setting-> lane_settings[lane].VOLTAGE_SWING); @@ -759,6 +1054,7 @@ enum dc_status dpcd_set_lane_settings( (link_training_setting-> lane_settings[lane].PRE_EMPHASIS == PRE_EMPHASIS_MAX_LEVEL ? 1 : 0); +#endif } status = core_link_write_dpcd(link, @@ -786,6 +1082,18 @@ enum dc_status dpcd_set_lane_settings( */ if (is_repeater(link, offset)) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link_training_setting->link_settings) == + DP_128b_132b_ENCODING) + DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n" + " 0x%X TX_FFE_PRESET_VALUE = %x\n", + __func__, + offset, + lane0_set_address, + dpcd_lane[0].tx_ffe.PRESET_VALUE); + else if (dp_get_link_encoding_format(&link_training_setting->link_settings) == + DP_8b_10b_ENCODING) +#endif DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n" " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", __func__, @@ -797,6 +1105,16 @@ enum dc_status dpcd_set_lane_settings( dpcd_lane[0].bits.MAX_PRE_EMPHASIS_REACHED); } else { +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link_training_setting->link_settings) == + DP_128b_132b_ENCODING) + DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n", + __func__, + lane0_set_address, + dpcd_lane[0].tx_ffe.PRESET_VALUE); + else if (dp_get_link_encoding_format(&link_training_setting->link_settings) == + DP_8b_10b_ENCODING) +#endif DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n", __func__, lane0_set_address, @@ -932,6 +1250,14 @@ uint32_t dp_translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval case 0x04: aux_rd_interval_us = 16000; break; +#if defined(CONFIG_DRM_AMD_DC_DCN) + case 0x05: + aux_rd_interval_us = 32000; + break; + case 0x06: + aux_rd_interval_us = 64000; + break; +#endif default: break; } @@ -972,8 +1298,13 @@ static enum link_training_result perform_channel_equalization_sequence( tr_pattern = lt_settings->pattern_for_eq; +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_repeater(link, offset) && dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) + tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4; +#else if (is_repeater(link, offset)) tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4; +#endif dp_set_hw_training_pattern(link, tr_pattern, offset); @@ -1125,9 +1456,28 @@ static enum link_training_result perform_clock_recovery_sequence( return LINK_TRAINING_SUCCESS; /* 6. max VS reached*/ +#if defined(CONFIG_DRM_AMD_DC_DCN) + if ((dp_get_link_encoding_format(<_settings->link_settings) == + DP_8b_10b_ENCODING) && + dp_is_max_vs_reached(lt_settings)) + break; +#else if (dp_is_max_vs_reached(lt_settings)) break; +#endif +#if defined(CONFIG_DRM_AMD_DC_DCN) + if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_128b_132b_ENCODING) && + lt_settings->lane_settings[0].FFE_PRESET.settings.level == + req_settings.lane_settings[0].FFE_PRESET.settings.level) + retries_cr++; + else if ((dp_get_link_encoding_format(<_settings->link_settings) == DP_8b_10b_ENCODING) && + lt_settings->lane_settings[0].VOLTAGE_SWING == + req_settings.lane_settings[0].VOLTAGE_SWING) + retries_cr++; + else + retries_cr = 0; +#else /* 7. same lane settings*/ /* Note: settings are the same for all lanes, * so comparing first lane is sufficient*/ @@ -1138,6 +1488,7 @@ static enum link_training_result perform_clock_recovery_sequence( retries_cr++; else retries_cr = 0; +#endif /* 8. update VS/PE/PC2 in lt_settings*/ dp_update_drive_settings(lt_settings, req_settings); @@ -1172,7 +1523,11 @@ static inline enum link_training_result dp_transition_to_video_idle( * TPS4 must be used instead of POST_LT_ADJ_REQ. */ if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 || +#if defined(CONFIG_DRM_AMD_DC_DCN) + lt_settings->pattern_for_eq >= DP_TRAINING_PATTERN_SEQUENCE_4) { +#else lt_settings->pattern_for_eq == DP_TRAINING_PATTERN_SEQUENCE_4) { +#endif /* delay 5ms after Main Link output idle pattern and then check * DPCD 0202h. */ @@ -1268,6 +1623,32 @@ static inline void decide_8b_10b_training_settings( lt_settings->should_set_fec_ready = true; } +#if defined(CONFIG_DRM_AMD_DC_DCN) +static inline void decide_128b_132b_training_settings(struct dc_link *link, + const struct dc_link_settings *link_settings, + struct link_training_settings *lt_settings) +{ + memset(lt_settings, 0, sizeof(*lt_settings)); + + lt_settings->link_settings = *link_settings; + /* TODO: should decide link spread when populating link_settings */ + lt_settings->link_settings.link_spread = link->dp_ss_off ? LINK_SPREAD_DISABLED : + LINK_SPREAD_05_DOWNSPREAD_30KHZ; + + lt_settings->pattern_for_cr = decide_cr_training_pattern(link_settings); + lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_settings); + lt_settings->eq_pattern_time = 2500; + lt_settings->eq_wait_time_limit = 400000; + lt_settings->eq_loop_count_limit = 20; + lt_settings->pattern_for_cds = DP_128b_132b_TPS2_CDS; + lt_settings->cds_pattern_time = 2500; + lt_settings->cds_wait_time_limit = (dp_convert_to_count( + link->dpcd_caps.lttpr_caps.phy_repeater_cnt) + 1) * 20000; + lt_settings->lttpr_mode = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) ? + LTTPR_MODE_NON_TRANSPARENT : LTTPR_MODE_TRANSPARENT; +} +#endif + void dp_decide_training_settings( struct dc_link *link, const struct dc_link_settings *link_settings, @@ -1275,6 +1656,10 @@ void dp_decide_training_settings( { if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) decide_8b_10b_training_settings(link, link_settings, lt_settings); +#if defined(CONFIG_DRM_AMD_DC_DCN) + else if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) + decide_128b_132b_training_settings(link, link_settings, lt_settings); +#endif } static void override_training_settings( @@ -1303,6 +1688,11 @@ static void override_training_settings( lt_settings->pre_emphasis = overrides->pre_emphasis; if (overrides->post_cursor2 != NULL) lt_settings->post_cursor2 = overrides->post_cursor2; +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (overrides->ffe_preset != NULL) + lt_settings->ffe_preset = overrides->ffe_preset; +#endif + for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) { lt_settings->lane_settings[lane].VOLTAGE_SWING = lt_settings->voltage_swing != NULL ? @@ -1489,6 +1879,17 @@ static void print_status_message( case LINK_RATE_HIGH3: link_rate = "HBR3"; break; +#if defined(CONFIG_DRM_AMD_DC_DCN) + case LINK_RATE_UHBR10: + link_rate = "UHBR10"; + break; + case LINK_RATE_UHBR13_5: + link_rate = "UHBR13.5"; + break; + case LINK_RATE_UHBR20: + link_rate = "UHBR20"; + break; +#endif default: break; } @@ -1518,6 +1919,20 @@ static void print_status_message( case LINK_TRAINING_LINK_LOSS: lt_result = "Link loss"; break; +#if defined(CONFIG_DRM_AMD_DC_DCN) + case DP_128b_132b_LT_FAILED: + lt_result = "LT_FAILED received"; + break; + case DP_128b_132b_MAX_LOOP_COUNT_REACHED: + lt_result = "max loop count reached"; + break; + case DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT: + lt_result = "channel EQ timeout"; + break; + case DP_128b_132b_CDS_DONE_TIMEOUT: + lt_result = "CDS timeout"; + break; +#endif default: break; } @@ -1537,6 +1952,9 @@ static void print_status_message( } /* Connectivity log: link training */ +#if defined(CONFIG_DRM_AMD_DC_DCN) + /* TODO - DP2.0 Log: add connectivity log for FFE PRESET */ +#endif CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d, DS=%s", link_rate, lt_settings->link_settings.lane_count, @@ -1619,9 +2037,23 @@ enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_train static void dpcd_exit_training_mode(struct dc_link *link) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + uint8_t sink_status = 0; + uint8_t i; +#endif /* clear training pattern set */ dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE); + +#if defined(CONFIG_DRM_AMD_DC_DCN) + /* poll for intra-hop disable */ + for (i = 0; i < 10; i++) { + if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) && + (sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION) == 0) + break; + udelay(1000); + } +#endif } enum dc_status dpcd_configure_channel_coding(struct dc_link *link, @@ -1645,6 +2077,131 @@ enum dc_status dpcd_configure_channel_coding(struct dc_link *link, return status; } +#if defined(CONFIG_DRM_AMD_DC_DCN) +static void dpcd_128b_132b_get_aux_rd_interval(struct dc_link *link, + uint32_t *interval_in_us) +{ + union dp_128b_132b_training_aux_rd_interval dpcd_interval; + uint32_t interval_unit = 0; + + dpcd_interval.raw = 0; + core_link_read_dpcd(link, DP_128b_132b_TRAINING_AUX_RD_INTERVAL, + &dpcd_interval.raw, sizeof(dpcd_interval.raw)); + interval_unit = dpcd_interval.bits.UNIT ? 1 : 2; /* 0b = 2 ms, 1b = 1 ms */ + /* (128b/132b_TRAINING_AUX_RD_INTERVAL value + 1) * + * INTERVAL_UNIT. The maximum is 256 ms + */ + *interval_in_us = (dpcd_interval.bits.VALUE + 1) * interval_unit * 1000; +} + +static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence( + struct dc_link *link, + struct link_training_settings *lt_settings) +{ + uint8_t loop_count = 0; + uint32_t aux_rd_interval = 0; + uint32_t wait_time = 0; + struct link_training_settings req_settings; + union lane_align_status_updated dpcd_lane_status_updated = { {0} }; + union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } }; + enum link_training_result status = LINK_TRAINING_SUCCESS; + + /* Transmit 128b/132b_TPS1 over Main-Link and Set TRAINING_PATTERN_SET to 01h */ + dp_set_hw_training_pattern(link, lt_settings->pattern_for_cr, DPRX); + dpcd_set_training_pattern(link, lt_settings->pattern_for_cr); + + /* Adjust TX_FFE_PRESET_VALUE as requested */ + dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status, + &dpcd_lane_status_updated, &req_settings, DPRX); + dp_update_drive_settings(lt_settings, req_settings); + dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval); + dp_set_hw_lane_settings(link, lt_settings, DPRX); + dpcd_set_lane_settings(link, lt_settings, DPRX); + + /* Transmit 128b/132b_TPS2 over Main-Link and Set TRAINING_PATTERN_SET to 02h */ + dp_set_hw_training_pattern(link, lt_settings->pattern_for_eq, DPRX); + dpcd_set_training_pattern(link, lt_settings->pattern_for_eq); + + /* poll for channel EQ done */ + while (status == LINK_TRAINING_SUCCESS) { + loop_count++; + dp_wait_for_training_aux_rd_interval(link, aux_rd_interval); + wait_time += aux_rd_interval; + dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status, + &dpcd_lane_status_updated, &req_settings, DPRX); + dp_update_drive_settings(lt_settings, req_settings); + dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval); + if (dp_is_ch_eq_done(lt_settings->link_settings.lane_count, + dpcd_lane_status)) { + /* pass */ + break; + } else if (loop_count >= lt_settings->eq_loop_count_limit) { + status = DP_128b_132b_MAX_LOOP_COUNT_REACHED; + } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) { + status = DP_128b_132b_LT_FAILED; + } else { + dp_set_hw_lane_settings(link, lt_settings, DPRX); + dpcd_set_lane_settings(link, lt_settings, DPRX); + } + } + + /* poll for EQ interlane align done */ + while (status == LINK_TRAINING_SUCCESS) { + if (dpcd_lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b) { + /* pass */ + break; + } else if (wait_time >= lt_settings->eq_wait_time_limit) { + status = DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT; + } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) { + status = DP_128b_132b_LT_FAILED; + } else { + dp_wait_for_training_aux_rd_interval(link, + lt_settings->eq_pattern_time); + wait_time += lt_settings->eq_pattern_time; + dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status, + &dpcd_lane_status_updated, &req_settings, DPRX); + } + } + + return status; +} + +static enum link_training_result dp_perform_128b_132b_cds_done_sequence( + struct dc_link *link, + struct link_training_settings *lt_settings) +{ + /* Assumption: assume hardware has transmitted eq pattern */ + enum link_training_result status = LINK_TRAINING_SUCCESS; + struct link_training_settings req_settings; + union lane_align_status_updated dpcd_lane_status_updated = { {0} }; + union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = { { {0} } }; + uint32_t wait_time = 0; + + /* initiate CDS done sequence */ + dpcd_set_training_pattern(link, lt_settings->pattern_for_cds); + + /* poll for CDS interlane align done and symbol lock */ + while (status == LINK_TRAINING_SUCCESS) { + dp_wait_for_training_aux_rd_interval(link, + lt_settings->cds_pattern_time); + wait_time += lt_settings->cds_pattern_time; + dp_get_lane_status_and_drive_settings(link, lt_settings, dpcd_lane_status, + &dpcd_lane_status_updated, &req_settings, DPRX); + if (dp_is_symbol_locked(lt_settings->link_settings.lane_count, dpcd_lane_status) && + dpcd_lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b) { + /* pass */ + break; + } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) { + status = DP_128b_132b_LT_FAILED; + } else if (wait_time >= lt_settings->cds_wait_time_limit) { + status = DP_128b_132b_CDS_DONE_TIMEOUT; + } + } + + return status; +} +#endif + static enum link_training_result dp_perform_8b_10b_link_training( struct dc_link *link, struct link_training_settings *lt_settings) @@ -1701,6 +2258,35 @@ static enum link_training_result dp_perform_8b_10b_link_training( return status; } +#if defined(CONFIG_DRM_AMD_DC_DCN) +static enum link_training_result dp_perform_128b_132b_link_training( + struct dc_link *link, + struct link_training_settings *lt_settings) +{ + enum link_training_result result = LINK_TRAINING_SUCCESS; + + /* TODO - DP2.0 Link: remove legacy_dp2_lt logic */ + if (link->dc->debug.legacy_dp2_lt) { + struct link_training_settings legacy_settings; + + decide_8b_10b_training_settings(link, + <_settings->link_settings, + &legacy_settings); + return dp_perform_8b_10b_link_training(link, &legacy_settings); + } + + dpcd_set_link_settings(link, lt_settings); + + if (result == LINK_TRAINING_SUCCESS) + result = dp_perform_128b_132b_channel_eq_done_sequence(link, lt_settings); + + if (result == LINK_TRAINING_SUCCESS) + result = dp_perform_128b_132b_cds_done_sequence(link, lt_settings); + + return result; +} +#endif + enum link_training_result dc_link_dp_perform_link_training( struct dc_link *link, const struct dc_link_settings *link_settings, @@ -1735,6 +2321,10 @@ enum link_training_result dc_link_dp_perform_link_training( */ if (encoding == DP_8b_10b_ENCODING) status = dp_perform_8b_10b_link_training(link, <_settings); +#if defined(CONFIG_DRM_AMD_DC_DCN) + else if (encoding == DP_128b_132b_ENCODING) + status = dp_perform_128b_132b_link_training(link, <_settings); +#endif else ASSERT(0); @@ -1780,7 +2370,10 @@ bool perform_link_training_with_retries( /* We need to do this before the link training to ensure the idle pattern in SST * mode will be sent right after the link training */ - link_enc->funcs->connect_dig_be_to_fe(link_enc, +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(¤t_setting) == DP_8b_10b_ENCODING) +#endif + link_enc->funcs->connect_dig_be_to_fe(link_enc, pipe_ctx->stream_res.stream_enc->id, true); for (j = 0; j < attempts; ++j) { @@ -1950,8 +2543,14 @@ enum link_training_result dc_link_dp_sync_lt_attempt( dp_cs_id, link_settings); /* Set FEC enable */ - fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable; - dp_set_fec_ready(link, fec_enable); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) { +#endif + fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable; + dp_set_fec_ready(link, fec_enable); +#if defined(CONFIG_DRM_AMD_DC_DCN) + } +#endif if (lt_overrides->alternate_scrambler_reset) { if (*lt_overrides->alternate_scrambler_reset) @@ -1993,14 +2592,36 @@ bool dc_link_dp_sync_lt_end(struct dc_link *link, bool link_down) * Still shouldn't turn off dp_receiver (DPCD:600h) */ if (link_down == true) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct dc_link_settings link_settings = link->cur_link_settings; +#endif dp_disable_link_phy(link, link->connector_signal); - dp_set_fec_ready(link, false); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING) +#endif + dp_set_fec_ready(link, false); } link->sync_lt_in_progress = false; return true; } +#if defined(CONFIG_DRM_AMD_DC_DCN) +static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link) +{ + enum dc_link_rate lttpr_max_link_rate = link->dpcd_caps.lttpr_caps.max_link_rate; + + if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR20) + lttpr_max_link_rate = LINK_RATE_UHBR20; + else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR13_5) + lttpr_max_link_rate = LINK_RATE_UHBR13_5; + else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR10) + lttpr_max_link_rate = LINK_RATE_UHBR10; + + return lttpr_max_link_rate; +} +#endif + bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap) { if (!max_link_enc_cap) { @@ -2022,9 +2643,17 @@ bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_ static struct dc_link_settings get_max_link_cap(struct dc_link *link) { struct dc_link_settings max_link_cap = {0}; +#if defined(CONFIG_DRM_AMD_DC_DCN) + enum dc_link_rate lttpr_max_link_rate; +#endif /* get max link encoder capability */ link->link_enc->funcs->get_max_link_cap(link->link_enc, &max_link_cap); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (max_link_cap.link_rate >= LINK_RATE_UHBR10 && + !link->hpo_dp_link_enc) + max_link_cap.link_rate = LINK_RATE_HIGH3; +#endif /* Lower link settings based on sink's link cap */ if (link->reported_link_cap.lane_count < max_link_cap.lane_count) @@ -2045,8 +2674,15 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link) if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count) max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count; +#if defined(CONFIG_DRM_AMD_DC_DCN) + lttpr_max_link_rate = get_lttpr_max_link_rate(link); + + if (lttpr_max_link_rate < max_link_cap.link_rate) + max_link_cap.link_rate = lttpr_max_link_rate; +#else if (link->dpcd_caps.lttpr_caps.max_link_rate < max_link_cap.link_rate) max_link_cap.link_rate = link->dpcd_caps.lttpr_caps.max_link_rate; +#endif DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n", __func__, @@ -2205,6 +2841,10 @@ bool dp_verify_link_cap( core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, &grant, sizeof(grant)); } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING) + reset_dp_hpo_stream_encoders_for_link(link); +#endif /* TODO implement override and monitor patch later */ /* try to train the link from high to low to @@ -2360,7 +3000,17 @@ static struct dc_link_settings get_common_supported_link_settings( * We map it to the maximum supported link rate that * is smaller than MAX_LINK_BW in this case. */ +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (link_settings.link_rate > LINK_RATE_UHBR20) { + link_settings.link_rate = LINK_RATE_UHBR20; + } else if (link_settings.link_rate < LINK_RATE_UHBR20 && + link_settings.link_rate > LINK_RATE_UHBR13_5) { + link_settings.link_rate = LINK_RATE_UHBR13_5; + } else if (link_settings.link_rate < LINK_RATE_UHBR10 && + link_settings.link_rate > LINK_RATE_HIGH3) { +#else if (link_settings.link_rate > LINK_RATE_HIGH3) { +#endif link_settings.link_rate = LINK_RATE_HIGH3; } else if (link_settings.link_rate < LINK_RATE_HIGH3 && link_settings.link_rate > LINK_RATE_HIGH2) { @@ -2405,6 +3055,14 @@ static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count) static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate) { switch (link_rate) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + case LINK_RATE_UHBR20: + return LINK_RATE_UHBR13_5; + case LINK_RATE_UHBR13_5: + return LINK_RATE_UHBR10; + case LINK_RATE_UHBR10: + return LINK_RATE_HIGH3; +#endif case LINK_RATE_HIGH3: return LINK_RATE_HIGH2; case LINK_RATE_HIGH2: @@ -2439,11 +3097,55 @@ static enum dc_link_rate increase_link_rate(enum dc_link_rate link_rate) return LINK_RATE_HIGH2; case LINK_RATE_HIGH2: return LINK_RATE_HIGH3; +#if defined(CONFIG_DRM_AMD_DC_DCN) + case LINK_RATE_HIGH3: + return LINK_RATE_UHBR10; + case LINK_RATE_UHBR10: + return LINK_RATE_UHBR13_5; + case LINK_RATE_UHBR13_5: + return LINK_RATE_UHBR20; +#endif default: return LINK_RATE_UNKNOWN; } } +#if defined(CONFIG_DRM_AMD_DC_DCN) +static bool decide_fallback_link_setting_max_bw_policy( + const struct dc_link_settings *max, + struct dc_link_settings *cur) +{ + uint8_t cur_idx = 0, next_idx; + bool found = false; + + while (cur_idx < ARRAY_SIZE(dp_lt_fallbacks)) + /* find current index */ + if (dp_lt_fallbacks[cur_idx].lane_count == cur->lane_count && + dp_lt_fallbacks[cur_idx].link_rate == cur->link_rate) + break; + else + cur_idx++; + + next_idx = cur_idx + 1; + + while (next_idx < ARRAY_SIZE(dp_lt_fallbacks)) + /* find next index */ + if (dp_lt_fallbacks[next_idx].lane_count <= max->lane_count && + dp_lt_fallbacks[next_idx].link_rate <= max->link_rate) + break; + else + next_idx++; + + if (next_idx < ARRAY_SIZE(dp_lt_fallbacks)) { + cur->lane_count = dp_lt_fallbacks[next_idx].lane_count; + cur->link_rate = dp_lt_fallbacks[next_idx].link_rate; + found = true; + } + + return found; +} +#endif + /* * function: set link rate and lane count fallback based * on current link setting and last link training result @@ -2459,6 +3161,11 @@ static bool decide_fallback_link_setting( { if (!current_link_setting) return false; +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&initial_link_settings) == DP_128b_132b_ENCODING) + return decide_fallback_link_setting_max_bw_policy(&initial_link_settings, + current_link_setting); +#endif switch (training_result) { case LINK_TRAINING_CR_FAIL_LANE0: @@ -2831,9 +3538,15 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) union phy_test_pattern dpcd_test_pattern; union lane_adjust dpcd_lane_adjustment[2]; unsigned char dpcd_post_cursor_2_adjustment = 0; +#if defined(CONFIG_DRM_AMD_DC_DCN) + unsigned char test_pattern_buffer[ + (DP_TEST_264BIT_CUSTOM_PATTERN_263_256 - + DP_TEST_264BIT_CUSTOM_PATTERN_7_0)+1] = {0}; +#else unsigned char test_pattern_buffer[ (DP_TEST_80BIT_CUSTOM_PATTERN_79_72 - DP_TEST_80BIT_CUSTOM_PATTERN_7_0)+1] = {0}; +#endif unsigned int test_pattern_size = 0; enum dp_test_pattern test_pattern; struct dc_link_training_settings link_settings; @@ -2899,6 +3612,35 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) case PHY_TEST_PATTERN_CP2520_3: test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; break; +#if defined(CONFIG_DRM_AMD_DC_DCN) + case PHY_TEST_PATTERN_128b_132b_TPS1: + test_pattern = DP_TEST_PATTERN_128b_132b_TPS1; + break; + case PHY_TEST_PATTERN_128b_132b_TPS2: + test_pattern = DP_TEST_PATTERN_128b_132b_TPS2; + break; + case PHY_TEST_PATTERN_PRBS9: + test_pattern = DP_TEST_PATTERN_PRBS9; + break; + case PHY_TEST_PATTERN_PRBS11: + test_pattern = DP_TEST_PATTERN_PRBS11; + break; + case PHY_TEST_PATTERN_PRBS15: + test_pattern = DP_TEST_PATTERN_PRBS15; + break; + case PHY_TEST_PATTERN_PRBS23: + test_pattern = DP_TEST_PATTERN_PRBS23; + break; + case PHY_TEST_PATTERN_PRBS31: + test_pattern = DP_TEST_PATTERN_PRBS31; + break; + case PHY_TEST_PATTERN_264BIT_CUSTOM: + test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM; + break; + case PHY_TEST_PATTERN_SQUARE_PULSE: + test_pattern = DP_TEST_PATTERN_SQUARE_PULSE; + break; +#endif default: test_pattern = DP_TEST_PATTERN_VIDEO_MODE; break; @@ -2914,6 +3656,27 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) test_pattern_size); } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (test_pattern == DP_TEST_PATTERN_SQUARE_PULSE) { + test_pattern_size = 1; // Square pattern data is 1 byte (DP spec) + core_link_read_dpcd( + link, + DP_PHY_SQUARE_PATTERN, + test_pattern_buffer, + test_pattern_size); + } + + if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) { + test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_256- + DP_TEST_264BIT_CUSTOM_PATTERN_7_0) + 1; + core_link_read_dpcd( + link, + DP_TEST_264BIT_CUSTOM_PATTERN_7_0, + test_pattern_buffer, + test_pattern_size); + } +#endif + /* prepare link training settings */ link_settings.link = link->cur_link_settings; @@ -2922,6 +3685,24 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) lane++) { dpcd_lane_adjust.raw = get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link->cur_link_settings) == + DP_128b_132b_ENCODING) { + link_settings.lane_settings[lane].FFE_PRESET.raw = + dpcd_lane_adjust.tx_ffe.PRESET_VALUE; + } else if (dp_get_link_encoding_format(&link->cur_link_settings) == + DP_8b_10b_ENCODING) { + link_settings.lane_settings[lane].VOLTAGE_SWING = + (enum dc_voltage_swing) + (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE); + link_settings.lane_settings[lane].PRE_EMPHASIS = + (enum dc_pre_emphasis) + (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE); + link_settings.lane_settings[lane].POST_CURSOR2 = + (enum dc_post_cursor2) + ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03); + } +#else link_settings.lane_settings[lane].VOLTAGE_SWING = (enum dc_voltage_swing) (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE); @@ -2931,6 +3712,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) link_settings.lane_settings[lane].POST_CURSOR2 = (enum dc_post_cursor2) ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03); +#endif } for (i = 0; i < 4; i++) @@ -3535,6 +4317,43 @@ static void get_active_converter_info( dp_hw_fw_revision.ieee_fw_rev, sizeof(dp_hw_fw_revision.ieee_fw_rev)); } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 && + link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) { + union dp_dfp_cap_ext dfp_cap_ext; + memset(&dfp_cap_ext, '\0', sizeof (dfp_cap_ext)); + core_link_read_dpcd( + link, + DP_DFP_CAPABILITY_EXTENSION_SUPPORT, + dfp_cap_ext.raw, + sizeof(dfp_cap_ext.raw)); + link->dpcd_caps.dongle_caps.dfp_cap_ext.supported = dfp_cap_ext.fields.supported; + link->dpcd_caps.dongle_caps.dfp_cap_ext.max_pixel_rate_in_mps = + dfp_cap_ext.fields.max_pixel_rate_in_mps[0] + + (dfp_cap_ext.fields.max_pixel_rate_in_mps[1] << 8); + link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width = + dfp_cap_ext.fields.max_video_h_active_width[0] + + (dfp_cap_ext.fields.max_video_h_active_width[1] << 8); + link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height = + dfp_cap_ext.fields.max_video_v_active_height[0] + + (dfp_cap_ext.fields.max_video_v_active_height[1] << 8); + link->dpcd_caps.dongle_caps.dfp_cap_ext.encoding_format_caps = + dfp_cap_ext.fields.encoding_format_caps; + link->dpcd_caps.dongle_caps.dfp_cap_ext.rgb_color_depth_caps = + dfp_cap_ext.fields.rgb_color_depth_caps; + link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr444_color_depth_caps = + dfp_cap_ext.fields.ycbcr444_color_depth_caps; + link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr422_color_depth_caps = + dfp_cap_ext.fields.ycbcr422_color_depth_caps; + link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr420_color_depth_caps = + dfp_cap_ext.fields.ycbcr420_color_depth_caps; + DC_LOG_DP2("DFP capability extension is read at link %d", link->link_index); + DC_LOG_DP2("\tdfp_cap_ext.supported = %s", link->dpcd_caps.dongle_caps.dfp_cap_ext.supported ? "true" : "false"); + DC_LOG_DP2("\tdfp_cap_ext.max_pixel_rate_in_mps = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_pixel_rate_in_mps); + DC_LOG_DP2("\tdfp_cap_ext.max_video_h_active_width = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width); + DC_LOG_DP2("\tdfp_cap_ext.max_video_v_active_height = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height); + } +#endif } static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data, @@ -3594,7 +4413,12 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link) bool dp_retrieve_lttpr_cap(struct dc_link *link) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + uint8_t lttpr_dpcd_data[8]; + bool allow_lttpr_non_transparent_mode = 0; +#else uint8_t lttpr_dpcd_data[6]; +#endif bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable; bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware; enum dc_status status = DC_ERROR_UNEXPECTED; @@ -3602,6 +4426,16 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data)); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if ((link->dc->config.allow_lttpr_non_transparent_mode.bits.DP2_0 && + link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)) { + allow_lttpr_non_transparent_mode = 1; + } else if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A && + !link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) { + allow_lttpr_non_transparent_mode = 1; + } +#endif + /* * Logic to determine LTTPR mode */ @@ -3609,13 +4443,21 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) if (vbios_lttpr_enable && vbios_lttpr_interop) link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; else if (!vbios_lttpr_enable && vbios_lttpr_interop) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (allow_lttpr_non_transparent_mode) +#else if (link->dc->config.allow_lttpr_non_transparent_mode) +#endif link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; else link->lttpr_mode = LTTPR_MODE_TRANSPARENT; } else if (!vbios_lttpr_enable && !vbios_lttpr_interop) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (!allow_lttpr_non_transparent_mode || !link->dc->caps.extended_aux_timeout_support) +#else if (!link->dc->config.allow_lttpr_non_transparent_mode || !link->dc->caps.extended_aux_timeout_support) +#endif link->lttpr_mode = LTTPR_MODE_NON_LTTPR; else link->lttpr_mode = LTTPR_MODE_NON_TRANSPARENT; @@ -3659,6 +4501,16 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link) lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; +#if defined(CONFIG_DRM_AMD_DC_DCN) + link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw = + lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; + + link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw = + lttpr_dpcd_data[DP_PHY_REPEATER_128b_132b_RATES - + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; +#endif + /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ is_lttpr_present = (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 && link->dpcd_caps.lttpr_caps.max_lane_count > 0 && @@ -3909,16 +4761,82 @@ static bool retrieve_link_cap(struct dc_link *link) DP_DSC_SUPPORT, link->dpcd_caps.dsc_caps.dsc_basic_caps.raw, sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw)); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) { + status = core_link_read_dpcd( + link, + DP_DSC_BRANCH_OVERALL_THROUGHPUT_0, + link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw, + sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw)); + DC_LOG_DSC("DSC branch decoder capability is read at link %d", link->link_index); + DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_0 = 0x%02x", + link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_0); + DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_1 = 0x%02x", + link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_1); + DC_LOG_DSC("\tBRANCH_MAX_LINE_WIDTH 0x%02x", + link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_MAX_LINE_WIDTH); + } +#else status = core_link_read_dpcd( link, DP_DSC_BRANCH_OVERALL_THROUGHPUT_0, link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw, sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw)); +#endif } if (!dpcd_read_sink_ext_caps(link)) link->dpcd_sink_ext_caps.raw = 0; +#if defined(CONFIG_DRM_AMD_DC_DCN) + link->dpcd_caps.channel_coding_cap.raw = dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_CAP - DP_DPCD_REV]; + + if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) { + DC_LOG_DP2("128b/132b encoding is supported at link %d", link->link_index); + + core_link_read_dpcd(link, + DP_128b_132b_SUPPORTED_LINK_RATES, + &link->dpcd_caps.dp_128b_132b_supported_link_rates.raw, + sizeof(link->dpcd_caps.dp_128b_132b_supported_link_rates.raw)); + if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR20) + link->reported_link_cap.link_rate = LINK_RATE_UHBR20; + else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5) + link->reported_link_cap.link_rate = LINK_RATE_UHBR13_5; + else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR10) + link->reported_link_cap.link_rate = LINK_RATE_UHBR10; + else + dm_error("%s: Invalid RX 128b_132b_supported_link_rates\n", __func__); + DC_LOG_DP2("128b/132b supported link rates is read at link %d", link->link_index); + DC_LOG_DP2("\tmax 128b/132b link rate support is %d.%d GHz", + link->reported_link_cap.link_rate / 100, + link->reported_link_cap.link_rate % 100); + + core_link_read_dpcd(link, + DP_SINK_VIDEO_FALLBACK_FORMATS, + &link->dpcd_caps.fallback_formats.raw, + sizeof(link->dpcd_caps.fallback_formats.raw)); + DC_LOG_DP2("sink video fallback format is read at link %d", link->link_index); + if (link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support) + DC_LOG_DP2("\t1920x1080@60Hz 24bpp fallback format supported"); + if (link->dpcd_caps.fallback_formats.bits.dp_1280x720_60Hz_24bpp_support) + DC_LOG_DP2("\t1280x720@60Hz 24bpp fallback format supported"); + if (link->dpcd_caps.fallback_formats.bits.dp_1024x768_60Hz_24bpp_support) + DC_LOG_DP2("\t1024x768@60Hz 24bpp fallback format supported"); + if (link->dpcd_caps.fallback_formats.raw == 0) { + DC_LOG_DP2("\tno supported fallback formats, assume 1920x1080@60Hz 24bpp is supported"); + link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support = 1; + } + + core_link_read_dpcd(link, + DP_FEC_CAPABILITY_1, + &link->dpcd_caps.fec_cap1.raw, + sizeof(link->dpcd_caps.fec_cap1.raw)); + DC_LOG_DP2("FEC CAPABILITY 1 is read at link %d", link->link_index); + if (link->dpcd_caps.fec_cap1.bits.AGGREGATED_ERROR_COUNTERS_CAPABLE) + DC_LOG_DP2("\tFEC aggregated error counters are supported"); + } +#endif + /* Connectivity log: detection */ CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: "); @@ -4389,6 +5307,35 @@ bool dc_link_dp_set_test_pattern( case DP_TEST_PATTERN_CP2520_3: pattern = PHY_TEST_PATTERN_CP2520_3; break; +#if defined(CONFIG_DRM_AMD_DC_DCN) + case DP_TEST_PATTERN_128b_132b_TPS1: + pattern = PHY_TEST_PATTERN_128b_132b_TPS1; + break; + case DP_TEST_PATTERN_128b_132b_TPS2: + pattern = PHY_TEST_PATTERN_128b_132b_TPS2; + break; + case DP_TEST_PATTERN_PRBS9: + pattern = PHY_TEST_PATTERN_PRBS9; + break; + case DP_TEST_PATTERN_PRBS11: + pattern = PHY_TEST_PATTERN_PRBS11; + break; + case DP_TEST_PATTERN_PRBS15: + pattern = PHY_TEST_PATTERN_PRBS15; + break; + case DP_TEST_PATTERN_PRBS23: + pattern = PHY_TEST_PATTERN_PRBS23; + break; + case DP_TEST_PATTERN_PRBS31: + pattern = PHY_TEST_PATTERN_PRBS31; + break; + case DP_TEST_PATTERN_264BIT_CUSTOM: + pattern = PHY_TEST_PATTERN_264BIT_CUSTOM; + break; + case DP_TEST_PATTERN_SQUARE_PULSE: + pattern = PHY_TEST_PATTERN_SQUARE_PULSE; + break; +#endif default: return false; } @@ -4964,6 +5911,208 @@ enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings if ((link_settings->link_rate >= LINK_RATE_LOW) && (link_settings->link_rate <= LINK_RATE_HIGH3)) return DP_8b_10b_ENCODING; +#if defined(CONFIG_DRM_AMD_DC_DCN) + else if ((link_settings->link_rate >= LINK_RATE_UHBR10) && + (link_settings->link_rate <= LINK_RATE_UHBR20)) + return DP_128b_132b_ENCODING; +#endif return DP_UNKNOWN_ENCODING; } +#if defined(CONFIG_DRM_AMD_DC_DCN) +// TODO - DP2.0 Link: Fix get_lane_status to handle LTTPR offset (SST and MST) +static void get_lane_status( + struct dc_link *link, + uint32_t lane_count, + union lane_status *status, + union lane_align_status_updated *status_updated) +{ + unsigned int lane; + uint8_t dpcd_buf[3] = {0}; + + if (status == NULL || status_updated == NULL) { + return; + } + + core_link_read_dpcd( + link, + DP_LANE0_1_STATUS, + dpcd_buf, + sizeof(dpcd_buf)); + + for (lane = 0; lane < lane_count; lane++) { + status[lane].raw = get_nibble_at_index(&dpcd_buf[0], lane); + } + + status_updated->raw = dpcd_buf[2]; +} + +bool dpcd_write_128b_132b_sst_payload_allocation_table( + const struct dc_stream_state *stream, + struct dc_link *link, + struct link_mst_stream_allocation_table *proposed_table, + bool allocate) +{ + const uint8_t vc_id = 1; /// VC ID always 1 for SST + const uint8_t start_time_slot = 0; /// Always start at time slot 0 for SST + bool result = false; + uint8_t req_slot_count = 0; + struct fixed31_32 avg_time_slots_per_mtp = { 0 }; + union payload_table_update_status update_status = { 0 }; + const uint32_t max_retries = 30; + uint32_t retries = 0; + + if (allocate) { + avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, link); + req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp); + } else { + /// Leave req_slot_count = 0 if allocate is false. + } + + /// Write DPCD 2C0 = 1 to start updating + update_status.bits.VC_PAYLOAD_TABLE_UPDATED = 1; + core_link_write_dpcd( + link, + DP_PAYLOAD_TABLE_UPDATE_STATUS, + &update_status.raw, + 1); + + /// Program the changes in DPCD 1C0 - 1C2 + ASSERT(vc_id == 1); + core_link_write_dpcd( + link, + DP_PAYLOAD_ALLOCATE_SET, + &vc_id, + 1); + + ASSERT(start_time_slot == 0); + core_link_write_dpcd( + link, + DP_PAYLOAD_ALLOCATE_START_TIME_SLOT, + &start_time_slot, + 1); + + ASSERT(req_slot_count <= MAX_MTP_SLOT_COUNT); /// Validation should filter out modes that exceed link BW + core_link_write_dpcd( + link, + DP_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT, + &req_slot_count, + 1); + + /// Poll till DPCD 2C0 read 1 + /// Try for at least 150ms (30 retries, with 5ms delay after each attempt) + + while (retries < max_retries) { + if (core_link_read_dpcd( + link, + DP_PAYLOAD_TABLE_UPDATE_STATUS, + &update_status.raw, + 1) == DC_OK) { + if (update_status.bits.VC_PAYLOAD_TABLE_UPDATED == 1) { + DC_LOG_DP2("SST Update Payload: downstream payload table updated."); + result = true; + break; + } + } else { + union dpcd_rev dpcdRev; + + if (core_link_read_dpcd( + link, + DP_DPCD_REV, + &dpcdRev.raw, + 1) != DC_OK) { + DC_LOG_ERROR("SST Update Payload: Unable to read DPCD revision " + "of sink while polling payload table " + "updated status bit."); + break; + } + } + retries++; + udelay(5000); + } + + if (!result && retries == max_retries) { + DC_LOG_ERROR("SST Update Payload: Payload table not updated after retries, " + "continue on. Something is wrong with the branch."); + // TODO - DP2.0 Payload: Read and log the payload table from downstream branch + } + + proposed_table->stream_count = 1; /// Always 1 stream for SST + proposed_table->stream_allocations[0].slot_count = req_slot_count; + proposed_table->stream_allocations[0].vcp_id = vc_id; + + return result; +} + +bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link) +{ + /* + * wait for ACT handled + */ + int i; + const int act_retries = 30; + enum act_return_status result = ACT_FAILED; + union payload_table_update_status update_status = {0}; + union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX]; + union lane_align_status_updated lane_status_updated; + + for (i = 0; i < act_retries; i++) { + get_lane_status(link, link->cur_link_settings.lane_count, dpcd_lane_status, &lane_status_updated); + + if (!dp_is_cr_done(link->cur_link_settings.lane_count, dpcd_lane_status) || + !dp_is_ch_eq_done(link->cur_link_settings.lane_count, dpcd_lane_status) || + !dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) || + !dp_is_interlane_aligned(lane_status_updated)) { + DC_LOG_ERROR("SST Update Payload: Link loss occurred while " + "polling for ACT handled."); + result = ACT_LINK_LOST; + break; + } + core_link_read_dpcd( + link, + DP_PAYLOAD_TABLE_UPDATE_STATUS, + &update_status.raw, + 1); + + if (update_status.bits.ACT_HANDLED == 1) { + DC_LOG_DP2("SST Update Payload: ACT handled by downstream."); + result = ACT_SUCCESS; + break; + } + + udelay(5000); + } + + if (result == ACT_FAILED) { + DC_LOG_ERROR("SST Update Payload: ACT still not handled after retries, " + "continue on. Something is wrong with the branch."); + } + + return (result == ACT_SUCCESS); +} + +struct fixed31_32 calculate_sst_avg_time_slots_per_mtp( + const struct dc_stream_state *stream, + const struct dc_link *link) +{ + struct fixed31_32 link_bw_effective = + dc_fixpt_from_int( + dc_link_bandwidth_kbps(link, &link->cur_link_settings)); + struct fixed31_32 timeslot_bw_effective = + dc_fixpt_div_int(link_bw_effective, MAX_MTP_SLOT_COUNT); + struct fixed31_32 timing_bw = + dc_fixpt_from_int( + dc_bandwidth_in_kbps_from_timing(&stream->timing)); + struct fixed31_32 avg_time_slots_per_mtp = + dc_fixpt_div(timing_bw, timeslot_bw_effective); + + return avg_time_slots_per_mtp; +} + +bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx) +{ + return (pipe_ctx->stream_res.hpo_dp_stream_enc && + pipe_ctx->stream->link->hpo_dp_link_enc && + dc_is_dp_signal(pipe_ctx->stream->signal)); +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 9c51cd09dcf1a..29b9c128c87c9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -17,6 +17,7 @@ #include "link_enc_cfg.h" #include "clk_mgr.h" #include "inc/link_dpcd.h" +#include "dccg.h" static uint8_t convert_to_count(uint8_t lttpr_repeater_count) { @@ -111,12 +112,37 @@ void dp_enable_link_phy( link->cur_link_settings = *link_settings; +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) { + /* TODO - DP2.0 HW: notify link rate change here */ + } else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) { + if (dc->clk_mgr->funcs->notify_link_rate_change) + dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); + } +#else if (dc->clk_mgr->funcs->notify_link_rate_change) dc->clk_mgr->funcs->notify_link_rate_change(dc->clk_mgr, link); - +#endif if (dmcu != NULL && dmcu->funcs->lock_phy) dmcu->funcs->lock_phy(dmcu); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) { + enable_dp_hpo_output(link, link_settings); + } else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) { + if (dc_is_dp_sst_signal(signal)) { + link_enc->funcs->enable_dp_output( + link_enc, + link_settings, + clock_source); + } else { + link_enc->funcs->enable_dp_mst_output( + link_enc, + link_settings, + clock_source); + } + } +#else if (dc_is_dp_sst_signal(signal)) { link_enc->funcs->enable_dp_output( link_enc, @@ -128,7 +154,7 @@ void dp_enable_link_phy( link_settings, clock_source); } - +#endif if (dmcu != NULL && dmcu->funcs->unlock_phy) dmcu->funcs->unlock_phy(dmcu); @@ -206,6 +232,9 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) { struct dc *dc = link->ctx->dc; struct dmcu *dmcu = dc->res_pool->dmcu; +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct hpo_dp_link_encoder *hpo_link_enc = link->hpo_dp_link_enc; +#endif struct link_encoder *link_enc; /* Link should always be assigned encoder when en-/disabling. */ @@ -221,14 +250,28 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) if (signal == SIGNAL_TYPE_EDP) { if (link->dc->hwss.edp_backlight_control) link->dc->hwss.edp_backlight_control(link, false); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING) + disable_dp_hpo_output(link, signal); + else + link_enc->funcs->disable_output(link_enc, signal); +#else link_enc->funcs->disable_output(link_enc, signal); +#endif link->dc->hwss.edp_power_control(link, false); } else { if (dmcu != NULL && dmcu->funcs->lock_phy) dmcu->funcs->lock_phy(dmcu); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link->cur_link_settings) == DP_128b_132b_ENCODING && + hpo_link_enc) + disable_dp_hpo_output(link, signal); + else + link_enc->funcs->disable_output(link_enc, signal); +#else link_enc->funcs->disable_output(link_enc, signal); - +#endif if (dmcu != NULL && dmcu->funcs->unlock_phy) dmcu->funcs->unlock_phy(dmcu); } @@ -273,6 +316,14 @@ bool dp_set_hw_training_pattern( case DP_TRAINING_PATTERN_SEQUENCE_4: test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4; break; +#if defined(CONFIG_DRM_AMD_DC_DCN) + case DP_128b_132b_TPS1: + test_pattern = DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE; + break; + case DP_128b_132b_TPS2: + test_pattern = DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE; + break; +#endif default: break; } @@ -282,6 +333,10 @@ bool dp_set_hw_training_pattern( return true; } +#if defined(CONFIG_DRM_AMD_DC_DCN) +#define DC_LOGGER \ + link->ctx->logger +#endif void dp_set_hw_lane_settings( struct dc_link *link, const struct link_training_settings *link_settings, @@ -293,7 +348,20 @@ void dp_set_hw_lane_settings( return; /* call Encoder to set lane settings */ +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dp_get_link_encoding_format(&link_settings->link_settings) == + DP_128b_132b_ENCODING) { + link->hpo_dp_link_enc->funcs->set_ffe( + link->hpo_dp_link_enc, + &link_settings->link_settings, + link_settings->lane_settings[0].FFE_PRESET.raw); + } else if (dp_get_link_encoding_format(&link_settings->link_settings) + == DP_8b_10b_ENCODING) { + encoder->funcs->dp_set_lane_settings(encoder, link_settings); + } +#else encoder->funcs->dp_set_lane_settings(encoder, link_settings); +#endif } void dp_set_hw_test_pattern( @@ -304,6 +372,9 @@ void dp_set_hw_test_pattern( { struct encoder_set_dp_phy_pattern_param pattern_param = {0}; struct link_encoder *encoder; +#if defined(CONFIG_DRM_AMD_DC_DCN) + enum dp_link_encoding link_encoding_format = dp_get_link_encoding_format(&link->cur_link_settings); +#endif /* Access link encoder based on whether it is statically * or dynamically assigned to a link. @@ -319,8 +390,27 @@ void dp_set_hw_test_pattern( pattern_param.custom_pattern_size = custom_pattern_size; pattern_param.dp_panel_mode = dp_get_panel_mode(link); +#if defined(CONFIG_DRM_AMD_DC_DCN) + switch (link_encoding_format) { + case DP_128b_132b_ENCODING: + link->hpo_dp_link_enc->funcs->set_link_test_pattern( + link->hpo_dp_link_enc, &pattern_param); + break; + case DP_8b_10b_ENCODING: + ASSERT(encoder); + encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); + break; + default: + DC_LOG_ERROR("%s: Unknown link encoding format.", __func__); + break; + } +#else encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); +#endif } +#if defined(CONFIG_DRM_AMD_DC_DCN) +#undef DC_LOGGER +#endif void dp_retrain_link_dp_test(struct dc_link *link, struct dc_link_settings *link_setting, @@ -468,7 +558,12 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) optc_dsc_mode = dsc_optc_cfg.is_pixel_format_444 ? OPTC_DSC_ENABLED_444 : OPTC_DSC_ENABLED_NATIVE_SUBSAMPLED; /* Enable DSC in encoder */ +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) + && !is_dp_128b_132b_signal(pipe_ctx)) { +#else if (dc_is_dp_signal(stream->signal) && !IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { +#endif DC_LOG_DSC("Setting stream encoder DSC config for engine %d:", (int)pipe_ctx->stream_res.stream_enc->id); dsc_optc_config_log(dsc, &dsc_optc_cfg); pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config(pipe_ctx->stream_res.stream_enc, @@ -495,13 +590,21 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) /* disable DSC in stream encoder */ if (dc_is_dp_signal(stream->signal)) { - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config( - pipe_ctx->stream_res.stream_enc, - OPTC_DSC_DISABLED, 0, 0); - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.stream_enc, false, NULL); - } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.hpo_dp_stream_enc, + false, + NULL); + else +#endif + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_config( + pipe_ctx->stream_res.stream_enc, + OPTC_DSC_DISABLED, 0, 0); + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.stream_enc, false, NULL); + } } /* disable DSC block */ @@ -562,16 +665,32 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable) dsc->funcs->dsc_get_packed_pps(dsc, &dsc_cfg, &dsc_packed_pps[0]); if (dc_is_dp_signal(stream->signal)) { DC_LOG_DSC("Setting stream encoder DSC PPS SDP for engine %d\n", (int)pipe_ctx->stream_res.stream_enc->id); - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.stream_enc, - true, - &dsc_packed_pps[0]); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.hpo_dp_stream_enc, + true, + &dsc_packed_pps[0]); + else +#endif + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.stream_enc, + true, + &dsc_packed_pps[0]); } } else { /* disable DSC PPS in stream encoder */ if (dc_is_dp_signal(stream->signal)) { - pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.stream_enc, false, NULL); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.hpo_dp_stream_enc, + false, + NULL); + else +#endif + pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( + pipe_ctx->stream_res.stream_enc, false, NULL); } } @@ -593,3 +712,167 @@ bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx) return true; } +#if defined(CONFIG_DRM_AMD_DC_DCN) +#undef DC_LOGGER +#define DC_LOGGER \ + link->ctx->logger + +static enum phyd32clk_clock_source get_phyd32clk_src(struct dc_link *link) +{ + switch (link->link_enc->transmitter) { + case TRANSMITTER_UNIPHY_A: + return PHYD32CLKA; + case TRANSMITTER_UNIPHY_B: + return PHYD32CLKB; + case TRANSMITTER_UNIPHY_C: + return PHYD32CLKC; + case TRANSMITTER_UNIPHY_D: + return PHYD32CLKD; + case TRANSMITTER_UNIPHY_E: + return PHYD32CLKE; + default: + return PHYD32CLKA; + } +} + +void enable_dp_hpo_output(struct dc_link *link, const struct dc_link_settings *link_settings) +{ + const struct dc *dc = link->dc; + enum phyd32clk_clock_source phyd32clk; + + /* Enable PHY PLL at target bit rate + * UHBR10 = 10Gbps (SYMCLK32 = 312.5MHz) + * UBR13.5 = 13.5Gbps (SYMCLK32 = 421.875MHz) + * UHBR20 = 20Gbps (SYMCLK32 = 625MHz) + */ + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + switch (link_settings->link_rate) { + case LINK_RATE_UHBR10: + dm_set_phyd32clk(dc->ctx, 312500); + break; + case LINK_RATE_UHBR13_5: + dm_set_phyd32clk(dc->ctx, 412875); + break; + case LINK_RATE_UHBR20: + dm_set_phyd32clk(dc->ctx, 625000); + break; + default: + return; + } + } else { + /* DP2.0 HW: call transmitter control to enable PHY */ + link->hpo_dp_link_enc->funcs->enable_link_phy( + link->hpo_dp_link_enc, + link_settings, + link->link_enc->transmitter); + } + + /* DCCG muxing and DTBCLK DTO */ + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + dc->res_pool->dccg->funcs->set_physymclk( + dc->res_pool->dccg, + link->link_enc_hw_inst, + PHYSYMCLK_FORCE_SRC_PHYD32CLK, + true); + + phyd32clk = get_phyd32clk_src(link); + dc->res_pool->dccg->funcs->enable_symclk32_le( + dc->res_pool->dccg, + link->hpo_dp_link_enc->inst, + phyd32clk); + link->hpo_dp_link_enc->funcs->link_enable( + link->hpo_dp_link_enc, + link_settings->lane_count); + } +} + +void disable_dp_hpo_output(struct dc_link *link, enum signal_type signal) +{ + const struct dc *dc = link->dc; + + link->hpo_dp_link_enc->funcs->link_disable(link->hpo_dp_link_enc); + + if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { + dc->res_pool->dccg->funcs->disable_symclk32_le( + dc->res_pool->dccg, + link->hpo_dp_link_enc->inst); + + dc->res_pool->dccg->funcs->set_physymclk( + dc->res_pool->dccg, + link->link_enc_hw_inst, + PHYSYMCLK_FORCE_SRC_SYMCLK, + false); + + dm_set_phyd32clk(dc->ctx, 0); + } else { + /* DP2.0 HW: call transmitter control to disable PHY */ + link->hpo_dp_link_enc->funcs->disable_link_phy( + link->hpo_dp_link_enc, + signal); + } +} + +void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable) +{ + struct dc_stream_state *stream = pipe_ctx->stream; + struct dc *dc = pipe_ctx->stream->ctx->dc; + struct pipe_ctx *odm_pipe; + int odm_combine_num_segments = 1; + enum phyd32clk_clock_source phyd32clk; + + if (enable) { + for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) + odm_combine_num_segments++; + + dc->res_pool->dccg->funcs->set_dpstreamclk( + dc->res_pool->dccg, + DTBCLK0, + pipe_ctx->stream_res.tg->inst); + + phyd32clk = get_phyd32clk_src(stream->link); + dc->res_pool->dccg->funcs->enable_symclk32_se( + dc->res_pool->dccg, + pipe_ctx->stream_res.hpo_dp_stream_enc->inst, + phyd32clk); + + dc->res_pool->dccg->funcs->set_dtbclk_dto( + dc->res_pool->dccg, + pipe_ctx->stream_res.tg->inst, + stream->phy_pix_clk, + odm_combine_num_segments, + &stream->timing); + } else { + dc->res_pool->dccg->funcs->set_dtbclk_dto( + dc->res_pool->dccg, + pipe_ctx->stream_res.tg->inst, + 0, + 0, + &stream->timing); + dc->res_pool->dccg->funcs->disable_symclk32_se( + dc->res_pool->dccg, + pipe_ctx->stream_res.hpo_dp_stream_enc->inst); + dc->res_pool->dccg->funcs->set_dpstreamclk( + dc->res_pool->dccg, + REFCLK, + pipe_ctx->stream_res.tg->inst); + } +} + +void reset_dp_hpo_stream_encoders_for_link(struct dc_link *link) +{ + const struct dc *dc = link->dc; + struct dc_state *state = dc->current_state; + uint8_t i; + + for (i = 0; i < MAX_PIPES; i++) { + if (state->res_ctx.pipe_ctx[i].stream_res.hpo_dp_stream_enc && + state->res_ctx.pipe_ctx[i].stream && + state->res_ctx.pipe_ctx[i].stream->link == link && + !state->res_ctx.pipe_ctx[i].stream->dpms_off) { + setup_dp_hpo_stream(&state->res_ctx.pipe_ctx[i], false); + } + } +} + +#undef DC_LOGGER +#endif diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index a60396d5be445..57420bf107866 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -41,6 +41,7 @@ #include "set_mode_types.h" #include "virtual/virtual_stream_encoder.h" #include "dpcd_defs.h" +#include "dc_link_dp.h" #if defined(CONFIG_DRM_AMD_DC_SI) #include "dce60/dce60_resource.h" @@ -346,6 +347,29 @@ bool resource_construct( } } +#if defined(CONFIG_DRM_AMD_DC_DCN) + pool->hpo_dp_stream_enc_count = 0; + if (create_funcs->create_hpo_dp_stream_encoder) { + for (i = 0; i < caps->num_hpo_dp_stream_encoder; i++) { + pool->hpo_dp_stream_enc[i] = create_funcs->create_hpo_dp_stream_encoder(i+ENGINE_ID_HPO_DP_0, ctx); + if (pool->hpo_dp_stream_enc[i] == NULL) + DC_ERR("DC: failed to create HPO DP stream encoder!\n"); + pool->hpo_dp_stream_enc_count++; + + } + } + + pool->hpo_dp_link_enc_count = 0; + if (create_funcs->create_hpo_dp_link_encoder) { + for (i = 0; i < caps->num_hpo_dp_link_encoder; i++) { + pool->hpo_dp_link_enc[i] = create_funcs->create_hpo_dp_link_encoder(i, ctx); + if (pool->hpo_dp_link_enc[i] == NULL) + DC_ERR("DC: failed to create HPO DP link encoder!\n"); + pool->hpo_dp_link_enc_count++; + } + } +#endif + #if defined(CONFIG_DRM_AMD_DC_DCN) for (i = 0; i < caps->num_mpc_3dlut; i++) { pool->mpc_lut[i] = dc_create_3dlut_func(); @@ -1665,6 +1689,22 @@ static void update_stream_engine_usage( } } +#if defined(CONFIG_DRM_AMD_DC_DCN) +static void update_hpo_dp_stream_engine_usage( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct hpo_dp_stream_encoder *hpo_dp_stream_enc, + bool acquired) +{ + int i; + + for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) { + if (pool->hpo_dp_stream_enc[i] == hpo_dp_stream_enc) + res_ctx->is_hpo_dp_stream_enc_acquired[i] = acquired; + } +} +#endif + /* TODO: release audio object */ void update_audio_usage( struct resource_context *res_ctx, @@ -1709,6 +1749,26 @@ static int acquire_first_free_pipe( return -1; } +#if defined(CONFIG_DRM_AMD_DC_DCN) +static struct hpo_dp_stream_encoder *find_first_free_match_hpo_dp_stream_enc_for_link( + struct resource_context *res_ctx, + const struct resource_pool *pool, + struct dc_stream_state *stream) +{ + int i; + + for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) { + if (!res_ctx->is_hpo_dp_stream_enc_acquired[i] && + pool->hpo_dp_stream_enc[i]) { + + return pool->hpo_dp_stream_enc[i]; + } + } + + return NULL; +} +#endif + static struct audio *find_first_free_audio( struct resource_context *res_ctx, const struct resource_pool *pool, @@ -1799,6 +1859,15 @@ enum dc_status dc_remove_stream_from_ctx( if (dc->res_pool->funcs->link_enc_unassign) dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(del_pipe)) { + update_hpo_dp_stream_engine_usage( + &new_ctx->res_ctx, dc->res_pool, + del_pipe->stream_res.hpo_dp_stream_enc, + false); + } +#endif + if (del_pipe->stream_res.audio) update_audio_usage( &new_ctx->res_ctx, @@ -2051,6 +2120,31 @@ enum dc_status resource_map_pool_resources( pipe_ctx->stream_res.stream_enc, true); +#if defined(CONFIG_DRM_AMD_DC_DCN) + /* Allocate DP HPO Stream Encoder based on signal, hw capabilities + * and link settings + */ + if (dc_is_dp_signal(stream->signal) && + dc->caps.dp_hpo) { + struct dc_link_settings link_settings = {0}; + + decide_link_settings(stream, &link_settings); + if (dp_get_link_encoding_format(&link_settings) == DP_128b_132b_ENCODING) { + pipe_ctx->stream_res.hpo_dp_stream_enc = + find_first_free_match_hpo_dp_stream_enc_for_link( + &context->res_ctx, pool, stream); + + if (!pipe_ctx->stream_res.hpo_dp_stream_enc) + return DC_NO_STREAM_ENC_RESOURCE; + + update_hpo_dp_stream_engine_usage( + &context->res_ctx, pool, + pipe_ctx->stream_res.hpo_dp_stream_enc, + true); + } + } +#endif + /* TODO: Add check if ASIC support and EDID audio */ if (!stream->converter_disable_audio && dc_is_audio_capable_signal(pipe_ctx->stream->signal) && @@ -2726,6 +2820,11 @@ bool pipe_need_reprogram( if (pipe_ctx_old->stream_res.dsc != pipe_ctx->stream_res.dsc) return true; +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (pipe_ctx_old->stream_res.hpo_dp_stream_enc != pipe_ctx->stream_res.hpo_dp_stream_enc) + return true; +#endif + /* DIG link encoder resource assignment for stream changed. */ if (pipe_ctx_old->stream->link_enc != pipe_ctx->stream->link_enc) return true; @@ -2975,3 +3074,22 @@ void get_audio_check(struct audio_info *aud_modes, } } +#if defined(CONFIG_DRM_AMD_DC_DCN) +struct hpo_dp_link_encoder *resource_get_unused_hpo_dp_link_encoder( + const struct resource_pool *pool) +{ + uint8_t i; + struct hpo_dp_link_encoder *enc = NULL; + + ASSERT(pool->hpo_dp_link_enc_count <= MAX_HPO_DP2_LINK_ENCODERS); + + for (i = 0; i < pool->hpo_dp_link_enc_count; i++) { + if (pool->hpo_dp_link_enc[i]->transmitter == TRANSMITTER_UNKNOWN) { + enc = pool->hpo_dp_link_enc[i]; + break; + } + } + + return enc; +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 3ab52d9a82cf6..1a2b47fdece41 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -183,6 +183,9 @@ struct dc_caps { unsigned int cursor_cache_size; struct dc_plane_cap planes[MAX_PLANES]; struct dc_color_caps color; +#if defined(CONFIG_DRM_AMD_DC_DCN) + bool dp_hpo; +#endif bool vbios_lttpr_aware; bool vbios_lttpr_enable; }; @@ -289,7 +292,15 @@ struct dc_cap_funcs { struct link_training_settings; - +#if defined(CONFIG_DRM_AMD_DC_DCN) +union allow_lttpr_non_transparent_mode { + struct { + bool DP1_4A : 1; + bool DP2_0 : 1; + } bits; + unsigned char raw; +}; +#endif /* Structure to hold configuration flags set by dm at dc creation. */ struct dc_config { bool gpu_vm_support; @@ -302,7 +313,11 @@ struct dc_config { bool edp_no_power_sequencing; bool force_enum_edp; bool forced_clocks; +#if defined(CONFIG_DRM_AMD_DC_DCN) + union allow_lttpr_non_transparent_mode allow_lttpr_non_transparent_mode; +#else bool allow_lttpr_non_transparent_mode; +#endif bool multi_mon_pp_mclk_switch; bool disable_dmcu; bool enable_4to1MPC; @@ -614,6 +629,10 @@ struct dc_debug_options { bool enable_dmcub_surface_flip; bool usbc_combo_phy_reset_wa; bool enable_dram_clock_change_one_display_vactive; +#if defined(CONFIG_DRM_AMD_DC_DCN) + /* TODO - remove once tested */ + bool legacy_dp2_lt; +#endif union mem_low_power_enable_options enable_mem_low_power; bool force_vblank_alignment; @@ -1146,6 +1165,12 @@ struct dpcd_caps { struct dc_lttpr_caps lttpr_caps; struct psr_caps psr_caps; +#if defined(CONFIG_DRM_AMD_DC_DCN) + union dp_128b_132b_supported_link_rates dp_128b_132b_supported_link_rates; + union dp_main_line_channel_coding_cap channel_coding_cap; + union dp_sink_video_fallback_formats fallback_formats; + union dp_fec_capability1 fec_cap1; +#endif }; union dpcd_sink_ext_caps { diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 4f54bde1bb1c7..a5e798b5da796 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -53,7 +53,17 @@ enum dc_link_rate { LINK_RATE_RBR2 = 0x0C, // Rate_5 (RBR2)- 3.24 Gbps/Lane LINK_RATE_RATE_6 = 0x10, // Rate_6 - 4.32 Gbps/Lane LINK_RATE_HIGH2 = 0x14, // Rate_7 (HBR2)- 5.40 Gbps/Lane +#if defined(CONFIG_DRM_AMD_DC_DCN) + LINK_RATE_HIGH3 = 0x1E, // Rate_8 (HBR3)- 8.10 Gbps/Lane + /* Starting from DP2.0 link rate enum directly represents actual + * link rate value in unit of 10 mbps + */ + LINK_RATE_UHBR10 = 1000, // UHBR10 - 10.0 Gbps/Lane + LINK_RATE_UHBR13_5 = 1350, // UHBR13.5 - 13.5 Gbps/Lane + LINK_RATE_UHBR20 = 2000, // UHBR10 - 20.0 Gbps/Lane +#else LINK_RATE_HIGH3 = 0x1E // Rate_8 (HBR3)- 8.10 Gbps/Lane +#endif }; enum dc_link_spread { @@ -90,17 +100,47 @@ enum dc_post_cursor2 { POST_CURSOR2_MAX_LEVEL = POST_CURSOR2_LEVEL3, }; +#if defined(CONFIG_DRM_AMD_DC_DCN) +enum dc_dp_ffe_preset_level { + DP_FFE_PRESET_LEVEL0 = 0, + DP_FFE_PRESET_LEVEL1, + DP_FFE_PRESET_LEVEL2, + DP_FFE_PRESET_LEVEL3, + DP_FFE_PRESET_LEVEL4, + DP_FFE_PRESET_LEVEL5, + DP_FFE_PRESET_LEVEL6, + DP_FFE_PRESET_LEVEL7, + DP_FFE_PRESET_LEVEL8, + DP_FFE_PRESET_LEVEL9, + DP_FFE_PRESET_LEVEL10, + DP_FFE_PRESET_LEVEL11, + DP_FFE_PRESET_LEVEL12, + DP_FFE_PRESET_LEVEL13, + DP_FFE_PRESET_LEVEL14, + DP_FFE_PRESET_LEVEL15, + DP_FFE_PRESET_MAX_LEVEL = DP_FFE_PRESET_LEVEL15, +}; +#endif + enum dc_dp_training_pattern { DP_TRAINING_PATTERN_SEQUENCE_1 = 0, DP_TRAINING_PATTERN_SEQUENCE_2, DP_TRAINING_PATTERN_SEQUENCE_3, DP_TRAINING_PATTERN_SEQUENCE_4, DP_TRAINING_PATTERN_VIDEOIDLE, +#if defined(CONFIG_DRM_AMD_DC_DCN) + DP_128b_132b_TPS1, + DP_128b_132b_TPS2, + DP_128b_132b_TPS2_CDS, +#endif }; enum dp_link_encoding { DP_UNKNOWN_ENCODING = 0, DP_8b_10b_ENCODING = 1, +#if defined(CONFIG_DRM_AMD_DC_DCN) + DP_128b_132b_ENCODING = 2, +#endif }; struct dc_link_settings { @@ -112,10 +152,26 @@ struct dc_link_settings { bool dpcd_source_device_specific_field_support; }; +#if defined(CONFIG_DRM_AMD_DC_DCN) +union dc_dp_ffe_preset { + struct { + uint8_t level : 4; + uint8_t reserved : 1; + uint8_t no_preshoot : 1; + uint8_t no_deemphasis : 1; + uint8_t method2 : 1; + } settings; + uint8_t raw; +}; +#endif + struct dc_lane_settings { enum dc_voltage_swing VOLTAGE_SWING; enum dc_pre_emphasis PRE_EMPHASIS; enum dc_post_cursor2 POST_CURSOR2; +#if defined(CONFIG_DRM_AMD_DC_DCN) + union dc_dp_ffe_preset FFE_PRESET; +#endif }; struct dc_link_training_settings { @@ -127,6 +183,9 @@ struct dc_link_training_overrides { enum dc_voltage_swing *voltage_swing; enum dc_pre_emphasis *pre_emphasis; enum dc_post_cursor2 *post_cursor2; +#if defined(CONFIG_DRM_AMD_DC_DCN) + union dc_dp_ffe_preset *ffe_preset; +#endif uint16_t *cr_pattern_time; uint16_t *eq_pattern_time; @@ -140,6 +199,16 @@ struct dc_link_training_overrides { bool *fec_enable; }; +#if defined(CONFIG_DRM_AMD_DC_DCN) +union payload_table_update_status { + struct { + uint8_t VC_PAYLOAD_TABLE_UPDATED:1; + uint8_t ACT_HANDLED:1; + } bits; + uint8_t raw; +}; +#endif + union dpcd_rev { struct { uint8_t MINOR:4; @@ -227,7 +296,14 @@ union lane_align_status_updated { struct { uint8_t INTERLANE_ALIGN_DONE:1; uint8_t POST_LT_ADJ_REQ_IN_PROGRESS:1; +#if defined(CONFIG_DRM_AMD_DC_DCN) + uint8_t EQ_INTERLANE_ALIGN_DONE_128b_132b:1; + uint8_t CDS_INTERLANE_ALIGN_DONE_128b_132b:1; + uint8_t LT_FAILED_128b_132b:1; + uint8_t RESERVED:1; +#else uint8_t RESERVED:4; +#endif uint8_t DOWNSTREAM_PORT_STATUS_CHANGED:1; uint8_t LINK_STATUS_UPDATED:1; } bits; @@ -240,6 +316,12 @@ union lane_adjust { uint8_t PRE_EMPHASIS_LANE:2; uint8_t RESERVED:4; } bits; +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct { + uint8_t PRESET_VALUE :4; + uint8_t RESERVED :4; + } tx_ffe; +#endif uint8_t raw; }; @@ -269,6 +351,12 @@ union dpcd_training_lane { uint8_t MAX_PRE_EMPHASIS_REACHED:1; uint8_t RESERVED:2; } bits; +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct { + uint8_t PRESET_VALUE :4; + uint8_t RESERVED :4; + } tx_ffe; +#endif uint8_t raw; }; @@ -551,12 +639,18 @@ union test_response { union phy_test_pattern { struct { +#if defined(CONFIG_DRM_AMD_DC_DCN) + /* This field is 7 bits for DP2.0 */ + uint8_t PATTERN :7; + uint8_t RESERVED :1; +#else /* DpcdPhyTestPatterns. This field is 2 bits for DP1.1 * and 3 bits for DP1.2. */ uint8_t PATTERN :3; /* BY speci, bit7:2 is 0 for DP1.1. */ uint8_t RESERVED :5; +#endif } bits; uint8_t raw; }; @@ -634,7 +728,14 @@ union dpcd_fec_capability { uint8_t UNCORRECTED_BLOCK_ERROR_COUNT_CAPABLE:1; uint8_t CORRECTED_BLOCK_ERROR_COUNT_CAPABLE:1; uint8_t BIT_ERROR_COUNT_CAPABLE:1; +#if defined(CONFIG_DRM_AMD_DC_DCN) + uint8_t PARITY_BLOCK_ERROR_COUNT_CAPABLE:1; + uint8_t ARITY_BIT_ERROR_COUNT_CAPABLE:1; + uint8_t FEC_RUNNING_INDICATOR_SUPPORTED:1; + uint8_t FEC_ERROR_REPORTING_POLICY_SUPPORTED:1; +#else uint8_t RESERVED:4; +#endif } bits; uint8_t raw; }; @@ -758,4 +859,125 @@ struct psr_caps { bool psr_exit_link_training_required; }; +#if defined(CONFIG_DRM_AMD_DC_DCN) +#define DP_MAIN_LINK_CHANNEL_CODING_CAP 0x006 +#define DP_SINK_VIDEO_FALLBACK_FORMATS 0x020 +#define DP_FEC_CAPABILITY_1 0x091 +#define DP_DFP_CAPABILITY_EXTENSION_SUPPORT 0x0A3 +#define DP_DSC_CONFIGURATION 0x161 +#define DP_PHY_SQUARE_PATTERN 0x249 +#define DP_128b_132b_SUPPORTED_LINK_RATES 0x2215 +#define DP_128b_132b_TRAINING_AUX_RD_INTERVAL 0x2216 +#define DP_TEST_264BIT_CUSTOM_PATTERN_7_0 0X2230 +#define DP_TEST_264BIT_CUSTOM_PATTERN_263_256 0X2250 +#define DP_DSC_SUPPORT_AND_DECODER_COUNT 0x2260 +#define DP_DSC_MAX_SLICE_COUNT_AND_AGGREGATION_0 0x2270 +# define DP_DSC_DECODER_0_MAXIMUM_SLICE_COUNT_MASK (1 << 0) +# define DP_DSC_DECODER_0_AGGREGATION_SUPPORT_MASK (0b111 << 1) +# define DP_DSC_DECODER_0_AGGREGATION_SUPPORT_SHIFT 1 +# define DP_DSC_DECODER_COUNT_MASK (0b111 << 5) +# define DP_DSC_DECODER_COUNT_SHIFT 5 +#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108 +#define DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER 0xF0006 +#define DP_PHY_REPEATER_128b_132b_RATES 0xF0007 +#define DP_128b_132b_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER1 0xF0022 +#define DP_INTRA_HOP_AUX_REPLY_INDICATION (1 << 3) +/* TODO - Use DRM header to replace above once available */ + +union dp_main_line_channel_coding_cap { + struct { + uint8_t DP_8b_10b_SUPPORTED :1; + uint8_t DP_128b_132b_SUPPORTED :1; + uint8_t RESERVED :6; + } bits; + uint8_t raw; +}; + +union dp_main_link_channel_coding_lttpr_cap { + struct { + uint8_t DP_128b_132b_SUPPORTED :1; + uint8_t RESERVED :7; + } bits; + uint8_t raw; +}; + +union dp_128b_132b_supported_link_rates { + struct { + uint8_t UHBR10 :1; + uint8_t UHBR20 :1; + uint8_t UHBR13_5:1; + uint8_t RESERVED:5; + } bits; + uint8_t raw; +}; + +union dp_128b_132b_supported_lttpr_link_rates { + struct { + uint8_t UHBR10 :1; + uint8_t UHBR13_5:1; + uint8_t UHBR20 :1; + uint8_t RESERVED:5; + } bits; + uint8_t raw; +}; + +union dp_sink_video_fallback_formats { + struct { + uint8_t dp_1024x768_60Hz_24bpp_support :1; + uint8_t dp_1280x720_60Hz_24bpp_support :1; + uint8_t dp_1920x1080_60Hz_24bpp_support :1; + uint8_t RESERVED :5; + } bits; + uint8_t raw; +}; + +union dp_fec_capability1 { + struct { + uint8_t AGGREGATED_ERROR_COUNTERS_CAPABLE :1; + uint8_t RESERVED :7; + } bits; + uint8_t raw; +}; + +struct dp_color_depth_caps { + uint8_t support_6bpc :1; + uint8_t support_8bpc :1; + uint8_t support_10bpc :1; + uint8_t support_12bpc :1; + uint8_t support_16bpc :1; + uint8_t RESERVED :3; +}; + +struct dp_encoding_format_caps { + uint8_t support_rgb :1; + uint8_t support_ycbcr444:1; + uint8_t support_ycbcr422:1; + uint8_t support_ycbcr420:1; + uint8_t RESERVED :4; +}; + +union dp_dfp_cap_ext { + struct { + uint8_t supported; + uint8_t max_pixel_rate_in_mps[2]; + uint8_t max_video_h_active_width[2]; + uint8_t max_video_v_active_height[2]; + struct dp_encoding_format_caps encoding_format_caps; + struct dp_color_depth_caps rgb_color_depth_caps; + struct dp_color_depth_caps ycbcr444_color_depth_caps; + struct dp_color_depth_caps ycbcr422_color_depth_caps; + struct dp_color_depth_caps ycbcr420_color_depth_caps; + } fields; + uint8_t raw[12]; +}; + +union dp_128b_132b_training_aux_rd_interval { + struct { + uint8_t VALUE :7; + uint8_t UNIT :1; + } bits; + uint8_t raw; +}; +#endif + #endif /* DC_DP_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 4450078213a27..4fdb24ba24af3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -154,6 +154,9 @@ struct dc_link { struct panel_cntl *panel_cntl; struct link_encoder *link_enc; +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct hpo_dp_link_encoder *hpo_dp_link_enc; +#endif struct graphics_object_id link_id; /* Endpoint type distinguishes display endpoints which do not have entries * in the BIOS connector table from those that do. Helps when tracking link diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index c1532930169b7..3c109c805447b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -395,9 +395,27 @@ struct dc_lttpr_caps { uint8_t max_link_rate; uint8_t phy_repeater_cnt; uint8_t max_ext_timeout; +#if defined(CONFIG_DRM_AMD_DC_DCN) + union dp_main_link_channel_coding_lttpr_cap main_link_channel_coding; + union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates; +#endif uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1]; }; +#if defined(CONFIG_DRM_AMD_DC_DCN) +struct dc_dongle_dfp_cap_ext { + bool supported; + uint16_t max_pixel_rate_in_mps; + uint16_t max_video_h_active_width; + uint16_t max_video_v_active_height; + struct dp_encoding_format_caps encoding_format_caps; + struct dp_color_depth_caps rgb_color_depth_caps; + struct dp_color_depth_caps ycbcr444_color_depth_caps; + struct dp_color_depth_caps ycbcr422_color_depth_caps; + struct dp_color_depth_caps ycbcr420_color_depth_caps; +}; +#endif + struct dc_dongle_caps { /* dongle type (DP converter, CV smart dongle) */ enum display_dongle_type dongle_type; @@ -411,6 +429,9 @@ struct dc_dongle_caps { bool is_dp_hdmi_ycbcr420_converter; uint32_t dp_hdmi_max_bpc; uint32_t dp_hdmi_max_pixel_clk_in_khz; +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct dc_dongle_dfp_cap_ext dfp_cap_ext; +#endif }; /* Scaling format */ enum scaling_transformation { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 62d595ded8668..f660472e71fb3 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1108,8 +1108,17 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) clk_mgr->funcs->enable_pme_wa(clk_mgr); /* un-mute audio */ /* TODO: audio should be per stream rather than per link */ - pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_res.hpo_dp_stream_enc, false); + else + pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( pipe_ctx->stream_res.stream_enc, false); +#else + pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_res.stream_enc, false); +#endif if (pipe_ctx->stream_res.audio) pipe_ctx->stream_res.audio->enabled = true; } @@ -1129,14 +1138,32 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx) if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false) return; +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_res.hpo_dp_stream_enc, true); + else + pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_res.stream_enc, true); +#else pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( pipe_ctx->stream_res.stream_enc, true); +#endif if (pipe_ctx->stream_res.audio) { pipe_ctx->stream_res.audio->enabled = false; if (dc_is_dp_signal(pipe_ctx->stream->signal)) +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_disable( + pipe_ctx->stream_res.hpo_dp_stream_enc); + else + pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( + pipe_ctx->stream_res.stream_enc); +#else pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( pipe_ctx->stream_res.stream_enc); +#endif else pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( pipe_ctx->stream_res.stream_enc); @@ -1166,16 +1193,37 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc); } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(pipe_ctx)) { + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->stop_dp_info_packets( + pipe_ctx->stream_res.hpo_dp_stream_enc); + } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) +#else if (dc_is_dp_signal(pipe_ctx->stream->signal)) +#endif pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( pipe_ctx->stream_res.stream_enc); dc->hwss.disable_audio_stream(pipe_ctx); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(pipe_ctx)) { + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->disable( + pipe_ctx->stream_res.hpo_dp_stream_enc); + setup_dp_hpo_stream(pipe_ctx, false); + /* TODO - DP2.0 HW: unmap stream from link encoder here */ + } else { + link->link_enc->funcs->connect_dig_be_to_fe( + link->link_enc, + pipe_ctx->stream_res.stream_enc->id, + false); + } +#else link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc, pipe_ctx->stream_res.stream_enc->id, false); +#endif } @@ -1210,7 +1258,15 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx) link->dc->hwss.set_abm_immediate_disable(pipe_ctx); } +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(pipe_ctx)) { + /* TODO - DP2.0 HW: Set ODM mode in dp hpo encoder here */ + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_blank( + pipe_ctx->stream_res.hpo_dp_stream_enc); + } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { +#else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { +#endif pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); if (!dc_is_embedded_signal(pipe_ctx->stream->signal)) { @@ -1451,10 +1507,23 @@ static enum dc_status apply_single_controller_ctx_to_hw( build_audio_output(context, pipe_ctx, &audio_output); if (dc_is_dp_signal(pipe_ctx->stream->signal)) +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup( + pipe_ctx->stream_res.hpo_dp_stream_enc, + pipe_ctx->stream_res.audio->inst, + &pipe_ctx->stream->audio_info); + else + pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( + pipe_ctx->stream_res.stream_enc, + pipe_ctx->stream_res.audio->inst, + &pipe_ctx->stream->audio_info); +#else pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.audio->inst, &pipe_ctx->stream->audio_info); +#endif else pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( pipe_ctx->stream_res.stream_enc, @@ -1469,10 +1538,18 @@ static enum dc_status apply_single_controller_ctx_to_hw( &pipe_ctx->stream->audio_info); } - /* */ - /* Do not touch stream timing on seamless boot optimization. */ - if (!pipe_ctx->stream->apply_seamless_boot_optimization) - hws->funcs.enable_stream_timing(pipe_ctx, context, dc); +#if defined(CONFIG_DRM_AMD_DC_DCN) + /* DCN3.1 FPGA Workaround + * Need to enable HPO DP Stream Encoder before setting OTG master enable. + * To do so, move calling function enable_stream_timing to only be done AFTER calling + * function core_link_enable_stream + */ + if (!(hws->wa.dp_hpo_and_otg_sequence && is_dp_128b_132b_signal(pipe_ctx))) +#endif + /* */ + /* Do not touch stream timing on seamless boot optimization. */ + if (!pipe_ctx->stream->apply_seamless_boot_optimization) + hws->funcs.enable_stream_timing(pipe_ctx, context, dc); if (hws->funcs.setup_vupdate_interrupt) hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx); @@ -1526,6 +1603,18 @@ static enum dc_status apply_single_controller_ctx_to_hw( if (!stream->dpms_off) core_link_enable_stream(context, pipe_ctx); +#if defined(CONFIG_DRM_AMD_DC_DCN) + /* DCN3.1 FPGA Workaround + * Need to enable HPO DP Stream Encoder before setting OTG master enable. + * To do so, move calling function enable_stream_timing to only be done AFTER calling + * function core_link_enable_stream + */ + if (hws->wa.dp_hpo_and_otg_sequence && is_dp_128b_132b_signal(pipe_ctx)) { + if (!pipe_ctx->stream->apply_seamless_boot_optimization) + hws->funcs.enable_stream_timing(pipe_ctx, context, dc); + } +#endif + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0; pipe_ctx->stream->link->psr_settings.psr_feature_enabled = false; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c index e4701825b5a03..2dc4b4e4ba02c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c @@ -1460,5 +1460,14 @@ void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc, if (enc->features.flags.bits.IS_HBR3_CAPABLE) max_link_cap.link_rate = LINK_RATE_HIGH3; + if (enc->features.flags.bits.IS_UHBR10_CAPABLE) + max_link_cap.link_rate = LINK_RATE_UHBR10; + + if (enc->features.flags.bits.IS_UHBR13_5_CAPABLE) + max_link_cap.link_rate = LINK_RATE_UHBR13_5; + + if (enc->features.flags.bits.IS_UHBR20_CAPABLE) + max_link_cap.link_rate = LINK_RATE_UHBR20; + *link_settings = max_link_cap; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index a47ba1d45be92..b9276da878723 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -2135,7 +2135,12 @@ void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx, params.link_settings.link_rate = link_settings->link_rate; - if (dc_is_dp_signal(pipe_ctx->stream->signal)) { + if (is_dp_128b_132b_signal(pipe_ctx)) { + /* TODO - DP2.0 HW: Set ODM mode in dp hpo encoder here */ + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_unblank( + pipe_ctx->stream_res.hpo_dp_stream_enc, + pipe_ctx->stream_res.tg->inst); + } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1) params.timing.pix_clk_100hz /= 2; pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine( @@ -2380,8 +2385,19 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) * disconnect them during disable_stream * BY this, it is logic clean to separate stream and link */ - link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, - pipe_ctx->stream_res.stream_enc->id, true); + if (is_dp_128b_132b_signal(pipe_ctx)) { + setup_dp_hpo_stream(pipe_ctx, true); + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->enable_stream( + pipe_ctx->stream_res.hpo_dp_stream_enc); + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->map_stream_to_link( + pipe_ctx->stream_res.hpo_dp_stream_enc, + pipe_ctx->stream_res.hpo_dp_stream_enc->inst, + link->hpo_dp_link_enc->inst); + } + + if (!is_dp_128b_132b_signal(pipe_ctx)) + link->link_enc->funcs->connect_dig_be_to_fe( + link->link_enc, pipe_ctx->stream_res.stream_enc->id, true); if (pipe_ctx->plane_state && pipe_ctx->plane_state->flip_immediate != 1) { if (link->dc->hwss.program_dmdata_engine) @@ -2406,7 +2422,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) /* enable audio only within mode set */ if (pipe_ctx->stream_res.audio != NULL) { - if (dc_is_dp_signal(pipe_ctx->stream->signal)) + if (is_dp_128b_132b_signal(pipe_ctx)) + pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.hpo_dp_stream_enc); + else if (dc_is_dp_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc); } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index e3e01b17c164e..0159700c148a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -63,6 +63,7 @@ #include "dcn20_dccg.h" #include "dcn20_vmid.h" #include "dc_link_ddc.h" +#include "dc_link_dp.h" #include "dce/dce_panel_cntl.h" #include "navi10_ip_offset.h" @@ -1604,6 +1605,7 @@ static void get_pixel_clock_parameters( pixel_clk_params->signal_type = pipe_ctx->stream->signal; pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; /* TODO: un-hardcode*/ + /* TODO - DP2.0 HW: calculate requested_sym_clk for UHBR rates */ pixel_clk_params->requested_sym_clk = LINK_RATE_LOW * LINK_RATE_REF_FREQ_IN_KHZ; pixel_clk_params->flags.ENABLE_SS = 0; @@ -3044,6 +3046,8 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) for (i = 0; i < dc->res_pool->pipe_count; i++) { if (!context->res_ctx.pipe_ctx[i].stream) continue; + if (is_dp_128b_132b_signal(&context->res_ctx.pipe_ctx[i])) + return true; } return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index f264a32ebade5..463e96f8f14c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -561,11 +561,6 @@ static const struct dcn10_link_enc_mask le_mask = { DPCS_DCN31_MASK_SH_LIST(_MASK) }; -#define dpp_regs(id)\ -[id] = {\ - DPP_REG_LIST_DCN30(id),\ -} - #define hpo_dp_stream_encoder_reg_list(id)\ [id] = {\ DCN3_1_HPO_DP_STREAM_ENC_REG_LIST(id)\ @@ -609,6 +604,11 @@ static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = { DCN3_1_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK) }; +#define dpp_regs(id)\ +[id] = {\ + DPP_REG_LIST_DCN30(id),\ +} + static const struct dcn3_dpp_registers dpp_regs[] = { dpp_regs(0), dpp_regs(1), @@ -1449,6 +1449,13 @@ static struct dce_hwseq *dcn31_hwseq_create( hws->regs = &hwseq_reg; hws->shifts = &hwseq_shift; hws->masks = &hwseq_mask; + /* DCN3.1 FPGA Workaround + * Need to enable HPO DP Stream Encoder before setting OTG master enable. + * To do so, move calling function enable_stream_timing to only be done AFTER calling + * function core_link_enable_stream + */ + if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) + hws->wa.dp_hpo_and_otg_sequence = true; } return hws; } @@ -2102,6 +2109,7 @@ static bool dcn31_resource_construct( dc->caps.max_slave_rgb_planes = 1; dc->caps.post_blend_color_processing = true; dc->caps.force_dp_tps4_for_cp2520 = true; + dc->caps.dp_hpo = true; dc->caps.extended_aux_timeout_support = true; dc->caps.dmcub_support = true; dc->caps.is_apu = true; diff --git a/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h b/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h index a9170b9f84d31..43f33e1860888 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h +++ b/drivers/gpu/drm/amd/display/dc/dm_cp_psp.h @@ -37,6 +37,7 @@ struct cp_psp_stream_config { uint8_t phy_idx; uint8_t assr_enabled; uint8_t mst_enabled; + uint8_t dp2_enabled; void *dm_stream_ctx; bool dpms_off; }; diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index 9ab854293ace5..8de554fb98b9b 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -160,6 +160,8 @@ void dm_set_dcn_clocks( struct dc_context *ctx, struct dc_clocks *clks); +void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz); + bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable); void dm_helpers_smu_timeout(struct dc_context *ctx, unsigned int msg_id, unsigned int param, unsigned int timeout_us); diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 01c3a31be191a..3cc110e13213c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -30,6 +30,7 @@ #define LINK_TRAINING_RETRY_DELAY 50 /* ms */ #define LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD 3200 /*us*/ #define LINK_AUX_DEFAULT_TIMEOUT_PERIOD 552 /*us*/ +#define MAX_MTP_SLOT_COUNT 64 #define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50 #define TRAINING_AUX_RD_INTERVAL 100 //us @@ -189,5 +190,26 @@ enum dc_status dpcd_configure_lttpr_mode( struct link_training_settings *lt_settings); enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings); +bool dpcd_write_128b_132b_sst_payload_allocation_table( + const struct dc_stream_state *stream, + struct dc_link *link, + struct link_mst_stream_allocation_table *proposed_table, + bool allocate); + +enum dc_status dpcd_configure_channel_coding( + struct dc_link *link, + struct link_training_settings *lt_settings); + +bool dpcd_poll_for_allocation_change_trigger(struct dc_link *link); + +struct fixed31_32 calculate_sst_avg_time_slots_per_mtp( + const struct dc_stream_state *stream, + const struct dc_link *link); +void enable_dp_hpo_output(struct dc_link *link, const struct dc_link_settings *link_settings); +void disable_dp_hpo_output(struct dc_link *link, enum signal_type signal); +void setup_dp_hpo_stream(struct pipe_ctx *pipe_ctx, bool enable); +bool is_dp_128b_132b_signal(struct pipe_ctx *pipe_ctx); +void reset_dp_hpo_stream_encoders_for_link(struct dc_link *link); + bool dp_retrieve_lttpr_cap(struct dc_link *link); #endif /* __DC_LINK_DP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h index f7f7e4fff0c29..d09eed7bcc4a4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer_private.h @@ -41,6 +41,9 @@ struct dce_hwseq_wa { bool DEGVIDCN10_254; bool DEGVIDCN21; bool disallow_self_refresh_during_multi_plane_transition; +#if defined(CONFIG_DRM_AMD_DC_DCN) + bool dp_hpo_and_otg_sequence; +#endif }; struct hwseq_wa_state { diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 713f6d5cf3e0e..3fbda9d7e2576 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -200,4 +200,9 @@ int get_num_mpc_splits(struct pipe_ctx *pipe); int get_num_odm_splits(struct pipe_ctx *pipe); +#if defined(CONFIG_DRM_AMD_DC_DCN) +struct hpo_dp_link_encoder *resource_get_unused_hpo_dp_link_encoder( + const struct resource_pool *pool); +#endif + #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index aec7389aff370..6fb7c0145cb6f 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -80,6 +80,15 @@ enum dpcd_phy_test_patterns { PHY_TEST_PATTERN_CP2520_1, PHY_TEST_PATTERN_CP2520_2, PHY_TEST_PATTERN_CP2520_3, /* same as TPS4 */ + PHY_TEST_PATTERN_128b_132b_TPS1 = 0x8, + PHY_TEST_PATTERN_128b_132b_TPS2 = 0x10, + PHY_TEST_PATTERN_PRBS9 = 0x18, + PHY_TEST_PATTERN_PRBS11 = 0x20, + PHY_TEST_PATTERN_PRBS15 = 0x28, + PHY_TEST_PATTERN_PRBS23 = 0x30, + PHY_TEST_PATTERN_PRBS31 = 0x38, + PHY_TEST_PATTERN_264BIT_CUSTOM = 0x40, + PHY_TEST_PATTERN_SQUARE_PULSE = 0x48, }; enum dpcd_test_dyn_range { @@ -135,7 +144,14 @@ enum dpcd_training_patterns { DPCD_TRAINING_PATTERN_1, DPCD_TRAINING_PATTERN_2, DPCD_TRAINING_PATTERN_3, +#if defined(CONFIG_DRM_AMD_DC_DCN) + DPCD_TRAINING_PATTERN_4 = 7, + DPCD_128b_132b_TPS1 = 1, + DPCD_128b_132b_TPS2 = 2, + DPCD_128b_132b_TPS2_CDS = 3, +#else DPCD_TRAINING_PATTERN_4 = 7 +#endif }; /* This enum is for use with PsrSinkPsrStatus.bits.sinkSelfRefreshStatus diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index efd9812c13ec2..c729b50c4f20c 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -53,7 +53,11 @@ enum edp_revision { }; enum { - LINK_RATE_REF_FREQ_IN_KHZ = 27000 /*27MHz*/ + LINK_RATE_REF_FREQ_IN_KHZ = 27000, /*27MHz*/ + BITS_PER_DP_BYTE = 10, + DATA_EFFICIENCY_8b_10b_x10000 = 8000, /* 80% data efficiency */ + DATA_EFFICIENCY_8b_10b_FEC_EFFICIENCY_x100 = 97, /* 97% data efficiency when FEC is enabled */ + DATA_EFFICIENCY_128b_132b_x10000 = 9646, /* 96.71% data efficiency x 99.75% downspread factor */ }; enum link_training_result { @@ -70,6 +74,12 @@ enum link_training_result { LINK_TRAINING_LINK_LOSS, /* Abort link training (because sink unplugged) */ LINK_TRAINING_ABORT, +#if defined(CONFIG_DRM_AMD_DC_DCN) + DP_128b_132b_LT_FAILED, + DP_128b_132b_MAX_LOOP_COUNT_REACHED, + DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT, + DP_128b_132b_CDS_DONE_TIMEOUT, +#endif }; enum lttpr_mode { @@ -86,11 +96,23 @@ struct link_training_settings { enum dc_pre_emphasis *pre_emphasis; enum dc_post_cursor2 *post_cursor2; bool should_set_fec_ready; +#if defined(CONFIG_DRM_AMD_DC_DCN) + /* TODO - factor lane_settings out because it changes during LT */ + union dc_dp_ffe_preset *ffe_preset; +#endif uint16_t cr_pattern_time; uint16_t eq_pattern_time; + uint16_t cds_pattern_time; enum dc_dp_training_pattern pattern_for_cr; enum dc_dp_training_pattern pattern_for_eq; +#if defined(CONFIG_DRM_AMD_DC_DCN) + enum dc_dp_training_pattern pattern_for_cds; + + uint32_t eq_wait_time_limit; + uint8_t eq_loop_count_limit; + uint32_t cds_wait_time_limit; +#endif bool enhanced_framing; bool allow_invalid_msa_timing_param; diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index 571fcf23cea92..370fad883e338 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -72,6 +72,9 @@ #define DC_LOG_DSC(...) DRM_DEBUG_KMS(__VA_ARGS__) #define DC_LOG_SMU(...) pr_debug("[SMU_MSG]:"__VA_ARGS__) #define DC_LOG_DWB(...) DRM_DEBUG_KMS(__VA_ARGS__) +#if defined(CONFIG_DRM_AMD_DC_DCN) +#define DC_LOG_DP2(...) DRM_DEBUG_KMS(__VA_ARGS__) +#endif struct dal_logger; @@ -123,6 +126,9 @@ enum dc_log_type { LOG_MAX_HW_POINTS, LOG_ALL_TF_CHANNELS, LOG_SAMPLE_1DLUT, +#if defined(CONFIG_DRM_AMD_DC_DCN) + LOG_DP2, +#endif LOG_SECTION_TOTAL_COUNT }; From b5ce6fe8129f7e738941c70f9a82f4a98d0c1aad Mon Sep 17 00:00:00 2001 From: Josip Pavic Date: Mon, 9 Aug 2021 15:13:49 -0400 Subject: [PATCH 007/151] drm/amd/display: add missing ABM register offsets [Why] Some ABM registers don't exist on DCN 3.01, so are missing from its register offset list. However, this list was copied to later versions of DCN that do have these registers. As a result, they're inaccessible from the driver on those DCN versions even though they exist. [How] Add the missing ABM register offsets to DCN 3.02+ Reviewed-by: Anthony Koo Acked-by: Qingqing Zhuo Signed-off-by: Josip Pavic Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_abm.h | 16 ++++++++++++++++ .../drm/amd/display/dc/dcn302/dcn302_resource.c | 2 +- .../drm/amd/display/dc/dcn303/dcn303_resource.c | 2 +- .../drm/amd/display/dc/dcn31/dcn31_resource.c | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index 456fadbbfac70..b699d1b2ba83c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -96,6 +96,22 @@ SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ NBIO_SR(BIOS_SCRATCH_2) +#define ABM_DCN302_REG_LIST(id)\ + ABM_COMMON_REG_LIST_DCE_BASE(), \ + SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ + SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ + SRI(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \ + SRI(DC_ABM1_HG_MISC_CTRL, ABM, id), \ + SRI(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \ + SRI(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \ + SRI(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \ + SRI(BL1_PWM_USER_LEVEL, ABM, id), \ + SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ + SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ + SRI(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \ + SRI(DC_ABM1_ACE_THRES_12, ABM, id), \ + NBIO_SR(BIOS_SCRATCH_2) + #define ABM_DCN30_REG_LIST(id)\ ABM_COMMON_REG_LIST_DCE_BASE(), \ SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c index 7d3ff5d444023..5cd55e8573f70 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c @@ -1462,7 +1462,7 @@ static const struct dccg_mask dccg_mask = { }; #define abm_regs(id)\ - [id] = { ABM_DCN301_REG_LIST(id) } + [id] = { ABM_DCN302_REG_LIST(id) } static const struct dce_abm_registers abm_regs[] = { abm_regs(0), diff --git a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c index dd38796ba30ad..2ce6eae7535d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c @@ -1394,7 +1394,7 @@ static const struct dccg_mask dccg_mask = { }; #define abm_regs(id)\ - [id] = { ABM_DCN301_REG_LIST(id) } + [id] = { ABM_DCN302_REG_LIST(id) } static const struct dce_abm_registers abm_regs[] = { abm_regs(0), diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 463e96f8f14c7..5a4d33836f5e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -366,7 +366,7 @@ static const struct dce110_clk_src_mask cs_mask = { #define abm_regs(id)\ [id] = {\ - ABM_DCN301_REG_LIST(id)\ + ABM_DCN302_REG_LIST(id)\ } static const struct dce_abm_registers abm_regs[] = { From e27c41d5b0681c597ac1894f4e02cf626e062250 Mon Sep 17 00:00:00 2001 From: Jude Shih Date: Sun, 25 Jul 2021 13:55:02 +0800 Subject: [PATCH 008/151] drm/amd/display: Support for DMUB HPD interrupt handling [WHY] To add support for HPD interrupt handling from DMUB. HPD interrupt could be triggered from outbox1 from DMUB [HOW] 1) Use queue_work to handle hpd task from outbox1 2) Add handle_hpd_irq_helper to share interrupt handling code between legacy and DMUB HPD from outbox1 3) Added DMUB HPD handling in dmub_srv_stat_get_notification(). HPD handling callback function and wake up the DMUB thread. Reviewed-by: Nicholas Kazlauskas Acked-by: Qingqing Zhuo Signed-off-by: Jude Shih Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 171 +++++++++++++++++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 40 ++++ 2 files changed, 203 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9b1fc54555ee6..e771da33a24ad 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -215,6 +215,8 @@ static void handle_cursor_update(struct drm_plane *plane, static const struct drm_format_info * amd_get_format_info(const struct drm_mode_fb_cmd2 *cmd); +static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector); + static bool is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state, struct drm_crtc_state *new_crtc_state); @@ -618,6 +620,116 @@ static void dm_dcn_vertical_interrupt0_high_irq(void *interrupt_params) } #endif +/** + * dmub_aux_setconfig_reply_callback - Callback for AUX or SET_CONFIG command. + * @adev: amdgpu_device pointer + * @notify: dmub notification structure + * + * Dmub AUX or SET_CONFIG command completion processing callback + * Copies dmub notification to DM which is to be read by AUX command. + * issuing thread and also signals the event to wake up the thread. + */ +void dmub_aux_setconfig_callback(struct amdgpu_device *adev, struct dmub_notification *notify) +{ + if (adev->dm.dmub_notify) + memcpy(adev->dm.dmub_notify, notify, sizeof(struct dmub_notification)); + if (notify->type == DMUB_NOTIFICATION_AUX_REPLY) + complete(&adev->dm.dmub_aux_transfer_done); +} + +/** + * dmub_hpd_callback - DMUB HPD interrupt processing callback. + * @adev: amdgpu_device pointer + * @notify: dmub notification structure + * + * Dmub Hpd interrupt processing callback. Gets displayindex through the + * ink index and calls helper to do the processing. + */ +void dmub_hpd_callback(struct amdgpu_device *adev, struct dmub_notification *notify) +{ + struct amdgpu_dm_connector *aconnector; + struct drm_connector *connector; + struct drm_connector_list_iter iter; + struct dc_link *link; + uint8_t link_index = 0; + struct drm_device *dev = adev->dm.ddev; + + if (adev == NULL) + return; + + if (notify == NULL) { + DRM_ERROR("DMUB HPD callback notification was NULL"); + return; + } + + if (notify->link_index > adev->dm.dc->link_count) { + DRM_ERROR("DMUB HPD index (%u)is abnormal", notify->link_index); + return; + } + + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); + + link_index = notify->link_index; + + link = adev->dm.dc->links[link_index]; + + drm_connector_list_iter_begin(dev, &iter); + drm_for_each_connector_iter(connector, &iter) { + aconnector = to_amdgpu_dm_connector(connector); + if (link && aconnector->dc_link == link) { + DRM_INFO("DMUB HPD callback: link_index=%u\n", link_index); + handle_hpd_irq_helper(aconnector); + break; + } + } + drm_connector_list_iter_end(&iter); + drm_modeset_unlock(&dev->mode_config.connection_mutex); + +} + +/** + * register_dmub_notify_callback - Sets callback for DMUB notify + * @adev: amdgpu_device pointer + * @type: Type of dmub notification + * @callback: Dmub interrupt callback function + * @dmub_int_thread_offload: offload indicator + * + * API to register a dmub callback handler for a dmub notification + * Also sets indicator whether callback processing to be offloaded. + * to dmub interrupt handling thread + * Return: true if successfully registered, false if there is existing registration + */ +bool register_dmub_notify_callback(struct amdgpu_device *adev, enum dmub_notification_type type, +dmub_notify_interrupt_callback_t callback, bool dmub_int_thread_offload) +{ + if (callback != NULL && type < ARRAY_SIZE(adev->dm.dmub_thread_offload)) { + adev->dm.dmub_callback[type] = callback; + adev->dm.dmub_thread_offload[type] = dmub_int_thread_offload; + } else + return false; + + return true; +} + +static void dm_handle_hpd_work(struct work_struct *work) +{ + struct dmub_hpd_work *dmub_hpd_wrk; + + dmub_hpd_wrk = container_of(work, struct dmub_hpd_work, handle_hpd_work); + + if (!dmub_hpd_wrk->dmub_notify) { + DRM_ERROR("dmub_hpd_wrk dmub_notify is NULL"); + return; + } + + if (dmub_hpd_wrk->dmub_notify->type < ARRAY_SIZE(dmub_hpd_wrk->adev->dm.dmub_callback)) { + dmub_hpd_wrk->adev->dm.dmub_callback[dmub_hpd_wrk->dmub_notify->type](dmub_hpd_wrk->adev, + dmub_hpd_wrk->dmub_notify); + } + kfree(dmub_hpd_wrk); + +} + #define DMUB_TRACE_MAX_READ 64 /** * dm_dmub_outbox1_low_irq() - Handles Outbox interrupt @@ -634,18 +746,33 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params) struct amdgpu_display_manager *dm = &adev->dm; struct dmcub_trace_buf_entry entry = { 0 }; uint32_t count = 0; + struct dmub_hpd_work *dmub_hpd_wrk; if (dc_enable_dmub_notifications(adev->dm.dc)) { + dmub_hpd_wrk = kzalloc(sizeof(*dmub_hpd_wrk), GFP_ATOMIC); + if (!dmub_hpd_wrk) { + DRM_ERROR("Failed to allocate dmub_hpd_wrk"); + return; + } + INIT_WORK(&dmub_hpd_wrk->handle_hpd_work, dm_handle_hpd_work); + if (irq_params->irq_src == DC_IRQ_SOURCE_DMCUB_OUTBOX) { do { dc_stat_get_dmub_notification(adev->dm.dc, ¬ify); - } while (notify.pending_notification); + if (notify.type > ARRAY_SIZE(dm->dmub_thread_offload)) { + DRM_ERROR("DM: notify type %d larger than the array size %ld !", notify.type, + ARRAY_SIZE(dm->dmub_thread_offload)); + continue; + } + if (dm->dmub_thread_offload[notify.type] == true) { + dmub_hpd_wrk->dmub_notify = ¬ify; + dmub_hpd_wrk->adev = adev; + queue_work(adev->dm.delayed_hpd_wq, &dmub_hpd_wrk->handle_hpd_work); + } else { + dm->dmub_callback[notify.type](adev, ¬ify); + } - if (adev->dm.dmub_notify) - memcpy(adev->dm.dmub_notify, ¬ify, sizeof(struct dmub_notification)); - if (notify.type == DMUB_NOTIFICATION_AUX_REPLY) - complete(&adev->dm.dmub_aux_transfer_done); - // TODO : HPD Implementation + } while (notify.pending_notification); } else { DRM_ERROR("DM: Failed to receive correct outbox IRQ !"); @@ -1251,7 +1378,25 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) DRM_INFO("amdgpu: fail to allocate adev->dm.dmub_notify"); goto error; } + + adev->dm.delayed_hpd_wq = create_singlethread_workqueue("amdgpu_dm_hpd_wq"); + if (!adev->dm.delayed_hpd_wq) { + DRM_ERROR("amdgpu: failed to create hpd offload workqueue.\n"); + goto error; + } + amdgpu_dm_outbox_init(adev); +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_AUX_REPLY, + dmub_aux_setconfig_callback, false)) { + DRM_ERROR("amdgpu: fail to register dmub aux callback"); + goto error; + } + if (!register_dmub_notify_callback(adev, DMUB_NOTIFICATION_HPD, dmub_hpd_callback, true)) { + DRM_ERROR("amdgpu: fail to register dmub hpd callback"); + goto error; + } +#endif } if (amdgpu_dm_initialize_drm_device(adev)) { @@ -1333,6 +1478,8 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) if (dc_enable_dmub_notifications(adev->dm.dc)) { kfree(adev->dm.dmub_notify); adev->dm.dmub_notify = NULL; + destroy_workqueue(adev->dm.delayed_hpd_wq); + adev->dm.delayed_hpd_wq = NULL; } if (adev->dm.dmub_bo) @@ -2611,9 +2758,8 @@ void amdgpu_dm_update_connector_after_detect( dc_sink_release(sink); } -static void handle_hpd_irq(void *param) +static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) { - struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param; struct drm_connector *connector = &aconnector->base; struct drm_device *dev = connector->dev; enum dc_connection_type new_connection_type = dc_connection_none; @@ -2672,6 +2818,15 @@ static void handle_hpd_irq(void *param) } +static void handle_hpd_irq(void *param) +{ + struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param; + + handle_hpd_irq_helper(aconnector); + +} + + static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) { uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index d1d353a7c77d3..be796c2fed7d7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -47,6 +47,8 @@ #define AMDGPU_DM_MAX_CRTC 6 #define AMDGPU_DM_MAX_NUM_EDP 2 + +#define AMDGPU_DMUB_NOTIFICATION_MAX 5 /* #include "include/amdgpu_dal_power_if.h" #include "amdgpu_dm_irq.h" @@ -86,6 +88,21 @@ struct dm_compressor_info { uint64_t gpu_addr; }; +typedef void (*dmub_notify_interrupt_callback_t)(struct amdgpu_device *adev, struct dmub_notification *notify); + +/** + * struct dmub_hpd_work - Handle time consuming work in low priority outbox IRQ + * + * @handle_hpd_work: Work to be executed in a separate thread to handle hpd_low_irq + * @dmub_notify: notification for callback function + * @adev: amdgpu_device pointer + */ +struct dmub_hpd_work { + struct work_struct handle_hpd_work; + struct dmub_notification *dmub_notify; + struct amdgpu_device *adev; +}; + /** * struct vblank_control_work - Work data for vblank control * @work: Kernel work data for the work event @@ -190,8 +207,30 @@ struct amdgpu_display_manager { */ struct dmub_srv *dmub_srv; + /** + * @dmub_notify: + * + * Notification from DMUB. + */ + struct dmub_notification *dmub_notify; + /** + * @dmub_callback: + * + * Callback functions to handle notification from DMUB. + */ + + dmub_notify_interrupt_callback_t dmub_callback[AMDGPU_DMUB_NOTIFICATION_MAX]; + + /** + * @dmub_thread_offload: + * + * Flag to indicate if callback is offload. + */ + + bool dmub_thread_offload[AMDGPU_DMUB_NOTIFICATION_MAX]; + /** * @dmub_fb_info: * @@ -439,6 +478,7 @@ struct amdgpu_display_manager { */ struct list_head da_list; struct completion dmub_aux_transfer_done; + struct workqueue_struct *delayed_hpd_wq; /** * @brightness: From bc204778b4032b336cb3bde85bea852d79e7e389 Mon Sep 17 00:00:00 2001 From: Michael Strauss Date: Wed, 11 Aug 2021 11:38:44 -0400 Subject: [PATCH 009/151] drm/amd/display: Set min dcfclk if pipe count is 0 [WHY] Clocks don't get recalculated in 0 stream/0 pipe configs, blocking S0i3 if dcfclk gets high enough [HOW] Create DCN31 copy of DCN30 bandwidth validation func which doesn't entirely skip validation in 0 pipe scenarios Override dcfclk to vlevel 0/min value during validation if pipe count is 0 Reviewed-by: Eric Yang Acked-by: Qingqing Zhuo Signed-off-by: Michael Strauss Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn30/dcn30_resource.c | 2 +- .../drm/amd/display/dc/dcn30/dcn30_resource.h | 7 +++ .../drm/amd/display/dc/dcn31/dcn31_resource.c | 63 ++++++++++++++++++- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index a0de309475a97..2feffe75ca625 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -1856,7 +1856,7 @@ static struct pipe_ctx *dcn30_find_split_pipe( return pipe; } -static noinline bool dcn30_internal_validate_bw( +noinline bool dcn30_internal_validate_bw( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h index b754b89beadfb..b92e4cc0232f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h @@ -55,6 +55,13 @@ unsigned int dcn30_calc_max_scaled_time( bool dcn30_validate_bandwidth(struct dc *dc, struct dc_state *context, bool fast_validate); +bool dcn30_internal_validate_bw( + struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *pipe_cnt_out, + int *vlevel_out, + bool fast_validate); void dcn30_calculate_wm_and_dlg( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 5a4d33836f5e0..3223a1ff2292b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -1827,6 +1827,15 @@ static void dcn31_calculate_wm_and_dlg_fp( if (context->bw_ctx.dml.soc.min_dcfclk > dcfclk) dcfclk = context->bw_ctx.dml.soc.min_dcfclk; + /* We don't recalculate clocks for 0 pipe configs, which can block + * S0i3 as high clocks will block low power states + * Override any clocks that can block S0i3 to min here + */ + if (pipe_cnt == 0) { + context->bw_ctx.bw.dcn.clk.dcfclk_khz = dcfclk; // always should be vlevel 0 + return; + } + pipes[0].clks_cfg.voltage = vlevel; pipes[0].clks_cfg.dcfclk_mhz = dcfclk; pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz; @@ -1952,6 +1961,58 @@ static void dcn31_calculate_wm_and_dlg( DC_FP_END(); } +bool dcn31_validate_bandwidth(struct dc *dc, + struct dc_state *context, + bool fast_validate) +{ + bool out = false; + + BW_VAL_TRACE_SETUP(); + + int vlevel = 0; + int pipe_cnt = 0; + display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); + DC_LOGGER_INIT(dc->ctx->logger); + + BW_VAL_TRACE_COUNT(); + + out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate); + + // Disable fast_validate to set min dcfclk in alculate_wm_and_dlg + if (pipe_cnt == 0) + fast_validate = false; + + if (!out) + goto validate_fail; + + BW_VAL_TRACE_END_VOLTAGE_LEVEL(); + + if (fast_validate) { + BW_VAL_TRACE_SKIP(fast); + goto validate_out; + } + + dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); + + BW_VAL_TRACE_END_WATERMARKS(); + + goto validate_out; + +validate_fail: + DC_LOG_WARNING("Mode Validation Warning: %s failed alidation.\n", + dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); + + BW_VAL_TRACE_SKIP(fail); + out = false; + +validate_out: + kfree(pipes); + + BW_VAL_TRACE_FINISH(); + + return out; +} + static struct dc_cap_funcs cap_funcs = { .get_dcc_compression_cap = dcn20_get_dcc_compression_cap }; @@ -2034,7 +2095,7 @@ static struct resource_funcs dcn31_res_pool_funcs = { .link_encs_assign = link_enc_cfg_link_encs_assign, .link_enc_unassign = link_enc_cfg_link_enc_unassign, .panel_cntl_create = dcn31_panel_cntl_create, - .validate_bandwidth = dcn30_validate_bandwidth, + .validate_bandwidth = dcn31_validate_bandwidth, .calculate_wm_and_dlg = dcn31_calculate_wm_and_dlg, .update_soc_for_wm_a = dcn31_update_soc_for_wm_a, .populate_dml_pipes = dcn31_populate_dml_pipes_from_context, From f1c1a98221493fcb56bebaf3f1850f7c5eaae363 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Fri, 30 Jul 2021 17:35:35 -0400 Subject: [PATCH 010/151] drm/amd/display: Use max target bpp override option [Why] Max target bpp override is an option for working around DSC issues. It is supported on DC level, but was not used in DM. [How] Use actual option value instead of 0. Reviewed-by: Rodrigo Siqueira Acked-by: Qingqing Zhuo Signed-off-by: Roman Li Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 +++++++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e771da33a24ad..c648f45f48760 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5753,9 +5753,15 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector, { struct drm_connector *drm_connector = &aconnector->base; uint32_t link_bandwidth_kbps; + uint32_t max_dsc_target_bpp_limit_override = 0; link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, dc_link_get_link_cap(aconnector->dc_link)); + + if (stream->link && stream->link->local_sink) + max_dsc_target_bpp_limit_override = + stream->link->local_sink->edid_caps.panel_patch.max_dsc_target_bpp_limit; + /* Set DSC policy according to dsc_clock_en */ dc_dsc_policy_set_enable_dsc_when_not_needed( aconnector->dsc_settings.dsc_force_enable == DSC_CLK_FORCE_ENABLE); @@ -5765,7 +5771,7 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector, if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0], dsc_caps, aconnector->dc_link->ctx->dc->debug.dsc_min_slice_height_override, - 0, + max_dsc_target_bpp_limit_override, link_bandwidth_kbps, &stream->timing, &stream->timing.dsc_cfg)) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 1bcba6943fd7f..705f2e67edb5e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -547,7 +547,7 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p params[i].sink->ctx->dc->res_pool->dscs[0], ¶ms[i].sink->dsc_caps.dsc_dec_caps, params[i].sink->ctx->dc->debug.dsc_min_slice_height_override, - 0, + params[i].sink->edid_caps.panel_patch.max_dsc_target_bpp_limit, 0, params[i].timing, ¶ms[i].timing->dsc_cfg)) { @@ -579,7 +579,7 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn) param.sink->ctx->dc->res_pool->dscs[0], ¶m.sink->dsc_caps.dsc_dec_caps, param.sink->ctx->dc->debug.dsc_min_slice_height_override, - 0, + param.sink->edid_caps.panel_patch.max_dsc_target_bpp_limit, (int) kbps, param.timing, &dsc_config); return dsc_config.bits_per_pixel; From 55eea8ef98641f6e1e1c202bd3a49a57c1dd4059 Mon Sep 17 00:00:00 2001 From: Roman Li Date: Fri, 30 Jul 2021 18:30:41 -0400 Subject: [PATCH 011/151] drm/amd/display: Limit max DSC target bpp for specific monitors [Why] Some monitors exhibit corruption at 16bpp DSC. [How] - Add helpers for patching edid caps. - Use it for limiting DSC target bitrate to 15bpp for known monitors Reviewed-by: Rodrigo Siqueira Acked-by: Qingqing Zhuo Signed-off-by: Roman Li Cc: stable@vger.kernel.org Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 22ddd8d71bcf2..8c17926378367 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -40,6 +40,39 @@ #include "dm_helpers.h" +struct monitor_patch_info { + unsigned int manufacturer_id; + unsigned int product_id; + void (*patch_func)(struct dc_edid_caps *edid_caps, unsigned int param); + unsigned int patch_param; +}; +static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param); + +static const struct monitor_patch_info monitor_patch_table[] = { +{0x6D1E, 0x5BBF, set_max_dsc_bpp_limit, 15}, +{0x6D1E, 0x5B9A, set_max_dsc_bpp_limit, 15}, +}; + +static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param) +{ + if (edid_caps) + edid_caps->panel_patch.max_dsc_target_bpp_limit = param; +} + +static int amdgpu_dm_patch_edid_caps(struct dc_edid_caps *edid_caps) +{ + int i, ret = 0; + + for (i = 0; i < ARRAY_SIZE(monitor_patch_table); i++) + if ((edid_caps->manufacturer_id == monitor_patch_table[i].manufacturer_id) + && (edid_caps->product_id == monitor_patch_table[i].product_id)) { + monitor_patch_table[i].patch_func(edid_caps, monitor_patch_table[i].patch_param); + ret++; + } + + return ret; +} + /* dm_helpers_parse_edid_caps * * Parse edid caps @@ -125,6 +158,8 @@ enum dc_edid_status dm_helpers_parse_edid_caps( kfree(sads); kfree(sadb); + amdgpu_dm_patch_edid_caps(edid_caps); + return result; } From 9b2fdc332189334f8b33ff5d62594a2fb65794f0 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Wed, 11 Aug 2021 14:38:44 -0400 Subject: [PATCH 012/151] drm/amd/display: Add emulated sink support for updating FS [Why] When forced modes are used during certain IGT tests, without a real connector, dc_sink would be null when standard modes are added by the driver. Calling the function to update freesync capabilities at this point will result in an error being printed [How] Use emulated sink when available. If both the normal and emulated sink are not available, set all freesync parameters to 0. Reviewed-by: Nicholas Kazlauskas Acked-by: Qingqing Zhuo Signed-off-by: Aurabindo Pillai Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index c648f45f48760..7f311bba97355 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -10917,6 +10917,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); struct dm_connector_state *dm_con_state = NULL; + struct dc_sink *sink = amdgpu_dm_connector->dc_sink; struct drm_device *dev = connector->dev; struct amdgpu_device *adev = drm_to_adev(dev); @@ -10928,28 +10929,31 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, goto update; } - if (!edid) { + sink = amdgpu_dm_connector->dc_sink ? + amdgpu_dm_connector->dc_sink : + amdgpu_dm_connector->dc_em_sink; + + if (!edid || !sink) { dm_con_state = to_dm_connector_state(connector->state); amdgpu_dm_connector->min_vfreq = 0; amdgpu_dm_connector->max_vfreq = 0; amdgpu_dm_connector->pixel_clock_mhz = 0; + connector->display_info.monitor_range.min_vfreq = 0; + connector->display_info.monitor_range.max_vfreq = 0; + freesync_capable = false; goto update; } dm_con_state = to_dm_connector_state(connector->state); - if (!amdgpu_dm_connector->dc_sink) { - DRM_ERROR("dc_sink NULL, could not add free_sync module.\n"); - goto update; - } if (!adev->dm.freesync_module) goto update; - if (amdgpu_dm_connector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT - || amdgpu_dm_connector->dc_sink->sink_signal == SIGNAL_TYPE_EDP) { + if (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT + || sink->sink_signal == SIGNAL_TYPE_EDP) { bool edid_check_required = false; if (edid) { @@ -10996,7 +11000,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, freesync_capable = true; } } - } else if (edid && amdgpu_dm_connector->dc_sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) { + } else if (edid && sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A) { i = parse_hdmi_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info); if (i >= 0 && vsdb_info.freesync_supported) { timing = &edid->detailed_timings[i]; From 94b1c9c739ed986c34bbadd3ecdb99a184c574c5 Mon Sep 17 00:00:00 2001 From: Wyatt Wood Date: Thu, 12 Aug 2021 11:23:27 -0400 Subject: [PATCH 013/151] drm/amd/display: Initialize GSP1 SDP header [Why + How] Initialize GSP1 SDP header for use in DMCUB FW. Reviewed-by: Anthony Koo Acked-by: Qingqing Zhuo Signed-off-by: Wyatt Wood Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn10/dcn10_stream_encoder.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index cf364ae931386..bccefb6c22c84 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -726,6 +726,16 @@ void enc1_stream_encoder_update_dp_info_packets( 0, /* packetIndex */ &info_frame->vsc); + /* VSC SDP at packetIndex 1 is used by PSR in DMCUB FW. + * Note that the enablement of GSP1 is not done below, + * it's done in FW. + */ + if (info_frame->vsc.valid) + enc1_update_generic_info_packet( + enc1, + 1, /* packetIndex */ + &info_frame->vsc); + if (info_frame->spd.valid) enc1_update_generic_info_packet( enc1, From 58065a1e524de30df9a2d8214661d5d7eed0a2d9 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Fri, 30 Jul 2021 16:55:06 -0400 Subject: [PATCH 014/151] drm/amd/display: Update swizzle mode enums [Why] Swizzle mode enum for DC_SW_VAR_R_X was existing, but not mapped correctly. [How] Update mapping and conversion for DC_SW_VAR_R_X. Reviewed-by: XiangBing Foo Reviewed-by: Martin Leung Acked-by: Qingqing Zhuo Signed-off-by: Alvin Lee Cc: stable@vger.kernel.org Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 4 +++- drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 0159700c148a1..7bab88356df48 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -1856,7 +1856,9 @@ static void swizzle_to_dml_params( case DC_SW_VAR_D_X: *sw_mode = dm_sw_var_d_x; break; - + case DC_SW_VAR_R_X: + *sw_mode = dm_sw_var_r_x; + break; default: ASSERT(0); /* Not supported */ break; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h index 1051ca1a23b8a..edb9f7567d6d9 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h @@ -80,11 +80,11 @@ enum dm_swizzle_mode { dm_sw_SPARE_13 = 24, dm_sw_64kb_s_x = 25, dm_sw_64kb_d_x = 26, - dm_sw_SPARE_14 = 27, + dm_sw_64kb_r_x = 27, dm_sw_SPARE_15 = 28, dm_sw_var_s_x = 29, dm_sw_var_d_x = 30, - dm_sw_64kb_r_x, + dm_sw_var_r_x = 31, dm_sw_gfx7_2d_thin_l_vp, dm_sw_gfx7_2d_thin_gl, }; From 3a9d5b0b5301fb992554ee93ae34fe91771e6434 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sat, 14 Aug 2021 20:02:06 -0400 Subject: [PATCH 015/151] drm/amd/display: [FW Promotion] Release 0.0.80 - Add volatile to avoid incomplete flushing of data in rb Reviewed-by: Aric Cyr Acked-by: Qingqing Zhuo Signed-off-by: Anthony Koo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 13611c94a3bb8..3388188701d3a 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -47,10 +47,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x7383caadc +#define DMUB_FW_VERSION_GIT_HASH 0x591aacca1 #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 79 +#define DMUB_FW_VERSION_REVISION 80 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 @@ -2485,14 +2485,16 @@ static inline bool dmub_rb_full(struct dmub_rb *rb) static inline bool dmub_rb_push_front(struct dmub_rb *rb, const union dmub_rb_cmd *cmd) { - uint8_t *dst = (uint8_t *)(rb->base_address) + rb->wrpt; - const uint8_t *src = (const uint8_t *)cmd; + uint64_t volatile *dst = (uint64_t volatile *)(rb->base_address) + rb->wrpt / sizeof(uint64_t); + const uint64_t *src = (const uint64_t *)cmd; + uint8_t i; if (dmub_rb_full(rb)) return false; // copying data - dmub_memcpy(dst, src, DMUB_RB_CMD_SIZE); + for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++) + *dst++ = *src++; rb->wrpt += DMUB_RB_CMD_SIZE; @@ -2601,14 +2603,16 @@ static inline bool dmub_rb_peek_offset(struct dmub_rb *rb, static inline bool dmub_rb_out_front(struct dmub_rb *rb, union dmub_rb_out_cmd *cmd) { - const uint8_t *src = (const uint8_t *)(rb->base_address) + rb->rptr; - uint8_t *dst = (uint8_t *)cmd; + const uint64_t volatile *src = (const uint64_t volatile *)(rb->base_address) + rb->rptr / sizeof(uint64_t); + uint64_t *dst = (uint64_t *)cmd; + uint8_t i; if (dmub_rb_empty(rb)) return false; // copying data - dmub_memcpy(dst, src, DMUB_RB_CMD_SIZE); + for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++) + *dst++ = *src++; return true; } @@ -2643,14 +2647,17 @@ static inline bool dmub_rb_pop_front(struct dmub_rb *rb) */ static inline void dmub_rb_flush_pending(const struct dmub_rb *rb) { - uint8_t buf[DMUB_RB_CMD_SIZE]; uint32_t rptr = rb->rptr; uint32_t wptr = rb->wrpt; while (rptr != wptr) { - const uint8_t *data = (const uint8_t *)rb->base_address + rptr; + uint64_t volatile *data = (uint64_t volatile *)rb->base_address + rptr / sizeof(uint64_t); + //uint64_t volatile *p = (uint64_t volatile *)data; + uint64_t temp; + uint8_t i; - dmub_memcpy(buf, data, DMUB_RB_CMD_SIZE); + for (i = 0; i < DMUB_RB_CMD_SIZE / sizeof(uint64_t); i++) + temp = *data++; rptr += DMUB_RB_CMD_SIZE; if (rptr >= rb->capacity) From 391ac13539cadf3377460bb7140829ee99799de4 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sat, 14 Aug 2021 20:28:55 -0400 Subject: [PATCH 016/151] drm/amd/display: 3.2.150 This version brings along following fixes: - FW promotion 0.0.80 - Add missing ABM register offsets - Fix in swizzle mode mapping - Emulated sink support for freesync - Improvoments in max target bpp Acked-by: Qingqing Zhuo Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1a2b47fdece41..0505081e4fe83 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -45,7 +45,7 @@ /* forward declaration */ struct aux_payload; -#define DC_VER "3.2.149" +#define DC_VER "3.2.150" #define MAX_SURFACES 3 #define MAX_PLANES 6 From 84d588c3de84d07ef83608b60faa4fffdea32aad Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Tue, 24 Aug 2021 20:39:18 +0200 Subject: [PATCH 017/151] drm/amdgpu: rework context priority handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To get a hardware queue priority for a context, we are currently mapping AMDGPU_CTX_PRIORITY_* to DRM_SCHED_PRIORITY_* and then to hardware queue priority, which is not the right way to do that as DRM_SCHED_PRIORITY_* is software scheduler's priority and it is independent from a hardware queue priority. Use userspace provided context priority, AMDGPU_CTX_PRIORITY_* to map a context to proper hardware queue priority. Signed-off-by: Nirmoy Das Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 127 ++++++++++++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h | 8 +- drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c | 44 ++------ 3 files changed, 105 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index e7a010b7ca1f8..c88c5c6c54a25 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -43,14 +43,61 @@ const unsigned int amdgpu_ctx_num_entities[AMDGPU_HW_IP_NUM] = { [AMDGPU_HW_IP_VCN_JPEG] = 1, }; +bool amdgpu_ctx_priority_is_valid(int32_t ctx_prio) +{ + switch (ctx_prio) { + case AMDGPU_CTX_PRIORITY_UNSET: + case AMDGPU_CTX_PRIORITY_VERY_LOW: + case AMDGPU_CTX_PRIORITY_LOW: + case AMDGPU_CTX_PRIORITY_NORMAL: + case AMDGPU_CTX_PRIORITY_HIGH: + case AMDGPU_CTX_PRIORITY_VERY_HIGH: + return true; + default: + return false; + } +} + +static enum drm_sched_priority +amdgpu_ctx_to_drm_sched_prio(int32_t ctx_prio) +{ + switch (ctx_prio) { + case AMDGPU_CTX_PRIORITY_UNSET: + return DRM_SCHED_PRIORITY_UNSET; + + case AMDGPU_CTX_PRIORITY_VERY_LOW: + return DRM_SCHED_PRIORITY_MIN; + + case AMDGPU_CTX_PRIORITY_LOW: + return DRM_SCHED_PRIORITY_MIN; + + case AMDGPU_CTX_PRIORITY_NORMAL: + return DRM_SCHED_PRIORITY_NORMAL; + + case AMDGPU_CTX_PRIORITY_HIGH: + return DRM_SCHED_PRIORITY_HIGH; + + case AMDGPU_CTX_PRIORITY_VERY_HIGH: + return DRM_SCHED_PRIORITY_HIGH; + + /* This should not happen as we sanitized userspace provided priority + * already, WARN if this happens. + */ + default: + WARN(1, "Invalid context priority %d\n", ctx_prio); + return DRM_SCHED_PRIORITY_NORMAL; + } + +} + static int amdgpu_ctx_priority_permit(struct drm_file *filp, - enum drm_sched_priority priority) + int32_t priority) { - if (priority < 0 || priority >= DRM_SCHED_PRIORITY_COUNT) + if (!amdgpu_ctx_priority_is_valid(priority)) return -EINVAL; /* NORMAL and below are accessible by everyone */ - if (priority <= DRM_SCHED_PRIORITY_NORMAL) + if (priority <= AMDGPU_CTX_PRIORITY_NORMAL) return 0; if (capable(CAP_SYS_NICE)) @@ -62,26 +109,35 @@ static int amdgpu_ctx_priority_permit(struct drm_file *filp, return -EACCES; } -static enum gfx_pipe_priority amdgpu_ctx_sched_prio_to_compute_prio(enum drm_sched_priority prio) +static enum gfx_pipe_priority amdgpu_ctx_prio_to_compute_prio(int32_t prio) { switch (prio) { - case DRM_SCHED_PRIORITY_HIGH: - case DRM_SCHED_PRIORITY_KERNEL: + case AMDGPU_CTX_PRIORITY_HIGH: + case AMDGPU_CTX_PRIORITY_VERY_HIGH: return AMDGPU_GFX_PIPE_PRIO_HIGH; default: return AMDGPU_GFX_PIPE_PRIO_NORMAL; } } -static unsigned int amdgpu_ctx_prio_sched_to_hw(struct amdgpu_device *adev, - enum drm_sched_priority prio, - u32 hw_ip) +static unsigned int amdgpu_ctx_get_hw_prio(struct amdgpu_ctx *ctx, u32 hw_ip) { + struct amdgpu_device *adev = ctx->adev; + int32_t ctx_prio; unsigned int hw_prio; - hw_prio = (hw_ip == AMDGPU_HW_IP_COMPUTE) ? - amdgpu_ctx_sched_prio_to_compute_prio(prio) : - AMDGPU_RING_PRIO_DEFAULT; + ctx_prio = (ctx->override_priority == AMDGPU_CTX_PRIORITY_UNSET) ? + ctx->init_priority : ctx->override_priority; + + switch (hw_ip) { + case AMDGPU_HW_IP_COMPUTE: + hw_prio = amdgpu_ctx_prio_to_compute_prio(ctx_prio); + break; + default: + hw_prio = AMDGPU_RING_PRIO_DEFAULT; + break; + } + hw_ip = array_index_nospec(hw_ip, AMDGPU_HW_IP_NUM); if (adev->gpu_sched[hw_ip][hw_prio].num_scheds == 0) hw_prio = AMDGPU_RING_PRIO_DEFAULT; @@ -89,15 +145,17 @@ static unsigned int amdgpu_ctx_prio_sched_to_hw(struct amdgpu_device *adev, return hw_prio; } + static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip, - const u32 ring) + const u32 ring) { struct amdgpu_device *adev = ctx->adev; struct amdgpu_ctx_entity *entity; struct drm_gpu_scheduler **scheds = NULL, *sched = NULL; unsigned num_scheds = 0; + int32_t ctx_prio; unsigned int hw_prio; - enum drm_sched_priority priority; + enum drm_sched_priority drm_prio; int r; entity = kzalloc(struct_size(entity, fences, amdgpu_sched_jobs), @@ -105,10 +163,11 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip, if (!entity) return -ENOMEM; + ctx_prio = (ctx->override_priority == AMDGPU_CTX_PRIORITY_UNSET) ? + ctx->init_priority : ctx->override_priority; entity->sequence = 1; - priority = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ? - ctx->init_priority : ctx->override_priority; - hw_prio = amdgpu_ctx_prio_sched_to_hw(adev, priority, hw_ip); + hw_prio = amdgpu_ctx_get_hw_prio(ctx, hw_ip); + drm_prio = amdgpu_ctx_to_drm_sched_prio(ctx_prio); hw_ip = array_index_nospec(hw_ip, AMDGPU_HW_IP_NUM); scheds = adev->gpu_sched[hw_ip][hw_prio].sched; @@ -124,7 +183,7 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip, num_scheds = 1; } - r = drm_sched_entity_init(&entity->entity, priority, scheds, num_scheds, + r = drm_sched_entity_init(&entity->entity, drm_prio, scheds, num_scheds, &ctx->guilty); if (r) goto error_free_entity; @@ -139,7 +198,7 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip, } static int amdgpu_ctx_init(struct amdgpu_device *adev, - enum drm_sched_priority priority, + int32_t priority, struct drm_file *filp, struct amdgpu_ctx *ctx) { @@ -161,7 +220,7 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, ctx->reset_counter_query = ctx->reset_counter; ctx->vram_lost_counter = atomic_read(&adev->vram_lost_counter); ctx->init_priority = priority; - ctx->override_priority = DRM_SCHED_PRIORITY_UNSET; + ctx->override_priority = AMDGPU_CTX_PRIORITY_UNSET; return 0; } @@ -234,7 +293,7 @@ int amdgpu_ctx_get_entity(struct amdgpu_ctx *ctx, u32 hw_ip, u32 instance, static int amdgpu_ctx_alloc(struct amdgpu_device *adev, struct amdgpu_fpriv *fpriv, struct drm_file *filp, - enum drm_sched_priority priority, + int32_t priority, uint32_t *id) { struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr; @@ -397,19 +456,19 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, { int r; uint32_t id; - enum drm_sched_priority priority; + int32_t priority; union drm_amdgpu_ctx *args = data; struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv = filp->driver_priv; id = args->in.ctx_id; - r = amdgpu_to_sched_priority(args->in.priority, &priority); + priority = args->in.priority; /* For backwards compatibility reasons, we need to accept * ioctls with garbage in the priority field */ - if (r == -EINVAL) - priority = DRM_SCHED_PRIORITY_NORMAL; + if (!amdgpu_ctx_priority_is_valid(priority)) + priority = AMDGPU_CTX_PRIORITY_NORMAL; switch (args->in.op) { case AMDGPU_CTX_OP_ALLOC_CTX: @@ -515,9 +574,9 @@ struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, } static void amdgpu_ctx_set_entity_priority(struct amdgpu_ctx *ctx, - struct amdgpu_ctx_entity *aentity, - int hw_ip, - enum drm_sched_priority priority) + struct amdgpu_ctx_entity *aentity, + int hw_ip, + int32_t priority) { struct amdgpu_device *adev = ctx->adev; unsigned int hw_prio; @@ -525,12 +584,12 @@ static void amdgpu_ctx_set_entity_priority(struct amdgpu_ctx *ctx, unsigned num_scheds; /* set sw priority */ - drm_sched_entity_set_priority(&aentity->entity, priority); + drm_sched_entity_set_priority(&aentity->entity, + amdgpu_ctx_to_drm_sched_prio(priority)); /* set hw priority */ if (hw_ip == AMDGPU_HW_IP_COMPUTE) { - hw_prio = amdgpu_ctx_prio_sched_to_hw(adev, priority, - AMDGPU_HW_IP_COMPUTE); + hw_prio = amdgpu_ctx_get_hw_prio(ctx, hw_ip); hw_prio = array_index_nospec(hw_prio, AMDGPU_RING_PRIO_MAX); scheds = adev->gpu_sched[hw_ip][hw_prio].sched; num_scheds = adev->gpu_sched[hw_ip][hw_prio].num_scheds; @@ -540,14 +599,14 @@ static void amdgpu_ctx_set_entity_priority(struct amdgpu_ctx *ctx, } void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx, - enum drm_sched_priority priority) + int32_t priority) { - enum drm_sched_priority ctx_prio; + int32_t ctx_prio; unsigned i, j; ctx->override_priority = priority; - ctx_prio = (ctx->override_priority == DRM_SCHED_PRIORITY_UNSET) ? + ctx_prio = (ctx->override_priority == AMDGPU_CTX_PRIORITY_UNSET) ? ctx->init_priority : ctx->override_priority; for (i = 0; i < AMDGPU_HW_IP_NUM; ++i) { for (j = 0; j < amdgpu_ctx_num_entities[i]; ++j) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h index 14db16bc33222..a44b8b8ed39c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.h @@ -47,8 +47,8 @@ struct amdgpu_ctx { spinlock_t ring_lock; struct amdgpu_ctx_entity *entities[AMDGPU_HW_IP_NUM][AMDGPU_MAX_ENTITY_NUM]; bool preamble_presented; - enum drm_sched_priority init_priority; - enum drm_sched_priority override_priority; + int32_t init_priority; + int32_t override_priority; struct mutex lock; atomic_t guilty; unsigned long ras_counter_ce; @@ -75,8 +75,8 @@ void amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, struct drm_sched_entity *entity, uint64_t seq); -void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx, - enum drm_sched_priority priority); +bool amdgpu_ctx_priority_is_valid(int32_t ctx_prio); +void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx, int32_t ctx_prio); int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c index b7d861ed52849..e9b45089a28a6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c @@ -32,37 +32,9 @@ #include "amdgpu_sched.h" #include "amdgpu_vm.h" -int amdgpu_to_sched_priority(int amdgpu_priority, - enum drm_sched_priority *prio) -{ - switch (amdgpu_priority) { - case AMDGPU_CTX_PRIORITY_VERY_HIGH: - *prio = DRM_SCHED_PRIORITY_HIGH; - break; - case AMDGPU_CTX_PRIORITY_HIGH: - *prio = DRM_SCHED_PRIORITY_HIGH; - break; - case AMDGPU_CTX_PRIORITY_NORMAL: - *prio = DRM_SCHED_PRIORITY_NORMAL; - break; - case AMDGPU_CTX_PRIORITY_LOW: - case AMDGPU_CTX_PRIORITY_VERY_LOW: - *prio = DRM_SCHED_PRIORITY_MIN; - break; - case AMDGPU_CTX_PRIORITY_UNSET: - *prio = DRM_SCHED_PRIORITY_UNSET; - break; - default: - WARN(1, "Invalid context priority %d\n", amdgpu_priority); - return -EINVAL; - } - - return 0; -} - static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev, int fd, - enum drm_sched_priority priority) + int32_t priority) { struct fd f = fdget(fd); struct amdgpu_fpriv *fpriv; @@ -89,7 +61,7 @@ static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev, static int amdgpu_sched_context_priority_override(struct amdgpu_device *adev, int fd, unsigned ctx_id, - enum drm_sched_priority priority) + int32_t priority) { struct fd f = fdget(fd); struct amdgpu_fpriv *fpriv; @@ -124,7 +96,6 @@ int amdgpu_sched_ioctl(struct drm_device *dev, void *data, { union drm_amdgpu_sched *args = data; struct amdgpu_device *adev = drm_to_adev(dev); - enum drm_sched_priority priority; int r; /* First check the op, then the op's argument. @@ -138,21 +109,22 @@ int amdgpu_sched_ioctl(struct drm_device *dev, void *data, return -EINVAL; } - r = amdgpu_to_sched_priority(args->in.priority, &priority); - if (r) - return r; + if (!amdgpu_ctx_priority_is_valid(args->in.priority)) { + WARN(1, "Invalid context priority %d\n", args->in.priority); + return -EINVAL; + } switch (args->in.op) { case AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE: r = amdgpu_sched_process_priority_override(adev, args->in.fd, - priority); + args->in.priority); break; case AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE: r = amdgpu_sched_context_priority_override(adev, args->in.fd, args->in.ctx_id, - priority); + args->in.priority); break; default: /* Impossible. From 34eaf30f9a66d94f1185df852987957240b8846c Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Wed, 25 Aug 2021 17:11:31 +0200 Subject: [PATCH 018/151] drm/amdgpu: detach ring priority from gfx priority Currently AMDGPU_RING_PRIO_MAX is redefinition of a max gfx hwip priority, this won't work well when we will have a hwip with different set of priorities than gfx. Also, HW ring priorities are different from ring priorities. Create a global enum for ring priority levels which each HWIP can use to define its own priority levels. Signed-off-by: Nirmoy Das Reviewed-by: Lijo Lazar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 7 +++---- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 9 +++++++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index c88c5c6c54a25..0d19282606507 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -109,7 +109,7 @@ static int amdgpu_ctx_priority_permit(struct drm_file *filp, return -EACCES; } -static enum gfx_pipe_priority amdgpu_ctx_prio_to_compute_prio(int32_t prio) +static enum amdgpu_gfx_pipe_priority amdgpu_ctx_prio_to_compute_prio(int32_t prio) { switch (prio) { case AMDGPU_CTX_PRIORITY_HIGH: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h index d43fe2ed81168..f851196c83a55 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h @@ -42,10 +42,9 @@ #define AMDGPU_MAX_GFX_QUEUES KGD_MAX_QUEUES #define AMDGPU_MAX_COMPUTE_QUEUES KGD_MAX_QUEUES -enum gfx_pipe_priority { - AMDGPU_GFX_PIPE_PRIO_NORMAL = 1, - AMDGPU_GFX_PIPE_PRIO_HIGH, - AMDGPU_GFX_PIPE_PRIO_MAX +enum amdgpu_gfx_pipe_priority { + AMDGPU_GFX_PIPE_PRIO_NORMAL = AMDGPU_RING_PRIO_1, + AMDGPU_GFX_PIPE_PRIO_HIGH = AMDGPU_RING_PRIO_2 }; /* Argument for PPSMC_MSG_GpuChangeState */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index e713d31619fe7..88d80eb3fea12 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -36,8 +36,13 @@ #define AMDGPU_MAX_VCE_RINGS 3 #define AMDGPU_MAX_UVD_ENC_RINGS 2 -#define AMDGPU_RING_PRIO_DEFAULT 1 -#define AMDGPU_RING_PRIO_MAX AMDGPU_GFX_PIPE_PRIO_MAX +enum amdgpu_ring_priority_level { + AMDGPU_RING_PRIO_0, + AMDGPU_RING_PRIO_1, + AMDGPU_RING_PRIO_DEFAULT = 1, + AMDGPU_RING_PRIO_2, + AMDGPU_RING_PRIO_MAX +}; /* some special values for the owner field */ #define AMDGPU_FENCE_OWNER_UNDEFINED ((void *)0ul) From f9e476c5bb342bdc7f615c0e320000a96d5e3a0a Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 25 Aug 2021 12:36:15 +0100 Subject: [PATCH 019/151] drm/amd/display: fix spelling mistake "alidation" -> "validation" There is a spelling mistake in a DC_LOG_WARNING message. Fix it. Reviewed-by: Harry Wentland Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 3223a1ff2292b..91cbc0922ad43 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -1999,7 +1999,7 @@ bool dcn31_validate_bandwidth(struct dc *dc, goto validate_out; validate_fail: - DC_LOG_WARNING("Mode Validation Warning: %s failed alidation.\n", + DC_LOG_WARNING("Mode Validation Warning: %s failed validation.\n", dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states])); BW_VAL_TRACE_SKIP(fail); From 37df9560cd3e7cb23f28ab04514f0a2ab08b3cea Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 20 Aug 2021 14:03:12 -0400 Subject: [PATCH 020/151] drm/amd/amdgpu: New debugfs interface for MMIO registers (v5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This new debugfs interface uses an IOCTL interface in order to pass along state information like SRBM and GRBM bank switching. This new interface also allows a full 32-bit MMIO address range which the previous didn't. With this new design we have room to grow the flexibility of the file as need be. (v2): Move read/write to .read/.write, fix style, add comment for IOCTL data structure (v3): C style comments (v4): use u32 in struct and remove offset variable (v5): Drop flag clearing in op function, use 0xFFFFFFFF for broadcast instead of 0x3FF, use mutex for op/ioctl. Signed-off-by: Tom St Denis Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 152 ++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_umr.h | 51 +++++++ 3 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_umr.h diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 277128846dd12..d256215ab2c77 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -36,6 +36,7 @@ #include "amdgpu_rap.h" #include "amdgpu_securedisplay.h" #include "amdgpu_fw_attestation.h" +#include "amdgpu_umr.h" int amdgpu_debugfs_wait_dump(struct amdgpu_device *adev) { @@ -279,6 +280,145 @@ static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf, return amdgpu_debugfs_process_reg_op(false, f, (char __user *)buf, size, pos); } +static int amdgpu_debugfs_regs2_open(struct inode *inode, struct file *file) +{ + struct amdgpu_debugfs_regs2_data *rd; + + rd = kzalloc(sizeof *rd, GFP_KERNEL); + if (!rd) + return -ENOMEM; + rd->adev = file_inode(file)->i_private; + file->private_data = rd; + mutex_init(&rd->lock); + + return 0; +} + +static int amdgpu_debugfs_regs2_release(struct inode *inode, struct file *file) +{ + struct amdgpu_debugfs_regs2_data *rd = file->private_data; + mutex_destroy(&rd->lock); + kfree(file->private_data); + return 0; +} + +static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 offset, size_t size, int write_en) +{ + struct amdgpu_debugfs_regs2_data *rd = f->private_data; + struct amdgpu_device *adev = rd->adev; + ssize_t result = 0; + int r; + uint32_t value; + + if (size & 0x3 || offset & 0x3) + return -EINVAL; + + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); + if (r < 0) { + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + return r; + } + + r = amdgpu_virt_enable_access_debugfs(adev); + if (r < 0) { + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + return r; + } + + mutex_lock(&rd->lock); + + if (rd->id.use_grbm) { + if ((rd->id.grbm.sh != 0xFFFFFFFF && rd->id.grbm.sh >= adev->gfx.config.max_sh_per_se) || + (rd->id.grbm.se != 0xFFFFFFFF && rd->id.grbm.se >= adev->gfx.config.max_shader_engines)) { + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + amdgpu_virt_disable_access_debugfs(adev); + mutex_unlock(&rd->lock); + return -EINVAL; + } + mutex_lock(&adev->grbm_idx_mutex); + amdgpu_gfx_select_se_sh(adev, rd->id.grbm.se, + rd->id.grbm.sh, + rd->id.grbm.instance); + } + + if (rd->id.use_srbm) { + mutex_lock(&adev->srbm_mutex); + amdgpu_gfx_select_me_pipe_q(adev, rd->id.srbm.me, rd->id.srbm.pipe, + rd->id.srbm.queue, rd->id.srbm.vmid); + } + + if (rd->id.pg_lock) + mutex_lock(&adev->pm.mutex); + + while (size) { + if (!write_en) { + value = RREG32(offset >> 2); + r = put_user(value, (uint32_t *)buf); + } else { + r = get_user(value, (uint32_t *)buf); + if (!r) + amdgpu_mm_wreg_mmio_rlc(adev, offset >> 2, value); + } + if (r) { + result = r; + goto end; + } + offset += 4; + size -= 4; + result += 4; + buf += 4; + } +end: + if (rd->id.use_grbm) { + amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); + mutex_unlock(&adev->grbm_idx_mutex); + } + + if (rd->id.use_srbm) { + amdgpu_gfx_select_me_pipe_q(adev, 0, 0, 0, 0); + mutex_unlock(&adev->srbm_mutex); + } + + if (rd->id.pg_lock) + mutex_unlock(&adev->pm.mutex); + + mutex_unlock(&rd->lock); + + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); + + amdgpu_virt_disable_access_debugfs(adev); + return result; +} + +static long amdgpu_debugfs_regs2_ioctl(struct file *f, unsigned int cmd, unsigned long data) +{ + struct amdgpu_debugfs_regs2_data *rd = f->private_data; + int r; + + switch (cmd) { + case AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE: + mutex_lock(&rd->lock); + r = copy_from_user(&rd->id, (struct amdgpu_debugfs_regs2_iocdata *)data, sizeof rd->id); + mutex_unlock(&rd->lock); + return r ? -EINVAL : 0; + default: + return -EINVAL; + } + return 0; +} + +static ssize_t amdgpu_debugfs_regs2_read(struct file *f, char __user *buf, size_t size, loff_t *pos) +{ + return amdgpu_debugfs_regs2_op(f, buf, *pos, size, 0); +} + +static ssize_t amdgpu_debugfs_regs2_write(struct file *f, const char __user *buf, size_t size, loff_t *pos) +{ + return amdgpu_debugfs_regs2_op(f, (char __user *)buf, *pos, size, 1); +} + /** * amdgpu_debugfs_regs_pcie_read - Read from a PCIE register @@ -1091,6 +1231,16 @@ static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf, return result; } +static const struct file_operations amdgpu_debugfs_regs2_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = amdgpu_debugfs_regs2_ioctl, + .read = amdgpu_debugfs_regs2_read, + .write = amdgpu_debugfs_regs2_write, + .open = amdgpu_debugfs_regs2_open, + .release = amdgpu_debugfs_regs2_release, + .llseek = default_llseek +}; + static const struct file_operations amdgpu_debugfs_regs_fops = { .owner = THIS_MODULE, .read = amdgpu_debugfs_regs_read, @@ -1148,6 +1298,7 @@ static const struct file_operations amdgpu_debugfs_gfxoff_fops = { static const struct file_operations *debugfs_regs[] = { &amdgpu_debugfs_regs_fops, + &amdgpu_debugfs_regs2_fops, &amdgpu_debugfs_regs_didt_fops, &amdgpu_debugfs_regs_pcie_fops, &amdgpu_debugfs_regs_smc_fops, @@ -1160,6 +1311,7 @@ static const struct file_operations *debugfs_regs[] = { static const char *debugfs_regs_names[] = { "amdgpu_regs", + "amdgpu_regs2", "amdgpu_regs_didt", "amdgpu_regs_pcie", "amdgpu_regs_smc", diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h index 141a8474e24f2..6d4965b2d01e8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.h @@ -22,7 +22,6 @@ * OTHER DEALINGS IN THE SOFTWARE. * */ - /* * Debugfs */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umr.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umr.h new file mode 100644 index 0000000000000..919d9d4017509 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umr.h @@ -0,0 +1,51 @@ +/* + * Copyright 2021 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. + * + */ +#include + +/* + * MMIO debugfs IOCTL structure + */ +struct amdgpu_debugfs_regs2_iocdata { + __u32 use_srbm, use_grbm, pg_lock; + struct { + __u32 se, sh, instance; + } grbm; + struct { + __u32 me, pipe, queue, vmid; + } srbm; +}; + +/* + * MMIO debugfs state data (per file* handle) + */ +struct amdgpu_debugfs_regs2_data { + struct amdgpu_device *adev; + struct mutex lock; + struct amdgpu_debugfs_regs2_iocdata id; +}; + +enum AMDGPU_DEBUGFS_REGS2_CMDS { + AMDGPU_DEBUGFS_REGS2_CMD_SET_STATE=0, +}; + +#define AMDGPU_DEBUGFS_REGS2_IOC_SET_STATE _IOWR(0x20, AMDGPU_DEBUGFS_REGS2_CMD_SET_STATE, struct amdgpu_debugfs_regs2_iocdata) From 25c94b33dd3a978abf9678f5ceff693eb8426334 Mon Sep 17 00:00:00 2001 From: Candice Li Date: Fri, 27 Aug 2021 00:10:49 +0800 Subject: [PATCH 021/151] drm/amd/amdgpu: consolidate PSP TA unload function Create common PSP TA unload function and replace all common TA unloading sequences. Signed-off-by: Candice Li Reviewed-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 160 ++++++------------------ 1 file changed, 40 insertions(+), 120 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 9b41cb8c3de54..54c26432c65b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -46,6 +46,9 @@ static int psp_sysfs_init(struct amdgpu_device *adev); static void psp_sysfs_fini(struct amdgpu_device *adev); static int psp_load_smu_fw(struct psp_context *psp); +static int psp_ta_unload(struct psp_context *psp, uint32_t session_id); +static int psp_rap_terminate(struct psp_context *psp); +static int psp_securedisplay_terminate(struct psp_context *psp); /* * Due to DF Cstate management centralized to PMFW, the firmware @@ -829,10 +832,28 @@ static void psp_prep_ta_unload_cmd_buf(struct psp_gfx_cmd_resp *cmd, cmd->cmd.cmd_unload_ta.session_id = session_id; } +static int psp_ta_unload(struct psp_context *psp, uint32_t session_id) +{ + int ret; + struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); + + psp_prep_ta_unload_cmd_buf(cmd, session_id); + + ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); + + release_psp_cmd_buf(psp); + + return ret; +} + static int psp_asd_unload(struct psp_context *psp) +{ + return psp_ta_unload(psp, psp->asd_context.session_id); +} + +static int psp_asd_terminate(struct psp_context *psp) { int ret; - struct psp_gfx_cmd_resp *cmd; if (amdgpu_sriov_vf(psp->adev)) return 0; @@ -840,17 +861,11 @@ static int psp_asd_unload(struct psp_context *psp) if (!psp->asd_context.asd_initialized) return 0; - cmd = acquire_psp_cmd_buf(psp); - - psp_prep_ta_unload_cmd_buf(cmd, psp->asd_context.session_id); + ret = psp_asd_unload(psp); - ret = psp_cmd_submit_buf(psp, NULL, cmd, - psp->fence_buf_mc_addr); if (!ret) psp->asd_context.asd_initialized = false; - release_psp_cmd_buf(psp); - return ret; } @@ -990,29 +1005,7 @@ static int psp_xgmi_load(struct psp_context *psp) static int psp_xgmi_unload(struct psp_context *psp) { - int ret; - struct psp_gfx_cmd_resp *cmd; - struct amdgpu_device *adev = psp->adev; - - /* XGMI TA unload currently is not supported on Arcturus/Aldebaran A+A */ - if (adev->asic_type == CHIP_ARCTURUS || - (adev->asic_type == CHIP_ALDEBARAN && adev->gmc.xgmi.connected_to_cpu)) - return 0; - - /* - * TODO: bypass the unloading in sriov for now - */ - - cmd = acquire_psp_cmd_buf(psp); - - psp_prep_ta_unload_cmd_buf(cmd, psp->xgmi_context.context.session_id); - - ret = psp_cmd_submit_buf(psp, NULL, cmd, - psp->fence_buf_mc_addr); - - release_psp_cmd_buf(psp); - - return ret; + return psp_ta_unload(psp, psp->xgmi_context.context.session_id); } int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id) @@ -1023,6 +1016,12 @@ int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id) int psp_xgmi_terminate(struct psp_context *psp) { int ret; + struct amdgpu_device *adev = psp->adev; + + /* XGMI TA unload currently is not supported on Arcturus/Aldebaran A+A */ + if (adev->asic_type == CHIP_ARCTURUS || + (adev->asic_type == CHIP_ALDEBARAN && adev->gmc.xgmi.connected_to_cpu)) + return 0; if (!psp->xgmi_context.context.initialized) return 0; @@ -1337,25 +1336,7 @@ static int psp_ras_load(struct psp_context *psp) static int psp_ras_unload(struct psp_context *psp) { - int ret; - struct psp_gfx_cmd_resp *cmd; - - /* - * TODO: bypass the unloading in sriov for now - */ - if (amdgpu_sriov_vf(psp->adev)) - return 0; - - cmd = acquire_psp_cmd_buf(psp); - - psp_prep_ta_unload_cmd_buf(cmd, psp->ras_context.context.session_id); - - ret = psp_cmd_submit_buf(psp, NULL, cmd, - psp->fence_buf_mc_addr); - - release_psp_cmd_buf(psp); - - return ret; + return psp_ta_unload(psp, psp->ras_context.context.session_id); } int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id) @@ -1644,24 +1625,7 @@ static int psp_hdcp_initialize(struct psp_context *psp) static int psp_hdcp_unload(struct psp_context *psp) { - int ret; - struct psp_gfx_cmd_resp *cmd; - - /* - * TODO: bypass the unloading in sriov for now - */ - if (amdgpu_sriov_vf(psp->adev)) - return 0; - - cmd = acquire_psp_cmd_buf(psp); - - psp_prep_ta_unload_cmd_buf(cmd, psp->hdcp_context.context.session_id); - - ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); - - release_psp_cmd_buf(psp); - - return ret; + return psp_ta_unload(psp, psp->hdcp_context.context.session_id); } int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id) @@ -1778,24 +1742,7 @@ static int psp_dtm_initialize(struct psp_context *psp) static int psp_dtm_unload(struct psp_context *psp) { - int ret; - struct psp_gfx_cmd_resp *cmd; - - /* - * TODO: bypass the unloading in sriov for now - */ - if (amdgpu_sriov_vf(psp->adev)) - return 0; - - cmd = acquire_psp_cmd_buf(psp); - - psp_prep_ta_unload_cmd_buf(cmd, psp->dtm_context.context.session_id); - - ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); - - release_psp_cmd_buf(psp); - - return ret; + return psp_ta_unload(psp, psp->dtm_context.context.session_id); } int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id) @@ -1877,16 +1824,7 @@ static int psp_rap_load(struct psp_context *psp) static int psp_rap_unload(struct psp_context *psp) { - int ret; - struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); - - psp_prep_ta_unload_cmd_buf(cmd, psp->rap_context.context.session_id); - - ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); - - release_psp_cmd_buf(psp); - - return ret; + return psp_ta_unload(psp, psp->rap_context.context.session_id); } static int psp_rap_initialize(struct psp_context *psp) @@ -1918,11 +1856,7 @@ static int psp_rap_initialize(struct psp_context *psp) ret = psp_rap_invoke(psp, TA_CMD_RAP__INITIALIZE, &status); if (ret || status != TA_RAP_STATUS__SUCCESS) { - psp_rap_unload(psp); - - psp_ta_free_shared_buf(&psp->rap_context.context.mem_context); - - psp->rap_context.context.initialized = false; + psp_rap_terminate(psp); dev_warn(psp->adev->dev, "RAP TA initialize fail (%d) status %d.\n", ret, status); @@ -2022,16 +1956,7 @@ static int psp_securedisplay_load(struct psp_context *psp) static int psp_securedisplay_unload(struct psp_context *psp) { - int ret; - struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); - - psp_prep_ta_unload_cmd_buf(cmd, psp->securedisplay_context.context.session_id); - - ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); - - release_psp_cmd_buf(psp); - - return ret; + return psp_ta_unload(psp, psp->securedisplay_context.context.session_id); } static int psp_securedisplay_initialize(struct psp_context *psp) @@ -2066,12 +1991,7 @@ static int psp_securedisplay_initialize(struct psp_context *psp) ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA); if (ret) { - psp_securedisplay_unload(psp); - - psp_ta_free_shared_buf(&psp->securedisplay_context.context.mem_context); - - psp->securedisplay_context.context.initialized = false; - + psp_securedisplay_terminate(psp); dev_err(psp->adev->dev, "SECUREDISPLAY TA initialize fail.\n"); return -EINVAL; } @@ -2721,7 +2641,7 @@ static int psp_hw_fini(void *handle) psp_hdcp_terminate(psp); } - psp_asd_unload(psp); + psp_asd_terminate(psp); psp_tmr_terminate(psp); psp_ring_destroy(psp, PSP_RING_TYPE__KM); @@ -2779,9 +2699,9 @@ static int psp_suspend(void *handle) } } - ret = psp_asd_unload(psp); + ret = psp_asd_terminate(psp); if (ret) { - DRM_ERROR("Failed to unload asd\n"); + DRM_ERROR("Failed to terminate asd\n"); return ret; } From a0a2f7bb220945e369de77ea004d96236e9463a6 Mon Sep 17 00:00:00 2001 From: Candice Li Date: Fri, 27 Aug 2021 19:14:36 +0800 Subject: [PATCH 022/151] drm/amd/amdgpu: add mpio to ras block Add MPIO to RAS block Signed-off-by: Candice Li Reviewed-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 2 ++ drivers/gpu/drm/amd/amdgpu/ta_ras_if.h | 1 + 3 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 96a8fd0ca1df3..77140821dc112 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -61,6 +61,7 @@ const char *ras_block_string[] = { "mp0", "mp1", "fuse", + "mpio", }; #define ras_err_str(i) (ras_error_string[ffs(i)]) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index eae604fd90b81..1670467c20546 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -544,6 +544,8 @@ amdgpu_ras_block_to_ta(enum amdgpu_ras_block block) { return TA_RAS_BLOCK__MP1; case AMDGPU_RAS_BLOCK__FUSE: return TA_RAS_BLOCK__FUSE; + case AMDGPU_RAS_BLOCK__MPIO: + return TA_RAS_BLOCK__MPIO; default: WARN_ONCE(1, "RAS ERROR: unexpected block id %d\n", block); return TA_RAS_BLOCK__UMC; diff --git a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h index 0f214a398dd8f..532260fd64db1 100644 --- a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h +++ b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h @@ -73,6 +73,7 @@ enum ta_ras_block { TA_RAS_BLOCK__MP0, TA_RAS_BLOCK__MP1, TA_RAS_BLOCK__FUSE, + TA_RAS_BLOCK__MPIO, TA_NUM_BLOCK_MAX }; From 080e613c74bb50e6fc52cf466ff2a43cbd5a382b Mon Sep 17 00:00:00 2001 From: Satyajit Sahu Date: Fri, 27 Aug 2021 11:41:08 +0530 Subject: [PATCH 023/151] drm/amdgpu/vce: set the priority for each ring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VCE has multiple rings. Set the proper priority level for each ring while initializing. Signed-off-by: Satyajit Sahu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 14 ++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h | 1 + drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 4 +++- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 4 +++- drivers/gpu/drm/amd/amdgpu/vce_v4_0.c | 4 +++- 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 8e8dee9fac9f6..e9fdf49d69e8c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -1167,3 +1167,17 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout) amdgpu_bo_free_kernel(&bo, NULL, NULL); return r; } + +enum amdgpu_ring_priority_level amdgpu_vce_get_ring_prio(int ring) +{ + switch(ring) { + case 0: + return AMDGPU_RING_PRIO_0; + case 1: + return AMDGPU_RING_PRIO_1; + case 2: + return AMDGPU_RING_PRIO_2; + default: + return AMDGPU_RING_PRIO_0; + } +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h index d6d83a3ec8030..be4a6e773c5b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h @@ -71,5 +71,6 @@ void amdgpu_vce_ring_begin_use(struct amdgpu_ring *ring); void amdgpu_vce_ring_end_use(struct amdgpu_ring *ring); unsigned amdgpu_vce_ring_get_emit_ib_size(struct amdgpu_ring *ring); unsigned amdgpu_vce_ring_get_dma_frame_size(struct amdgpu_ring *ring); +enum amdgpu_ring_priority_level amdgpu_vce_get_ring_prio(int ring); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index b70c17f0c52e8..84e488f189f5f 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -431,10 +431,12 @@ static int vce_v2_0_sw_init(void *handle) return r; for (i = 0; i < adev->vce.num_rings; i++) { + enum amdgpu_ring_priority_level hw_prio = amdgpu_vce_get_ring_prio(i); + ring = &adev->vce.ring[i]; sprintf(ring->name, "vce%d", i); r = amdgpu_ring_init(adev, ring, 512, &adev->vce.irq, 0, - AMDGPU_RING_PRIO_DEFAULT, NULL); + hw_prio, NULL); if (r) return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 9de66893ccd6d..2a18c1e089fdd 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -440,10 +440,12 @@ static int vce_v3_0_sw_init(void *handle) return r; for (i = 0; i < adev->vce.num_rings; i++) { + enum amdgpu_ring_priority_level hw_prio = amdgpu_vce_get_ring_prio(i); + ring = &adev->vce.ring[i]; sprintf(ring->name, "vce%d", i); r = amdgpu_ring_init(adev, ring, 512, &adev->vce.irq, 0, - AMDGPU_RING_PRIO_DEFAULT, NULL); + hw_prio, NULL); if (r) return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c index fec902b800c28..044cf9d74b85e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c @@ -463,6 +463,8 @@ static int vce_v4_0_sw_init(void *handle) } for (i = 0; i < adev->vce.num_rings; i++) { + enum amdgpu_ring_priority_level hw_prio = amdgpu_vce_get_ring_prio(i); + ring = &adev->vce.ring[i]; sprintf(ring->name, "vce%d", i); if (amdgpu_sriov_vf(adev)) { @@ -478,7 +480,7 @@ static int vce_v4_0_sw_init(void *handle) ring->doorbell_index = adev->doorbell_index.uvd_vce.vce_ring2_3 * 2 + 1; } r = amdgpu_ring_init(adev, ring, 512, &adev->vce.irq, 0, - AMDGPU_RING_PRIO_DEFAULT, NULL); + hw_prio, NULL); if (r) return r; } From 0ad29a4eb13577ff5c7e5d545d4a49c79052ffb0 Mon Sep 17 00:00:00 2001 From: Satyajit Sahu Date: Fri, 27 Aug 2021 11:58:45 +0530 Subject: [PATCH 024/151] drm/amdgpu/vcn: set the priority for each encode ring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VCN has multiple rings. Set the proper priority level for each encode ring while initializing. Signed-off-by: Satyajit Sahu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 14 ++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 2 ++ drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 4 +++- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 4 +++- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 4 +++- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 5 +++-- 6 files changed, 28 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 008a308a4ecaf..561296a85b436 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -949,3 +949,17 @@ int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) return r; } + +enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring) +{ + switch(ring) { + case 0: + return AMDGPU_RING_PRIO_0; + case 1: + return AMDGPU_RING_PRIO_1; + case 2: + return AMDGPU_RING_PRIO_2; + default: + return AMDGPU_RING_PRIO_0; + } +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index d74c62b497954..795cbaa02ff86 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -308,4 +308,6 @@ int amdgpu_vcn_dec_sw_ring_test_ib(struct amdgpu_ring *ring, long timeout); int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring); int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout); +enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index 121ee9f2b8d16..6c11739270c1f 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -145,10 +145,12 @@ static int vcn_v1_0_sw_init(void *handle) SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP); for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i); + ring = &adev->vcn.inst->ring_enc[i]; sprintf(ring->name, "vcn_enc%d", i); r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst->irq, 0, - AMDGPU_RING_PRIO_DEFAULT, NULL); + hw_prio, NULL); if (r) return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index f4686e918e0d1..e6e9ef50719e5 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -159,6 +159,8 @@ static int vcn_v2_0_sw_init(void *handle) adev->vcn.inst->external.nop = SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP); for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i); + ring = &adev->vcn.inst->ring_enc[i]; ring->use_doorbell = true; if (!amdgpu_sriov_vf(adev)) @@ -167,7 +169,7 @@ static int vcn_v2_0_sw_init(void *handle) ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 1 + i; sprintf(ring->name, "vcn_enc%d", i); r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst->irq, 0, - AMDGPU_RING_PRIO_DEFAULT, NULL); + hw_prio, NULL); if (r) return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index e0c0c3734432e..2e6b7913bf6c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -194,6 +194,8 @@ static int vcn_v2_5_sw_init(void *handle) return r; for (i = 0; i < adev->vcn.num_enc_rings; ++i) { + enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(i); + ring = &adev->vcn.inst[j].ring_enc[i]; ring->use_doorbell = true; @@ -203,7 +205,7 @@ static int vcn_v2_5_sw_init(void *handle) sprintf(ring->name, "vcn_enc_%d.%d", j, i); r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[j].irq, 0, - AMDGPU_RING_PRIO_DEFAULT, NULL); + hw_prio, NULL); if (r) return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 3d18aab88b4e2..b1af70d49c6e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -224,6 +224,8 @@ static int vcn_v3_0_sw_init(void *handle) return r; for (j = 0; j < adev->vcn.num_enc_rings; ++j) { + enum amdgpu_ring_priority_level hw_prio = amdgpu_vcn_get_enc_ring_prio(j); + /* VCN ENC TRAP */ r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i], j + VCN_2_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst[i].irq); @@ -239,8 +241,7 @@ static int vcn_v3_0_sw_init(void *handle) } sprintf(ring->name, "vcn_enc_%d.%d", i, j); r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0, - AMDGPU_RING_PRIO_DEFAULT, - &adev->vcn.inst[i].sched_score); + hw_prio, &adev->vcn.inst[i].sched_score); if (r) return r; } From 7d7630fc6b8850ceae5a708bd37dcc7583658316 Mon Sep 17 00:00:00 2001 From: Satyajit Sahu Date: Thu, 26 Aug 2021 12:20:14 +0530 Subject: [PATCH 025/151] drm/amdgpu:schedule vce/vcn encode based on priority MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Schedule the encode job in VCE/VCN encode ring based on the priority set by UMD. Signed-off-by: Satyajit Sahu Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 0d19282606507..468003583b2a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -120,6 +120,18 @@ static enum amdgpu_gfx_pipe_priority amdgpu_ctx_prio_to_compute_prio(int32_t pri } } +static enum amdgpu_ring_priority_level amdgpu_ctx_sched_prio_to_ring_prio(int32_t prio) +{ + switch (prio) { + case AMDGPU_CTX_PRIORITY_HIGH: + return AMDGPU_RING_PRIO_1; + case AMDGPU_CTX_PRIORITY_VERY_HIGH: + return AMDGPU_RING_PRIO_2; + default: + return AMDGPU_RING_PRIO_0; + } +} + static unsigned int amdgpu_ctx_get_hw_prio(struct amdgpu_ctx *ctx, u32 hw_ip) { struct amdgpu_device *adev = ctx->adev; @@ -133,6 +145,10 @@ static unsigned int amdgpu_ctx_get_hw_prio(struct amdgpu_ctx *ctx, u32 hw_ip) case AMDGPU_HW_IP_COMPUTE: hw_prio = amdgpu_ctx_prio_to_compute_prio(ctx_prio); break; + case AMDGPU_HW_IP_VCE: + case AMDGPU_HW_IP_VCN_ENC: + hw_prio = amdgpu_ctx_sched_prio_to_ring_prio(ctx_prio); + break; default: hw_prio = AMDGPU_RING_PRIO_DEFAULT; break; From fd30b7d9e48ddb319deee6bd83aa9c3328846c09 Mon Sep 17 00:00:00 2001 From: Yifan Zha Date: Mon, 30 Aug 2021 14:07:29 +0800 Subject: [PATCH 026/151] drm/amd/pm: Update navi12 smu message mapping table in sriov [Why] Sending invalid SMU message in sriov cause set dpm level fail. [How] Update message table based on SMU firmware. Signed-off-by: Yifan Zha Review-by: Horace Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index a5fc5d7cb6c79..4c81989b81626 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -86,21 +86,21 @@ static struct cmn2asic_msg_mapping navi10_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 0), MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 1), MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 1), - MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 1), + MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 0), MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0), - MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 0), - MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 0), + MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1), + MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1), MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0), MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0), - MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), + MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1), MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0), MSG_MAP(UseBackupPPTable, PPSMC_MSG_UseBackupPPTable, 0), MSG_MAP(RunBtc, PPSMC_MSG_RunBtc, 0), MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0), - MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 0), - MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 0), - MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 1), + MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 1), + MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 1), + MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 0), MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0), MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1), MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1), From 9ad544670514e2a79aad7567295c198609d999ee Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 29 Aug 2021 17:46:24 +0100 Subject: [PATCH 027/151] drm/amd/display: Fix unused initialization of pointer sink Pointer sink is being inintialized with a value that is never read, it is later being re-assigned a new value. Remove the redundant initialization. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 7f311bba97355..8837259215d9a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -10917,7 +10917,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); struct dm_connector_state *dm_con_state = NULL; - struct dc_sink *sink = amdgpu_dm_connector->dc_sink; + struct dc_sink *sink; struct drm_device *dev = connector->dev; struct amdgpu_device *adev = drm_to_adev(dev); From cd54323e762ddda11552ee5258d35a3a7cc5cc0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ernst=20Sj=C3=B6strand?= Date: Thu, 2 Sep 2021 09:50:27 +0200 Subject: [PATCH 028/151] drm/amd/amdgpu: Increase HWIP_MAX_INSTANCE to 10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seems like newer cards can have even more instances now. Found by UBSAN: array-index-out-of-bounds in drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c:318:29 index 8 is out of range for type 'uint32_t *[8]' Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1697 Cc: stable@vger.kernel.org Signed-off-by: Ernst Sjöstrand Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index dc3c6b3a00e53..d356e329e6f89 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -758,7 +758,7 @@ enum amd_hw_ip_block_type { MAX_HWIP }; -#define HWIP_MAX_INSTANCE 8 +#define HWIP_MAX_INSTANCE 10 struct amd_powerplay { void *pp_handle; From 68e7d0baa1f2bd6eab56d3f701c3779b261f57d8 Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Mon, 6 Sep 2021 07:55:01 +0800 Subject: [PATCH 029/151] drm/amd/pm: fix the issue of uploading powerplay table fix the issue of uploading powerplay table due to the dependancy of rlc. Signed-off-by: Kenneth Feng Reviewed-by: Jack Gui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 3ab1ce4d3419b..04863a7971155 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1404,7 +1404,7 @@ static int smu_disable_dpms(struct smu_context *smu) */ if (smu->uploading_custom_pp_table && (adev->asic_type >= CHIP_NAVI10) && - (adev->asic_type <= CHIP_DIMGREY_CAVEFISH)) + (adev->asic_type <= CHIP_BEIGE_GOBY)) return smu_disable_all_features_with_exception(smu, true, SMU_FEATURE_COUNT); From ac1509d19e2e44d1ea13753cfc265c4693f12ef5 Mon Sep 17 00:00:00 2001 From: Candice Li Date: Sat, 4 Sep 2021 16:45:03 +0800 Subject: [PATCH 030/151] drm/amdgpu: Create common PSP TA load function Creat common PSP TA load function and update PSP ta_mem_context with size information. Signed-off-by: Candice Li Reviewed-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 280 +++++++----------------- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 17 +- 2 files changed, 93 insertions(+), 204 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 54c26432c65b3..75eed18370eb1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -901,22 +901,20 @@ int psp_reg_program(struct psp_context *psp, enum psp_reg_prog_id reg, static void psp_prep_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, uint64_t ta_bin_mc, uint32_t ta_bin_size, - uint64_t ta_shared_mc, - uint32_t ta_shared_size) + struct ta_mem_context *mem_ctx) { cmd->cmd_id = GFX_CMD_ID_LOAD_TA; cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(ta_bin_mc); cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(ta_bin_mc); cmd->cmd.cmd_load_ta.app_len = ta_bin_size; - cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = lower_32_bits(ta_shared_mc); - cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = upper_32_bits(ta_shared_mc); - cmd->cmd.cmd_load_ta.cmd_buf_len = ta_shared_size; + cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = lower_32_bits(mem_ctx->shared_mc_addr); + cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = upper_32_bits(mem_ctx->shared_mc_addr); + cmd->cmd.cmd_load_ta.cmd_buf_len = mem_ctx->shared_mem_size; } static int psp_ta_init_shared_buf(struct psp_context *psp, - struct ta_mem_context *mem_ctx, - uint32_t shared_mem_size) + struct ta_mem_context *mem_ctx) { int ret; @@ -924,8 +922,8 @@ static int psp_ta_init_shared_buf(struct psp_context *psp, * Allocate 16k memory aligned to 4k from Frame Buffer (local * physical) for ta to host memory */ - ret = amdgpu_bo_create_kernel(psp->adev, shared_mem_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, + ret = amdgpu_bo_create_kernel(psp->adev, mem_ctx->shared_mem_size, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, &mem_ctx->shared_bo, &mem_ctx->shared_mc_addr, &mem_ctx->shared_buf); @@ -941,8 +939,7 @@ static void psp_ta_free_shared_buf(struct ta_mem_context *mem_ctx) static int psp_xgmi_init_shared_buf(struct psp_context *psp) { - return psp_ta_init_shared_buf(psp, &psp->xgmi_context.context.mem_context, - PSP_XGMI_SHARED_MEM_SIZE); + return psp_ta_init_shared_buf(psp, &psp->xgmi_context.context.mem_context); } static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd, @@ -971,31 +968,27 @@ static int psp_ta_invoke(struct psp_context *psp, return ret; } -static int psp_xgmi_load(struct psp_context *psp) +static int psp_ta_load(struct psp_context *psp, + struct psp_bin_desc *bin_desc, + struct ta_context *context) { int ret; struct psp_gfx_cmd_resp *cmd; - /* - * TODO: bypass the loading in sriov for now - */ - cmd = acquire_psp_cmd_buf(psp); - psp_copy_fw(psp, psp->xgmi.start_addr, psp->xgmi.size_bytes); + psp_copy_fw(psp, bin_desc->start_addr, bin_desc->size_bytes); psp_prep_ta_load_cmd_buf(cmd, psp->fw_pri_mc_addr, - psp->xgmi.size_bytes, - psp->xgmi_context.context.mem_context.shared_mc_addr, - PSP_XGMI_SHARED_MEM_SIZE); + bin_desc->size_bytes, + &context->mem_context); ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); if (!ret) { - psp->xgmi_context.context.initialized = true; - psp->xgmi_context.context.session_id = cmd->resp.session_id; + context->session_id = cmd->resp.session_id; } release_psp_cmd_buf(psp); @@ -1003,6 +996,11 @@ static int psp_xgmi_load(struct psp_context *psp) return ret; } +static int psp_xgmi_load(struct psp_context *psp) +{ + return psp_ta_load(psp, &psp->xgmi, &psp->xgmi_context.context); +} + static int psp_xgmi_unload(struct psp_context *psp) { return psp_ta_unload(psp, psp->xgmi_context.context.session_id); @@ -1051,6 +1049,8 @@ int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool lo if (!load_ta) goto invoke; + psp->xgmi_context.context.mem_context.shared_mem_size = PSP_XGMI_SHARED_MEM_SIZE; + if (!psp->xgmi_context.context.initialized) { ret = psp_xgmi_init_shared_buf(psp); if (ret) @@ -1059,7 +1059,9 @@ int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool lo /* Load XGMI TA */ ret = psp_xgmi_load(psp); - if (ret) + if (!ret) + psp->xgmi_context.context.initialized = true; + else return ret; invoke: @@ -1281,57 +1283,12 @@ int psp_xgmi_set_topology_info(struct psp_context *psp, // ras begin static int psp_ras_init_shared_buf(struct psp_context *psp) { - return psp_ta_init_shared_buf(psp, &psp->ras_context.context.mem_context, - PSP_RAS_SHARED_MEM_SIZE); + return psp_ta_init_shared_buf(psp, &psp->ras_context.context.mem_context); } static int psp_ras_load(struct psp_context *psp) { - int ret; - struct psp_gfx_cmd_resp *cmd; - struct ta_ras_shared_memory *ras_cmd; - - /* - * TODO: bypass the loading in sriov for now - */ - if (amdgpu_sriov_vf(psp->adev)) - return 0; - - psp_copy_fw(psp, psp->ras.start_addr, psp->ras.size_bytes); - - ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf; - - if (psp->adev->gmc.xgmi.connected_to_cpu) - ras_cmd->ras_in_message.init_flags.poison_mode_en = 1; - else - ras_cmd->ras_in_message.init_flags.dgpu_mode = 1; - - cmd = acquire_psp_cmd_buf(psp); - - psp_prep_ta_load_cmd_buf(cmd, - psp->fw_pri_mc_addr, - psp->ras.size_bytes, - psp->ras_context.context.mem_context.shared_mc_addr, - PSP_RAS_SHARED_MEM_SIZE); - - ret = psp_cmd_submit_buf(psp, NULL, cmd, - psp->fence_buf_mc_addr); - - if (!ret) { - psp->ras_context.context.session_id = cmd->resp.session_id; - - if (!ras_cmd->ras_status) - psp->ras_context.context.initialized = true; - else - dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status); - } - - release_psp_cmd_buf(psp); - - if (ret || ras_cmd->ras_status) - amdgpu_ras_fini(psp->adev); - - return ret; + return psp_ta_load(psp, &psp->ras, &psp->ras_context.context); } static int psp_ras_unload(struct psp_context *psp) @@ -1458,6 +1415,7 @@ static int psp_ras_initialize(struct psp_context *psp) int ret; uint32_t boot_cfg = 0xFF; struct amdgpu_device *adev = psp->adev; + struct ta_ras_shared_memory *ras_cmd; /* * TODO: bypass the initialize in sriov for now @@ -1512,17 +1470,33 @@ static int psp_ras_initialize(struct psp_context *psp) } } + psp->ras_context.context.mem_context.shared_mem_size = PSP_RAS_SHARED_MEM_SIZE; + if (!psp->ras_context.context.initialized) { ret = psp_ras_init_shared_buf(psp); if (ret) return ret; } + ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf; + memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory)); + + if (psp->adev->gmc.xgmi.connected_to_cpu) + ras_cmd->ras_in_message.init_flags.poison_mode_en = 1; + else + ras_cmd->ras_in_message.init_flags.dgpu_mode = 1; + ret = psp_ras_load(psp); - if (ret) - return ret; - return 0; + if (!ret && !ras_cmd->ras_status) + psp->ras_context.context.initialized = true; + else { + if (ras_cmd->ras_status) + dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status); + amdgpu_ras_fini(psp->adev); + } + + return ret; } int psp_ras_trigger_error(struct psp_context *psp, @@ -1556,43 +1530,12 @@ int psp_ras_trigger_error(struct psp_context *psp, // HDCP start static int psp_hdcp_init_shared_buf(struct psp_context *psp) { - return psp_ta_init_shared_buf(psp, &psp->hdcp_context.context.mem_context, - PSP_HDCP_SHARED_MEM_SIZE); + return psp_ta_init_shared_buf(psp, &psp->hdcp_context.context.mem_context); } static int psp_hdcp_load(struct psp_context *psp) { - int ret; - struct psp_gfx_cmd_resp *cmd; - - /* - * TODO: bypass the loading in sriov for now - */ - if (amdgpu_sriov_vf(psp->adev)) - return 0; - - psp_copy_fw(psp, psp->hdcp.start_addr, - psp->hdcp.size_bytes); - - cmd = acquire_psp_cmd_buf(psp); - - psp_prep_ta_load_cmd_buf(cmd, - psp->fw_pri_mc_addr, - psp->hdcp.size_bytes, - psp->hdcp_context.context.mem_context.shared_mc_addr, - PSP_HDCP_SHARED_MEM_SIZE); - - ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); - - if (!ret) { - psp->hdcp_context.context.initialized = true; - psp->hdcp_context.context.session_id = cmd->resp.session_id; - mutex_init(&psp->hdcp_context.mutex); - } - - release_psp_cmd_buf(psp); - - return ret; + return psp_ta_load(psp, &psp->hdcp, &psp->hdcp_context.context); } static int psp_hdcp_initialize(struct psp_context *psp) { @@ -1610,6 +1553,8 @@ static int psp_hdcp_initialize(struct psp_context *psp) return 0; } + psp->hdcp_context.context.mem_context.shared_mem_size = PSP_HDCP_SHARED_MEM_SIZE; + if (!psp->hdcp_context.context.initialized) { ret = psp_hdcp_init_shared_buf(psp); if (ret) @@ -1617,10 +1562,12 @@ static int psp_hdcp_initialize(struct psp_context *psp) } ret = psp_hdcp_load(psp); - if (ret) - return ret; + if (!ret) { + psp->hdcp_context.context.initialized = true; + mutex_init(&psp->hdcp_context.mutex); + } - return 0; + return ret; } static int psp_hdcp_unload(struct psp_context *psp) @@ -1673,42 +1620,12 @@ static int psp_hdcp_terminate(struct psp_context *psp) // DTM start static int psp_dtm_init_shared_buf(struct psp_context *psp) { - return psp_ta_init_shared_buf(psp, &psp->dtm_context.context.mem_context, - PSP_DTM_SHARED_MEM_SIZE); + return psp_ta_init_shared_buf(psp, &psp->dtm_context.context.mem_context); } static int psp_dtm_load(struct psp_context *psp) { - int ret; - struct psp_gfx_cmd_resp *cmd; - - /* - * TODO: bypass the loading in sriov for now - */ - if (amdgpu_sriov_vf(psp->adev)) - return 0; - - psp_copy_fw(psp, psp->dtm.start_addr, psp->dtm.size_bytes); - - cmd = acquire_psp_cmd_buf(psp); - - psp_prep_ta_load_cmd_buf(cmd, - psp->fw_pri_mc_addr, - psp->dtm.size_bytes, - psp->dtm_context.context.mem_context.shared_mc_addr, - PSP_DTM_SHARED_MEM_SIZE); - - ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); - - if (!ret) { - psp->dtm_context.context.initialized = true; - psp->dtm_context.context.session_id = cmd->resp.session_id; - mutex_init(&psp->dtm_context.mutex); - } - - release_psp_cmd_buf(psp); - - return ret; + return psp_ta_load(psp, &psp->dtm, &psp->dtm_context.context); } static int psp_dtm_initialize(struct psp_context *psp) @@ -1727,6 +1644,8 @@ static int psp_dtm_initialize(struct psp_context *psp) return 0; } + psp->dtm_context.context.mem_context.shared_mem_size = PSP_DTM_SHARED_MEM_SIZE; + if (!psp->dtm_context.context.initialized) { ret = psp_dtm_init_shared_buf(psp); if (ret) @@ -1734,10 +1653,12 @@ static int psp_dtm_initialize(struct psp_context *psp) } ret = psp_dtm_load(psp); - if (ret) - return ret; + if (!ret) { + psp->dtm_context.context.initialized = true; + mutex_init(&psp->dtm_context.mutex); + } - return 0; + return ret; } static int psp_dtm_unload(struct psp_context *psp) @@ -1790,36 +1711,12 @@ static int psp_dtm_terminate(struct psp_context *psp) // RAP start static int psp_rap_init_shared_buf(struct psp_context *psp) { - return psp_ta_init_shared_buf(psp, &psp->rap_context.context.mem_context, - PSP_RAP_SHARED_MEM_SIZE); + return psp_ta_init_shared_buf(psp, &psp->rap_context.context.mem_context); } static int psp_rap_load(struct psp_context *psp) { - int ret; - struct psp_gfx_cmd_resp *cmd; - - psp_copy_fw(psp, psp->rap.start_addr, psp->rap.size_bytes); - - cmd = acquire_psp_cmd_buf(psp); - - psp_prep_ta_load_cmd_buf(cmd, - psp->fw_pri_mc_addr, - psp->rap.size_bytes, - psp->rap_context.context.mem_context.shared_mc_addr, - PSP_RAP_SHARED_MEM_SIZE); - - ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); - - if (!ret) { - psp->rap_context.context.initialized = true; - psp->rap_context.context.session_id = cmd->resp.session_id; - mutex_init(&psp->rap_context.mutex); - } - - release_psp_cmd_buf(psp); - - return ret; + return psp_ta_load(psp, &psp->rap, &psp->rap_context.context); } static int psp_rap_unload(struct psp_context *psp) @@ -1844,6 +1741,8 @@ static int psp_rap_initialize(struct psp_context *psp) return 0; } + psp->rap_context.context.mem_context.shared_mem_size = PSP_RAP_SHARED_MEM_SIZE; + if (!psp->rap_context.context.initialized) { ret = psp_rap_init_shared_buf(psp); if (ret) @@ -1851,7 +1750,10 @@ static int psp_rap_initialize(struct psp_context *psp) } ret = psp_rap_load(psp); - if (ret) + if (!ret) { + psp->rap_context.context.initialized = true; + mutex_init(&psp->rap_context.mutex); + } else return ret; ret = psp_rap_invoke(psp, TA_CMD_RAP__INITIALIZE, &status); @@ -1923,35 +1825,13 @@ int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id, enum ta_rap_stat static int psp_securedisplay_init_shared_buf(struct psp_context *psp) { return psp_ta_init_shared_buf( - psp, &psp->securedisplay_context.context.mem_context, - PSP_SECUREDISPLAY_SHARED_MEM_SIZE); + psp, &psp->securedisplay_context.context.mem_context); } static int psp_securedisplay_load(struct psp_context *psp) { - int ret; - struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); - - memset(psp->fw_pri_buf, 0, PSP_1_MEG); - memcpy(psp->fw_pri_buf, psp->securedisplay.start_addr, psp->securedisplay.size_bytes); - - psp_prep_ta_load_cmd_buf(cmd, - psp->fw_pri_mc_addr, - psp->securedisplay.size_bytes, - psp->securedisplay_context.context.mem_context.shared_mc_addr, - PSP_SECUREDISPLAY_SHARED_MEM_SIZE); - - ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); - - if (!ret) { - psp->securedisplay_context.context.initialized = true; - psp->securedisplay_context.context.session_id = cmd->resp.session_id; - mutex_init(&psp->securedisplay_context.mutex); - } - - release_psp_cmd_buf(psp); - - return ret; + return psp_ta_load(psp, &psp->securedisplay, + &psp->securedisplay_context.context); } static int psp_securedisplay_unload(struct psp_context *psp) @@ -1976,6 +1856,9 @@ static int psp_securedisplay_initialize(struct psp_context *psp) return 0; } + psp->securedisplay_context.context.mem_context.shared_mem_size = + PSP_SECUREDISPLAY_SHARED_MEM_SIZE; + if (!psp->securedisplay_context.context.initialized) { ret = psp_securedisplay_init_shared_buf(psp); if (ret) @@ -1983,7 +1866,10 @@ static int psp_securedisplay_initialize(struct psp_context *psp) } ret = psp_securedisplay_load(psp); - if (ret) + if (!ret) { + psp->securedisplay_context.context.initialized = true; + mutex_init(&psp->securedisplay_context.mutex); + } else return ret; psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index 8ef2d28af92ae..cc09b9e911199 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -34,17 +34,19 @@ #define PSP_FENCE_BUFFER_SIZE 0x1000 #define PSP_CMD_BUFFER_SIZE 0x1000 -#define PSP_XGMI_SHARED_MEM_SIZE 0x4000 -#define PSP_RAS_SHARED_MEM_SIZE 0x4000 #define PSP_1_MEG 0x100000 #define PSP_TMR_SIZE(adev) ((adev)->asic_type == CHIP_ALDEBARAN ? 0x800000 : 0x400000) -#define PSP_HDCP_SHARED_MEM_SIZE 0x4000 -#define PSP_DTM_SHARED_MEM_SIZE 0x4000 -#define PSP_RAP_SHARED_MEM_SIZE 0x4000 -#define PSP_SECUREDISPLAY_SHARED_MEM_SIZE 0x4000 -#define PSP_SHARED_MEM_SIZE 0x4000 #define PSP_FW_NAME_LEN 0x24 +enum psp_shared_mem_size { + PSP_XGMI_SHARED_MEM_SIZE = 0x4000, + PSP_RAS_SHARED_MEM_SIZE = 0x4000, + PSP_HDCP_SHARED_MEM_SIZE = 0x4000, + PSP_DTM_SHARED_MEM_SIZE = 0x4000, + PSP_RAP_SHARED_MEM_SIZE = 0x4000, + PSP_SECUREDISPLAY_SHARED_MEM_SIZE = 0x4000, +}; + struct psp_context; struct psp_xgmi_node_info; struct psp_xgmi_topology_info; @@ -140,6 +142,7 @@ struct ta_mem_context { struct amdgpu_bo *shared_bo; uint64_t shared_mc_addr; void *shared_buf; + enum psp_shared_mem_size shared_mem_size; }; struct ta_context { From 101ba90ff0339f02591ea141ea5cf09f4377d31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 7 Sep 2021 09:37:52 +0200 Subject: [PATCH 031/151] drm/amdgpu: fix use after free during BO move MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The memory backing old_mem is already freed at that point, move the check a bit more up. Signed-off-by: Christian König Fixes: bfa3357ef9ab ("drm/ttm: allocate resource object instead of embedding it v2") Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1699 Acked-by: Nirmoy Das Reviewed-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 38dade421d465..94126dc396888 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -515,6 +515,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, goto out; } + if (bo->type == ttm_bo_type_device && + new_mem->mem_type == TTM_PL_VRAM && + old_mem->mem_type != TTM_PL_VRAM) { + /* amdgpu_bo_fault_reserve_notify will re-set this if the CPU + * accesses the BO after it's moved. + */ + abo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; + } + if (adev->mman.buffer_funcs_enabled) { if (((old_mem->mem_type == TTM_PL_SYSTEM && new_mem->mem_type == TTM_PL_VRAM) || @@ -545,15 +554,6 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, return r; } - if (bo->type == ttm_bo_type_device && - new_mem->mem_type == TTM_PL_VRAM && - old_mem->mem_type != TTM_PL_VRAM) { - /* amdgpu_bo_fault_reserve_notify will re-set this if the CPU - * accesses the BO after it's moved. - */ - abo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; - } - out: /* update statistics */ atomic64_add(bo->base.size, &adev->num_bytes_moved); From a7181b52eabcd2663b78394ac88e80e8dff488b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 7 Sep 2021 10:13:21 +0200 Subject: [PATCH 032/151] drm/amdgpu: remove unused amdgpu_bo_validate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just drop some dead code. Signed-off-by: Christian König Reviewed-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 34 ---------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 1 - 2 files changed, 35 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 01a78c7865367..32f36992291e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -694,40 +694,6 @@ int amdgpu_bo_create_vm(struct amdgpu_device *adev, return r; } -/** - * amdgpu_bo_validate - validate an &amdgpu_bo buffer object - * @bo: pointer to the buffer object - * - * Sets placement according to domain; and changes placement and caching - * policy of the buffer object according to the placement. - * This is used for validating shadow bos. It calls ttm_bo_validate() to - * make sure the buffer is resident where it needs to be. - * - * Returns: - * 0 for success or a negative error code on failure. - */ -int amdgpu_bo_validate(struct amdgpu_bo *bo) -{ - struct ttm_operation_ctx ctx = { false, false }; - uint32_t domain; - int r; - - if (bo->tbo.pin_count) - return 0; - - domain = bo->preferred_domains; - -retry: - amdgpu_bo_placement_from_domain(bo, domain); - r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); - if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) { - domain = bo->allowed_domains; - goto retry; - } - - return r; -} - /** * amdgpu_bo_add_to_shadow_list - add a BO to the shadow list * diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 9d6c001c15f89..d2cbabaf2a46d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -327,7 +327,6 @@ int amdgpu_bo_sync_wait_resv(struct amdgpu_device *adev, struct dma_resv *resv, int amdgpu_bo_sync_wait(struct amdgpu_bo *bo, void *owner, bool intr); u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo); u64 amdgpu_bo_gpu_offset_no_check(struct amdgpu_bo *bo); -int amdgpu_bo_validate(struct amdgpu_bo *bo); void amdgpu_bo_get_memory(struct amdgpu_bo *bo, uint64_t *vram_mem, uint64_t *gtt_mem, uint64_t *cpu_mem); void amdgpu_bo_add_to_shadow_list(struct amdgpu_bo_vm *vmbo); From 9ae807f0ec6ac4873289b5c03af40aeaba836ea1 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 2 Sep 2021 22:45:10 +0100 Subject: [PATCH 033/151] drm/amdgpu: clean up inconsistent indenting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are a couple of statements that are indented one character too deeply, clean these up. Reviewed-by: Christian König Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index d6aa032890ee8..a573424a6e0b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -60,10 +60,9 @@ static vm_fault_t amdgpu_gem_fault(struct vm_fault *vmf) goto unlock; } - ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, - TTM_BO_VM_NUM_PREFAULT, 1); - - drm_dev_exit(idx); + ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, + TTM_BO_VM_NUM_PREFAULT, 1); + drm_dev_exit(idx); } else { ret = ttm_bo_vm_dummy_page(vmf, vmf->vma->vm_page_prot); } From e8ba4922a2ed616125182f072eec2ec991da0341 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 2 Sep 2021 22:51:27 +0100 Subject: [PATCH 034/151] drm/amdgpu: sdma: clean up identation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a statement that is indented incorrectly. Clean it up. Reviewed-by: Christian König Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c index 779f5c911e112..e4a96e7e386d0 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c @@ -375,10 +375,10 @@ static void sdma_v5_2_ring_emit_ib(struct amdgpu_ring *ring, */ static void sdma_v5_2_ring_emit_mem_sync(struct amdgpu_ring *ring) { - uint32_t gcr_cntl = - SDMA_GCR_GL2_INV | SDMA_GCR_GL2_WB | SDMA_GCR_GLM_INV | - SDMA_GCR_GL1_INV | SDMA_GCR_GLV_INV | SDMA_GCR_GLK_INV | - SDMA_GCR_GLI_INV(1); + uint32_t gcr_cntl = SDMA_GCR_GL2_INV | SDMA_GCR_GL2_WB | + SDMA_GCR_GLM_INV | SDMA_GCR_GL1_INV | + SDMA_GCR_GLV_INV | SDMA_GCR_GLK_INV | + SDMA_GCR_GLI_INV(1); /* flush entire cache L0/L1/L2, this can be optimized by performance requirement */ amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_GCR_REQ)); From 67684fcbdd0ef60a52f15e74e0e8a85edc867ce4 Mon Sep 17 00:00:00 2001 From: Len Baker Date: Sat, 4 Sep 2021 17:41:06 +0200 Subject: [PATCH 035/151] drm/radeon: Prefer kcalloc over open coded arithmetic As noted in the "Deprecated Interfaces, Language Features, Attributes, and Conventions" documentation [1], size calculations (especially multiplication) should not be performed in memory allocator (or similar) function arguments due to the risk of them overflowing. This could lead to values wrapping around and a smaller allocation being made than the caller was expecting. Using those allocations could lead to linear overflows of heap memory and other misbehaviors. So, refactor the code a bit to use the purpose specific kcalloc() function instead of the calculated size argument in the kzalloc() function. [1] https://www.kernel.org/doc/html/v5.14/process/deprecated.html#open-coded-arithmetic-in-allocator-arguments Signed-off-by: Len Baker Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index 35b77c9447010..fd4226b99862b 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -820,12 +820,12 @@ union fan_info { static int r600_parse_clk_voltage_dep_table(struct radeon_clock_voltage_dependency_table *radeon_table, ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table) { - u32 size = atom_table->ucNumEntries * - sizeof(struct radeon_clock_voltage_dependency_entry); int i; ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry; - radeon_table->entries = kzalloc(size, GFP_KERNEL); + radeon_table->entries = kcalloc(atom_table->ucNumEntries, + sizeof(struct radeon_clock_voltage_dependency_entry), + GFP_KERNEL); if (!radeon_table->entries) return -ENOMEM; From a906331c452b41f94f2dedd6eaf415feed08a731 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 7 Sep 2021 14:19:34 +0000 Subject: [PATCH 036/151] amd/display: downgrade validation failure log level In amdgpu_dm_atomic_check, dc_validate_global_state is called. On failure this logs a warning to the kernel journal. However warnings shouldn't be used for atomic test-only commit failures: user-space might be perfoming a lot of atomic test-only commits to find the best hardware configuration. Downgrade the log to a regular DRM atomic message. While at it, use the new device-aware logging infrastructure. This fixes error messages in the kernel when running gamescope [1]. [1]: https://github.com/Plagman/gamescope/issues/245 Reviewed-by: Nicholas Kazlauskas Signed-off-by: Simon Ser Cc: Alex Deucher Cc: Harry Wentland Cc: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8837259215d9a..53363728dbbdc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -10653,7 +10653,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; status = dc_validate_global_state(dc, dm_state->context, false); if (status != DC_OK) { - DC_LOG_WARNING("DC global validation failure: %s (%d)", + drm_dbg_atomic(dev, + "DC global validation failure: %s (%d)", dc_status_to_str(status), status); ret = -EINVAL; goto fail; From f7ea304f198871559a3784772c12a111dfbaacc8 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 7 Sep 2021 12:09:13 +0100 Subject: [PATCH 037/151] drm/radeon/ci_dpm: Remove redundant initialization of variables hi_sidd, lo_sidd The variables hi_sidd and lo_sidd are being initialized with a values that are never read, they are being updated later on. The assignments are redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index f0cfb58da4672..ac006bed4743b 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -390,8 +390,7 @@ static int ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(struct radeon_device *rdev) static int ci_populate_bapm_vddc_base_leakage_sidd(struct radeon_device *rdev) { struct ci_power_info *pi = ci_get_pi(rdev); - u16 hi_sidd = pi->smc_powertune_table.BapmVddCBaseLeakageHiSidd; - u16 lo_sidd = pi->smc_powertune_table.BapmVddCBaseLeakageLoSidd; + u16 hi_sidd, lo_sidd; struct radeon_cac_tdp_table *cac_tdp_table = rdev->pm.dpm.dyn_state.cac_tdp_table; From 1c48fbf691391512f01300ae296744b4962f9598 Mon Sep 17 00:00:00 2001 From: chongjiapeng Date: Mon, 6 Sep 2021 17:23:28 +0800 Subject: [PATCH 038/151] drm/amd/display: Fix warning comparing pointer to 0 Fix the following coccicheck warning: ./drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c:643:35-36: WARNING comparing pointer to 0. Reported-by: Abaci Robot Signed-off-by: chongjiapeng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 4a4894e9d9c9a..15491e3ca11a6 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -640,7 +640,7 @@ void dcn31_clk_mgr_construct( sizeof(struct dcn31_watermarks), &clk_mgr->smu_wm_set.mc_address.quad_part); - if (clk_mgr->smu_wm_set.wm_set == 0) { + if (!clk_mgr->smu_wm_set.wm_set) { clk_mgr->smu_wm_set.wm_set = &dummy_wms; clk_mgr->smu_wm_set.mc_address.quad_part = 0; } From bbb36348004595799a5c6df0d9e4e6f65772c2ab Mon Sep 17 00:00:00 2001 From: chongjiapeng Date: Mon, 6 Sep 2021 17:42:27 +0800 Subject: [PATCH 039/151] drm/amd/display: make configure_lttpr_mode_transparent and configure_lttpr_mode_non_transparent static This symbols is not used outside of dc_link_dp.c, so marks it static. Fix the following sparse warning: drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_link_dp.c:1766:16: warning: symbol 'configure_lttpr_mode_non_transparent' was not declared. Should it be static? drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_link_dp.c:1755:16: warning: symbol 'configure_lttpr_mode_transparent' was not declared. Should it be static? Reported-by: Abaci Robot Signed-off-by: chongjiapeng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index b7531cdc8bfe7..e412a096a4b82 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1752,7 +1752,7 @@ uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count) return 0; // invalid value } -enum dc_status configure_lttpr_mode_transparent(struct dc_link *link) +static enum dc_status configure_lttpr_mode_transparent(struct dc_link *link) { uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT; @@ -1763,7 +1763,7 @@ enum dc_status configure_lttpr_mode_transparent(struct dc_link *link) sizeof(repeater_mode)); } -enum dc_status configure_lttpr_mode_non_transparent( +static enum dc_status configure_lttpr_mode_non_transparent( struct dc_link *link, const struct link_training_settings *lt_settings) { From 59715cffce19cfd4f7cffcf6d7ecc18478af8c4a Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Thu, 2 Sep 2021 13:27:56 +0200 Subject: [PATCH 040/151] drm/amdgpu: use IS_ERR for debugfs APIs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit debugfs APIs returns encoded error so use IS_ERR for checking return value. v2: return PTR_ERR(ent) References: https://gitlab.freedesktop.org/drm/amd/-/issues/1686 Signed-off-by: Nirmoy Das Reviewed-by: Christian König Reviewed-By: Shashank Sharma Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 10 ++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index d256215ab2c77..60f46a4b0144c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1696,20 +1696,18 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) struct dentry *ent; int r, i; - - ent = debugfs_create_file("amdgpu_preempt_ib", 0600, root, adev, &fops_ib_preempt); - if (!ent) { + if (IS_ERR(ent)) { DRM_ERROR("unable to create amdgpu_preempt_ib debugsfs file\n"); - return -EIO; + return PTR_ERR(ent); } ent = debugfs_create_file("amdgpu_force_sclk", 0200, root, adev, &fops_sclk_set); - if (!ent) { + if (IS_ERR(ent)) { DRM_ERROR("unable to create amdgpu_set_sclk debugsfs file\n"); - return -EIO; + return PTR_ERR(ent); } /* Register debugfs entries for amdgpu_ttm */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 7b634a1517f9c..0554576d36955 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -428,8 +428,8 @@ int amdgpu_debugfs_ring_init(struct amdgpu_device *adev, ent = debugfs_create_file(name, S_IFREG | S_IRUGO, root, ring, &amdgpu_debugfs_ring_fops); - if (!ent) - return -ENOMEM; + if (IS_ERR(ent)) + return PTR_ERR(ent); i_size_write(ent->d_inode, ring->ring_size + 12); ring->ent = ent; From 62d266b2bd4afb216791d6eff8f3d65542fd4d16 Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Thu, 2 Sep 2021 15:31:07 +0200 Subject: [PATCH 041/151] drm/amdgpu: cleanup debugfs for amdgpu rings Use debugfs_create_file_size API for creating ring debugfs, and as its a NULL returning API, change the return type for amdgpu_debugfs_ring_init API as well. Also cleanup surrounding code. Signed-off-by: Nirmoy Das Reviewed-by: Shashank Sharma Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 4 +--- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 18 ++++++------------ drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 10 ++-------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 60f46a4b0144c..97d88f3e1c4c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1734,9 +1734,7 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) if (!ring) continue; - if (amdgpu_debugfs_ring_init(adev, ring)) { - DRM_ERROR("Failed to register debugfs file for rings !\n"); - } + amdgpu_debugfs_ring_init(adev, ring); } amdgpu_ras_debugfs_create_all(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 0554576d36955..ab2351ba95748 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -415,26 +415,20 @@ static const struct file_operations amdgpu_debugfs_ring_fops = { #endif -int amdgpu_debugfs_ring_init(struct amdgpu_device *adev, - struct amdgpu_ring *ring) +void amdgpu_debugfs_ring_init(struct amdgpu_device *adev, + struct amdgpu_ring *ring) { #if defined(CONFIG_DEBUG_FS) struct drm_minor *minor = adev_to_drm(adev)->primary; - struct dentry *ent, *root = minor->debugfs_root; + struct dentry *root = minor->debugfs_root; char name[32]; sprintf(name, "amdgpu_ring_%s", ring->name); + debugfs_create_file_size(name, S_IFREG | S_IRUGO, root, ring, + &amdgpu_debugfs_ring_fops, + ring->ring_size + 12); - ent = debugfs_create_file(name, - S_IFREG | S_IRUGO, root, - ring, &amdgpu_debugfs_ring_fops); - if (IS_ERR(ent)) - return PTR_ERR(ent); - - i_size_write(ent->d_inode, ring->ring_size + 12); - ring->ent = ent; #endif - return 0; } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index 88d80eb3fea12..4d380e79752c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -253,10 +253,6 @@ struct amdgpu_ring { bool has_compute_vm_bug; bool no_scheduler; int hw_prio; - -#if defined(CONFIG_DEBUG_FS) - struct dentry *ent; -#endif }; #define amdgpu_ring_parse_cs(r, p, ib) ((r)->funcs->parse_cs((p), (ib))) @@ -356,8 +352,6 @@ static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring, int amdgpu_ring_test_helper(struct amdgpu_ring *ring); -int amdgpu_debugfs_ring_init(struct amdgpu_device *adev, - struct amdgpu_ring *ring); -void amdgpu_debugfs_ring_fini(struct amdgpu_ring *ring); - +void amdgpu_debugfs_ring_init(struct amdgpu_device *adev, + struct amdgpu_ring *ring); #endif From 8a4d393ef4977dd5b937f09753d603de9e29b9bf Mon Sep 17 00:00:00 2001 From: Roy Sun Date: Mon, 6 Sep 2021 20:47:49 +0800 Subject: [PATCH 042/151] drm/amd/amdgpu: Enable some sysnodes for guest smi Enable sysnode vclk and dclk on Navi21 asic for guest smi Signed-off-by: Roy Sun Reviewed-by: Emily.Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 249cb0aeb5ae4..c255b4b8e6857 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -2087,10 +2087,10 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ if (asic_type < CHIP_VEGA12) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_vclk)) { - if (!(asic_type == CHIP_VANGOGH)) + if (!(asic_type == CHIP_VANGOGH || asic_type == CHIP_SIENNA_CICHLID)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) { - if (!(asic_type == CHIP_VANGOGH)) + if (!(asic_type == CHIP_VANGOGH || asic_type == CHIP_SIENNA_CICHLID)) *states = ATTR_STATE_UNSUPPORTED; } From 06dd1888ee58d2529f55916e250f0e272b0b8407 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 7 Sep 2021 09:53:03 -0400 Subject: [PATCH 043/151] drm/amd/display: Add NULL checks for vblank workqueue [Why] If we're running a headless config with 0 links then the vblank workqueue will be NULL - causing a NULL pointer exception during any commit. [How] Guard access to the workqueue if it's NULL and don't queue or flush work if it is. Reported-by: Mike Lothian BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1700 Fixes: 58aa1c50e5a231 ("drm/amd/display: Use vblank control events for PSR enable/disable") Signed-off-by: Nicholas Kazlauskas Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 53363728dbbdc..24002a9891961 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6185,21 +6185,23 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) return 0; #if defined(CONFIG_DRM_AMD_DC_DCN) - work = kzalloc(sizeof(*work), GFP_ATOMIC); - if (!work) - return -ENOMEM; + if (dm->vblank_control_workqueue) { + work = kzalloc(sizeof(*work), GFP_ATOMIC); + if (!work) + return -ENOMEM; - INIT_WORK(&work->work, vblank_control_worker); - work->dm = dm; - work->acrtc = acrtc; - work->enable = enable; + INIT_WORK(&work->work, vblank_control_worker); + work->dm = dm; + work->acrtc = acrtc; + work->enable = enable; - if (acrtc_state->stream) { - dc_stream_retain(acrtc_state->stream); - work->stream = acrtc_state->stream; - } + if (acrtc_state->stream) { + dc_stream_retain(acrtc_state->stream); + work->stream = acrtc_state->stream; + } - queue_work(dm->vblank_control_workqueue, &work->work); + queue_work(dm->vblank_control_workqueue, &work->work); + } #endif return 0; @@ -8809,7 +8811,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, * If PSR or idle optimizations are enabled then flush out * any pending work before hardware programming. */ - flush_workqueue(dm->vblank_control_workqueue); + if (dm->vblank_control_workqueue) + flush_workqueue(dm->vblank_control_workqueue); #endif bundle->stream_update.stream = acrtc_state->stream; @@ -9144,7 +9147,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) /* if there mode set or reset, disable eDP PSR */ if (mode_set_reset_required) { #if defined(CONFIG_DRM_AMD_DC_DCN) - flush_workqueue(dm->vblank_control_workqueue); + if (dm->vblank_control_workqueue) + flush_workqueue(dm->vblank_control_workqueue); #endif amdgpu_dm_psr_disable_all(dm); } From 02f958a20cb24311f519cd33d918a6de20c45157 Mon Sep 17 00:00:00 2001 From: Likun Gao Date: Thu, 9 Sep 2021 14:30:10 +0800 Subject: [PATCH 044/151] drm/amdgpu: refactor function to init no-psp fw Refactor the code of amdgpu_ucode_init_single_fw to make it more readable as too many ucode need to handle on this function currently. Signed-off-by: Likun Gao Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 160 ++++++++++------------ 1 file changed, 75 insertions(+), 85 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index abd8469380e51..5f396936c6add 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -572,6 +572,7 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev, const struct dmcu_firmware_header_v1_0 *dmcu_hdr = NULL; const struct dmcub_firmware_header_v1_0 *dmcub_hdr = NULL; const struct mes_firmware_header_v1_0 *mes_hdr = NULL; + u8 *ucode_addr; if (NULL == ucode->fw) return 0; @@ -588,94 +589,83 @@ static int amdgpu_ucode_init_single_fw(struct amdgpu_device *adev, dmcub_hdr = (const struct dmcub_firmware_header_v1_0 *)ucode->fw->data; mes_hdr = (const struct mes_firmware_header_v1_0 *)ucode->fw->data; - if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP || - (ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC1 && - ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC2 && - ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC1_JT && - ucode->ucode_id != AMDGPU_UCODE_ID_CP_MEC2_JT && - ucode->ucode_id != AMDGPU_UCODE_ID_CP_MES && - ucode->ucode_id != AMDGPU_UCODE_ID_CP_MES_DATA && - ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL && - ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM && - ucode->ucode_id != AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM && - ucode->ucode_id != AMDGPU_UCODE_ID_RLC_IRAM && - ucode->ucode_id != AMDGPU_UCODE_ID_RLC_DRAM && - ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_ERAM && - ucode->ucode_id != AMDGPU_UCODE_ID_DMCU_INTV && - ucode->ucode_id != AMDGPU_UCODE_ID_DMCUB)) { - ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes); - - memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data + - le32_to_cpu(header->ucode_array_offset_bytes)), - ucode->ucode_size); - } else if (ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC1 || - ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC2) { - ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes) - - le32_to_cpu(cp_hdr->jt_size) * 4; - - memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data + - le32_to_cpu(header->ucode_array_offset_bytes)), - ucode->ucode_size); - } else if (ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC1_JT || - ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC2_JT) { - ucode->ucode_size = le32_to_cpu(cp_hdr->jt_size) * 4; - - memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data + - le32_to_cpu(header->ucode_array_offset_bytes) + - le32_to_cpu(cp_hdr->jt_offset) * 4), - ucode->ucode_size); - } else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCU_ERAM) { - ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes) - + if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { + switch (ucode->ucode_id) { + case AMDGPU_UCODE_ID_CP_MEC1: + case AMDGPU_UCODE_ID_CP_MEC2: + ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes) - + le32_to_cpu(cp_hdr->jt_size) * 4; + ucode_addr = (u8 *)ucode->fw->data + + le32_to_cpu(header->ucode_array_offset_bytes); + break; + case AMDGPU_UCODE_ID_CP_MEC1_JT: + case AMDGPU_UCODE_ID_CP_MEC2_JT: + ucode->ucode_size = le32_to_cpu(cp_hdr->jt_size) * 4; + ucode_addr = (u8 *)ucode->fw->data + + le32_to_cpu(header->ucode_array_offset_bytes) + + le32_to_cpu(cp_hdr->jt_offset) * 4; + break; + case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL: + ucode->ucode_size = adev->gfx.rlc.save_restore_list_cntl_size_bytes; + ucode_addr = adev->gfx.rlc.save_restore_list_cntl; + break; + case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM: + ucode->ucode_size = adev->gfx.rlc.save_restore_list_gpm_size_bytes; + ucode_addr = adev->gfx.rlc.save_restore_list_gpm; + break; + case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM: + ucode->ucode_size = adev->gfx.rlc.save_restore_list_srm_size_bytes; + ucode_addr = adev->gfx.rlc.save_restore_list_srm; + break; + case AMDGPU_UCODE_ID_RLC_IRAM: + ucode->ucode_size = adev->gfx.rlc.rlc_iram_ucode_size_bytes; + ucode_addr = adev->gfx.rlc.rlc_iram_ucode; + break; + case AMDGPU_UCODE_ID_RLC_DRAM: + ucode->ucode_size = adev->gfx.rlc.rlc_dram_ucode_size_bytes; + ucode_addr = adev->gfx.rlc.rlc_dram_ucode; + break; + case AMDGPU_UCODE_ID_CP_MES: + ucode->ucode_size = le32_to_cpu(mes_hdr->mes_ucode_size_bytes); + ucode_addr = (u8 *)ucode->fw->data + + le32_to_cpu(mes_hdr->mes_ucode_offset_bytes); + break; + case AMDGPU_UCODE_ID_CP_MES_DATA: + ucode->ucode_size = le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes); + ucode_addr = (u8 *)ucode->fw->data + + le32_to_cpu(mes_hdr->mes_ucode_data_offset_bytes); + break; + case AMDGPU_UCODE_ID_DMCU_ERAM: + ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes) - le32_to_cpu(dmcu_hdr->intv_size_bytes); - - memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data + - le32_to_cpu(header->ucode_array_offset_bytes)), - ucode->ucode_size); - } else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCU_INTV) { - ucode->ucode_size = le32_to_cpu(dmcu_hdr->intv_size_bytes); - - memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data + - le32_to_cpu(header->ucode_array_offset_bytes) + - le32_to_cpu(dmcu_hdr->intv_offset_bytes)), - ucode->ucode_size); - } else if (ucode->ucode_id == AMDGPU_UCODE_ID_DMCUB) { - ucode->ucode_size = le32_to_cpu(dmcub_hdr->inst_const_bytes); - memcpy(ucode->kaddr, - (void *)((uint8_t *)ucode->fw->data + - le32_to_cpu(header->ucode_array_offset_bytes)), - ucode->ucode_size); - } else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL) { - ucode->ucode_size = adev->gfx.rlc.save_restore_list_cntl_size_bytes; - memcpy(ucode->kaddr, adev->gfx.rlc.save_restore_list_cntl, - ucode->ucode_size); - } else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM) { - ucode->ucode_size = adev->gfx.rlc.save_restore_list_gpm_size_bytes; - memcpy(ucode->kaddr, adev->gfx.rlc.save_restore_list_gpm, - ucode->ucode_size); - } else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM) { - ucode->ucode_size = adev->gfx.rlc.save_restore_list_srm_size_bytes; - memcpy(ucode->kaddr, adev->gfx.rlc.save_restore_list_srm, - ucode->ucode_size); - } else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_IRAM) { - ucode->ucode_size = adev->gfx.rlc.rlc_iram_ucode_size_bytes; - memcpy(ucode->kaddr, adev->gfx.rlc.rlc_iram_ucode, - ucode->ucode_size); - } else if (ucode->ucode_id == AMDGPU_UCODE_ID_RLC_DRAM) { - ucode->ucode_size = adev->gfx.rlc.rlc_dram_ucode_size_bytes; - memcpy(ucode->kaddr, adev->gfx.rlc.rlc_dram_ucode, - ucode->ucode_size); - } else if (ucode->ucode_id == AMDGPU_UCODE_ID_CP_MES) { - ucode->ucode_size = le32_to_cpu(mes_hdr->mes_ucode_size_bytes); - memcpy(ucode->kaddr, (void *)((uint8_t *)adev->mes.fw->data + - le32_to_cpu(mes_hdr->mes_ucode_offset_bytes)), - ucode->ucode_size); - } else if (ucode->ucode_id == AMDGPU_UCODE_ID_CP_MES_DATA) { - ucode->ucode_size = le32_to_cpu(mes_hdr->mes_ucode_data_size_bytes); - memcpy(ucode->kaddr, (void *)((uint8_t *)adev->mes.fw->data + - le32_to_cpu(mes_hdr->mes_ucode_data_offset_bytes)), - ucode->ucode_size); + ucode_addr = (u8 *)ucode->fw->data + + le32_to_cpu(header->ucode_array_offset_bytes); + break; + case AMDGPU_UCODE_ID_DMCU_INTV: + ucode->ucode_size = le32_to_cpu(dmcu_hdr->intv_size_bytes); + ucode_addr = (u8 *)ucode->fw->data + + le32_to_cpu(header->ucode_array_offset_bytes) + + le32_to_cpu(dmcu_hdr->intv_offset_bytes); + break; + case AMDGPU_UCODE_ID_DMCUB: + ucode->ucode_size = le32_to_cpu(dmcub_hdr->inst_const_bytes); + ucode_addr = (u8 *)ucode->fw->data + + le32_to_cpu(header->ucode_array_offset_bytes); + break; + default: + ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes); + ucode_addr = (u8 *)ucode->fw->data + + le32_to_cpu(header->ucode_array_offset_bytes); + break; + } + } else { + ucode->ucode_size = le32_to_cpu(header->ucode_size_bytes); + ucode_addr = (u8 *)ucode->fw->data + + le32_to_cpu(header->ucode_array_offset_bytes); } + memcpy(ucode->kaddr, ucode_addr, ucode->ucode_size); + return 0; } From 334f81d1643bfb5ab97fccaf73dc0fe0f9d61e28 Mon Sep 17 00:00:00 2001 From: John Clements Date: Thu, 9 Sep 2021 16:05:01 +0800 Subject: [PATCH 045/151] drm/amdgpu: Update RAS status print Remove uncessary RAS status prints Reviewed-by: Hawking Zhang Signed-off-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 37 +++++++------------------ 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 75eed18370eb1..885876e2ce73b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1334,31 +1334,6 @@ int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id) return ret; } -static int psp_ras_status_to_errno(struct amdgpu_device *adev, - enum ta_ras_status ras_status) -{ - int ret = -EINVAL; - - switch (ras_status) { - case TA_RAS_STATUS__SUCCESS: - ret = 0; - break; - case TA_RAS_STATUS__RESET_NEEDED: - ret = -EAGAIN; - break; - case TA_RAS_STATUS__ERROR_RAS_NOT_AVAILABLE: - dev_warn(adev->dev, "RAS WARN: ras function unavailable\n"); - break; - case TA_RAS_STATUS__ERROR_ASD_READ_WRITE: - dev_warn(adev->dev, "RAS WARN: asd read or write failed\n"); - break; - default: - dev_err(adev->dev, "RAS ERROR: ras function failed ret 0x%X\n", ret); - } - - return ret; -} - int psp_ras_enable_features(struct psp_context *psp, union ta_ras_cmd_input *info, bool enable) { @@ -1382,7 +1357,10 @@ int psp_ras_enable_features(struct psp_context *psp, if (ret) return -EINVAL; - return psp_ras_status_to_errno(psp->adev, ras_cmd->ras_status); + if (ras_cmd->ras_status) + dev_warn(psp->adev->dev, "RAS WARNING: ras status = 0x%X\n", ras_cmd->ras_status); + + return 0; } static int psp_ras_terminate(struct psp_context *psp) @@ -1523,7 +1501,12 @@ int psp_ras_trigger_error(struct psp_context *psp, if (amdgpu_ras_intr_triggered()) return 0; - return psp_ras_status_to_errno(psp->adev, ras_cmd->ras_status); + if (ras_cmd->ras_status) { + dev_warn(psp->adev->dev, "RAS WARNING: ras status = 0x%X\n", ras_cmd->ras_status); + return -EINVAL; + } + + return 0; } // ras end From 3771449bc80fa494c15f366ce1fa9e3168332b6a Mon Sep 17 00:00:00 2001 From: John Clements Date: Thu, 9 Sep 2021 16:05:12 +0800 Subject: [PATCH 046/151] drm/amdgpu: Update RAS trigger error block support Added trigger error support for MP0/MP1/MPIO blocks Reviewed-by: Hawking Zhang Signed-off-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 77140821dc112..b5332db4d2873 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1028,6 +1028,9 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev, case AMDGPU_RAS_BLOCK__SDMA: case AMDGPU_RAS_BLOCK__MMHUB: case AMDGPU_RAS_BLOCK__PCIE_BIF: + case AMDGPU_RAS_BLOCK__MP0: + case AMDGPU_RAS_BLOCK__MP1: + case AMDGPU_RAS_BLOCK__MPIO: ret = psp_ras_trigger_error(&adev->psp, &block_info); break; case AMDGPU_RAS_BLOCK__XGMI_WAFL: From 5f64d9af02793c3514ed82a71b6d91327d624068 Mon Sep 17 00:00:00 2001 From: Anson Jacob Date: Thu, 9 Sep 2021 12:48:29 -0400 Subject: [PATCH 047/151] drm/amd/display: dc_assert_fp_enabled assert only if FPU is not enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assert only when FPU is not enabled. Fixes: 0ea7ee821701 ("drm/amd/display: Add DC_FP helper to check FPU state") Signed-off-by: Anson Jacob Cc: Christian König Cc: Hersen Wu Cc: Harry Wentland Cc: Rodrigo Siqueira Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c index c9f47d1674723..b1bf80da3a55f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c @@ -62,7 +62,7 @@ inline void dc_assert_fp_enabled(void) depth = *pcpu; put_cpu_ptr(&fpu_recursion_depth); - ASSERT(depth > 1); + ASSERT(depth >= 1); } /** From ee121f7ebe608a46ac9c22ec257a392bfcfb5471 Mon Sep 17 00:00:00 2001 From: Lang Yu Date: Wed, 8 Sep 2021 13:34:26 +0800 Subject: [PATCH 048/151] drm/amdgpu: fix sysfs_emit/sysfs_emit_at warnings(v2) sysfs_emit and sysfs_emit_at requrie a page boundary aligned buf address. Make them happy! v2: use an inline function. Warning Log: [ 492.545174] invalid sysfs_emit_at: buf:00000000f19bdfde at:0 [ 492.546416] WARNING: CPU: 7 PID: 1304 at fs/sysfs/file.c:765 sysfs_emit_at+0x4a/0xa0 [ 492.654805] Call Trace: [ 492.655353] ? smu_cmn_get_metrics_table+0x40/0x50 [amdgpu] [ 492.656780] vangogh_print_clk_levels+0x369/0x410 [amdgpu] [ 492.658245] vangogh_common_print_clk_levels+0x77/0x80 [amdgpu] [ 492.659733] ? preempt_schedule_common+0x18/0x30 [ 492.660713] smu_print_ppclk_levels+0x65/0x90 [amdgpu] [ 492.662107] amdgpu_get_pp_od_clk_voltage+0x13d/0x190 [amdgpu] [ 492.663620] dev_attr_show+0x1d/0x40 Signed-off-by: Lang Yu Acked-by: Huang Rui Signed-off-by: Alex Deucher --- .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 8 ++++++-- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 4 +++- .../drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 4 +++- drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c | 16 ++++++++++------ drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 2 ++ .../gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c | 12 ++++++++---- .../gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 6 ++++-- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 13 +++++++++++++ 8 files changed, 49 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index e343cc218990b..082f01893f3d1 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -771,8 +771,12 @@ static int arcturus_print_clk_levels(struct smu_context *smu, struct smu_11_0_dpm_context *dpm_context = NULL; uint32_t gen_speed, lane_width; - if (amdgpu_ras_intr_triggered()) - return sysfs_emit(buf, "unavailable\n"); + smu_cmn_get_sysfs_buf(&buf, &size); + + if (amdgpu_ras_intr_triggered()) { + size += sysfs_emit_at(buf, size, "unavailable\n"); + return size; + } dpm_context = smu_dpm->dpm_context; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 4c81989b81626..63e1f0db579cc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1279,6 +1279,8 @@ static int navi10_print_clk_levels(struct smu_context *smu, struct smu_11_0_overdrive_table *od_settings = smu->od_settings; uint32_t min_value, max_value; + smu_cmn_get_sysfs_buf(&buf, &size); + switch (clk_type) { case SMU_GFXCLK: case SMU_SCLK: @@ -1392,7 +1394,7 @@ static int navi10_print_clk_levels(struct smu_context *smu, case SMU_OD_RANGE: if (!smu->od_enabled || !od_table || !od_settings) break; - size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) { navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMIN, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 5e292c3f5050e..d7519688065ff 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1058,6 +1058,8 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu, uint32_t min_value, max_value; uint32_t smu_version; + smu_cmn_get_sysfs_buf(&buf, &size); + switch (clk_type) { case SMU_GFXCLK: case SMU_SCLK: @@ -1180,7 +1182,7 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu, if (!smu->od_enabled || !od_table || !od_settings) break; - size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); if (sienna_cichlid_is_od_feature_supported(od_settings, SMU_11_0_7_ODCAP_GFXCLK_LIMITS)) { sienna_cichlid_get_od_setting_range(od_settings, SMU_11_0_7_ODSETTING_GFXCLKFMIN, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c index 3a3421452e57a..f6ef0ce6e9e2c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -589,10 +589,12 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu, if (ret) return ret; + smu_cmn_get_sysfs_buf(&buf, &size); + switch (clk_type) { case SMU_OD_SCLK: if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { - size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); + size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK"); size += sysfs_emit_at(buf, size, "0: %10uMhz\n", (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); size += sysfs_emit_at(buf, size, "1: %10uMhz\n", @@ -601,7 +603,7 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu, break; case SMU_OD_CCLK: if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { - size = sysfs_emit(buf, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select); + size += sysfs_emit_at(buf, size, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select); size += sysfs_emit_at(buf, size, "0: %10uMhz\n", (smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq); size += sysfs_emit_at(buf, size, "1: %10uMhz\n", @@ -610,7 +612,7 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu, break; case SMU_OD_RANGE: if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { - size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n", @@ -688,10 +690,12 @@ static int vangogh_print_clk_levels(struct smu_context *smu, if (ret) return ret; + smu_cmn_get_sysfs_buf(&buf, &size); + switch (clk_type) { case SMU_OD_SCLK: if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { - size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); + size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK"); size += sysfs_emit_at(buf, size, "0: %10uMhz\n", (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); size += sysfs_emit_at(buf, size, "1: %10uMhz\n", @@ -700,7 +704,7 @@ static int vangogh_print_clk_levels(struct smu_context *smu, break; case SMU_OD_CCLK: if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { - size = sysfs_emit(buf, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select); + size += sysfs_emit_at(buf, size, "CCLK_RANGE in Core%d:\n", smu->cpu_core_id_select); size += sysfs_emit_at(buf, size, "0: %10uMhz\n", (smu->cpu_actual_soft_min_freq > 0) ? smu->cpu_actual_soft_min_freq : smu->cpu_default_soft_min_freq); size += sysfs_emit_at(buf, size, "1: %10uMhz\n", @@ -709,7 +713,7 @@ static int vangogh_print_clk_levels(struct smu_context *smu, break; case SMU_OD_RANGE: if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { - size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); size += sysfs_emit_at(buf, size, "CCLK: %7uMhz %10uMhz\n", diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index 5aa175e12a783..145f13b8c977d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -497,6 +497,8 @@ static int renoir_print_clk_levels(struct smu_context *smu, if (ret) return ret; + smu_cmn_get_sysfs_buf(&buf, &size); + switch (clk_type) { case SMU_OD_RANGE: if (smu_dpm_ctx->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index ab652028e0034..5019903db492a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -733,15 +733,19 @@ static int aldebaran_print_clk_levels(struct smu_context *smu, uint32_t freq_values[3] = {0}; uint32_t min_clk, max_clk; - if (amdgpu_ras_intr_triggered()) - return sysfs_emit(buf, "unavailable\n"); + smu_cmn_get_sysfs_buf(&buf, &size); + + if (amdgpu_ras_intr_triggered()) { + size += sysfs_emit_at(buf, size, "unavailable\n"); + return size; + } dpm_context = smu_dpm->dpm_context; switch (type) { case SMU_OD_SCLK: - size = sysfs_emit(buf, "%s:\n", "GFXCLK"); + size += sysfs_emit_at(buf, size, "%s:\n", "GFXCLK"); fallthrough; case SMU_SCLK: ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_GFXCLK, &now); @@ -795,7 +799,7 @@ static int aldebaran_print_clk_levels(struct smu_context *smu, break; case SMU_OD_MCLK: - size = sysfs_emit(buf, "%s:\n", "MCLK"); + size += sysfs_emit_at(buf, size, "%s:\n", "MCLK"); fallthrough; case SMU_MCLK: ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_UCLK, &now); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c index 627ba2eec7fda..a403657151ba1 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c @@ -1052,16 +1052,18 @@ static int yellow_carp_print_clk_levels(struct smu_context *smu, int i, size = 0, ret = 0; uint32_t cur_value = 0, value = 0, count = 0; + smu_cmn_get_sysfs_buf(&buf, &size); + switch (clk_type) { case SMU_OD_SCLK: - size = sysfs_emit(buf, "%s:\n", "OD_SCLK"); + size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK"); size += sysfs_emit_at(buf, size, "0: %10uMhz\n", (smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq); size += sysfs_emit_at(buf, size, "1: %10uMhz\n", (smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq); break; case SMU_OD_RANGE: - size = sysfs_emit(buf, "%s:\n", "OD_RANGE"); + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq); break; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h index 16993daa2ae04..4054d9493e774 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h @@ -110,5 +110,18 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev); int smu_cmn_set_mp1_state(struct smu_context *smu, enum pp_mp1_state mp1_state); +/* + * Helper function to make sysfs_emit_at() happy. Align buf to + * the current page boundary and record the offset. + */ +static inline void smu_cmn_get_sysfs_buf(char **buf, int *offset) +{ + if (!*buf || !offset) + return; + + *offset = offset_in_page(*buf); + *buf -= *offset; +} + #endif #endif From c7c6b86acbd7fee59def4bb7ae1630ce5d5ec85e Mon Sep 17 00:00:00 2001 From: Lang Yu Date: Tue, 24 Aug 2021 17:02:57 +0800 Subject: [PATCH 049/151] drm/amdgpu: update SMU PPSMC for cyan skilfish Add some PPSMC MSGs for cyan skilfish. Signed-off-by: Lang Yu Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h index 6e6088760b180..909a86aa60f32 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_8_ppsmc.h @@ -65,6 +65,13 @@ #define PPSMC_MSG_SetDriverTableVMID 0x34 #define PPSMC_MSG_SetSoftMinCclk 0x35 #define PPSMC_MSG_SetSoftMaxCclk 0x36 -#define PPSMC_Message_Count 0x37 +#define PPSMC_MSG_GetGfxFrequency 0x37 +#define PPSMC_MSG_GetGfxVid 0x38 +#define PPSMC_MSG_ForceGfxFreq 0x39 +#define PPSMC_MSG_UnForceGfxFreq 0x3A +#define PPSMC_MSG_ForceGfxVid 0x3B +#define PPSMC_MSG_UnforceGfxVid 0x3C +#define PPSMC_MSG_GetEnabledSmuFeatures 0x3D +#define PPSMC_Message_Count 0x3E #endif From ca8ff8fcb3f036550527a740f731aa6b36139eaf Mon Sep 17 00:00:00 2001 From: Lang Yu Date: Fri, 27 Aug 2021 14:16:31 +0800 Subject: [PATCH 050/151] drm/amdgpu: update SMU driver interface for cyan skilfish(v3) Add SmuMetrics_t definition for cyan skilfish. v2: update SmuMetrics_t definition. v3: cleanup and rearrange the order of fields. Signed-off-by: Lang Yu Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- .../pm/inc/smu11_driver_if_cyan_skillfish.h | 86 ++++++++----------- 1 file changed, 35 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h index 8a08ecc34c699..4884a4e1f261c 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h +++ b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_cyan_skillfish.h @@ -33,63 +33,47 @@ #define TABLE_PMSTATUSLOG 3 // Called by Tools for Agm logging #define TABLE_DPMCLOCKS 4 // Called by Driver; defined here, but not used, for backward compatible #define TABLE_MOMENTARY_PM 5 // Called by Tools; defined here, but not used, for backward compatible -#define TABLE_COUNT 6 +#define TABLE_SMU_METRICS 6 // Called by Driver +#define TABLE_COUNT 7 -#define NUM_DSPCLK_LEVELS 8 -#define NUM_SOCCLK_DPM_LEVELS 8 -#define NUM_DCEFCLK_DPM_LEVELS 4 -#define NUM_FCLK_DPM_LEVELS 4 -#define NUM_MEMCLK_DPM_LEVELS 4 +typedef struct SmuMetricsTable_t { + //CPU status + uint16_t CoreFrequency[6]; //[MHz] + uint32_t CorePower[6]; //[mW] + uint16_t CoreTemperature[6]; //[centi-Celsius] + uint16_t L3Frequency[2]; //[MHz] + uint16_t L3Temperature[2]; //[centi-Celsius] + uint16_t C0Residency[6]; //Percentage -#define NUMBER_OF_PSTATES 8 -#define NUMBER_OF_CORES 8 + // GFX status + uint16_t GfxclkFrequency; //[MHz] + uint16_t GfxTemperature; //[centi-Celsius] -typedef enum { - S3_TYPE_ENTRY, - S5_TYPE_ENTRY, -} Sleep_Type_e; + // SOC IP info + uint16_t SocclkFrequency; //[MHz] + uint16_t VclkFrequency; //[MHz] + uint16_t DclkFrequency; //[MHz] + uint16_t MemclkFrequency; //[MHz] -typedef enum { - GFX_OFF = 0, - GFX_ON = 1, -} GFX_Mode_e; + // power, VF info for CPU/GFX telemetry rails, and then socket power total + uint32_t Voltage[2]; //[mV] indices: VDDCR_VDD, VDDCR_GFX + uint32_t Current[2]; //[mA] indices: VDDCR_VDD, VDDCR_GFX + uint32_t Power[2]; //[mW] indices: VDDCR_VDD, VDDCR_GFX + uint32_t CurrentSocketPower; //[mW] -typedef enum { - CPU_P0 = 0, - CPU_P1, - CPU_P2, - CPU_P3, - CPU_P4, - CPU_P5, - CPU_P6, - CPU_P7 -} CPU_PState_e; + uint16_t SocTemperature; //[centi-Celsius] + uint16_t EdgeTemperature; + uint16_t ThrottlerStatus; + uint16_t Spare; -typedef enum { - CPU_CORE0 = 0, - CPU_CORE1, - CPU_CORE2, - CPU_CORE3, - CPU_CORE4, - CPU_CORE5, - CPU_CORE6, - CPU_CORE7 -} CORE_ID_e; +} SmuMetricsTable_t; -typedef enum { - DF_DPM0 = 0, - DF_DPM1, - DF_DPM2, - DF_DPM3, - DF_PState_Count -} DF_PState_e; - -typedef enum { - GFX_DPM0 = 0, - GFX_DPM1, - GFX_DPM2, - GFX_DPM3, - GFX_PState_Count -} GFX_PState_e; +typedef struct SmuMetrics_t { + SmuMetricsTable_t Current; + SmuMetricsTable_t Average; + uint32_t SampleStartTime; + uint32_t SampleStopTime; + uint32_t Accnt; +} SmuMetrics_t; #endif From 2ba83fd53f28438359ab56eb5bd54646b78439c0 Mon Sep 17 00:00:00 2001 From: Lang Yu Date: Fri, 27 Aug 2021 15:03:50 +0800 Subject: [PATCH 051/151] drm/amdgpu: add some pptable funcs for cyan skilfish(v3) Add print_clk_levels and read_sensor pptable funcs for cyan skilfish. v2: keep consitency and add get_gpu_metrics callback. v3: use sysfs_emit_at() in sysfs show function. Signed-off-by: Lang Yu Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- .../amd/pm/swsmu/smu11/cyan_skillfish_ppt.c | 347 ++++++++++++++++++ 1 file changed, 347 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c index b05f9541accc3..e1fab030cfc50 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c @@ -44,6 +44,12 @@ #undef pr_info #undef pr_debug +#define FEATURE_MASK(feature) (1ULL << feature) +#define SMC_DPM_FEATURE ( \ + FEATURE_MASK(FEATURE_FCLK_DPM_BIT) | \ + FEATURE_MASK(FEATURE_SOC_DPM_BIT) | \ + FEATURE_MASK(FEATURE_GFX_DPM_BIT)) + static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 0), @@ -52,14 +58,354 @@ static struct cmn2asic_msg_mapping cyan_skillfish_message_map[SMU_MSG_MAX_COUNT] MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverTableDramAddrLow, 0), MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), + MSG_MAP(GetEnabledSmuFeatures, PPSMC_MSG_GetEnabledSmuFeatures, 0), + MSG_MAP(RequestGfxclk, PPSMC_MSG_RequestGfxclk, 0), + MSG_MAP(ForceGfxVid, PPSMC_MSG_ForceGfxVid, 0), + MSG_MAP(UnforceGfxVid, PPSMC_MSG_UnforceGfxVid, 0), +}; + +static struct cmn2asic_mapping cyan_skillfish_table_map[SMU_TABLE_COUNT] = { + TAB_MAP_VALID(SMU_METRICS), }; +static int cyan_skillfish_tables_init(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *tables = smu_table->tables; + + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, + sizeof(SmuMetrics_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM); + + smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); + if (!smu_table->metrics_table) + goto err0_out; + + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_2); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) + goto err1_out; + + smu_table->metrics_time = 0; + + return 0; + +err1_out: + smu_table->gpu_metrics_table_size = 0; + kfree(smu_table->metrics_table); +err0_out: + return -ENOMEM; +} + +static int cyan_skillfish_init_smc_tables(struct smu_context *smu) +{ + int ret = 0; + + ret = cyan_skillfish_tables_init(smu); + if (ret) + return ret; + + return smu_v11_0_init_smc_tables(smu); +} + +static int cyan_skillfish_finit_smc_tables(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + + kfree(smu_table->metrics_table); + smu_table->metrics_table = NULL; + + kfree(smu_table->gpu_metrics_table); + smu_table->gpu_metrics_table = NULL; + smu_table->gpu_metrics_table_size = 0; + + smu_table->metrics_time = 0; + + return 0; +} + +static int +cyan_skillfish_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table = &smu->smu_table; + SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = smu_cmn_get_metrics_table_locked(smu, NULL, false); + if (ret) { + mutex_unlock(&smu->metrics_lock); + return ret; + } + + switch (member) { + case METRICS_CURR_GFXCLK: + *value = metrics->Current.GfxclkFrequency; + break; + case METRICS_CURR_SOCCLK: + *value = metrics->Current.SocclkFrequency; + break; + case METRICS_CURR_VCLK: + *value = metrics->Current.VclkFrequency; + break; + case METRICS_CURR_DCLK: + *value = metrics->Current.DclkFrequency; + break; + case METRICS_CURR_UCLK: + *value = metrics->Current.MemclkFrequency; + break; + case METRICS_AVERAGE_SOCKETPOWER: + *value = (metrics->Current.CurrentSocketPower << 8) / + 1000; + break; + case METRICS_TEMPERATURE_EDGE: + *value = metrics->Current.GfxTemperature / 100 * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_HOTSPOT: + *value = metrics->Current.SocTemperature / 100 * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_VOLTAGE_VDDSOC: + *value = metrics->Current.Voltage[0]; + break; + case METRICS_VOLTAGE_VDDGFX: + *value = metrics->Current.Voltage[1]; + break; + case METRICS_THROTTLER_STATUS: + *value = metrics->Current.ThrottlerStatus; + break; + default: + *value = UINT_MAX; + break; + } + + mutex_unlock(&smu->metrics_lock); + + return ret; +} + +static int cyan_skillfish_read_sensor(struct smu_context *smu, + enum amd_pp_sensors sensor, + void *data, + uint32_t *size) +{ + int ret = 0; + + if (!data || !size) + return -EINVAL; + + mutex_lock(&smu->sensor_lock); + + switch (sensor) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = cyan_skillfish_get_smu_metrics_data(smu, + METRICS_CURR_GFXCLK, + (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = cyan_skillfish_get_smu_metrics_data(smu, + METRICS_CURR_UCLK, + (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_POWER: + ret = cyan_skillfish_get_smu_metrics_data(smu, + METRICS_AVERAGE_SOCKETPOWER, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + ret = cyan_skillfish_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_HOTSPOT, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_EDGE_TEMP: + ret = cyan_skillfish_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_EDGE, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDNB: + ret = cyan_skillfish_get_smu_metrics_data(smu, + METRICS_VOLTAGE_VDDSOC, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDGFX: + ret = cyan_skillfish_get_smu_metrics_data(smu, + METRICS_VOLTAGE_VDDGFX, + (uint32_t *)data); + *size = 4; + break; + default: + ret = -EOPNOTSUPP; + break; + } + + mutex_unlock(&smu->sensor_lock); + + return ret; +} + +static int cyan_skillfish_get_current_clk_freq(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *value) +{ + MetricsMember_t member_type; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + member_type = METRICS_CURR_GFXCLK; + break; + case SMU_FCLK: + case SMU_MCLK: + member_type = METRICS_CURR_UCLK; + break; + case SMU_SOCCLK: + member_type = METRICS_CURR_SOCCLK; + break; + case SMU_VCLK: + member_type = METRICS_CURR_VCLK; + break; + case SMU_DCLK: + member_type = METRICS_CURR_DCLK; + break; + default: + return -EINVAL; + } + + return cyan_skillfish_get_smu_metrics_data(smu, member_type, value); +} + +static int cyan_skillfish_print_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, + char *buf) +{ + int ret = 0, size = 0; + uint32_t cur_value = 0; + + smu_cmn_get_sysfs_buf(&buf, &size); + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + case SMU_FCLK: + case SMU_MCLK: + case SMU_SOCCLK: + case SMU_VCLK: + case SMU_DCLK: + ret = cyan_skillfish_get_current_clk_freq(smu, clk_type, &cur_value); + if (ret) + return ret; + size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value); + break; + default: + dev_warn(smu->adev->dev, "Unsupported clock type\n"); + return ret; + } + + return size; +} + +static bool cyan_skillfish_is_dpm_running(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + int ret = 0; + uint32_t feature_mask[2]; + uint64_t feature_enabled; + + /* we need to re-init after suspend so return false */ + if (adev->in_suspend) + return false; + + ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2); + + if (ret) + return false; + + feature_enabled = (uint64_t)feature_mask[0] | + ((uint64_t)feature_mask[1] << 32); + + return !!(feature_enabled & SMC_DPM_FEATURE); +} + +static ssize_t cyan_skillfish_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v2_2 *gpu_metrics = + (struct gpu_metrics_v2_2 *)smu_table->gpu_metrics_table; + SmuMetrics_t metrics; + int i, ret = 0; + + ret = smu_cmn_get_metrics_table(smu, &metrics, true); + if (ret) + return ret; + + smu_cmn_init_soft_gpu_metrics(gpu_metrics, 2, 2); + + gpu_metrics->temperature_gfx = metrics.Current.GfxTemperature; + gpu_metrics->temperature_soc = metrics.Current.SocTemperature; + + gpu_metrics->average_socket_power = metrics.Current.CurrentSocketPower; + gpu_metrics->average_soc_power = metrics.Current.Power[0]; + gpu_metrics->average_gfx_power = metrics.Current.Power[1]; + + gpu_metrics->average_gfxclk_frequency = metrics.Average.GfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.Average.SocclkFrequency; + gpu_metrics->average_uclk_frequency = metrics.Average.MemclkFrequency; + gpu_metrics->average_fclk_frequency = metrics.Average.MemclkFrequency; + gpu_metrics->average_vclk_frequency = metrics.Average.VclkFrequency; + gpu_metrics->average_dclk_frequency = metrics.Average.DclkFrequency; + + gpu_metrics->current_gfxclk = metrics.Current.GfxclkFrequency; + gpu_metrics->current_socclk = metrics.Current.SocclkFrequency; + gpu_metrics->current_uclk = metrics.Current.MemclkFrequency; + gpu_metrics->current_fclk = metrics.Current.MemclkFrequency; + gpu_metrics->current_vclk = metrics.Current.VclkFrequency; + gpu_metrics->current_dclk = metrics.Current.DclkFrequency; + + for (i = 0; i < 6; i++) { + gpu_metrics->temperature_core[i] = metrics.Current.CoreTemperature[i]; + gpu_metrics->average_core_power[i] = metrics.Average.CorePower[i]; + gpu_metrics->current_coreclk[i] = metrics.Current.CoreFrequency[i]; + } + + for (i = 0; i < 2; i++) { + gpu_metrics->temperature_l3[i] = metrics.Current.L3Temperature[i]; + gpu_metrics->current_l3clk[i] = metrics.Current.L3Frequency[i]; + } + + gpu_metrics->throttle_status = metrics.Current.ThrottlerStatus; + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v2_2); +} + static const struct pptable_funcs cyan_skillfish_ppt_funcs = { .check_fw_status = smu_v11_0_check_fw_status, .check_fw_version = smu_v11_0_check_fw_version, .init_power = smu_v11_0_init_power, .fini_power = smu_v11_0_fini_power, + .init_smc_tables = cyan_skillfish_init_smc_tables, + .fini_smc_tables = cyan_skillfish_finit_smc_tables, + .read_sensor = cyan_skillfish_read_sensor, + .print_clk_levels = cyan_skillfish_print_clk_levels, + .is_dpm_running = cyan_skillfish_is_dpm_running, + .get_gpu_metrics = cyan_skillfish_get_gpu_metrics, .register_irq_handler = smu_v11_0_register_irq_handler, .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, @@ -72,5 +418,6 @@ void cyan_skillfish_set_ppt_funcs(struct smu_context *smu) { smu->ppt_funcs = &cyan_skillfish_ppt_funcs; smu->message_map = cyan_skillfish_message_map; + smu->table_map = cyan_skillfish_table_map; smu->is_apu = true; } From d4ac13324846f89e0822a629c93cdcb32c73649a Mon Sep 17 00:00:00 2001 From: Lang Yu Date: Fri, 27 Aug 2021 15:20:51 +0800 Subject: [PATCH 052/151] drm/amdgpu: add manual sclk/vddc setting support for cyan skilfish(v3) Add manual sclk/vddc setting supoort via pp_od_clk_voltage sysfs to maintain consistency with other asics. As cyan skillfish doesn't support DPM, there is only a single frequency and voltage to adjust. v2: maintain consistency and add command guide. v3: adjust user settings storage and coding style. Command guide: echo vc point sclk vddc > pp_od_clk_voltage "vc" - sclk voltage curve "point" - must be 0 "sclk" - target value of sclk(MHz), should be in safe range "vddc" - target value of vddc(mV), a 6.25(mV) stepping is recommended and should be in safe range (the real vddc is an approximation of target value) echo c > pp_od_clk_voltage "c" - commit the changes of sclk and vddc, only after the commit command, the target values set by "vc" command will take effect echo r > pp_od_clk_voltage "r" - reset sclk and vddc to default value, a subsequent commit command is needed to take effect Example: 1) Check default sclk and vddc $ cat pp_od_clk_voltage OD_SCLK: 0: 1800Mhz * OD_VDDC: 0: 862mV * OD_RANGE: SCLK: 1000Mhz 2000Mhz VDDC: 700mV 1129mV 2) Set sclk to 1500MHz and vddc to 700mV $ echo vc 0 1500 700 > pp_od_clk_voltage $ echo c > pp_od_clk_voltage $ cat pp_od_clk_voltage OD_SCLK: 0: 1500Mhz * OD_VDDC: 0: 693mV * OD_RANGE: SCLK: 1000Mhz 2000Mhz VDDC: 700mV 1129mV 3) Reset sclk and vddc to default $ echo r > pp_od_clk_voltage $ echo c > pp_od_clk_voltage $ cat pp_od_clk_voltage OD_SCLK: 0: 1800Mhz * OD_VDDC: 0: 874mV * OD_RANGE: SCLK: 1000Mhz 2000Mhz VDDC: 700mV 1129mV NOTE: We don't specify an explicit safe range, you can set any values between min and max at your own risk. Enjoy! Signed-off-by: Lang Yu Reviewed-by: Lijo Lazar Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/inc/smu_types.h | 5 +- .../amd/pm/swsmu/smu11/cyan_skillfish_ppt.c | 134 ++++++++++++++++++ 2 files changed, 138 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/inc/smu_types.h b/drivers/gpu/drm/amd/pm/inc/smu_types.h index 6f1b1b50d527c..18b862a90fbe5 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_types.h @@ -226,7 +226,10 @@ __SMU_DUMMY_MAP(SetUclkDpmMode), \ __SMU_DUMMY_MAP(LightSBR), \ __SMU_DUMMY_MAP(GfxDriverResetRecovery), \ - __SMU_DUMMY_MAP(BoardPowerCalibration), + __SMU_DUMMY_MAP(BoardPowerCalibration), \ + __SMU_DUMMY_MAP(RequestGfxclk), \ + __SMU_DUMMY_MAP(ForceGfxVid), \ + __SMU_DUMMY_MAP(UnforceGfxVid), #undef __SMU_DUMMY_MAP #define __SMU_DUMMY_MAP(type) SMU_MSG_##type diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c index e1fab030cfc50..3d4c65bc29dc3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/cyan_skillfish_ppt.c @@ -44,6 +44,21 @@ #undef pr_info #undef pr_debug +/* unit: MHz */ +#define CYAN_SKILLFISH_SCLK_MIN 1000 +#define CYAN_SKILLFISH_SCLK_MAX 2000 +#define CYAN_SKILLFISH_SCLK_DEFAULT 1800 + +/* unit: mV */ +#define CYAN_SKILLFISH_VDDC_MIN 700 +#define CYAN_SKILLFISH_VDDC_MAX 1129 +#define CYAN_SKILLFISH_VDDC_MAGIC 5118 // 0x13fe + +static struct gfx_user_settings { + uint32_t sclk; + uint32_t vddc; +} cyan_skillfish_user_settings; + #define FEATURE_MASK(feature) (1ULL << feature) #define SMC_DPM_FEATURE ( \ FEATURE_MASK(FEATURE_FCLK_DPM_BIT) | \ @@ -297,6 +312,27 @@ static int cyan_skillfish_print_clk_levels(struct smu_context *smu, smu_cmn_get_sysfs_buf(&buf, &size); switch (clk_type) { + case SMU_OD_SCLK: + ret = cyan_skillfish_get_smu_metrics_data(smu, METRICS_CURR_GFXCLK, &cur_value); + if (ret) + return ret; + size += sysfs_emit_at(buf, size,"%s:\n", "OD_SCLK"); + size += sysfs_emit_at(buf, size, "0: %uMhz *\n", cur_value); + break; + case SMU_OD_VDDC_CURVE: + ret = cyan_skillfish_get_smu_metrics_data(smu, METRICS_VOLTAGE_VDDGFX, &cur_value); + if (ret) + return ret; + size += sysfs_emit_at(buf, size,"%s:\n", "OD_VDDC"); + size += sysfs_emit_at(buf, size, "0: %umV *\n", cur_value); + break; + case SMU_OD_RANGE: + size += sysfs_emit_at(buf, size, "%s:\n", "OD_RANGE"); + size += sysfs_emit_at(buf, size, "SCLK: %7uMhz %10uMhz\n", + CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); + size += sysfs_emit_at(buf, size, "VDDC: %7umV %10umV\n", + CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); + break; case SMU_GFXCLK: case SMU_SCLK: case SMU_FCLK: @@ -394,6 +430,103 @@ static ssize_t cyan_skillfish_get_gpu_metrics(struct smu_context *smu, return sizeof(struct gpu_metrics_v2_2); } +static int cyan_skillfish_od_edit_dpm_table(struct smu_context *smu, + enum PP_OD_DPM_TABLE_COMMAND type, + long input[], uint32_t size) +{ + int ret = 0; + uint32_t vid; + + switch (type) { + case PP_OD_EDIT_VDDC_CURVE: + if (size != 3 || input[0] != 0) { + dev_err(smu->adev->dev, "Invalid parameter!\n"); + return -EINVAL; + } + + if (input[1] <= CYAN_SKILLFISH_SCLK_MIN || + input[1] > CYAN_SKILLFISH_SCLK_MAX) { + dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n", + CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); + return -EINVAL; + } + + if (input[2] <= CYAN_SKILLFISH_VDDC_MIN || + input[2] > CYAN_SKILLFISH_VDDC_MAX) { + dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n", + CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); + return -EINVAL; + } + + cyan_skillfish_user_settings.sclk = input[1]; + cyan_skillfish_user_settings.vddc = input[2]; + + break; + case PP_OD_RESTORE_DEFAULT_TABLE: + if (size != 0) { + dev_err(smu->adev->dev, "Invalid parameter!\n"); + return -EINVAL; + } + + cyan_skillfish_user_settings.sclk = CYAN_SKILLFISH_SCLK_DEFAULT; + cyan_skillfish_user_settings.vddc = CYAN_SKILLFISH_VDDC_MAGIC; + + break; + case PP_OD_COMMIT_DPM_TABLE: + if (size != 0) { + dev_err(smu->adev->dev, "Invalid parameter!\n"); + return -EINVAL; + } + + if (cyan_skillfish_user_settings.sclk < CYAN_SKILLFISH_SCLK_MIN || + cyan_skillfish_user_settings.sclk > CYAN_SKILLFISH_SCLK_MAX) { + dev_err(smu->adev->dev, "Invalid sclk! Valid sclk range: %uMHz - %uMhz\n", + CYAN_SKILLFISH_SCLK_MIN, CYAN_SKILLFISH_SCLK_MAX); + return -EINVAL; + } + + if ((cyan_skillfish_user_settings.vddc != CYAN_SKILLFISH_VDDC_MAGIC) && + (cyan_skillfish_user_settings.vddc < CYAN_SKILLFISH_VDDC_MIN || + cyan_skillfish_user_settings.vddc > CYAN_SKILLFISH_VDDC_MAX)) { + dev_err(smu->adev->dev, "Invalid vddc! Valid vddc range: %umV - %umV\n", + CYAN_SKILLFISH_VDDC_MIN, CYAN_SKILLFISH_VDDC_MAX); + return -EINVAL; + } + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_RequestGfxclk, + cyan_skillfish_user_settings.sclk, NULL); + if (ret) { + dev_err(smu->adev->dev, "Set sclk failed!\n"); + return ret; + } + + if (cyan_skillfish_user_settings.vddc == CYAN_SKILLFISH_VDDC_MAGIC) { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_UnforceGfxVid, NULL); + if (ret) { + dev_err(smu->adev->dev, "Unforce vddc failed!\n"); + return ret; + } + } else { + /* + * PMFW accepts SVI2 VID code, convert voltage to VID: + * vid = (uint32_t)((1.55 - voltage) * 160.0 + 0.00001) + */ + vid = (1550 - cyan_skillfish_user_settings.vddc) * 160 / 1000; + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ForceGfxVid, vid, NULL); + if (ret) { + dev_err(smu->adev->dev, "Force vddc failed!\n"); + return ret; + } + } + + break; + default: + return -EOPNOTSUPP; + } + + return ret; +} + static const struct pptable_funcs cyan_skillfish_ppt_funcs = { .check_fw_status = smu_v11_0_check_fw_status, @@ -406,6 +539,7 @@ static const struct pptable_funcs cyan_skillfish_ppt_funcs = { .print_clk_levels = cyan_skillfish_print_clk_levels, .is_dpm_running = cyan_skillfish_is_dpm_running, .get_gpu_metrics = cyan_skillfish_get_gpu_metrics, + .od_edit_dpm_table = cyan_skillfish_od_edit_dpm_table, .register_irq_handler = smu_v11_0_register_irq_handler, .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, From a7496559e4d101eaaff99ccfd93298e557cc8505 Mon Sep 17 00:00:00 2001 From: xinhui pan Date: Thu, 9 Sep 2021 13:26:49 +0800 Subject: [PATCH 053/151] drm/amdgpu: Increase direct IB pool size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Direct IB pool is used for vce/vcn IB extra msg too. Increase its size to AMDGPU_IB_POOL_SIZE. v2: Squash in unused variable removal Signed-off-by: xinhui pan Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index c076a6b9a5a2e..bc1297dcdf976 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -300,20 +300,15 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, */ int amdgpu_ib_pool_init(struct amdgpu_device *adev) { - unsigned size; int r, i; if (adev->ib_pool_ready) return 0; for (i = 0; i < AMDGPU_IB_POOL_MAX; i++) { - if (i == AMDGPU_IB_POOL_DIRECT) - size = PAGE_SIZE * 6; - else - size = AMDGPU_IB_POOL_SIZE; - r = amdgpu_sa_bo_manager_init(adev, &adev->ib_pools[i], - size, AMDGPU_GPU_PAGE_SIZE, + AMDGPU_IB_POOL_SIZE, + AMDGPU_GPU_PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT); if (r) goto error; From e312af6c2a920b8df2adee1ae31f5c364a4091fb Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Tue, 31 Aug 2021 17:42:15 -0400 Subject: [PATCH 054/151] drm/amdkfd: make needs_pcie_atomics FW-version dependent On some GPUs the PCIe atomic requirement for KFD depends on the MEC firmware version. Add a firmware version check for this. The minimum firmware version that works without atomics can be updated in the device_info structure for each GPU type. Move PCIe atomic detection from kgd2kfd_probe into kgd2kfd_device_init because the MEC firmware is not loaded yet at the probe stage. Signed-off-by: Felix Kuehling Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 44 ++++++++++++++++--------- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 1 + 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 16a57b70cc1a9..30fde852af193 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -468,6 +468,7 @@ static const struct kfd_device_info navi10_device_info = { .needs_iommu_device = false, .supports_cwsr = true, .needs_pci_atomics = true, + .no_atomic_fw_version = 145, .num_sdma_engines = 2, .num_xgmi_sdma_engines = 0, .num_sdma_queues_per_engine = 8, @@ -487,6 +488,7 @@ static const struct kfd_device_info navi12_device_info = { .needs_iommu_device = false, .supports_cwsr = true, .needs_pci_atomics = true, + .no_atomic_fw_version = 145, .num_sdma_engines = 2, .num_xgmi_sdma_engines = 0, .num_sdma_queues_per_engine = 8, @@ -506,6 +508,7 @@ static const struct kfd_device_info navi14_device_info = { .needs_iommu_device = false, .supports_cwsr = true, .needs_pci_atomics = true, + .no_atomic_fw_version = 145, .num_sdma_engines = 2, .num_xgmi_sdma_engines = 0, .num_sdma_queues_per_engine = 8, @@ -525,6 +528,7 @@ static const struct kfd_device_info sienna_cichlid_device_info = { .needs_iommu_device = false, .supports_cwsr = true, .needs_pci_atomics = true, + .no_atomic_fw_version = 92, .num_sdma_engines = 4, .num_xgmi_sdma_engines = 0, .num_sdma_queues_per_engine = 8, @@ -544,6 +548,7 @@ static const struct kfd_device_info navy_flounder_device_info = { .needs_iommu_device = false, .supports_cwsr = true, .needs_pci_atomics = true, + .no_atomic_fw_version = 92, .num_sdma_engines = 2, .num_xgmi_sdma_engines = 0, .num_sdma_queues_per_engine = 8, @@ -562,7 +567,8 @@ static const struct kfd_device_info vangogh_device_info = { .mqd_size_aligned = MQD_SIZE_ALIGNED, .needs_iommu_device = false, .supports_cwsr = true, - .needs_pci_atomics = false, + .needs_pci_atomics = true, + .no_atomic_fw_version = 92, .num_sdma_engines = 1, .num_xgmi_sdma_engines = 0, .num_sdma_queues_per_engine = 2, @@ -582,6 +588,7 @@ static const struct kfd_device_info dimgrey_cavefish_device_info = { .needs_iommu_device = false, .supports_cwsr = true, .needs_pci_atomics = true, + .no_atomic_fw_version = 92, .num_sdma_engines = 2, .num_xgmi_sdma_engines = 0, .num_sdma_queues_per_engine = 8, @@ -601,6 +608,7 @@ static const struct kfd_device_info beige_goby_device_info = { .needs_iommu_device = false, .supports_cwsr = true, .needs_pci_atomics = true, + .no_atomic_fw_version = 92, .num_sdma_engines = 1, .num_xgmi_sdma_engines = 0, .num_sdma_queues_per_engine = 8, @@ -619,7 +627,8 @@ static const struct kfd_device_info yellow_carp_device_info = { .mqd_size_aligned = MQD_SIZE_ALIGNED, .needs_iommu_device = false, .supports_cwsr = true, - .needs_pci_atomics = false, + .needs_pci_atomics = true, + .no_atomic_fw_version = 92, .num_sdma_engines = 1, .num_xgmi_sdma_engines = 0, .num_sdma_queues_per_engine = 2, @@ -708,20 +717,6 @@ struct kfd_dev *kgd2kfd_probe(struct kgd_dev *kgd, if (!kfd) return NULL; - /* Allow BIF to recode atomics to PCIe 3.0 AtomicOps. - * 32 and 64-bit requests are possible and must be - * supported. - */ - kfd->pci_atomic_requested = amdgpu_amdkfd_have_atomics_support(kgd); - if (device_info->needs_pci_atomics && - !kfd->pci_atomic_requested) { - dev_info(kfd_device, - "skipped device %x:%x, PCI rejects atomics\n", - pdev->vendor, pdev->device); - kfree(kfd); - return NULL; - } - kfd->kgd = kgd; kfd->device_info = device_info; kfd->pdev = pdev; @@ -821,6 +816,23 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, kfd->vm_info.vmid_num_kfd = kfd->vm_info.last_vmid_kfd - kfd->vm_info.first_vmid_kfd + 1; + /* Allow BIF to recode atomics to PCIe 3.0 AtomicOps. + * 32 and 64-bit requests are possible and must be + * supported. + */ + kfd->pci_atomic_requested = amdgpu_amdkfd_have_atomics_support(kfd->kgd); + if (!kfd->pci_atomic_requested && + kfd->device_info->needs_pci_atomics && + (!kfd->device_info->no_atomic_fw_version || + kfd->mec_fw_version < kfd->device_info->no_atomic_fw_version)) { + dev_info(kfd_device, + "skipped device %x:%x, PCI rejects atomics %d<%d\n", + kfd->pdev->vendor, kfd->pdev->device, + kfd->mec_fw_version, + kfd->device_info->no_atomic_fw_version); + return false; + } + /* Verify module parameters regarding mapped process number*/ if ((hws_max_conc_proc < 0) || (hws_max_conc_proc > kfd->vm_info.vmid_num_kfd)) { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index ab83b0de6b22d..6d8f9bb2d9057 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -207,6 +207,7 @@ struct kfd_device_info { bool supports_cwsr; bool needs_iommu_device; bool needs_pci_atomics; + uint32_t no_atomic_fw_version; unsigned int num_sdma_engines; unsigned int num_xgmi_sdma_engines; unsigned int num_sdma_queues_per_engine; From b25715a0155dc2b4efb1700aea829eac10832514 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Mon, 9 Aug 2021 13:02:10 -0400 Subject: [PATCH 055/151] drm/amd/display: expose dsc overhead bw in dc dsc header [why] DM needs to know how much overhead is added to DSC as result of AMD internal DSC limitation. Acked-by: Mikita Lipski Signed-off-by: Wenjing Liu Reviewed-by: George Shen Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_dsc.h | 5 ++ drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 69 ++++++++++----------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dsc.h b/drivers/gpu/drm/amd/display/dc/dc_dsc.h index 16cc76ce3739d..c8cc6a448c363 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dsc.h @@ -81,6 +81,11 @@ bool dc_dsc_compute_config( uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing, uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp); +uint32_t dc_dsc_stream_bandwidth_overhead_in_kbps( + const struct dc_crtc_timing *timing, + const int num_slices_h, + const bool is_dp); + void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, uint32_t max_target_bpp_limit_override_x16, struct dc_dsc_policy *policy); diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index f5b7da0e64c07..1e30a742ae01c 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -76,11 +76,6 @@ static bool setup_dsc_config( int max_dsc_target_bpp_limit_override_x16, struct dc_dsc_config *dsc_cfg); -static struct fixed31_32 compute_dsc_max_bandwidth_overhead( - const struct dc_crtc_timing *timing, - const int num_slices_h, - const bool is_dp); - static bool dsc_buff_block_size_from_dpcd(int dpcd_buff_block_size, int *buff_block_size) { @@ -462,32 +457,6 @@ static inline uint32_t dsc_div_by_10_round_up(uint32_t value) return (value + 9) / 10; } -static struct fixed31_32 compute_dsc_max_bandwidth_overhead( - const struct dc_crtc_timing *timing, - const int num_slices_h, - const bool is_dp) -{ - struct fixed31_32 max_dsc_overhead; - struct fixed31_32 refresh_rate; - - if (dsc_policy_disable_dsc_stream_overhead || !is_dp) - return dc_fixpt_from_int(0); - - /* use target bpp that can take entire target bandwidth */ - refresh_rate = dc_fixpt_from_int(timing->pix_clk_100hz); - refresh_rate = dc_fixpt_div_int(refresh_rate, timing->h_total); - refresh_rate = dc_fixpt_div_int(refresh_rate, timing->v_total); - refresh_rate = dc_fixpt_mul_int(refresh_rate, 100); - - max_dsc_overhead = dc_fixpt_from_int(num_slices_h); - max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, timing->v_total); - max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, 256); - max_dsc_overhead = dc_fixpt_div_int(max_dsc_overhead, 1000); - max_dsc_overhead = dc_fixpt_mul(max_dsc_overhead, refresh_rate); - - return max_dsc_overhead; -} - static uint32_t compute_bpp_x16_from_target_bandwidth( const uint32_t bandwidth_in_kbps, const struct dc_crtc_timing *timing, @@ -495,14 +464,14 @@ static uint32_t compute_bpp_x16_from_target_bandwidth( const uint32_t bpp_increment_div, const bool is_dp) { - struct fixed31_32 overhead_in_kbps; + uint32_t overhead_in_kbps; struct fixed31_32 effective_bandwidth_in_kbps; struct fixed31_32 bpp_x16; - overhead_in_kbps = compute_dsc_max_bandwidth_overhead( + overhead_in_kbps = dc_dsc_stream_bandwidth_overhead_in_kbps( timing, num_slices_h, is_dp); effective_bandwidth_in_kbps = dc_fixpt_from_int(bandwidth_in_kbps); - effective_bandwidth_in_kbps = dc_fixpt_sub(effective_bandwidth_in_kbps, + effective_bandwidth_in_kbps = dc_fixpt_sub_int(effective_bandwidth_in_kbps, overhead_in_kbps); bpp_x16 = dc_fixpt_mul_int(effective_bandwidth_in_kbps, 10); bpp_x16 = dc_fixpt_div_int(bpp_x16, timing->pix_clk_100hz); @@ -994,19 +963,45 @@ bool dc_dsc_compute_config( uint32_t dc_dsc_stream_bandwidth_in_kbps(const struct dc_crtc_timing *timing, uint32_t bpp_x16, uint32_t num_slices_h, bool is_dp) { - struct fixed31_32 overhead_in_kbps; + uint32_t overhead_in_kbps; struct fixed31_32 bpp; struct fixed31_32 actual_bandwidth_in_kbps; - overhead_in_kbps = compute_dsc_max_bandwidth_overhead( + overhead_in_kbps = dc_dsc_stream_bandwidth_overhead_in_kbps( timing, num_slices_h, is_dp); bpp = dc_fixpt_from_fraction(bpp_x16, 16); actual_bandwidth_in_kbps = dc_fixpt_from_fraction(timing->pix_clk_100hz, 10); actual_bandwidth_in_kbps = dc_fixpt_mul(actual_bandwidth_in_kbps, bpp); - actual_bandwidth_in_kbps = dc_fixpt_add(actual_bandwidth_in_kbps, overhead_in_kbps); + actual_bandwidth_in_kbps = dc_fixpt_add_int(actual_bandwidth_in_kbps, overhead_in_kbps); return dc_fixpt_ceil(actual_bandwidth_in_kbps); } +uint32_t dc_dsc_stream_bandwidth_overhead_in_kbps( + const struct dc_crtc_timing *timing, + const int num_slices_h, + const bool is_dp) +{ + struct fixed31_32 max_dsc_overhead; + struct fixed31_32 refresh_rate; + + if (dsc_policy_disable_dsc_stream_overhead || !is_dp) + return 0; + + /* use target bpp that can take entire target bandwidth */ + refresh_rate = dc_fixpt_from_int(timing->pix_clk_100hz); + refresh_rate = dc_fixpt_div_int(refresh_rate, timing->h_total); + refresh_rate = dc_fixpt_div_int(refresh_rate, timing->v_total); + refresh_rate = dc_fixpt_mul_int(refresh_rate, 100); + + max_dsc_overhead = dc_fixpt_from_int(num_slices_h); + max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, timing->v_total); + max_dsc_overhead = dc_fixpt_mul_int(max_dsc_overhead, 256); + max_dsc_overhead = dc_fixpt_div_int(max_dsc_overhead, 1000); + max_dsc_overhead = dc_fixpt_mul(max_dsc_overhead, refresh_rate); + + return dc_fixpt_ceil(max_dsc_overhead); +} + void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, uint32_t max_target_bpp_limit_override_x16, struct dc_dsc_policy *policy) From 3550d6225b1ff8ce0429ad889848dc789edf56e8 Mon Sep 17 00:00:00 2001 From: "Leo (Hanghong) Ma" Date: Sun, 15 Aug 2021 14:17:25 -0400 Subject: [PATCH 056/151] drm/amd/display: Add DPCD writes at key points This reverts commit "Revert "Add DPCD writes at key points" ". The following patch will fix the system hang issue. v2: squash in indentation warning fix Signed-off-by: Leo (Hanghong) Ma Acked-by: Mikita Lipski Reviewed-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 7 ++++++ .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 +++---- .../drm/amd/display/dc/core/dc_link_hwss.c | 13 ++++++++++- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../amd/display/dc/dce/dce_stream_encoder.c | 2 ++ .../display/dc/dce110/dce110_hw_sequencer.c | 22 ++++++++++++++----- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 4 ++-- .../display/dc/dcn10/dcn10_stream_encoder.c | 10 +++++++++ .../display/dc/dcn10/dcn10_stream_encoder.h | 2 ++ .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 10 ++++++++- .../display/dc/dcn20/dcn20_stream_encoder.c | 5 +++++ .../display/dc/dcn20/dcn20_stream_encoder.h | 1 + .../drm/amd/display/dc/dcn30/dcn30_hwseq.c | 2 +- .../drm/amd/display/dc/dcn31/dcn31_hwseq.c | 2 +- .../amd/display/dc/inc/hw/stream_encoder.h | 2 ++ .../gpu/drm/amd/display/dc/inc/link_hwss.h | 1 + .../dc/virtual/virtual_stream_encoder.c | 2 ++ .../gpu/drm/amd/display/include/dpcd_defs.h | 1 + .../amd/display/include/link_service_types.h | 16 ++++++++++++++ 19 files changed, 96 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 54ff4fb1ea032..f1c9ee53ac676 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3572,6 +3572,7 @@ void core_link_enable_stream( { struct dc *dc = pipe_ctx->stream->ctx->dc; struct dc_stream_state *stream = pipe_ctx->stream; + struct dc_link *link = stream->sink->link; enum dc_status status; #if defined(CONFIG_DRM_AMD_DC_DCN) enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO; @@ -3624,6 +3625,9 @@ void core_link_enable_stream( stream->link->dpcd_caps.dprx_feature.bits.SST_SPLIT_SDP_CAP); #endif + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR); + if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->hdmi_set_stream_attribute( pipe_ctx->stream_res.stream_enc, @@ -3659,6 +3663,9 @@ void core_link_enable_stream( resource_build_info_frame(pipe_ctx); dc->hwss.update_info_frame(pipe_ctx); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); + /* Do not touch link on seamless boot optimization. */ if (pipe_ctx->stream->apply_seamless_boot_optimization) { pipe_ctx->stream->dpms_off = false; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index e412a096a4b82..3b68d77404986 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2370,11 +2370,11 @@ bool perform_link_training_with_retries( /* We need to do this before the link training to ensure the idle pattern in SST * mode will be sent right after the link training */ -#if defined(CONFIG_DRM_AMD_DC_DCN) - if (dp_get_link_encoding_format(¤t_setting) == DP_8b_10b_ENCODING) -#endif + if (dp_get_link_encoding_format(¤t_setting) == DP_8b_10b_ENCODING) { link_enc->funcs->connect_dig_be_to_fe(link_enc, pipe_ctx->stream_res.stream_enc->id, true); + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE); + } for (j = 0; j < attempts; ++j) { @@ -5267,7 +5267,7 @@ bool dc_link_dp_set_test_pattern( * MuteAudioEndpoint(pPathMode->pDisplayPath, true); */ /* Blank stream */ - pipes->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); + pipes->stream_res.stream_enc->funcs->dp_blank(link, pipe_ctx->stream_res.stream_enc); } dp_set_hw_test_pattern(link, test_pattern, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 29b9c128c87c9..58abfa5a7bacf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -62,6 +62,13 @@ void dp_receiver_power_ctrl(struct dc_link *link, bool on) sizeof(state)); } +void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode) +{ + if (link->dc->debug.enable_driver_sequence_debug) + core_link_write_dpcd(link, DP_SOURCE_SEQUENCE, + &dp_test_mode, sizeof(dp_test_mode)); +} + void dp_enable_link_phy( struct dc_link *link, enum signal_type signal, @@ -158,6 +165,7 @@ void dp_enable_link_phy( if (dmcu != NULL && dmcu->funcs->unlock_phy) dmcu->funcs->unlock_phy(dmcu); + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY); dp_receiver_power_ctrl(link, true); } @@ -276,6 +284,8 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) dmcu->funcs->unlock_phy(dmcu); } + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY); + /* Clear current link setting.*/ memset(&link->cur_link_settings, 0, sizeof(link->cur_link_settings)); @@ -407,6 +417,7 @@ void dp_set_hw_test_pattern( #else encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param); #endif + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN); } #if defined(CONFIG_DRM_AMD_DC_DCN) #undef DC_LOGGER @@ -428,7 +439,7 @@ void dp_retrain_link_dp_test(struct dc_link *link, pipes[i].stream->link == link) { udelay(100); - pipes[i].stream_res.stream_enc->funcs->dp_blank( + pipes[i].stream_res.stream_enc->funcs->dp_blank(link, pipes[i].stream_res.stream_enc); /* disable any test pattern that might be active */ diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0505081e4fe83..bcae2250a574e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -643,6 +643,7 @@ struct dc_debug_options { bool force_enable_edp_fec; /* FEC/PSR1 sequence enable delay in 100us */ uint8_t fec_enable_delay_in100us; + bool enable_driver_sequence_debug; #if defined(CONFIG_DRM_AMD_DC_DCN) bool disable_z10; bool enable_sw_cntl_psr; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index 8d4263da59f25..779bc92a2968e 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c @@ -919,6 +919,7 @@ static void dce110_stream_encoder_stop_dp_info_packets( } static void dce110_stream_encoder_dp_blank( + struct dc_link *link, struct stream_encoder *enc) { struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); @@ -967,6 +968,7 @@ static void dce110_stream_encoder_dp_blank( /* output video stream to link encoder */ static void dce110_stream_encoder_dp_unblank( + struct dc_link *link, struct stream_encoder *enc, const struct encoder_unblank_param *param) { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index f660472e71fb3..cf8fee721f30a 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -57,7 +57,8 @@ #include "audio.h" #include "reg_helper.h" #include "panel_cntl.h" - +#include "inc/link_dpcd.h" +#include "dpcd_defs.h" /* include DCE11 register header files */ #include "dce/dce_11_0_d.h" #include "dce/dce_11_0_sh_mask.h" @@ -1122,6 +1123,9 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) if (pipe_ctx->stream_res.audio) pipe_ctx->stream_res.audio->enabled = true; } + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM); } void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx) @@ -1178,6 +1182,9 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx) * stream->stream_engine_id); */ } + + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM); } void dce110_disable_stream(struct pipe_ctx *pipe_ctx) @@ -1224,7 +1231,8 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.stream_enc->id, false); #endif - + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE); } void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, @@ -1240,7 +1248,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, params.link_settings.link_rate = link_settings->link_rate; if (dc_is_dp_signal(pipe_ctx->stream->signal)) - pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); + pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms); if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { hws->funcs.edp_backlight_control(link, true); @@ -1267,7 +1275,7 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx) #else if (dc_is_dp_signal(pipe_ctx->stream->signal)) { #endif - pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); + pipe_ctx->stream_res.stream_enc->funcs->dp_blank(link, pipe_ctx->stream_res.stream_enc); if (!dc_is_embedded_signal(pipe_ctx->stream->signal)) { /* @@ -1492,6 +1500,7 @@ static enum dc_status apply_single_controller_ctx_to_hw( struct dc *dc) { struct dc_stream_state *stream = pipe_ctx->stream; + struct dc_link *link = stream->link; struct drr_params params = {0}; unsigned int event_triggers = 0; struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe; @@ -1576,6 +1585,9 @@ static enum dc_status apply_single_controller_ctx_to_hw( pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.tg->inst); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_OTG); + pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion( pipe_ctx->stream_res.opp, COLOR_SPACE_YCBCR601, @@ -1632,7 +1644,7 @@ static void power_down_encoders(struct dc *dc) * hurt for non-DP */ for (i = 0; i < dc->res_pool->stream_enc_count; i++) { - dc->res_pool->stream_enc[i]->funcs->dp_blank( + dc->res_pool->stream_enc[i]->funcs->dp_blank(dc->links[i], dc->res_pool->stream_enc[i]); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 70d47773c23c9..b4cf2e92694c0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1489,7 +1489,7 @@ void dcn10_init_hw(struct dc *dc) for (j = 0; j < dc->res_pool->stream_enc_count; j++) { if (fe == dc->res_pool->stream_enc[j]->id) { - dc->res_pool->stream_enc[j]->funcs->dp_blank( + dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i], dc->res_pool->stream_enc[j]); break; } @@ -3678,7 +3678,7 @@ void dcn10_unblank_stream(struct pipe_ctx *pipe_ctx, if (dc_is_dp_signal(pipe_ctx->stream->signal)) { if (params.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) params.timing.pix_clk_100hz /= 2; - pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); + pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms); } if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index bccefb6c22c84..b7d55212dc8f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -29,6 +29,8 @@ #include "dcn10_stream_encoder.h" #include "reg_helper.h" #include "hw_shared.h" +#include "inc/link_dpcd.h" +#include "dpcd_defs.h" #define DC_LOGGER \ enc1->base.ctx->logger @@ -894,6 +896,7 @@ void enc1_stream_encoder_stop_dp_info_packets( } void enc1_stream_encoder_dp_blank( + struct dc_link *link, struct stream_encoder *enc) { struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); @@ -924,6 +927,8 @@ void enc1_stream_encoder_dp_blank( /* disable DP stream */ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0); + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_DISABLE_DP_VID_STREAM); + /* the encoder stops sending the video stream * at the start of the vertical blanking. * Poll for DP_VID_STREAM_STATUS == 0 @@ -940,10 +945,13 @@ void enc1_stream_encoder_dp_blank( */ REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, true); + + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_FIFO_STEER_RESET); } /* output video stream to link encoder */ void enc1_stream_encoder_dp_unblank( + struct dc_link *link, struct stream_encoder *enc, const struct encoder_unblank_param *param) { @@ -1010,6 +1018,8 @@ void enc1_stream_encoder_dp_unblank( */ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); + + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); } void enc1_stream_encoder_set_avmute( diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h index 0d86df97878ca..687d7e4bf7cad 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h @@ -627,9 +627,11 @@ void enc1_stream_encoder_stop_dp_info_packets( struct stream_encoder *enc); void enc1_stream_encoder_dp_blank( + struct dc_link *link, struct stream_encoder *enc); void enc1_stream_encoder_dp_unblank( + struct dc_link *link, struct stream_encoder *enc, const struct encoder_unblank_param *param); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index b9276da878723..ffc0b9ab976f1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -52,6 +52,8 @@ #include "dc_dmub_srv.h" #include "dce/dmub_hw_lock_mgr.h" #include "hw_sequencer.h" +#include "inc/link_dpcd.h" +#include "dpcd_defs.h" #define DC_LOGGER_INIT(logger) @@ -2145,7 +2147,7 @@ void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx, params.timing.pix_clk_100hz /= 2; pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine( pipe_ctx->stream_res.stream_enc, params.opp_cnt > 1); - pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms); + pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(link, pipe_ctx->stream_res.stream_enc, ¶ms); } if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { @@ -2399,6 +2401,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc, pipe_ctx->stream_res.stream_enc->id, true); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE); + if (pipe_ctx->plane_state && pipe_ctx->plane_state->flip_immediate != 1) { if (link->dc->hwss.program_dmdata_engine) link->dc->hwss.program_dmdata_engine(pipe_ctx); @@ -2406,6 +2411,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) link->dc->hwss.update_info_frame(pipe_ctx); + if (dc_is_dp_signal(pipe_ctx->stream->signal)) + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME); + /* enable early control to avoid corruption on DP monitor*/ active_total_with_borders = timing->h_addressable diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c index e6307397e0d2a..44f31b7b9ac90 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c @@ -29,6 +29,8 @@ #include "dcn20_stream_encoder.h" #include "reg_helper.h" #include "hw_shared.h" +#include "inc/link_dpcd.h" +#include "dpcd_defs.h" #define DC_LOGGER \ enc1->base.ctx->logger @@ -444,6 +446,7 @@ static bool is_two_pixels_per_containter(const struct dc_crtc_timing *timing) } void enc2_stream_encoder_dp_unblank( + struct dc_link *link, struct stream_encoder *enc, const struct encoder_unblank_param *param) { @@ -522,6 +525,8 @@ void enc2_stream_encoder_dp_unblank( */ REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, true); + + dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); } static void enc2_dp_set_odm_combine( diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h index f3d1a0237bda0..baa1e539f3418 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.h @@ -104,6 +104,7 @@ void enc2_stream_encoder_dp_set_stream_attribute( uint32_t enable_sdp_splitting); void enc2_stream_encoder_dp_unblank( + struct dc_link *link, struct stream_encoder *enc, const struct encoder_unblank_param *param); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index fafed1e4a998d..b132ebed09d4a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -559,7 +559,7 @@ void dcn30_init_hw(struct dc *dc) for (j = 0; j < dc->res_pool->stream_enc_count; j++) { if (fe == dc->res_pool->stream_enc[j]->id) { - dc->res_pool->stream_enc[j]->funcs->dp_blank( + dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i], dc->res_pool->stream_enc[j]); break; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c index 3f2333ec67e22..7feba8a0d8477 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c @@ -194,7 +194,7 @@ void dcn31_init_hw(struct dc *dc) for (j = 0; j < dc->res_pool->stream_enc_count; j++) { if (fe == dc->res_pool->stream_enc[j]->id) { - dc->res_pool->stream_enc[j]->funcs->dp_blank( + dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i], dc->res_pool->stream_enc[j]); break; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 40a138a9593fe..9f03fda5b9658 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -165,9 +165,11 @@ struct stream_encoder_funcs { struct stream_encoder *enc); void (*dp_blank)( + struct dc_link *link, struct stream_encoder *enc); void (*dp_unblank)( + struct dc_link *link, struct stream_encoder *enc, const struct encoder_unblank_param *param); diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h index fc1d289bb9fe6..ba664bc495957 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h @@ -37,6 +37,7 @@ void dp_enable_link_phy( const struct dc_link_settings *link_settings); void dp_receiver_power_ctrl(struct dc_link *link, bool on); +void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode); void edp_add_delay_for_T9(struct dc_link *link); bool edp_receiver_ready_T9(struct dc_link *link); bool edp_receiver_ready_T7(struct dc_link *link); diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c index 1053b165c1391..42a29b712e0e6 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c @@ -69,9 +69,11 @@ static void virtual_stream_encoder_stop_dp_info_packets( struct stream_encoder *enc) {} static void virtual_stream_encoder_dp_blank( + struct dc_link *link, struct stream_encoder *enc) {} static void virtual_stream_encoder_dp_unblank( + struct dc_link *link, struct stream_encoder *enc, const struct encoder_unblank_param *param) {} diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h index 6fb7c0145cb6f..ffd0df1701e64 100644 --- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h +++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h @@ -165,6 +165,7 @@ enum dpcd_psr_sink_states { PSR_SINK_STATE_SINK_INTERNAL_ERROR = 7, }; +#define DP_SOURCE_SEQUENCE 0x30c #define DP_SOURCE_TABLE_REVISION 0x310 #define DP_SOURCE_PAYLOAD_SIZE 0x311 #define DP_SOURCE_SINK_CAP 0x317 diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index c729b50c4f20c..9ffea7b405454 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -191,6 +191,22 @@ enum dp_panel_mode { DP_PANEL_MODE_SPECIAL }; +enum dpcd_source_sequence { + DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_OTG = 1, /*done in apply_single_controller_ctx_to_hw */ + DPCD_SOURCE_SEQ_AFTER_DP_STREAM_ATTR, /*done in core_link_enable_stream */ + DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME, /*done in core_link_enable_stream/dcn20_enable_stream */ + DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE, /*done in perform_link_training_with_retries/dcn20_enable_stream */ + DPCD_SOURCE_SEQ_AFTER_ENABLE_LINK_PHY, /*done in dp_enable_link_phy */ + DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN, /*done in dp_set_hw_test_pattern */ + DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM, /*done in dce110_enable_audio_stream */ + DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM, /*done in enc1_stream_encoder_dp_unblank */ + DPCD_SOURCE_SEQ_AFTER_DISABLE_DP_VID_STREAM, /*done in enc1_stream_encoder_dp_blank */ + DPCD_SOURCE_SEQ_AFTER_FIFO_STEER_RESET, /*done in enc1_stream_encoder_dp_blank */ + DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM, /*done in dce110_disable_audio_stream */ + DPCD_SOURCE_SEQ_AFTER_DISABLE_LINK_PHY, /*done in dp_disable_link_phy */ + DPCD_SOURCE_SEQ_AFTER_DISCONNECT_DIG_FE_BE, /*done in dce110_disable_stream */ +}; + /* DPCD_ADDR_TRAINING_LANEx_SET registers value */ union dpcd_training_lane_set { struct { From 952ab0b302396bd6cba0859c585208882389807d Mon Sep 17 00:00:00 2001 From: "Leo (Hanghong) Ma" Date: Mon, 16 Aug 2021 14:35:59 -0400 Subject: [PATCH 057/151] drm/amd/display: Fix system hang at boot [Why] During DQE's promotion test, system hang issue is found on linux system; [How] 1. Add NULL pointor check for the link in the sequence trace function; 2. Get the right link for the stream encoder before blank DP stream; Acked-by: Mikita Lipski Signed-off-by: Leo (Hanghong) Ma Reviewed-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/core/dc_link_hwss.c | 2 +- .../display/dc/dce110/dce110_hw_sequencer.c | 27 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 58abfa5a7bacf..b9570b7c557b6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -64,7 +64,7 @@ void dp_receiver_power_ctrl(struct dc_link *link, bool on) void dp_source_sequence_trace(struct dc_link *link, uint8_t dp_test_mode) { - if (link->dc->debug.enable_driver_sequence_debug) + if (link != NULL && link->dc->debug.enable_driver_sequence_debug) core_link_write_dpcd(link, DP_SOURCE_SEQUENCE, &dp_test_mode, sizeof(dp_test_mode)); } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index cf8fee721f30a..2ce668a23fe8b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1638,23 +1638,30 @@ static enum dc_status apply_single_controller_ctx_to_hw( static void power_down_encoders(struct dc *dc) { - int i; - - /* do not know BIOS back-front mapping, simply blank all. It will not - * hurt for non-DP - */ - for (i = 0; i < dc->res_pool->stream_enc_count; i++) { - dc->res_pool->stream_enc[i]->funcs->dp_blank(dc->links[i], - dc->res_pool->stream_enc[i]); - } + int i, j; for (i = 0; i < dc->link_count; i++) { enum signal_type signal = dc->links[i]->connector_signal; if ((signal == SIGNAL_TYPE_EDP) || - (signal == SIGNAL_TYPE_DISPLAY_PORT)) + (signal == SIGNAL_TYPE_DISPLAY_PORT)) { + if (dc->links[i]->link_enc->funcs->get_dig_frontend && + dc->links[i]->link_enc->funcs->is_dig_enabled(dc->links[i]->link_enc)) { + unsigned int fe = dc->links[i]->link_enc->funcs->get_dig_frontend( + dc->links[i]->link_enc); + + for (j = 0; j < dc->res_pool->stream_enc_count; j++) { + if (fe == dc->res_pool->stream_enc[j]->id) { + dc->res_pool->stream_enc[j]->funcs->dp_blank(dc->links[i], + dc->res_pool->stream_enc[j]); + break; + } + } + } + if (!dc->links[i]->wa_flags.dp_keep_receiver_powered) dp_receiver_power_ctrl(dc->links[i], false); + } if (signal != SIGNAL_TYPE_EDP) signal = SIGNAL_TYPE_NONE; From e0d09634acbbd0e217876e51d1a4d2d2a9397bc2 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Mon, 9 Aug 2021 17:00:12 -0400 Subject: [PATCH 058/151] drm/amd/display: move bpp range decision in decide dsc bw range function [why] Before get dsc bw range is used to compute DSC bw range based on the given fixed bpp min/max input. The new change will merge any specs, signal, timing specific bpp range decision into this function. So the function needs to make a decision with all aspects considered. Acked-by: Mikita Lipski Signed-off-by: Wenjing Liu Reviewed-by: George Shen Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_dsc.h | 6 +- drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 126 ++++++++++---------- 2 files changed, 69 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dsc.h b/drivers/gpu/drm/amd/display/dc/dc_dsc.h index c8cc6a448c363..684713b2cff74 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dsc.h @@ -51,7 +51,6 @@ struct dc_dsc_policy { int min_slice_height; // Must not be less than 8 uint32_t max_target_bpp; uint32_t min_target_bpp; - uint32_t preferred_bpp_x16; bool enable_dsc_when_not_needed; }; @@ -86,6 +85,11 @@ uint32_t dc_dsc_stream_bandwidth_overhead_in_kbps( const int num_slices_h, const bool is_dp); +/* TODO - Hardware/specs limitation should be owned by dc dsc and returned to DM, + * and DM can choose to OVERRIDE the limitation on CASE BY CASE basis. + * Hardware/specs limitation should not be writable by DM. + * It should be decoupled from DM specific policy and named differently. + */ void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, uint32_t max_target_bpp_limit_override_x16, struct dc_dsc_policy *policy); diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index 1e30a742ae01c..0321b4446e056 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -40,8 +40,15 @@ static bool dsc_policy_enable_dsc_when_not_needed; static bool dsc_policy_disable_dsc_stream_overhead; +#ifndef MAX +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#endif +#ifndef MIN +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#endif + /* Forward Declerations */ -static void get_dsc_bandwidth_range( +static bool decide_dsc_bandwidth_range( const uint32_t min_bpp_x16, const uint32_t max_bpp_x16, const uint32_t num_slices_h, @@ -356,7 +363,7 @@ bool dc_dsc_compute_bandwidth_range( dsc_min_slice_height_override, max_bpp_x16, &config); if (is_dsc_possible) - get_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16, + is_dsc_possible = decide_dsc_bandwidth_range(min_bpp_x16, max_bpp_x16, config.num_slices_h, &dsc_common_caps, timing, range); return is_dsc_possible; @@ -481,10 +488,12 @@ static uint32_t compute_bpp_x16_from_target_bandwidth( return dc_fixpt_floor(bpp_x16); } -/* Get DSC bandwidth range based on [min_bpp, max_bpp] target bitrate range, and timing's pixel clock - * and uncompressed bandwidth. +/* Decide DSC bandwidth range based on signal, timing, specs specific and input min and max + * requirements. + * The range output includes decided min/max target bpp, the respective bandwidth requirements + * and native timing bandwidth requirement when DSC is not used. */ -static void get_dsc_bandwidth_range( +static bool decide_dsc_bandwidth_range( const uint32_t min_bpp_x16, const uint32_t max_bpp_x16, const uint32_t num_slices_h, @@ -492,39 +501,45 @@ static void get_dsc_bandwidth_range( const struct dc_crtc_timing *timing, struct dc_dsc_bw_range *range) { - /* native stream bandwidth */ - range->stream_kbps = dc_bandwidth_in_kbps_from_timing(timing); - - /* max dsc target bpp */ - range->max_kbps = dc_dsc_stream_bandwidth_in_kbps(timing, - max_bpp_x16, num_slices_h, dsc_caps->is_dp); - range->max_target_bpp_x16 = max_bpp_x16; - if (range->max_kbps > range->stream_kbps) { - /* max dsc target bpp is capped to native bandwidth */ - range->max_kbps = range->stream_kbps; - range->max_target_bpp_x16 = compute_bpp_x16_from_target_bandwidth( - range->max_kbps, timing, num_slices_h, - dsc_caps->bpp_increment_div, - dsc_caps->is_dp); + uint32_t preferred_bpp_x16 = timing->dsc_fixed_bits_per_pixel_x16; + + memset(range, 0, sizeof(*range)); + + /* apply signal, timing, specs and explicitly specified DSC range requirements */ + if (preferred_bpp_x16) { + if (preferred_bpp_x16 <= max_bpp_x16 && + preferred_bpp_x16 >= min_bpp_x16) { + range->max_target_bpp_x16 = preferred_bpp_x16; + range->min_target_bpp_x16 = preferred_bpp_x16; + } + } + else { + range->max_target_bpp_x16 = max_bpp_x16; + range->min_target_bpp_x16 = min_bpp_x16; } - /* min dsc target bpp */ - range->min_kbps = dc_dsc_stream_bandwidth_in_kbps(timing, - min_bpp_x16, num_slices_h, dsc_caps->is_dp); - range->min_target_bpp_x16 = min_bpp_x16; - if (range->min_kbps > range->max_kbps) { - /* min dsc target bpp is capped to max dsc bandwidth*/ - range->min_kbps = range->max_kbps; - range->min_target_bpp_x16 = range->max_target_bpp_x16; + /* populate output structure */ + if (range->max_target_bpp_x16 >= range->min_target_bpp_x16 && range->min_target_bpp_x16 > 0) { + /* native stream bandwidth */ + range->stream_kbps = dc_bandwidth_in_kbps_from_timing(timing); + + /* max dsc target bpp */ + range->max_kbps = dc_dsc_stream_bandwidth_in_kbps(timing, + range->max_target_bpp_x16, num_slices_h, dsc_caps->is_dp); + + /* min dsc target bpp */ + range->min_kbps = dc_dsc_stream_bandwidth_in_kbps(timing, + range->min_target_bpp_x16, num_slices_h, dsc_caps->is_dp); } + + return range->max_kbps >= range->min_kbps && range->min_kbps > 0; } /* Decides if DSC should be used and calculates target bpp if it should, applying DSC policy. * * Returns: - * - 'true' if DSC was required by policy and was successfully applied - * - 'false' if DSC was not necessary (e.g. if uncompressed stream fits 'target_bandwidth_kbps'), - * or if it couldn't be applied based on DSC policy. + * - 'true' if target bpp is decided + * - 'false' if target bpp cannot be decided (e.g. cannot fit even with min DSC bpp), */ static bool decide_dsc_target_bpp_x16( const struct dc_dsc_policy *policy, @@ -534,40 +549,29 @@ static bool decide_dsc_target_bpp_x16( const int num_slices_h, int *target_bpp_x16) { - bool should_use_dsc = false; struct dc_dsc_bw_range range; - memset(&range, 0, sizeof(range)); - - get_dsc_bandwidth_range(policy->min_target_bpp * 16, policy->max_target_bpp * 16, - num_slices_h, dsc_common_caps, timing, &range); - if (!policy->enable_dsc_when_not_needed && target_bandwidth_kbps >= range.stream_kbps) { - /* enough bandwidth without dsc */ - *target_bpp_x16 = 0; - should_use_dsc = false; - } else if (policy->preferred_bpp_x16 > 0 && - policy->preferred_bpp_x16 <= range.max_target_bpp_x16 && - policy->preferred_bpp_x16 >= range.min_target_bpp_x16) { - *target_bpp_x16 = policy->preferred_bpp_x16; - should_use_dsc = true; - } else if (target_bandwidth_kbps >= range.max_kbps) { - /* use max target bpp allowed */ - *target_bpp_x16 = range.max_target_bpp_x16; - should_use_dsc = true; - } else if (target_bandwidth_kbps >= range.min_kbps) { - /* use target bpp that can take entire target bandwidth */ - *target_bpp_x16 = compute_bpp_x16_from_target_bandwidth( - target_bandwidth_kbps, timing, num_slices_h, - dsc_common_caps->bpp_increment_div, - dsc_common_caps->is_dp); - should_use_dsc = true; - } else { - /* not enough bandwidth to fulfill minimum requirement */ - *target_bpp_x16 = 0; - should_use_dsc = false; + *target_bpp_x16 = 0; + + if (decide_dsc_bandwidth_range(policy->min_target_bpp * 16, policy->max_target_bpp * 16, + num_slices_h, dsc_common_caps, timing, &range)) { + if (target_bandwidth_kbps >= range.stream_kbps) { + if (policy->enable_dsc_when_not_needed) + /* enable max bpp even dsc is not needed */ + *target_bpp_x16 = range.max_target_bpp_x16; + } else if (target_bandwidth_kbps >= range.max_kbps) { + /* use max target bpp allowed */ + *target_bpp_x16 = range.max_target_bpp_x16; + } else if (target_bandwidth_kbps >= range.min_kbps) { + /* use target bpp that can take entire target bandwidth */ + *target_bpp_x16 = compute_bpp_x16_from_target_bandwidth( + target_bandwidth_kbps, timing, num_slices_h, + dsc_common_caps->bpp_increment_div, + dsc_common_caps->is_dp); + } } - return should_use_dsc; + return *target_bpp_x16 != 0; } #define MIN_AVAILABLE_SLICES_SIZE 4 @@ -1059,8 +1063,6 @@ void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, return; } - policy->preferred_bpp_x16 = timing->dsc_fixed_bits_per_pixel_x16; - /* internal upper limit, default 16 bpp */ if (policy->max_target_bpp > dsc_policy_max_target_bpp_limit) policy->max_target_bpp = dsc_policy_max_target_bpp_limit; From 928adbf65bb1f813487164edde6293bf42d8f195 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Fri, 13 Aug 2021 19:49:43 -0400 Subject: [PATCH 059/151] drm/amd/display: update conditions to do dfp cap ext validation [why] According to DP specs dfp cap ext validation is only for branch device withou 128b/132b channel coding support and downstream of the branch device doesn't have compression. Therefore we are adding conditions to only do dfp cap extension validation for branch devcie supporting 8b/10b channel coding only and it has no DSC passthrough capability. Acked-by: Mikita Lipski Signed-off-by: Wenjing Liu Reviewed-by: George Shen Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index f1c9ee53ac676..5d9460e0dbabf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2606,7 +2606,9 @@ static bool dp_active_dongle_validate_timing( #if defined(CONFIG_DRM_AMD_DC_DCN) } - if (dongle_caps->dfp_cap_ext.supported) { + if (dpcd_caps->channel_coding_cap.bits.DP_128b_132b_SUPPORTED == 0 && + dpcd_caps->dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT == 0 && + dongle_caps->dfp_cap_ext.supported) { if (dongle_caps->dfp_cap_ext.max_pixel_rate_in_mps < (timing->pix_clk_100hz / 10000)) return false; From 410ad92d7fecd30de7456c19e326e272c2153ff2 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Fri, 13 Aug 2021 15:54:47 +0800 Subject: [PATCH 060/151] drm/amd/display: Add option to defer works of hpd_rx_irq [Why & How] Due to some code flow constraints, we need to defer dc_lock needed works from dc_link_handle_hpd_rx_irq(). Thus, do following changes: * Change allow_hpd_rx_irq() from static to public * Change handle_automated_test() from static to public * Extract link lost handling flow out from dc_link_handle_hpd_rx_irq() and put those into a new function dc_link_dp_handle_link_loss() * Add one option parameter to decide whether defer works within dc_link_handle_hpd_rx_irq() Acked-by: Mikita Lipski Signed-off-by: Wayne Lin Reviewed-by: Nicholas Kazlauskas Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 92 ++++++++++++------- drivers/gpu/drm/amd/display/dc/dc_link.h | 3 + 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 3b68d77404986..ea0a4154bd84f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -3431,7 +3431,7 @@ void decide_link_settings(struct dc_stream_state *stream, } /*************************Short Pulse IRQ***************************/ -static bool allow_hpd_rx_irq(const struct dc_link *link) +bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link) { /* * Don't handle RX IRQ unless one of following is met: @@ -3940,7 +3940,7 @@ static void dp_test_get_audio_test_data(struct dc_link *link, bool disable_video } } -static void handle_automated_test(struct dc_link *link) +void dc_link_dp_handle_automated_test(struct dc_link *link) { union test_request test_request; union test_response test_response; @@ -3989,17 +3989,50 @@ static void handle_automated_test(struct dc_link *link) sizeof(test_response)); } -bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss) +void dc_link_dp_handle_link_loss(struct dc_link *link) +{ + int i; + struct pipe_ctx *pipe_ctx; + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link) + break; + } + + if (pipe_ctx == NULL || pipe_ctx->stream == NULL) + return; + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off && + pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) { + core_link_disable_stream(pipe_ctx); + } + } + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off && + pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) { + core_link_enable_stream(link->dc->current_state, pipe_ctx); + } + } +} + +static bool handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss, + bool defer_handling, bool *has_left_work) { union hpd_irq_data hpd_irq_dpcd_data = { { { {0} } } }; union device_service_irq device_service_clear = { { 0 } }; enum dc_status result; bool status = false; - struct pipe_ctx *pipe_ctx; - int i; if (out_link_loss) *out_link_loss = false; + + if (has_left_work) + *has_left_work = false; /* For use cases related to down stream connection status change, * PSR and device auto test, refer to function handle_sst_hpd_irq * in DAL2.1*/ @@ -4031,11 +4064,14 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd &device_service_clear.raw, sizeof(device_service_clear.raw)); device_service_clear.raw = 0; - handle_automated_test(link); + if (defer_handling && has_left_work) + *has_left_work = true; + else + dc_link_dp_handle_automated_test(link); return false; } - if (!allow_hpd_rx_irq(link)) { + if (!dc_link_dp_allow_hpd_rx_irq(link)) { DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n", __func__, link->link_index); return false; @@ -4049,12 +4085,18 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd * so do not handle as a normal sink status change interrupt. */ - if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) + if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) { + if (defer_handling && has_left_work) + *has_left_work = true; return true; + } /* check if we have MST msg and return since we poll for it */ - if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) + if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) { + if (defer_handling && has_left_work) + *has_left_work = true; return false; + } /* For now we only handle 'Downstream port status' case. * If we got sink count changed it means @@ -4071,29 +4113,10 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd sizeof(hpd_irq_dpcd_data), "Status: "); - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link) - break; - } - - if (pipe_ctx == NULL || pipe_ctx->stream == NULL) - return false; - - - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off && - pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) - core_link_disable_stream(pipe_ctx); - } - - for (i = 0; i < MAX_PIPES; i++) { - pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; - if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off && - pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) - core_link_enable_stream(link->dc->current_state, pipe_ctx); - } + if (defer_handling && has_left_work) + *has_left_work = true; + else + dc_link_dp_handle_link_loss(link); status = false; if (out_link_loss) @@ -4119,6 +4142,11 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd return status; } +bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss) +{ + return handle_hpd_rx_irq(link, out_hpd_irq_dpcd_data, out_link_loss, false, NULL); +} + /*query dpcd for version and mst cap addresses*/ bool is_mst_supported(struct dc_link *link) { diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index 4fdb24ba24af3..bb515d6409657 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -315,6 +315,9 @@ bool dc_link_wait_for_t12(struct dc_link *link); enum dc_status read_hpd_rx_irq_data( struct dc_link *link, union hpd_irq_data *irq_data); +void dc_link_dp_handle_automated_test(struct dc_link *link); +void dc_link_dp_handle_link_loss(struct dc_link *link); +bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link); struct dc_sink_init_data; From 8e794421bc981586d0af4e959ec76d668c793a55 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Fri, 23 Jul 2021 11:50:28 +0800 Subject: [PATCH 061/151] drm/amd/display: Fork thread to offload work of hpd_rx_irq [Why] Currently, we will try to get dm.dc_lock in handle_hpd_rx_irq() when link lost happened, which is risky and could cause deadlock. e.g. If we are under procedure to enable MST streams and then monitor happens to toggle short hpd to notify link lost, then handle_hpd_rx_irq() will get blocked due to stream enabling flow has dc_lock. However, under MST, enabling streams involves communication with remote sinks which need to use handle_hpd_rx_irq() to handle sideband messages. Thus, we have deadlock here. [How] Target is to have handle_hpd_rx_irq() finished as soon as possilble. Hence we can react to interrupt quickly. Besides, we should avoid to grabe dm.dc_lock within handle_hpd_rx_irq() to avoid deadlock situation. Firstly, revert patches which introduced to use dm.dc_lock in handle_hpd_rx_irq(): * commit ("drm/amd/display: NULL pointer error during ") * commit ("drm/amd/display: Only one display lights up while using MST") * commit ("drm/amd/display: take dc_lock in short pulse handler only") Instead, create work to handle irq events which needs dm.dc_lock. Besides: * Create struct hpd_rx_irq_offload_work_queue for each link to handle its short hpd events * Avoid to handle link lost/ automated test if the link is disconnected * Defer dc_lock needed works in dc_link_handle_hpd_rx_irq(). This function should just handle simple stuff for us (e.g. DPCD R/W). However, deferred works should still be handled by the order that dc_link_handle_hpd_rx_irq() used to be. * Change function name dm_handle_hpd_rx_irq() to dm_handle_mst_sideband_msg() to be more specific Reviewed-by: Nicholas Kazlauskas Acked-by: Mikita Lipski Signed-off-by: Wayne Lin Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 203 ++++++++++++++---- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 49 ++++- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 9 +- drivers/gpu/drm/amd/display/dc/dc_link.h | 6 +- 4 files changed, 219 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 24002a9891961..a8bc3ff8d9f1c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1208,6 +1208,83 @@ static void vblank_control_worker(struct work_struct *work) } #endif + +static void dm_handle_hpd_rx_offload_work(struct work_struct *work) +{ + struct hpd_rx_irq_offload_work *offload_work; + struct amdgpu_dm_connector *aconnector; + struct dc_link *dc_link; + struct amdgpu_device *adev; + enum dc_connection_type new_connection_type = dc_connection_none; + unsigned long flags; + + offload_work = container_of(work, struct hpd_rx_irq_offload_work, work); + aconnector = offload_work->offload_wq->aconnector; + + if (!aconnector) { + DRM_ERROR("Can't retrieve aconnector in hpd_rx_irq_offload_work"); + goto skip; + } + + adev = drm_to_adev(aconnector->base.dev); + dc_link = aconnector->dc_link; + + mutex_lock(&aconnector->hpd_lock); + if (!dc_link_detect_sink(dc_link, &new_connection_type)) + DRM_ERROR("KMS: Failed to detect connector\n"); + mutex_unlock(&aconnector->hpd_lock); + + if (new_connection_type == dc_connection_none) + goto skip; + + if (amdgpu_in_reset(adev)) + goto skip; + + mutex_lock(&adev->dm.dc_lock); + if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) + dc_link_dp_handle_automated_test(dc_link); + else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) && + hpd_rx_irq_check_link_loss_status(dc_link, &offload_work->data) && + dc_link_dp_allow_hpd_rx_irq(dc_link)) { + dc_link_dp_handle_link_loss(dc_link); + spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags); + offload_work->offload_wq->is_handling_link_loss = false; + spin_unlock_irqrestore(&offload_work->offload_wq->offload_lock, flags); + } + mutex_unlock(&adev->dm.dc_lock); + +skip: + kfree(offload_work); + +} + +static struct hpd_rx_irq_offload_work_queue *hpd_rx_irq_create_workqueue(struct dc *dc) +{ + int max_caps = dc->caps.max_links; + int i = 0; + struct hpd_rx_irq_offload_work_queue *hpd_rx_offload_wq = NULL; + + hpd_rx_offload_wq = kcalloc(max_caps, sizeof(*hpd_rx_offload_wq), GFP_KERNEL); + + if (!hpd_rx_offload_wq) + return NULL; + + + for (i = 0; i < max_caps; i++) { + hpd_rx_offload_wq[i].wq = + create_singlethread_workqueue("amdgpu_dm_hpd_rx_offload_wq"); + + if (hpd_rx_offload_wq[i].wq == NULL) { + DRM_ERROR("create amdgpu_dm_hpd_rx_offload_wq fail!"); + return NULL; + } + + spin_lock_init(&hpd_rx_offload_wq[i].offload_lock); + } + + return hpd_rx_offload_wq; +} + static int amdgpu_dm_init(struct amdgpu_device *adev) { struct dc_init_data init_data; @@ -1326,6 +1403,12 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) dc_hardware_init(adev->dm.dc); + adev->dm.hpd_rx_offload_wq = hpd_rx_irq_create_workqueue(adev->dm.dc); + if (!adev->dm.hpd_rx_offload_wq) { + DRM_ERROR("amdgpu: failed to create hpd rx offload workqueue.\n"); + goto error; + } + #if defined(CONFIG_DRM_AMD_DC_DCN) if ((adev->flags & AMD_IS_APU) && (adev->asic_type >= CHIP_CARRIZO)) { struct dc_phy_addr_space_config pa_config; @@ -1505,6 +1588,18 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) adev->dm.freesync_module = NULL; } + if (adev->dm.hpd_rx_offload_wq) { + for (i = 0; i < adev->dm.dc->caps.max_links; i++) { + if (adev->dm.hpd_rx_offload_wq[i].wq) { + destroy_workqueue(adev->dm.hpd_rx_offload_wq[i].wq); + adev->dm.hpd_rx_offload_wq[i].wq = NULL; + } + } + + kfree(adev->dm.hpd_rx_offload_wq); + adev->dm.hpd_rx_offload_wq = NULL; + } + mutex_destroy(&adev->dm.audio_lock); mutex_destroy(&adev->dm.dc_lock); @@ -2123,6 +2218,16 @@ static enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc) return res; } +static void hpd_rx_irq_work_suspend(struct amdgpu_display_manager *dm) +{ + int i; + + if (dm->hpd_rx_offload_wq) { + for (i = 0; i < dm->dc->caps.max_links; i++) + flush_workqueue(dm->hpd_rx_offload_wq[i].wq); + } +} + static int dm_suspend(void *handle) { struct amdgpu_device *adev = handle; @@ -2144,6 +2249,8 @@ static int dm_suspend(void *handle) amdgpu_dm_irq_suspend(adev); + hpd_rx_irq_work_suspend(dm); + return ret; } @@ -2154,6 +2261,8 @@ static int dm_suspend(void *handle) amdgpu_dm_irq_suspend(adev); + hpd_rx_irq_work_suspend(dm); + dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3); return 0; @@ -2826,8 +2935,7 @@ static void handle_hpd_irq(void *param) } - -static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) +static void dm_handle_mst_sideband_msg(struct amdgpu_dm_connector *aconnector) { uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 }; uint8_t dret; @@ -2905,6 +3013,25 @@ static void dm_handle_hpd_rx_irq(struct amdgpu_dm_connector *aconnector) DRM_DEBUG_DRIVER("Loop exceeded max iterations\n"); } +static void schedule_hpd_rx_offload_work(struct hpd_rx_irq_offload_work_queue *offload_wq, + union hpd_irq_data hpd_irq_data) +{ + struct hpd_rx_irq_offload_work *offload_work = + kzalloc(sizeof(*offload_work), GFP_KERNEL); + + if (!offload_work) { + DRM_ERROR("Failed to allocate hpd_rx_irq_offload_work.\n"); + return; + } + + INIT_WORK(&offload_work->work, dm_handle_hpd_rx_offload_work); + offload_work->data = hpd_irq_data; + offload_work->offload_wq = offload_wq; + + queue_work(offload_wq->wq, &offload_work->work); + DRM_DEBUG_KMS("queue work to handle hpd_rx offload work"); +} + static void handle_hpd_rx_irq(void *param) { struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param; @@ -2916,14 +3043,16 @@ static void handle_hpd_rx_irq(void *param) enum dc_connection_type new_connection_type = dc_connection_none; struct amdgpu_device *adev = drm_to_adev(dev); union hpd_irq_data hpd_irq_data; - bool lock_flag = 0; + bool link_loss = false; + bool has_left_work = false; + int idx = aconnector->base.index; + struct hpd_rx_irq_offload_work_queue *offload_wq = &adev->dm.hpd_rx_offload_wq[idx]; memset(&hpd_irq_data, 0, sizeof(hpd_irq_data)); if (adev->dm.disable_hpd_irq) return; - /* * TODO:Temporary add mutex to protect hpd interrupt not have a gpio * conflict, after implement i2c helper, this mutex should be @@ -2931,43 +3060,41 @@ static void handle_hpd_rx_irq(void *param) */ mutex_lock(&aconnector->hpd_lock); - read_hpd_rx_irq_data(dc_link, &hpd_irq_data); + result = dc_link_handle_hpd_rx_irq(dc_link, &hpd_irq_data, + &link_loss, true, &has_left_work); - if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) || - (dc_link->type == dc_connection_mst_branch)) { - if (hpd_irq_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) { - result = true; - dm_handle_hpd_rx_irq(aconnector); - goto out; - } else if (hpd_irq_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) { - result = false; - dm_handle_hpd_rx_irq(aconnector); + if (!has_left_work) + goto out; + + if (hpd_irq_data.bytes.device_service_irq.bits.AUTOMATED_TEST) { + schedule_hpd_rx_offload_work(offload_wq, hpd_irq_data); + goto out; + } + + if (dc_link_dp_allow_hpd_rx_irq(dc_link)) { + if (hpd_irq_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY || + hpd_irq_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) { + dm_handle_mst_sideband_msg(aconnector); goto out; } - } - /* - * TODO: We need the lock to avoid touching DC state while it's being - * modified during automated compliance testing, or when link loss - * happens. While this should be split into subhandlers and proper - * interfaces to avoid having to conditionally lock like this in the - * outer layer, we need this workaround temporarily to allow MST - * lightup in some scenarios to avoid timeout. - */ - if (!amdgpu_in_reset(adev) && - (hpd_rx_irq_check_link_loss_status(dc_link, &hpd_irq_data) || - hpd_irq_data.bytes.device_service_irq.bits.AUTOMATED_TEST)) { - mutex_lock(&adev->dm.dc_lock); - lock_flag = 1; - } + if (link_loss) { + bool skip = false; -#ifdef CONFIG_DRM_AMD_DC_HDCP - result = dc_link_handle_hpd_rx_irq(dc_link, &hpd_irq_data, NULL); -#else - result = dc_link_handle_hpd_rx_irq(dc_link, NULL, NULL); -#endif - if (!amdgpu_in_reset(adev) && lock_flag) - mutex_unlock(&adev->dm.dc_lock); + spin_lock(&offload_wq->offload_lock); + skip = offload_wq->is_handling_link_loss; + + if (!skip) + offload_wq->is_handling_link_loss = true; + + spin_unlock(&offload_wq->offload_lock); + + if (!skip) + schedule_hpd_rx_offload_work(offload_wq, hpd_irq_data); + + goto out; + } + } out: if (result && !is_mst_root_connector) { @@ -3052,6 +3179,10 @@ static void register_hpd_handlers(struct amdgpu_device *adev) amdgpu_dm_irq_register_interrupt(adev, &int_params, handle_hpd_rx_irq, (void *) aconnector); + + if (adev->dm.hpd_rx_offload_wq) + adev->dm.hpd_rx_offload_wq[connector->index].aconnector = + aconnector; } } } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index be796c2fed7d7..a038c70037b5b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -171,6 +171,48 @@ struct dal_allocation { u64 gpu_addr; }; +/** + * struct hpd_rx_irq_offload_work_queue - Work queue to handle hpd_rx_irq + * offload work + */ +struct hpd_rx_irq_offload_work_queue { + /** + * @wq: workqueue structure to queue offload work. + */ + struct workqueue_struct *wq; + /** + * @offload_lock: To protect fields of offload work queue. + */ + spinlock_t offload_lock; + /** + * @is_handling_link_loss: Used to prevent inserting link loss event when + * we're handling link loss + */ + bool is_handling_link_loss; + /** + * @aconnector: The aconnector that this work queue is attached to + */ + struct amdgpu_dm_connector *aconnector; +}; + +/** + * struct hpd_rx_irq_offload_work - hpd_rx_irq offload work structure + */ +struct hpd_rx_irq_offload_work { + /** + * @work: offload work + */ + struct work_struct work; + /** + * @data: reference irq data which is used while handling offload work + */ + union hpd_irq_data data; + /** + * @offload_wq: offload work queue that this work is queued to + */ + struct hpd_rx_irq_offload_work_queue *offload_wq; +}; + /** * struct amdgpu_display_manager - Central amdgpu display manager device * @@ -461,7 +503,12 @@ struct amdgpu_display_manager { */ struct crc_rd_work *crc_rd_wrk; #endif - + /** + * @hpd_rx_offload_wq: + * + * Work queue to offload works of hpd_rx_irq + */ + struct hpd_rx_irq_offload_work_queue *hpd_rx_offload_wq; /** * @mst_encoders: * diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index ea0a4154bd84f..e573b0cea9a22 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2692,7 +2692,7 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link) return max_link_cap; } -enum dc_status read_hpd_rx_irq_data( +static enum dc_status read_hpd_rx_irq_data( struct dc_link *link, union hpd_irq_data *irq_data) { @@ -4020,7 +4020,7 @@ void dc_link_dp_handle_link_loss(struct dc_link *link) } } -static bool handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss, +bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss, bool defer_handling, bool *has_left_work) { union hpd_irq_data hpd_irq_dpcd_data = { { { {0} } } }; @@ -4142,11 +4142,6 @@ static bool handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_ return status; } -bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool *out_link_loss) -{ - return handle_hpd_rx_irq(link, out_hpd_irq_dpcd_data, out_link_loss, false, NULL); -} - /*query dpcd for version and mst cap addresses*/ bool is_mst_supported(struct dc_link *link) { diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index bb515d6409657..56340a1765542 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h @@ -303,7 +303,8 @@ enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx); * false - no change in Downstream port status. No further action required * from DM. */ bool dc_link_handle_hpd_rx_irq(struct dc_link *dc_link, - union hpd_irq_data *hpd_irq_dpcd_data, bool *out_link_loss); + union hpd_irq_data *hpd_irq_dpcd_data, bool *out_link_loss, + bool defer_handling, bool *has_left_work); /* * On eDP links this function call will stall until T12 has elapsed. @@ -312,9 +313,6 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *dc_link, */ bool dc_link_wait_for_t12(struct dc_link *link); -enum dc_status read_hpd_rx_irq_data( - struct dc_link *link, - union hpd_irq_data *irq_data); void dc_link_dp_handle_automated_test(struct dc_link *link); void dc_link_dp_handle_link_loss(struct dc_link *link); bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link); From 6077911b49fe2f8049a6d7650bccbbaa03a928d5 Mon Sep 17 00:00:00 2001 From: Josip Pavic Date: Thu, 19 Aug 2021 09:25:22 -0400 Subject: [PATCH 062/151] drm/amd/display: unblock abm when odm is enabled only on configs that support it [Why] When ODM is enabled, ABM is blocked on dcn31 but unblocked on dcn30. Since the dcn31 firmware is now able to handle ABM interop with ODM, it is no longer necessary to block ABM when ODM is enabled. Since the dcn30 firmware does not handle ABM interop with ODM, leaving that combination unblocked can lead to one side of the screen appearing brighter than the other. [How] When ODM is enabled, unblock abm on dcn31 and block it on dcn30 Reviewed-by: Anthony Koo Acked-by: Mikita Lipski Signed-off-by: Josip Pavic Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 1 + .../gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c | 15 --------------- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c | 1 - 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index 3a5b53dd2f6d9..93f32a312fee8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -100,6 +100,7 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, .get_dcc_en_bits = dcn10_get_dcc_en_bits, .update_visual_confirm_color = dcn20_update_visual_confirm_color, + .is_abm_supported = dcn21_is_abm_supported }; static const struct hwseq_private_funcs dcn30_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c index 7feba8a0d8477..2434232fb3f52 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c @@ -595,18 +595,3 @@ void dcn31_reset_hw_ctx_wrap( } } } - -bool dcn31_is_abm_supported(struct dc *dc, - struct dc_state *context, struct dc_stream_state *stream) -{ - int i; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - if (pipe_ctx->stream == stream && - (pipe_ctx->prev_odm_pipe == NULL && pipe_ctx->next_odm_pipe == NULL)) - return true; - } - return false; -} diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c index 40011cd3c8ef0..10c83f4083b56 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c @@ -98,7 +98,6 @@ static const struct hw_sequencer_funcs dcn31_funcs = { .set_pipe = dcn21_set_pipe, .z10_restore = dcn31_z10_restore, .z10_save_init = dcn31_z10_save_init, - .is_abm_supported = dcn31_is_abm_supported, .set_disp_pattern_generator = dcn30_set_disp_pattern_generator, .update_visual_confirm_color = dcn20_update_visual_confirm_color, }; From 035f54969bb2c1a5ced52f43e4ef393e0c0f6bfa Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Fri, 13 Aug 2021 15:15:03 -0400 Subject: [PATCH 063/151] drm/amd/display: Add flag to detect dpms force off during HPD [Why] When a connector is unplugged, dpms is forced off so that some connector allocations are cleared off. This is done outside the commit sequence from the userspace. This causes HUBP blank. Due to the blank hubp, a non blocking commit which queues flip will encounter a timeout waiting for the flip_done because prior to writing the surface flip address, hubp was in blank. [How] Add a marker to DM's crtc state and use this field to indicate whether dpms was forced off during an HPD. Check for this marker before queuing the flip. Reviewed-by: Anson Jacob Acked-by: Mikita Lipski Signed-off-by: Aurabindo Pillai Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 19 +++++++++++++------ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 ++ .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 18 ++++++++++++++---- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a8bc3ff8d9f1c..283d660a0a66f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2409,7 +2409,7 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state, return; } -static void dm_set_dpms_off(struct dc_link *link) +static void dm_set_dpms_off(struct dc_link *link, struct dm_crtc_state *acrtc_state) { struct dc_stream_state *stream_state; struct amdgpu_dm_connector *aconnector = link->priv; @@ -2430,6 +2430,7 @@ static void dm_set_dpms_off(struct dc_link *link) } stream_update.stream = stream_state; + acrtc_state->force_dpms_off = true; dc_commit_updates_for_stream(stream_state->ctx->dc, NULL, 0, stream_state, &stream_update, stream_state->ctx->dc->current_state); @@ -2873,13 +2874,16 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) struct drm_device *dev = connector->dev; enum dc_connection_type new_connection_type = dc_connection_none; struct amdgpu_device *adev = drm_to_adev(dev); -#ifdef CONFIG_DRM_AMD_DC_HDCP struct dm_connector_state *dm_con_state = to_dm_connector_state(connector->state); -#endif + struct dm_crtc_state *dm_crtc_state = NULL; if (adev->dm.disable_hpd_irq) return; + if (dm_con_state->base.state && dm_con_state->base.crtc) + dm_crtc_state = to_dm_crtc_state(drm_atomic_get_crtc_state( + dm_con_state->base.state, + dm_con_state->base.crtc)); /* * In case of failure or MST no need to update connector status or notify the OS * since (for MST case) MST does this in its own context. @@ -2911,8 +2915,9 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) } else if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) { if (new_connection_type == dc_connection_none && - aconnector->dc_link->type == dc_connection_none) - dm_set_dpms_off(aconnector->dc_link); + aconnector->dc_link->type == dc_connection_none && + dm_crtc_state) + dm_set_dpms_off(aconnector->dc_link, dm_crtc_state); amdgpu_dm_update_connector_after_detect(aconnector); @@ -6253,6 +6258,7 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc) state->freesync_config = cur->freesync_config; state->cm_has_degamma = cur->cm_has_degamma; state->cm_is_degamma_srgb = cur->cm_is_degamma_srgb; + state->force_dpms_off = cur->force_dpms_off; /* TODO Duplicate dc_stream after objects are stream object is flattened */ return &state->base; @@ -8916,7 +8922,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, * and rely on sending it from software. */ if (acrtc_attach->base.state->event && - acrtc_state->active_planes > 0) { + acrtc_state->active_planes > 0 && + !acrtc_state->force_dpms_off) { drm_crtc_vblank_get(pcrtc); spin_lock_irqsave(&pcrtc->dev->event_lock, flags); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index a038c70037b5b..a85b09986aabd 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -629,6 +629,8 @@ struct dm_crtc_state { bool dsc_force_changed; bool vrr_supported; + + bool force_dpms_off; struct mod_freesync_config freesync_config; struct dc_info_packet vrr_infopacket; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index c5f1dc3b59614..c5f61be1f6b58 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -448,6 +448,10 @@ static void update_config(void *handle, struct cp_psp_stream_config *config) struct mod_hdcp_display *display = &hdcp_work[link_index].display; struct mod_hdcp_link *link = &hdcp_work[link_index].link; struct drm_connector_state *conn_state; + struct dc_sink *sink = NULL; +#if defined(CONFIG_DRM_AMD_DC_DCN3_1) + bool link_is_hdcp14 = false; +#endif if (config->dpms_off) { hdcp_remove_display(hdcp_work, link_index, aconnector); @@ -460,8 +464,13 @@ static void update_config(void *handle, struct cp_psp_stream_config *config) display->index = aconnector->base.index; display->state = MOD_HDCP_DISPLAY_ACTIVE; - if (aconnector->dc_sink != NULL) - link->mode = mod_hdcp_signal_type_to_operation_mode(aconnector->dc_sink->sink_signal); + if (aconnector->dc_sink) + sink = aconnector->dc_sink; + else if (aconnector->dc_em_sink) + sink = aconnector->dc_em_sink; + + if (sink != NULL) + link->mode = mod_hdcp_signal_type_to_operation_mode(sink->sink_signal); display->controller = CONTROLLER_ID_D0 + config->otg_inst; display->dig_fe = config->dig_fe; @@ -470,8 +479,9 @@ static void update_config(void *handle, struct cp_psp_stream_config *config) display->stream_enc_idx = config->stream_enc_idx; link->link_enc_idx = config->link_enc_idx; link->phy_idx = config->phy_idx; - link->hdcp_supported_informational = dc_link_is_hdcp14(aconnector->dc_link, - aconnector->dc_sink->sink_signal) ? 1 : 0; + if (sink) + link_is_hdcp14 = dc_link_is_hdcp14(aconnector->dc_link, sink->sink_signal); + link->hdcp_supported_informational = link_is_hdcp14; link->dp.rev = aconnector->dc_link->dpcd_caps.dpcd_rev.raw; link->dp.assr_enabled = config->assr_enabled; link->dp.mst_enabled = config->mst_enabled; From 64d283cb379eadcb412ebba3b61808b58d0c6193 Mon Sep 17 00:00:00 2001 From: Jimmy Kizito Date: Tue, 10 Aug 2021 19:07:43 -0400 Subject: [PATCH 064/151] drm/amd/display: Fix dynamic link encoder access. [Why] Assuming DIG link encoders are statically mapped to links can cause system instability due to null pointer accesses. [How] - Add checks for non-null link encoder pointers before trying to access them. - When a hardware platform uses dynamic DIG assignment (i.e. resource function 'link_encs_assign' defined) and a link supports flexible mapping to DIGs, use the link_enc_cfg API to access the DIG assigned to a link or stream. Reviewed-by: Meenakshikumar Somasundaram Acked-by: Mikita Lipski Signed-off-by: Jimmy Kizito Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 42 +++++++++++++++---- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 36 ++++++++++++++-- .../drm/amd/display/dc/core/dc_link_enc_cfg.c | 25 ++++++----- .../drm/amd/display/dc/core/dc_link_hwss.c | 7 ++-- .../gpu/drm/amd/display/dc/core/dc_resource.c | 3 +- .../display/dc/dce110/dce110_hw_sequencer.c | 22 +++++++--- .../drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 13 ++++-- .../drm/amd/display/dc/dcn20/dcn20_resource.c | 20 ++++++++- .../drm/amd/display/dc/dcn31/dcn31_hwseq.c | 9 +++- .../gpu/drm/amd/display/dc/inc/link_enc_cfg.h | 5 +++ 12 files changed, 147 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 15491e3ca11a6..1414da4b95d7c 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -87,7 +87,7 @@ int dcn31_get_active_display_cnt_wa( const struct dc_link *link = dc->links[i]; /* abusing the fact that the dig and phy are coupled to see if the phy is enabled */ - if (link->link_enc->funcs->is_dig_enabled && + if (link->link_enc && link->link_enc->funcs->is_dig_enabled && link->link_enc->funcs->is_dig_enabled(link->link_enc)) display_count++; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 5d9460e0dbabf..3c8eb3e659af1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3457,6 +3457,10 @@ static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx) static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) { struct cp_psp *cp_psp = &pipe_ctx->stream->ctx->cp_psp; +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct link_encoder *link_enc = NULL; +#endif + if (cp_psp && cp_psp->funcs.update_stream_config) { struct cp_psp_stream_config config = {0}; enum dp_panel_mode panel_mode = @@ -3468,8 +3472,21 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) config.dig_be = pipe_ctx->stream->link->link_enc_hw_inst; #if defined(CONFIG_DRM_AMD_DC_DCN) config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA; - config.link_enc_idx = pipe_ctx->stream->link->link_enc->transmitter - TRANSMITTER_UNIPHY_A; - config.phy_idx = pipe_ctx->stream->link->link_enc->transmitter - TRANSMITTER_UNIPHY_A; + if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_PHY) { + link_enc = pipe_ctx->stream->link->link_enc; + config.phy_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A; + } else if (pipe_ctx->stream->link->dc->res_pool->funcs->link_encs_assign) { + /* Use link encoder assignment from current DC state - which may differ from the DC state to be + * committed - when updating PSP config. + */ + link_enc = link_enc_cfg_get_link_enc_used_by_stream( + pipe_ctx->stream->link->dc->current_state, + pipe_ctx->stream); + config.phy_idx = 0; /* Clear phy_idx for non-physical display endpoints. */ + } + ASSERT(link_enc); + if (link_enc) + config.link_enc_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A; if (is_dp_128b_132b_signal(pipe_ctx)) { config.stream_enc_idx = pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0; config.link_enc_idx = pipe_ctx->stream->link->hpo_dp_link_enc->inst; @@ -3576,6 +3593,7 @@ void core_link_enable_stream( struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; enum dc_status status; + struct link_encoder *link_enc; #if defined(CONFIG_DRM_AMD_DC_DCN) enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO; #endif @@ -3585,15 +3603,22 @@ void core_link_enable_stream( dc_is_virtual_signal(pipe_ctx->stream->signal)) return; + if (dc->res_pool->funcs->link_encs_assign && stream->link->ep_type != DISPLAY_ENDPOINT_PHY) + link_enc = stream->link_enc; + else + link_enc = stream->link->link_enc; + ASSERT(link_enc); + #if defined(CONFIG_DRM_AMD_DC_DCN) if (!dc_is_virtual_signal(pipe_ctx->stream->signal) && !is_dp_128b_132b_signal(pipe_ctx)) { #else if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) { #endif - stream->link->link_enc->funcs->setup( - stream->link->link_enc, - pipe_ctx->stream->signal); + if (link_enc) + link_enc->funcs->setup( + link_enc, + pipe_ctx->stream->signal); pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync( pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.tg->inst, @@ -3748,9 +3773,10 @@ void core_link_enable_stream( #else if (!dc_is_virtual_signal(pipe_ctx->stream->signal)) #endif - stream->link->link_enc->funcs->setup( - stream->link->link_enc, - pipe_ctx->stream->signal); + if (link_enc) + link_enc->funcs->setup( + link_enc, + pipe_ctx->stream->signal); dc->hwss.enable_stream(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index e573b0cea9a22..07c2343185bd6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2624,13 +2624,27 @@ static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link) bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap) { + struct link_encoder *link_enc = NULL; + if (!max_link_enc_cap) { DC_LOG_ERROR("%s: Could not return max link encoder caps", __func__); return false; } - if (link->link_enc->funcs->get_max_link_cap) { - link->link_enc->funcs->get_max_link_cap(link->link_enc, max_link_enc_cap); + /* Links supporting dynamically assigned link encoder will be assigned next + * available encoder if one not already assigned. + */ + if (link->is_dig_mapping_flexible && + link->dc->res_pool->funcs->link_encs_assign) { + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + if (link_enc == NULL) + link_enc = link_enc_cfg_get_next_avail_link_enc(link->dc, link->dc->current_state); + } else + link_enc = link->link_enc; + ASSERT(link_enc); + + if (link_enc && link_enc->funcs->get_max_link_cap) { + link_enc->funcs->get_max_link_cap(link_enc, max_link_enc_cap); return true; } @@ -2646,9 +2660,23 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link) #if defined(CONFIG_DRM_AMD_DC_DCN) enum dc_link_rate lttpr_max_link_rate; #endif + struct link_encoder *link_enc = NULL; + + /* Links supporting dynamically assigned link encoder will be assigned next + * available encoder if one not already assigned. + */ + if (link->is_dig_mapping_flexible && + link->dc->res_pool->funcs->link_encs_assign) { + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + if (link_enc == NULL) + link_enc = link_enc_cfg_get_next_avail_link_enc(link->dc, link->dc->current_state); + } else + link_enc = link->link_enc; + ASSERT(link_enc); /* get max link encoder capability */ - link->link_enc->funcs->get_max_link_cap(link->link_enc, &max_link_cap); + if (link_enc) + link_enc->funcs->get_max_link_cap(link_enc, &max_link_cap); #if defined(CONFIG_DRM_AMD_DC_DCN) if (max_link_cap.link_rate >= LINK_RATE_UHBR10 && !link->hpo_dp_link_enc) @@ -2867,7 +2895,7 @@ bool dp_verify_link_cap( * PHY will sometimes be in bad state on hotplugging display from certain USB-C dongle, * so add extra cycle of enabling and disabling the PHY before first link training. */ - if (link->link_enc->features.flags.bits.DP_IS_USB_C && + if (link->link_enc && link->link_enc->features.flags.bits.DP_IS_USB_C && link->dc->debug.usbc_combo_phy_reset_wa) { dp_enable_link_phy(link, link->connector_signal, dp_cs_id, cur); dp_disable_link_phy(link, link->connector_signal); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c index de80a9ea4cfaa..49b17bbea8d1a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c @@ -139,7 +139,7 @@ static struct dc_stream_state *get_stream_using_link_enc( for (i = 0; i < state->stream_count; i++) { struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; - if (assignment.valid && (assignment.eng_id == eng_id)) { + if ((assignment.valid == true) && (assignment.eng_id == eng_id)) { stream_idx = i; break; } @@ -254,7 +254,7 @@ struct dc_link *link_enc_cfg_get_link_using_link_enc( for (i = 0; i < state->stream_count; i++) { struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; - if (assignment.valid && (assignment.eng_id == eng_id)) { + if ((assignment.valid == true) && (assignment.eng_id == eng_id)) { stream_idx = i; break; } @@ -274,7 +274,6 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_link( { struct link_encoder *link_enc = NULL; struct display_endpoint_id ep_id; - int stream_idx = -1; int i; ep_id = (struct display_endpoint_id) { @@ -283,20 +282,15 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_link( for (i = 0; i < state->stream_count; i++) { struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; - - if (assignment.valid && + if (assignment.valid == true && assignment.ep_id.link_id.id == ep_id.link_id.id && assignment.ep_id.link_id.enum_id == ep_id.link_id.enum_id && assignment.ep_id.link_id.type == ep_id.link_id.type && assignment.ep_id.ep_type == ep_id.ep_type) { - stream_idx = i; - break; + link_enc = link->dc->res_pool->link_encoders[assignment.eng_id - ENGINE_ID_DIGA]; } } - if (stream_idx != -1) - link_enc = state->streams[stream_idx]->link_enc; - return link_enc; } @@ -313,3 +307,14 @@ struct link_encoder *link_enc_cfg_get_next_avail_link_enc( return link_enc; } + +struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream( + struct dc_state *state, + const struct dc_stream_state *stream) +{ + struct link_encoder *link_enc; + + link_enc = link_enc_cfg_get_link_enc_used_by_link(state, stream->link); + + return link_enc; +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index b9570b7c557b6..dae0ab761b619 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -452,9 +452,10 @@ void dp_retrain_link_dp_test(struct dc_link *link, if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only) (&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio); - link->link_enc->funcs->disable_output( - link->link_enc, - SIGNAL_TYPE_DISPLAY_PORT); + if (link->link_enc) + link->link_enc->funcs->disable_output( + link->link_enc, + SIGNAL_TYPE_DISPLAY_PORT); /* Clear current link setting. */ memset(&link->cur_link_settings, 0, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 57420bf107866..8766b124d4b01 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2970,7 +2970,8 @@ enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream) res = DC_FAIL_CONTROLLER_VALIDATE; if (res == DC_OK) { - if (!link->link_enc->funcs->validate_output_with_stream( + if (link->ep_type == DISPLAY_ENDPOINT_PHY && + !link->link_enc->funcs->validate_output_with_stream( link->link_enc, stream)) res = DC_FAIL_ENC_VALIDATE; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 2ce668a23fe8b..102f764627521 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -46,6 +46,7 @@ #include "transform.h" #include "stream_encoder.h" #include "link_encoder.h" +#include "link_enc_cfg.h" #include "link_hwss.h" #include "dc_link_dp.h" #if defined(CONFIG_DRM_AMD_DC_DCN) @@ -1192,6 +1193,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->link; struct dc *dc = pipe_ctx->stream->ctx->dc; + struct link_encoder *link_enc = NULL; if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal)) { pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( @@ -1213,6 +1215,13 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) dc->hwss.disable_audio_stream(pipe_ctx); + /* Link encoder may have been dynamically assigned to non-physical display endpoint. */ + if (link->ep_type == DISPLAY_ENDPOINT_PHY) + link_enc = link->link_enc; + else if (dc->res_pool->funcs->link_encs_assign) + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + ASSERT(link_enc); + #if defined(CONFIG_DRM_AMD_DC_DCN) if (is_dp_128b_132b_signal(pipe_ctx)) { pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->disable( @@ -1220,13 +1229,15 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) setup_dp_hpo_stream(pipe_ctx, false); /* TODO - DP2.0 HW: unmap stream from link encoder here */ } else { - link->link_enc->funcs->connect_dig_be_to_fe( - link->link_enc, + if (link_enc) + link_enc->funcs->connect_dig_be_to_fe( + link_enc, pipe_ctx->stream_res.stream_enc->id, false); } #else - link->link_enc->funcs->connect_dig_be_to_fe( + if (link_enc) + link_enc->funcs->connect_dig_be_to_fe( link->link_enc, pipe_ctx->stream_res.stream_enc->id, false); @@ -1666,8 +1677,9 @@ static void power_down_encoders(struct dc *dc) if (signal != SIGNAL_TYPE_EDP) signal = SIGNAL_TYPE_NONE; - dc->links[i]->link_enc->funcs->disable_output( - dc->links[i]->link_enc, signal); + if (dc->links[i]->ep_type == DISPLAY_ENDPOINT_PHY) + dc->links[i]->link_enc->funcs->disable_output( + dc->links[i]->link_enc, signal); dc->links[i]->link_status.link_active = false; memset(&dc->links[i]->cur_link_settings, 0, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 7daadb6a52332..f37551e00023f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1296,7 +1296,7 @@ struct stream_encoder *dcn10_find_first_free_match_stream_enc_for_link( * in daisy chain use case */ j = i; - if (pool->stream_enc[i]->id == + if (link->ep_type == DISPLAY_ENDPOINT_PHY && pool->stream_enc[i]->id == link->link_enc->preferred_engine) return pool->stream_enc[i]; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index ffc0b9ab976f1..c0aed7d07eeba 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -2381,6 +2381,13 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) uint32_t active_total_with_borders; uint32_t early_control = 0; struct timing_generator *tg = pipe_ctx->stream_res.tg; + struct link_encoder *link_enc; + + if (link->is_dig_mapping_flexible && + link->dc->res_pool->funcs->link_encs_assign) + link_enc = pipe_ctx->stream->link_enc; + else + link_enc = link->link_enc; /* For MST, there are multiply stream go to only one link. * connect DIG back_end to front_end while enable_stream and @@ -2397,9 +2404,9 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) link->hpo_dp_link_enc->inst); } - if (!is_dp_128b_132b_signal(pipe_ctx)) - link->link_enc->funcs->connect_dig_be_to_fe( - link->link_enc, pipe_ctx->stream_res.stream_enc->id, true); + if (!is_dp_128b_132b_signal(pipe_ctx) && link_enc) + link_enc->funcs->connect_dig_be_to_fe( + link_enc, pipe_ctx->stream_res.stream_enc->id, true); if (dc_is_dp_signal(pipe_ctx->stream->signal)) dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_CONNECT_DIG_FE_BE); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 7bab88356df48..e69f553d680f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -87,6 +87,7 @@ #include "dce/dce_aux.h" #include "dce/dce_i2c.h" #include "vm_helper.h" +#include "link_enc_cfg.h" #include "amdgpu_socbb.h" @@ -1596,12 +1597,29 @@ static void get_pixel_clock_parameters( const struct dc_stream_state *stream = pipe_ctx->stream; struct pipe_ctx *odm_pipe; int opp_cnt = 1; + struct dc_link *link = stream->link; + struct link_encoder *link_enc = NULL; for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) opp_cnt++; pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz; - pixel_clk_params->encoder_object_id = stream->link->link_enc->id; + + /* Links supporting dynamically assigned link encoder will be assigned next + * available encoder if one not already assigned. + */ + if (link->is_dig_mapping_flexible && + link->dc->res_pool->funcs->link_encs_assign) { + link_enc = link_enc_cfg_get_link_enc_used_by_stream(stream->link->dc->current_state, stream); + if (link_enc == NULL) + link_enc = link_enc_cfg_get_next_avail_link_enc(stream->link->dc, + stream->link->dc->current_state); + } else + link_enc = stream->link->link_enc; + ASSERT(link_enc); + + if (link_enc) + pixel_clk_params->encoder_object_id = link_enc->id; pixel_clk_params->signal_type = pipe_ctx->stream->signal; pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1; /* TODO: un-hardcode*/ diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c index 2434232fb3f52..83f223d745fa2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c @@ -157,6 +157,9 @@ void dcn31_init_hw(struct dc *dc) */ struct dc_link *link = dc->links[i]; + if (link->ep_type != DISPLAY_ENDPOINT_PHY) + continue; + link->link_enc->funcs->hw_init(link->link_enc); /* Check for enabled DIG to identify enabled display */ @@ -184,7 +187,8 @@ void dcn31_init_hw(struct dc *dc) &dpcd_power_state, sizeof(dpcd_power_state)); if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) { /* blank dp stream before power off receiver*/ - if (dc->links[i]->link_enc->funcs->get_dig_frontend) { + if (dc->links[i]->ep_type == DISPLAY_ENDPOINT_PHY && + dc->links[i]->link_enc->funcs->get_dig_frontend) { unsigned int fe; fe = dc->links[i]->link_enc->funcs->get_dig_frontend( @@ -248,7 +252,8 @@ void dcn31_init_hw(struct dc *dc) for (i = 0; i < dc->link_count; i++) { struct dc_link *link = dc->links[i]; - if (link->link_enc->funcs->is_dig_enabled && + if (link->ep_type == DISPLAY_ENDPOINT_PHY && + link->link_enc->funcs->is_dig_enabled && link->link_enc->funcs->is_dig_enabled(link->link_enc) && dc->hwss.power_down) { dc->hwss.power_down(dc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h index 883dd8733ea4e..2472c9aed0955 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h @@ -88,4 +88,9 @@ struct link_encoder *link_enc_cfg_get_next_avail_link_enc( const struct dc *dc, const struct dc_state *state); +/* Return DIG link encoder used by stream. NULL if unused. */ +struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream( + struct dc_state *state, + const struct dc_stream_state *stream); + #endif /* DC_INC_LINK_ENC_CFG_H_ */ From 5e1a9a3ed65a906481bea56eaae77a2ba01ef2b1 Mon Sep 17 00:00:00 2001 From: Anson Jacob Date: Fri, 20 Aug 2021 19:42:16 -0400 Subject: [PATCH 065/151] drm/amd/display: Fix false BAD_FREE warning from Coverity This is an attempt to fix false warning raised by Coverity via multiple CID's. Addresses-Coverity-ID: 1487412 ("Free of address-of expression") Cc: Wesley Chalmers Reviewed-by: Wesley Chalmers Acked-by: Mikita Lipski Signed-off-by: Anson Jacob Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c index 72970e49800a6..7f25c11f42484 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c @@ -176,12 +176,15 @@ static void dpcd_reduce_address_range( uint8_t * const reduced_data, const uint32_t reduced_size) { - const uint32_t reduced_end_address = END_ADDRESS(reduced_address, reduced_size); - const uint32_t extended_end_address = END_ADDRESS(extended_address, extended_size); const uint32_t offset = reduced_address - extended_address; - if (extended_end_address == reduced_end_address && extended_address == reduced_address) - return; /* extended and reduced address ranges point to the same data */ + /* + * If the address is same, address was not extended. + * So we do not need to free any memory. + * The data is in original buffer(reduced_data). + */ + if (extended_data == reduced_data) + return; memcpy(&extended_data[offset], reduced_data, reduced_size); kfree(extended_data); From 13900e6fde3f91ea34a586002d592a2b20e1142e Mon Sep 17 00:00:00 2001 From: Meenakshikumar Somasundaram Date: Fri, 13 Aug 2021 13:09:25 -0400 Subject: [PATCH 066/151] drm/amd/display: Fix for null pointer access for ddc pin and aux engine. [Why] Need a check for NULL pointer access for ddc pin and aux engine. [How] Adding a check for ddc pin and aux engine accesses. Reviewed-by: Jimmy Kizito Acked-by: Mikita Lipski Signed-off-by: Meenakshikumar Somasundaram Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 2 -- drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 12 +++++++++--- drivers/gpu/drm/amd/display/include/dal_asic_id.h | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c index c5f61be1f6b58..5bfdc66b5867c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c @@ -449,9 +449,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config) struct mod_hdcp_link *link = &hdcp_work[link_index].link; struct drm_connector_state *conn_state; struct dc_sink *sink = NULL; -#if defined(CONFIG_DRM_AMD_DC_DCN3_1) bool link_is_hdcp14 = false; -#endif if (config->dpms_off) { hdcp_remove_display(hdcp_work, link_index, aconnector); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index e14f99b4b0c3f..4a3b94fa3e401 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -689,8 +689,8 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, enum aux_return_code_type operation_result; bool retry_on_defer = false; struct ddc *ddc_pin = ddc->ddc_pin; - struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; - struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine); + struct dce_aux *aux_engine = NULL; + struct aux_engine_dce110 *aux110 = NULL; uint32_t defer_time_in_ms = 0; int aux_ack_retries = 0, @@ -699,6 +699,11 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, aux_timeout_retries = 0, aux_invalid_reply_retries = 0; + if (ddc_pin) { + aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; + aux110 = FROM_AUX_ENGINE(aux_engine); + } + if (!payload->reply) { payload_reply = false; payload->reply = &reply; @@ -765,7 +770,8 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_DEFER"); /* polling_timeout_period is in us */ - defer_time_in_ms += aux110->polling_timeout_period / 1000; + if (aux110) + defer_time_in_ms += aux110->polling_timeout_period / 1000; ++aux_defer_retries; fallthrough; case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER: diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 381c17caace18..3d2f0817e40a1 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -227,7 +227,7 @@ enum { #define FAMILY_YELLOW_CARP 146 #define YELLOW_CARP_A0 0x01 -#define YELLOW_CARP_B0 0x02 // TODO: DCN31 - update with correct B0 ID +#define YELLOW_CARP_B0 0x20 #define YELLOW_CARP_UNKNOWN 0xFF #ifndef ASICREV_IS_YELLOW_CARP From 0d0118ccd44edb659f40c0925abc410e7cee166c Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 20 Aug 2021 18:02:26 -0400 Subject: [PATCH 067/151] drm/amd/display: [FW Promotion] Release 0.0.81 * PSR optimizations * add support for ABM when ODM is enabled * Z10 with PSR fixes * Increase trace buffer Acked-by: Mikita Lipski Signed-off-by: Anthony Koo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 3388188701d3a..8cf86f7cda418 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -47,10 +47,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x591aacca1 +#define DMUB_FW_VERSION_GIT_HASH 0x8ebc06e16 #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 80 +#define DMUB_FW_VERSION_REVISION 81 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 From caf58a2c82243e5fe028737e8190e6d194ed10e7 Mon Sep 17 00:00:00 2001 From: Qingqing Zhuo Date: Fri, 20 Aug 2021 17:40:42 -0400 Subject: [PATCH 068/151] drm/amd/display: Revert "dc: w/a for hard hang on HPD on native DP" This reverts commit "drm/amd/display: w/a for hard hang on HPD on native DP". [How & Why] Revert change as it does not fix the hard hang in all cases. An alternative w/a will be submitted separately. Acked-by: Mikita Lipski Signed-off-by: Qingqing Zhuo Reviewed-by: Bhawanpreet Lakha Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index 6185f9475fa22..c6f494f0dcea3 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -66,11 +66,9 @@ int rn_get_active_display_cnt_wa( for (i = 0; i < context->stream_count; i++) { const struct dc_stream_state *stream = context->streams[i]; - /* Extend the WA to DP for Linux*/ if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A || stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK || - stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK || - stream->signal == SIGNAL_TYPE_DISPLAY_PORT) + stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) tmds_present = true; } From f22268ce0a3f4065cddfb62ac29845b2c07c1c5a Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sat, 21 Aug 2021 14:27:13 -0400 Subject: [PATCH 069/151] drm/amd/display: 3.2.151 * coverity kernel memory leak fixes * NULL pointer dereference fixes * Add periodic detection when zstate is enabled * Fork thread to offload work of hpd_rx_irq Acked-by: Mikita Lipski Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index bcae2250a574e..ece44796a74fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -45,7 +45,7 @@ /* forward declaration */ struct aux_payload; -#define DC_VER "3.2.150" +#define DC_VER "3.2.151" #define MAX_SURFACES 3 #define MAX_PLANES 6 From 7b89bf83181363a84f86da787159ddbbef505b8c Mon Sep 17 00:00:00 2001 From: Anson Jacob Date: Mon, 23 Aug 2021 13:41:13 -0400 Subject: [PATCH 070/151] drm/amd/display: Fix multiple memory leaks reported by coverity coccinelle patch used: @@ expression enc1,vpg,afmt; @@ - if (!enc1 || !vpg || !afmt) + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); return NULL; + } Addresses-Coverity-ID: 1466017: ("Resource leaks") Reviewed-by: Aurabindo Jayamohanan Pillai Acked-by: Mikita Lipski Signed-off-by: Anson Jacob Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 6 +++++- .../gpu/drm/amd/display/dc/dcn301/dcn301_resource.c | 6 +++++- .../gpu/drm/amd/display/dc/dcn302/dcn302_resource.c | 6 +++++- .../gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 12 ++++++++++-- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 2feffe75ca625..3a8a3214f770d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -1164,8 +1164,12 @@ struct stream_encoder *dcn30_stream_encoder_create( vpg = dcn30_vpg_create(ctx, vpg_inst); afmt = dcn30_afmt_create(ctx, afmt_inst); - if (!enc1 || !vpg || !afmt) + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); return NULL; + } dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, vpg, afmt, diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c index 912285fdce18e..73b8fcb3c5c9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c @@ -1195,8 +1195,12 @@ struct stream_encoder *dcn301_stream_encoder_create( vpg = dcn301_vpg_create(ctx, vpg_inst); afmt = dcn301_afmt_create(ctx, afmt_inst); - if (!enc1 || !vpg || !afmt) + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); return NULL; + } dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, vpg, afmt, diff --git a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c index 5cd55e8573f70..fcf96cf08c761 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c @@ -542,8 +542,12 @@ static struct stream_encoder *dcn302_stream_encoder_create(enum engine_id eng_id vpg = dcn302_vpg_create(ctx, vpg_inst); afmt = dcn302_afmt_create(ctx, afmt_inst); - if (!enc1 || !vpg || !afmt) + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); return NULL; + } dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, vpg, afmt, &stream_enc_regs[eng_id], &se_shift, &se_mask); diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 91cbc0922ad43..e0b93665bf55a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -1366,8 +1366,12 @@ static struct stream_encoder *dcn31_stream_encoder_create( vpg = dcn31_vpg_create(ctx, vpg_inst); afmt = dcn31_afmt_create(ctx, afmt_inst); - if (!enc1 || !vpg || !afmt) + if (!enc1 || !vpg || !afmt) { + kfree(enc1); + kfree(vpg); + kfree(afmt); return NULL; + } dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, vpg, afmt, @@ -1412,8 +1416,12 @@ static struct hpo_dp_stream_encoder *dcn31_hpo_dp_stream_encoder_create( vpg = dcn31_vpg_create(ctx, vpg_inst); apg = dcn31_apg_create(ctx, apg_inst); - if (!hpo_dp_enc31 || !vpg || !apg) + if (!hpo_dp_enc31 || !vpg || !apg) { + kfree(hpo_dp_enc31); + kfree(vpg); + kfree(apg); return NULL; + } dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios, hpo_dp_inst, eng_id, vpg, apg, From 9e0d55ae545f4a8f4c00339ad97ee2ef9e8e06ff Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 16 Aug 2021 15:57:12 -0400 Subject: [PATCH 071/151] drm/amd/display: Get backlight from PWM if DMCU is not initialized On Carrizo/Stoney systems we set backlight through panel_cntl, i.e. directly via the PWM registers, if DMCU is not initialized. We always read it back through ABM registers which leads to a mismatch and forces atomic_commit to program the backlight each time. Instead make sure we use the same logic for backlight readback, i.e. read it from panel_cntl if DMCU is not initialized. We also need to remove some extraneous and incorrect calculations at the end of dce_get_16_bit_backlight_from_pwm. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1666 Cc: stable@vger.kernel.org Reviewed-by: Josip Pavic Acked-by: Mikita Lipski Signed-off-by: Harry Wentland Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 16 ++++++++++++---- .../gpu/drm/amd/display/dc/dce/dce_panel_cntl.c | 10 ---------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 3c8eb3e659af1..61e49671fed5e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -2752,13 +2752,21 @@ static struct abm *get_abm_from_stream_res(const struct dc_link *link) int dc_link_get_backlight_level(const struct dc_link *link) { - struct abm *abm = get_abm_from_stream_res(link); + struct panel_cntl *panel_cntl = link->panel_cntl; + struct dc *dc = link->ctx->dc; + struct dmcu *dmcu = dc->res_pool->dmcu; + bool fw_set_brightness = true; - if (abm == NULL || abm->funcs->get_current_backlight == NULL) - return DC_ERROR_UNEXPECTED; + if (dmcu) + fw_set_brightness = dmcu->funcs->is_dmcu_initialized(dmcu); - return (int) abm->funcs->get_current_backlight(abm); + if (!fw_set_brightness && panel_cntl->funcs->get_current_backlight) + return panel_cntl->funcs->get_current_backlight(panel_cntl); + else if (abm != NULL && abm->funcs->get_current_backlight != NULL) + return (int) abm->funcs->get_current_backlight(abm); + else + return DC_ERROR_UNEXPECTED; } int dc_link_get_target_backlight_pwm(const struct dc_link *link) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c index e923392358631..e8570060d007b 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c @@ -49,7 +49,6 @@ static unsigned int dce_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_cntl) { uint64_t current_backlight; - uint32_t round_result; uint32_t bl_period, bl_int_count; uint32_t bl_pwm, fractional_duty_cycle_en; uint32_t bl_period_mask, bl_pwm_mask; @@ -84,15 +83,6 @@ static unsigned int dce_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_c current_backlight = div_u64(current_backlight, bl_period); current_backlight = (current_backlight + 1) >> 1; - current_backlight = (uint64_t)(current_backlight) * bl_period; - - round_result = (uint32_t)(current_backlight & 0xFFFFFFFF); - - round_result = (round_result >> (bl_int_count-1)) & 1; - - current_backlight >>= bl_int_count; - current_backlight += round_result; - return (uint32_t)(current_backlight); } From 1131cadfd7563975f3a4efcc6f7c1fdc872db38b Mon Sep 17 00:00:00 2001 From: Anson Jacob Date: Tue, 24 Aug 2021 09:32:53 -0400 Subject: [PATCH 072/151] drm/amd/display: Revert "Directly retrain link from debugfs" This reverts commit f5b6a20c7ef40599095c796b0500d842ffdbc639. This patch broke new settings from taking effect. Hotplug is required for new settings to take effect. Reviewed-by: Mikita Lipski Acked-by: Mikita Lipski Signed-off-by: Anson Jacob Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 87daa78a32b8b..f3ada9b6be5a0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -247,6 +247,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf, { struct amdgpu_dm_connector *connector = file_inode(f)->i_private; struct dc_link *link = connector->dc_link; + struct dc *dc = (struct dc *)link->dc; struct dc_link_settings prefer_link_settings; char *wr_buf = NULL; const uint32_t wr_buf_size = 40; @@ -313,7 +314,7 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf, prefer_link_settings.lane_count = param[0]; prefer_link_settings.link_rate = param[1]; - dp_retrain_link_dp_test(link, &prefer_link_settings, false); + dc_link_set_preferred_training_settings(dc, &prefer_link_settings, NULL, link, true); kfree(wr_buf); return size; From d020970959169627d59a711769f8c4b87bf5f90c Mon Sep 17 00:00:00 2001 From: Jaehyun Chung Date: Tue, 24 Aug 2021 14:05:48 -0400 Subject: [PATCH 073/151] drm/amd/display: Add regamma/degamma coefficients and set sRGB when TF is BT709 [Why] In YUV case, need to set the input TF to sRGB instead of BT709, even though the input TF type is distributed. SRGB was not being used because pixel format was not being set in the surface update sequence. Also, we were using the same coefficients for degamma and regamma formula, causing the cutoff point of the linear section of the curve to be incorrect. [How] Set pixel format in the surface update sequence. Add separate coefficient arrays for regamma and degamma. Reviewed-by: Krunoslav Kovac Acked-by: Mikita Lipski Signed-off-by: Jaehyun Chung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/modules/color/color_gamma.c | 60 ++++++++++++------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c index ef742d95ef057..275f11f8bea3f 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c @@ -54,12 +54,18 @@ static struct hw_x_point coordinates_x[MAX_HW_POINTS + 2]; * just multiply with 2^gamma which can be computed once, and save the result so we * recursively compute all the values. */ - /*sRGB 709 2.2 2.4 P3*/ -static const int32_t gamma_numerator01[] = { 31308, 180000, 0, 0, 0}; -static const int32_t gamma_numerator02[] = { 12920, 4500, 0, 0, 0}; -static const int32_t gamma_numerator03[] = { 55, 99, 0, 0, 0}; -static const int32_t gamma_numerator04[] = { 55, 99, 0, 0, 0}; -static const int32_t gamma_numerator05[] = { 2400, 2200, 2200, 2400, 2600}; + /*sRGB 709 2.2 2.4 P3*/ +static const int32_t regamma_numerator01[] = { 31308, 180000, 0, 0, 0}; +static const int32_t regamma_numerator02[] = { 12920, 4500, 0, 0, 0}; +static const int32_t regamma_numerator03[] = { 55, 99, 0, 0, 0}; +static const int32_t regamma_numerator04[] = { 55, 99, 0, 0, 0}; +static const int32_t regamma_numerator05[] = { 2400, 2200, 2200, 2400, 2600}; + +static const int32_t degamma_numerator01[] = { 40450, 810000, 0, 0, 0}; +static const int32_t degamma_numerator02[] = { 12920, 4500, 0, 0, 0}; +static const int32_t degamma_numerator03[] = { 55, 99, 0, 0, 0}; +static const int32_t degamma_numerator04[] = { 55, 99, 0, 0, 0}; +static const int32_t degamma_numerator05[] = { 2400, 2200, 2200, 2400, 2600}; /* one-time setup of X points */ void setup_x_points_distribution(void) @@ -288,7 +294,8 @@ struct dividers { }; -static bool build_coefficients(struct gamma_coefficients *coefficients, enum dc_transfer_func_predefined type) +static bool build_coefficients(struct gamma_coefficients *coefficients, + enum dc_transfer_func_predefined type, bool isRegamma) { uint32_t i = 0; @@ -311,16 +318,29 @@ static bool build_coefficients(struct gamma_coefficients *coefficients, enum dc_ } do { - coefficients->a0[i] = dc_fixpt_from_fraction( - gamma_numerator01[index], 10000000); - coefficients->a1[i] = dc_fixpt_from_fraction( - gamma_numerator02[index], 1000); - coefficients->a2[i] = dc_fixpt_from_fraction( - gamma_numerator03[index], 1000); - coefficients->a3[i] = dc_fixpt_from_fraction( - gamma_numerator04[index], 1000); - coefficients->user_gamma[i] = dc_fixpt_from_fraction( - gamma_numerator05[index], 1000); + if (isRegamma) { + coefficients->a0[i] = dc_fixpt_from_fraction( + regamma_numerator01[index], 10000000); + coefficients->a1[i] = dc_fixpt_from_fraction( + regamma_numerator02[index], 1000); + coefficients->a2[i] = dc_fixpt_from_fraction( + regamma_numerator03[index], 1000); + coefficients->a3[i] = dc_fixpt_from_fraction( + regamma_numerator04[index], 1000); + coefficients->user_gamma[i] = dc_fixpt_from_fraction( + regamma_numerator05[index], 1000); + } else { + coefficients->a0[i] = dc_fixpt_from_fraction( + degamma_numerator01[index], 10000000); + coefficients->a1[i] = dc_fixpt_from_fraction( + degamma_numerator02[index], 1000); + coefficients->a2[i] = dc_fixpt_from_fraction( + degamma_numerator03[index], 1000); + coefficients->a3[i] = dc_fixpt_from_fraction( + degamma_numerator04[index], 1000); + coefficients->user_gamma[i] = dc_fixpt_from_fraction( + degamma_numerator05[index], 1000); + } ++i; } while (i != ARRAY_SIZE(coefficients->a0)); @@ -833,7 +853,7 @@ static bool build_regamma(struct pwl_float_data_ex *rgb_regamma, if (!coeff) goto release; - if (!build_coefficients(coeff, type)) + if (!build_coefficients(coeff, type, true)) goto release; memset(cal_buffer->buffer, 0, NUM_PTS_IN_REGION * sizeof(struct fixed31_32)); @@ -1082,7 +1102,7 @@ static bool build_degamma(struct pwl_float_data_ex *curve, uint32_t begin_index, end_index; bool ret = false; - if (!build_coefficients(&coeff, type)) + if (!build_coefficients(&coeff, type, false)) goto release; i = 0; @@ -1685,7 +1705,7 @@ static void apply_degamma_for_user_regamma(struct pwl_float_data_ex *rgb_regamma struct pwl_float_data_ex *rgb = rgb_regamma; const struct hw_x_point *coord_x = coordinates_x; - build_coefficients(&coeff, TRANSFER_FUNCTION_SRGB); + build_coefficients(&coeff, TRANSFER_FUNCTION_SRGB, true); i = 0; while (i != hw_points_num + 1) { From 2a50edbf10c8c56e930bfb53d8f9f00a33fd837e Mon Sep 17 00:00:00 2001 From: Qingqing Zhuo Date: Tue, 17 Aug 2021 16:29:07 -0400 Subject: [PATCH 074/151] drm/amd/display: Apply w/a for hard hang on HPD [Why] HPD disable and enable sequences are not mutually exclusive on Linux. For HPDs that spans under 1s (i.e. HPD low = 1s), part of the disable sequence (specifically, a request to SMU to lower refclk) could come right before the call to PHY enablement, causing DMUB to access an irresponsive PHY and thus a hard hang on the system. [How] Disable 48mhz refclk off when there is any HPD status in connected state. Reviewed-by: Hersen Wu Acked-by: Mikita Lipski Signed-off-by: Qingqing Zhuo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 12 ++++++++- .../display/dc/irq/dcn21/irq_service_dcn21.c | 25 +++++++++++++++++++ .../display/dc/irq/dcn21/irq_service_dcn21.h | 2 ++ .../gpu/drm/amd/display/dc/irq/irq_service.c | 2 +- .../gpu/drm/amd/display/dc/irq/irq_service.h | 4 +++ 5 files changed, 43 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index c6f494f0dcea3..3fabf32a05584 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -42,6 +42,7 @@ #include "clk/clk_10_0_2_sh_mask.h" #include "renoir_ip_offset.h" +#include "irq/dcn21/irq_service_dcn21.h" /* Constants */ @@ -129,9 +130,11 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base, struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; struct dc *dc = clk_mgr_base->ctx->dc; int display_count; + int irq_src; bool update_dppclk = false; bool update_dispclk = false; bool dpp_clock_lowered = false; + uint32_t hpd_state; struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu; @@ -147,8 +150,15 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base, if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) { display_count = rn_get_active_display_cnt_wa(dc, context); + + for (irq_src = DC_IRQ_SOURCE_HPD1; irq_src <= DC_IRQ_SOURCE_HPD5; irq_src++) { + hpd_state = dal_get_hpd_state_dcn21(dc->res_pool->irqs, irq_src); + if (hpd_state) + break; + } + /* if we can go lower, go lower */ - if (display_count == 0) { + if (display_count == 0 && !hpd_state) { rn_vbios_smu_set_dcn_low_power_state(clk_mgr, DCN_PWR_STATE_LOW_POWER); /* update power state */ clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c index ed54e1c819bed..685528734575d 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c @@ -135,6 +135,31 @@ enum dc_irq_source to_dal_irq_source_dcn21( return DC_IRQ_SOURCE_INVALID; } +uint32_t dal_get_hpd_state_dcn21(struct irq_service *irq_service, enum dc_irq_source source) +{ + const struct irq_source_info *info; + uint32_t addr; + uint32_t value; + uint32_t current_status; + + info = find_irq_source_info(irq_service, source); + if (!info) + return 0; + + addr = info->status_reg; + if (!addr) + return 0; + + value = dm_read_reg(irq_service->ctx, addr); + current_status = + get_reg_field_value( + value, + HPD0_DC_HPD_INT_STATUS, + DC_HPD_SENSE); + + return current_status; +} + static bool hpd_ack( struct irq_service *irq_service, const struct irq_source_info *info) diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h index da2bd0e93d7ad..3df2ceeb2b706 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h @@ -31,4 +31,6 @@ struct irq_service *dal_irq_service_dcn21_create( struct irq_service_init_data *init_data); +uint32_t dal_get_hpd_state_dcn21(struct irq_service *irq_service, enum dc_irq_source source); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index a2a4fbeb83f86..4db1133e4466b 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -79,7 +79,7 @@ void dal_irq_service_destroy(struct irq_service **irq_service) *irq_service = NULL; } -static const struct irq_source_info *find_irq_source_info( +const struct irq_source_info *find_irq_source_info( struct irq_service *irq_service, enum dc_irq_source source) { diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h index dbfcb096eedd6..e60b824800932 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h @@ -69,6 +69,10 @@ struct irq_service { const struct irq_service_funcs *funcs; }; +const struct irq_source_info *find_irq_source_info( + struct irq_service *irq_service, + enum dc_irq_source source); + void dal_irq_service_construct( struct irq_service *irq_service, struct irq_service_init_data *init_data); From 34316c1e561db0b24e341029f04a5a5bead9a7bc Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Thu, 19 Aug 2021 16:36:09 -0400 Subject: [PATCH 075/151] drm/amd/display: Optimize bandwidth on following fast update [Why] The current call to optimize_bandwidth never occurs because flip is always pending from the FULL and FAST updates. [How] Optimize on the following flip when it's a FAST update and we know we aren't going to be modifying the clocks again. Reviewed-by: Bhawanpreet Lakha Acked-by: Mikita Lipski Signed-off-by: Nicholas Kazlauskas Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index f58d3956f3e2a..822239b59a789 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1801,6 +1801,11 @@ void dc_post_update_surfaces_to_stream(struct dc *dc) post_surface_trace(dc); + if (dc->ctx->dce_version >= DCE_VERSION_MAX) + TRACE_DCN_CLOCK_STATE(&context->bw_ctx.bw.dcn.clk); + else + TRACE_DCE_CLOCK_STATE(&context->bw_ctx.bw.dce); + if (is_flip_pending_in_pipes(dc, context)) return; @@ -2986,6 +2991,9 @@ void dc_commit_updates_for_stream(struct dc *dc, if (new_pipe->plane_state && new_pipe->plane_state != old_pipe->plane_state) new_pipe->plane_state->force_full_update = true; } + } else if (update_type == UPDATE_TYPE_FAST) { + /* Previous frame finished and HW is ready for optimization. */ + dc_post_update_surfaces_to_stream(dc); } @@ -3042,15 +3050,6 @@ void dc_commit_updates_for_stream(struct dc *dc, pipe_ctx->plane_state->force_full_update = false; } } - /*let's use current_state to update watermark etc*/ - if (update_type >= UPDATE_TYPE_FULL) { - dc_post_update_surfaces_to_stream(dc); - - if (dc_ctx->dce_version >= DCE_VERSION_MAX) - TRACE_DCN_CLOCK_STATE(&context->bw_ctx.bw.dcn.clk); - else - TRACE_DCE_CLOCK_STATE(&context->bw_ctx.bw.dce); - } return; From 63f8bee439c0e3f94cff90d0f9c7b719be693265 Mon Sep 17 00:00:00 2001 From: Dale Zhao Date: Mon, 23 Aug 2021 16:44:37 +0800 Subject: [PATCH 076/151] drm/amd/display: Refine condition of cursor visibility for pipe-split [Why] In some scenarios like fullscreen game, major plane is scaled. Then if a upper layer owns the cursor, cursor is invisiable in the majority of the screen. [How] Instead assuming upper plane handles cursor, summing up upper split planes on the same layer. If whole upper plane covers current half/whole pipe plane, disable cursor. Reviewed-by: Krunoslav Kovac Acked-by: Mikita Lipski Signed-off-by: Dale Zhao Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index b4cf2e92694c0..e1edbfa761f1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -3241,13 +3241,11 @@ void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data) static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) { - struct pipe_ctx *test_pipe; + struct pipe_ctx *test_pipe, *split_pipe; const struct scaler_data *scl_data = &pipe_ctx->plane_res.scl_data; - const struct rect *r1 = &scl_data->recout, *r2; - int r1_r = r1->x + r1->width, r1_b = r1->y + r1->height, r2_r, r2_b; + struct rect r1 = scl_data->recout, r2, r2_half; + int r1_r = r1.x + r1.width, r1_b = r1.y + r1.height, r2_r, r2_b; int cur_layer = pipe_ctx->plane_state->layer_index; - bool upper_pipe_exists = false; - struct fixed31_32 one = dc_fixpt_from_int(1); /** * Disable the cursor if there's another pipe above this with a @@ -3256,26 +3254,33 @@ static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx) */ for (test_pipe = pipe_ctx->top_pipe; test_pipe; test_pipe = test_pipe->top_pipe) { - if (!test_pipe->plane_state->visible) + // Skip invisible layer and pipe-split plane on same layer + if (!test_pipe->plane_state->visible || test_pipe->plane_state->layer_index == cur_layer) continue; - r2 = &test_pipe->plane_res.scl_data.recout; - r2_r = r2->x + r2->width; - r2_b = r2->y + r2->height; + r2 = test_pipe->plane_res.scl_data.recout; + r2_r = r2.x + r2.width; + r2_b = r2.y + r2.height; + split_pipe = test_pipe; - if (r1->x >= r2->x && r1->y >= r2->y && r1_r <= r2_r && r1_b <= r2_b) - return true; + /** + * There is another half plane on same layer because of + * pipe-split, merge together per same height. + */ + for (split_pipe = pipe_ctx->top_pipe; split_pipe; + split_pipe = split_pipe->top_pipe) + if (split_pipe->plane_state->layer_index == test_pipe->plane_state->layer_index) { + r2_half = split_pipe->plane_res.scl_data.recout; + r2.x = (r2_half.x < r2.x) ? r2_half.x : r2.x; + r2.width = r2.width + r2_half.width; + r2_r = r2.x + r2.width; + break; + } - if (test_pipe->plane_state->layer_index < cur_layer) - upper_pipe_exists = true; + if (r1.x >= r2.x && r1.y >= r2.y && r1_r <= r2_r && r1_b <= r2_b) + return true; } - // if plane scaled, assume an upper plane can handle cursor if it exists. - if (upper_pipe_exists && - (scl_data->ratios.horz.value != one.value || - scl_data->ratios.vert.value != one.value)) - return true; - return false; } From 6513104ba4a808de07722ef4ffb960f0229752b4 Mon Sep 17 00:00:00 2001 From: Hersen Wu Date: Wed, 25 Aug 2021 16:27:47 -0400 Subject: [PATCH 077/151] drm/amd/display: dsc mst 2 4K displays go dark with 2 lane HBR3 [Why] call stack of amdgpu dsc mst pbn, slot num calculation is as below: -compute_bpp_x16_from_target_bandwidth -decide_dsc_target_bpp_x16 -setup_dsc_config -dc_dsc_compute_bandwidth_range -compute_mst_dsc_configs_for_link -compute_mst_dsc_configs_for_state from pbn -> dsc target bpp_x16 bpp_x16 is calulated by compute_bpp_x16_from_target_bandwidth. Beside pixel clock and bpp, num_slices_h and bpp_increment_div will also affect bpp_x16. from dsc target bpp_x16 -> pbn within dm_update_mst_vcpi_slots_for_dsc, pbn = drm_dp_calc_pbn_mode(clock, bpp_x16, true); drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc) { return DIV_ROUND_UP_ULL(mul_u32_u32(clock * (bpp / 16), 64 * 1006), 8 * 54 * 1000 * 1000); } bpp / 16 trunc digits after decimal point. This will cause calculation delta. drm_dp_calc_pbn_mode does not have other informations, like num_slices_h, bpp_increment_div. therefore, it does not do revese calcuation properly from bpp_x16 to pbn. pbn from drm_dp_calc_pbn_mode is less than pbn from compute_mst_dsc_configs_for_state. This cause not enough mst slot allocated to display. display could not visually light up. [How] pass pbn from compute_mst_dsc_configs_for_state to dm_update_mst_vcpi_slots_for_dsc Cc: stable@vger.kernel.org Reviewed-by: Scott Foster Acked-by: Mikita Lipski Signed-off-by: Hersen Wu Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 22 ++++++++++++++----- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 18 +++++++-------- .../display/amdgpu_dm/amdgpu_dm_mst_types.h | 11 +++++++++- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 283d660a0a66f..24cd4c819e99a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7092,14 +7092,15 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { #if defined(CONFIG_DRM_AMD_DC_DCN) static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, - struct dc_state *dc_state) + struct dc_state *dc_state, + struct dsc_mst_fairness_vars *vars) { struct dc_stream_state *stream = NULL; struct drm_connector *connector; struct drm_connector_state *new_con_state; struct amdgpu_dm_connector *aconnector; struct dm_connector_state *dm_conn_state; - int i, j, clock, bpp; + int i, j, clock; int vcpi, pbn_div, pbn = 0; for_each_new_connector_in_state(state, connector, new_con_state, i) { @@ -7138,9 +7139,15 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, } pbn_div = dm_mst_get_pbn_divider(stream->link); - bpp = stream->timing.dsc_cfg.bits_per_pixel; clock = stream->timing.pix_clk_100hz / 10; - pbn = drm_dp_calc_pbn_mode(clock, bpp, true); + /* pbn is calculated by compute_mst_dsc_configs_for_state*/ + for (j = 0; j < dc_state->stream_count; j++) { + if (vars[j].aconnector == aconnector) { + pbn = vars[j].pbn; + break; + } + } + vcpi = drm_dp_mst_atomic_enable_dsc(state, aconnector->port, pbn, pbn_div, @@ -10546,6 +10553,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, int ret, i; bool lock_and_validation_needed = false; struct dm_crtc_state *dm_old_crtc_state; +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct dsc_mst_fairness_vars vars[MAX_PIPES]; +#endif trace_amdgpu_dm_atomic_check_begin(state); @@ -10776,10 +10786,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; #if defined(CONFIG_DRM_AMD_DC_DCN) - if (!compute_mst_dsc_configs_for_state(state, dm_state->context)) + if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) goto fail; - ret = dm_update_mst_vcpi_slots_for_dsc(state, dm_state->context); + ret = dm_update_mst_vcpi_slots_for_dsc(state, dm_state->context, vars); if (ret) goto fail; #endif diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 705f2e67edb5e..1a99fcc270782 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -518,12 +518,7 @@ struct dsc_mst_fairness_params { uint32_t num_slices_h; uint32_t num_slices_v; uint32_t bpp_overwrite; -}; - -struct dsc_mst_fairness_vars { - int pbn; - bool dsc_enabled; - int bpp_x16; + struct amdgpu_dm_connector *aconnector; }; static int kbps_to_peak_pbn(int kbps) @@ -750,12 +745,12 @@ static void try_disable_dsc(struct drm_atomic_state *state, static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, struct dc_state *dc_state, - struct dc_link *dc_link) + struct dc_link *dc_link, + struct dsc_mst_fairness_vars *vars) { int i; struct dc_stream_state *stream; struct dsc_mst_fairness_params params[MAX_PIPES]; - struct dsc_mst_fairness_vars vars[MAX_PIPES]; struct amdgpu_dm_connector *aconnector; int count = 0; bool debugfs_overwrite = false; @@ -776,6 +771,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, params[count].timing = &stream->timing; params[count].sink = stream->sink; aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; + params[count].aconnector = aconnector; params[count].port = aconnector->port; params[count].clock_force_enable = aconnector->dsc_settings.dsc_force_enable; if (params[count].clock_force_enable == DSC_CLK_FORCE_ENABLE) @@ -798,6 +794,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, } /* Try no compression */ for (i = 0; i < count; i++) { + vars[i].aconnector = params[i].aconnector; vars[i].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); vars[i].dsc_enabled = false; vars[i].bpp_x16 = 0; @@ -851,7 +848,8 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, } bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, - struct dc_state *dc_state) + struct dc_state *dc_state, + struct dsc_mst_fairness_vars *vars) { int i, j; struct dc_stream_state *stream; @@ -882,7 +880,7 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, return false; mutex_lock(&aconnector->mst_mgr.lock); - if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link)) { + if (!compute_mst_dsc_configs_for_link(state, dc_state, stream->link, vars)) { mutex_unlock(&aconnector->mst_mgr.lock); return false; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index b38bd68121ceb..900d3f7a84989 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -39,8 +39,17 @@ void dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev); #if defined(CONFIG_DRM_AMD_DC_DCN) + +struct dsc_mst_fairness_vars { + int pbn; + bool dsc_enabled; + int bpp_x16; + struct amdgpu_dm_connector *aconnector; +}; + bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state, - struct dc_state *dc_state); + struct dc_state *dc_state, + struct dsc_mst_fairness_vars *vars); #endif #endif From ac02dc34258569b793b78483154ca336f103946f Mon Sep 17 00:00:00 2001 From: Eric Yang Date: Wed, 25 Aug 2021 20:02:22 -0400 Subject: [PATCH 078/151] drm/amd/display: Add periodic detection when zstate is enabled [Why] When system is in Z10 HPD interrupts cannot fire, we may miss display configuration changes. [How] When Zstate is enabled, if DMUB indicate DCN has lost power, do a complete detection periodically. Reviewed-by: Nicholas Kazlauskas Acked-by: Mikita Lipski Signed-off-by: Eric Yang Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 6 ++++++ .../drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 2 ++ drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++++ drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h | 2 +- drivers/gpu/drm/amd/display/dc/dm_helpers.h | 4 ++++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 4 ++++ drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 8 ++++++++ drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h | 2 ++ drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c | 10 +++++++++- 13 files changed, 44 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 8c17926378367..1aa69dd8e02f4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -793,4 +793,10 @@ void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz) // FPGA programming for this clock in diags framework that // needs to go through dm layer, therefore leave dummy interace here } + + +void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable) +{ + /* TODO: add peridic detection implementation */ +} #endif \ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 1414da4b95d7c..d7bf9283dc907 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -142,6 +142,7 @@ static void dcn31_update_clocks(struct clk_mgr *clk_mgr_base, if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_ALLOW && new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { dcn31_smu_set_Z9_support(clk_mgr, true); + dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true); clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; } @@ -166,6 +167,7 @@ static void dcn31_update_clocks(struct clk_mgr *clk_mgr_base, if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW && new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { dcn31_smu_set_Z9_support(clk_mgr, false); + dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false); clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 822239b59a789..7a1f910d711e4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1562,7 +1562,7 @@ static uint8_t get_stream_mask(struct dc *dc, struct dc_state *context) } #if defined(CONFIG_DRM_AMD_DC_DCN) -void dc_z10_restore(struct dc *dc) +void dc_z10_restore(const struct dc *dc) { if (dc->hwss.z10_restore) dc->hwss.z10_restore(dc); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 61e49671fed5e..46933a43ef2e9 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1250,6 +1250,10 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) } } +#if defined(CONFIG_DRM_AMD_DC_DCN) + dc_z10_restore(dc); +#endif + /* get out of low power state */ if (!can_apply_seamless_boot && reason != DETECT_REASON_BOOT) clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ece44796a74fa..134faa7a19373 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1363,7 +1363,7 @@ void dc_hardware_release(struct dc *dc); bool dc_set_psr_allow_active(struct dc *dc, bool enable); #if defined(CONFIG_DRM_AMD_DC_DCN) -void dc_z10_restore(struct dc *dc); +void dc_z10_restore(const struct dc *dc); void dc_z10_save_init(struct dc *dc); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c index 83f223d745fa2..d3598ce1f5de1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c @@ -425,7 +425,7 @@ void dcn31_z10_save_init(struct dc *dc) dc_dmub_srv_wait_idle(dc->ctx->dmub_srv); } -void dcn31_z10_restore(struct dc *dc) +void dcn31_z10_restore(const struct dc *dc) { union dmub_rb_cmd cmd; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h index 140435e4f7fff..7ae45dd202d9b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h @@ -43,7 +43,7 @@ void dcn31_enable_power_gating_plane( void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx); -void dcn31_z10_restore(struct dc *dc); +void dcn31_z10_restore(const struct dc *dc); void dcn31_z10_save_init(struct dc *dc); void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on); diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index 8de554fb98b9b..3a905fb667bf4 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -160,6 +160,10 @@ void dm_set_dcn_clocks( struct dc_context *ctx, struct dc_clocks *clks); +#if defined(CONFIG_DRM_AMD_DC_DCN) +void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable); +#endif + void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz); bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index ad5f2adcc40d5..d50f4bd06b5d9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -236,7 +236,7 @@ struct hw_sequencer_funcs { const struct tg_color *solid_color, int width, int height, int offset); - void (*z10_restore)(struct dc *dc); + void (*z10_restore)(const struct dc *dc); void (*z10_save_init)(struct dc *dc); void (*update_visual_confirm_color)(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index caf961bb633f6..ef324fc393151 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -358,6 +358,8 @@ struct dmub_srv_hw_funcs { uint32_t (*get_current_time)(struct dmub_srv *dmub); void (*get_diagnostic_data)(struct dmub_srv *dmub, struct dmub_diagnostic_data *dmub_oca); + + bool (*should_detect)(struct dmub_srv *dmub); }; /** @@ -724,6 +726,8 @@ bool dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entr bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data); +bool dmub_srv_should_detect(struct dmub_srv *dmub); + #if defined(__cplusplus) } #endif diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c index fc667cb17eb07..6ac370c15dea2 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c @@ -432,3 +432,11 @@ void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); diag_data->is_cw6_enabled = is_cw6_enabled; } + +bool dmub_dcn31_should_detect(struct dmub_srv *dmub) +{ + uint32_t fw_boot_status = REG_READ(DMCUB_SCRATCH0); + bool should_detect = fw_boot_status & DMUB_FW_BOOT_STATUS_BIT_DETECTION_REQUIRED; + return should_detect; +} + diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h index bb62605d2ac89..59ddc81b5a0e4 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h @@ -245,4 +245,6 @@ uint32_t dmub_dcn31_get_current_time(struct dmub_srv *dmub); void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data); +bool dmub_dcn31_should_detect(struct dmub_srv *dmub); + #endif /* _DMUB_DCN31_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index 75a91cfaf0360..a6188d067d655 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -234,7 +234,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) funcs->set_outbox0_rptr = dmub_dcn31_set_outbox0_rptr; funcs->get_diagnostic_data = dmub_dcn31_get_diagnostic_data; - + funcs->should_detect = dmub_dcn31_should_detect; funcs->get_current_time = dmub_dcn31_get_current_time; break; @@ -816,3 +816,11 @@ bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_ dmub->hw_funcs.get_diagnostic_data(dmub, diag_data); return true; } + +bool dmub_srv_should_detect(struct dmub_srv *dmub) +{ + if (!dmub->hw_init || !dmub->hw_funcs.should_detect) + return false; + + return dmub->hw_funcs.should_detect(dmub); +} From c580afa2c0c24645fbe6d0275ca7d58c8b2270b5 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 27 Aug 2021 17:15:35 -0400 Subject: [PATCH 079/151] drm/amd/display: [FW Promotion] Release 0.0.82 * PSR SMU optimizations * MST dock fixes Reviewed-by: Anthony Koo Acked-by: Mikita Lipski Signed-off-by: Anthony Koo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 8cf86f7cda418..2c4ec3cac70e8 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -47,10 +47,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x8ebc06e16 +#define DMUB_FW_VERSION_GIT_HASH 0x3f002dea8 #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 81 +#define DMUB_FW_VERSION_REVISION 82 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 From 1b76cd177288bc2ca6ff05ec244361271151a57d Mon Sep 17 00:00:00 2001 From: Jaehyun Chung Date: Fri, 27 Aug 2021 16:10:54 -0400 Subject: [PATCH 080/151] drm/amd/display: Correct degamma coefficients [Why] Some incorrect coefficients were being used Reviewed-by: Michael Strauss Acked-by: Mikita Lipski Signed-off-by: Jaehyun Chung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/modules/color/color_gamma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c index 275f11f8bea3f..2465c88e28793 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c @@ -61,7 +61,7 @@ static const int32_t regamma_numerator03[] = { 55, 99, 0, 0, 0}; static const int32_t regamma_numerator04[] = { 55, 99, 0, 0, 0}; static const int32_t regamma_numerator05[] = { 2400, 2200, 2200, 2400, 2600}; -static const int32_t degamma_numerator01[] = { 40450, 810000, 0, 0, 0}; +static const int32_t degamma_numerator01[] = { 404500, 180000, 0, 0, 0}; static const int32_t degamma_numerator02[] = { 12920, 4500, 0, 0, 0}; static const int32_t degamma_numerator03[] = { 55, 99, 0, 0, 0}; static const int32_t degamma_numerator04[] = { 55, 99, 0, 0, 0}; From 68e1634d5fdaee73fc4e628905a2be715df744db Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 29 Aug 2021 18:44:22 -0400 Subject: [PATCH 081/151] drm/amd/display: 3.2.152 * Correct degamma coefficients * Optimize bandwidth on following fast update * Fix multiple memory leaks reported by coverity * Get backlight from PWM if DMCU is not initialized Acked-by: Mikita Lipski Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 134faa7a19373..4426053544303 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -45,7 +45,7 @@ /* forward declaration */ struct aux_payload; -#define DC_VER "3.2.151" +#define DC_VER "3.2.152" #define MAX_SURFACES 3 #define MAX_PLANES 6 From 0d9a947b5cbb80780ca4202ea82568e07f0fc720 Mon Sep 17 00:00:00 2001 From: Qingqing Zhuo Date: Fri, 27 Aug 2021 06:58:38 -0400 Subject: [PATCH 082/151] drm/amd/display: Fix unstable HPCP compliance on Chrome Barcelo [Why] Intermittently, there presents two occurrences of 0 stream commits in a single HPD event. Current HDCP sequence does not consider such scenerio, and will thus disable HDCP. [How] Add condition check to include stream remove and re-enable case for HDCP enable. Reviewed-by: Bhawanpreet Lakha Acked-by: Mikita Lipski Signed-off-by: Qingqing Zhuo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 24cd4c819e99a..85d1304b8236e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8365,8 +8365,26 @@ static bool is_content_protection_different(struct drm_connector_state *state, state->content_protection == DRM_MODE_CONTENT_PROTECTION_ENABLED) state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; - /* Check if something is connected/enabled, otherwise we start hdcp but nothing is connected/enabled - * hot-plug, headless s3, dpms + /* Stream removed and re-enabled + * + * Can sometimes overlap with the HPD case, + * thus set update_hdcp to false to avoid + * setting HDCP multiple times. + * + * Handles: DESIRED -> DESIRED (Special case) + */ + if (!(old_state->crtc && old_state->crtc->enabled) && + state->crtc && state->crtc->enabled && + connector->state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) { + dm_con_state->update_hdcp = false; + return true; + } + + /* Hot-plug, headless s3, dpms + * + * Only start HDCP if the display is connected/enabled. + * update_hdcp flag will be set to false until the next + * HPD comes in. * * Handles: DESIRED -> DESIRED (Special case) */ From db7b568e6d995d8395bb904a8df0b629271c5a45 Mon Sep 17 00:00:00 2001 From: Meenakshikumar Somasundaram Date: Mon, 30 Aug 2021 14:01:10 -0400 Subject: [PATCH 083/151] drm/amd/display: Link training retry fix for abort case [Why] If link training is aborted, it shall be retried if sink is present. [How] Check hpd status to find out whether sink is present or not. If sink is present, then link training shall be tried again with same settings. Otherwise, link training shall be aborted. Reviewed-by: Jimmy Kizito Acked-by: Mikita Lipski Signed-off-by: Meenakshikumar Somasundaram Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 07c2343185bd6..6663cfc4eb71b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2433,9 +2433,13 @@ bool perform_link_training_with_retries( dp_disable_link_phy(link, signal); /* Abort link training if failure due to sink being unplugged. */ - if (status == LINK_TRAINING_ABORT) - break; - else if (do_fallback) { + if (status == LINK_TRAINING_ABORT) { + enum dc_connection_type type = dc_connection_none; + + dc_link_detect_sink(link, &type); + if (type == dc_connection_none) + break; + } else if (do_fallback) { decide_fallback_link_setting(*link_setting, ¤t_setting, status); /* Fail link training if reduced link bandwidth no longer meets * stream requirements. From 9b3d76527f6ea50270f7f7ac749493b41783e8bd Mon Sep 17 00:00:00 2001 From: Jaehyun Chung Date: Mon, 30 Aug 2021 16:46:42 -0400 Subject: [PATCH 084/151] drm/amd/display: Revert adding degamma coefficients [Why] Degamma coefficients are calculated in our degamma formula using the regamma coefficients. We do not need to add separate degamma coefficients. [How] Remove the change to add separate degamma coefficients. Reviewed-by: Krunoslav Kovac Acked-by: Mikita Lipski Signed-off-by: Jaehyun Chung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/modules/color/color_gamma.c | 64 ++++++++----------- 1 file changed, 25 insertions(+), 39 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c index 2465c88e28793..64a38f08f4974 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c @@ -54,18 +54,17 @@ static struct hw_x_point coordinates_x[MAX_HW_POINTS + 2]; * just multiply with 2^gamma which can be computed once, and save the result so we * recursively compute all the values. */ - /*sRGB 709 2.2 2.4 P3*/ -static const int32_t regamma_numerator01[] = { 31308, 180000, 0, 0, 0}; -static const int32_t regamma_numerator02[] = { 12920, 4500, 0, 0, 0}; -static const int32_t regamma_numerator03[] = { 55, 99, 0, 0, 0}; -static const int32_t regamma_numerator04[] = { 55, 99, 0, 0, 0}; -static const int32_t regamma_numerator05[] = { 2400, 2200, 2200, 2400, 2600}; - -static const int32_t degamma_numerator01[] = { 404500, 180000, 0, 0, 0}; -static const int32_t degamma_numerator02[] = { 12920, 4500, 0, 0, 0}; -static const int32_t degamma_numerator03[] = { 55, 99, 0, 0, 0}; -static const int32_t degamma_numerator04[] = { 55, 99, 0, 0, 0}; -static const int32_t degamma_numerator05[] = { 2400, 2200, 2200, 2400, 2600}; + +/* + * Regamma coefficients are used for both regamma and degamma. Degamma + * coefficients are calculated in our formula using the regamma coefficients. + */ + /*sRGB 709 2.2 2.4 P3*/ +static const int32_t numerator01[] = { 31308, 180000, 0, 0, 0}; +static const int32_t numerator02[] = { 12920, 4500, 0, 0, 0}; +static const int32_t numerator03[] = { 55, 99, 0, 0, 0}; +static const int32_t numerator04[] = { 55, 99, 0, 0, 0}; +static const int32_t numerator05[] = { 2400, 2200, 2200, 2400, 2600}; /* one-time setup of X points */ void setup_x_points_distribution(void) @@ -295,7 +294,7 @@ struct dividers { static bool build_coefficients(struct gamma_coefficients *coefficients, - enum dc_transfer_func_predefined type, bool isRegamma) + enum dc_transfer_func_predefined type) { uint32_t i = 0; @@ -318,29 +317,16 @@ static bool build_coefficients(struct gamma_coefficients *coefficients, } do { - if (isRegamma) { - coefficients->a0[i] = dc_fixpt_from_fraction( - regamma_numerator01[index], 10000000); - coefficients->a1[i] = dc_fixpt_from_fraction( - regamma_numerator02[index], 1000); - coefficients->a2[i] = dc_fixpt_from_fraction( - regamma_numerator03[index], 1000); - coefficients->a3[i] = dc_fixpt_from_fraction( - regamma_numerator04[index], 1000); - coefficients->user_gamma[i] = dc_fixpt_from_fraction( - regamma_numerator05[index], 1000); - } else { - coefficients->a0[i] = dc_fixpt_from_fraction( - degamma_numerator01[index], 10000000); - coefficients->a1[i] = dc_fixpt_from_fraction( - degamma_numerator02[index], 1000); - coefficients->a2[i] = dc_fixpt_from_fraction( - degamma_numerator03[index], 1000); - coefficients->a3[i] = dc_fixpt_from_fraction( - degamma_numerator04[index], 1000); - coefficients->user_gamma[i] = dc_fixpt_from_fraction( - degamma_numerator05[index], 1000); - } + coefficients->a0[i] = dc_fixpt_from_fraction( + numerator01[index], 10000000); + coefficients->a1[i] = dc_fixpt_from_fraction( + numerator02[index], 1000); + coefficients->a2[i] = dc_fixpt_from_fraction( + numerator03[index], 1000); + coefficients->a3[i] = dc_fixpt_from_fraction( + numerator04[index], 1000); + coefficients->user_gamma[i] = dc_fixpt_from_fraction( + numerator05[index], 1000); ++i; } while (i != ARRAY_SIZE(coefficients->a0)); @@ -853,7 +839,7 @@ static bool build_regamma(struct pwl_float_data_ex *rgb_regamma, if (!coeff) goto release; - if (!build_coefficients(coeff, type, true)) + if (!build_coefficients(coeff, type)) goto release; memset(cal_buffer->buffer, 0, NUM_PTS_IN_REGION * sizeof(struct fixed31_32)); @@ -1102,7 +1088,7 @@ static bool build_degamma(struct pwl_float_data_ex *curve, uint32_t begin_index, end_index; bool ret = false; - if (!build_coefficients(&coeff, type, false)) + if (!build_coefficients(&coeff, type)) goto release; i = 0; @@ -1705,7 +1691,7 @@ static void apply_degamma_for_user_regamma(struct pwl_float_data_ex *rgb_regamma struct pwl_float_data_ex *rgb = rgb_regamma; const struct hw_x_point *coord_x = coordinates_x; - build_coefficients(&coeff, TRANSFER_FUNCTION_SRGB, true); + build_coefficients(&coeff, true); i = 0; while (i != hw_points_num + 1) { From 18b4f1a022951df15a446e485f8e4e506d535b3e Mon Sep 17 00:00:00 2001 From: Michael Strauss Date: Mon, 23 Aug 2021 10:47:49 -0400 Subject: [PATCH 085/151] drm/amd/display: Add VPG and AFMT low power support for DCN3.1 [WHY] Power down VPG and AFMT blocks when not in use [HOW] Create afmt31 and vpg31 structs and add necessary fields to reg list Reviewed-by: Eric Yang Acked-by: Mikita Lipski Signed-off-by: Michael Strauss Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 ++ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 17 ++ drivers/gpu/drm/amd/display/dc/dc.h | 2 + .../display/dc/dcn10/dcn10_stream_encoder.c | 10 ++ .../gpu/drm/amd/display/dc/dcn30/dcn30_afmt.c | 24 ++- .../gpu/drm/amd/display/dc/dcn30/dcn30_afmt.h | 24 +++ .../dc/dcn30/dcn30_dio_stream_encoder.c | 2 + .../gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c | 2 +- .../gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h | 11 ++ drivers/gpu/drm/amd/display/dc/dcn31/Makefile | 3 +- .../gpu/drm/amd/display/dc/dcn31/dcn31_afmt.c | 92 ++++++++++ .../gpu/drm/amd/display/dc/dcn31/dcn31_afmt.h | 126 ++++++++++++++ .../drm/amd/display/dc/dcn31/dcn31_resource.c | 50 +++--- .../gpu/drm/amd/display/dc/dcn31/dcn31_vpg.c | 87 ++++++++++ .../gpu/drm/amd/display/dc/dcn31/dcn31_vpg.h | 162 ++++++++++++++++++ 15 files changed, 593 insertions(+), 29 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_afmt.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_afmt.h create mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.c create mode 100644 drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.h diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7a1f910d711e4..e362ec65349de 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -71,6 +71,8 @@ #include "dmub/dmub_srv.h" +#include "dcn30/dcn30_vpg.h" + #include "i2caux_interface.h" #include "dce/dmub_hw_lock_mgr.h" @@ -2555,6 +2557,9 @@ static void commit_planes_do_stream_update(struct dc *dc, enum surface_update_type update_type, struct dc_state *context) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct vpg *vpg; +#endif int j; // Stream updates @@ -2575,6 +2580,11 @@ static void commit_planes_do_stream_update(struct dc *dc, stream_update->vrr_infopacket || stream_update->vsc_infopacket || stream_update->vsp_infopacket) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + vpg = pipe_ctx->stream_res.stream_enc->vpg; + if (vpg && vpg->funcs->vpg_poweron) + vpg->funcs->vpg_poweron(vpg); +#endif resource_build_info_frame(pipe_ctx); dc->hwss.update_info_frame(pipe_ctx); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 46933a43ef2e9..9c5dbcf42f46f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -51,6 +51,8 @@ #include "inc/link_enc_cfg.h" #include "inc/link_dpcd.h" +#include "dc/dcn30/dcn30_vpg.h" + #define DC_LOGGER_INIT(logger) #define LINK_INFO(...) \ @@ -3608,6 +3610,7 @@ void core_link_enable_stream( struct link_encoder *link_enc; #if defined(CONFIG_DRM_AMD_DC_DCN) enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO; + struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg; #endif DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); @@ -3699,6 +3702,12 @@ void core_link_enable_stream( pipe_ctx->stream->apply_edp_fast_boot_optimization = false; +#if defined(CONFIG_DRM_AMD_DC_DCN) + // Enable VPG before building infoframe + if (vpg && vpg->funcs->vpg_poweron) + vpg->funcs->vpg_poweron(vpg); +#endif + resource_build_info_frame(pipe_ctx); dc->hwss.update_info_frame(pipe_ctx); @@ -3845,6 +3854,9 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) struct dc *dc = pipe_ctx->stream->ctx->dc; struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; +#if defined(CONFIG_DRM_AMD_DC_DCN) + struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg; +#endif if (!IS_DIAG_DC(dc->ctx->dce_environment) && dc_is_virtual_signal(pipe_ctx->stream->signal)) @@ -3928,6 +3940,11 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, OUT_MUX_DIO); } #endif + +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (vpg && vpg->funcs->vpg_powerdown) + vpg->funcs->vpg_powerdown(vpg); +#endif } void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4426053544303..15b67239266e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -471,6 +471,8 @@ union mem_low_power_enable_options { bool cm: 1; bool mpc: 1; bool optc: 1; + bool vpg: 1; + bool afmt: 1; } bits; uint32_t u32All; }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index b7d55212dc8f2..a97bdaa54f734 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -31,6 +31,7 @@ #include "hw_shared.h" #include "inc/link_dpcd.h" #include "dpcd_defs.h" +#include "dcn30/dcn30_afmt.h" #define DC_LOGGER \ enc1->base.ctx->logger @@ -1401,6 +1402,11 @@ static void enc1_se_disable_dp_audio( struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); uint32_t value = 0; +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (enc->afmt && enc->afmt->funcs->afmt_powerdown) + enc->afmt->funcs->afmt_powerdown(enc->afmt); +#endif + /* Disable Audio packets */ REG_UPDATE_5(DP_SEC_CNTL, DP_SEC_ASP_ENABLE, 0, @@ -1464,6 +1470,10 @@ void enc1_se_hdmi_audio_setup( void enc1_se_hdmi_audio_disable( struct stream_encoder *enc) { +#if defined(CONFIG_DRM_AMD_DC_DCN) + if (enc->afmt && enc->afmt->funcs->afmt_powerdown) + enc->afmt->funcs->afmt_powerdown(enc->afmt); +#endif enc1_se_enable_audio_clock(enc, false); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.c index fa981cd04dd0b..95528e5ef89e1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.c @@ -44,11 +44,14 @@ afmt3->base.ctx -static void afmt3_setup_hdmi_audio( +void afmt3_setup_hdmi_audio( struct afmt *afmt) { struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt); + if (afmt->funcs->afmt_poweron) + afmt->funcs->afmt_poweron(afmt); + /* AFMT_AUDIO_PACKET_CONTROL */ REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); @@ -113,7 +116,7 @@ static union audio_cea_channels speakers_to_channels( return cea_channels; } -static void afmt3_se_audio_setup( +void afmt3_se_audio_setup( struct afmt *afmt, unsigned int az_inst, struct audio_info *audio_info) @@ -138,20 +141,24 @@ static void afmt3_se_audio_setup( REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, channels); /* Disable forced mem power off */ - REG_UPDATE(AFMT_MEM_PWR, AFMT_MEM_PWR_FORCE, 0); + if (afmt->funcs->afmt_poweron == NULL) + REG_UPDATE(AFMT_MEM_PWR, AFMT_MEM_PWR_FORCE, 0); } -static void afmt3_audio_mute_control( +void afmt3_audio_mute_control( struct afmt *afmt, bool mute) { struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt); - + if (mute && afmt->funcs->afmt_powerdown) + afmt->funcs->afmt_powerdown(afmt); + if (!mute && afmt->funcs->afmt_poweron) + afmt->funcs->afmt_poweron(afmt); /* enable/disable transmission of audio packets */ REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, !mute); } -static void afmt3_audio_info_immediate_update( +void afmt3_audio_info_immediate_update( struct afmt *afmt) { struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt); @@ -160,11 +167,14 @@ static void afmt3_audio_info_immediate_update( REG_UPDATE(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, 1); } -static void afmt3_setup_dp_audio( +void afmt3_setup_dp_audio( struct afmt *afmt) { struct dcn30_afmt *afmt3 = DCN30_AFMT_FROM_AFMT(afmt); + if (afmt->funcs->afmt_poweron) + afmt->funcs->afmt_poweron(afmt); + /* AFMT_AUDIO_PACKET_CONTROL */ REG_UPDATE(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, 1); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.h index 85d4619207e20..97e0cf62f98e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_afmt.h @@ -121,6 +121,12 @@ struct afmt_funcs { void (*setup_dp_audio)( struct afmt *afmt); + + void (*afmt_poweron)( + struct afmt *afmt); + + void (*afmt_powerdown)( + struct afmt *afmt); }; struct afmt { @@ -136,6 +142,24 @@ struct dcn30_afmt { const struct dcn30_afmt_mask *afmt_mask; }; +void afmt3_setup_hdmi_audio( + struct afmt *afmt); + +void afmt3_se_audio_setup( + struct afmt *afmt, + unsigned int az_inst, + struct audio_info *audio_info); + +void afmt3_audio_mute_control( + struct afmt *afmt, + bool mute); + +void afmt3_audio_info_immediate_update( + struct afmt *afmt); + +void afmt3_setup_dp_audio( + struct afmt *afmt); + void afmt3_construct(struct dcn30_afmt *afmt3, struct dc_context *ctx, uint32_t inst, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c index 8487516819ef2..b73dfd2661b91 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c @@ -704,6 +704,8 @@ static void enc3_se_setup_dp_audio( static void enc3_se_dp_audio_enable( struct stream_encoder *enc) { + if (enc->afmt->funcs->afmt_poweron) + enc->afmt->funcs->afmt_poweron(enc->afmt); enc1_se_enable_audio_clock(enc, true); enc3_se_setup_dp_audio(enc); enc1_se_enable_dp_audio(enc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c index 8cfd181b4d5f7..9748aaa044f70 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c @@ -43,7 +43,7 @@ vpg3->base.ctx -static void vpg3_update_generic_info_packet( +void vpg3_update_generic_info_packet( struct vpg *vpg, uint32_t packet_index, const struct dc_info_packet *info_packet) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h index 6161e9e663556..96dccb2f1124a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h @@ -139,6 +139,12 @@ struct vpg_funcs { struct vpg *vpg, uint32_t packet_index, const struct dc_info_packet *info_packet); + + void (*vpg_poweron)( + struct vpg *vpg); + + void (*vpg_powerdown)( + struct vpg *vpg); }; struct vpg { @@ -154,6 +160,11 @@ struct dcn30_vpg { const struct dcn30_vpg_mask *vpg_mask; }; +void vpg3_update_generic_info_packet( + struct vpg *vpg, + uint32_t packet_index, + const struct dc_info_packet *info_packet); + void vpg3_construct(struct dcn30_vpg *vpg3, struct dc_context *ctx, uint32_t inst, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile index 5197825e79656..d20e3b8ccc306 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile @@ -12,7 +12,8 @@ DCN31 = dcn31_resource.o dcn31_hubbub.o dcn31_hwseq.o dcn31_init.o dcn31_hubp.o \ dcn31_dccg.o dcn31_optc.o dcn31_dio_link_encoder.o dcn31_panel_cntl.o \ - dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o + dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o \ + dcn31_afmt.o dcn31_vpg.o ifdef CONFIG_X86 CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o := -msse diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_afmt.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_afmt.c new file mode 100644 index 0000000000000..d380a8ec21843 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_afmt.c @@ -0,0 +1,92 @@ +/* + * Copyright 2019 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 + * + */ + +#include "dc_bios_types.h" +#include "hw_shared.h" +#include "dcn30/dcn30_afmt.h" +#include "dcn31_afmt.h" +#include "reg_helper.h" +#include "dc/dc.h" + +#define DC_LOGGER \ + afmt31->base.ctx->logger + +#define REG(reg)\ + (afmt31->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + afmt31->afmt_shift->field_name, afmt31->afmt_mask->field_name + + +#define CTX \ + afmt31->base.ctx + +static struct afmt_funcs dcn31_afmt_funcs = { + .setup_hdmi_audio = afmt3_setup_hdmi_audio, + .se_audio_setup = afmt3_se_audio_setup, + .audio_mute_control = afmt3_audio_mute_control, + .audio_info_immediate_update = afmt3_audio_info_immediate_update, + .setup_dp_audio = afmt3_setup_dp_audio, + .afmt_powerdown = afmt31_powerdown, + .afmt_poweron = afmt31_poweron +}; + +void afmt31_powerdown(struct afmt *afmt) +{ + struct dcn31_afmt *afmt31 = DCN31_AFMT_FROM_AFMT(afmt); + + if (afmt->ctx->dc->debug.enable_mem_low_power.bits.afmt == false) + return; + + REG_UPDATE_2(AFMT_MEM_PWR, AFMT_MEM_PWR_DIS, 0, AFMT_MEM_PWR_FORCE, 1); +} + +void afmt31_poweron(struct afmt *afmt) +{ + struct dcn31_afmt *afmt31 = DCN31_AFMT_FROM_AFMT(afmt); + + if (afmt->ctx->dc->debug.enable_mem_low_power.bits.afmt == false) + return; + + REG_UPDATE_2(AFMT_MEM_PWR, AFMT_MEM_PWR_DIS, 1, AFMT_MEM_PWR_FORCE, 0); +} + +void afmt31_construct(struct dcn31_afmt *afmt31, + struct dc_context *ctx, + uint32_t inst, + const struct dcn31_afmt_registers *afmt_regs, + const struct dcn31_afmt_shift *afmt_shift, + const struct dcn31_afmt_mask *afmt_mask) +{ + afmt31->base.ctx = ctx; + + afmt31->base.inst = inst; + afmt31->base.funcs = &dcn31_afmt_funcs; + + afmt31->regs = afmt_regs; + afmt31->afmt_shift = afmt_shift; + afmt31->afmt_mask = afmt_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_afmt.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_afmt.h new file mode 100644 index 0000000000000..802cb05b6ab97 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_afmt.h @@ -0,0 +1,126 @@ +/* + * Copyright 2019 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 __DAL_DCN31_AFMT_H__ +#define __DAL_DCN31_AFMT_H__ + + +#define DCN31_AFMT_FROM_AFMT(afmt)\ + container_of(afmt, struct dcn31_afmt, base) + +#define AFMT_DCN31_REG_LIST(id) \ + SRI(AFMT_INFOFRAME_CONTROL0, AFMT, id), \ + SRI(AFMT_VBI_PACKET_CONTROL, AFMT, id), \ + SRI(AFMT_AUDIO_PACKET_CONTROL, AFMT, id), \ + SRI(AFMT_AUDIO_PACKET_CONTROL2, AFMT, id), \ + SRI(AFMT_AUDIO_SRC_CONTROL, AFMT, id), \ + SRI(AFMT_60958_0, AFMT, id), \ + SRI(AFMT_60958_1, AFMT, id), \ + SRI(AFMT_60958_2, AFMT, id), \ + SRI(AFMT_MEM_PWR, AFMT, id) + +struct dcn31_afmt_registers { + uint32_t AFMT_INFOFRAME_CONTROL0; + uint32_t AFMT_VBI_PACKET_CONTROL; + uint32_t AFMT_AUDIO_PACKET_CONTROL; + uint32_t AFMT_AUDIO_PACKET_CONTROL2; + uint32_t AFMT_AUDIO_SRC_CONTROL; + uint32_t AFMT_60958_0; + uint32_t AFMT_60958_1; + uint32_t AFMT_60958_2; + uint32_t AFMT_MEM_PWR; +}; + +#define DCN31_AFMT_MASK_SH_LIST(mask_sh)\ + SE_SF(AFMT0_AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\ + SE_SF(AFMT0_AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\ + SE_SF(AFMT0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\ + SE_SF(AFMT0_AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\ + SE_SF(AFMT0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\ + SE_SF(AFMT0_AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\ + SE_SF(AFMT0_AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\ + SE_SF(AFMT0_AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh),\ + SE_SF(AFMT0_AFMT_MEM_PWR, AFMT_MEM_PWR_FORCE, mask_sh),\ + SE_SF(AFMT0_AFMT_MEM_PWR, AFMT_MEM_PWR_DIS, mask_sh),\ + SE_SF(AFMT0_AFMT_MEM_PWR, AFMT_MEM_PWR_STATE, mask_sh) + +#define AFMT_DCN31_REG_FIELD_LIST(type) \ + type AFMT_AUDIO_INFO_UPDATE;\ + type AFMT_AUDIO_SRC_SELECT;\ + type AFMT_AUDIO_CHANNEL_ENABLE;\ + type AFMT_60958_CS_UPDATE;\ + type AFMT_AUDIO_LAYOUT_OVRD;\ + type AFMT_60958_OSF_OVRD;\ + type AFMT_60958_CS_CHANNEL_NUMBER_L;\ + type AFMT_60958_CS_CLOCK_ACCURACY;\ + type AFMT_60958_CS_CHANNEL_NUMBER_R;\ + type AFMT_60958_CS_CHANNEL_NUMBER_2;\ + type AFMT_60958_CS_CHANNEL_NUMBER_3;\ + type AFMT_60958_CS_CHANNEL_NUMBER_4;\ + type AFMT_60958_CS_CHANNEL_NUMBER_5;\ + type AFMT_60958_CS_CHANNEL_NUMBER_6;\ + type AFMT_60958_CS_CHANNEL_NUMBER_7;\ + type AFMT_AUDIO_SAMPLE_SEND;\ + type AFMT_MEM_PWR_FORCE;\ + type AFMT_MEM_PWR_DIS;\ + type AFMT_MEM_PWR_STATE + +struct dcn31_afmt_shift { + AFMT_DCN31_REG_FIELD_LIST(uint8_t); +}; + +struct dcn31_afmt_mask { + AFMT_DCN31_REG_FIELD_LIST(uint32_t); +}; + +struct dcn31_afmt { + struct afmt base; + const struct dcn31_afmt_registers *regs; + const struct dcn31_afmt_shift *afmt_shift; + const struct dcn31_afmt_mask *afmt_mask; +}; + +void afmt31_poweron( + struct afmt *afmt); + +void afmt31_powerdown( + struct afmt *afmt); + +void afmt31_construct(struct dcn31_afmt *afmt31, + struct dc_context *ctx, + uint32_t inst, + const struct dcn31_afmt_registers *afmt_regs, + const struct dcn31_afmt_shift *afmt_shift, + const struct dcn31_afmt_mask *afmt_mask); + +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index e0b93665bf55a..cf6392eadaf2b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -56,6 +56,8 @@ #include "dcn31/dcn31_hpo_dp_link_encoder.h" #include "dcn31/dcn31_apg.h" #include "dcn31/dcn31_dio_link_encoder.h" +#include "dcn31/dcn31_vpg.h" +#include "dcn31/dcn31_afmt.h" #include "dce/dce_clock_source.h" #include "dce/dce_audio.h" #include "dce/dce_hwseq.h" @@ -414,10 +416,10 @@ static const struct dce_audio_mask audio_mask = { #define vpg_regs(id)\ [id] = {\ - VPG_DCN3_REG_LIST(id)\ + VPG_DCN31_REG_LIST(id)\ } -static const struct dcn30_vpg_registers vpg_regs[] = { +static const struct dcn31_vpg_registers vpg_regs[] = { vpg_regs(0), vpg_regs(1), vpg_regs(2), @@ -430,20 +432,20 @@ static const struct dcn30_vpg_registers vpg_regs[] = { vpg_regs(9), }; -static const struct dcn30_vpg_shift vpg_shift = { - DCN3_VPG_MASK_SH_LIST(__SHIFT) +static const struct dcn31_vpg_shift vpg_shift = { + DCN31_VPG_MASK_SH_LIST(__SHIFT) }; -static const struct dcn30_vpg_mask vpg_mask = { - DCN3_VPG_MASK_SH_LIST(_MASK) +static const struct dcn31_vpg_mask vpg_mask = { + DCN31_VPG_MASK_SH_LIST(_MASK) }; #define afmt_regs(id)\ [id] = {\ - AFMT_DCN3_REG_LIST(id)\ + AFMT_DCN31_REG_LIST(id)\ } -static const struct dcn30_afmt_registers afmt_regs[] = { +static const struct dcn31_afmt_registers afmt_regs[] = { afmt_regs(0), afmt_regs(1), afmt_regs(2), @@ -452,12 +454,12 @@ static const struct dcn30_afmt_registers afmt_regs[] = { afmt_regs(5) }; -static const struct dcn30_afmt_shift afmt_shift = { - DCN3_AFMT_MASK_SH_LIST(__SHIFT) +static const struct dcn31_afmt_shift afmt_shift = { + DCN31_AFMT_MASK_SH_LIST(__SHIFT) }; -static const struct dcn30_afmt_mask afmt_mask = { - DCN3_AFMT_MASK_SH_LIST(_MASK) +static const struct dcn31_afmt_mask afmt_mask = { + DCN31_AFMT_MASK_SH_LIST(_MASK) }; #define apg_regs(id)\ @@ -1014,6 +1016,8 @@ static const struct dc_debug_options debug_defaults_drv = { .cm = false, .mpc = false, .optc = false, + .vpg = false, + .afmt = false, } }, .optimize_edp_link_rate = true, @@ -1298,34 +1302,40 @@ static struct vpg *dcn31_vpg_create( struct dc_context *ctx, uint32_t inst) { - struct dcn30_vpg *vpg3 = kzalloc(sizeof(struct dcn30_vpg), GFP_KERNEL); + struct dcn31_vpg *vpg31 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL); - if (!vpg3) + if (!vpg31) return NULL; - vpg3_construct(vpg3, ctx, inst, + vpg31_construct(vpg31, ctx, inst, &vpg_regs[inst], &vpg_shift, &vpg_mask); - return &vpg3->base; + // Will re-enable hw block when we enable stream + // Check for enabled stream before powering down? + vpg31_powerdown(&vpg31->base); + + return &vpg31->base; } static struct afmt *dcn31_afmt_create( struct dc_context *ctx, uint32_t inst) { - struct dcn30_afmt *afmt3 = kzalloc(sizeof(struct dcn30_afmt), GFP_KERNEL); + struct dcn31_afmt *afmt31 = kzalloc(sizeof(struct dcn31_afmt), GFP_KERNEL); - if (!afmt3) + if (!afmt31) return NULL; - afmt3_construct(afmt3, ctx, inst, + afmt31_construct(afmt31, ctx, inst, &afmt_regs[inst], &afmt_shift, &afmt_mask); - return &afmt3->base; + // Light sleep by default, no need to power down here + + return &afmt31->base; } static struct apg *dcn31_apg_create( diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.c new file mode 100644 index 0000000000000..f1deb1c3c3630 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.c @@ -0,0 +1,87 @@ +/* + * Copyright 2019 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 + * + */ + +#include "dc_bios_types.h" +#include "dcn30/dcn30_vpg.h" +#include "dcn31_vpg.h" +#include "reg_helper.h" +#include "dc/dc.h" + +#define DC_LOGGER \ + vpg31->base.ctx->logger + +#define REG(reg)\ + (vpg31->regs->reg) + +#undef FN +#define FN(reg_name, field_name) \ + vpg31->vpg_shift->field_name, vpg31->vpg_mask->field_name + + +#define CTX \ + vpg31->base.ctx + +static struct vpg_funcs dcn31_vpg_funcs = { + .update_generic_info_packet = vpg3_update_generic_info_packet, + .vpg_poweron = vpg31_poweron, + .vpg_powerdown = vpg31_powerdown, +}; + +void vpg31_powerdown(struct vpg *vpg) +{ + struct dcn31_vpg *vpg31 = DCN31_VPG_FROM_VPG(vpg); + + if (vpg->ctx->dc->debug.enable_mem_low_power.bits.vpg == false) + return; + + REG_UPDATE_2(VPG_MEM_PWR, VPG_GSP_MEM_LIGHT_SLEEP_DIS, 0, VPG_GSP_LIGHT_SLEEP_FORCE, 1); +} + +void vpg31_poweron(struct vpg *vpg) +{ + struct dcn31_vpg *vpg31 = DCN31_VPG_FROM_VPG(vpg); + + if (vpg->ctx->dc->debug.enable_mem_low_power.bits.vpg == false) + return; + + REG_UPDATE_2(VPG_MEM_PWR, VPG_GSP_MEM_LIGHT_SLEEP_DIS, 1, VPG_GSP_LIGHT_SLEEP_FORCE, 0); +} + +void vpg31_construct(struct dcn31_vpg *vpg31, + struct dc_context *ctx, + uint32_t inst, + const struct dcn31_vpg_registers *vpg_regs, + const struct dcn31_vpg_shift *vpg_shift, + const struct dcn31_vpg_mask *vpg_mask) +{ + vpg31->base.ctx = ctx; + + vpg31->base.inst = inst; + vpg31->base.funcs = &dcn31_vpg_funcs; + + vpg31->regs = vpg_regs; + vpg31->vpg_shift = vpg_shift; + vpg31->vpg_mask = vpg_mask; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.h new file mode 100644 index 0000000000000..0e76eabce441b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.h @@ -0,0 +1,162 @@ +/* + * Copyright 2019 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 __DAL_DCN31_VPG_H__ +#define __DAL_DCN31_VPG_H__ + + +#define DCN31_VPG_FROM_VPG(vpg)\ + container_of(vpg, struct dcn31_vpg, base) + +#define VPG_DCN31_REG_LIST(id) \ + SRI(VPG_GENERIC_STATUS, VPG, id), \ + SRI(VPG_GENERIC_PACKET_ACCESS_CTRL, VPG, id), \ + SRI(VPG_GENERIC_PACKET_DATA, VPG, id), \ + SRI(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id), \ + SRI(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id), \ + SRI(VPG_MEM_PWR, VPG, id) + +struct dcn31_vpg_registers { + uint32_t VPG_GENERIC_STATUS; + uint32_t VPG_GENERIC_PACKET_ACCESS_CTRL; + uint32_t VPG_GENERIC_PACKET_DATA; + uint32_t VPG_GSP_FRAME_UPDATE_CTRL; + uint32_t VPG_GSP_IMMEDIATE_UPDATE_CTRL; + uint32_t VPG_MEM_PWR; +}; + +#define DCN31_VPG_MASK_SH_LIST(mask_sh)\ + SE_SF(VPG0_VPG_GENERIC_STATUS, VPG_GENERIC_CONFLICT_OCCURED, mask_sh),\ + SE_SF(VPG0_VPG_GENERIC_STATUS, VPG_GENERIC_CONFLICT_CLR, mask_sh),\ + SE_SF(VPG0_VPG_GENERIC_PACKET_ACCESS_CTRL, VPG_GENERIC_DATA_INDEX, mask_sh),\ + SE_SF(VPG0_VPG_GENERIC_PACKET_DATA, VPG_GENERIC_DATA_BYTE0, mask_sh),\ + SE_SF(VPG0_VPG_GENERIC_PACKET_DATA, VPG_GENERIC_DATA_BYTE1, mask_sh),\ + SE_SF(VPG0_VPG_GENERIC_PACKET_DATA, VPG_GENERIC_DATA_BYTE2, mask_sh),\ + SE_SF(VPG0_VPG_GENERIC_PACKET_DATA, VPG_GENERIC_DATA_BYTE3, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC0_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC1_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC2_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC3_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC4_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC5_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC6_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC7_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC8_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC9_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC10_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC11_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC12_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC13_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_FRAME_UPDATE_CTRL, VPG_GENERIC14_FRAME_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC0_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC1_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC2_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC3_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC4_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC5_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC6_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC7_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC8_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC9_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC10_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC11_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC12_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC13_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG_GENERIC14_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(VPG0_VPG_MEM_PWR, VPG_GSP_MEM_LIGHT_SLEEP_DIS, mask_sh),\ + SE_SF(VPG0_VPG_MEM_PWR, VPG_GSP_LIGHT_SLEEP_FORCE, mask_sh),\ + SE_SF(VPG0_VPG_MEM_PWR, VPG_GSP_MEM_PWR_STATE, mask_sh) + +#define VPG_DCN31_REG_FIELD_LIST(type) \ + type VPG_GENERIC_CONFLICT_OCCURED;\ + type VPG_GENERIC_CONFLICT_CLR;\ + type VPG_GENERIC_DATA_INDEX;\ + type VPG_GENERIC_DATA_BYTE0;\ + type VPG_GENERIC_DATA_BYTE1;\ + type VPG_GENERIC_DATA_BYTE2;\ + type VPG_GENERIC_DATA_BYTE3;\ + type VPG_GENERIC0_FRAME_UPDATE;\ + type VPG_GENERIC1_FRAME_UPDATE;\ + type VPG_GENERIC2_FRAME_UPDATE;\ + type VPG_GENERIC3_FRAME_UPDATE;\ + type VPG_GENERIC4_FRAME_UPDATE;\ + type VPG_GENERIC5_FRAME_UPDATE;\ + type VPG_GENERIC6_FRAME_UPDATE;\ + type VPG_GENERIC7_FRAME_UPDATE;\ + type VPG_GENERIC8_FRAME_UPDATE;\ + type VPG_GENERIC9_FRAME_UPDATE;\ + type VPG_GENERIC10_FRAME_UPDATE;\ + type VPG_GENERIC11_FRAME_UPDATE;\ + type VPG_GENERIC12_FRAME_UPDATE;\ + type VPG_GENERIC13_FRAME_UPDATE;\ + type VPG_GENERIC14_FRAME_UPDATE;\ + type VPG_GENERIC0_IMMEDIATE_UPDATE;\ + type VPG_GENERIC1_IMMEDIATE_UPDATE;\ + type VPG_GENERIC2_IMMEDIATE_UPDATE;\ + type VPG_GENERIC3_IMMEDIATE_UPDATE;\ + type VPG_GENERIC4_IMMEDIATE_UPDATE;\ + type VPG_GENERIC5_IMMEDIATE_UPDATE;\ + type VPG_GENERIC6_IMMEDIATE_UPDATE;\ + type VPG_GENERIC7_IMMEDIATE_UPDATE;\ + type VPG_GENERIC8_IMMEDIATE_UPDATE;\ + type VPG_GENERIC9_IMMEDIATE_UPDATE;\ + type VPG_GENERIC10_IMMEDIATE_UPDATE;\ + type VPG_GENERIC11_IMMEDIATE_UPDATE;\ + type VPG_GENERIC12_IMMEDIATE_UPDATE;\ + type VPG_GENERIC13_IMMEDIATE_UPDATE;\ + type VPG_GENERIC14_IMMEDIATE_UPDATE;\ + type VPG_GSP_MEM_LIGHT_SLEEP_DIS;\ + type VPG_GSP_LIGHT_SLEEP_FORCE;\ + type VPG_GSP_MEM_PWR_STATE + +struct dcn31_vpg_shift { + VPG_DCN31_REG_FIELD_LIST(uint8_t); +}; + +struct dcn31_vpg_mask { + VPG_DCN31_REG_FIELD_LIST(uint32_t); +}; + +struct dcn31_vpg { + struct vpg base; + const struct dcn31_vpg_registers *regs; + const struct dcn31_vpg_shift *vpg_shift; + const struct dcn31_vpg_mask *vpg_mask; +}; + +void vpg31_poweron( + struct vpg *vpg); + +void vpg31_powerdown( + struct vpg *vpg); + +void vpg31_construct(struct dcn31_vpg *vpg31, + struct dc_context *ctx, + uint32_t inst, + const struct dcn31_vpg_registers *vpg_regs, + const struct dcn31_vpg_shift *vpg_shift, + const struct dcn31_vpg_mask *vpg_mask); + +#endif From 0c55b63ba3a76673ee21bc1b82c4a33f091ff908 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Wed, 1 Sep 2021 14:22:13 +0800 Subject: [PATCH 086/151] drm/amd/display: remove force_enable_edp_fec param. Reviewed-by: Wenjing Liu Acked-by: Mikita Lipski Signed-off-by: Ian Chen Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 9c5dbcf42f46f..2225095576724 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -4237,8 +4237,8 @@ bool dc_link_should_enable_fec(const struct dc_link *link) if ((link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT_MST && link->local_sink && link->local_sink->edid_caps.panel_patch.disable_fec) || - (link->connector_signal == SIGNAL_TYPE_EDP && - link->dc->debug.force_enable_edp_fec == false)) // Disable FEC for eDP + (link->connector_signal == SIGNAL_TYPE_EDP + )) is_fec_disable = true; if (dc_link_is_fec_supported(link) && !link->dc->debug.disable_fec && !is_fec_disable) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 15b67239266e8..8897750bdaea0 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -641,8 +641,6 @@ struct dc_debug_options { /* Enable dmub aux for legacy ddc */ bool enable_dmub_aux_for_legacy_ddc; bool optimize_edp_link_rate; /* eDP ILR */ - /* force enable edp FEC */ - bool force_enable_edp_fec; /* FEC/PSR1 sequence enable delay in 100us */ uint8_t fec_enable_delay_in100us; bool enable_driver_sequence_debug; From 3da35006fef89d15d101622445d7f4760953a5f1 Mon Sep 17 00:00:00 2001 From: Michael Strauss Date: Wed, 1 Sep 2021 13:49:37 -0400 Subject: [PATCH 087/151] drm/amd/display: Enable mem low power control for DCN3.1 sub-IP blocks [WHY] Sequences to handle powering down these sub-IP blocks are now ready for use Reviewed-by: Eric Yang Acked-by: Mikita Lipski Signed-off-by: Michael Strauss Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn31/dcn31_resource.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index cf6392eadaf2b..613d34bde7dd1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -1009,15 +1009,15 @@ static const struct dc_debug_options debug_defaults_drv = { .use_max_lb = true, .enable_mem_low_power = { .bits = { - .vga = false, - .i2c = false, + .vga = true, + .i2c = true, .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled - .dscl = false, - .cm = false, - .mpc = false, - .optc = false, - .vpg = false, - .afmt = false, + .dscl = true, + .cm = true, + .mpc = true, + .optc = true, + .vpg = true, + .afmt = true, } }, .optimize_edp_link_rate = true, From 8e6d0b699635ecc5bad8629b8da685621aa416ca Mon Sep 17 00:00:00 2001 From: shaoyunl Date: Wed, 8 Sep 2021 22:12:55 -0400 Subject: [PATCH 088/151] drm/amdgpu: Get atomicOps info from Host for sriov setup The AtomicOp Requester Enable bit is reserved in VFs and the PF value applies to all associated VFs. so guest driver can not directly enable the atomicOps for VF, it depends on PF to enable it. In current design, amdgpu driver will get the enabled atomicOps bits through private pf2vf data Signed-off-by: shaoyunl Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 24 +++++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h | 4 +++- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 41c6b3aacd379..aefa96bcbbab4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3530,17 +3530,6 @@ int amdgpu_device_init(struct amdgpu_device *adev, DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)adev->rmmio_base); DRM_INFO("register mmio size: %u\n", (unsigned)adev->rmmio_size); - /* enable PCIE atomic ops */ - r = pci_enable_atomic_ops_to_root(adev->pdev, - PCI_EXP_DEVCAP2_ATOMIC_COMP32 | - PCI_EXP_DEVCAP2_ATOMIC_COMP64); - if (r) { - adev->have_atomics_support = false; - DRM_INFO("PCIE atomic ops is not supported\n"); - } else { - adev->have_atomics_support = true; - } - amdgpu_device_get_pcie_info(adev); if (amdgpu_mcbp) @@ -3563,6 +3552,19 @@ int amdgpu_device_init(struct amdgpu_device *adev, if (r) return r; + /* enable PCIE atomic ops */ + if (amdgpu_sriov_vf(adev)) + adev->have_atomics_support = ((struct amd_sriov_msg_pf2vf_info *) + adev->virt.fw_reserve.p_pf2vf)->pcie_atomic_ops_enabled_flags == + (PCI_EXP_DEVCAP2_ATOMIC_COMP32 | PCI_EXP_DEVCAP2_ATOMIC_COMP64); + else + adev->have_atomics_support = + !pci_enable_atomic_ops_to_root(adev->pdev, + PCI_EXP_DEVCAP2_ATOMIC_COMP32 | + PCI_EXP_DEVCAP2_ATOMIC_COMP64); + if (!adev->have_atomics_support) + dev_info(adev->dev, "PCIE atomic ops is not supported\n"); + /* doorbell bar mapping and doorbell index init*/ amdgpu_device_doorbell_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h index a434c71fde8ec..995899191288d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h @@ -204,8 +204,10 @@ struct amd_sriov_msg_pf2vf_info { } mm_bw_management[AMD_SRIOV_MSG_RESERVE_VCN_INST]; /* UUID info */ struct amd_sriov_msg_uuid_info uuid_info; + /* pcie atomic Ops info */ + uint32_t pcie_atomic_ops_enabled_flags; /* reserved */ - uint32_t reserved[256 - 47]; + uint32_t reserved[256 - 48]; }; struct amd_sriov_msg_vf2pf_info_header { From f8846323d544540be07d7662325ad459f868dcc0 Mon Sep 17 00:00:00 2001 From: James Zhu Date: Tue, 7 Sep 2021 11:13:02 -0400 Subject: [PATCH 089/151] drm/amdkfd: separate kfd_iommu_resume from kfd_resume Separate kfd_iommu_resume from kfd_resume for fine-tuning of amdgpu device init/resume/reset/recovery sequence. v2: squash in fix for !CONFIG_HSA_AMD Bug: https://bugzilla.kernel.org/show_bug.cgi?id=211277 Signed-off-by: James Zhu Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 6 ++++++ drivers/gpu/drm/amd/amdkfd/kfd_device.c | 12 ++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index ec028cf963f5a..089c7b9670087 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -327,6 +327,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, const struct kgd2kfd_shared_resources *gpu_resources); void kgd2kfd_device_exit(struct kfd_dev *kfd); void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm); +int kgd2kfd_resume_iommu(struct kfd_dev *kfd); int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm); int kgd2kfd_pre_reset(struct kfd_dev *kfd); int kgd2kfd_post_reset(struct kfd_dev *kfd); @@ -365,6 +366,11 @@ static inline void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) { } +static int __maybe_unused kgd2kfd_resume_iommu(struct kfd_dev *kfd) +{ + return 0; +} + static inline int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) { return 0; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 30fde852af193..98d1b3ab3a464 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -1069,17 +1069,21 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) return ret; } -static int kfd_resume(struct kfd_dev *kfd) +int kgd2kfd_resume_iommu(struct kfd_dev *kfd) { int err = 0; err = kfd_iommu_resume(kfd); - if (err) { + if (err) dev_err(kfd_device, "Failed to resume IOMMU for device %x:%x\n", kfd->pdev->vendor, kfd->pdev->device); - return err; - } + return err; +} + +static int kfd_resume(struct kfd_dev *kfd) +{ + int err = 0; err = kfd->dqm->ops.start(kfd->dqm); if (err) { From ea20e246f39aa3dc092627c632c2dac1d4d55de0 Mon Sep 17 00:00:00 2001 From: James Zhu Date: Tue, 7 Sep 2021 11:27:31 -0400 Subject: [PATCH 090/151] drm/amdgpu: add amdgpu_amdkfd_resume_iommu Add amdgpu_amdkfd_resume_iommu for amdgpu. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=211277 Signed-off-by: James Zhu Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 10 ++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 3003ee1c94873..1d41c2c00623b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -192,6 +192,16 @@ void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool run_pm) kgd2kfd_suspend(adev->kfd.dev, run_pm); } +int amdgpu_amdkfd_resume_iommu(struct amdgpu_device *adev) +{ + int r = 0; + + if (adev->kfd.dev) + r = kgd2kfd_resume_iommu(adev->kfd.dev); + + return r; +} + int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm) { int r = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index 089c7b9670087..3bc52b2c604fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -137,6 +137,7 @@ int amdgpu_amdkfd_init(void); void amdgpu_amdkfd_fini(void); void amdgpu_amdkfd_suspend(struct amdgpu_device *adev, bool run_pm); +int amdgpu_amdkfd_resume_iommu(struct amdgpu_device *adev); int amdgpu_amdkfd_resume(struct amdgpu_device *adev, bool run_pm); void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev, const void *ih_ring_entry); From 9cec53c18a3170c7e5673c414da56aeecee94832 Mon Sep 17 00:00:00 2001 From: James Zhu Date: Tue, 7 Sep 2021 11:32:22 -0400 Subject: [PATCH 091/151] drm/amdgpu: move iommu_resume before ip init/resume Separate iommu_resume from kfd_resume, and move it before other amdgpu ip init/resume. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=211277 Signed-off-by: James Zhu Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index aefa96bcbbab4..620c7b773b15a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2394,6 +2394,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) if (r) goto init_failed; + r = amdgpu_amdkfd_resume_iommu(adev); + if (r) + goto init_failed; + r = amdgpu_device_ip_hw_init_phase1(adev); if (r) goto init_failed; @@ -3148,6 +3152,10 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev) { int r; + r = amdgpu_amdkfd_resume_iommu(adev); + if (r) + return r; + r = amdgpu_device_ip_resume_phase1(adev); if (r) return r; @@ -4603,6 +4611,10 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle, dev_warn(tmp_adev->dev, "asic atom init failed!"); } else { dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n"); + r = amdgpu_amdkfd_resume_iommu(tmp_adev); + if (r) + goto out; + r = amdgpu_device_ip_resume_phase1(tmp_adev); if (r) goto out; From de3a1e336057fd12210eead4367205594e5ac991 Mon Sep 17 00:00:00 2001 From: Candice Li Date: Wed, 8 Sep 2021 23:58:59 +0800 Subject: [PATCH 092/151] drm/amdgpu: Unify PSP TA context Remove all TA binary structures and add the specific binary structure in struct ta_context. Signed-off-by: Candice Li Reviewed-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 23 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 122 +++++++++++----------- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 23 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 9 +- drivers/gpu/drm/amd/amdgpu/psp_v10_0.c | 22 ++-- drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 40 ++++--- drivers/gpu/drm/amd/amdgpu/psp_v12_0.c | 14 +-- 8 files changed, 141 insertions(+), 118 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 7e45640fbee02..d2955ea4a62bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -341,27 +341,34 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, switch (query_fw->index) { case TA_FW_TYPE_PSP_XGMI: fw_info->ver = adev->psp.ta_fw_version; - fw_info->feature = adev->psp.xgmi.feature_version; + fw_info->feature = adev->psp.xgmi_context.context + .bin_desc.feature_version; break; case TA_FW_TYPE_PSP_RAS: fw_info->ver = adev->psp.ta_fw_version; - fw_info->feature = adev->psp.ras.feature_version; + fw_info->feature = adev->psp.ras_context.context + .bin_desc.feature_version; break; case TA_FW_TYPE_PSP_HDCP: fw_info->ver = adev->psp.ta_fw_version; - fw_info->feature = adev->psp.hdcp.feature_version; + fw_info->feature = adev->psp.hdcp_context.context + .bin_desc.feature_version; break; case TA_FW_TYPE_PSP_DTM: fw_info->ver = adev->psp.ta_fw_version; - fw_info->feature = adev->psp.dtm.feature_version; + fw_info->feature = adev->psp.dtm_context.context + .bin_desc.feature_version; break; case TA_FW_TYPE_PSP_RAP: fw_info->ver = adev->psp.ta_fw_version; - fw_info->feature = adev->psp.rap.feature_version; + fw_info->feature = adev->psp.rap_context.context + .bin_desc.feature_version; break; case TA_FW_TYPE_PSP_SECUREDISPLAY: fw_info->ver = adev->psp.ta_fw_version; - fw_info->feature = adev->psp.securedisplay.feature_version; + fw_info->feature = + adev->psp.securedisplay_context.context.bin_desc + .feature_version; break; default: return -EINVAL; @@ -378,8 +385,8 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, fw_info->feature = adev->psp.sos.feature_version; break; case AMDGPU_INFO_FW_ASD: - fw_info->ver = adev->psp.asd.fw_version; - fw_info->feature = adev->psp.asd.feature_version; + fw_info->ver = adev->psp.asd_context.bin_desc.fw_version; + fw_info->feature = adev->psp.asd_context.bin_desc.feature_version; break; case AMDGPU_INFO_FW_DMCU: fw_info->ver = adev->dm.dmcu_fw_version; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 885876e2ce73b..071dadf3a4509 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -803,15 +803,16 @@ static int psp_asd_load(struct psp_context *psp) * add workaround to bypass it for sriov now. * TODO: add version check to make it common */ - if (amdgpu_sriov_vf(psp->adev) || !psp->asd.size_bytes) + if (amdgpu_sriov_vf(psp->adev) || !psp->asd_context.bin_desc.size_bytes) return 0; cmd = acquire_psp_cmd_buf(psp); - psp_copy_fw(psp, psp->asd.start_addr, psp->asd.size_bytes); + psp_copy_fw(psp, psp->asd_context.bin_desc.start_addr, + psp->asd_context.bin_desc.size_bytes); psp_prep_asd_load_cmd_buf(cmd, psp->fw_pri_mc_addr, - psp->asd.size_bytes); + psp->asd_context.bin_desc.size_bytes); ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); @@ -900,17 +901,18 @@ int psp_reg_program(struct psp_context *psp, enum psp_reg_prog_id reg, static void psp_prep_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, uint64_t ta_bin_mc, - uint32_t ta_bin_size, - struct ta_mem_context *mem_ctx) + struct ta_context *context) { cmd->cmd_id = GFX_CMD_ID_LOAD_TA; cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(ta_bin_mc); cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(ta_bin_mc); - cmd->cmd.cmd_load_ta.app_len = ta_bin_size; + cmd->cmd.cmd_load_ta.app_len = context->bin_desc.size_bytes; - cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = lower_32_bits(mem_ctx->shared_mc_addr); - cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = upper_32_bits(mem_ctx->shared_mc_addr); - cmd->cmd.cmd_load_ta.cmd_buf_len = mem_ctx->shared_mem_size; + cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = + lower_32_bits(context->mem_context.shared_mc_addr); + cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = + upper_32_bits(context->mem_context.shared_mc_addr); + cmd->cmd.cmd_load_ta.cmd_buf_len = context->mem_context.shared_mem_size; } static int psp_ta_init_shared_buf(struct psp_context *psp, @@ -969,7 +971,6 @@ static int psp_ta_invoke(struct psp_context *psp, } static int psp_ta_load(struct psp_context *psp, - struct psp_bin_desc *bin_desc, struct ta_context *context) { int ret; @@ -977,12 +978,12 @@ static int psp_ta_load(struct psp_context *psp, cmd = acquire_psp_cmd_buf(psp); - psp_copy_fw(psp, bin_desc->start_addr, bin_desc->size_bytes); + psp_copy_fw(psp, context->bin_desc.start_addr, + context->bin_desc.size_bytes); psp_prep_ta_load_cmd_buf(cmd, psp->fw_pri_mc_addr, - bin_desc->size_bytes, - &context->mem_context); + context); ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); @@ -998,7 +999,7 @@ static int psp_ta_load(struct psp_context *psp, static int psp_xgmi_load(struct psp_context *psp) { - return psp_ta_load(psp, &psp->xgmi, &psp->xgmi_context.context); + return psp_ta_load(psp, &psp->xgmi_context.context); } static int psp_xgmi_unload(struct psp_context *psp) @@ -1042,8 +1043,8 @@ int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool lo int ret; if (!psp->ta_fw || - !psp->xgmi.size_bytes || - !psp->xgmi.start_addr) + !psp->xgmi_context.context.bin_desc.size_bytes || + !psp->xgmi_context.context.bin_desc.start_addr) return -ENOENT; if (!load_ta) @@ -1119,7 +1120,7 @@ int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id) static bool psp_xgmi_peer_link_info_supported(struct psp_context *psp) { return psp->adev->asic_type == CHIP_ALDEBARAN && - psp->xgmi.feature_version >= 0x2000000b; + psp->xgmi_context.context.bin_desc.feature_version >= 0x2000000b; } /* @@ -1288,7 +1289,7 @@ static int psp_ras_init_shared_buf(struct psp_context *psp) static int psp_ras_load(struct psp_context *psp) { - return psp_ta_load(psp, &psp->ras, &psp->ras_context.context); + return psp_ta_load(psp, &psp->ras_context.context); } static int psp_ras_unload(struct psp_context *psp) @@ -1401,8 +1402,8 @@ static int psp_ras_initialize(struct psp_context *psp) if (amdgpu_sriov_vf(adev)) return 0; - if (!adev->psp.ras.size_bytes || - !adev->psp.ras.start_addr) { + if (!adev->psp.ras_context.context.bin_desc.size_bytes || + !adev->psp.ras_context.context.bin_desc.start_addr) { dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n"); return 0; } @@ -1518,8 +1519,9 @@ static int psp_hdcp_init_shared_buf(struct psp_context *psp) static int psp_hdcp_load(struct psp_context *psp) { - return psp_ta_load(psp, &psp->hdcp, &psp->hdcp_context.context); + return psp_ta_load(psp, &psp->hdcp_context.context); } + static int psp_hdcp_initialize(struct psp_context *psp) { int ret; @@ -1530,8 +1532,8 @@ static int psp_hdcp_initialize(struct psp_context *psp) if (amdgpu_sriov_vf(psp->adev)) return 0; - if (!psp->hdcp.size_bytes || - !psp->hdcp.start_addr) { + if (!psp->hdcp_context.context.bin_desc.size_bytes || + !psp->hdcp_context.context.bin_desc.start_addr) { dev_info(psp->adev->dev, "HDCP: optional hdcp ta ucode is not available\n"); return 0; } @@ -1608,7 +1610,7 @@ static int psp_dtm_init_shared_buf(struct psp_context *psp) static int psp_dtm_load(struct psp_context *psp) { - return psp_ta_load(psp, &psp->dtm, &psp->dtm_context.context); + return psp_ta_load(psp, &psp->dtm_context.context); } static int psp_dtm_initialize(struct psp_context *psp) @@ -1621,8 +1623,8 @@ static int psp_dtm_initialize(struct psp_context *psp) if (amdgpu_sriov_vf(psp->adev)) return 0; - if (!psp->dtm.size_bytes || - !psp->dtm.start_addr) { + if (!psp->dtm_context.context.bin_desc.size_bytes || + !psp->dtm_context.context.bin_desc.start_addr) { dev_info(psp->adev->dev, "DTM: optional dtm ta ucode is not available\n"); return 0; } @@ -1699,7 +1701,7 @@ static int psp_rap_init_shared_buf(struct psp_context *psp) static int psp_rap_load(struct psp_context *psp) { - return psp_ta_load(psp, &psp->rap, &psp->rap_context.context); + return psp_ta_load(psp, &psp->rap_context.context); } static int psp_rap_unload(struct psp_context *psp) @@ -1718,8 +1720,8 @@ static int psp_rap_initialize(struct psp_context *psp) if (amdgpu_sriov_vf(psp->adev)) return 0; - if (!psp->rap.size_bytes || - !psp->rap.start_addr) { + if (!psp->rap_context.context.bin_desc.size_bytes || + !psp->rap_context.context.bin_desc.start_addr) { dev_info(psp->adev->dev, "RAP: optional rap ta ucode is not available\n"); return 0; } @@ -1813,8 +1815,7 @@ static int psp_securedisplay_init_shared_buf(struct psp_context *psp) static int psp_securedisplay_load(struct psp_context *psp) { - return psp_ta_load(psp, &psp->securedisplay, - &psp->securedisplay_context.context); + return psp_ta_load(psp, &psp->securedisplay_context.context); } static int psp_securedisplay_unload(struct psp_context *psp) @@ -1833,8 +1834,8 @@ static int psp_securedisplay_initialize(struct psp_context *psp) if (amdgpu_sriov_vf(psp->adev)) return 0; - if (!psp->securedisplay.size_bytes || - !psp->securedisplay.start_addr) { + if (!psp->securedisplay_context.context.bin_desc.size_bytes || + !psp->securedisplay_context.context.bin_desc.start_addr) { dev_info(psp->adev->dev, "SECUREDISPLAY: securedisplay ta ucode is not available\n"); return 0; } @@ -2783,10 +2784,10 @@ int psp_init_asd_microcode(struct psp_context *psp, goto out; asd_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.asd_fw->data; - adev->psp.asd.fw_version = le32_to_cpu(asd_hdr->header.ucode_version); - adev->psp.asd.feature_version = le32_to_cpu(asd_hdr->sos.fw_version); - adev->psp.asd.size_bytes = le32_to_cpu(asd_hdr->header.ucode_size_bytes); - adev->psp.asd.start_addr = (uint8_t *)asd_hdr + + adev->psp.asd_context.bin_desc.fw_version = le32_to_cpu(asd_hdr->header.ucode_version); + adev->psp.asd_context.bin_desc.feature_version = le32_to_cpu(asd_hdr->sos.fw_version); + adev->psp.asd_context.bin_desc.size_bytes = le32_to_cpu(asd_hdr->header.ucode_size_bytes); + adev->psp.asd_context.bin_desc.start_addr = (uint8_t *)asd_hdr + le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes); return 0; out: @@ -3073,40 +3074,43 @@ static int parse_ta_bin_descriptor(struct psp_context *psp, switch (desc->fw_type) { case TA_FW_TYPE_PSP_ASD: - psp->asd.fw_version = le32_to_cpu(desc->fw_version); - psp->asd.feature_version = le32_to_cpu(desc->fw_version); - psp->asd.size_bytes = le32_to_cpu(desc->size_bytes); - psp->asd.start_addr = ucode_start_addr; + psp->asd_context.bin_desc.fw_version = le32_to_cpu(desc->fw_version); + psp->asd_context.bin_desc.feature_version = le32_to_cpu(desc->fw_version); + psp->asd_context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes); + psp->asd_context.bin_desc.start_addr = ucode_start_addr; break; case TA_FW_TYPE_PSP_XGMI: - psp->xgmi.feature_version = le32_to_cpu(desc->fw_version); - psp->xgmi.size_bytes = le32_to_cpu(desc->size_bytes); - psp->xgmi.start_addr = ucode_start_addr; + psp->xgmi_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version); + psp->xgmi_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes); + psp->xgmi_context.context.bin_desc.start_addr = ucode_start_addr; break; case TA_FW_TYPE_PSP_RAS: - psp->ras.feature_version = le32_to_cpu(desc->fw_version); - psp->ras.size_bytes = le32_to_cpu(desc->size_bytes); - psp->ras.start_addr = ucode_start_addr; + psp->ras_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version); + psp->ras_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes); + psp->ras_context.context.bin_desc.start_addr = ucode_start_addr; break; case TA_FW_TYPE_PSP_HDCP: - psp->hdcp.feature_version = le32_to_cpu(desc->fw_version); - psp->hdcp.size_bytes = le32_to_cpu(desc->size_bytes); - psp->hdcp.start_addr = ucode_start_addr; + psp->hdcp_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version); + psp->hdcp_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes); + psp->hdcp_context.context.bin_desc.start_addr = ucode_start_addr; break; case TA_FW_TYPE_PSP_DTM: - psp->dtm.feature_version = le32_to_cpu(desc->fw_version); - psp->dtm.size_bytes = le32_to_cpu(desc->size_bytes); - psp->dtm.start_addr = ucode_start_addr; + psp->dtm_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version); + psp->dtm_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes); + psp->dtm_context.context.bin_desc.start_addr = ucode_start_addr; break; case TA_FW_TYPE_PSP_RAP: - psp->rap.feature_version = le32_to_cpu(desc->fw_version); - psp->rap.size_bytes = le32_to_cpu(desc->size_bytes); - psp->rap.start_addr = ucode_start_addr; + psp->rap_context.context.bin_desc.feature_version = le32_to_cpu(desc->fw_version); + psp->rap_context.context.bin_desc.size_bytes = le32_to_cpu(desc->size_bytes); + psp->rap_context.context.bin_desc.start_addr = ucode_start_addr; break; case TA_FW_TYPE_PSP_SECUREDISPLAY: - psp->securedisplay.feature_version = le32_to_cpu(desc->fw_version); - psp->securedisplay.size_bytes = le32_to_cpu(desc->size_bytes); - psp->securedisplay.start_addr = ucode_start_addr; + psp->securedisplay_context.context.bin_desc.feature_version = + le32_to_cpu(desc->fw_version); + psp->securedisplay_context.context.bin_desc.size_bytes = + le32_to_cpu(desc->size_bytes); + psp->securedisplay_context.context.bin_desc.start_addr = + ucode_start_addr; break; default: dev_warn(psp->adev->dev, "Unsupported TA type: %d\n", desc->fw_type); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index cc09b9e911199..cfd7ac976cd1e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -133,9 +133,17 @@ struct psp_xgmi_topology_info { struct psp_xgmi_node_info nodes[AMDGPU_XGMI_MAX_CONNECTED_NODES]; }; +struct psp_bin_desc { + uint32_t fw_version; + uint32_t feature_version; + uint32_t size_bytes; + uint8_t *start_addr; +}; + struct psp_asd_context { bool asd_initialized; uint32_t session_id; + struct psp_bin_desc bin_desc; }; struct ta_mem_context { @@ -149,6 +157,7 @@ struct ta_context { bool initialized; uint32_t session_id; struct ta_mem_context mem_context; + struct psp_bin_desc bin_desc; }; struct ta_cp_context { @@ -266,13 +275,6 @@ struct psp_runtime_boot_cfg_entry { uint32_t reserved; }; -struct psp_bin_desc { - uint32_t fw_version; - uint32_t feature_version; - uint32_t size_bytes; - uint8_t *start_addr; -}; - struct psp_context { struct amdgpu_device *adev; @@ -304,7 +306,6 @@ struct psp_context /* asd firmware */ const struct firmware *asd_fw; - struct psp_bin_desc asd; /* toc firmware */ const struct firmware *toc_fw; @@ -329,12 +330,6 @@ struct psp_context /* xgmi ta firmware and buffer */ const struct firmware *ta_fw; uint32_t ta_fw_version; - struct psp_bin_desc xgmi; - struct psp_bin_desc ras; - struct psp_bin_desc hdcp; - struct psp_bin_desc dtm; - struct psp_bin_desc rap; - struct psp_bin_desc securedisplay; struct psp_asd_context asd_context; struct psp_xgmi_context xgmi_context; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 5f396936c6add..527d67ded8a00 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -525,9 +525,9 @@ FW_VERSION_ATTR(rlc_srls_fw_version, 0444, gfx.rlc_srls_fw_version); FW_VERSION_ATTR(mec_fw_version, 0444, gfx.mec_fw_version); FW_VERSION_ATTR(mec2_fw_version, 0444, gfx.mec2_fw_version); FW_VERSION_ATTR(sos_fw_version, 0444, psp.sos.fw_version); -FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd.fw_version); -FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras.feature_version); -FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.xgmi.feature_version); +FW_VERSION_ATTR(asd_fw_version, 0444, psp.asd_context.bin_desc.fw_version); +FW_VERSION_ATTR(ta_ras_fw_version, 0444, psp.ras_context.context.bin_desc.feature_version); +FW_VERSION_ATTR(ta_xgmi_fw_version, 0444, psp.xgmi_context.context.bin_desc.feature_version); FW_VERSION_ATTR(smc_fw_version, 0444, pm.fw_version); FW_VERSION_ATTR(sdma_fw_version, 0444, sdma.instance[0].fw_version); FW_VERSION_ATTR(sdma2_fw_version, 0444, sdma.instance[1].fw_version); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index ca058fbcccd43..88c4177b708ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -532,9 +532,12 @@ static void amdgpu_virt_populate_vf2pf_ucode_info(struct amdgpu_device *adev) POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC, adev->gfx.mec_fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_MEC2, adev->gfx.mec2_fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SOS, adev->psp.sos.fw_version); - POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD, adev->psp.asd.fw_version); - POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_RAS, adev->psp.ras.feature_version); - POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_XGMI, adev->psp.xgmi.feature_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_ASD, + adev->psp.asd_context.bin_desc.fw_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_RAS, + adev->psp.ras_context.context.bin_desc.feature_version); + POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_TA_XGMI, + adev->psp.xgmi_context.context.bin_desc.feature_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SMC, adev->pm.fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA, adev->sdma.instance[0].fw_version); POPULATE_UCODE_INFO(vf2pf_info, AMD_SRIOV_UCODE_ID_SDMA2, adev->sdma.instance[1].fw_version); diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c index 5872d68ed13d7..59644015dfc3e 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c @@ -84,28 +84,28 @@ static int psp_v10_0_init_microcode(struct psp_context *psp) ta_hdr = (const struct ta_firmware_header_v1_0 *) adev->psp.ta_fw->data; - adev->psp.hdcp.feature_version = + adev->psp.hdcp_context.context.bin_desc.feature_version = le32_to_cpu(ta_hdr->hdcp.fw_version); - adev->psp.hdcp.size_bytes = + adev->psp.hdcp_context.context.bin_desc.size_bytes = le32_to_cpu(ta_hdr->hdcp.size_bytes); - adev->psp.hdcp.start_addr = + adev->psp.hdcp_context.context.bin_desc.start_addr = (uint8_t *)ta_hdr + le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); - adev->psp.dtm.feature_version = + adev->psp.dtm_context.context.bin_desc.feature_version = le32_to_cpu(ta_hdr->dtm.fw_version); - adev->psp.dtm.size_bytes = + adev->psp.dtm_context.context.bin_desc.size_bytes = le32_to_cpu(ta_hdr->dtm.size_bytes); - adev->psp.dtm.start_addr = - (uint8_t *)adev->psp.hdcp.start_addr + + adev->psp.dtm_context.context.bin_desc.start_addr = + (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr + le32_to_cpu(ta_hdr->dtm.offset_bytes); - adev->psp.securedisplay.feature_version = + adev->psp.securedisplay_context.context.bin_desc.feature_version = le32_to_cpu(ta_hdr->securedisplay.fw_version); - adev->psp.securedisplay.size_bytes = + adev->psp.securedisplay_context.context.bin_desc.size_bytes = le32_to_cpu(ta_hdr->securedisplay.size_bytes); - adev->psp.securedisplay.start_addr = - (uint8_t *)adev->psp.hdcp.start_addr + + adev->psp.securedisplay_context.context.bin_desc.start_addr = + (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr + le32_to_cpu(ta_hdr->securedisplay.offset_bytes); adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c index 29bf9f09944be..3c02e75fd366b 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c @@ -151,14 +151,20 @@ static int psp_v11_0_init_microcode(struct psp_context *psp) goto out2; ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data; - adev->psp.xgmi.feature_version = le32_to_cpu(ta_hdr->xgmi.fw_version); - adev->psp.xgmi.size_bytes = le32_to_cpu(ta_hdr->xgmi.size_bytes); - adev->psp.xgmi.start_addr = (uint8_t *)ta_hdr + + adev->psp.xgmi_context.context.bin_desc.feature_version = + le32_to_cpu(ta_hdr->xgmi.fw_version); + adev->psp.xgmi_context.context.bin_desc.size_bytes = + le32_to_cpu(ta_hdr->xgmi.size_bytes); + adev->psp.xgmi_context.context.bin_desc.start_addr = + (uint8_t *)ta_hdr + le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); - adev->psp.ras.feature_version = le32_to_cpu(ta_hdr->ras.fw_version); - adev->psp.ras.size_bytes = le32_to_cpu(ta_hdr->ras.size_bytes); - adev->psp.ras.start_addr = (uint8_t *)adev->psp.xgmi.start_addr + + adev->psp.ras_context.context.bin_desc.feature_version = + le32_to_cpu(ta_hdr->ras.fw_version); + adev->psp.ras_context.context.bin_desc.size_bytes = + le32_to_cpu(ta_hdr->ras.size_bytes); + adev->psp.ras_context.context.bin_desc.start_addr = + (uint8_t *)adev->psp.xgmi_context.context.bin_desc.start_addr + le32_to_cpu(ta_hdr->ras.offset_bytes); } break; @@ -186,16 +192,24 @@ static int psp_v11_0_init_microcode(struct psp_context *psp) goto out2; ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data; - adev->psp.hdcp.feature_version = le32_to_cpu(ta_hdr->hdcp.fw_version); - adev->psp.hdcp.size_bytes = le32_to_cpu(ta_hdr->hdcp.size_bytes); - adev->psp.hdcp.start_addr = (uint8_t *)ta_hdr + - le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); + adev->psp.hdcp_context.context.bin_desc.feature_version = + le32_to_cpu(ta_hdr->hdcp.fw_version); + adev->psp.hdcp_context.context.bin_desc.size_bytes = + le32_to_cpu(ta_hdr->hdcp.size_bytes); + adev->psp.hdcp_context.context.bin_desc.start_addr = + (uint8_t *)ta_hdr + + le32_to_cpu( + ta_hdr->header.ucode_array_offset_bytes); adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); - adev->psp.dtm.feature_version = le32_to_cpu(ta_hdr->dtm.fw_version); - adev->psp.dtm.size_bytes = le32_to_cpu(ta_hdr->dtm.size_bytes); - adev->psp.dtm.start_addr = (uint8_t *)adev->psp.hdcp.start_addr + + adev->psp.dtm_context.context.bin_desc.feature_version = + le32_to_cpu(ta_hdr->dtm.fw_version); + adev->psp.dtm_context.context.bin_desc.size_bytes = + le32_to_cpu(ta_hdr->dtm.size_bytes); + adev->psp.dtm_context.context.bin_desc.start_addr = + (uint8_t *)adev->psp.hdcp_context.context + .bin_desc.start_addr + le32_to_cpu(ta_hdr->dtm.offset_bytes); } break; diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c index cc649406234ba..281bc4d7f0a1a 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c @@ -84,22 +84,22 @@ static int psp_v12_0_init_microcode(struct psp_context *psp) ta_hdr = (const struct ta_firmware_header_v1_0 *) adev->psp.ta_fw->data; - adev->psp.hdcp.feature_version = + adev->psp.hdcp_context.context.bin_desc.feature_version = le32_to_cpu(ta_hdr->hdcp.fw_version); - adev->psp.hdcp.size_bytes = + adev->psp.hdcp_context.context.bin_desc.size_bytes = le32_to_cpu(ta_hdr->hdcp.size_bytes); - adev->psp.hdcp.start_addr = + adev->psp.hdcp_context.context.bin_desc.start_addr = (uint8_t *)ta_hdr + le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); - adev->psp.dtm.feature_version = + adev->psp.dtm_context.context.bin_desc.feature_version = le32_to_cpu(ta_hdr->dtm.fw_version); - adev->psp.dtm.size_bytes = + adev->psp.dtm_context.context.bin_desc.size_bytes = le32_to_cpu(ta_hdr->dtm.size_bytes); - adev->psp.dtm.start_addr = - (uint8_t *)adev->psp.hdcp.start_addr + + adev->psp.dtm_context.context.bin_desc.start_addr = + (uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr + le32_to_cpu(ta_hdr->dtm.offset_bytes); } From 68331d7cf3a9cd0ddfb7463798a209b1e28ac4bf Mon Sep 17 00:00:00 2001 From: xinhui pan Date: Fri, 10 Sep 2021 07:54:46 +0800 Subject: [PATCH 093/151] drm/amdgpu: UVD avoid memory allocation during IB test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit move BO allocation in sw_init. Signed-off-by: xinhui pan Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 104 ++++++++++++++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h | 1 + drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 11 +-- drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 11 +-- 4 files changed, 74 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index d451c359606ae..b6e2abf26e183 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -134,6 +134,51 @@ MODULE_FIRMWARE(FIRMWARE_VEGA12); MODULE_FIRMWARE(FIRMWARE_VEGA20); static void amdgpu_uvd_idle_work_handler(struct work_struct *work); +static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo); + +static int amdgpu_uvd_create_msg_bo_helper(struct amdgpu_device *adev, + uint32_t size, + struct amdgpu_bo **bo_ptr) +{ + struct ttm_operation_ctx ctx = { true, false }; + struct amdgpu_bo *bo = NULL; + void *addr; + int r; + + r = amdgpu_bo_create_reserved(adev, size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_GTT, + &bo, NULL, &addr); + if (r) + return r; + + if (adev->uvd.address_64_bit) + goto succ; + + amdgpu_bo_kunmap(bo); + amdgpu_bo_unpin(bo); + amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM); + amdgpu_uvd_force_into_uvd_segment(bo); + r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); + if (r) + goto err; + r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_VRAM); + if (r) + goto err_pin; + r = amdgpu_bo_kmap(bo, &addr); + if (r) + goto err_kmap; +succ: + amdgpu_bo_unreserve(bo); + *bo_ptr = bo; + return 0; +err_kmap: + amdgpu_bo_unpin(bo); +err_pin: +err: + amdgpu_bo_unreserve(bo); + amdgpu_bo_unref(&bo); + return r; +} int amdgpu_uvd_sw_init(struct amdgpu_device *adev) { @@ -302,6 +347,10 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev) if (!amdgpu_device_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0)) adev->uvd.address_64_bit = true; + r = amdgpu_uvd_create_msg_bo_helper(adev, 128 << 10, &adev->uvd.ib_bo); + if (r) + return r; + switch (adev->asic_type) { case CHIP_TONGA: adev->uvd.use_ctx_buf = adev->uvd.fw_version >= FW_1_65_10; @@ -324,6 +373,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev) int amdgpu_uvd_sw_fini(struct amdgpu_device *adev) { + void *addr = amdgpu_bo_kptr(adev->uvd.ib_bo); int i, j; drm_sched_entity_destroy(&adev->uvd.entity); @@ -342,6 +392,7 @@ int amdgpu_uvd_sw_fini(struct amdgpu_device *adev) for (i = 0; i < AMDGPU_MAX_UVD_ENC_RINGS; ++i) amdgpu_ring_fini(&adev->uvd.inst[j].ring_enc[i]); } + amdgpu_bo_free_kernel(&adev->uvd.ib_bo, NULL, &addr); release_firmware(adev->uvd.fw); return 0; @@ -1080,23 +1131,10 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, unsigned offset_idx = 0; unsigned offset[3] = { UVD_BASE_SI, 0, 0 }; - amdgpu_bo_kunmap(bo); - amdgpu_bo_unpin(bo); - - if (!ring->adev->uvd.address_64_bit) { - struct ttm_operation_ctx ctx = { true, false }; - - amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM); - amdgpu_uvd_force_into_uvd_segment(bo); - r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); - if (r) - goto err; - } - r = amdgpu_job_alloc_with_ib(adev, 64, direct ? AMDGPU_IB_POOL_DIRECT : AMDGPU_IB_POOL_DELAYED, &job); if (r) - goto err; + return r; if (adev->asic_type >= CHIP_VEGA10) { offset_idx = 1 + ring->me; @@ -1147,9 +1185,9 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, goto err_free; } + amdgpu_bo_reserve(bo, true); amdgpu_bo_fence(bo, f, false); amdgpu_bo_unreserve(bo); - amdgpu_bo_unref(&bo); if (fence) *fence = dma_fence_get(f); @@ -1159,10 +1197,6 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, err_free: amdgpu_job_free(job); - -err: - amdgpu_bo_unreserve(bo); - amdgpu_bo_unref(&bo); return r; } @@ -1173,16 +1207,11 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, struct dma_fence **fence) { struct amdgpu_device *adev = ring->adev; - struct amdgpu_bo *bo = NULL; + struct amdgpu_bo *bo = adev->uvd.ib_bo; uint32_t *msg; - int r, i; - - r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_GTT, - &bo, NULL, (void **)&msg); - if (r) - return r; + int i; + msg = amdgpu_bo_kptr(bo); /* stitch together an UVD create msg */ msg[0] = cpu_to_le32(0x00000de4); msg[1] = cpu_to_le32(0x00000000); @@ -1199,6 +1228,7 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, msg[i] = cpu_to_le32(0x0); return amdgpu_uvd_send_msg(ring, bo, true, fence); + } int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, @@ -1209,12 +1239,15 @@ int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, uint32_t *msg; int r, i; - r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_GTT, - &bo, NULL, (void **)&msg); - if (r) - return r; + if (direct) { + bo = adev->uvd.ib_bo; + } else { + r = amdgpu_uvd_create_msg_bo_helper(adev, 4096, &bo); + if (r) + return r; + } + msg = amdgpu_bo_kptr(bo); /* stitch together an UVD destroy msg */ msg[0] = cpu_to_le32(0x00000de4); msg[1] = cpu_to_le32(0x00000002); @@ -1223,7 +1256,12 @@ int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, for (i = 4; i < 1024; ++i) msg[i] = cpu_to_le32(0x0); - return amdgpu_uvd_send_msg(ring, bo, direct, fence); + r = amdgpu_uvd_send_msg(ring, bo, direct, fence); + + if (!direct) + amdgpu_bo_free_kernel(&bo, NULL, (void **)&msg); + + return r; } static void amdgpu_uvd_idle_work_handler(struct work_struct *work) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h index edbb8194ee81b..76ac9699885da 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h @@ -68,6 +68,7 @@ struct amdgpu_uvd { /* store image width to adjust nb memory state */ unsigned decode_image_width; uint32_t keyselect; + struct amdgpu_bo *ib_bo; }; int amdgpu_uvd_sw_init(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index bc571833632ea..d5d023a242691 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -332,15 +332,9 @@ static int uvd_v6_0_enc_get_destroy_msg(struct amdgpu_ring *ring, static int uvd_v6_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct dma_fence *fence = NULL; - struct amdgpu_bo *bo = NULL; + struct amdgpu_bo *bo = ring->adev->uvd.ib_bo; long r; - r = amdgpu_bo_create_reserved(ring->adev, 128 * 1024, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &bo, NULL, NULL); - if (r) - return r; - r = uvd_v6_0_enc_get_create_msg(ring, 1, bo, NULL); if (r) goto error; @@ -357,9 +351,6 @@ static int uvd_v6_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) error: dma_fence_put(fence); - amdgpu_bo_unpin(bo); - amdgpu_bo_unreserve(bo); - amdgpu_bo_unref(&bo); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index b6e82d75561f6..c115b2da22ef6 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -338,15 +338,9 @@ static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handl static int uvd_v7_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct dma_fence *fence = NULL; - struct amdgpu_bo *bo = NULL; + struct amdgpu_bo *bo = ring->adev->uvd.ib_bo; long r; - r = amdgpu_bo_create_reserved(ring->adev, 128 * 1024, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &bo, NULL, NULL); - if (r) - return r; - r = uvd_v7_0_enc_get_create_msg(ring, 1, bo, NULL); if (r) goto error; @@ -363,9 +357,6 @@ static int uvd_v7_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) error: dma_fence_put(fence); - amdgpu_bo_unpin(bo); - amdgpu_bo_unreserve(bo); - amdgpu_bo_unref(&bo); return r; } From cb9038aa8a4e9f4535165602fd39f90c0892bc1b Mon Sep 17 00:00:00 2001 From: xinhui pan Date: Fri, 10 Sep 2021 07:56:30 +0800 Subject: [PATCH 094/151] drm/amdgpu: VCE avoid memory allocation during IB test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit alloc extra msg from direct IB pool. Signed-off-by: xinhui pan Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 27 ++++++++++++------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index e9fdf49d69e8c..caa4d3420e006 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -82,7 +82,6 @@ MODULE_FIRMWARE(FIRMWARE_VEGA20); static void amdgpu_vce_idle_work_handler(struct work_struct *work); static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, - struct amdgpu_bo *bo, struct dma_fence **fence); static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, bool direct, struct dma_fence **fence); @@ -441,12 +440,12 @@ void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp) * Open up a stream for HW test */ static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, - struct amdgpu_bo *bo, struct dma_fence **fence) { const unsigned ib_size_dw = 1024; struct amdgpu_job *job; struct amdgpu_ib *ib; + struct amdgpu_ib ib_msg; struct dma_fence *f = NULL; uint64_t addr; int i, r; @@ -456,9 +455,17 @@ static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, if (r) return r; - ib = &job->ibs[0]; + memset(&ib_msg, 0, sizeof(ib_msg)); + /* only one gpu page is needed, alloc +1 page to make addr aligned. */ + r = amdgpu_ib_get(ring->adev, NULL, AMDGPU_GPU_PAGE_SIZE * 2, + AMDGPU_IB_POOL_DIRECT, + &ib_msg); + if (r) + goto err; - addr = amdgpu_bo_gpu_offset(bo); + ib = &job->ibs[0]; + /* let addr point to page boundary */ + addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg.gpu_addr); /* stitch together an VCE create msg */ ib->length_dw = 0; @@ -498,6 +505,7 @@ static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, ib->ptr[i] = 0x0; r = amdgpu_job_submit_direct(job, ring, &f); + amdgpu_ib_free(ring->adev, &ib_msg, f); if (r) goto err; @@ -1134,20 +1142,13 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring) int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct dma_fence *fence = NULL; - struct amdgpu_bo *bo = NULL; long r; /* skip vce ring1/2 ib test for now, since it's not reliable */ if (ring != &ring->adev->vce.ring[0]) return 0; - r = amdgpu_bo_create_reserved(ring->adev, 512, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &bo, NULL, NULL); - if (r) - return r; - - r = amdgpu_vce_get_create_msg(ring, 1, bo, NULL); + r = amdgpu_vce_get_create_msg(ring, 1, NULL); if (r) goto error; @@ -1163,8 +1164,6 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout) error: dma_fence_put(fence); - amdgpu_bo_unreserve(bo); - amdgpu_bo_free_kernel(&bo, NULL, NULL); return r; } From 405a81ae3fe81a175ef51e6f4ed240744370163e Mon Sep 17 00:00:00 2001 From: xinhui pan Date: Fri, 10 Sep 2021 07:56:36 +0800 Subject: [PATCH 095/151] drm/amdgpu: VCN avoid memory allocation during IB test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit alloc extra msg from direct IB pool. Signed-off-by: xinhui pan Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 97 +++++++++++-------------- 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 561296a85b436..b60b8fe5bf672 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -541,15 +541,14 @@ int amdgpu_vcn_dec_sw_ring_test_ring(struct amdgpu_ring *ring) } static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring, - struct amdgpu_bo *bo, + struct amdgpu_ib *ib_msg, struct dma_fence **fence) { struct amdgpu_device *adev = ring->adev; struct dma_fence *f = NULL; struct amdgpu_job *job; struct amdgpu_ib *ib; - uint64_t addr; - void *msg = NULL; + uint64_t addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr); int i, r; r = amdgpu_job_alloc_with_ib(adev, 64, @@ -558,8 +557,6 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring, goto err; ib = &job->ibs[0]; - addr = amdgpu_bo_gpu_offset(bo); - msg = amdgpu_bo_kptr(bo); ib->ptr[0] = PACKET0(adev->vcn.internal.data0, 0); ib->ptr[1] = addr; ib->ptr[2] = PACKET0(adev->vcn.internal.data1, 0); @@ -576,9 +573,7 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring, if (r) goto err_free; - amdgpu_bo_fence(bo, f, false); - amdgpu_bo_unreserve(bo); - amdgpu_bo_free_kernel(&bo, NULL, (void **)&msg); + amdgpu_ib_free(adev, ib_msg, f); if (fence) *fence = dma_fence_get(f); @@ -588,27 +583,26 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring, err_free: amdgpu_job_free(job); - err: - amdgpu_bo_unreserve(bo); - amdgpu_bo_free_kernel(&bo, NULL, (void **)&msg); + amdgpu_ib_free(adev, ib_msg, f); return r; } static int amdgpu_vcn_dec_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, - struct amdgpu_bo **bo) + struct amdgpu_ib *ib) { struct amdgpu_device *adev = ring->adev; uint32_t *msg; int r, i; - *bo = NULL; - r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - bo, NULL, (void **)&msg); + memset(ib, 0, sizeof(*ib)); + r = amdgpu_ib_get(adev, NULL, AMDGPU_GPU_PAGE_SIZE * 2, + AMDGPU_IB_POOL_DIRECT, + ib); if (r) return r; + msg = (uint32_t *)AMDGPU_GPU_PAGE_ALIGN((unsigned long)ib->ptr); msg[0] = cpu_to_le32(0x00000028); msg[1] = cpu_to_le32(0x00000038); msg[2] = cpu_to_le32(0x00000001); @@ -630,19 +624,20 @@ static int amdgpu_vcn_dec_get_create_msg(struct amdgpu_ring *ring, uint32_t hand } static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, - struct amdgpu_bo **bo) + struct amdgpu_ib *ib) { struct amdgpu_device *adev = ring->adev; uint32_t *msg; int r, i; - *bo = NULL; - r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - bo, NULL, (void **)&msg); + memset(ib, 0, sizeof(*ib)); + r = amdgpu_ib_get(adev, NULL, AMDGPU_GPU_PAGE_SIZE * 2, + AMDGPU_IB_POOL_DIRECT, + ib); if (r) return r; + msg = (uint32_t *)AMDGPU_GPU_PAGE_ALIGN((unsigned long)ib->ptr); msg[0] = cpu_to_le32(0x00000028); msg[1] = cpu_to_le32(0x00000018); msg[2] = cpu_to_le32(0x00000000); @@ -658,21 +653,21 @@ static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct dma_fence *fence = NULL; - struct amdgpu_bo *bo; + struct amdgpu_ib ib; long r; - r = amdgpu_vcn_dec_get_create_msg(ring, 1, &bo); + r = amdgpu_vcn_dec_get_create_msg(ring, 1, &ib); if (r) goto error; - r = amdgpu_vcn_dec_send_msg(ring, bo, NULL); + r = amdgpu_vcn_dec_send_msg(ring, &ib, NULL); if (r) goto error; - r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &bo); + r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &ib); if (r) goto error; - r = amdgpu_vcn_dec_send_msg(ring, bo, &fence); + r = amdgpu_vcn_dec_send_msg(ring, &ib, &fence); if (r) goto error; @@ -688,8 +683,8 @@ int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout) } static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring, - struct amdgpu_bo *bo, - struct dma_fence **fence) + struct amdgpu_ib *ib_msg, + struct dma_fence **fence) { struct amdgpu_vcn_decode_buffer *decode_buffer = NULL; const unsigned int ib_size_dw = 64; @@ -697,7 +692,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring, struct dma_fence *f = NULL; struct amdgpu_job *job; struct amdgpu_ib *ib; - uint64_t addr; + uint64_t addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr); int i, r; r = amdgpu_job_alloc_with_ib(adev, ib_size_dw * 4, @@ -706,7 +701,6 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring, goto err; ib = &job->ibs[0]; - addr = amdgpu_bo_gpu_offset(bo); ib->length_dw = 0; ib->ptr[ib->length_dw++] = sizeof(struct amdgpu_vcn_decode_buffer) + 8; @@ -726,9 +720,7 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring, if (r) goto err_free; - amdgpu_bo_fence(bo, f, false); - amdgpu_bo_unreserve(bo); - amdgpu_bo_unref(&bo); + amdgpu_ib_free(adev, ib_msg, f); if (fence) *fence = dma_fence_get(f); @@ -738,31 +730,29 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring, err_free: amdgpu_job_free(job); - err: - amdgpu_bo_unreserve(bo); - amdgpu_bo_unref(&bo); + amdgpu_ib_free(adev, ib_msg, f); return r; } int amdgpu_vcn_dec_sw_ring_test_ib(struct amdgpu_ring *ring, long timeout) { struct dma_fence *fence = NULL; - struct amdgpu_bo *bo; + struct amdgpu_ib ib; long r; - r = amdgpu_vcn_dec_get_create_msg(ring, 1, &bo); + r = amdgpu_vcn_dec_get_create_msg(ring, 1, &ib); if (r) goto error; - r = amdgpu_vcn_dec_sw_send_msg(ring, bo, NULL); + r = amdgpu_vcn_dec_sw_send_msg(ring, &ib, NULL); if (r) goto error; - r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &bo); + r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &ib); if (r) goto error; - r = amdgpu_vcn_dec_sw_send_msg(ring, bo, &fence); + r = amdgpu_vcn_dec_sw_send_msg(ring, &ib, &fence); if (r) goto error; @@ -809,7 +799,7 @@ int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring) } static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, - struct amdgpu_bo *bo, + struct amdgpu_ib *ib_msg, struct dma_fence **fence) { const unsigned ib_size_dw = 16; @@ -825,7 +815,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand return r; ib = &job->ibs[0]; - addr = amdgpu_bo_gpu_offset(bo); + addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr); ib->length_dw = 0; ib->ptr[ib->length_dw++] = 0x00000018; @@ -863,7 +853,7 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand } static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, - struct amdgpu_bo *bo, + struct amdgpu_ib *ib_msg, struct dma_fence **fence) { const unsigned ib_size_dw = 16; @@ -879,7 +869,7 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han return r; ib = &job->ibs[0]; - addr = amdgpu_bo_gpu_offset(bo); + addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr); ib->length_dw = 0; ib->ptr[ib->length_dw++] = 0x00000018; @@ -918,21 +908,23 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) { + struct amdgpu_device *adev = ring->adev; struct dma_fence *fence = NULL; - struct amdgpu_bo *bo = NULL; + struct amdgpu_ib ib; long r; - r = amdgpu_bo_create_reserved(ring->adev, 128 * 1024, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &bo, NULL, NULL); + memset(&ib, 0, sizeof(ib)); + r = amdgpu_ib_get(adev, NULL, (128 << 10) + AMDGPU_GPU_PAGE_SIZE, + AMDGPU_IB_POOL_DIRECT, + &ib); if (r) return r; - r = amdgpu_vcn_enc_get_create_msg(ring, 1, bo, NULL); + r = amdgpu_vcn_enc_get_create_msg(ring, 1, &ib, NULL); if (r) goto error; - r = amdgpu_vcn_enc_get_destroy_msg(ring, 1, bo, &fence); + r = amdgpu_vcn_enc_get_destroy_msg(ring, 1, &ib, &fence); if (r) goto error; @@ -943,9 +935,8 @@ int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) r = 0; error: + amdgpu_ib_free(adev, &ib, fence); dma_fence_put(fence); - amdgpu_bo_unreserve(bo); - amdgpu_bo_free_kernel(&bo, NULL, NULL); return r; } From 0fcfb30019d3e0b891a201e41262b926648c38b0 Mon Sep 17 00:00:00 2001 From: xinhui pan Date: Sat, 11 Sep 2021 09:41:29 +0800 Subject: [PATCH 096/151] drm/amdgpu: Fix a race of IB test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Direct IB submission should be exclusive. So use write lock. Signed-off-by: xinhui pan Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 97d88f3e1c4c2..074ffcf0dac2f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1358,7 +1358,7 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused) } /* Avoid accidently unparking the sched thread during GPU reset */ - r = down_read_killable(&adev->reset_sem); + r = down_write_killable(&adev->reset_sem); if (r) return r; @@ -1387,7 +1387,7 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused) kthread_unpark(ring->sched.thread); } - up_read(&adev->reset_sem); + up_write(&adev->reset_sem); pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); From be68d44bf82aa23c53bff0ad4cfd3f90b3b82220 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 9 Sep 2021 11:01:00 +0800 Subject: [PATCH 097/151] drm/amd/pm: fix runpm hang when amdgpu loaded prior to sound driver Current RUNPM mechanism relies on PMFW to master the timing for BACO in/exit. And that needs cooperation from sound driver for dstate change notification for function 1(audio). Otherwise(on sound driver missing), BACO cannot be kicked in correctly and hang will be observed on RUNPM exit. By switching back to legacy message way on sound driver missing, we are able to fix the runpm hang observed for the scenario below: amdgpu driver loaded -> runpm suspend kicked -> sound driver loaded Signed-off-by: Evan Quan Reported-and-tested-by: Pierre-Eric Pelloux-Prayer Reviewed-by: Lijo Lazar Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher --- .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 24 +++++++++++++++++-- .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 4 ++-- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 21 ++++++++++++++++ drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 2 ++ 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 63e1f0db579cc..ae11f5ed7a978 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2274,7 +2274,27 @@ static int navi10_baco_enter(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; - if (adev->in_runpm) + /* + * This aims the case below: + * amdgpu driver loaded -> runpm suspend kicked -> sound driver loaded + * + * For NAVI10 and later ASICs, we rely on PMFW to handle the runpm. To + * make that possible, PMFW needs to acknowledge the dstate transition + * process for both gfx(function 0) and audio(function 1) function of + * the ASIC. + * + * The PCI device's initial runpm status is RUNPM_SUSPENDED. So as the + * device representing the audio function of the ASIC. And that means + * even if the sound driver(snd_hda_intel) was not loaded yet, it's still + * possible runpm suspend kicked on the ASIC. However without the dstate + * transition notification from audio function, pmfw cannot handle the + * BACO in/exit correctly. And that will cause driver hang on runpm + * resuming. + * + * To address this, we revert to legacy message way(driver masters the + * timing for BACO in/exit) on sound driver missing. + */ + if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO); else return smu_v11_0_baco_enter(smu); @@ -2284,7 +2304,7 @@ static int navi10_baco_exit(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; - if (adev->in_runpm) { + if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) { /* Wait for PMFW handling for the Dstate change */ msleep(10); return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index d7519688065ff..ca57221e39629 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -2189,7 +2189,7 @@ static int sienna_cichlid_baco_enter(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; - if (adev->in_runpm) + if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO); else return smu_v11_0_baco_enter(smu); @@ -2199,7 +2199,7 @@ static int sienna_cichlid_baco_exit(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; - if (adev->in_runpm) { + if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) { /* Wait for PMFW handling for the Dstate change */ msleep(10); return smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index 66711ab24c15a..843d2cbfc71d4 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -1053,3 +1053,24 @@ int smu_cmn_set_mp1_state(struct smu_context *smu, return ret; } + +bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev) +{ + struct pci_dev *p = NULL; + bool snd_driver_loaded; + + /* + * If the ASIC comes with no audio function, we always assume + * it is "enabled". + */ + p = pci_get_domain_bus_and_slot(pci_domain_nr(adev->pdev->bus), + adev->pdev->bus->number, 1); + if (!p) + return true; + + snd_driver_loaded = pci_is_enabled(p) ? true : false; + + pci_dev_put(p); + + return snd_driver_loaded; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h index 4054d9493e774..beea03810bcaa 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h @@ -123,5 +123,7 @@ static inline void smu_cmn_get_sysfs_buf(char **buf, int *offset) *buf -= *offset; } +bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev); + #endif #endif From f7f3e6258b0d8b4f7ae8cfa132d2611ab2dcabe1 Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Mon, 13 Sep 2021 10:08:23 +0200 Subject: [PATCH 098/151] drm/radeon: pass drm dev radeon_agp_head_init directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass drm dev directly as rdev->ddev gets initialized later on at radeon_device_init(). Bug: https://bugzilla.kernel.org/show_bug.cgi?id=214375 Signed-off-by: Nirmoy Das Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_kms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 0473583dcdac2..482fb0ae6cb5d 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -119,7 +119,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) #endif if (pci_find_capability(pdev, PCI_CAP_ID_AGP)) - rdev->agp = radeon_agp_head_init(rdev->ddev); + rdev->agp = radeon_agp_head_init(dev); if (rdev->agp) { rdev->agp->agp_mtrr = arch_phys_wc_add( rdev->agp->agp_info.aper_base, From 6cd1f9b40a3a74c67f9a9dc1b81cbe99900f1bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 9 Sep 2021 18:56:28 +0200 Subject: [PATCH 099/151] drm/amdgpu: Drop inline from amdgpu_ras_eeprom_max_record_count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was unusual; normally, inline functions are declared static as well, and defined in a header file if used by multiple compilation units. The latter would be more involved in this case, so just drop the inline declaration for now. Fixes compile failure building for ppc64le on RHEL 8: In file included from ../drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h:32, from ../drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c:33: ../drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c: In function ‘amdgpu_ras_recovery_init’: ../drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h:90:17: error: inlining failed in call to ‘always_inline’ ‘amdgpu_ras_eeprom_max_record_count’: function body not available 90 | inline uint32_t amdgpu_ras_eeprom_max_record_count(void); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c:1985:34: note: called from here 1985 | max_eeprom_records_len = amdgpu_ras_eeprom_max_record_count(); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Fixes: c84d46707ebb "drm/amdgpu: validate bad page threshold in ras(v3)" Reviewed-by: Lyude Paul Signed-off-by: Michel Dänzer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index dc44c946a2442..98732518543e5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -757,7 +757,7 @@ int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control, return res; } -inline uint32_t amdgpu_ras_eeprom_max_record_count(void) +uint32_t amdgpu_ras_eeprom_max_record_count(void) { return RAS_MAX_RECORD_COUNT; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h index f95fc61b30219..6bb00578bfbbc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h @@ -120,7 +120,7 @@ int amdgpu_ras_eeprom_read(struct amdgpu_ras_eeprom_control *control, int amdgpu_ras_eeprom_append(struct amdgpu_ras_eeprom_control *control, struct eeprom_table_record *records, const u32 num); -inline uint32_t amdgpu_ras_eeprom_max_record_count(void); +uint32_t amdgpu_ras_eeprom_max_record_count(void); void amdgpu_ras_debugfs_set_ret_size(struct amdgpu_ras_eeprom_control *control); From 31ea43442d0b3797ffd9906ee8ef1a1264565443 Mon Sep 17 00:00:00 2001 From: Paul Menzel Date: Mon, 13 Sep 2021 10:34:11 +0200 Subject: [PATCH 100/151] drm/amdgpu: Demote TMZ unsupported log message from warning to info As the user cannot do anything about the unsupported Trusted Memory Zone (TMZ) feature, do not warn about it, but make it informational, so demote the log level from warning to info. Signed-off-by: Paul Menzel Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index c7797eac83c3a..9ff600a38559d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -598,7 +598,7 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev) break; default: adev->gmc.tmz_enabled = false; - dev_warn(adev->dev, + dev_info(adev->dev, "Trusted Memory Zone (TMZ) feature not supported\n"); break; } From d77de7880e0e08f05ed2d4c533c647a618aa8632 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Fri, 10 Sep 2021 15:37:41 +0000 Subject: [PATCH 101/151] amd/display: enable panel orientation quirks This patch allows panel orientation quirks from DRM core to be used. They attach a DRM connector property "panel orientation" which indicates in which direction the panel has been mounted. Some machines have the internal screen mounted with a rotation. Since the panel orientation quirks need the native mode from the EDID, check for it in amdgpu_dm_connector_ddc_get_modes. Signed-off-by: Simon Ser Cc: Alex Deucher Cc: Harry Wentland Cc: Nicholas Kazlauskas Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 85d1304b8236e..ad2a7d6d47dad 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7826,6 +7826,32 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, } } +static void amdgpu_set_panel_orientation(struct drm_connector *connector) +{ + struct drm_encoder *encoder; + struct amdgpu_encoder *amdgpu_encoder; + const struct drm_display_mode *native_mode; + + if (connector->connector_type != DRM_MODE_CONNECTOR_eDP && + connector->connector_type != DRM_MODE_CONNECTOR_LVDS) + return; + + encoder = amdgpu_dm_connector_to_encoder(connector); + if (!encoder) + return; + + amdgpu_encoder = to_amdgpu_encoder(encoder); + + native_mode = &amdgpu_encoder->native_mode; + if (native_mode->hdisplay == 0 || native_mode->vdisplay == 0) + return; + + drm_connector_set_panel_orientation_with_quirk(connector, + DRM_MODE_PANEL_ORIENTATION_UNKNOWN, + native_mode->hdisplay, + native_mode->vdisplay); +} + static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, struct edid *edid) { @@ -7854,6 +7880,8 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, * restored here. */ amdgpu_dm_update_freesync_caps(connector, edid); + + amdgpu_set_panel_orientation(connector); } else { amdgpu_dm_connector->num_modes = 0; } From a0f884f5abcde966af7b99766d2de8a729d6c6fd Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Mon, 13 Sep 2021 14:56:44 -0400 Subject: [PATCH 102/151] drm/amd/display: Fix white screen page fault for gpuvm [Why] The "base_addr_is_mc_addr" field was added for dcn3.1 support but pa_config was never updated to set it to false. Uninitialized memory causes it to be set to true which results in address mistranslation and white screen. [How] Use memset to ensure all fields are initialized to 0 by default. Fixes: 64b1d0e8d500 ("drm/amd/display: Add DCN3.1 HWSEQ") Signed-off-by: Nicholas Kazlauskas Acked-by: Alex Deucher Acked-by: Aaron Liu Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ad2a7d6d47dad..ab5aad21a0415 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1125,6 +1125,8 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_ uint32_t agp_base, agp_bot, agp_top; PHYSICAL_ADDRESS_LOC page_table_start, page_table_end, page_table_base; + memset(pa_config, 0, sizeof(*pa_config)); + logical_addr_low = min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18; pt_base = amdgpu_gmc_pd_addr(adev->gart.bo); From 44144f1a3f20fe4cf934c624bd998ce97ebca608 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 14 Sep 2021 10:50:47 -0400 Subject: [PATCH 103/151] drm/amdgpu/display: add a proper license to dc_link_dp.c Was missing. Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 6663cfc4eb71b..7ea5051093404 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1,4 +1,26 @@ -/* Copyright 2015 Advanced Micro Devices, Inc. */ +/* + * Copyright 2015 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 + */ #include "dm_services.h" #include "dc.h" #include "dc_link_dp.h" From 3f83f17b73113f4008ba9b20dd9a17d2d044c289 Mon Sep 17 00:00:00 2001 From: Candice Li Date: Thu, 9 Sep 2021 20:18:48 +0800 Subject: [PATCH 104/151] drm/amdgpu: Conform ASD header/loading to generic TA systems Update asd_context structure and add asd_initialize function to conform ASD header/loading to generic TA systems. Signed-off-by: Candice Li Reviewed-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 60 ++++++++++--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 10 ++--- 2 files changed, 26 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 071dadf3a4509..bc861f2fe0ecf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -47,6 +47,7 @@ static void psp_sysfs_fini(struct amdgpu_device *adev); static int psp_load_smu_fw(struct psp_context *psp); static int psp_ta_unload(struct psp_context *psp, uint32_t session_id); +static int psp_ta_load(struct psp_context *psp, struct ta_context *context); static int psp_rap_terminate(struct psp_context *psp); static int psp_securedisplay_terminate(struct psp_context *psp); @@ -781,23 +782,14 @@ static int psp_rl_load(struct amdgpu_device *adev) return ret; } -static void psp_prep_asd_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, - uint64_t asd_mc, uint32_t size) +static int psp_asd_load(struct psp_context *psp) { - cmd->cmd_id = GFX_CMD_ID_LOAD_ASD; - cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(asd_mc); - cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(asd_mc); - cmd->cmd.cmd_load_ta.app_len = size; - - cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo = 0; - cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi = 0; - cmd->cmd.cmd_load_ta.cmd_buf_len = 0; + return psp_ta_load(psp, &psp->asd_context); } -static int psp_asd_load(struct psp_context *psp) +static int psp_asd_initialize(struct psp_context *psp) { int ret; - struct psp_gfx_cmd_resp *cmd; /* If PSP version doesn't match ASD version, asd loading will be failed. * add workaround to bypass it for sriov now. @@ -806,22 +798,13 @@ static int psp_asd_load(struct psp_context *psp) if (amdgpu_sriov_vf(psp->adev) || !psp->asd_context.bin_desc.size_bytes) return 0; - cmd = acquire_psp_cmd_buf(psp); + psp->asd_context.mem_context.shared_mc_addr = 0; + psp->asd_context.mem_context.shared_mem_size = PSP_ASD_SHARED_MEM_SIZE; + psp->asd_context.ta_load_type = GFX_CMD_ID_LOAD_ASD; - psp_copy_fw(psp, psp->asd_context.bin_desc.start_addr, - psp->asd_context.bin_desc.size_bytes); - - psp_prep_asd_load_cmd_buf(cmd, psp->fw_pri_mc_addr, - psp->asd_context.bin_desc.size_bytes); - - ret = psp_cmd_submit_buf(psp, NULL, cmd, - psp->fence_buf_mc_addr); - if (!ret) { - psp->asd_context.asd_initialized = true; - psp->asd_context.session_id = cmd->resp.session_id; - } - - release_psp_cmd_buf(psp); + ret = psp_asd_load(psp); + if (!ret) + psp->asd_context.initialized = true; return ret; } @@ -859,13 +842,13 @@ static int psp_asd_terminate(struct psp_context *psp) if (amdgpu_sriov_vf(psp->adev)) return 0; - if (!psp->asd_context.asd_initialized) + if (!psp->asd_context.initialized) return 0; ret = psp_asd_unload(psp); if (!ret) - psp->asd_context.asd_initialized = false; + psp->asd_context.initialized = false; return ret; } @@ -903,7 +886,7 @@ static void psp_prep_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd, uint64_t ta_bin_mc, struct ta_context *context) { - cmd->cmd_id = GFX_CMD_ID_LOAD_TA; + cmd->cmd_id = context->ta_load_type; cmd->cmd.cmd_load_ta.app_phy_addr_lo = lower_32_bits(ta_bin_mc); cmd->cmd.cmd_load_ta.app_phy_addr_hi = upper_32_bits(ta_bin_mc); cmd->cmd.cmd_load_ta.app_len = context->bin_desc.size_bytes; @@ -970,8 +953,7 @@ static int psp_ta_invoke(struct psp_context *psp, return ret; } -static int psp_ta_load(struct psp_context *psp, - struct ta_context *context) +static int psp_ta_load(struct psp_context *psp, struct ta_context *context) { int ret; struct psp_gfx_cmd_resp *cmd; @@ -981,9 +963,7 @@ static int psp_ta_load(struct psp_context *psp, psp_copy_fw(psp, context->bin_desc.start_addr, context->bin_desc.size_bytes); - psp_prep_ta_load_cmd_buf(cmd, - psp->fw_pri_mc_addr, - context); + psp_prep_ta_load_cmd_buf(cmd, psp->fw_pri_mc_addr, context); ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); @@ -1051,6 +1031,7 @@ int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool lo goto invoke; psp->xgmi_context.context.mem_context.shared_mem_size = PSP_XGMI_SHARED_MEM_SIZE; + psp->xgmi_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; if (!psp->xgmi_context.context.initialized) { ret = psp_xgmi_init_shared_buf(psp); @@ -1450,6 +1431,7 @@ static int psp_ras_initialize(struct psp_context *psp) } psp->ras_context.context.mem_context.shared_mem_size = PSP_RAS_SHARED_MEM_SIZE; + psp->ras_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; if (!psp->ras_context.context.initialized) { ret = psp_ras_init_shared_buf(psp); @@ -1539,6 +1521,7 @@ static int psp_hdcp_initialize(struct psp_context *psp) } psp->hdcp_context.context.mem_context.shared_mem_size = PSP_HDCP_SHARED_MEM_SIZE; + psp->hdcp_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; if (!psp->hdcp_context.context.initialized) { ret = psp_hdcp_init_shared_buf(psp); @@ -1630,6 +1613,7 @@ static int psp_dtm_initialize(struct psp_context *psp) } psp->dtm_context.context.mem_context.shared_mem_size = PSP_DTM_SHARED_MEM_SIZE; + psp->dtm_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; if (!psp->dtm_context.context.initialized) { ret = psp_dtm_init_shared_buf(psp); @@ -1727,6 +1711,7 @@ static int psp_rap_initialize(struct psp_context *psp) } psp->rap_context.context.mem_context.shared_mem_size = PSP_RAP_SHARED_MEM_SIZE; + psp->rap_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; if (!psp->rap_context.context.initialized) { ret = psp_rap_init_shared_buf(psp); @@ -1842,6 +1827,7 @@ static int psp_securedisplay_initialize(struct psp_context *psp) psp->securedisplay_context.context.mem_context.shared_mem_size = PSP_SECUREDISPLAY_SHARED_MEM_SIZE; + psp->securedisplay_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA; if (!psp->securedisplay_context.context.initialized) { ret = psp_securedisplay_init_shared_buf(psp); @@ -2419,7 +2405,7 @@ static int psp_load_fw(struct amdgpu_device *adev) if (ret) goto failed; - ret = psp_asd_load(psp); + ret = psp_asd_initialize(psp); if (ret) { DRM_ERROR("PSP load asd failed!\n"); return ret; @@ -2616,7 +2602,7 @@ static int psp_resume(void *handle) if (ret) goto failed; - ret = psp_asd_load(psp); + ret = psp_asd_initialize(psp); if (ret) { DRM_ERROR("PSP load asd failed!\n"); goto failed; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index cfd7ac976cd1e..f29afabbff1fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -39,6 +39,7 @@ #define PSP_FW_NAME_LEN 0x24 enum psp_shared_mem_size { + PSP_ASD_SHARED_MEM_SIZE = 0x0, PSP_XGMI_SHARED_MEM_SIZE = 0x4000, PSP_RAS_SHARED_MEM_SIZE = 0x4000, PSP_HDCP_SHARED_MEM_SIZE = 0x4000, @@ -140,12 +141,6 @@ struct psp_bin_desc { uint8_t *start_addr; }; -struct psp_asd_context { - bool asd_initialized; - uint32_t session_id; - struct psp_bin_desc bin_desc; -}; - struct ta_mem_context { struct amdgpu_bo *shared_bo; uint64_t shared_mc_addr; @@ -158,6 +153,7 @@ struct ta_context { uint32_t session_id; struct ta_mem_context mem_context; struct psp_bin_desc bin_desc; + enum psp_gfx_cmd_id ta_load_type; }; struct ta_cp_context { @@ -331,7 +327,7 @@ struct psp_context const struct firmware *ta_fw; uint32_t ta_fw_version; - struct psp_asd_context asd_context; + struct ta_context asd_context; struct psp_xgmi_context xgmi_context; struct psp_ras_context ras_context; struct ta_cp_context hdcp_context; From 17c6805a009cdc78581065a1fb086f5ca9db3a9e Mon Sep 17 00:00:00 2001 From: Candice Li Date: Fri, 10 Sep 2021 22:04:54 +0800 Subject: [PATCH 105/151] drm/amdgpu: Update PSP TA unload function Update PSP TA unload function to use PSP TA context as input argument. Signed-off-by: Candice Li Reviewed-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index bc861f2fe0ecf..7d09b28889afe 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -46,7 +46,7 @@ static int psp_sysfs_init(struct amdgpu_device *adev); static void psp_sysfs_fini(struct amdgpu_device *adev); static int psp_load_smu_fw(struct psp_context *psp); -static int psp_ta_unload(struct psp_context *psp, uint32_t session_id); +static int psp_ta_unload(struct psp_context *psp, struct ta_context *context); static int psp_ta_load(struct psp_context *psp, struct ta_context *context); static int psp_rap_terminate(struct psp_context *psp); static int psp_securedisplay_terminate(struct psp_context *psp); @@ -816,12 +816,12 @@ static void psp_prep_ta_unload_cmd_buf(struct psp_gfx_cmd_resp *cmd, cmd->cmd.cmd_unload_ta.session_id = session_id; } -static int psp_ta_unload(struct psp_context *psp, uint32_t session_id) +static int psp_ta_unload(struct psp_context *psp, struct ta_context *context) { int ret; struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp); - psp_prep_ta_unload_cmd_buf(cmd, session_id); + psp_prep_ta_unload_cmd_buf(cmd, context->session_id); ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); @@ -832,7 +832,7 @@ static int psp_ta_unload(struct psp_context *psp, uint32_t session_id) static int psp_asd_unload(struct psp_context *psp) { - return psp_ta_unload(psp, psp->asd_context.session_id); + return psp_ta_unload(psp, &psp->asd_context); } static int psp_asd_terminate(struct psp_context *psp) @@ -984,7 +984,7 @@ static int psp_xgmi_load(struct psp_context *psp) static int psp_xgmi_unload(struct psp_context *psp) { - return psp_ta_unload(psp, psp->xgmi_context.context.session_id); + return psp_ta_unload(psp, &psp->xgmi_context.context); } int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id) @@ -1275,7 +1275,7 @@ static int psp_ras_load(struct psp_context *psp) static int psp_ras_unload(struct psp_context *psp) { - return psp_ta_unload(psp, psp->ras_context.context.session_id); + return psp_ta_unload(psp, &psp->ras_context.context); } int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id) @@ -1540,7 +1540,7 @@ static int psp_hdcp_initialize(struct psp_context *psp) static int psp_hdcp_unload(struct psp_context *psp) { - return psp_ta_unload(psp, psp->hdcp_context.context.session_id); + return psp_ta_unload(psp, &psp->hdcp_context.context); } int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id) @@ -1632,7 +1632,7 @@ static int psp_dtm_initialize(struct psp_context *psp) static int psp_dtm_unload(struct psp_context *psp) { - return psp_ta_unload(psp, psp->dtm_context.context.session_id); + return psp_ta_unload(psp, &psp->dtm_context.context); } int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id) @@ -1690,7 +1690,7 @@ static int psp_rap_load(struct psp_context *psp) static int psp_rap_unload(struct psp_context *psp) { - return psp_ta_unload(psp, psp->rap_context.context.session_id); + return psp_ta_unload(psp, &psp->rap_context.context); } static int psp_rap_initialize(struct psp_context *psp) @@ -1805,7 +1805,7 @@ static int psp_securedisplay_load(struct psp_context *psp) static int psp_securedisplay_unload(struct psp_context *psp) { - return psp_ta_unload(psp, psp->securedisplay_context.context.session_id); + return psp_ta_unload(psp, &psp->securedisplay_context.context); } static int psp_securedisplay_initialize(struct psp_context *psp) From 226f4f5a6b6cb417ab2ed8550ea47c10190426a1 Mon Sep 17 00:00:00 2001 From: John Clements Date: Wed, 15 Sep 2021 17:14:12 +0800 Subject: [PATCH 106/151] drm/amdgpu: Resolve nBIF RAS error harvesting bug Set correct RAS nBIF error query register offsets on aldebaran Signed-off-by: John Clements Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c | 30 ++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c index f50045cebd44c..0a9fc19b1be02 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c @@ -566,7 +566,9 @@ static int nbio_v7_4_init_ras_err_event_athub_interrupt (struct amdgpu_device *a return r; } -#define smnPARITY_ERROR_STATUS_UNCORR_GRP2 0x13a20030 +#define smnPARITY_ERROR_STATUS_UNCORR_GRP2 0x13a20030 +#define smnPARITY_ERROR_STATUS_UNCORR_GRP2_ALDE 0x13b20030 +#define smnRAS_GLOBAL_STATUS_LO_ALDE 0x13b20020 static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev, void *ras_error_status) @@ -575,12 +577,20 @@ static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev, uint32_t corr, fatal, non_fatal; struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; - global_sts = RREG32_PCIE(smnRAS_GLOBAL_STATUS_LO); + if (adev->asic_type == CHIP_ALDEBARAN) + global_sts = RREG32_PCIE(smnRAS_GLOBAL_STATUS_LO_ALDE); + else + global_sts = RREG32_PCIE(smnRAS_GLOBAL_STATUS_LO); + corr = REG_GET_FIELD(global_sts, RAS_GLOBAL_STATUS_LO, ParityErrCorr); fatal = REG_GET_FIELD(global_sts, RAS_GLOBAL_STATUS_LO, ParityErrFatal); non_fatal = REG_GET_FIELD(global_sts, RAS_GLOBAL_STATUS_LO, ParityErrNonFatal); - parity_sts = RREG32_PCIE(smnPARITY_ERROR_STATUS_UNCORR_GRP2); + + if (adev->asic_type == CHIP_ALDEBARAN) + parity_sts = RREG32_PCIE(smnPARITY_ERROR_STATUS_UNCORR_GRP2_ALDE); + else + parity_sts = RREG32_PCIE(smnPARITY_ERROR_STATUS_UNCORR_GRP2); if (corr) err_data->ce_count++; @@ -589,13 +599,21 @@ static void nbio_v7_4_query_ras_error_count(struct amdgpu_device *adev, if (corr || fatal || non_fatal) { central_sts = RREG32_PCIE(smnBIFL_RAS_CENTRAL_STATUS); + /* clear error status register */ - WREG32_PCIE(smnRAS_GLOBAL_STATUS_LO, global_sts); + if (adev->asic_type == CHIP_ALDEBARAN) + WREG32_PCIE(smnRAS_GLOBAL_STATUS_LO_ALDE, global_sts); + else + WREG32_PCIE(smnRAS_GLOBAL_STATUS_LO, global_sts); if (fatal) + { /* clear parity fatal error indication field */ - WREG32_PCIE(smnPARITY_ERROR_STATUS_UNCORR_GRP2, - parity_sts); + if (adev->asic_type == CHIP_ALDEBARAN) + WREG32_PCIE(smnPARITY_ERROR_STATUS_UNCORR_GRP2_ALDE, parity_sts); + else + WREG32_PCIE(smnPARITY_ERROR_STATUS_UNCORR_GRP2, parity_sts); + } if (REG_GET_FIELD(central_sts, BIFL_RAS_CENTRAL_STATUS, BIFL_RasContller_Intr_Recv)) { From b64cc0575d0a1b9e96c5345a6a8a06a43377acf9 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 15 Sep 2021 12:36:11 +0100 Subject: [PATCH 107/151] drm/radeon: make array encoded_lanes static Don't populate the read-only array encoded_lanes on the stack but instead it static. Also makes the object code smaller by 97 bytes: Before: text data bss dec hex filename 38899 8064 0 46963 b773 ./drivers/gpu/drm/radeon/r600_dpm.o After: text data bss dec hex filename 38738 8128 0 46866 b712 ./drivers/gpu/drm/radeon/r600_dpm.o (gcc version 11.2.0) Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_dpm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index fd4226b99862b..9d2bcb9551e61 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c @@ -1361,7 +1361,9 @@ u16 r600_get_pcie_lane_support(struct radeon_device *rdev, u8 r600_encode_pci_lane_width(u32 lanes) { - u8 encoded_lanes[] = { 0, 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6 }; + static const u8 encoded_lanes[] = { + 0, 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6 + }; if (lanes > 16) return 0; From 3d360154dd1148ed7834cd48bd78d67925821fe8 Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Wed, 15 Sep 2021 00:59:46 +0100 Subject: [PATCH 108/151] drm/amd/display: Use dcc_ind_blk value to set register directly We don't need to do this workaround if we start setting this value when we fill the plane attributes. Acked-by: Harry Wentland Signed-off-by: Joshua Ashton Reviewed-by: Bas Nieuwenhuizen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 ++++++- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c | 6 ------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index ab5aad21a0415..e577bc93465be 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5052,10 +5052,15 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev, if (modifier_has_dcc(modifier) && !force_disable_dcc) { uint64_t dcc_address = afb->address + afb->base.offsets[1]; + bool independent_64b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier); dcc->enable = 1; dcc->meta_pitch = afb->base.pitches[1]; - dcc->independent_64b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier); + dcc->independent_64b_blks = independent_64b_blks; + if (independent_64b_blks) + dcc->dcc_ind_blk = hubp_ind_block_64b; + else + dcc->dcc_ind_blk = hubp_ind_block_unconstrained; address->grph.meta_addr.low_part = lower_32_bits(dcc_address); address->grph.meta_addr.high_part = upper_32_bits(dcc_address); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e362ec65349de..331a7517176b5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2015,7 +2015,7 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa } if (u->plane_info->dcc.enable != u->surface->dcc.enable - || u->plane_info->dcc.independent_64b_blks != u->surface->dcc.independent_64b_blks + || u->plane_info->dcc.dcc_ind_blk != u->surface->dcc.dcc_ind_blk || u->plane_info->dcc.meta_pitch != u->surface->dcc.meta_pitch) { /* During DCC on/off, stutter period is calculated before * DCC has fully transitioned. This results in incorrect diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c index f246125232482..eac08926b5741 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c @@ -356,12 +356,6 @@ void hubp3_dcc_control_sienna_cichlid(struct hubp *hubp, { struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp); - /*Workaround until UMD fix the new dcc_ind_blk interface */ - if (dcc->independent_64b_blks && dcc->dcc_ind_blk == 0) - dcc->dcc_ind_blk = 1; - if (dcc->independent_64b_blks_c && dcc->dcc_ind_blk_c == 0) - dcc->dcc_ind_blk_c = 1; - REG_UPDATE_6(DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, dcc->enable, PRIMARY_SURFACE_DCC_IND_BLK, dcc->dcc_ind_blk, From a86396c3a742865821f29fdb3b9bb00e005d013f Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Wed, 15 Sep 2021 00:59:47 +0100 Subject: [PATCH 109/151] drm/amd/display: Handle GFX10_RBPLUS modifiers for dcc_ind_blk Adds the missing logic to set the correct value of dcc_ind_blk for this tiling version. Signed-off-by: Joshua Ashton Reviewed-by: Bas Nieuwenhuizen Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e577bc93465be..db2ca49a36e1a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5053,14 +5053,26 @@ fill_gfx9_plane_attributes_from_modifiers(struct amdgpu_device *adev, if (modifier_has_dcc(modifier) && !force_disable_dcc) { uint64_t dcc_address = afb->address + afb->base.offsets[1]; bool independent_64b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_64B, modifier); + bool independent_128b_blks = AMD_FMT_MOD_GET(DCC_INDEPENDENT_128B, modifier); dcc->enable = 1; dcc->meta_pitch = afb->base.pitches[1]; dcc->independent_64b_blks = independent_64b_blks; - if (independent_64b_blks) - dcc->dcc_ind_blk = hubp_ind_block_64b; - else - dcc->dcc_ind_blk = hubp_ind_block_unconstrained; + if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) == AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) { + if (independent_64b_blks && independent_128b_blks) + dcc->dcc_ind_blk = hubp_ind_block_64b; + else if (independent_128b_blks) + dcc->dcc_ind_blk = hubp_ind_block_128b; + else if (independent_64b_blks && !independent_128b_blks) + dcc->dcc_ind_blk = hubp_ind_block_64b_no_128bcl; + else + dcc->dcc_ind_blk = hubp_ind_block_unconstrained; + } else { + if (independent_64b_blks) + dcc->dcc_ind_blk = hubp_ind_block_64b; + else + dcc->dcc_ind_blk = hubp_ind_block_unconstrained; + } address->grph.meta_addr.low_part = lower_32_bits(dcc_address); address->grph.meta_addr.high_part = upper_32_bits(dcc_address); From 7f6ab50a62a81f91aba6e853364e4f7d9fbaf27d Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Wed, 15 Sep 2021 00:59:48 +0100 Subject: [PATCH 110/151] drm/amd/display: Add modifiers capable of DCC image stores for gfx10_3 Some games, ie. Doom Eternal, present from compute following compute post-fx and would benefit from having DCC image stores available. DCN on gfx10_3 doesn't need INDEPENDENT_128B_BLOCKS = 0 so we can expose these modifiers capable of DCC image stores. Signed-off-by: Joshua Ashton Reviewed-by: Bas Nieuwenhuizen Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index db2ca49a36e1a..5d3679bd6b29b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4955,6 +4955,16 @@ add_gfx10_3_modifiers(const struct amdgpu_device *adev, AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) | AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B)); + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(PACKERS, pkrs) | + AMD_FMT_MOD_SET(DCC, 1) | + AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) | + AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) | + AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B)); + add_modifier(mods, size, capacity, AMD_FMT_MOD | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) | AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) | @@ -4967,6 +4977,17 @@ add_gfx10_3_modifiers(const struct amdgpu_device *adev, AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) | AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_64B)); + add_modifier(mods, size, capacity, AMD_FMT_MOD | + AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) | + AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) | + AMD_FMT_MOD_SET(PIPE_XOR_BITS, pipe_xor_bits) | + AMD_FMT_MOD_SET(PACKERS, pkrs) | + AMD_FMT_MOD_SET(DCC, 1) | + AMD_FMT_MOD_SET(DCC_RETILE, 1) | + AMD_FMT_MOD_SET(DCC_CONSTANT_ENCODE, 1) | + AMD_FMT_MOD_SET(DCC_INDEPENDENT_128B, 1) | + AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, AMD_FMT_MOD_DCC_BLOCK_128B)); + add_modifier(mods, size, capacity, AMD_FMT_MOD | AMD_FMT_MOD_SET(TILE, AMD_FMT_MOD_TILE_GFX9_64K_R_X) | AMD_FMT_MOD_SET(TILE_VERSION, AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS) | From 006c26a0f1c851e0693e4bdd5657a687514d21cf Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 15 Sep 2021 16:07:49 -0400 Subject: [PATCH 111/151] drm/amd/display: Fix crash on device remove/driver unload Why: DC core is being released from DM before it's referenced from hpd_rx wq destruction code. How: Move hpd_rx destruction before DC core destruction. Signed-off-by: Andrey Grodzovsky Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 5d3679bd6b29b..1c0547bb09de5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1572,6 +1572,18 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) &adev->dm.dmub_bo_gpu_addr, &adev->dm.dmub_bo_cpu_addr); + if (adev->dm.hpd_rx_offload_wq) { + for (i = 0; i < adev->dm.dc->caps.max_links; i++) { + if (adev->dm.hpd_rx_offload_wq[i].wq) { + destroy_workqueue(adev->dm.hpd_rx_offload_wq[i].wq); + adev->dm.hpd_rx_offload_wq[i].wq = NULL; + } + } + + kfree(adev->dm.hpd_rx_offload_wq); + adev->dm.hpd_rx_offload_wq = NULL; + } + /* DC Destroy TODO: Replace destroy DAL */ if (adev->dm.dc) dc_destroy(&adev->dm.dc); @@ -1590,18 +1602,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev) adev->dm.freesync_module = NULL; } - if (adev->dm.hpd_rx_offload_wq) { - for (i = 0; i < adev->dm.dc->caps.max_links; i++) { - if (adev->dm.hpd_rx_offload_wq[i].wq) { - destroy_workqueue(adev->dm.hpd_rx_offload_wq[i].wq); - adev->dm.hpd_rx_offload_wq[i].wq = NULL; - } - } - - kfree(adev->dm.hpd_rx_offload_wq); - adev->dm.hpd_rx_offload_wq = NULL; - } - mutex_destroy(&adev->dm.audio_lock); mutex_destroy(&adev->dm.dc_lock); From b2fe31cf648156331991333c1d87346321cab056 Mon Sep 17 00:00:00 2001 From: xinhui pan Date: Wed, 15 Sep 2021 09:08:28 +0800 Subject: [PATCH 112/151] drm/amdgpu: Put drm_dev_enter/exit outside hot codepath We hit soft hang while doing memory pressure test on one numa system. After a qucik look, this is because kfd invalid/valid userptr memory frequently with process_info lock hold. Looks like update page table mapping use too much cpu time. perf top says below, 75.81% [kernel] [k] __srcu_read_unlock 6.19% [amdgpu] [k] amdgpu_gmc_set_pte_pde 3.56% [kernel] [k] __srcu_read_lock 2.20% [amdgpu] [k] amdgpu_vm_cpu_update 2.20% [kernel] [k] __sg_page_iter_dma_next 2.15% [drm] [k] drm_dev_enter 1.70% [drm] [k] drm_prime_sg_to_dma_addr_array 1.18% [kernel] [k] __sg_alloc_table_from_pages 1.09% [drm] [k] drm_dev_exit So move drm_dev_enter/exit outside gmc code, instead let caller do it. They are gart_unbind, gart_map, vm_clear_bo, vm_update_pdes and gmc_init_pdb0. vm_bo_update_mapping already calls it. Signed-off-by: xinhui pan Reviewed-and-tested-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c | 11 ++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 11 +++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 28 +++++++++++++++++------- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index 76efd5f8950fc..d7e4f4660acf2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -34,6 +34,7 @@ #include #endif #include "amdgpu.h" +#include /* * GART @@ -230,12 +231,16 @@ int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, u64 page_base; /* Starting from VEGA10, system bit must be 0 to mean invalid. */ uint64_t flags = 0; + int idx; if (!adev->gart.ready) { WARN(1, "trying to unbind memory from uninitialized GART !\n"); return -EINVAL; } + if (!drm_dev_enter(&adev->ddev, &idx)) + return 0; + t = offset / AMDGPU_GPU_PAGE_SIZE; p = t / AMDGPU_GPU_PAGES_IN_CPU_PAGE; for (i = 0; i < pages; i++, p++) { @@ -254,6 +259,7 @@ int amdgpu_gart_unbind(struct amdgpu_device *adev, uint64_t offset, for (i = 0; i < adev->num_vmhubs; i++) amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0); + drm_dev_exit(idx); return 0; } @@ -276,12 +282,16 @@ int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset, { uint64_t page_base; unsigned i, j, t; + int idx; if (!adev->gart.ready) { WARN(1, "trying to bind memory to uninitialized GART !\n"); return -EINVAL; } + if (!drm_dev_enter(&adev->ddev, &idx)) + return 0; + t = offset / AMDGPU_GPU_PAGE_SIZE; for (i = 0; i < pages; i++) { @@ -291,6 +301,7 @@ int amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset, page_base += AMDGPU_GPU_PAGE_SIZE; } } + drm_dev_exit(idx); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 9ff600a38559d..a0dec7f211f05 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -153,10 +153,6 @@ int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr, { void __iomem *ptr = (void *)cpu_pt_addr; uint64_t value; - int idx; - - if (!drm_dev_enter(&adev->ddev, &idx)) - return 0; /* * The following is for PTE only. GART does not have PDEs. @@ -165,8 +161,6 @@ int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr, value |= flags; writeq(value, ptr + (gpu_page_idx * 8)); - drm_dev_exit(idx); - return 0; } @@ -749,6 +743,10 @@ void amdgpu_gmc_init_pdb0(struct amdgpu_device *adev) adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size; u64 vram_end = vram_addr + vram_size; u64 gart_ptb_gpu_pa = amdgpu_gmc_vram_pa(adev, adev->gart.bo); + int idx; + + if (!drm_dev_enter(&adev->ddev, &idx)) + return; flags |= AMDGPU_PTE_VALID | AMDGPU_PTE_READABLE; flags |= AMDGPU_PTE_WRITEABLE; @@ -770,6 +768,7 @@ void amdgpu_gmc_init_pdb0(struct amdgpu_device *adev) flags |= AMDGPU_PDE_BFS(0) | AMDGPU_PTE_SNOOPED; /* Requires gart_ptb_gpu_pa to be 4K aligned */ amdgpu_gmc_set_pte_pde(adev, adev->gmc.ptr_pdb0, i, gart_ptb_gpu_pa, flags); + drm_dev_exit(idx); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 6b15cad78de9d..a1ddf74bbdbaf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -800,7 +800,7 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, struct amdgpu_bo *bo = &vmbo->bo; unsigned entries, ats_entries; uint64_t addr; - int r; + int r, idx; /* Figure out our place in the hierarchy */ if (ancestor->parent) { @@ -845,9 +845,12 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, return r; } + if (!drm_dev_enter(&adev->ddev, &idx)) + return -ENODEV; + r = vm->update_funcs->map_table(vmbo); if (r) - return r; + goto exit; memset(¶ms, 0, sizeof(params)); params.adev = adev; @@ -856,7 +859,7 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, r = vm->update_funcs->prepare(¶ms, NULL, AMDGPU_SYNC_EXPLICIT); if (r) - return r; + goto exit; addr = 0; if (ats_entries) { @@ -872,7 +875,7 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, r = vm->update_funcs->update(¶ms, vmbo, addr, 0, ats_entries, value, flags); if (r) - return r; + goto exit; addr += ats_entries * 8; } @@ -895,10 +898,13 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, r = vm->update_funcs->update(¶ms, vmbo, addr, 0, entries, value, flags); if (r) - return r; + goto exit; } - return vm->update_funcs->commit(¶ms, NULL); + r = vm->update_funcs->commit(¶ms, NULL); +exit: + drm_dev_exit(idx); + return r; } /** @@ -1384,11 +1390,14 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev, struct amdgpu_vm *vm, bool immediate) { struct amdgpu_vm_update_params params; - int r; + int r, idx; if (list_empty(&vm->relocated)) return 0; + if (!drm_dev_enter(&adev->ddev, &idx)) + return -ENODEV; + memset(¶ms, 0, sizeof(params)); params.adev = adev; params.vm = vm; @@ -1396,7 +1405,7 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev, r = vm->update_funcs->prepare(¶ms, NULL, AMDGPU_SYNC_EXPLICIT); if (r) - return r; + goto exit; while (!list_empty(&vm->relocated)) { struct amdgpu_vm_bo_base *entry; @@ -1414,10 +1423,13 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev, r = vm->update_funcs->commit(¶ms, &vm->last_update); if (r) goto error; + drm_dev_exit(idx); return 0; error: amdgpu_vm_invalidate_pds(adev, vm); +exit: + drm_dev_exit(idx); return r; } From 0a2267809fc96505aa91703640a121e84bcbdd81 Mon Sep 17 00:00:00 2001 From: xinhui pan Date: Thu, 16 Sep 2021 09:35:47 +0800 Subject: [PATCH 113/151] drm/amdgpu: Fix uvd ib test timeout when use pre-allocated BO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now we use same BO for create/destroy msg. So destroy will wait for the fence returned from create to be signaled. The default timeout value in destroy is 10ms which is too short. Lets wait both fences with the specific timeout. Signed-off-by: xinhui pan Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index b6e2abf26e183..8a26459bd80bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -1336,10 +1336,17 @@ int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, long timeout) struct dma_fence *fence; long r; - r = amdgpu_uvd_get_create_msg(ring, 1, NULL); + r = amdgpu_uvd_get_create_msg(ring, 1, &fence); if (r) goto error; + r = dma_fence_wait_timeout(fence, false, timeout); + dma_fence_put(fence); + if (r == 0) + r = -ETIMEDOUT; + if (r < 0) + goto error; + r = amdgpu_uvd_get_destroy_msg(ring, 1, true, &fence); if (r) goto error; From d82e2c249c8ffaec20fa618611ea2ab4dcfd4d01 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Wed, 15 Sep 2021 15:27:18 -0400 Subject: [PATCH 114/151] drm/amdgpu: Fix crash on device remove/driver unload Crash: BUG: unable to handle page fault for address: 00000000000010e1 RIP: 0010:vega10_power_gate_vce+0x26/0x50 [amdgpu] Call Trace: pp_set_powergating_by_smu+0x16a/0x2b0 [amdgpu] amdgpu_dpm_set_powergating_by_smu+0x92/0xf0 [amdgpu] amdgpu_dpm_enable_vce+0x2e/0xc0 [amdgpu] vce_v4_0_hw_fini+0x95/0xa0 [amdgpu] amdgpu_device_fini_hw+0x232/0x30d [amdgpu] amdgpu_driver_unload_kms+0x5c/0x80 [amdgpu] amdgpu_pci_remove+0x27/0x40 [amdgpu] pci_device_remove+0x3e/0xb0 device_release_driver_internal+0x103/0x1d0 device_release_driver+0x12/0x20 pci_stop_bus_device+0x79/0xa0 pci_stop_and_remove_bus_device_locked+0x1b/0x30 remove_store+0x7b/0x90 dev_attr_store+0x17/0x30 sysfs_kf_write+0x4b/0x60 kernfs_fop_write_iter+0x151/0x1e0 Why: VCE/UVD had dependency on SMC block for their suspend but SMC block is the first to do HW fini due to some constraints How: Since the original patch was dealing with suspend issues move the SMC block dependency back into suspend hooks as was done in V1 of the original patches. Keep flushing idle work both in suspend and HW fini seuqnces since it's essential in both cases. Fixes: 859e4659273f1d ("drm/amdgpu: add missing cleanups for more ASICs on UVD/VCE suspend") Fixes: bf756fb833cbe8 ("drm/amdgpu: add missing cleanups for Polaris12 UVD/VCE on suspend") Signed-off-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c | 24 ++++++++------- drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c | 24 ++++++++------- drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c | 24 ++++++++------- drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 32 ++++++++++--------- drivers/gpu/drm/amd/amdgpu/vce_v2_0.c | 19 +++++++----- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 28 +++++++++-------- drivers/gpu/drm/amd/amdgpu/vce_v4_0.c | 44 ++++++++++++++------------- 7 files changed, 105 insertions(+), 90 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c index 7232241e3bfb2..0fef925b66024 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c @@ -698,6 +698,19 @@ static int uvd_v3_1_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + cancel_delayed_work_sync(&adev->uvd.idle_work); + + if (RREG32(mmUVD_STATUS) != 0) + uvd_v3_1_stop(adev); + + return 0; +} + +static int uvd_v3_1_suspend(void *handle) +{ + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + /* * Proper cleanups before halting the HW engine: * - cancel the delayed idle work @@ -722,17 +735,6 @@ static int uvd_v3_1_hw_fini(void *handle) AMD_CG_STATE_GATE); } - if (RREG32(mmUVD_STATUS) != 0) - uvd_v3_1_stop(adev); - - return 0; -} - -static int uvd_v3_1_suspend(void *handle) -{ - int r; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = uvd_v3_1_hw_fini(adev); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c index 52d6de969f462..c108b83817951 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c @@ -212,6 +212,19 @@ static int uvd_v4_2_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + cancel_delayed_work_sync(&adev->uvd.idle_work); + + if (RREG32(mmUVD_STATUS) != 0) + uvd_v4_2_stop(adev); + + return 0; +} + +static int uvd_v4_2_suspend(void *handle) +{ + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + /* * Proper cleanups before halting the HW engine: * - cancel the delayed idle work @@ -236,17 +249,6 @@ static int uvd_v4_2_hw_fini(void *handle) AMD_CG_STATE_GATE); } - if (RREG32(mmUVD_STATUS) != 0) - uvd_v4_2_stop(adev); - - return 0; -} - -static int uvd_v4_2_suspend(void *handle) -{ - int r; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = uvd_v4_2_hw_fini(adev); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c index db6d06758e4d4..563493d1f8306 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c @@ -210,6 +210,19 @@ static int uvd_v5_0_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + cancel_delayed_work_sync(&adev->uvd.idle_work); + + if (RREG32(mmUVD_STATUS) != 0) + uvd_v5_0_stop(adev); + + return 0; +} + +static int uvd_v5_0_suspend(void *handle) +{ + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + /* * Proper cleanups before halting the HW engine: * - cancel the delayed idle work @@ -234,17 +247,6 @@ static int uvd_v5_0_hw_fini(void *handle) AMD_CG_STATE_GATE); } - if (RREG32(mmUVD_STATUS) != 0) - uvd_v5_0_stop(adev); - - return 0; -} - -static int uvd_v5_0_suspend(void *handle) -{ - int r; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = uvd_v5_0_hw_fini(adev); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index c115b2da22ef6..b483f03b4591b 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -597,6 +597,23 @@ static int uvd_v7_0_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + cancel_delayed_work_sync(&adev->uvd.idle_work); + + if (!amdgpu_sriov_vf(adev)) + uvd_v7_0_stop(adev); + else { + /* full access mode, so don't touch any UVD register */ + DRM_DEBUG("For SRIOV client, shouldn't do anything.\n"); + } + + return 0; +} + +static int uvd_v7_0_suspend(void *handle) +{ + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + /* * Proper cleanups before halting the HW engine: * - cancel the delayed idle work @@ -621,21 +638,6 @@ static int uvd_v7_0_hw_fini(void *handle) AMD_CG_STATE_GATE); } - if (!amdgpu_sriov_vf(adev)) - uvd_v7_0_stop(adev); - else { - /* full access mode, so don't touch any UVD register */ - DRM_DEBUG("For SRIOV client, shouldn't do anything.\n"); - } - - return 0; -} - -static int uvd_v7_0_suspend(void *handle) -{ - int r; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = uvd_v7_0_hw_fini(adev); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index 84e488f189f5f..67eb01fef789b 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -481,6 +481,17 @@ static int vce_v2_0_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + cancel_delayed_work_sync(&adev->vce.idle_work); + + return 0; +} + +static int vce_v2_0_suspend(void *handle) +{ + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + /* * Proper cleanups before halting the HW engine: * - cancel the delayed idle work @@ -504,14 +515,6 @@ static int vce_v2_0_hw_fini(void *handle) AMD_CG_STATE_GATE); } - return 0; -} - -static int vce_v2_0_suspend(void *handle) -{ - int r; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = vce_v2_0_hw_fini(adev); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 2a18c1e089fdd..142e291983b45 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -492,6 +492,21 @@ static int vce_v3_0_hw_fini(void *handle) int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; + cancel_delayed_work_sync(&adev->vce.idle_work); + + r = vce_v3_0_wait_for_idle(handle); + if (r) + return r; + + vce_v3_0_stop(adev); + return vce_v3_0_set_clockgating_state(adev, AMD_CG_STATE_GATE); +} + +static int vce_v3_0_suspend(void *handle) +{ + int r; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + /* * Proper cleanups before halting the HW engine: * - cancel the delayed idle work @@ -515,19 +530,6 @@ static int vce_v3_0_hw_fini(void *handle) AMD_CG_STATE_GATE); } - r = vce_v3_0_wait_for_idle(handle); - if (r) - return r; - - vce_v3_0_stop(adev); - return vce_v3_0_set_clockgating_state(adev, AMD_CG_STATE_GATE); -} - -static int vce_v3_0_suspend(void *handle) -{ - int r; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = vce_v3_0_hw_fini(adev); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c index 044cf9d74b85e..226b79254db85 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v4_0.c @@ -544,29 +544,8 @@ static int vce_v4_0_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - /* - * Proper cleanups before halting the HW engine: - * - cancel the delayed idle work - * - enable powergating - * - enable clockgating - * - disable dpm - * - * TODO: to align with the VCN implementation, move the - * jobs for clockgating/powergating/dpm setting to - * ->set_powergating_state(). - */ cancel_delayed_work_sync(&adev->vce.idle_work); - if (adev->pm.dpm_enabled) { - amdgpu_dpm_enable_vce(adev, false); - } else { - amdgpu_asic_set_vce_clocks(adev, 0, 0); - amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_GATE); - amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, - AMD_CG_STATE_GATE); - } - if (!amdgpu_sriov_vf(adev)) { /* vce_v4_0_wait_for_idle(handle); */ vce_v4_0_stop(adev); @@ -596,6 +575,29 @@ static int vce_v4_0_suspend(void *handle) drm_dev_exit(idx); } + /* + * Proper cleanups before halting the HW engine: + * - cancel the delayed idle work + * - enable powergating + * - enable clockgating + * - disable dpm + * + * TODO: to align with the VCN implementation, move the + * jobs for clockgating/powergating/dpm setting to + * ->set_powergating_state(). + */ + cancel_delayed_work_sync(&adev->vce.idle_work); + + if (adev->pm.dpm_enabled) { + amdgpu_dpm_enable_vce(adev, false); + } else { + amdgpu_asic_set_vce_clocks(adev, 0, 0); + amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_GATE); + amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, + AMD_CG_STATE_GATE); + } + r = vce_v4_0_hw_fini(adev); if (r) return r; From c03509cbc01559549700e14c4a6239f2572ab4ba Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Thu, 16 Sep 2021 12:54:07 -0400 Subject: [PATCH 115/151] drm/amdgpu: Fix MMIO access page fault Add more guards to MMIO access post device unbind/unplug Bug: https://bugs.archlinux.org/task/72092?project=1&order=dateopened&sort=desc&pagenum=1 Signed-off-by: Andrey Grodzovsky Reviewed-by: James Zhu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 8 ++++++-- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 17 +++++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index e6e9ef50719e5..a03c0fc8338ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -22,6 +22,7 @@ */ #include +#include #include "amdgpu.h" #include "amdgpu_vcn.h" @@ -194,11 +195,14 @@ static int vcn_v2_0_sw_init(void *handle) */ static int vcn_v2_0_sw_fini(void *handle) { - int r; + int r, idx; struct amdgpu_device *adev = (struct amdgpu_device *)handle; volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst->fw_shared_cpu_addr; - fw_shared->present_flag_0 = 0; + if (drm_dev_enter(&adev->ddev, &idx)) { + fw_shared->present_flag_0 = 0; + drm_dev_exit(idx); + } amdgpu_virt_free_mm_table(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 2e6b7913bf6c9..1780ad1eacd67 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -22,6 +22,7 @@ */ #include +#include #include "amdgpu.h" #include "amdgpu_vcn.h" @@ -235,17 +236,21 @@ static int vcn_v2_5_sw_init(void *handle) */ static int vcn_v2_5_sw_fini(void *handle) { - int i, r; + int i, r, idx; struct amdgpu_device *adev = (struct amdgpu_device *)handle; volatile struct amdgpu_fw_shared *fw_shared; - for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - if (adev->vcn.harvest_config & (1 << i)) - continue; - fw_shared = adev->vcn.inst[i].fw_shared_cpu_addr; - fw_shared->present_flag_0 = 0; + if (drm_dev_enter(&adev->ddev, &idx)) { + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + if (adev->vcn.harvest_config & (1 << i)) + continue; + fw_shared = adev->vcn.inst[i].fw_shared_cpu_addr; + fw_shared->present_flag_0 = 0; + } + drm_dev_exit(idx); } + if (amdgpu_sriov_vf(adev)) amdgpu_virt_free_mm_table(adev); From ebe86a57c882871a927986ee6514cb171483d074 Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Fri, 17 Sep 2021 07:18:29 -0400 Subject: [PATCH 116/151] drm/amdgpu: Fix resume failures when device is gone Problem: When device goes into suspend and unplugged during it then all HW programming during resume fails leading to a bad SW during pci remove handling which follows. Because device is first resumed and only later removed we cannot rely on drm_dev_enter/exit here. Fix: Use a flag we use for PCIe error recovery to avoid accessing registres. This allows to successfully complete pm resume sequence and finish pci remove. Signed-off-by: Andrey Grodzovsky Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index f18240f873878..15b27bcf52730 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1508,6 +1508,10 @@ static int amdgpu_pmops_resume(struct device *dev) struct amdgpu_device *adev = drm_to_adev(drm_dev); int r; + /* Avoids registers access if device is physically gone */ + if (!pci_device_is_present(adev->pdev)) + adev->no_hw_access = true; + r = amdgpu_device_resume(drm_dev, true); if (amdgpu_acpi_is_s0ix_active(adev)) adev->in_s0ix = false; From 7ac805321fc174216f61cf98c61f70c22e9a6cd6 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 20 Sep 2021 14:16:00 +0200 Subject: [PATCH 117/151] drm/amd/display: fix empty debug macros Using an empty macro expansion as a conditional expression produces a W=1 warning: drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_aux.c: In function 'dce_aux_transfer_with_retries': drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_aux.c:775:156: error: suggest braces around empty body in an 'if' statement [-Werror=empty-body] 775 | "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER"); | ^ drivers/gpu/drm/amd/amdgpu/../display/dc/dce/dce_aux.c:783:155: error: suggest braces around empty body in an 'if' statement [-Werror=empty-body] 783 | "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK"); | ^ Expand it to "do { } while (0)" instead to make the expression more robust and avoid the warning. Fixes: 56aca2309301 ("drm/amd/display: Add AUX I2C tracing.") Signed-off-by: Arnd Bergmann Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index 4a3b94fa3e401..5666543f095bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c @@ -42,7 +42,7 @@ #define DC_LOGGER \ engine->ctx->logger -#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ +#define DC_TRACE_LEVEL_MESSAGE(...) do { } while (0) #define IS_DC_I2CAUX_LOGGING_ENABLED() (false) #define LOG_FLAG_Error_I2cAux LOG_ERROR #define LOG_FLAG_I2cAux_DceAux LOG_I2C_AUX @@ -76,7 +76,7 @@ enum { #define DEFAULT_AUX_ENGINE_MULT 0 #define DEFAULT_AUX_ENGINE_LENGTH 69 -#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ +#define DC_TRACE_LEVEL_MESSAGE(...) do { } while (0) static void release_engine( struct dce_aux *engine) From 5ff560cb72ccc5615faded9a98b327264131583b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 17 Sep 2021 12:05:30 -0400 Subject: [PATCH 118/151] MAINTAINERS: fix up entry for AMD Powerplay Fix the path to cover both the older powerplay infrastructure and the newer SwSMU infrastructure. Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 851255b71cccd..379092f34fffa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -972,12 +972,12 @@ L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/amd-pmc.* -AMD POWERPLAY +AMD POWERPLAY AND SWSMU M: Evan Quan L: amd-gfx@lists.freedesktop.org S: Supported T: git https://gitlab.freedesktop.org/agd5f/linux.git -F: drivers/gpu/drm/amd/pm/powerplay/ +F: drivers/gpu/drm/amd/pm/ AMD SEATTLE DEVICE TREE SUPPORT M: Brijesh Singh From 1aed482819524b10923ef5171caea47e23bbf014 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Mon, 13 Sep 2021 10:03:36 -0400 Subject: [PATCH 119/151] drm/amdkfd: SVM map to gpus check vma boundary SVM range may includes multiple VMAs with different vm_flags, if prange page index is the last page of the VMA offset + npages, update GPU mapping to create GPU page table with same VMA access permission. Signed-off-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 9fc8021bb0ab2..432d5aae09623 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -1178,7 +1178,11 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm, for (i = offset; i < offset + npages; i++) { last_domain = dma_addr[i] & SVM_RANGE_VRAM_DOMAIN; dma_addr[i] &= ~SVM_RANGE_VRAM_DOMAIN; - if ((prange->start + i) < prange->last && + + /* Collect all pages in the same address range and memory domain + * that can be mapped with a single call to update mapping. + */ + if (i < offset + npages - 1 && last_domain == (dma_addr[i + 1] & SVM_RANGE_VRAM_DOMAIN)) continue; From e7eb2137e84adc7c6594463fbb41b9962d311f16 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Tue, 14 Sep 2021 16:33:40 -0400 Subject: [PATCH 120/151] drm/amdkfd: fix dma mapping leaking warning For xnack off, restore work dma unmap previous system memory page, and dma map the updated system memory page to update GPU mapping, this is not dma mapping leaking, remove the WARN_ONCE for dma mapping leaking. prange->dma_addr store the VRAM page pfn after the range migrated to VRAM, should not dma unmap VRAM page when updating GPU mapping or remove prange. Add helper svm_is_valid_dma_mapping_addr to check VRAM page and error cases. Mask out SVM_RANGE_VRAM_DOMAIN flag in dma_addr before calling amdgpu vm update to avoid BUG_ON(*addr & 0xFFFF00000000003FULL), and set it again immediately after. This flag is used to know the type of page later to dma unmapping system memory page. Fixes: 1d5dbfe6c06a ("drm/amdkfd: classify and map mixed svm range pages in GPU") Signed-off-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 432d5aae09623..9d0f65a90002d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -118,6 +118,13 @@ static void svm_range_remove_notifier(struct svm_range *prange) mmu_interval_notifier_remove(&prange->notifier); } +static bool +svm_is_valid_dma_mapping_addr(struct device *dev, dma_addr_t dma_addr) +{ + return dma_addr && !dma_mapping_error(dev, dma_addr) && + !(dma_addr & SVM_RANGE_VRAM_DOMAIN); +} + static int svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange, unsigned long offset, unsigned long npages, @@ -139,8 +146,7 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange, addr += offset; for (i = 0; i < npages; i++) { - if (WARN_ONCE(addr[i] && !dma_mapping_error(dev, addr[i]), - "leaking dma mapping\n")) + if (svm_is_valid_dma_mapping_addr(dev, addr[i])) dma_unmap_page(dev, addr[i], PAGE_SIZE, dir); page = hmm_pfn_to_page(hmm_pfns[i]); @@ -209,7 +215,7 @@ void svm_range_dma_unmap(struct device *dev, dma_addr_t *dma_addr, return; for (i = offset; i < offset + npages; i++) { - if (!dma_addr[i] || dma_mapping_error(dev, dma_addr[i])) + if (!svm_is_valid_dma_mapping_addr(dev, dma_addr[i])) continue; pr_debug("dma unmapping 0x%llx\n", dma_addr[i] >> PAGE_SHIFT); dma_unmap_page(dev, dma_addr[i], PAGE_SIZE, dir); @@ -1165,7 +1171,7 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm, unsigned long last_start; int last_domain; int r = 0; - int64_t i; + int64_t i, j; last_start = prange->start + offset; @@ -1205,6 +1211,10 @@ svm_range_map_to_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm, NULL, dma_addr, &vm->last_update, &table_freed); + + for (j = last_start - prange->start; j <= i; j++) + dma_addr[j] |= last_domain; + if (r) { pr_debug("failed %d to map to gpu 0x%lx\n", r, prange->start); goto out; From 22667e6ec6b2ce9ca706e9061660b059725d009c Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 7 Sep 2021 19:40:06 -0400 Subject: [PATCH 121/151] drm/amd/display: Pass display_pipe_params_st as const in DML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Why] This neither needs to be on the stack nor passed by value to each function call. In fact, when building with clang it seems to break the Linux's default 1024 byte stack frame limit. [How] We can simply pass this as a const pointer. This patch fixes these Coverity IDs Addresses-Coverity-ID: 1424031: ("Big parameter passed by value") Addresses-Coverity-ID: 1423970: ("Big parameter passed by value") Addresses-Coverity-ID: 1423941: ("Big parameter passed by value") Addresses-Coverity-ID: 1451742: ("Big parameter passed by value") Addresses-Coverity-ID: 1451887: ("Big parameter passed by value") Addresses-Coverity-ID: 1454146: ("Big parameter passed by value") Addresses-Coverity-ID: 1454152: ("Big parameter passed by value") Addresses-Coverity-ID: 1454413: ("Big parameter passed by value") Addresses-Coverity-ID: 1466144: ("Big parameter passed by value") Addresses-Coverity-ID: 1487237: ("Big parameter passed by value") Signed-off-by: Harry Wentland Fixes: 3fe617ccafd6 ("Enable '-Werror' by default for all kernel builds") Cc: Nick Desaulniers Cc: Linus Torvalds Cc: amd-gfx@lists.freedesktop.org Cc: Linux Kernel Mailing List Cc: Arnd Bergmann Cc: Leo Li Cc: Alex Deucher Cc: Christian König Cc: Xinhui Pan Cc: Nathan Chancellor Cc: Guenter Roeck Cc: llvm@lists.linux.dev Acked-by: Christian König Build-tested-by: Nathan Chancellor Reviewed-by: Leo Li Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/dcn20/dcn20_resource.c | 2 +- .../dc/dml/dcn20/display_rq_dlg_calc_20.c | 6 +- .../dc/dml/dcn20/display_rq_dlg_calc_20.h | 4 +- .../dc/dml/dcn20/display_rq_dlg_calc_20v2.c | 6 +- .../dc/dml/dcn20/display_rq_dlg_calc_20v2.h | 4 +- .../dc/dml/dcn21/display_rq_dlg_calc_21.c | 62 ++++++++-------- .../dc/dml/dcn21/display_rq_dlg_calc_21.h | 4 +- .../dc/dml/dcn30/display_rq_dlg_calc_30.c | 72 +++++++++---------- .../dc/dml/dcn30/display_rq_dlg_calc_30.h | 4 +- .../dc/dml/dcn31/display_rq_dlg_calc_31.c | 68 +++++++++--------- .../dc/dml/dcn31/display_rq_dlg_calc_31.h | 4 +- .../drm/amd/display/dc/dml/display_mode_lib.h | 4 +- 12 files changed, 120 insertions(+), 120 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index e69f553d680f5..1872c456e2c9d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -3176,7 +3176,7 @@ void dcn20_calculate_dlg_params( context->bw_ctx.dml.funcs.rq_dlg_get_rq_reg(&context->bw_ctx.dml, &context->res_ctx.pipe_ctx[i].rq_regs, - pipes[pipe_idx].pipe); + &pipes[pipe_idx].pipe); pipe_idx++; } } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c index 2091dd8c252da..8c168f348a27f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c @@ -768,12 +768,12 @@ static void dml20_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, void dml20_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, - const display_pipe_params_st pipe_param) + const display_pipe_params_st *pipe_param) { display_rq_params_st rq_param = {0}; memset(rq_regs, 0, sizeof(*rq_regs)); - dml20_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param.src); + dml20_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param->src); extract_rq_regs(mode_lib, rq_regs, rq_param); print__rq_regs_st(mode_lib, *rq_regs); @@ -1549,7 +1549,7 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, void dml20_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 display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h index d0b90947f5409..8b23867e97c18 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.h @@ -43,7 +43,7 @@ struct display_mode_lib; void dml20_rq_dlg_get_rq_reg( struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, - const display_pipe_params_st pipe_param); + const display_pipe_params_st *pipe_param); // Function: dml_rq_dlg_get_dlg_reg @@ -61,7 +61,7 @@ void dml20_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 display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c index 1a0c14e465faa..26ececfd40cdc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c @@ -768,12 +768,12 @@ static void dml20v2_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, 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) + const display_pipe_params_st *pipe_param) { display_rq_params_st rq_param = {0}; memset(rq_regs, 0, sizeof(*rq_regs)); - dml20v2_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param.src); + dml20v2_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param->src); extract_rq_regs(mode_lib, rq_regs, rq_param); print__rq_regs_st(mode_lib, *rq_regs); @@ -1550,7 +1550,7 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, 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 display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h index 27cf8bed9376f..2b4e46ea1c3df 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.h @@ -43,7 +43,7 @@ struct display_mode_lib; 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); + const display_pipe_params_st *pipe_param); // Function: dml_rq_dlg_get_dlg_reg @@ -61,7 +61,7 @@ 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 display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c index 287e31052b307..736978c4d40a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c @@ -694,7 +694,7 @@ static void get_surf_rq_param( display_data_rq_sizing_params_st *rq_sizing_param, display_data_rq_dlg_params_st *rq_dlg_param, display_data_rq_misc_params_st *rq_misc_param, - const display_pipe_params_st pipe_param, + const display_pipe_params_st *pipe_param, bool is_chroma) { bool mode_422 = false; @@ -706,30 +706,30 @@ static void get_surf_rq_param( // FIXME check if ppe apply for both luma and chroma in 422 case if (is_chroma) { - vp_width = pipe_param.src.viewport_width_c / ppe; - vp_height = pipe_param.src.viewport_height_c; - data_pitch = pipe_param.src.data_pitch_c; - meta_pitch = pipe_param.src.meta_pitch_c; + vp_width = pipe_param->src.viewport_width_c / ppe; + vp_height = pipe_param->src.viewport_height_c; + data_pitch = pipe_param->src.data_pitch_c; + meta_pitch = pipe_param->src.meta_pitch_c; } else { - vp_width = pipe_param.src.viewport_width / ppe; - vp_height = pipe_param.src.viewport_height; - data_pitch = pipe_param.src.data_pitch; - meta_pitch = pipe_param.src.meta_pitch; + vp_width = pipe_param->src.viewport_width / ppe; + vp_height = pipe_param->src.viewport_height; + data_pitch = pipe_param->src.data_pitch; + meta_pitch = pipe_param->src.meta_pitch; } - if (pipe_param.dest.odm_combine) { + if (pipe_param->dest.odm_combine) { unsigned int access_dir; unsigned int full_src_vp_width; unsigned int hactive_half; unsigned int src_hactive_half; - access_dir = (pipe_param.src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed - hactive_half = pipe_param.dest.hactive / 2; + access_dir = (pipe_param->src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed + hactive_half = pipe_param->dest.hactive / 2; if (is_chroma) { - full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio_c * pipe_param.dest.full_recout_width; - src_hactive_half = pipe_param.scale_ratio_depth.hscl_ratio_c * hactive_half; + full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio_c * pipe_param->dest.full_recout_width; + src_hactive_half = pipe_param->scale_ratio_depth.hscl_ratio_c * hactive_half; } else { - full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio * pipe_param.dest.full_recout_width; - src_hactive_half = pipe_param.scale_ratio_depth.hscl_ratio * hactive_half; + full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio * pipe_param->dest.full_recout_width; + src_hactive_half = pipe_param->scale_ratio_depth.hscl_ratio * hactive_half; } if (access_dir == 0) { @@ -754,7 +754,7 @@ static void get_surf_rq_param( rq_sizing_param->meta_chunk_bytes = 2048; rq_sizing_param->min_meta_chunk_bytes = 256; - if (pipe_param.src.hostvm) + if (pipe_param->src.hostvm) rq_sizing_param->mpte_group_bytes = 512; else rq_sizing_param->mpte_group_bytes = 2048; @@ -768,23 +768,23 @@ static void get_surf_rq_param( vp_height, data_pitch, meta_pitch, - pipe_param.src.source_format, - pipe_param.src.sw_mode, - pipe_param.src.macro_tile_size, - pipe_param.src.source_scan, - pipe_param.src.hostvm, + pipe_param->src.source_format, + pipe_param->src.sw_mode, + pipe_param->src.macro_tile_size, + pipe_param->src.source_scan, + pipe_param->src.hostvm, is_chroma); } static void dml_rq_dlg_get_rq_params( struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, - const display_pipe_params_st pipe_param) + const display_pipe_params_st *pipe_param) { // get param for luma surface - rq_param->yuv420 = pipe_param.src.source_format == dm_420_8 - || pipe_param.src.source_format == dm_420_10; - rq_param->yuv420_10bpc = pipe_param.src.source_format == dm_420_10; + rq_param->yuv420 = pipe_param->src.source_format == dm_420_8 + || pipe_param->src.source_format == dm_420_10; + rq_param->yuv420_10bpc = pipe_param->src.source_format == dm_420_10; get_surf_rq_param( mode_lib, @@ -794,7 +794,7 @@ static void dml_rq_dlg_get_rq_params( pipe_param, 0); - if (is_dual_plane((enum source_format_class) (pipe_param.src.source_format))) { + if (is_dual_plane((enum source_format_class) (pipe_param->src.source_format))) { // get param for chroma surface get_surf_rq_param( mode_lib, @@ -806,14 +806,14 @@ static void dml_rq_dlg_get_rq_params( } // calculate how to split the det buffer space between luma and chroma - handle_det_buf_split(mode_lib, rq_param, pipe_param.src); + handle_det_buf_split(mode_lib, rq_param, pipe_param->src); print__rq_params_st(mode_lib, *rq_param); } void dml21_rq_dlg_get_rq_reg( struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, - const display_pipe_params_st pipe_param) + const display_pipe_params_st *pipe_param) { display_rq_params_st rq_param = {0}; @@ -1658,7 +1658,7 @@ void dml21_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 display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, @@ -1696,7 +1696,7 @@ void dml21_rq_dlg_get_dlg_reg( // system parameter calculation done dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); - dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe); + dml_rq_dlg_get_rq_params(mode_lib, &rq_param, &e2e_pipe_param[pipe_idx].pipe); dml_rq_dlg_get_dlg_params( mode_lib, e2e_pipe_param, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.h b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.h index e8f7785e3fc63..af6ad0ca9cf8a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.h @@ -44,7 +44,7 @@ struct display_mode_lib; void dml21_rq_dlg_get_rq_reg( struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, - const display_pipe_params_st pipe_param); + 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 @@ -61,7 +61,7 @@ void dml21_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 display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c index 0d934fae1c3a6..2120e0941a095 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c @@ -747,7 +747,7 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, display_data_rq_sizing_params_st *rq_sizing_param, display_data_rq_dlg_params_st *rq_dlg_param, display_data_rq_misc_params_st *rq_misc_param, - const display_pipe_params_st pipe_param, + const display_pipe_params_st *pipe_param, bool is_chroma, bool is_alpha) { @@ -761,32 +761,32 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, // FIXME check if ppe apply for both luma and chroma in 422 case if (is_chroma | is_alpha) { - vp_width = pipe_param.src.viewport_width_c / ppe; - vp_height = pipe_param.src.viewport_height_c; - data_pitch = pipe_param.src.data_pitch_c; - meta_pitch = pipe_param.src.meta_pitch_c; - surface_height = pipe_param.src.surface_height_y / 2.0; + vp_width = pipe_param->src.viewport_width_c / ppe; + vp_height = pipe_param->src.viewport_height_c; + data_pitch = pipe_param->src.data_pitch_c; + meta_pitch = pipe_param->src.meta_pitch_c; + surface_height = pipe_param->src.surface_height_y / 2.0; } else { - vp_width = pipe_param.src.viewport_width / ppe; - vp_height = pipe_param.src.viewport_height; - data_pitch = pipe_param.src.data_pitch; - meta_pitch = pipe_param.src.meta_pitch; - surface_height = pipe_param.src.surface_height_y; + vp_width = pipe_param->src.viewport_width / ppe; + vp_height = pipe_param->src.viewport_height; + data_pitch = pipe_param->src.data_pitch; + meta_pitch = pipe_param->src.meta_pitch; + surface_height = pipe_param->src.surface_height_y; } - if (pipe_param.dest.odm_combine) { + if (pipe_param->dest.odm_combine) { unsigned int access_dir = 0; unsigned int full_src_vp_width = 0; unsigned int hactive_odm = 0; unsigned int src_hactive_odm = 0; - access_dir = (pipe_param.src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed - hactive_odm = pipe_param.dest.hactive / ((unsigned int)pipe_param.dest.odm_combine*2); + access_dir = (pipe_param->src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed + hactive_odm = pipe_param->dest.hactive / ((unsigned int) pipe_param->dest.odm_combine*2); if (is_chroma) { - full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio_c * pipe_param.dest.full_recout_width; - src_hactive_odm = pipe_param.scale_ratio_depth.hscl_ratio_c * hactive_odm; + full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio_c * pipe_param->dest.full_recout_width; + src_hactive_odm = pipe_param->scale_ratio_depth.hscl_ratio_c * hactive_odm; } else { - full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio * pipe_param.dest.full_recout_width; - src_hactive_odm = pipe_param.scale_ratio_depth.hscl_ratio * hactive_odm; + full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio * pipe_param->dest.full_recout_width; + src_hactive_odm = pipe_param->scale_ratio_depth.hscl_ratio * hactive_odm; } if (access_dir == 0) { @@ -815,7 +815,7 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, rq_sizing_param->meta_chunk_bytes = 2048; rq_sizing_param->min_meta_chunk_bytes = 256; - if (pipe_param.src.hostvm) + if (pipe_param->src.hostvm) rq_sizing_param->mpte_group_bytes = 512; else rq_sizing_param->mpte_group_bytes = 2048; @@ -828,28 +828,28 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, vp_height, data_pitch, meta_pitch, - pipe_param.src.source_format, - pipe_param.src.sw_mode, - pipe_param.src.macro_tile_size, - pipe_param.src.source_scan, - pipe_param.src.hostvm, + pipe_param->src.source_format, + pipe_param->src.sw_mode, + pipe_param->src.macro_tile_size, + pipe_param->src.source_scan, + pipe_param->src.hostvm, is_chroma, surface_height); } static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, - const display_pipe_params_st pipe_param) + const display_pipe_params_st *pipe_param) { // get param for luma surface - rq_param->yuv420 = pipe_param.src.source_format == dm_420_8 - || pipe_param.src.source_format == dm_420_10 - || pipe_param.src.source_format == dm_rgbe_alpha - || pipe_param.src.source_format == dm_420_12; + rq_param->yuv420 = pipe_param->src.source_format == dm_420_8 + || pipe_param->src.source_format == dm_420_10 + || pipe_param->src.source_format == dm_rgbe_alpha + || pipe_param->src.source_format == dm_420_12; - rq_param->yuv420_10bpc = pipe_param.src.source_format == dm_420_10; + rq_param->yuv420_10bpc = pipe_param->src.source_format == dm_420_10; - rq_param->rgbe_alpha = (pipe_param.src.source_format == dm_rgbe_alpha)?1:0; + rq_param->rgbe_alpha = (pipe_param->src.source_format == dm_rgbe_alpha)?1:0; get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_l), @@ -859,7 +859,7 @@ static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, 0, 0); - if (is_dual_plane((enum source_format_class)(pipe_param.src.source_format))) { + if (is_dual_plane((enum source_format_class)(pipe_param->src.source_format))) { // get param for chroma surface get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_c), @@ -871,13 +871,13 @@ static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, } // calculate how to split the det buffer space between luma and chroma - handle_det_buf_split(mode_lib, rq_param, pipe_param.src); + handle_det_buf_split(mode_lib, rq_param, pipe_param->src); print__rq_params_st(mode_lib, *rq_param); } void dml30_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, - const display_pipe_params_st pipe_param) + const display_pipe_params_st *pipe_param) { display_rq_params_st rq_param = { 0 }; @@ -1831,7 +1831,7 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, void dml30_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 display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, @@ -1866,7 +1866,7 @@ void dml30_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, // system parameter calculation done dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); - dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe); + dml_rq_dlg_get_rq_params(mode_lib, &rq_param, &e2e_pipe_param[pipe_idx].pipe); dml_rq_dlg_get_dlg_params(mode_lib, e2e_pipe_param, num_pipes, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h index c04965cceff35..625e41f8d5751 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.h @@ -41,7 +41,7 @@ struct display_mode_lib; // See also: void dml30_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, - const display_pipe_params_st pipe_param); + 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 @@ -57,7 +57,7 @@ void dml30_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, void dml30_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 display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c index c23905bc733ae..57bd4e3f8a823 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c @@ -738,7 +738,7 @@ static void get_surf_rq_param( display_data_rq_sizing_params_st *rq_sizing_param, display_data_rq_dlg_params_st *rq_dlg_param, display_data_rq_misc_params_st *rq_misc_param, - const display_pipe_params_st pipe_param, + const display_pipe_params_st *pipe_param, bool is_chroma, bool is_alpha) { @@ -752,33 +752,33 @@ static void get_surf_rq_param( // FIXME check if ppe apply for both luma and chroma in 422 case if (is_chroma | is_alpha) { - vp_width = pipe_param.src.viewport_width_c / ppe; - vp_height = pipe_param.src.viewport_height_c; - data_pitch = pipe_param.src.data_pitch_c; - meta_pitch = pipe_param.src.meta_pitch_c; - surface_height = pipe_param.src.surface_height_y / 2.0; + vp_width = pipe_param->src.viewport_width_c / ppe; + vp_height = pipe_param->src.viewport_height_c; + data_pitch = pipe_param->src.data_pitch_c; + meta_pitch = pipe_param->src.meta_pitch_c; + surface_height = pipe_param->src.surface_height_y / 2.0; } else { - vp_width = pipe_param.src.viewport_width / ppe; - vp_height = pipe_param.src.viewport_height; - data_pitch = pipe_param.src.data_pitch; - meta_pitch = pipe_param.src.meta_pitch; - surface_height = pipe_param.src.surface_height_y; + vp_width = pipe_param->src.viewport_width / ppe; + vp_height = pipe_param->src.viewport_height; + data_pitch = pipe_param->src.data_pitch; + meta_pitch = pipe_param->src.meta_pitch; + surface_height = pipe_param->src.surface_height_y; } - if (pipe_param.dest.odm_combine) { + if (pipe_param->dest.odm_combine) { unsigned int access_dir; unsigned int full_src_vp_width; unsigned int hactive_odm; unsigned int src_hactive_odm; - access_dir = (pipe_param.src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed - hactive_odm = pipe_param.dest.hactive / ((unsigned int) pipe_param.dest.odm_combine * 2); + access_dir = (pipe_param->src.source_scan == dm_vert); // vp access direction: horizontal or vertical accessed + hactive_odm = pipe_param->dest.hactive / ((unsigned int) pipe_param->dest.odm_combine * 2); if (is_chroma) { - full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio_c * pipe_param.dest.full_recout_width; - src_hactive_odm = pipe_param.scale_ratio_depth.hscl_ratio_c * hactive_odm; + full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio_c * pipe_param->dest.full_recout_width; + src_hactive_odm = pipe_param->scale_ratio_depth.hscl_ratio_c * hactive_odm; } else { - full_src_vp_width = pipe_param.scale_ratio_depth.hscl_ratio * pipe_param.dest.full_recout_width; - src_hactive_odm = pipe_param.scale_ratio_depth.hscl_ratio * hactive_odm; + full_src_vp_width = pipe_param->scale_ratio_depth.hscl_ratio * pipe_param->dest.full_recout_width; + src_hactive_odm = pipe_param->scale_ratio_depth.hscl_ratio * hactive_odm; } if (access_dir == 0) { @@ -808,7 +808,7 @@ static void get_surf_rq_param( rq_sizing_param->meta_chunk_bytes = 2048; rq_sizing_param->min_meta_chunk_bytes = 256; - if (pipe_param.src.hostvm) + if (pipe_param->src.hostvm) rq_sizing_param->mpte_group_bytes = 512; else rq_sizing_param->mpte_group_bytes = 2048; @@ -822,38 +822,38 @@ static void get_surf_rq_param( vp_height, data_pitch, meta_pitch, - pipe_param.src.source_format, - pipe_param.src.sw_mode, - pipe_param.src.macro_tile_size, - pipe_param.src.source_scan, - pipe_param.src.hostvm, + pipe_param->src.source_format, + pipe_param->src.sw_mode, + pipe_param->src.macro_tile_size, + pipe_param->src.source_scan, + pipe_param->src.hostvm, is_chroma, surface_height); } -static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, const display_pipe_params_st pipe_param) +static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, const display_pipe_params_st *pipe_param) { // get param for luma surface - rq_param->yuv420 = pipe_param.src.source_format == dm_420_8 || pipe_param.src.source_format == dm_420_10 || pipe_param.src.source_format == dm_rgbe_alpha - || pipe_param.src.source_format == dm_420_12; + rq_param->yuv420 = pipe_param->src.source_format == dm_420_8 || pipe_param->src.source_format == dm_420_10 || pipe_param->src.source_format == dm_rgbe_alpha + || pipe_param->src.source_format == dm_420_12; - rq_param->yuv420_10bpc = pipe_param.src.source_format == dm_420_10; + rq_param->yuv420_10bpc = pipe_param->src.source_format == dm_420_10; - rq_param->rgbe_alpha = (pipe_param.src.source_format == dm_rgbe_alpha) ? 1 : 0; + rq_param->rgbe_alpha = (pipe_param->src.source_format == dm_rgbe_alpha) ? 1 : 0; get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_l), &(rq_param->dlg.rq_l), &(rq_param->misc.rq_l), pipe_param, 0, 0); - if (is_dual_plane((enum source_format_class) (pipe_param.src.source_format))) { + if (is_dual_plane((enum source_format_class) (pipe_param->src.source_format))) { // get param for chroma surface get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_c), &(rq_param->dlg.rq_c), &(rq_param->misc.rq_c), pipe_param, 1, rq_param->rgbe_alpha); } // calculate how to split the det buffer space between luma and chroma - handle_det_buf_split(mode_lib, rq_param, pipe_param.src); + handle_det_buf_split(mode_lib, rq_param, pipe_param->src); print__rq_params_st(mode_lib, *rq_param); } -void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, const display_pipe_params_st pipe_param) +void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, const display_pipe_params_st *pipe_param) { display_rq_params_st rq_param = {0}; @@ -1677,7 +1677,7 @@ void dml31_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 display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, @@ -1704,7 +1704,7 @@ void dml31_rq_dlg_get_dlg_reg( // system parameter calculation done dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); - dml_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe); + dml_rq_dlg_get_rq_params(mode_lib, &rq_param, &e2e_pipe_param[pipe_idx].pipe); dml_rq_dlg_get_dlg_params( mode_lib, e2e_pipe_param, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.h b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.h index adf8518f761f9..8ee991351699d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.h @@ -41,7 +41,7 @@ struct display_mode_lib; // See also: void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, - const display_pipe_params_st pipe_param); + 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 @@ -57,7 +57,7 @@ void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, void dml31_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 display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h index d42a0aeca6be2..72b1957022aa2 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.h @@ -49,7 +49,7 @@ struct dml_funcs { 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 display_e2e_pipe_params_st *e2e_pipe_param, const unsigned int num_pipes, const unsigned int pipe_idx, const bool cstate_en, @@ -60,7 +60,7 @@ struct dml_funcs { void (*rq_dlg_get_rq_reg)( struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, - const display_pipe_params_st pipe_param); + const display_pipe_params_st *pipe_param); void (*recalculate)(struct display_mode_lib *mode_lib); void (*validate)(struct display_mode_lib *mode_lib); }; From 4768349e8885a171a279ff26af218b48b8cdddf0 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 8 Sep 2021 10:21:37 -0400 Subject: [PATCH 122/151] drm/amd/display: Pass all structs in display_rq_dlg_helpers by pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Passing structs adds a lot of overhead. We don't ever want to pass anything bigger than primitives by value. This patch fixes these Coverity IDs: Addresses-Coverity-ID: 1423868: ("Big parameter passed by value") Addresses-Coverity-ID: 1423870: ("Big parameter passed by value") Signed-off-by: Harry Wentland Cc: Nick Desaulniers Cc: Linus Torvalds Cc: amd-gfx@lists.freedesktop.org Cc: Linux Kernel Mailing List Cc: Arnd Bergmann Cc: Leo Li Cc: Alex Deucher Cc: Christian König Cc: Xinhui Pan Cc: Nathan Chancellor Cc: Guenter Roeck Cc: llvm@lists.linux.dev Acked-by: Christian König Build-tested-by: Nathan Chancellor Reviewed-by: Leo Li Signed-off-by: Alex Deucher --- .../dc/dml/dcn20/display_rq_dlg_calc_20.c | 32 +-- .../dc/dml/dcn20/display_rq_dlg_calc_20v2.c | 32 +-- .../dc/dml/dcn21/display_rq_dlg_calc_21.c | 32 +-- .../dc/dml/dcn30/display_rq_dlg_calc_30.c | 32 +-- .../dc/dml/dcn31/display_rq_dlg_calc_31.c | 32 +-- .../display/dc/dml/display_rq_dlg_helpers.c | 256 +++++++++--------- .../display/dc/dml/display_rq_dlg_helpers.h | 20 +- .../display/dc/dml/dml1_display_rq_dlg_calc.c | 28 +- 8 files changed, 232 insertions(+), 232 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c index 8c168f348a27f..6a4f479c5aabf 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c @@ -164,26 +164,26 @@ static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_si static void extract_rq_sizing_regs(struct display_mode_lib *mode_lib, display_data_rq_regs_st *rq_regs, - const display_data_rq_sizing_params_st rq_sizing) + const display_data_rq_sizing_params_st *rq_sizing) { dml_print("DML_DLG: %s: rq_sizing param\n", __func__); print__data_rq_sizing_params_st(mode_lib, rq_sizing); - rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; + rq_regs->chunk_size = dml_log2(rq_sizing->chunk_bytes) - 10; - if (rq_sizing.min_chunk_bytes == 0) + if (rq_sizing->min_chunk_bytes == 0) rq_regs->min_chunk_size = 0; else - rq_regs->min_chunk_size = dml_log2(rq_sizing.min_chunk_bytes) - 8 + 1; + rq_regs->min_chunk_size = dml_log2(rq_sizing->min_chunk_bytes) - 8 + 1; - rq_regs->meta_chunk_size = dml_log2(rq_sizing.meta_chunk_bytes) - 10; - if (rq_sizing.min_meta_chunk_bytes == 0) + rq_regs->meta_chunk_size = dml_log2(rq_sizing->meta_chunk_bytes) - 10; + if (rq_sizing->min_meta_chunk_bytes == 0) rq_regs->min_meta_chunk_size = 0; else - rq_regs->min_meta_chunk_size = dml_log2(rq_sizing.min_meta_chunk_bytes) - 6 + 1; + rq_regs->min_meta_chunk_size = dml_log2(rq_sizing->min_meta_chunk_bytes) - 6 + 1; - rq_regs->dpte_group_size = dml_log2(rq_sizing.dpte_group_bytes) - 6; - rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; + rq_regs->dpte_group_size = dml_log2(rq_sizing->dpte_group_bytes) - 6; + rq_regs->mpte_group_size = dml_log2(rq_sizing->mpte_group_bytes) - 6; } static void extract_rq_regs(struct display_mode_lib *mode_lib, @@ -193,13 +193,13 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib, unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param.sizing.rq_l); rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_l.dpte_row_height), 1) - 3; if (rq_param.yuv420) { - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param.sizing.rq_c); rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_c.dpte_row_height), 1) - 3; } @@ -763,7 +763,7 @@ static void dml20_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, // calculate how to split the det buffer space between luma and chroma handle_det_buf_split(mode_lib, rq_param, pipe_src_param); - print__rq_params_st(mode_lib, *rq_param); + print__rq_params_st(mode_lib, rq_param); } void dml20_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, @@ -776,7 +776,7 @@ void dml20_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, dml20_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param->src); extract_rq_regs(mode_lib, rq_regs, rq_param); - print__rq_regs_st(mode_lib, *rq_regs); + print__rq_regs_st(mode_lib, rq_regs); } // Note: currently taken in as is. @@ -1542,8 +1542,8 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, disp_ttu_regs->min_ttu_vblank = min_ttu_vblank * refclk_freq_in_mhz; ASSERT(disp_ttu_regs->min_ttu_vblank < dml_pow(2, 24)); - print__ttu_regs_st(mode_lib, *disp_ttu_regs); - print__dlg_regs_st(mode_lib, *disp_dlg_regs); + print__ttu_regs_st(mode_lib, disp_ttu_regs); + print__dlg_regs_st(mode_lib, disp_dlg_regs); } void dml20_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, @@ -1579,7 +1579,7 @@ void dml20_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency / dlg_sys_param.deepsleep_dcfclk_mhz; // TODO: Deprecated - print__dlg_sys_params_st(mode_lib, dlg_sys_param); + print__dlg_sys_params_st(mode_lib, &dlg_sys_param); // system parameter calculation done diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c index 26ececfd40cdc..b5f33f05c8e88 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c @@ -164,26 +164,26 @@ static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_si static void extract_rq_sizing_regs(struct display_mode_lib *mode_lib, display_data_rq_regs_st *rq_regs, - const display_data_rq_sizing_params_st rq_sizing) + const display_data_rq_sizing_params_st *rq_sizing) { dml_print("DML_DLG: %s: rq_sizing param\n", __func__); print__data_rq_sizing_params_st(mode_lib, rq_sizing); - rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; + rq_regs->chunk_size = dml_log2(rq_sizing->chunk_bytes) - 10; - if (rq_sizing.min_chunk_bytes == 0) + if (rq_sizing->min_chunk_bytes == 0) rq_regs->min_chunk_size = 0; else - rq_regs->min_chunk_size = dml_log2(rq_sizing.min_chunk_bytes) - 8 + 1; + rq_regs->min_chunk_size = dml_log2(rq_sizing->min_chunk_bytes) - 8 + 1; - rq_regs->meta_chunk_size = dml_log2(rq_sizing.meta_chunk_bytes) - 10; - if (rq_sizing.min_meta_chunk_bytes == 0) + rq_regs->meta_chunk_size = dml_log2(rq_sizing->meta_chunk_bytes) - 10; + if (rq_sizing->min_meta_chunk_bytes == 0) rq_regs->min_meta_chunk_size = 0; else - rq_regs->min_meta_chunk_size = dml_log2(rq_sizing.min_meta_chunk_bytes) - 6 + 1; + rq_regs->min_meta_chunk_size = dml_log2(rq_sizing->min_meta_chunk_bytes) - 6 + 1; - rq_regs->dpte_group_size = dml_log2(rq_sizing.dpte_group_bytes) - 6; - rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; + rq_regs->dpte_group_size = dml_log2(rq_sizing->dpte_group_bytes) - 6; + rq_regs->mpte_group_size = dml_log2(rq_sizing->mpte_group_bytes) - 6; } static void extract_rq_regs(struct display_mode_lib *mode_lib, @@ -193,13 +193,13 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib, unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param.sizing.rq_l); rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_l.dpte_row_height), 1) - 3; if (rq_param.yuv420) { - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param.sizing.rq_c); rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_c.dpte_row_height), 1) - 3; } @@ -763,7 +763,7 @@ static void dml20v2_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, // calculate how to split the det buffer space between luma and chroma handle_det_buf_split(mode_lib, rq_param, pipe_src_param); - print__rq_params_st(mode_lib, *rq_param); + print__rq_params_st(mode_lib, rq_param); } void dml20v2_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, @@ -776,7 +776,7 @@ void dml20v2_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, dml20v2_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param->src); extract_rq_regs(mode_lib, rq_regs, rq_param); - print__rq_regs_st(mode_lib, *rq_regs); + print__rq_regs_st(mode_lib, rq_regs); } // Note: currently taken in as is. @@ -1543,8 +1543,8 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, disp_ttu_regs->min_ttu_vblank = min_ttu_vblank * refclk_freq_in_mhz; ASSERT(disp_ttu_regs->min_ttu_vblank < dml_pow(2, 24)); - print__ttu_regs_st(mode_lib, *disp_ttu_regs); - print__dlg_regs_st(mode_lib, *disp_dlg_regs); + print__ttu_regs_st(mode_lib, disp_ttu_regs); + print__dlg_regs_st(mode_lib, disp_dlg_regs); } void dml20v2_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, @@ -1580,7 +1580,7 @@ void dml20v2_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency / dlg_sys_param.deepsleep_dcfclk_mhz; // TODO: Deprecated - print__dlg_sys_params_st(mode_lib, dlg_sys_param); + print__dlg_sys_params_st(mode_lib, &dlg_sys_param); // system parameter calculation done diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c index 736978c4d40a1..661fbb622824e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c @@ -141,26 +141,26 @@ static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_si static void extract_rq_sizing_regs( struct display_mode_lib *mode_lib, display_data_rq_regs_st *rq_regs, - const display_data_rq_sizing_params_st rq_sizing) + const display_data_rq_sizing_params_st *rq_sizing) { dml_print("DML_DLG: %s: rq_sizing param\n", __func__); print__data_rq_sizing_params_st(mode_lib, rq_sizing); - rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; + rq_regs->chunk_size = dml_log2(rq_sizing->chunk_bytes) - 10; - if (rq_sizing.min_chunk_bytes == 0) + if (rq_sizing->min_chunk_bytes == 0) rq_regs->min_chunk_size = 0; else - rq_regs->min_chunk_size = dml_log2(rq_sizing.min_chunk_bytes) - 8 + 1; + rq_regs->min_chunk_size = dml_log2(rq_sizing->min_chunk_bytes) - 8 + 1; - rq_regs->meta_chunk_size = dml_log2(rq_sizing.meta_chunk_bytes) - 10; - if (rq_sizing.min_meta_chunk_bytes == 0) + rq_regs->meta_chunk_size = dml_log2(rq_sizing->meta_chunk_bytes) - 10; + if (rq_sizing->min_meta_chunk_bytes == 0) rq_regs->min_meta_chunk_size = 0; else - rq_regs->min_meta_chunk_size = dml_log2(rq_sizing.min_meta_chunk_bytes) - 6 + 1; + rq_regs->min_meta_chunk_size = dml_log2(rq_sizing->min_meta_chunk_bytes) - 6 + 1; - rq_regs->dpte_group_size = dml_log2(rq_sizing.dpte_group_bytes) - 6; - rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; + rq_regs->dpte_group_size = dml_log2(rq_sizing->dpte_group_bytes) - 6; + rq_regs->mpte_group_size = dml_log2(rq_sizing->mpte_group_bytes) - 6; } static void extract_rq_regs( @@ -171,14 +171,14 @@ static void extract_rq_regs( unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param.sizing.rq_l); rq_regs->rq_regs_l.pte_row_height_linear = dml_floor( dml_log2(rq_param.dlg.rq_l.dpte_row_height), 1) - 3; if (rq_param.yuv420) { - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param.sizing.rq_c); rq_regs->rq_regs_c.pte_row_height_linear = dml_floor( dml_log2(rq_param.dlg.rq_c.dpte_row_height), 1) - 3; @@ -807,7 +807,7 @@ static void dml_rq_dlg_get_rq_params( // calculate how to split the det buffer space between luma and chroma handle_det_buf_split(mode_lib, rq_param, pipe_param->src); - print__rq_params_st(mode_lib, *rq_param); + print__rq_params_st(mode_lib, rq_param); } void dml21_rq_dlg_get_rq_reg( @@ -821,7 +821,7 @@ void dml21_rq_dlg_get_rq_reg( dml_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param); extract_rq_regs(mode_lib, rq_regs, rq_param); - print__rq_regs_st(mode_lib, *rq_regs); + print__rq_regs_st(mode_lib, rq_regs); } // Note: currently taken in as is. @@ -1650,8 +1650,8 @@ static void dml_rq_dlg_get_dlg_params( disp_ttu_regs->min_ttu_vblank = min_ttu_vblank * refclk_freq_in_mhz; ASSERT(disp_ttu_regs->min_ttu_vblank < dml_pow(2, 24)); - print__ttu_regs_st(mode_lib, *disp_ttu_regs); - print__dlg_regs_st(mode_lib, *disp_dlg_regs); + print__ttu_regs_st(mode_lib, disp_ttu_regs); + print__dlg_regs_st(mode_lib, disp_dlg_regs); } void dml21_rq_dlg_get_dlg_reg( @@ -1691,7 +1691,7 @@ void dml21_rq_dlg_get_dlg_reg( dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency / dlg_sys_param.deepsleep_dcfclk_mhz; // TODO: Deprecated - print__dlg_sys_params_st(mode_lib, dlg_sys_param); + print__dlg_sys_params_st(mode_lib, &dlg_sys_param); // system parameter calculation done diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c index 2120e0941a095..1535b01a8c5d8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c @@ -89,26 +89,26 @@ static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_si static void extract_rq_sizing_regs(struct display_mode_lib *mode_lib, display_data_rq_regs_st *rq_regs, - const display_data_rq_sizing_params_st rq_sizing) + const display_data_rq_sizing_params_st *rq_sizing) { dml_print("DML_DLG: %s: rq_sizing param\n", __func__); print__data_rq_sizing_params_st(mode_lib, rq_sizing); - rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; + rq_regs->chunk_size = dml_log2(rq_sizing->chunk_bytes) - 10; - if (rq_sizing.min_chunk_bytes == 0) + if (rq_sizing->min_chunk_bytes == 0) rq_regs->min_chunk_size = 0; else - rq_regs->min_chunk_size = dml_log2(rq_sizing.min_chunk_bytes) - 8 + 1; + rq_regs->min_chunk_size = dml_log2(rq_sizing->min_chunk_bytes) - 8 + 1; - rq_regs->meta_chunk_size = dml_log2(rq_sizing.meta_chunk_bytes) - 10; - if (rq_sizing.min_meta_chunk_bytes == 0) + rq_regs->meta_chunk_size = dml_log2(rq_sizing->meta_chunk_bytes) - 10; + if (rq_sizing->min_meta_chunk_bytes == 0) rq_regs->min_meta_chunk_size = 0; else - rq_regs->min_meta_chunk_size = dml_log2(rq_sizing.min_meta_chunk_bytes) - 6 + 1; + rq_regs->min_meta_chunk_size = dml_log2(rq_sizing->min_meta_chunk_bytes) - 6 + 1; - rq_regs->dpte_group_size = dml_log2(rq_sizing.dpte_group_bytes) - 6; - rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; + rq_regs->dpte_group_size = dml_log2(rq_sizing->dpte_group_bytes) - 6; + rq_regs->mpte_group_size = dml_log2(rq_sizing->mpte_group_bytes) - 6; } static void extract_rq_regs(struct display_mode_lib *mode_lib, @@ -118,13 +118,13 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib, unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param.sizing.rq_l); rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_l.dpte_row_height), 1) - 3; if (rq_param.yuv420) { - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param.sizing.rq_c); rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_c.dpte_row_height), 1) - 3; } @@ -872,7 +872,7 @@ static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, // calculate how to split the det buffer space between luma and chroma handle_det_buf_split(mode_lib, rq_param, pipe_param->src); - print__rq_params_st(mode_lib, *rq_param); + print__rq_params_st(mode_lib, rq_param); } void dml30_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, @@ -885,7 +885,7 @@ void dml30_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, dml_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param); extract_rq_regs(mode_lib, rq_regs, rq_param); - print__rq_regs_st(mode_lib, *rq_regs); + print__rq_regs_st(mode_lib, rq_regs); } static void calculate_ttu_cursor(struct display_mode_lib *mode_lib, @@ -1824,8 +1824,8 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, disp_ttu_regs->min_ttu_vblank = min_ttu_vblank * refclk_freq_in_mhz; ASSERT(disp_ttu_regs->min_ttu_vblank < dml_pow(2, 24)); - print__ttu_regs_st(mode_lib, *disp_ttu_regs); - print__dlg_regs_st(mode_lib, *disp_dlg_regs); + print__ttu_regs_st(mode_lib, disp_ttu_regs); + print__dlg_regs_st(mode_lib, disp_dlg_regs); } void dml30_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, @@ -1861,7 +1861,7 @@ void dml30_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, dlg_sys_param.t_srx_delay_us = mode_lib->ip.dcfclk_cstate_latency / dlg_sys_param.deepsleep_dcfclk_mhz; // TODO: Deprecated - print__dlg_sys_params_st(mode_lib, dlg_sys_param); + print__dlg_sys_params_st(mode_lib, &dlg_sys_param); // system parameter calculation done diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c index 57bd4e3f8a823..442abae4bc8c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c @@ -175,25 +175,25 @@ static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_si return (4 * 1024); } -static void extract_rq_sizing_regs(struct display_mode_lib *mode_lib, display_data_rq_regs_st *rq_regs, const display_data_rq_sizing_params_st rq_sizing) +static void extract_rq_sizing_regs(struct display_mode_lib *mode_lib, display_data_rq_regs_st *rq_regs, const display_data_rq_sizing_params_st *rq_sizing) { print__data_rq_sizing_params_st(mode_lib, rq_sizing); - rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; + rq_regs->chunk_size = dml_log2(rq_sizing->chunk_bytes) - 10; - if (rq_sizing.min_chunk_bytes == 0) + if (rq_sizing->min_chunk_bytes == 0) rq_regs->min_chunk_size = 0; else - rq_regs->min_chunk_size = dml_log2(rq_sizing.min_chunk_bytes) - 8 + 1; + rq_regs->min_chunk_size = dml_log2(rq_sizing->min_chunk_bytes) - 8 + 1; - rq_regs->meta_chunk_size = dml_log2(rq_sizing.meta_chunk_bytes) - 10; - if (rq_sizing.min_meta_chunk_bytes == 0) + rq_regs->meta_chunk_size = dml_log2(rq_sizing->meta_chunk_bytes) - 10; + if (rq_sizing->min_meta_chunk_bytes == 0) rq_regs->min_meta_chunk_size = 0; else - rq_regs->min_meta_chunk_size = dml_log2(rq_sizing.min_meta_chunk_bytes) - 6 + 1; + rq_regs->min_meta_chunk_size = dml_log2(rq_sizing->min_meta_chunk_bytes) - 6 + 1; - rq_regs->dpte_group_size = dml_log2(rq_sizing.dpte_group_bytes) - 6; - rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; + rq_regs->dpte_group_size = dml_log2(rq_sizing->dpte_group_bytes) - 6; + rq_regs->mpte_group_size = dml_log2(rq_sizing->mpte_group_bytes) - 6; } static void extract_rq_regs(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, const display_rq_params_st rq_param) @@ -201,12 +201,12 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib, display_rq_regs_s unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param.sizing.rq_l); rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_l.dpte_row_height), 1) - 3; if (rq_param.yuv420) { - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param.sizing.rq_c); rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_c.dpte_row_height), 1) - 3; } @@ -850,7 +850,7 @@ static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, display_ // calculate how to split the det buffer space between luma and chroma handle_det_buf_split(mode_lib, rq_param, pipe_param->src); - print__rq_params_st(mode_lib, *rq_param); + print__rq_params_st(mode_lib, rq_param); } void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, const display_pipe_params_st *pipe_param) @@ -861,7 +861,7 @@ void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_regs_ dml_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param); extract_rq_regs(mode_lib, rq_regs, rq_param); - print__rq_regs_st(mode_lib, *rq_regs); + print__rq_regs_st(mode_lib, rq_regs); } static void calculate_ttu_cursor( @@ -1669,8 +1669,8 @@ static void dml_rq_dlg_get_dlg_params( disp_ttu_regs->min_ttu_vblank = min_ttu_vblank * refclk_freq_in_mhz; ASSERT(disp_ttu_regs->min_ttu_vblank < dml_pow(2, 24)); - print__ttu_regs_st(mode_lib, *disp_ttu_regs); - print__dlg_regs_st(mode_lib, *disp_dlg_regs); + print__ttu_regs_st(mode_lib, disp_ttu_regs); + print__dlg_regs_st(mode_lib, disp_dlg_regs); } void dml31_rq_dlg_get_dlg_reg( @@ -1699,7 +1699,7 @@ void dml31_rq_dlg_get_dlg_reg( dlg_sys_param.total_flip_bw = get_total_immediate_flip_bw(mode_lib, e2e_pipe_param, num_pipes); dlg_sys_param.total_flip_bytes = get_total_immediate_flip_bytes(mode_lib, e2e_pipe_param, num_pipes); - print__dlg_sys_params_st(mode_lib, dlg_sys_param); + print__dlg_sys_params_st(mode_lib, &dlg_sys_param); // system parameter calculation done diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c index e2d82aacd3bc9..71ea503cb32ff 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c @@ -26,371 +26,371 @@ #include "display_rq_dlg_helpers.h" #include "dml_logger.h" -void print__rq_params_st(struct display_mode_lib *mode_lib, display_rq_params_st rq_param) +void print__rq_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_rq_params_st *rq_param) { dml_print("DML_RQ_DLG_CALC: ***************************\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_PARAM_ST\n"); dml_print("DML_RQ_DLG_CALC: \n"); - print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_l); + print__data_rq_sizing_params_st(mode_lib, &rq_param->sizing.rq_l); dml_print("DML_RQ_DLG_CALC: ===\n"); - print__data_rq_sizing_params_st(mode_lib, rq_param.sizing.rq_c); + print__data_rq_sizing_params_st(mode_lib, &rq_param->sizing.rq_c); dml_print("DML_RQ_DLG_CALC: \n"); - print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_l); + print__data_rq_dlg_params_st(mode_lib, &rq_param->dlg.rq_l); dml_print("DML_RQ_DLG_CALC: \n"); - print__data_rq_dlg_params_st(mode_lib, rq_param.dlg.rq_c); + print__data_rq_dlg_params_st(mode_lib, &rq_param->dlg.rq_c); dml_print("DML_RQ_DLG_CALC: \n"); - print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_l); + print__data_rq_misc_params_st(mode_lib, &rq_param->misc.rq_l); dml_print("DML_RQ_DLG_CALC: \n"); - print__data_rq_misc_params_st(mode_lib, rq_param.misc.rq_c); + print__data_rq_misc_params_st(mode_lib, &rq_param->misc.rq_c); dml_print("DML_RQ_DLG_CALC: ***************************\n"); } -void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, display_data_rq_sizing_params_st rq_sizing) +void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing) { dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_SIZING_PARAM_ST\n"); - dml_print("DML_RQ_DLG_CALC: chunk_bytes = %0d\n", rq_sizing.chunk_bytes); - dml_print("DML_RQ_DLG_CALC: min_chunk_bytes = %0d\n", rq_sizing.min_chunk_bytes); - dml_print("DML_RQ_DLG_CALC: meta_chunk_bytes = %0d\n", rq_sizing.meta_chunk_bytes); + dml_print("DML_RQ_DLG_CALC: chunk_bytes = %0d\n", rq_sizing->chunk_bytes); + dml_print("DML_RQ_DLG_CALC: min_chunk_bytes = %0d\n", rq_sizing->min_chunk_bytes); + dml_print("DML_RQ_DLG_CALC: meta_chunk_bytes = %0d\n", rq_sizing->meta_chunk_bytes); dml_print( "DML_RQ_DLG_CALC: min_meta_chunk_bytes = %0d\n", - rq_sizing.min_meta_chunk_bytes); - dml_print("DML_RQ_DLG_CALC: mpte_group_bytes = %0d\n", rq_sizing.mpte_group_bytes); - dml_print("DML_RQ_DLG_CALC: dpte_group_bytes = %0d\n", rq_sizing.dpte_group_bytes); + rq_sizing->min_meta_chunk_bytes); + dml_print("DML_RQ_DLG_CALC: mpte_group_bytes = %0d\n", rq_sizing->mpte_group_bytes); + dml_print("DML_RQ_DLG_CALC: dpte_group_bytes = %0d\n", rq_sizing->dpte_group_bytes); dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, display_data_rq_dlg_params_st rq_dlg_param) +void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param) { dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_DLG_PARAM_ST\n"); dml_print( "DML_RQ_DLG_CALC: swath_width_ub = %0d\n", - rq_dlg_param.swath_width_ub); + rq_dlg_param->swath_width_ub); dml_print( "DML_RQ_DLG_CALC: swath_height = %0d\n", - rq_dlg_param.swath_height); + rq_dlg_param->swath_height); dml_print( "DML_RQ_DLG_CALC: req_per_swath_ub = %0d\n", - rq_dlg_param.req_per_swath_ub); + rq_dlg_param->req_per_swath_ub); dml_print( "DML_RQ_DLG_CALC: meta_pte_bytes_per_frame_ub = %0d\n", - rq_dlg_param.meta_pte_bytes_per_frame_ub); + rq_dlg_param->meta_pte_bytes_per_frame_ub); dml_print( "DML_RQ_DLG_CALC: dpte_req_per_row_ub = %0d\n", - rq_dlg_param.dpte_req_per_row_ub); + rq_dlg_param->dpte_req_per_row_ub); dml_print( "DML_RQ_DLG_CALC: dpte_groups_per_row_ub = %0d\n", - rq_dlg_param.dpte_groups_per_row_ub); + rq_dlg_param->dpte_groups_per_row_ub); dml_print( "DML_RQ_DLG_CALC: dpte_row_height = %0d\n", - rq_dlg_param.dpte_row_height); + rq_dlg_param->dpte_row_height); dml_print( "DML_RQ_DLG_CALC: dpte_bytes_per_row_ub = %0d\n", - rq_dlg_param.dpte_bytes_per_row_ub); + rq_dlg_param->dpte_bytes_per_row_ub); dml_print( "DML_RQ_DLG_CALC: meta_chunks_per_row_ub = %0d\n", - rq_dlg_param.meta_chunks_per_row_ub); + rq_dlg_param->meta_chunks_per_row_ub); dml_print( "DML_RQ_DLG_CALC: meta_req_per_row_ub = %0d\n", - rq_dlg_param.meta_req_per_row_ub); + rq_dlg_param->meta_req_per_row_ub); dml_print( "DML_RQ_DLG_CALC: meta_row_height = %0d\n", - rq_dlg_param.meta_row_height); + rq_dlg_param->meta_row_height); dml_print( "DML_RQ_DLG_CALC: meta_bytes_per_row_ub = %0d\n", - rq_dlg_param.meta_bytes_per_row_ub); + rq_dlg_param->meta_bytes_per_row_ub); dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, display_data_rq_misc_params_st rq_misc_param) +void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param) { dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_MISC_PARAM_ST\n"); dml_print( "DML_RQ_DLG_CALC: full_swath_bytes = %0d\n", - rq_misc_param.full_swath_bytes); + rq_misc_param->full_swath_bytes); dml_print( "DML_RQ_DLG_CALC: stored_swath_bytes = %0d\n", - rq_misc_param.stored_swath_bytes); - dml_print("DML_RQ_DLG_CALC: blk256_width = %0d\n", rq_misc_param.blk256_width); - dml_print("DML_RQ_DLG_CALC: blk256_height = %0d\n", rq_misc_param.blk256_height); - dml_print("DML_RQ_DLG_CALC: req_width = %0d\n", rq_misc_param.req_width); - dml_print("DML_RQ_DLG_CALC: req_height = %0d\n", rq_misc_param.req_height); + rq_misc_param->stored_swath_bytes); + dml_print("DML_RQ_DLG_CALC: blk256_width = %0d\n", rq_misc_param->blk256_width); + dml_print("DML_RQ_DLG_CALC: blk256_height = %0d\n", rq_misc_param->blk256_height); + dml_print("DML_RQ_DLG_CALC: req_width = %0d\n", rq_misc_param->req_width); + dml_print("DML_RQ_DLG_CALC: req_height = %0d\n", rq_misc_param->req_height); dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__rq_dlg_params_st(struct display_mode_lib *mode_lib, display_rq_dlg_params_st rq_dlg_param) +void print__rq_dlg_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_rq_dlg_params_st *rq_dlg_param) { dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST\n"); dml_print("DML_RQ_DLG_CALC: \n"); - print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_l); + print__data_rq_dlg_params_st(mode_lib, &rq_dlg_param->rq_l); dml_print("DML_RQ_DLG_CALC: \n"); - print__data_rq_dlg_params_st(mode_lib, rq_dlg_param.rq_c); + print__data_rq_dlg_params_st(mode_lib, &rq_dlg_param->rq_c); dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, display_dlg_sys_params_st dlg_sys_param) +void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_dlg_sys_params_st *dlg_sys_param) { dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST\n"); - dml_print("DML_RQ_DLG_CALC: t_mclk_wm_us = %3.2f\n", dlg_sys_param.t_mclk_wm_us); - dml_print("DML_RQ_DLG_CALC: t_urg_wm_us = %3.2f\n", dlg_sys_param.t_urg_wm_us); - dml_print("DML_RQ_DLG_CALC: t_sr_wm_us = %3.2f\n", dlg_sys_param.t_sr_wm_us); - dml_print("DML_RQ_DLG_CALC: t_extra_us = %3.2f\n", dlg_sys_param.t_extra_us); + dml_print("DML_RQ_DLG_CALC: t_mclk_wm_us = %3.2f\n", dlg_sys_param->t_mclk_wm_us); + dml_print("DML_RQ_DLG_CALC: t_urg_wm_us = %3.2f\n", dlg_sys_param->t_urg_wm_us); + dml_print("DML_RQ_DLG_CALC: t_sr_wm_us = %3.2f\n", dlg_sys_param->t_sr_wm_us); + dml_print("DML_RQ_DLG_CALC: t_extra_us = %3.2f\n", dlg_sys_param->t_extra_us); dml_print( "DML_RQ_DLG_CALC: t_srx_delay_us = %3.2f\n", - dlg_sys_param.t_srx_delay_us); + dlg_sys_param->t_srx_delay_us); dml_print( "DML_RQ_DLG_CALC: deepsleep_dcfclk_mhz = %3.2f\n", - dlg_sys_param.deepsleep_dcfclk_mhz); + dlg_sys_param->deepsleep_dcfclk_mhz); dml_print( "DML_RQ_DLG_CALC: total_flip_bw = %3.2f\n", - dlg_sys_param.total_flip_bw); + dlg_sys_param->total_flip_bw); dml_print( "DML_RQ_DLG_CALC: total_flip_bytes = %i\n", - dlg_sys_param.total_flip_bytes); + dlg_sys_param->total_flip_bytes); dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__data_rq_regs_st(struct display_mode_lib *mode_lib, display_data_rq_regs_st rq_regs) +void print__data_rq_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_regs_st *rq_regs) { dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_REGS_ST\n"); - dml_print("DML_RQ_DLG_CALC: chunk_size = 0x%0x\n", rq_regs.chunk_size); - dml_print("DML_RQ_DLG_CALC: min_chunk_size = 0x%0x\n", rq_regs.min_chunk_size); - dml_print("DML_RQ_DLG_CALC: meta_chunk_size = 0x%0x\n", rq_regs.meta_chunk_size); + dml_print("DML_RQ_DLG_CALC: chunk_size = 0x%0x\n", rq_regs->chunk_size); + dml_print("DML_RQ_DLG_CALC: min_chunk_size = 0x%0x\n", rq_regs->min_chunk_size); + dml_print("DML_RQ_DLG_CALC: meta_chunk_size = 0x%0x\n", rq_regs->meta_chunk_size); dml_print( "DML_RQ_DLG_CALC: min_meta_chunk_size = 0x%0x\n", - rq_regs.min_meta_chunk_size); - dml_print("DML_RQ_DLG_CALC: dpte_group_size = 0x%0x\n", rq_regs.dpte_group_size); - dml_print("DML_RQ_DLG_CALC: mpte_group_size = 0x%0x\n", rq_regs.mpte_group_size); - dml_print("DML_RQ_DLG_CALC: swath_height = 0x%0x\n", rq_regs.swath_height); + rq_regs->min_meta_chunk_size); + dml_print("DML_RQ_DLG_CALC: dpte_group_size = 0x%0x\n", rq_regs->dpte_group_size); + dml_print("DML_RQ_DLG_CALC: mpte_group_size = 0x%0x\n", rq_regs->mpte_group_size); + dml_print("DML_RQ_DLG_CALC: swath_height = 0x%0x\n", rq_regs->swath_height); dml_print( "DML_RQ_DLG_CALC: pte_row_height_linear = 0x%0x\n", - rq_regs.pte_row_height_linear); + rq_regs->pte_row_height_linear); dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__rq_regs_st(struct display_mode_lib *mode_lib, display_rq_regs_st rq_regs) +void print__rq_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_rq_regs_st *rq_regs) { dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_REGS_ST\n"); dml_print("DML_RQ_DLG_CALC: \n"); - print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_l); + print__data_rq_regs_st(mode_lib, &rq_regs->rq_regs_l); dml_print("DML_RQ_DLG_CALC: \n"); - print__data_rq_regs_st(mode_lib, rq_regs.rq_regs_c); - dml_print("DML_RQ_DLG_CALC: drq_expansion_mode = 0x%0x\n", rq_regs.drq_expansion_mode); - dml_print("DML_RQ_DLG_CALC: prq_expansion_mode = 0x%0x\n", rq_regs.prq_expansion_mode); - dml_print("DML_RQ_DLG_CALC: mrq_expansion_mode = 0x%0x\n", rq_regs.mrq_expansion_mode); - dml_print("DML_RQ_DLG_CALC: crq_expansion_mode = 0x%0x\n", rq_regs.crq_expansion_mode); - dml_print("DML_RQ_DLG_CALC: plane1_base_address = 0x%0x\n", rq_regs.plane1_base_address); + print__data_rq_regs_st(mode_lib, &rq_regs->rq_regs_c); + dml_print("DML_RQ_DLG_CALC: drq_expansion_mode = 0x%0x\n", rq_regs->drq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: prq_expansion_mode = 0x%0x\n", rq_regs->prq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: mrq_expansion_mode = 0x%0x\n", rq_regs->mrq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: crq_expansion_mode = 0x%0x\n", rq_regs->crq_expansion_mode); + dml_print("DML_RQ_DLG_CALC: plane1_base_address = 0x%0x\n", rq_regs->plane1_base_address); dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__dlg_regs_st(struct display_mode_lib *mode_lib, display_dlg_regs_st dlg_regs) +void print__dlg_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_dlg_regs_st *dlg_regs) { dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_DLG_REGS_ST\n"); dml_print( "DML_RQ_DLG_CALC: refcyc_h_blank_end = 0x%0x\n", - dlg_regs.refcyc_h_blank_end); + dlg_regs->refcyc_h_blank_end); dml_print( "DML_RQ_DLG_CALC: dlg_vblank_end = 0x%0x\n", - dlg_regs.dlg_vblank_end); + dlg_regs->dlg_vblank_end); dml_print( "DML_RQ_DLG_CALC: min_dst_y_next_start = 0x%0x\n", - dlg_regs.min_dst_y_next_start); + dlg_regs->min_dst_y_next_start); dml_print( "DML_RQ_DLG_CALC: refcyc_per_htotal = 0x%0x\n", - dlg_regs.refcyc_per_htotal); + dlg_regs->refcyc_per_htotal); dml_print( "DML_RQ_DLG_CALC: refcyc_x_after_scaler = 0x%0x\n", - dlg_regs.refcyc_x_after_scaler); + dlg_regs->refcyc_x_after_scaler); dml_print( "DML_RQ_DLG_CALC: dst_y_after_scaler = 0x%0x\n", - dlg_regs.dst_y_after_scaler); + dlg_regs->dst_y_after_scaler); dml_print( "DML_RQ_DLG_CALC: dst_y_prefetch = 0x%0x\n", - dlg_regs.dst_y_prefetch); + dlg_regs->dst_y_prefetch); dml_print( "DML_RQ_DLG_CALC: dst_y_per_vm_vblank = 0x%0x\n", - dlg_regs.dst_y_per_vm_vblank); + dlg_regs->dst_y_per_vm_vblank); dml_print( "DML_RQ_DLG_CALC: dst_y_per_row_vblank = 0x%0x\n", - dlg_regs.dst_y_per_row_vblank); + dlg_regs->dst_y_per_row_vblank); dml_print( "DML_RQ_DLG_CALC: dst_y_per_vm_flip = 0x%0x\n", - dlg_regs.dst_y_per_vm_flip); + dlg_regs->dst_y_per_vm_flip); dml_print( "DML_RQ_DLG_CALC: dst_y_per_row_flip = 0x%0x\n", - dlg_regs.dst_y_per_row_flip); + dlg_regs->dst_y_per_row_flip); dml_print( "DML_RQ_DLG_CALC: ref_freq_to_pix_freq = 0x%0x\n", - dlg_regs.ref_freq_to_pix_freq); + dlg_regs->ref_freq_to_pix_freq); dml_print( "DML_RQ_DLG_CALC: vratio_prefetch = 0x%0x\n", - dlg_regs.vratio_prefetch); + dlg_regs->vratio_prefetch); dml_print( "DML_RQ_DLG_CALC: vratio_prefetch_c = 0x%0x\n", - dlg_regs.vratio_prefetch_c); + dlg_regs->vratio_prefetch_c); dml_print( "DML_RQ_DLG_CALC: refcyc_per_pte_group_vblank_l = 0x%0x\n", - dlg_regs.refcyc_per_pte_group_vblank_l); + dlg_regs->refcyc_per_pte_group_vblank_l); dml_print( "DML_RQ_DLG_CALC: refcyc_per_pte_group_vblank_c = 0x%0x\n", - dlg_regs.refcyc_per_pte_group_vblank_c); + dlg_regs->refcyc_per_pte_group_vblank_c); dml_print( "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_l = 0x%0x\n", - dlg_regs.refcyc_per_meta_chunk_vblank_l); + dlg_regs->refcyc_per_meta_chunk_vblank_l); dml_print( "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_vblank_c = 0x%0x\n", - dlg_regs.refcyc_per_meta_chunk_vblank_c); + dlg_regs->refcyc_per_meta_chunk_vblank_c); dml_print( "DML_RQ_DLG_CALC: refcyc_per_pte_group_flip_l = 0x%0x\n", - dlg_regs.refcyc_per_pte_group_flip_l); + dlg_regs->refcyc_per_pte_group_flip_l); dml_print( "DML_RQ_DLG_CALC: refcyc_per_pte_group_flip_c = 0x%0x\n", - dlg_regs.refcyc_per_pte_group_flip_c); + dlg_regs->refcyc_per_pte_group_flip_c); dml_print( "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_flip_l = 0x%0x\n", - dlg_regs.refcyc_per_meta_chunk_flip_l); + dlg_regs->refcyc_per_meta_chunk_flip_l); dml_print( "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_flip_c = 0x%0x\n", - dlg_regs.refcyc_per_meta_chunk_flip_c); + dlg_regs->refcyc_per_meta_chunk_flip_c); dml_print( "DML_RQ_DLG_CALC: dst_y_per_pte_row_nom_l = 0x%0x\n", - dlg_regs.dst_y_per_pte_row_nom_l); + dlg_regs->dst_y_per_pte_row_nom_l); dml_print( "DML_RQ_DLG_CALC: dst_y_per_pte_row_nom_c = 0x%0x\n", - dlg_regs.dst_y_per_pte_row_nom_c); + dlg_regs->dst_y_per_pte_row_nom_c); dml_print( "DML_RQ_DLG_CALC: refcyc_per_pte_group_nom_l = 0x%0x\n", - dlg_regs.refcyc_per_pte_group_nom_l); + dlg_regs->refcyc_per_pte_group_nom_l); dml_print( "DML_RQ_DLG_CALC: refcyc_per_pte_group_nom_c = 0x%0x\n", - dlg_regs.refcyc_per_pte_group_nom_c); + dlg_regs->refcyc_per_pte_group_nom_c); dml_print( "DML_RQ_DLG_CALC: dst_y_per_meta_row_nom_l = 0x%0x\n", - dlg_regs.dst_y_per_meta_row_nom_l); + dlg_regs->dst_y_per_meta_row_nom_l); dml_print( "DML_RQ_DLG_CALC: dst_y_per_meta_row_nom_c = 0x%0x\n", - dlg_regs.dst_y_per_meta_row_nom_c); + dlg_regs->dst_y_per_meta_row_nom_c); dml_print( "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_nom_l = 0x%0x\n", - dlg_regs.refcyc_per_meta_chunk_nom_l); + dlg_regs->refcyc_per_meta_chunk_nom_l); dml_print( "DML_RQ_DLG_CALC: refcyc_per_meta_chunk_nom_c = 0x%0x\n", - dlg_regs.refcyc_per_meta_chunk_nom_c); + dlg_regs->refcyc_per_meta_chunk_nom_c); dml_print( "DML_RQ_DLG_CALC: refcyc_per_line_delivery_pre_l = 0x%0x\n", - dlg_regs.refcyc_per_line_delivery_pre_l); + dlg_regs->refcyc_per_line_delivery_pre_l); dml_print( "DML_RQ_DLG_CALC: refcyc_per_line_delivery_pre_c = 0x%0x\n", - dlg_regs.refcyc_per_line_delivery_pre_c); + dlg_regs->refcyc_per_line_delivery_pre_c); dml_print( "DML_RQ_DLG_CALC: refcyc_per_line_delivery_l = 0x%0x\n", - dlg_regs.refcyc_per_line_delivery_l); + dlg_regs->refcyc_per_line_delivery_l); dml_print( "DML_RQ_DLG_CALC: refcyc_per_line_delivery_c = 0x%0x\n", - dlg_regs.refcyc_per_line_delivery_c); + dlg_regs->refcyc_per_line_delivery_c); dml_print( "DML_RQ_DLG_CALC: chunk_hdl_adjust_cur0 = 0x%0x\n", - dlg_regs.chunk_hdl_adjust_cur0); + dlg_regs->chunk_hdl_adjust_cur0); dml_print( "DML_RQ_DLG_CALC: dst_y_offset_cur1 = 0x%0x\n", - dlg_regs.dst_y_offset_cur1); + dlg_regs->dst_y_offset_cur1); dml_print( "DML_RQ_DLG_CALC: chunk_hdl_adjust_cur1 = 0x%0x\n", - dlg_regs.chunk_hdl_adjust_cur1); + dlg_regs->chunk_hdl_adjust_cur1); dml_print( "DML_RQ_DLG_CALC: vready_after_vcount0 = 0x%0x\n", - dlg_regs.vready_after_vcount0); + dlg_regs->vready_after_vcount0); dml_print( "DML_RQ_DLG_CALC: dst_y_delta_drq_limit = 0x%0x\n", - dlg_regs.dst_y_delta_drq_limit); + dlg_regs->dst_y_delta_drq_limit); dml_print( "DML_RQ_DLG_CALC: xfc_reg_transfer_delay = 0x%0x\n", - dlg_regs.xfc_reg_transfer_delay); + dlg_regs->xfc_reg_transfer_delay); dml_print( "DML_RQ_DLG_CALC: xfc_reg_precharge_delay = 0x%0x\n", - dlg_regs.xfc_reg_precharge_delay); + dlg_regs->xfc_reg_precharge_delay); dml_print( "DML_RQ_DLG_CALC: xfc_reg_remote_surface_flip_latency = 0x%0x\n", - dlg_regs.xfc_reg_remote_surface_flip_latency); + dlg_regs->xfc_reg_remote_surface_flip_latency); dml_print( "DML_RQ_DLG_CALC: refcyc_per_vm_dmdata = 0x%0x\n", - dlg_regs.refcyc_per_vm_dmdata); + dlg_regs->refcyc_per_vm_dmdata); dml_print("DML_RQ_DLG_CALC: =====================================\n"); } -void print__ttu_regs_st(struct display_mode_lib *mode_lib, display_ttu_regs_st ttu_regs) +void print__ttu_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_ttu_regs_st *ttu_regs) { dml_print("DML_RQ_DLG_CALC: =====================================\n"); dml_print("DML_RQ_DLG_CALC: DISPLAY_TTU_REGS_ST\n"); dml_print( "DML_RQ_DLG_CALC: qos_level_low_wm = 0x%0x\n", - ttu_regs.qos_level_low_wm); + ttu_regs->qos_level_low_wm); dml_print( "DML_RQ_DLG_CALC: qos_level_high_wm = 0x%0x\n", - ttu_regs.qos_level_high_wm); + ttu_regs->qos_level_high_wm); dml_print( "DML_RQ_DLG_CALC: min_ttu_vblank = 0x%0x\n", - ttu_regs.min_ttu_vblank); + ttu_regs->min_ttu_vblank); dml_print( "DML_RQ_DLG_CALC: qos_level_flip = 0x%0x\n", - ttu_regs.qos_level_flip); + ttu_regs->qos_level_flip); dml_print( "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_l = 0x%0x\n", - ttu_regs.refcyc_per_req_delivery_pre_l); + ttu_regs->refcyc_per_req_delivery_pre_l); dml_print( "DML_RQ_DLG_CALC: refcyc_per_req_delivery_l = 0x%0x\n", - ttu_regs.refcyc_per_req_delivery_l); + ttu_regs->refcyc_per_req_delivery_l); dml_print( "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_c = 0x%0x\n", - ttu_regs.refcyc_per_req_delivery_pre_c); + ttu_regs->refcyc_per_req_delivery_pre_c); dml_print( "DML_RQ_DLG_CALC: refcyc_per_req_delivery_c = 0x%0x\n", - ttu_regs.refcyc_per_req_delivery_c); + ttu_regs->refcyc_per_req_delivery_c); dml_print( "DML_RQ_DLG_CALC: refcyc_per_req_delivery_cur0 = 0x%0x\n", - ttu_regs.refcyc_per_req_delivery_cur0); + ttu_regs->refcyc_per_req_delivery_cur0); dml_print( "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur0 = 0x%0x\n", - ttu_regs.refcyc_per_req_delivery_pre_cur0); + ttu_regs->refcyc_per_req_delivery_pre_cur0); dml_print( "DML_RQ_DLG_CALC: refcyc_per_req_delivery_cur1 = 0x%0x\n", - ttu_regs.refcyc_per_req_delivery_cur1); + ttu_regs->refcyc_per_req_delivery_cur1); dml_print( "DML_RQ_DLG_CALC: refcyc_per_req_delivery_pre_cur1 = 0x%0x\n", - ttu_regs.refcyc_per_req_delivery_pre_cur1); + ttu_regs->refcyc_per_req_delivery_pre_cur1); dml_print( "DML_RQ_DLG_CALC: qos_level_fixed_l = 0x%0x\n", - ttu_regs.qos_level_fixed_l); + ttu_regs->qos_level_fixed_l); dml_print( "DML_RQ_DLG_CALC: qos_ramp_disable_l = 0x%0x\n", - ttu_regs.qos_ramp_disable_l); + ttu_regs->qos_ramp_disable_l); dml_print( "DML_RQ_DLG_CALC: qos_level_fixed_c = 0x%0x\n", - ttu_regs.qos_level_fixed_c); + ttu_regs->qos_level_fixed_c); dml_print( "DML_RQ_DLG_CALC: qos_ramp_disable_c = 0x%0x\n", - ttu_regs.qos_ramp_disable_c); + ttu_regs->qos_ramp_disable_c); dml_print( "DML_RQ_DLG_CALC: qos_level_fixed_cur0 = 0x%0x\n", - ttu_regs.qos_level_fixed_cur0); + ttu_regs->qos_level_fixed_cur0); dml_print( "DML_RQ_DLG_CALC: qos_ramp_disable_cur0 = 0x%0x\n", - ttu_regs.qos_ramp_disable_cur0); + ttu_regs->qos_ramp_disable_cur0); dml_print( "DML_RQ_DLG_CALC: qos_level_fixed_cur1 = 0x%0x\n", - ttu_regs.qos_level_fixed_cur1); + ttu_regs->qos_level_fixed_cur1); dml_print( "DML_RQ_DLG_CALC: qos_ramp_disable_cur1 = 0x%0x\n", - ttu_regs.qos_ramp_disable_cur1); + ttu_regs->qos_ramp_disable_cur1); dml_print("DML_RQ_DLG_CALC: =====================================\n"); } diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h index 2555ef0358c25..ebcd717744e58 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.h @@ -31,16 +31,16 @@ /* Function: Printer functions * Print various struct */ -void print__rq_params_st(struct display_mode_lib *mode_lib, display_rq_params_st rq_param); -void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, display_data_rq_sizing_params_st rq_sizing); -void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, display_data_rq_dlg_params_st rq_dlg_param); -void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, display_data_rq_misc_params_st rq_misc_param); -void print__rq_dlg_params_st(struct display_mode_lib *mode_lib, display_rq_dlg_params_st rq_dlg_param); -void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, display_dlg_sys_params_st dlg_sys_param); +void print__rq_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_rq_params_st *rq_param); +void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing); +void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param); +void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param); +void print__rq_dlg_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_rq_dlg_params_st *rq_dlg_param); +void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_dlg_sys_params_st *dlg_sys_param); -void print__data_rq_regs_st(struct display_mode_lib *mode_lib, display_data_rq_regs_st data_rq_regs); -void print__rq_regs_st(struct display_mode_lib *mode_lib, display_rq_regs_st rq_regs); -void print__dlg_regs_st(struct display_mode_lib *mode_lib, display_dlg_regs_st dlg_regs); -void print__ttu_regs_st(struct display_mode_lib *mode_lib, display_ttu_regs_st ttu_regs); +void print__data_rq_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_regs_st *rq_regs); +void print__rq_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_rq_regs_st *rq_regs); +void print__dlg_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_dlg_regs_st *dlg_regs); +void print__ttu_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_ttu_regs_st *ttu_regs); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c index 8f2b1684c2312..9bde3f9614098 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c @@ -206,26 +206,26 @@ static unsigned int get_blk_size_bytes(const enum source_macro_tile_size tile_si static void extract_rq_sizing_regs( struct display_mode_lib *mode_lib, struct _vcs_dpi_display_data_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_data_rq_sizing_params_st rq_sizing) + const struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing) { DTRACE("DLG: %s: rq_sizing param", __func__); print__data_rq_sizing_params_st(mode_lib, rq_sizing); - rq_regs->chunk_size = dml_log2(rq_sizing.chunk_bytes) - 10; + rq_regs->chunk_size = dml_log2(rq_sizing->chunk_bytes) - 10; - if (rq_sizing.min_chunk_bytes == 0) + if (rq_sizing->min_chunk_bytes == 0) rq_regs->min_chunk_size = 0; else - rq_regs->min_chunk_size = dml_log2(rq_sizing.min_chunk_bytes) - 8 + 1; + rq_regs->min_chunk_size = dml_log2(rq_sizing->min_chunk_bytes) - 8 + 1; - rq_regs->meta_chunk_size = dml_log2(rq_sizing.meta_chunk_bytes) - 10; - if (rq_sizing.min_meta_chunk_bytes == 0) + rq_regs->meta_chunk_size = dml_log2(rq_sizing->meta_chunk_bytes) - 10; + if (rq_sizing->min_meta_chunk_bytes == 0) rq_regs->min_meta_chunk_size = 0; else - rq_regs->min_meta_chunk_size = dml_log2(rq_sizing.min_meta_chunk_bytes) - 6 + 1; + rq_regs->min_meta_chunk_size = dml_log2(rq_sizing->min_meta_chunk_bytes) - 6 + 1; - rq_regs->dpte_group_size = dml_log2(rq_sizing.dpte_group_bytes) - 6; - rq_regs->mpte_group_size = dml_log2(rq_sizing.mpte_group_bytes) - 6; + rq_regs->dpte_group_size = dml_log2(rq_sizing->dpte_group_bytes) - 6; + rq_regs->mpte_group_size = dml_log2(rq_sizing->mpte_group_bytes) - 6; } void dml1_extract_rq_regs( @@ -236,9 +236,9 @@ void dml1_extract_rq_regs( unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), rq_param.sizing.rq_l); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param.sizing.rq_l); if (rq_param.yuv420) - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), rq_param.sizing.rq_c); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param.sizing.rq_c); rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); @@ -988,7 +988,7 @@ void dml1_rq_dlg_get_rq_params( /* calculate how to split the det buffer space between luma and chroma */ handle_det_buf_split(mode_lib, rq_param, pipe_src_param); - print__rq_params_st(mode_lib, *rq_param); + print__rq_params_st(mode_lib, rq_param); } /* Note: currently taken in as is. @@ -1927,6 +1927,6 @@ void dml1_rq_dlg_get_dlg_params( disp_ttu_regs->min_ttu_vblank = min_ttu_vblank * refclk_freq_in_mhz; ASSERT(disp_ttu_regs->min_ttu_vblank < dml_pow(2, 24)); - print__ttu_regs_st(mode_lib, *disp_ttu_regs); - print__dlg_regs_st(mode_lib, *disp_dlg_regs); + print__ttu_regs_st(mode_lib, disp_ttu_regs); + print__dlg_regs_st(mode_lib, disp_dlg_regs); } From 757af27b9fbbba773a28939a14dbb9bd516202c6 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Wed, 8 Sep 2021 13:40:28 -0400 Subject: [PATCH 123/151] drm/amd/display: Fix rest of pass-by-value structs in DML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Passing structs adds a lot of overhead. We don't ever want to pass anything bigger than primitives by value. This patch fixes these Coverity IDs: Addresses-Coverity-ID: 1424031: ("Big parameter passed by value") Addresses-Coverity-ID: 1424055: ("Big parameter passed by value") Addresses-Coverity-ID: 1424072: ("Big parameter passed by value") Addresses-Coverity-ID: 1423779: ("Big parameter passed by value") Signed-off-by: Harry Wentland Cc: Nick Desaulniers Cc: Linus Torvalds Cc: amd-gfx@lists.freedesktop.org Cc: Linux Kernel Mailing List Cc: Arnd Bergmann Cc: Leo Li Cc: Alex Deucher Cc: Christian König Cc: Xinhui Pan Cc: Nathan Chancellor Cc: Guenter Roeck Cc: llvm@lists.linux.dev Acked-by: Christian König Build-tested-by: Nathan Chancellor Reviewed-by: Leo Li Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 10 +- .../dc/dml/dcn20/display_rq_dlg_calc_20.c | 126 +++++----- .../dc/dml/dcn20/display_rq_dlg_calc_20v2.c | 124 +++++----- .../dc/dml/dcn21/display_rq_dlg_calc_21.c | 68 +++--- .../dc/dml/dcn30/display_rq_dlg_calc_30.c | 34 +-- .../dc/dml/dcn31/display_rq_dlg_calc_31.c | 72 +++--- .../display/dc/dml/dml1_display_rq_dlg_calc.c | 222 +++++++++--------- .../display/dc/dml/dml1_display_rq_dlg_calc.h | 10 +- 8 files changed, 333 insertions(+), 333 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 0e18df1283b68..8e3a9294be3ad 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -502,15 +502,15 @@ static void dcn_bw_calc_rq_dlg_ttu( /*todo: soc->sr_enter_plus_exit_time??*/ dlg_sys_param.t_srx_delay_us = dc->dcn_ip->dcfclk_cstate_latency / v->dcf_clk_deep_sleep; - dml1_rq_dlg_get_rq_params(dml, &rq_param, input.pipe.src); - dml1_extract_rq_regs(dml, rq_regs, rq_param); + dml1_rq_dlg_get_rq_params(dml, &rq_param, &input.pipe.src); + dml1_extract_rq_regs(dml, rq_regs, &rq_param); dml1_rq_dlg_get_dlg_params( dml, dlg_regs, ttu_regs, - rq_param.dlg, - dlg_sys_param, - input, + &rq_param.dlg, + &dlg_sys_param, + &input, true, true, v->pte_enable == dcn_bw_yes, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c index 6a4f479c5aabf..246071c72f6bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c @@ -37,8 +37,8 @@ // static void dml20_rq_dlg_get_rq_params( struct display_mode_lib *mode_lib, - display_rq_params_st * rq_param, - const display_pipe_source_params_st pipe_src_param); + display_rq_params_st *rq_param, + const display_pipe_source_params_st *pipe_src_param); // Function: dml20_rq_dlg_get_dlg_params // Calculate deadline related parameters @@ -49,8 +49,8 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, const unsigned int pipe_idx, display_dlg_regs_st *disp_dlg_regs, display_ttu_regs_st *disp_ttu_regs, - const display_rq_dlg_params_st rq_dlg_param, - const display_dlg_sys_params_st dlg_sys_param, + const display_rq_dlg_params_st *rq_dlg_param, + const display_dlg_sys_params_st *dlg_sys_param, const bool cstate_en, const bool pstate_en); /* @@ -188,28 +188,28 @@ static void extract_rq_sizing_regs(struct display_mode_lib *mode_lib, static void extract_rq_regs(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, - const display_rq_params_st rq_param) + const display_rq_params_st *rq_param) { unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param.sizing.rq_l); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param->sizing.rq_l); - rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_l.dpte_row_height), + rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param->dlg.rq_l.dpte_row_height), 1) - 3; - if (rq_param.yuv420) { - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param.sizing.rq_c); - rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_c.dpte_row_height), + if (rq_param->yuv420) { + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param->sizing.rq_c); + rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param->dlg.rq_c.dpte_row_height), 1) - 3; } - rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); - rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); + rq_regs->rq_regs_l.swath_height = dml_log2(rq_param->dlg.rq_l.swath_height); + rq_regs->rq_regs_c.swath_height = dml_log2(rq_param->dlg.rq_c.swath_height); // TODO: take the max between luma, chroma chunk size? // okay for now, as we are setting chunk_bytes to 8kb anyways - if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { //32kb + if (rq_param->sizing.rq_l.chunk_bytes >= 32 * 1024) { //32kb rq_regs->drq_expansion_mode = 0; } else { rq_regs->drq_expansion_mode = 2; @@ -218,9 +218,9 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib, rq_regs->mrq_expansion_mode = 1; rq_regs->crq_expansion_mode = 1; - if (rq_param.yuv420) { - if ((double) rq_param.misc.rq_l.stored_swath_bytes - / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { + if (rq_param->yuv420) { + if ((double) rq_param->misc.rq_l.stored_swath_bytes + / (double) rq_param->misc.rq_c.stored_swath_bytes <= 1.5) { detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); // half to chroma } else { detile_buf_plane1_addr = dml_round_to_multiple((unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), @@ -233,7 +233,7 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib, static void handle_det_buf_split(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, - const display_pipe_source_params_st pipe_src_param) + const display_pipe_source_params_st *pipe_src_param) { unsigned int total_swath_bytes = 0; unsigned int swath_bytes_l = 0; @@ -242,8 +242,8 @@ static void handle_det_buf_split(struct display_mode_lib *mode_lib, unsigned int full_swath_bytes_packed_c = 0; bool req128_l = false; bool req128_c = false; - bool surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); - bool surf_vert = (pipe_src_param.source_scan == dm_vert); + bool surf_linear = (pipe_src_param->sw_mode == dm_sw_linear); + bool surf_vert = (pipe_src_param->source_scan == dm_vert); unsigned int log2_swath_height_l = 0; unsigned int log2_swath_height_c = 0; unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; @@ -685,7 +685,7 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, display_data_rq_sizing_params_st *rq_sizing_param, display_data_rq_dlg_params_st *rq_dlg_param, display_data_rq_misc_params_st *rq_misc_param, - const display_pipe_source_params_st pipe_src_param, + const display_pipe_source_params_st *pipe_src_param, bool is_chroma) { bool mode_422 = false; @@ -697,15 +697,15 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, // TODO check if ppe apply for both luma and chroma in 422 case if (is_chroma) { - vp_width = pipe_src_param.viewport_width_c / ppe; - vp_height = pipe_src_param.viewport_height_c; - data_pitch = pipe_src_param.data_pitch_c; - meta_pitch = pipe_src_param.meta_pitch_c; + vp_width = pipe_src_param->viewport_width_c / ppe; + vp_height = pipe_src_param->viewport_height_c; + data_pitch = pipe_src_param->data_pitch_c; + meta_pitch = pipe_src_param->meta_pitch_c; } else { - vp_width = pipe_src_param.viewport_width / ppe; - vp_height = pipe_src_param.viewport_height; - data_pitch = pipe_src_param.data_pitch; - meta_pitch = pipe_src_param.meta_pitch; + vp_width = pipe_src_param->viewport_width / ppe; + vp_height = pipe_src_param->viewport_height; + data_pitch = pipe_src_param->data_pitch; + meta_pitch = pipe_src_param->meta_pitch; } rq_sizing_param->chunk_bytes = 8192; @@ -728,21 +728,21 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, vp_height, data_pitch, meta_pitch, - pipe_src_param.source_format, - pipe_src_param.sw_mode, - pipe_src_param.macro_tile_size, - pipe_src_param.source_scan, + pipe_src_param->source_format, + pipe_src_param->sw_mode, + pipe_src_param->macro_tile_size, + pipe_src_param->source_scan, is_chroma); } static void dml20_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, - const display_pipe_source_params_st pipe_src_param) + const display_pipe_source_params_st *pipe_src_param) { // get param for luma surface - rq_param->yuv420 = pipe_src_param.source_format == dm_420_8 - || pipe_src_param.source_format == dm_420_10; - rq_param->yuv420_10bpc = pipe_src_param.source_format == dm_420_10; + rq_param->yuv420 = pipe_src_param->source_format == dm_420_8 + || pipe_src_param->source_format == dm_420_10; + rq_param->yuv420_10bpc = pipe_src_param->source_format == dm_420_10; get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_l), @@ -751,7 +751,7 @@ static void dml20_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, pipe_src_param, 0); - if (is_dual_plane((enum source_format_class)(pipe_src_param.source_format))) { + if (is_dual_plane((enum source_format_class)(pipe_src_param->source_format))) { // get param for chroma surface get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_c), @@ -773,8 +773,8 @@ void dml20_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_params_st rq_param = {0}; memset(rq_regs, 0, sizeof(*rq_regs)); - dml20_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param->src); - extract_rq_regs(mode_lib, rq_regs, rq_param); + dml20_rq_dlg_get_rq_params(mode_lib, &rq_param, &pipe_param->src); + extract_rq_regs(mode_lib, rq_regs, &rq_param); print__rq_regs_st(mode_lib, rq_regs); } @@ -787,8 +787,8 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, const unsigned int pipe_idx, display_dlg_regs_st *disp_dlg_regs, display_ttu_regs_st *disp_ttu_regs, - const display_rq_dlg_params_st rq_dlg_param, - const display_dlg_sys_params_st dlg_sys_param, + const display_rq_dlg_params_st *rq_dlg_param, + const display_dlg_sys_params_st *dlg_sys_param, const bool cstate_en, const bool pstate_en) { @@ -935,7 +935,7 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, * (double) ref_freq_to_pix_freq); ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int) dml_pow(2, 13)); - min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; + min_dcfclk_mhz = dlg_sys_param->deepsleep_dcfclk_mhz; t_calc_us = get_tcalc(mode_lib, e2e_pipe_param, num_pipes); min_ttu_vblank = get_min_ttu_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); @@ -995,20 +995,20 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, // vinit_bot_l = scl.vinit_bot; // vinit_bot_c = scl.vinit_bot_c; -// unsigned int swath_height_l = rq_dlg_param.rq_l.swath_height; - swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; -// unsigned int dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; - dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; -// unsigned int meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; -// unsigned int meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; +// unsigned int swath_height_l = rq_dlg_param->rq_l.swath_height; + swath_width_ub_l = rq_dlg_param->rq_l.swath_width_ub; +// unsigned int dpte_bytes_per_row_ub_l = rq_dlg_param->rq_l.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_l = rq_dlg_param->rq_l.dpte_groups_per_row_ub; +// unsigned int meta_pte_bytes_per_frame_ub_l = rq_dlg_param->rq_l.meta_pte_bytes_per_frame_ub; +// unsigned int meta_bytes_per_row_ub_l = rq_dlg_param->rq_l.meta_bytes_per_row_ub; -// unsigned int swath_height_c = rq_dlg_param.rq_c.swath_height; - swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; - // dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; - dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; +// unsigned int swath_height_c = rq_dlg_param->rq_c.swath_height; + swath_width_ub_c = rq_dlg_param->rq_c.swath_width_ub; + // dpte_bytes_per_row_ub_c = rq_dlg_param->rq_c.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_c = rq_dlg_param->rq_c.dpte_groups_per_row_ub; - meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; - meta_chunks_per_row_ub_c = rq_dlg_param.rq_c.meta_chunks_per_row_ub; + meta_chunks_per_row_ub_l = rq_dlg_param->rq_l.meta_chunks_per_row_ub; + meta_chunks_per_row_ub_c = rq_dlg_param->rq_c.meta_chunks_per_row_ub; vupdate_offset = dst->vupdate_offset; vupdate_width = dst->vupdate_width; vready_offset = dst->vready_offset; @@ -1137,16 +1137,16 @@ static void dml20_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, dml_print("DML_DLG: %s: vratio_pre_c=%3.2f\n", __func__, vratio_pre_c); // Active - req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; - req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; - meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; - meta_row_height_c = rq_dlg_param.rq_c.meta_row_height; + req_per_swath_ub_l = rq_dlg_param->rq_l.req_per_swath_ub; + req_per_swath_ub_c = rq_dlg_param->rq_c.req_per_swath_ub; + meta_row_height_l = rq_dlg_param->rq_l.meta_row_height; + meta_row_height_c = rq_dlg_param->rq_c.meta_row_height; swath_width_pixels_ub_l = 0; swath_width_pixels_ub_c = 0; scaler_rec_in_width_l = 0; scaler_rec_in_width_c = 0; - dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; - dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; + dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height; + dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height; if (mode_422) { swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element @@ -1584,15 +1584,15 @@ void dml20_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, // system parameter calculation done dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); - dml20_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe.src); + dml20_rq_dlg_get_rq_params(mode_lib, &rq_param, &e2e_pipe_param[pipe_idx].pipe.src); dml20_rq_dlg_get_dlg_params(mode_lib, e2e_pipe_param, num_pipes, pipe_idx, dlg_regs, ttu_regs, - rq_param.dlg, - dlg_sys_param, + &rq_param.dlg, + &dlg_sys_param, cstate_en, pstate_en); dml_print("DML_DLG: Calculation for pipe[%d] end\n", pipe_idx); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c index b5f33f05c8e88..015e7f2c0b160 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c @@ -38,7 +38,7 @@ static void dml20v2_rq_dlg_get_rq_params( struct display_mode_lib *mode_lib, display_rq_params_st * rq_param, - const display_pipe_source_params_st pipe_src_param); + const display_pipe_source_params_st *pipe_src_param); // Function: dml20v2_rq_dlg_get_dlg_params // Calculate deadline related parameters @@ -49,8 +49,8 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, const unsigned int pipe_idx, display_dlg_regs_st *disp_dlg_regs, display_ttu_regs_st *disp_ttu_regs, - const display_rq_dlg_params_st rq_dlg_param, - const display_dlg_sys_params_st dlg_sys_param, + const display_rq_dlg_params_st *rq_dlg_param, + const display_dlg_sys_params_st *dlg_sys_param, const bool cstate_en, const bool pstate_en); /* @@ -188,28 +188,28 @@ static void extract_rq_sizing_regs(struct display_mode_lib *mode_lib, static void extract_rq_regs(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, - const display_rq_params_st rq_param) + const display_rq_params_st *rq_param) { unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param.sizing.rq_l); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param->sizing.rq_l); - rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_l.dpte_row_height), + rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param->dlg.rq_l.dpte_row_height), 1) - 3; - if (rq_param.yuv420) { - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param.sizing.rq_c); - rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_c.dpte_row_height), + if (rq_param->yuv420) { + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param->sizing.rq_c); + rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param->dlg.rq_c.dpte_row_height), 1) - 3; } - rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); - rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); + rq_regs->rq_regs_l.swath_height = dml_log2(rq_param->dlg.rq_l.swath_height); + rq_regs->rq_regs_c.swath_height = dml_log2(rq_param->dlg.rq_c.swath_height); // TODO: take the max between luma, chroma chunk size? // okay for now, as we are setting chunk_bytes to 8kb anyways - if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { //32kb + if (rq_param->sizing.rq_l.chunk_bytes >= 32 * 1024) { //32kb rq_regs->drq_expansion_mode = 0; } else { rq_regs->drq_expansion_mode = 2; @@ -218,9 +218,9 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib, rq_regs->mrq_expansion_mode = 1; rq_regs->crq_expansion_mode = 1; - if (rq_param.yuv420) { - if ((double) rq_param.misc.rq_l.stored_swath_bytes - / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { + if (rq_param->yuv420) { + if ((double) rq_param->misc.rq_l.stored_swath_bytes + / (double) rq_param->misc.rq_c.stored_swath_bytes <= 1.5) { detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); // half to chroma } else { detile_buf_plane1_addr = dml_round_to_multiple((unsigned int) ((2.0 * detile_buf_size_in_bytes) / 3.0), @@ -233,7 +233,7 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib, static void handle_det_buf_split(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, - const display_pipe_source_params_st pipe_src_param) + const display_pipe_source_params_st *pipe_src_param) { unsigned int total_swath_bytes = 0; unsigned int swath_bytes_l = 0; @@ -242,8 +242,8 @@ static void handle_det_buf_split(struct display_mode_lib *mode_lib, unsigned int full_swath_bytes_packed_c = 0; bool req128_l = false; bool req128_c = false; - bool surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); - bool surf_vert = (pipe_src_param.source_scan == dm_vert); + bool surf_linear = (pipe_src_param->sw_mode == dm_sw_linear); + bool surf_vert = (pipe_src_param->source_scan == dm_vert); unsigned int log2_swath_height_l = 0; unsigned int log2_swath_height_c = 0; unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; @@ -685,7 +685,7 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, display_data_rq_sizing_params_st *rq_sizing_param, display_data_rq_dlg_params_st *rq_dlg_param, display_data_rq_misc_params_st *rq_misc_param, - const display_pipe_source_params_st pipe_src_param, + const display_pipe_source_params_st *pipe_src_param, bool is_chroma) { bool mode_422 = false; @@ -697,15 +697,15 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, // TODO check if ppe apply for both luma and chroma in 422 case if (is_chroma) { - vp_width = pipe_src_param.viewport_width_c / ppe; - vp_height = pipe_src_param.viewport_height_c; - data_pitch = pipe_src_param.data_pitch_c; - meta_pitch = pipe_src_param.meta_pitch_c; + vp_width = pipe_src_param->viewport_width_c / ppe; + vp_height = pipe_src_param->viewport_height_c; + data_pitch = pipe_src_param->data_pitch_c; + meta_pitch = pipe_src_param->meta_pitch_c; } else { - vp_width = pipe_src_param.viewport_width / ppe; - vp_height = pipe_src_param.viewport_height; - data_pitch = pipe_src_param.data_pitch; - meta_pitch = pipe_src_param.meta_pitch; + vp_width = pipe_src_param->viewport_width / ppe; + vp_height = pipe_src_param->viewport_height; + data_pitch = pipe_src_param->data_pitch; + meta_pitch = pipe_src_param->meta_pitch; } rq_sizing_param->chunk_bytes = 8192; @@ -728,21 +728,21 @@ static void get_surf_rq_param(struct display_mode_lib *mode_lib, vp_height, data_pitch, meta_pitch, - pipe_src_param.source_format, - pipe_src_param.sw_mode, - pipe_src_param.macro_tile_size, - pipe_src_param.source_scan, + pipe_src_param->source_format, + pipe_src_param->sw_mode, + pipe_src_param->macro_tile_size, + pipe_src_param->source_scan, is_chroma); } static void dml20v2_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, - const display_pipe_source_params_st pipe_src_param) + const display_pipe_source_params_st *pipe_src_param) { // get param for luma surface - rq_param->yuv420 = pipe_src_param.source_format == dm_420_8 - || pipe_src_param.source_format == dm_420_10; - rq_param->yuv420_10bpc = pipe_src_param.source_format == dm_420_10; + rq_param->yuv420 = pipe_src_param->source_format == dm_420_8 + || pipe_src_param->source_format == dm_420_10; + rq_param->yuv420_10bpc = pipe_src_param->source_format == dm_420_10; get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_l), @@ -751,7 +751,7 @@ static void dml20v2_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, pipe_src_param, 0); - if (is_dual_plane((enum source_format_class)(pipe_src_param.source_format))) { + if (is_dual_plane((enum source_format_class)(pipe_src_param->source_format))) { // get param for chroma surface get_surf_rq_param(mode_lib, &(rq_param->sizing.rq_c), @@ -773,8 +773,8 @@ void dml20v2_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_params_st rq_param = {0}; memset(rq_regs, 0, sizeof(*rq_regs)); - dml20v2_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param->src); - extract_rq_regs(mode_lib, rq_regs, rq_param); + dml20v2_rq_dlg_get_rq_params(mode_lib, &rq_param, &pipe_param->src); + extract_rq_regs(mode_lib, rq_regs, &rq_param); print__rq_regs_st(mode_lib, rq_regs); } @@ -787,8 +787,8 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, const unsigned int pipe_idx, display_dlg_regs_st *disp_dlg_regs, display_ttu_regs_st *disp_ttu_regs, - const display_rq_dlg_params_st rq_dlg_param, - const display_dlg_sys_params_st dlg_sys_param, + const display_rq_dlg_params_st *rq_dlg_param, + const display_dlg_sys_params_st *dlg_sys_param, const bool cstate_en, const bool pstate_en) { @@ -935,7 +935,7 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, * (double) ref_freq_to_pix_freq); ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int) dml_pow(2, 13)); - min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; + min_dcfclk_mhz = dlg_sys_param->deepsleep_dcfclk_mhz; t_calc_us = get_tcalc(mode_lib, e2e_pipe_param, num_pipes); min_ttu_vblank = get_min_ttu_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); @@ -996,20 +996,20 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, // vinit_bot_l = scl.vinit_bot; // vinit_bot_c = scl.vinit_bot_c; -// unsigned int swath_height_l = rq_dlg_param.rq_l.swath_height; - swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; -// unsigned int dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; - dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; -// unsigned int meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; -// unsigned int meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; +// unsigned int swath_height_l = rq_dlg_param->rq_l.swath_height; + swath_width_ub_l = rq_dlg_param->rq_l.swath_width_ub; +// unsigned int dpte_bytes_per_row_ub_l = rq_dlg_param->rq_l.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_l = rq_dlg_param->rq_l.dpte_groups_per_row_ub; +// unsigned int meta_pte_bytes_per_frame_ub_l = rq_dlg_param->rq_l.meta_pte_bytes_per_frame_ub; +// unsigned int meta_bytes_per_row_ub_l = rq_dlg_param->rq_l.meta_bytes_per_row_ub; -// unsigned int swath_height_c = rq_dlg_param.rq_c.swath_height; - swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; - // dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; - dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; +// unsigned int swath_height_c = rq_dlg_param->rq_c.swath_height; + swath_width_ub_c = rq_dlg_param->rq_c.swath_width_ub; + // dpte_bytes_per_row_ub_c = rq_dlg_param->rq_c.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_c = rq_dlg_param->rq_c.dpte_groups_per_row_ub; - meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; - meta_chunks_per_row_ub_c = rq_dlg_param.rq_c.meta_chunks_per_row_ub; + meta_chunks_per_row_ub_l = rq_dlg_param->rq_l.meta_chunks_per_row_ub; + meta_chunks_per_row_ub_c = rq_dlg_param->rq_c.meta_chunks_per_row_ub; vupdate_offset = dst->vupdate_offset; vupdate_width = dst->vupdate_width; vready_offset = dst->vready_offset; @@ -1138,16 +1138,16 @@ static void dml20v2_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib, dml_print("DML_DLG: %s: vratio_pre_c=%3.2f\n", __func__, vratio_pre_c); // Active - req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; - req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; - meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; - meta_row_height_c = rq_dlg_param.rq_c.meta_row_height; + req_per_swath_ub_l = rq_dlg_param->rq_l.req_per_swath_ub; + req_per_swath_ub_c = rq_dlg_param->rq_c.req_per_swath_ub; + meta_row_height_l = rq_dlg_param->rq_l.meta_row_height; + meta_row_height_c = rq_dlg_param->rq_c.meta_row_height; swath_width_pixels_ub_l = 0; swath_width_pixels_ub_c = 0; scaler_rec_in_width_l = 0; scaler_rec_in_width_c = 0; - dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; - dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; + dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height; + dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height; if (mode_422) { swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element @@ -1585,15 +1585,15 @@ void dml20v2_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib, // system parameter calculation done dml_print("DML_DLG: Calculation for pipe[%d] start\n\n", pipe_idx); - dml20v2_rq_dlg_get_rq_params(mode_lib, &rq_param, e2e_pipe_param[pipe_idx].pipe.src); + dml20v2_rq_dlg_get_rq_params(mode_lib, &rq_param, &e2e_pipe_param[pipe_idx].pipe.src); dml20v2_rq_dlg_get_dlg_params(mode_lib, e2e_pipe_param, num_pipes, pipe_idx, dlg_regs, ttu_regs, - rq_param.dlg, - dlg_sys_param, + &rq_param.dlg, + &dlg_sys_param, cstate_en, pstate_en); dml_print("DML_DLG: Calculation for pipe[%d] end\n", pipe_idx); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c index 661fbb622824e..46c433c0bcb0f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c @@ -166,30 +166,30 @@ static void extract_rq_sizing_regs( static void extract_rq_regs( struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, - const display_rq_params_st rq_param) + const display_rq_params_st *rq_param) { unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param.sizing.rq_l); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param->sizing.rq_l); rq_regs->rq_regs_l.pte_row_height_linear = dml_floor( - dml_log2(rq_param.dlg.rq_l.dpte_row_height), + dml_log2(rq_param->dlg.rq_l.dpte_row_height), 1) - 3; - if (rq_param.yuv420) { - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param.sizing.rq_c); + if (rq_param->yuv420) { + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param->sizing.rq_c); rq_regs->rq_regs_c.pte_row_height_linear = dml_floor( - dml_log2(rq_param.dlg.rq_c.dpte_row_height), + dml_log2(rq_param->dlg.rq_c.dpte_row_height), 1) - 3; } - rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); - rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); + rq_regs->rq_regs_l.swath_height = dml_log2(rq_param->dlg.rq_l.swath_height); + rq_regs->rq_regs_c.swath_height = dml_log2(rq_param->dlg.rq_c.swath_height); // FIXME: take the max between luma, chroma chunk size? // okay for now, as we are setting chunk_bytes to 8kb anyways - if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { //32kb + if (rq_param->sizing.rq_l.chunk_bytes >= 32 * 1024) { //32kb rq_regs->drq_expansion_mode = 0; } else { rq_regs->drq_expansion_mode = 2; @@ -198,9 +198,9 @@ static void extract_rq_regs( rq_regs->mrq_expansion_mode = 1; rq_regs->crq_expansion_mode = 1; - if (rq_param.yuv420) { - if ((double) rq_param.misc.rq_l.stored_swath_bytes - / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { + if (rq_param->yuv420) { + if ((double) rq_param->misc.rq_l.stored_swath_bytes + / (double) rq_param->misc.rq_c.stored_swath_bytes <= 1.5) { detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); // half to chroma } else { detile_buf_plane1_addr = dml_round_to_multiple( @@ -215,7 +215,7 @@ static void extract_rq_regs( static void handle_det_buf_split( struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, - const display_pipe_source_params_st pipe_src_param) + const display_pipe_source_params_st *pipe_src_param) { unsigned int total_swath_bytes = 0; unsigned int swath_bytes_l = 0; @@ -224,8 +224,8 @@ static void handle_det_buf_split( unsigned int full_swath_bytes_packed_c = 0; bool req128_l = false; bool req128_c = false; - bool surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); - bool surf_vert = (pipe_src_param.source_scan == dm_vert); + bool surf_linear = (pipe_src_param->sw_mode == dm_sw_linear); + bool surf_vert = (pipe_src_param->source_scan == dm_vert); unsigned int log2_swath_height_l = 0; unsigned int log2_swath_height_c = 0; unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; @@ -806,7 +806,7 @@ static void dml_rq_dlg_get_rq_params( } // calculate how to split the det buffer space between luma and chroma - handle_det_buf_split(mode_lib, rq_param, pipe_param->src); + handle_det_buf_split(mode_lib, rq_param, &pipe_param->src); print__rq_params_st(mode_lib, rq_param); } @@ -819,7 +819,7 @@ void dml21_rq_dlg_get_rq_reg( memset(rq_regs, 0, sizeof(*rq_regs)); dml_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param); - extract_rq_regs(mode_lib, rq_regs, rq_param); + extract_rq_regs(mode_lib, rq_regs, &rq_param); print__rq_regs_st(mode_lib, rq_regs); } @@ -833,8 +833,8 @@ static void dml_rq_dlg_get_dlg_params( const unsigned int pipe_idx, display_dlg_regs_st *disp_dlg_regs, display_ttu_regs_st *disp_ttu_regs, - const display_rq_dlg_params_st rq_dlg_param, - const display_dlg_sys_params_st dlg_sys_param, + const display_rq_dlg_params_st *rq_dlg_param, + const display_dlg_sys_params_st *dlg_sys_param, const bool cstate_en, const bool pstate_en) { @@ -981,7 +981,7 @@ static void dml_rq_dlg_get_dlg_params( * (double) ref_freq_to_pix_freq); ASSERT(disp_dlg_regs->refcyc_h_blank_end < (unsigned int)dml_pow(2, 13)); - min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; + min_dcfclk_mhz = dlg_sys_param->deepsleep_dcfclk_mhz; t_calc_us = get_tcalc(mode_lib, e2e_pipe_param, num_pipes); min_ttu_vblank = get_min_ttu_vblank(mode_lib, e2e_pipe_param, num_pipes, pipe_idx); @@ -1042,13 +1042,13 @@ static void dml_rq_dlg_get_dlg_params( scl_enable = scl->scl_enable; line_time_in_us = (htotal / pclk_freq_in_mhz); - swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; - dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; - swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; - dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; + swath_width_ub_l = rq_dlg_param->rq_l.swath_width_ub; + dpte_groups_per_row_ub_l = rq_dlg_param->rq_l.dpte_groups_per_row_ub; + swath_width_ub_c = rq_dlg_param->rq_c.swath_width_ub; + dpte_groups_per_row_ub_c = rq_dlg_param->rq_c.dpte_groups_per_row_ub; - meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; - meta_chunks_per_row_ub_c = rq_dlg_param.rq_c.meta_chunks_per_row_ub; + meta_chunks_per_row_ub_l = rq_dlg_param->rq_l.meta_chunks_per_row_ub; + meta_chunks_per_row_ub_c = rq_dlg_param->rq_c.meta_chunks_per_row_ub; vupdate_offset = dst->vupdate_offset; vupdate_width = dst->vupdate_width; vready_offset = dst->vready_offset; @@ -1189,16 +1189,16 @@ static void dml_rq_dlg_get_dlg_params( dml_print("DML_DLG: %s: vratio_pre_c=%3.2f\n", __func__, vratio_pre_c); // Active - req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; - req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; - meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; - meta_row_height_c = rq_dlg_param.rq_c.meta_row_height; + req_per_swath_ub_l = rq_dlg_param->rq_l.req_per_swath_ub; + req_per_swath_ub_c = rq_dlg_param->rq_c.req_per_swath_ub; + meta_row_height_l = rq_dlg_param->rq_l.meta_row_height; + meta_row_height_c = rq_dlg_param->rq_c.meta_row_height; swath_width_pixels_ub_l = 0; swath_width_pixels_ub_c = 0; scaler_rec_in_width_l = 0; scaler_rec_in_width_c = 0; - dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; - dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; + dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height; + dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height; if (mode_422) { swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element @@ -1704,8 +1704,8 @@ void dml21_rq_dlg_get_dlg_reg( pipe_idx, dlg_regs, ttu_regs, - rq_param.dlg, - dlg_sys_param, + &rq_param.dlg, + &dlg_sys_param, cstate_en, pstate_en); dml_print("DML_DLG: Calculation for pipe[%d] end\n", pipe_idx); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c index 1535b01a8c5d8..aef8542700544 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c @@ -113,28 +113,28 @@ static void extract_rq_sizing_regs(struct display_mode_lib *mode_lib, static void extract_rq_regs(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, - const display_rq_params_st rq_param) + const display_rq_params_st *rq_param) { unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param.sizing.rq_l); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param->sizing.rq_l); - rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_l.dpte_row_height), + rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param->dlg.rq_l.dpte_row_height), 1) - 3; - if (rq_param.yuv420) { - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param.sizing.rq_c); - rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_c.dpte_row_height), + if (rq_param->yuv420) { + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param->sizing.rq_c); + rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param->dlg.rq_c.dpte_row_height), 1) - 3; } - rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); - rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); + rq_regs->rq_regs_l.swath_height = dml_log2(rq_param->dlg.rq_l.swath_height); + rq_regs->rq_regs_c.swath_height = dml_log2(rq_param->dlg.rq_c.swath_height); // FIXME: take the max between luma, chroma chunk size? // okay for now, as we are setting chunk_bytes to 8kb anyways - if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024 || (rq_param.yuv420 && rq_param.sizing.rq_c.chunk_bytes >= 32 * 1024)) { //32kb + if (rq_param->sizing.rq_l.chunk_bytes >= 32 * 1024 || (rq_param->yuv420 && rq_param->sizing.rq_c.chunk_bytes >= 32 * 1024)) { //32kb rq_regs->drq_expansion_mode = 0; } else { rq_regs->drq_expansion_mode = 2; @@ -143,9 +143,9 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib, rq_regs->mrq_expansion_mode = 1; rq_regs->crq_expansion_mode = 1; - if (rq_param.yuv420) { - if ((double)rq_param.misc.rq_l.stored_swath_bytes - / (double)rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { + if (rq_param->yuv420) { + if ((double)rq_param->misc.rq_l.stored_swath_bytes + / (double)rq_param->misc.rq_c.stored_swath_bytes <= 1.5) { detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); // half to chroma } else { detile_buf_plane1_addr = dml_round_to_multiple((unsigned int)((2.0 * detile_buf_size_in_bytes) / 3.0), @@ -158,7 +158,7 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib, static void handle_det_buf_split(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, - const display_pipe_source_params_st pipe_src_param) + const display_pipe_source_params_st *pipe_src_param) { unsigned int total_swath_bytes = 0; unsigned int swath_bytes_l = 0; @@ -167,8 +167,8 @@ static void handle_det_buf_split(struct display_mode_lib *mode_lib, unsigned int full_swath_bytes_packed_c = 0; bool req128_l = false; bool req128_c = false; - bool surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); - bool surf_vert = (pipe_src_param.source_scan == dm_vert); + bool surf_linear = (pipe_src_param->sw_mode == dm_sw_linear); + bool surf_vert = (pipe_src_param->source_scan == dm_vert); unsigned int log2_swath_height_l = 0; unsigned int log2_swath_height_c = 0; unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; @@ -871,7 +871,7 @@ static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, } // calculate how to split the det buffer space between luma and chroma - handle_det_buf_split(mode_lib, rq_param, pipe_param->src); + handle_det_buf_split(mode_lib, rq_param, &pipe_param->src); print__rq_params_st(mode_lib, rq_param); } @@ -883,7 +883,7 @@ void dml30_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, memset(rq_regs, 0, sizeof(*rq_regs)); dml_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param); - extract_rq_regs(mode_lib, rq_regs, rq_param); + extract_rq_regs(mode_lib, rq_regs, &rq_param); print__rq_regs_st(mode_lib, rq_regs); } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c index 442abae4bc8c8..e0fecf127bd5a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c @@ -196,26 +196,26 @@ static void extract_rq_sizing_regs(struct display_mode_lib *mode_lib, display_da rq_regs->mpte_group_size = dml_log2(rq_sizing->mpte_group_bytes) - 6; } -static void extract_rq_regs(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, const display_rq_params_st rq_param) +static void extract_rq_regs(struct display_mode_lib *mode_lib, display_rq_regs_st *rq_regs, const display_rq_params_st *rq_param) { unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param.sizing.rq_l); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param->sizing.rq_l); - rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_l.dpte_row_height), 1) - 3; + rq_regs->rq_regs_l.pte_row_height_linear = dml_floor(dml_log2(rq_param->dlg.rq_l.dpte_row_height), 1) - 3; - if (rq_param.yuv420) { - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param.sizing.rq_c); - rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param.dlg.rq_c.dpte_row_height), 1) - 3; + if (rq_param->yuv420) { + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param->sizing.rq_c); + rq_regs->rq_regs_c.pte_row_height_linear = dml_floor(dml_log2(rq_param->dlg.rq_c.dpte_row_height), 1) - 3; } - rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); - rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); + rq_regs->rq_regs_l.swath_height = dml_log2(rq_param->dlg.rq_l.swath_height); + rq_regs->rq_regs_c.swath_height = dml_log2(rq_param->dlg.rq_c.swath_height); // FIXME: take the max between luma, chroma chunk size? // okay for now, as we are setting chunk_bytes to 8kb anyways - if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024 || (rq_param.yuv420 && rq_param.sizing.rq_c.chunk_bytes >= 32 * 1024)) { //32kb + if (rq_param->sizing.rq_l.chunk_bytes >= 32 * 1024 || (rq_param->yuv420 && rq_param->sizing.rq_c.chunk_bytes >= 32 * 1024)) { //32kb rq_regs->drq_expansion_mode = 0; } else { rq_regs->drq_expansion_mode = 2; @@ -225,8 +225,8 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib, display_rq_regs_s rq_regs->crq_expansion_mode = 1; // Note: detile_buf_plane1_addr is in unit of 1KB - if (rq_param.yuv420) { - if ((double) rq_param.misc.rq_l.stored_swath_bytes / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { + if (rq_param->yuv420) { + if ((double) rq_param->misc.rq_l.stored_swath_bytes / (double) rq_param->misc.rq_c.stored_swath_bytes <= 1.5) { detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 1024.0); // half to chroma #ifdef __DML_RQ_DLG_CALC_DEBUG__ dml_print("DML_DLG: %s: detile_buf_plane1_addr = %0d (1/2 to chroma)\n", __func__, detile_buf_plane1_addr); @@ -244,14 +244,14 @@ static void extract_rq_regs(struct display_mode_lib *mode_lib, display_rq_regs_s dml_print("DML_DLG: %s: detile_buf_size_in_bytes = %0d\n", __func__, detile_buf_size_in_bytes); dml_print("DML_DLG: %s: detile_buf_plane1_addr = %0d\n", __func__, detile_buf_plane1_addr); dml_print("DML_DLG: %s: plane1_base_address = %0d\n", __func__, rq_regs->plane1_base_address); - dml_print("DML_DLG: %s: rq_l.stored_swath_bytes = %0d\n", __func__, rq_param.misc.rq_l.stored_swath_bytes); - dml_print("DML_DLG: %s: rq_c.stored_swath_bytes = %0d\n", __func__, rq_param.misc.rq_c.stored_swath_bytes); - dml_print("DML_DLG: %s: rq_l.swath_height = %0d\n", __func__, rq_param.dlg.rq_l.swath_height); - dml_print("DML_DLG: %s: rq_c.swath_height = %0d\n", __func__, rq_param.dlg.rq_c.swath_height); + dml_print("DML_DLG: %s: rq_l.stored_swath_bytes = %0d\n", __func__, rq_param->misc.rq_l.stored_swath_bytes); + dml_print("DML_DLG: %s: rq_c.stored_swath_bytes = %0d\n", __func__, rq_param->misc.rq_c.stored_swath_bytes); + dml_print("DML_DLG: %s: rq_l.swath_height = %0d\n", __func__, rq_param->dlg.rq_l.swath_height); + dml_print("DML_DLG: %s: rq_c.swath_height = %0d\n", __func__, rq_param->dlg.rq_c.swath_height); #endif } -static void handle_det_buf_split(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, const display_pipe_source_params_st pipe_src_param) +static void handle_det_buf_split(struct display_mode_lib *mode_lib, display_rq_params_st *rq_param, const display_pipe_source_params_st *pipe_src_param) { unsigned int total_swath_bytes = 0; unsigned int swath_bytes_l = 0; @@ -260,8 +260,8 @@ static void handle_det_buf_split(struct display_mode_lib *mode_lib, display_rq_p unsigned int full_swath_bytes_packed_c = 0; bool req128_l = 0; bool req128_c = 0; - bool surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); - bool surf_vert = (pipe_src_param.source_scan == dm_vert); + bool surf_linear = (pipe_src_param->sw_mode == dm_sw_linear); + bool surf_vert = (pipe_src_param->source_scan == dm_vert); unsigned int log2_swath_height_l = 0; unsigned int log2_swath_height_c = 0; unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; @@ -849,7 +849,7 @@ static void dml_rq_dlg_get_rq_params(struct display_mode_lib *mode_lib, display_ } // calculate how to split the det buffer space between luma and chroma - handle_det_buf_split(mode_lib, rq_param, pipe_param->src); + handle_det_buf_split(mode_lib, rq_param, &pipe_param->src); print__rq_params_st(mode_lib, rq_param); } @@ -859,7 +859,7 @@ void dml31_rq_dlg_get_rq_reg(struct display_mode_lib *mode_lib, display_rq_regs_ memset(rq_regs, 0, sizeof(*rq_regs)); dml_rq_dlg_get_rq_params(mode_lib, &rq_param, pipe_param); - extract_rq_regs(mode_lib, rq_regs, rq_param); + extract_rq_regs(mode_lib, rq_regs, &rq_param); print__rq_regs_st(mode_lib, rq_regs); } @@ -943,8 +943,8 @@ static void dml_rq_dlg_get_dlg_params( const unsigned int pipe_idx, display_dlg_regs_st *disp_dlg_regs, display_ttu_regs_st *disp_ttu_regs, - const display_rq_dlg_params_st rq_dlg_param, - const display_dlg_sys_params_st dlg_sys_param, + const display_rq_dlg_params_st *rq_dlg_param, + const display_dlg_sys_params_st *dlg_sys_param, const bool cstate_en, const bool pstate_en, const bool vm_en, @@ -1112,13 +1112,13 @@ static void dml_rq_dlg_get_dlg_params( vratio_c = scl->vscl_ratio_c; scl_enable = scl->scl_enable; - swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; - dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; - swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; - dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; + swath_width_ub_l = rq_dlg_param->rq_l.swath_width_ub; + dpte_groups_per_row_ub_l = rq_dlg_param->rq_l.dpte_groups_per_row_ub; + swath_width_ub_c = rq_dlg_param->rq_c.swath_width_ub; + dpte_groups_per_row_ub_c = rq_dlg_param->rq_c.dpte_groups_per_row_ub; - meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; - meta_chunks_per_row_ub_c = rq_dlg_param.rq_c.meta_chunks_per_row_ub; + meta_chunks_per_row_ub_l = rq_dlg_param->rq_l.meta_chunks_per_row_ub; + meta_chunks_per_row_ub_c = rq_dlg_param->rq_c.meta_chunks_per_row_ub; vupdate_offset = dst->vupdate_offset; vupdate_width = dst->vupdate_width; vready_offset = dst->vready_offset; @@ -1239,16 +1239,16 @@ static void dml_rq_dlg_get_dlg_params( dml_print("DML_DLG: %s: vratio_pre_c = %3.2f\n", __func__, vratio_pre_c); // Active - req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; - req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; - meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; - meta_row_height_c = rq_dlg_param.rq_c.meta_row_height; + req_per_swath_ub_l = rq_dlg_param->rq_l.req_per_swath_ub; + req_per_swath_ub_c = rq_dlg_param->rq_c.req_per_swath_ub; + meta_row_height_l = rq_dlg_param->rq_l.meta_row_height; + meta_row_height_c = rq_dlg_param->rq_c.meta_row_height; swath_width_pixels_ub_l = 0; swath_width_pixels_ub_c = 0; scaler_rec_in_width_l = 0; scaler_rec_in_width_c = 0; - dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; - dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; + dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height; + dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height; if (mode_422) { swath_width_pixels_ub_l = swath_width_ub_l * 2; // *2 for 2 pixel per element @@ -1712,8 +1712,8 @@ void dml31_rq_dlg_get_dlg_reg( pipe_idx, dlg_regs, ttu_regs, - rq_param.dlg, - dlg_sys_param, + &rq_param.dlg, + &dlg_sys_param, cstate_en, pstate_en, vm_en, diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c index 9bde3f9614098..59dc2c5b58dd7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c @@ -231,22 +231,22 @@ static void extract_rq_sizing_regs( void dml1_extract_rq_regs( struct display_mode_lib *mode_lib, struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_rq_params_st rq_param) + const struct _vcs_dpi_display_rq_params_st *rq_param) { unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; unsigned int detile_buf_plane1_addr = 0; - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param.sizing.rq_l); - if (rq_param.yuv420) - extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param.sizing.rq_c); + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_l), &rq_param->sizing.rq_l); + if (rq_param->yuv420) + extract_rq_sizing_regs(mode_lib, &(rq_regs->rq_regs_c), &rq_param->sizing.rq_c); - rq_regs->rq_regs_l.swath_height = dml_log2(rq_param.dlg.rq_l.swath_height); - rq_regs->rq_regs_c.swath_height = dml_log2(rq_param.dlg.rq_c.swath_height); + rq_regs->rq_regs_l.swath_height = dml_log2(rq_param->dlg.rq_l.swath_height); + rq_regs->rq_regs_c.swath_height = dml_log2(rq_param->dlg.rq_c.swath_height); /* TODO: take the max between luma, chroma chunk size? * okay for now, as we are setting chunk_bytes to 8kb anyways */ - if (rq_param.sizing.rq_l.chunk_bytes >= 32 * 1024) { /*32kb */ + if (rq_param->sizing.rq_l.chunk_bytes >= 32 * 1024) { /*32kb */ rq_regs->drq_expansion_mode = 0; } else { rq_regs->drq_expansion_mode = 2; @@ -255,9 +255,9 @@ void dml1_extract_rq_regs( rq_regs->mrq_expansion_mode = 1; rq_regs->crq_expansion_mode = 1; - if (rq_param.yuv420) { - if ((double) rq_param.misc.rq_l.stored_swath_bytes - / (double) rq_param.misc.rq_c.stored_swath_bytes <= 1.5) { + if (rq_param->yuv420) { + if ((double) rq_param->misc.rq_l.stored_swath_bytes + / (double) rq_param->misc.rq_c.stored_swath_bytes <= 1.5) { detile_buf_plane1_addr = (detile_buf_size_in_bytes / 2.0 / 64.0); /* half to chroma */ } else { detile_buf_plane1_addr = dml_round_to_multiple( @@ -272,7 +272,7 @@ void dml1_extract_rq_regs( static void handle_det_buf_split( struct display_mode_lib *mode_lib, struct _vcs_dpi_display_rq_params_st *rq_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) + const struct _vcs_dpi_display_pipe_source_params_st *pipe_src_param) { unsigned int total_swath_bytes = 0; unsigned int swath_bytes_l = 0; @@ -281,8 +281,8 @@ static void handle_det_buf_split( unsigned int full_swath_bytes_packed_c = 0; bool req128_l = 0; bool req128_c = 0; - bool surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); - bool surf_vert = (pipe_src_param.source_scan == dm_vert); + bool surf_linear = (pipe_src_param->sw_mode == dm_sw_linear); + bool surf_vert = (pipe_src_param->source_scan == dm_vert); unsigned int log2_swath_height_l = 0; unsigned int log2_swath_height_c = 0; unsigned int detile_buf_size_in_bytes = mode_lib->ip.det_buffer_size_kbytes * 1024; @@ -556,7 +556,7 @@ static void get_surf_rq_param( struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing_param, struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param, struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param, + const struct _vcs_dpi_display_pipe_source_params_st *pipe_src_param, bool is_chroma) { bool mode_422 = 0; @@ -622,15 +622,15 @@ static void get_surf_rq_param( /* TODO check if ppe apply for both luma and chroma in 422 case */ if (is_chroma) { - vp_width = pipe_src_param.viewport_width_c / ppe; - vp_height = pipe_src_param.viewport_height_c; - data_pitch = pipe_src_param.data_pitch_c; - meta_pitch = pipe_src_param.meta_pitch_c; + vp_width = pipe_src_param->viewport_width_c / ppe; + vp_height = pipe_src_param->viewport_height_c; + data_pitch = pipe_src_param->data_pitch_c; + meta_pitch = pipe_src_param->meta_pitch_c; } else { - vp_width = pipe_src_param.viewport_width / ppe; - vp_height = pipe_src_param.viewport_height; - data_pitch = pipe_src_param.data_pitch; - meta_pitch = pipe_src_param.meta_pitch; + vp_width = pipe_src_param->viewport_width / ppe; + vp_height = pipe_src_param->viewport_height; + data_pitch = pipe_src_param->data_pitch; + meta_pitch = pipe_src_param->meta_pitch; } rq_sizing_param->chunk_bytes = 8192; @@ -645,11 +645,11 @@ static void get_surf_rq_param( rq_sizing_param->mpte_group_bytes = 2048; - surf_linear = (pipe_src_param.sw_mode == dm_sw_linear); - surf_vert = (pipe_src_param.source_scan == dm_vert); + surf_linear = (pipe_src_param->sw_mode == dm_sw_linear); + surf_vert = (pipe_src_param->source_scan == dm_vert); bytes_per_element = get_bytes_per_element( - (enum source_format_class) pipe_src_param.source_format, + (enum source_format_class) pipe_src_param->source_format, is_chroma); log2_bytes_per_element = dml_log2(bytes_per_element); blk256_width = 0; @@ -671,7 +671,7 @@ static void get_surf_rq_param( log2_blk256_height = dml_log2((double) blk256_height); blk_bytes = surf_linear ? 256 : get_blk_size_bytes( - (enum source_macro_tile_size) pipe_src_param.macro_tile_size); + (enum source_macro_tile_size) pipe_src_param->macro_tile_size); log2_blk_bytes = dml_log2((double) blk_bytes); log2_blk_height = 0; log2_blk_width = 0; @@ -682,7 +682,7 @@ static void get_surf_rq_param( * "/2" is like square root * blk is vertical biased */ - if (pipe_src_param.sw_mode != dm_sw_linear) + if (pipe_src_param->sw_mode != dm_sw_linear) log2_blk_height = log2_blk256_height + dml_ceil((double) (log2_blk_bytes - 8) / 2.0, 1); else @@ -930,10 +930,10 @@ static void get_surf_rq_param( &func_meta_row_height, vp_width, data_pitch, - pipe_src_param.source_format, - pipe_src_param.sw_mode, - pipe_src_param.macro_tile_size, - pipe_src_param.source_scan, + pipe_src_param->source_format, + pipe_src_param->sw_mode, + pipe_src_param->macro_tile_size, + pipe_src_param->source_scan, is_chroma); /* Just a check to make sure this function and the new one give the same @@ -960,12 +960,12 @@ static void get_surf_rq_param( void dml1_rq_dlg_get_rq_params( struct display_mode_lib *mode_lib, struct _vcs_dpi_display_rq_params_st *rq_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param) + const struct _vcs_dpi_display_pipe_source_params_st *pipe_src_param) { /* get param for luma surface */ - rq_param->yuv420 = pipe_src_param.source_format == dm_420_8 - || pipe_src_param.source_format == dm_420_10; - rq_param->yuv420_10bpc = pipe_src_param.source_format == dm_420_10; + rq_param->yuv420 = pipe_src_param->source_format == dm_420_8 + || pipe_src_param->source_format == dm_420_10; + rq_param->yuv420_10bpc = pipe_src_param->source_format == dm_420_10; get_surf_rq_param( mode_lib, @@ -975,7 +975,7 @@ void dml1_rq_dlg_get_rq_params( pipe_src_param, 0); - if (is_dual_plane((enum source_format_class) pipe_src_param.source_format)) { + if (is_dual_plane((enum source_format_class) pipe_src_param->source_format)) { /* get param for chroma surface */ get_surf_rq_param( mode_lib, @@ -998,26 +998,26 @@ void dml1_rq_dlg_get_dlg_params( struct display_mode_lib *mode_lib, struct _vcs_dpi_display_dlg_regs_st *disp_dlg_regs, struct _vcs_dpi_display_ttu_regs_st *disp_ttu_regs, - const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const struct _vcs_dpi_display_rq_dlg_params_st *rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st *dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, const bool cstate_en, const bool pstate_en, const bool vm_en, const bool iflip_en) { /* Timing */ - unsigned int htotal = e2e_pipe_param.pipe.dest.htotal; - unsigned int hblank_end = e2e_pipe_param.pipe.dest.hblank_end; - unsigned int vblank_start = e2e_pipe_param.pipe.dest.vblank_start; - unsigned int vblank_end = e2e_pipe_param.pipe.dest.vblank_end; - bool interlaced = e2e_pipe_param.pipe.dest.interlaced; + unsigned int htotal = e2e_pipe_param->pipe.dest.htotal; + unsigned int hblank_end = e2e_pipe_param->pipe.dest.hblank_end; + unsigned int vblank_start = e2e_pipe_param->pipe.dest.vblank_start; + unsigned int vblank_end = e2e_pipe_param->pipe.dest.vblank_end; + bool interlaced = e2e_pipe_param->pipe.dest.interlaced; unsigned int min_vblank = mode_lib->ip.min_vblank_lines; - double pclk_freq_in_mhz = e2e_pipe_param.pipe.dest.pixel_rate_mhz; - double refclk_freq_in_mhz = e2e_pipe_param.clks_cfg.refclk_mhz; - double dppclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dppclk_mhz; - double dispclk_freq_in_mhz = e2e_pipe_param.clks_cfg.dispclk_mhz; + double pclk_freq_in_mhz = e2e_pipe_param->pipe.dest.pixel_rate_mhz; + double refclk_freq_in_mhz = e2e_pipe_param->clks_cfg.refclk_mhz; + double dppclk_freq_in_mhz = e2e_pipe_param->clks_cfg.dppclk_mhz; + double dispclk_freq_in_mhz = e2e_pipe_param->clks_cfg.dispclk_mhz; double ref_freq_to_pix_freq; double prefetch_xy_calc_in_dcfclk; @@ -1160,13 +1160,13 @@ void dml1_rq_dlg_get_dlg_params( disp_dlg_regs->dlg_vblank_end = interlaced ? (vblank_end / 2) : vblank_end; /* 15 bits */ prefetch_xy_calc_in_dcfclk = 24.0; /* TODO: ip_param */ - min_dcfclk_mhz = dlg_sys_param.deepsleep_dcfclk_mhz; + min_dcfclk_mhz = dlg_sys_param->deepsleep_dcfclk_mhz; t_calc_us = prefetch_xy_calc_in_dcfclk / min_dcfclk_mhz; - min_ttu_vblank = dlg_sys_param.t_urg_wm_us; + min_ttu_vblank = dlg_sys_param->t_urg_wm_us; if (cstate_en) - min_ttu_vblank = dml_max(dlg_sys_param.t_sr_wm_us, min_ttu_vblank); + min_ttu_vblank = dml_max(dlg_sys_param->t_sr_wm_us, min_ttu_vblank); if (pstate_en) - min_ttu_vblank = dml_max(dlg_sys_param.t_mclk_wm_us, min_ttu_vblank); + min_ttu_vblank = dml_max(dlg_sys_param->t_mclk_wm_us, min_ttu_vblank); min_ttu_vblank = min_ttu_vblank + t_calc_us; min_dst_y_ttu_vblank = min_ttu_vblank * pclk_freq_in_mhz / (double) htotal; @@ -1197,59 +1197,59 @@ void dml1_rq_dlg_get_dlg_params( /* ------------------------- */ /* Prefetch Calc */ /* Source */ - dcc_en = e2e_pipe_param.pipe.src.dcc; + dcc_en = e2e_pipe_param->pipe.src.dcc; dual_plane = is_dual_plane( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format); + (enum source_format_class) e2e_pipe_param->pipe.src.source_format); mode_422 = 0; /* TODO */ - access_dir = (e2e_pipe_param.pipe.src.source_scan == dm_vert); /* vp access direction: horizontal or vertical accessed */ + access_dir = (e2e_pipe_param->pipe.src.source_scan == dm_vert); /* vp access direction: horizontal or vertical accessed */ bytes_per_element_l = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + (enum source_format_class) e2e_pipe_param->pipe.src.source_format, 0); bytes_per_element_c = get_bytes_per_element( - (enum source_format_class) e2e_pipe_param.pipe.src.source_format, + (enum source_format_class) e2e_pipe_param->pipe.src.source_format, 1); - vp_height_l = e2e_pipe_param.pipe.src.viewport_height; - vp_width_l = e2e_pipe_param.pipe.src.viewport_width; - vp_height_c = e2e_pipe_param.pipe.src.viewport_height_c; - vp_width_c = e2e_pipe_param.pipe.src.viewport_width_c; + vp_height_l = e2e_pipe_param->pipe.src.viewport_height; + vp_width_l = e2e_pipe_param->pipe.src.viewport_width; + vp_height_c = e2e_pipe_param->pipe.src.viewport_height_c; + vp_width_c = e2e_pipe_param->pipe.src.viewport_width_c; /* Scaling */ - htaps_l = e2e_pipe_param.pipe.scale_taps.htaps; - htaps_c = e2e_pipe_param.pipe.scale_taps.htaps_c; - hratios_l = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; - hratios_c = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio_c; - vratio_l = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio; - vratio_c = e2e_pipe_param.pipe.scale_ratio_depth.vscl_ratio_c; + htaps_l = e2e_pipe_param->pipe.scale_taps.htaps; + htaps_c = e2e_pipe_param->pipe.scale_taps.htaps_c; + hratios_l = e2e_pipe_param->pipe.scale_ratio_depth.hscl_ratio; + hratios_c = e2e_pipe_param->pipe.scale_ratio_depth.hscl_ratio_c; + vratio_l = e2e_pipe_param->pipe.scale_ratio_depth.vscl_ratio; + vratio_c = e2e_pipe_param->pipe.scale_ratio_depth.vscl_ratio_c; line_time_in_us = (htotal / pclk_freq_in_mhz); - vinit_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit; - vinit_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_c; - vinit_bot_l = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot; - vinit_bot_c = e2e_pipe_param.pipe.scale_ratio_depth.vinit_bot_c; - - swath_height_l = rq_dlg_param.rq_l.swath_height; - swath_width_ub_l = rq_dlg_param.rq_l.swath_width_ub; - dpte_bytes_per_row_ub_l = rq_dlg_param.rq_l.dpte_bytes_per_row_ub; - dpte_groups_per_row_ub_l = rq_dlg_param.rq_l.dpte_groups_per_row_ub; - meta_pte_bytes_per_frame_ub_l = rq_dlg_param.rq_l.meta_pte_bytes_per_frame_ub; - meta_bytes_per_row_ub_l = rq_dlg_param.rq_l.meta_bytes_per_row_ub; - - swath_height_c = rq_dlg_param.rq_c.swath_height; - swath_width_ub_c = rq_dlg_param.rq_c.swath_width_ub; - dpte_bytes_per_row_ub_c = rq_dlg_param.rq_c.dpte_bytes_per_row_ub; - dpte_groups_per_row_ub_c = rq_dlg_param.rq_c.dpte_groups_per_row_ub; - - meta_chunks_per_row_ub_l = rq_dlg_param.rq_l.meta_chunks_per_row_ub; - vupdate_offset = e2e_pipe_param.pipe.dest.vupdate_offset; - vupdate_width = e2e_pipe_param.pipe.dest.vupdate_width; - vready_offset = e2e_pipe_param.pipe.dest.vready_offset; + vinit_l = e2e_pipe_param->pipe.scale_ratio_depth.vinit; + vinit_c = e2e_pipe_param->pipe.scale_ratio_depth.vinit_c; + vinit_bot_l = e2e_pipe_param->pipe.scale_ratio_depth.vinit_bot; + vinit_bot_c = e2e_pipe_param->pipe.scale_ratio_depth.vinit_bot_c; + + swath_height_l = rq_dlg_param->rq_l.swath_height; + swath_width_ub_l = rq_dlg_param->rq_l.swath_width_ub; + dpte_bytes_per_row_ub_l = rq_dlg_param->rq_l.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_l = rq_dlg_param->rq_l.dpte_groups_per_row_ub; + meta_pte_bytes_per_frame_ub_l = rq_dlg_param->rq_l.meta_pte_bytes_per_frame_ub; + meta_bytes_per_row_ub_l = rq_dlg_param->rq_l.meta_bytes_per_row_ub; + + swath_height_c = rq_dlg_param->rq_c.swath_height; + swath_width_ub_c = rq_dlg_param->rq_c.swath_width_ub; + dpte_bytes_per_row_ub_c = rq_dlg_param->rq_c.dpte_bytes_per_row_ub; + dpte_groups_per_row_ub_c = rq_dlg_param->rq_c.dpte_groups_per_row_ub; + + meta_chunks_per_row_ub_l = rq_dlg_param->rq_l.meta_chunks_per_row_ub; + vupdate_offset = e2e_pipe_param->pipe.dest.vupdate_offset; + vupdate_width = e2e_pipe_param->pipe.dest.vupdate_width; + vready_offset = e2e_pipe_param->pipe.dest.vready_offset; dppclk_delay_subtotal = mode_lib->ip.dppclk_delay_subtotal; dispclk_delay_subtotal = mode_lib->ip.dispclk_delay_subtotal; pixel_rate_delay_subtotal = dppclk_delay_subtotal * pclk_freq_in_mhz / dppclk_freq_in_mhz + dispclk_delay_subtotal * pclk_freq_in_mhz / dispclk_freq_in_mhz; - vstartup_start = e2e_pipe_param.pipe.dest.vstartup_start; + vstartup_start = e2e_pipe_param->pipe.dest.vstartup_start; if (interlaced) vstartup_start = vstartup_start / 2; @@ -1276,13 +1276,13 @@ void dml1_rq_dlg_get_dlg_params( dst_x_after_scaler = 0; dst_y_after_scaler = 0; - if (e2e_pipe_param.pipe.src.is_hsplit) + if (e2e_pipe_param->pipe.src.is_hsplit) dst_x_after_scaler = pixel_rate_delay_subtotal - + e2e_pipe_param.pipe.dest.recout_width; + + e2e_pipe_param->pipe.dest.recout_width; else dst_x_after_scaler = pixel_rate_delay_subtotal; - if (e2e_pipe_param.dout.output_format == dm_420) + if (e2e_pipe_param->dout.output_format == dm_420) dst_y_after_scaler = 1; else dst_y_after_scaler = 0; @@ -1334,7 +1334,7 @@ void dml1_rq_dlg_get_dlg_params( DTRACE( "DLG: %s: t_srx_delay_us = %3.2f", __func__, - (double) dlg_sys_param.t_srx_delay_us); + (double) dlg_sys_param->t_srx_delay_us); DTRACE("DLG: %s: line_time_in_us = %3.2f", __func__, (double) line_time_in_us); DTRACE("DLG: %s: vupdate_offset = %d", __func__, vupdate_offset); DTRACE("DLG: %s: vupdate_width = %d", __func__, vupdate_width); @@ -1408,12 +1408,12 @@ void dml1_rq_dlg_get_dlg_params( DTRACE("DLG: %s: dpte_row_bytes = %d", __func__, dpte_row_bytes); prefetch_bw = (vm_bytes + 2 * dpte_row_bytes + 2 * meta_row_bytes + sw_bytes) / t_pre_us; - flip_bw = ((vm_bytes + dpte_row_bytes + meta_row_bytes) * dlg_sys_param.total_flip_bw) - / (double) dlg_sys_param.total_flip_bytes; + flip_bw = ((vm_bytes + dpte_row_bytes + meta_row_bytes) * dlg_sys_param->total_flip_bw) + / (double) dlg_sys_param->total_flip_bytes; t_vm_us = line_time_in_us / 4.0; if (vm_en && dcc_en) { t_vm_us = dml_max( - dlg_sys_param.t_extra_us, + dlg_sys_param->t_extra_us, dml_max((double) vm_bytes / prefetch_bw, t_vm_us)); if (iflip_en && !dual_plane) { @@ -1423,12 +1423,12 @@ void dml1_rq_dlg_get_dlg_params( } } - t_r0_us = dml_max(dlg_sys_param.t_extra_us - t_vm_us, line_time_in_us - t_vm_us); + t_r0_us = dml_max(dlg_sys_param->t_extra_us - t_vm_us, line_time_in_us - t_vm_us); if (vm_en || dcc_en) { t_r0_us = dml_max( (double) (dpte_row_bytes + meta_row_bytes) / prefetch_bw, - dlg_sys_param.t_extra_us); + dlg_sys_param->t_extra_us); t_r0_us = dml_max((double) (line_time_in_us - t_vm_us), t_r0_us); if (iflip_en && !dual_plane) { @@ -1550,15 +1550,15 @@ void dml1_rq_dlg_get_dlg_params( disp_dlg_regs->refcyc_per_meta_chunk_vblank_l;/* dcc for 4:2:0 is not supported in dcn1.0. assigned to be the same as _l for now */ /* Active */ - req_per_swath_ub_l = rq_dlg_param.rq_l.req_per_swath_ub; - req_per_swath_ub_c = rq_dlg_param.rq_c.req_per_swath_ub; - meta_row_height_l = rq_dlg_param.rq_l.meta_row_height; + req_per_swath_ub_l = rq_dlg_param->rq_l.req_per_swath_ub; + req_per_swath_ub_c = rq_dlg_param->rq_c.req_per_swath_ub; + meta_row_height_l = rq_dlg_param->rq_l.meta_row_height; swath_width_pixels_ub_l = 0; swath_width_pixels_ub_c = 0; scaler_rec_in_width_l = 0; scaler_rec_in_width_c = 0; - dpte_row_height_l = rq_dlg_param.rq_l.dpte_row_height; - dpte_row_height_c = rq_dlg_param.rq_c.dpte_row_height; + dpte_row_height_l = rq_dlg_param->rq_l.dpte_row_height; + dpte_row_height_c = rq_dlg_param->rq_c.dpte_row_height; disp_dlg_regs->dst_y_per_pte_row_nom_l = (unsigned int) ((double) dpte_row_height_l / (double) vratio_l * dml_pow(2, 2)); @@ -1650,14 +1650,14 @@ void dml1_rq_dlg_get_dlg_params( refcyc_per_req_delivery_cur0 = 0.; full_recout_width = 0; - if (e2e_pipe_param.pipe.src.is_hsplit) { - if (e2e_pipe_param.pipe.dest.full_recout_width == 0) { + if (e2e_pipe_param->pipe.src.is_hsplit) { + if (e2e_pipe_param->pipe.dest.full_recout_width == 0) { DTRACE("DLG: %s: Warningfull_recout_width not set in hsplit mode", __func__); - full_recout_width = e2e_pipe_param.pipe.dest.recout_width * 2; /* assume half split for dcn1 */ + full_recout_width = e2e_pipe_param->pipe.dest.recout_width * 2; /* assume half split for dcn1 */ } else - full_recout_width = e2e_pipe_param.pipe.dest.full_recout_width; + full_recout_width = e2e_pipe_param->pipe.dest.full_recout_width; } else - full_recout_width = e2e_pipe_param.pipe.dest.recout_width; + full_recout_width = e2e_pipe_param->pipe.dest.recout_width; refcyc_per_line_delivery_pre_l = get_refcyc_per_delivery( mode_lib, @@ -1824,9 +1824,9 @@ void dml1_rq_dlg_get_dlg_params( } /* TTU - Cursor */ - hratios_cur0 = e2e_pipe_param.pipe.scale_ratio_depth.hscl_ratio; - cur0_src_width = e2e_pipe_param.pipe.src.cur0_src_width; /* cursor source width */ - cur0_bpp = (enum cursor_bpp) e2e_pipe_param.pipe.src.cur0_bpp; + hratios_cur0 = e2e_pipe_param->pipe.scale_ratio_depth.hscl_ratio; + cur0_src_width = e2e_pipe_param->pipe.src.cur0_src_width; /* cursor source width */ + cur0_bpp = (enum cursor_bpp) e2e_pipe_param->pipe.src.cur0_bpp; cur0_req_size = 0; cur0_req_width = 0; cur0_width_ub = 0.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h index 9c06913ad7676..e19ee3bde45f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.h @@ -33,7 +33,7 @@ struct display_mode_lib; void dml1_extract_rq_regs( struct display_mode_lib *mode_lib, struct _vcs_dpi_display_rq_regs_st *rq_regs, - const struct _vcs_dpi_display_rq_params_st rq_param); + const struct _vcs_dpi_display_rq_params_st *rq_param); /* Function: dml_rq_dlg_get_rq_params * Calculate requestor related parameters that register definition agnostic * (i.e. this layer does try to separate real values from register definition) @@ -45,7 +45,7 @@ void dml1_extract_rq_regs( void dml1_rq_dlg_get_rq_params( struct display_mode_lib *mode_lib, struct _vcs_dpi_display_rq_params_st *rq_param, - const struct _vcs_dpi_display_pipe_source_params_st pipe_src_param); + const struct _vcs_dpi_display_pipe_source_params_st *pipe_src_param); /* Function: dml_rq_dlg_get_dlg_params @@ -55,9 +55,9 @@ void dml1_rq_dlg_get_dlg_params( struct display_mode_lib *mode_lib, struct _vcs_dpi_display_dlg_regs_st *dlg_regs, struct _vcs_dpi_display_ttu_regs_st *ttu_regs, - const struct _vcs_dpi_display_rq_dlg_params_st rq_dlg_param, - const struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param, - const struct _vcs_dpi_display_e2e_pipe_params_st e2e_pipe_param, + const struct _vcs_dpi_display_rq_dlg_params_st *rq_dlg_param, + const struct _vcs_dpi_display_dlg_sys_params_st *dlg_sys_param, + const struct _vcs_dpi_display_e2e_pipe_params_st *e2e_pipe_param, const bool cstate_en, const bool pstate_en, const bool vm_en, From 1f2fcc8183e372b5d8f0e00d3e42e5d6a4a6a336 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 7 Sep 2021 20:22:13 -0400 Subject: [PATCH 124/151] drm/amd/display: Allocate structs needed by dcn_bw_calc_rq_dlg_ttu in pipe_ctx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Why & How] dcn_bw_calc_rq_dlg_ttu uses a stack frame great than 1024. To solve this we could allocate the rq_param, dlg_sys_param, and input structs dynamically. Since this function is inside a kernel_fpu_begin()/end() call we want to avoid memory allocation. Instead it's much safer to pre-allocate these on the pipe_ctx. Signed-off-by: Harry Wentland Fixes: 3fe617ccafd6 ("Enable '-Werror' by default for all kernel builds") Cc: Nick Desaulniers Cc: Linus Torvalds Cc: amd-gfx@lists.freedesktop.org Cc: Linux Kernel Mailing List Cc: Arnd Bergmann Cc: Leo Li Cc: Alex Deucher Cc: Christian König Cc: Xinhui Pan Cc: Nathan Chancellor Cc: Guenter Roeck Cc: llvm@lists.linux.dev Acked-by: Christian König Build-tested-by: Nathan Chancellor Reviewed-by: Leo Li Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 61 ++++++++++--------- .../gpu/drm/amd/display/dc/inc/core_types.h | 3 + 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c index 8e3a9294be3ad..6b248cd2a461c 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c @@ -459,9 +459,9 @@ static void dcn_bw_calc_rq_dlg_ttu( struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &pipe->dlg_regs; struct _vcs_dpi_display_ttu_regs_st *ttu_regs = &pipe->ttu_regs; struct _vcs_dpi_display_rq_regs_st *rq_regs = &pipe->rq_regs; - struct _vcs_dpi_display_rq_params_st rq_param = {0}; - struct _vcs_dpi_display_dlg_sys_params_st dlg_sys_param = {0}; - struct _vcs_dpi_display_e2e_pipe_params_st input = { { { 0 } } }; + struct _vcs_dpi_display_rq_params_st *rq_param = &pipe->dml_rq_param; + struct _vcs_dpi_display_dlg_sys_params_st *dlg_sys_param = &pipe->dml_dlg_sys_param; + struct _vcs_dpi_display_e2e_pipe_params_st *input = &pipe->dml_input; float total_active_bw = 0; float total_prefetch_bw = 0; int total_flip_bytes = 0; @@ -470,47 +470,50 @@ static void dcn_bw_calc_rq_dlg_ttu( memset(dlg_regs, 0, sizeof(*dlg_regs)); memset(ttu_regs, 0, sizeof(*ttu_regs)); memset(rq_regs, 0, sizeof(*rq_regs)); + memset(rq_param, 0, sizeof(*rq_param)); + memset(dlg_sys_param, 0, sizeof(*dlg_sys_param)); + memset(input, 0, sizeof(*input)); for (i = 0; i < number_of_planes; i++) { total_active_bw += v->read_bandwidth[i]; total_prefetch_bw += v->prefetch_bandwidth[i]; total_flip_bytes += v->total_immediate_flip_bytes[i]; } - dlg_sys_param.total_flip_bw = v->return_bw - dcn_bw_max2(total_active_bw, total_prefetch_bw); - if (dlg_sys_param.total_flip_bw < 0.0) - dlg_sys_param.total_flip_bw = 0; - - dlg_sys_param.t_mclk_wm_us = v->dram_clock_change_watermark; - dlg_sys_param.t_sr_wm_us = v->stutter_enter_plus_exit_watermark; - dlg_sys_param.t_urg_wm_us = v->urgent_watermark; - dlg_sys_param.t_extra_us = v->urgent_extra_latency; - dlg_sys_param.deepsleep_dcfclk_mhz = v->dcf_clk_deep_sleep; - dlg_sys_param.total_flip_bytes = total_flip_bytes; - - pipe_ctx_to_e2e_pipe_params(pipe, &input.pipe); - input.clks_cfg.dcfclk_mhz = v->dcfclk; - input.clks_cfg.dispclk_mhz = v->dispclk; - input.clks_cfg.dppclk_mhz = v->dppclk; - input.clks_cfg.refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0; - input.clks_cfg.socclk_mhz = v->socclk; - input.clks_cfg.voltage = v->voltage_level; + dlg_sys_param->total_flip_bw = v->return_bw - dcn_bw_max2(total_active_bw, total_prefetch_bw); + if (dlg_sys_param->total_flip_bw < 0.0) + dlg_sys_param->total_flip_bw = 0; + + dlg_sys_param->t_mclk_wm_us = v->dram_clock_change_watermark; + dlg_sys_param->t_sr_wm_us = v->stutter_enter_plus_exit_watermark; + dlg_sys_param->t_urg_wm_us = v->urgent_watermark; + dlg_sys_param->t_extra_us = v->urgent_extra_latency; + dlg_sys_param->deepsleep_dcfclk_mhz = v->dcf_clk_deep_sleep; + dlg_sys_param->total_flip_bytes = total_flip_bytes; + + pipe_ctx_to_e2e_pipe_params(pipe, &input->pipe); + input->clks_cfg.dcfclk_mhz = v->dcfclk; + input->clks_cfg.dispclk_mhz = v->dispclk; + input->clks_cfg.dppclk_mhz = v->dppclk; + input->clks_cfg.refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0; + input->clks_cfg.socclk_mhz = v->socclk; + input->clks_cfg.voltage = v->voltage_level; // dc->dml.logger = pool->base.logger; - input.dout.output_format = (v->output_format[in_idx] == dcn_bw_420) ? dm_420 : dm_444; - input.dout.output_type = (v->output[in_idx] == dcn_bw_hdmi) ? dm_hdmi : dm_dp; + input->dout.output_format = (v->output_format[in_idx] == dcn_bw_420) ? dm_420 : dm_444; + input->dout.output_type = (v->output[in_idx] == dcn_bw_hdmi) ? dm_hdmi : dm_dp; //input[in_idx].dout.output_standard; /*todo: soc->sr_enter_plus_exit_time??*/ - dlg_sys_param.t_srx_delay_us = dc->dcn_ip->dcfclk_cstate_latency / v->dcf_clk_deep_sleep; + dlg_sys_param->t_srx_delay_us = dc->dcn_ip->dcfclk_cstate_latency / v->dcf_clk_deep_sleep; - dml1_rq_dlg_get_rq_params(dml, &rq_param, &input.pipe.src); - dml1_extract_rq_regs(dml, rq_regs, &rq_param); + dml1_rq_dlg_get_rq_params(dml, rq_param, &input->pipe.src); + dml1_extract_rq_regs(dml, rq_regs, rq_param); dml1_rq_dlg_get_dlg_params( dml, dlg_regs, ttu_regs, - &rq_param.dlg, - &dlg_sys_param, - &input, + &rq_param->dlg, + dlg_sys_param, + input, true, true, v->pte_enable == dcn_bw_yes, diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index ed254c2771f08..0473cd28e8d17 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -375,6 +375,9 @@ struct pipe_ctx { struct _vcs_dpi_display_ttu_regs_st ttu_regs; struct _vcs_dpi_display_rq_regs_st rq_regs; struct _vcs_dpi_display_pipe_dest_params_st pipe_dlg_param; + struct _vcs_dpi_display_rq_params_st dml_rq_param; + struct _vcs_dpi_display_dlg_sys_params_st dml_dlg_sys_param; + struct _vcs_dpi_display_e2e_pipe_params_st dml_input; int det_buffer_size_kb; bool unbounded_req; #endif From a62427ef9b55d4b5aec2b08dc9b2d9719572bf57 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Mon, 13 Sep 2021 13:32:50 -0400 Subject: [PATCH 125/151] drm/amd/display: Reduce stack size for dml21_ModeSupportAndSystemConfigurationFull [Why & How] With Werror enabled in the kernel we were failing the clang build since dml21_ModeSupportAndSystemConfigurationFull's stack frame is 1064 when building with clang, and exceeding the default 1024 stack frame limit. The culprit seems to be the Pipe struct, so pull the relevant block out into its own sub-function. Signed-off-by: Harry Wentland Acked-by: Arnd Bergmann Reviewed-by: Leo Li Signed-off-by: Alex Deucher --- .../dc/dml/dcn21/display_mode_vba_21.c | 236 +++++++++--------- 1 file changed, 123 insertions(+), 113 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c index 4136eb8256cb5..8a7485e21d530 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c @@ -3394,6 +3394,127 @@ static unsigned int TruncToValidBPP( } } + +static noinline void CalculatePrefetchSchedulePerPlane( + struct display_mode_lib *mode_lib, + int i, + unsigned j, + unsigned k) +{ + struct vba_vars_st *locals = &mode_lib->vba; + Pipe myPipe; + HostVM myHostVM; + + if (mode_lib->vba.XFCEnabled[k] == true) { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = + CalculateRemoteSurfaceFlipDelay( + mode_lib, + mode_lib->vba.VRatio[k], + locals->SwathWidthYThisState[k], + dml_ceil(locals->BytePerPixelInDETY[k], 1.0), + mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], + mode_lib->vba.XFCTSlvVupdateOffset, + mode_lib->vba.XFCTSlvVupdateWidth, + mode_lib->vba.XFCTSlvVreadyOffset, + mode_lib->vba.XFCXBUFLatencyTolerance, + mode_lib->vba.XFCFillBWOverhead, + mode_lib->vba.XFCSlvChunkSize, + mode_lib->vba.XFCBusTransportTime, + mode_lib->vba.TimeCalc, + mode_lib->vba.TWait, + &mode_lib->vba.SrcActiveDrainRate, + &mode_lib->vba.TInitXFill, + &mode_lib->vba.TslvChk); + } else { + mode_lib->vba.XFCRemoteSurfaceFlipDelay = 0.0; + } + + myPipe.DPPCLK = locals->RequiredDPPCLK[i][j][k]; + myPipe.DISPCLK = locals->RequiredDISPCLK[i][j]; + myPipe.PixelClock = mode_lib->vba.PixelClock[k]; + myPipe.DCFCLKDeepSleep = mode_lib->vba.ProjectedDCFCLKDeepSleep[0][0]; + myPipe.DPPPerPlane = locals->NoOfDPP[i][j][k]; + myPipe.ScalerEnabled = mode_lib->vba.ScalerEnabled[k]; + myPipe.SourceScan = mode_lib->vba.SourceScan[k]; + myPipe.BlockWidth256BytesY = locals->Read256BlockWidthY[k]; + myPipe.BlockHeight256BytesY = locals->Read256BlockHeightY[k]; + myPipe.BlockWidth256BytesC = locals->Read256BlockWidthC[k]; + myPipe.BlockHeight256BytesC = locals->Read256BlockHeightC[k]; + myPipe.InterlaceEnable = mode_lib->vba.Interlace[k]; + myPipe.NumberOfCursors = mode_lib->vba.NumberOfCursors[k]; + myPipe.VBlank = mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k]; + myPipe.HTotal = mode_lib->vba.HTotal[k]; + + + myHostVM.Enable = mode_lib->vba.HostVMEnable; + myHostVM.MaxPageTableLevels = mode_lib->vba.HostVMMaxPageTableLevels; + myHostVM.CachedPageTableLevels = mode_lib->vba.HostVMCachedPageTableLevels; + + + mode_lib->vba.IsErrorResult[i][j][k] = CalculatePrefetchSchedule( + mode_lib, + mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData, + mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly, + &myPipe, + locals->DSCDelayPerState[i][k], + mode_lib->vba.DPPCLKDelaySubtotal, + mode_lib->vba.DPPCLKDelaySCL, + mode_lib->vba.DPPCLKDelaySCLLBOnly, + mode_lib->vba.DPPCLKDelayCNVCFormater, + mode_lib->vba.DPPCLKDelayCNVCCursor, + mode_lib->vba.DISPCLKDelaySubtotal, + locals->SwathWidthYThisState[k] / mode_lib->vba.HRatio[k], + mode_lib->vba.OutputFormat[k], + mode_lib->vba.MaxInterDCNTileRepeaters, + dml_min(mode_lib->vba.MaxVStartup, locals->MaximumVStartup[0][0][k]), + locals->MaximumVStartup[0][0][k], + mode_lib->vba.GPUVMMaxPageTableLevels, + mode_lib->vba.GPUVMEnable, + &myHostVM, + mode_lib->vba.DynamicMetadataEnable[k], + mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k], + mode_lib->vba.DynamicMetadataTransmittedBytes[k], + mode_lib->vba.DCCEnable[k], + mode_lib->vba.UrgentLatency, + mode_lib->vba.ExtraLatency, + mode_lib->vba.TimeCalc, + locals->PDEAndMetaPTEBytesPerFrame[0][0][k], + locals->MetaRowBytes[0][0][k], + locals->DPTEBytesPerRow[0][0][k], + locals->PrefetchLinesY[0][0][k], + locals->SwathWidthYThisState[k], + locals->BytePerPixelInDETY[k], + locals->PrefillY[k], + locals->MaxNumSwY[k], + locals->PrefetchLinesC[0][0][k], + locals->BytePerPixelInDETC[k], + locals->PrefillC[k], + locals->MaxNumSwC[k], + locals->SwathHeightYThisState[k], + locals->SwathHeightCThisState[k], + mode_lib->vba.TWait, + mode_lib->vba.XFCEnabled[k], + mode_lib->vba.XFCRemoteSurfaceFlipDelay, + mode_lib->vba.ProgressiveToInterlaceUnitInOPP, + &locals->dst_x_after_scaler, + &locals->dst_y_after_scaler, + &locals->LineTimesForPrefetch[k], + &locals->PrefetchBW[k], + &locals->LinesForMetaPTE[k], + &locals->LinesForMetaAndDPTERow[k], + &locals->VRatioPreY[i][j][k], + &locals->VRatioPreC[i][j][k], + &locals->RequiredPrefetchPixelDataBWLuma[i][j][k], + &locals->RequiredPrefetchPixelDataBWChroma[i][j][k], + &locals->VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, + &locals->Tno_bw[k], + &locals->prefetch_vmrow_bw[k], + locals->swath_width_luma_ub, + locals->swath_width_chroma_ub, + &mode_lib->vba.VUpdateOffsetPix[k], + &mode_lib->vba.VUpdateWidthPix[k], + &mode_lib->vba.VReadyOffsetPix[k]); +} void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib) { struct vba_vars_st *locals = &mode_lib->vba; @@ -4676,120 +4797,9 @@ void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l mode_lib->vba.DRAMClockChangeLatency, mode_lib->vba.UrgentLatency, mode_lib->vba.SREnterPlusExitTime); - for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { - Pipe myPipe; - HostVM myHostVM; - - if (mode_lib->vba.XFCEnabled[k] == true) { - mode_lib->vba.XFCRemoteSurfaceFlipDelay = - CalculateRemoteSurfaceFlipDelay( - mode_lib, - mode_lib->vba.VRatio[k], - locals->SwathWidthYThisState[k], - dml_ceil(locals->BytePerPixelInDETY[k], 1.0), - mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k], - mode_lib->vba.XFCTSlvVupdateOffset, - mode_lib->vba.XFCTSlvVupdateWidth, - mode_lib->vba.XFCTSlvVreadyOffset, - mode_lib->vba.XFCXBUFLatencyTolerance, - mode_lib->vba.XFCFillBWOverhead, - mode_lib->vba.XFCSlvChunkSize, - mode_lib->vba.XFCBusTransportTime, - mode_lib->vba.TimeCalc, - mode_lib->vba.TWait, - &mode_lib->vba.SrcActiveDrainRate, - &mode_lib->vba.TInitXFill, - &mode_lib->vba.TslvChk); - } else { - mode_lib->vba.XFCRemoteSurfaceFlipDelay = 0.0; - } + for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) + CalculatePrefetchSchedulePerPlane(mode_lib, i, j, k); - myPipe.DPPCLK = locals->RequiredDPPCLK[i][j][k]; - myPipe.DISPCLK = locals->RequiredDISPCLK[i][j]; - myPipe.PixelClock = mode_lib->vba.PixelClock[k]; - myPipe.DCFCLKDeepSleep = mode_lib->vba.ProjectedDCFCLKDeepSleep[0][0]; - myPipe.DPPPerPlane = locals->NoOfDPP[i][j][k]; - myPipe.ScalerEnabled = mode_lib->vba.ScalerEnabled[k]; - myPipe.SourceScan = mode_lib->vba.SourceScan[k]; - myPipe.BlockWidth256BytesY = locals->Read256BlockWidthY[k]; - myPipe.BlockHeight256BytesY = locals->Read256BlockHeightY[k]; - myPipe.BlockWidth256BytesC = locals->Read256BlockWidthC[k]; - myPipe.BlockHeight256BytesC = locals->Read256BlockHeightC[k]; - myPipe.InterlaceEnable = mode_lib->vba.Interlace[k]; - myPipe.NumberOfCursors = mode_lib->vba.NumberOfCursors[k]; - myPipe.VBlank = mode_lib->vba.VTotal[k] - mode_lib->vba.VActive[k]; - myPipe.HTotal = mode_lib->vba.HTotal[k]; - - - myHostVM.Enable = mode_lib->vba.HostVMEnable; - myHostVM.MaxPageTableLevels = mode_lib->vba.HostVMMaxPageTableLevels; - myHostVM.CachedPageTableLevels = mode_lib->vba.HostVMCachedPageTableLevels; - - - mode_lib->vba.IsErrorResult[i][j][k] = CalculatePrefetchSchedule( - mode_lib, - mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyPixelMixedWithVMData, - mode_lib->vba.PercentOfIdealDRAMFabricAndSDPPortBWReceivedAfterUrgLatencyVMDataOnly, - &myPipe, - locals->DSCDelayPerState[i][k], - mode_lib->vba.DPPCLKDelaySubtotal, - mode_lib->vba.DPPCLKDelaySCL, - mode_lib->vba.DPPCLKDelaySCLLBOnly, - mode_lib->vba.DPPCLKDelayCNVCFormater, - mode_lib->vba.DPPCLKDelayCNVCCursor, - mode_lib->vba.DISPCLKDelaySubtotal, - locals->SwathWidthYThisState[k] / mode_lib->vba.HRatio[k], - mode_lib->vba.OutputFormat[k], - mode_lib->vba.MaxInterDCNTileRepeaters, - dml_min(mode_lib->vba.MaxVStartup, locals->MaximumVStartup[0][0][k]), - locals->MaximumVStartup[0][0][k], - mode_lib->vba.GPUVMMaxPageTableLevels, - mode_lib->vba.GPUVMEnable, - &myHostVM, - mode_lib->vba.DynamicMetadataEnable[k], - mode_lib->vba.DynamicMetadataLinesBeforeActiveRequired[k], - mode_lib->vba.DynamicMetadataTransmittedBytes[k], - mode_lib->vba.DCCEnable[k], - mode_lib->vba.UrgentLatency, - mode_lib->vba.ExtraLatency, - mode_lib->vba.TimeCalc, - locals->PDEAndMetaPTEBytesPerFrame[0][0][k], - locals->MetaRowBytes[0][0][k], - locals->DPTEBytesPerRow[0][0][k], - locals->PrefetchLinesY[0][0][k], - locals->SwathWidthYThisState[k], - locals->BytePerPixelInDETY[k], - locals->PrefillY[k], - locals->MaxNumSwY[k], - locals->PrefetchLinesC[0][0][k], - locals->BytePerPixelInDETC[k], - locals->PrefillC[k], - locals->MaxNumSwC[k], - locals->SwathHeightYThisState[k], - locals->SwathHeightCThisState[k], - mode_lib->vba.TWait, - mode_lib->vba.XFCEnabled[k], - mode_lib->vba.XFCRemoteSurfaceFlipDelay, - mode_lib->vba.ProgressiveToInterlaceUnitInOPP, - &locals->dst_x_after_scaler, - &locals->dst_y_after_scaler, - &locals->LineTimesForPrefetch[k], - &locals->PrefetchBW[k], - &locals->LinesForMetaPTE[k], - &locals->LinesForMetaAndDPTERow[k], - &locals->VRatioPreY[i][j][k], - &locals->VRatioPreC[i][j][k], - &locals->RequiredPrefetchPixelDataBWLuma[i][j][k], - &locals->RequiredPrefetchPixelDataBWChroma[i][j][k], - &locals->VStartupRequiredWhenNotEnoughTimeForDynamicMetadata, - &locals->Tno_bw[k], - &locals->prefetch_vmrow_bw[k], - locals->swath_width_luma_ub, - locals->swath_width_chroma_ub, - &mode_lib->vba.VUpdateOffsetPix[k], - &mode_lib->vba.VUpdateWidthPix[k], - &mode_lib->vba.VReadyOffsetPix[k]); - } mode_lib->vba.MaximumReadBandwidthWithoutPrefetch = 0.0; mode_lib->vba.MaximumReadBandwidthWithPrefetch = 0.0; for (k = 0; k <= mode_lib->vba.NumberOfActivePlanes - 1; k++) { From 1bd3bc745e7f02f471fbf6e3f5f2ac5d788c9f39 Mon Sep 17 00:00:00 2001 From: Qingqing Zhuo Date: Wed, 25 Aug 2021 12:29:28 -0400 Subject: [PATCH 126/151] drm/amd/display: Extend w/a for hard hang on HPD to dcn20 [Why] HPD disable and enable sequences are not mutually exclusive on Linux. For HPDs that spans under 1s (i.e. HPD low = 1s), part of the disable sequence (specifically, a request to SMU to lower refclk) could come right before the call to PHY enablement, causing DMUB to access an irresponsive PHY and thus a hard hang on the system. [How] Disable 48mhz refclk off when there is any HPD status in connected state for dcn20. Reviewed-by: Hersen Wu Acked-by: Rodrigo Siqueira Signed-off-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- .../display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c | 12 ++++++++- .../display/dc/irq/dcn20/irq_service_dcn20.c | 25 +++++++++++++++++++ .../display/dc/irq/dcn20/irq_service_dcn20.h | 2 ++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c index 0d01aa9f15a62..315466f5aadeb 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c @@ -38,6 +38,8 @@ #include "clk/clk_11_0_0_offset.h" #include "clk/clk_11_0_0_sh_mask.h" +#include "irq/dcn20/irq_service_dcn20.h" + #undef FN #define FN(reg_name, field_name) \ clk_mgr->clk_mgr_shift->field_name, clk_mgr->clk_mgr_mask->field_name @@ -221,6 +223,8 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, bool force_reset = false; bool p_state_change_support; int total_plane_count; + int irq_src; + uint32_t hpd_state; if (dc->work_arounds.skip_clock_update) return; @@ -238,7 +242,13 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base, if (dc->res_pool->pp_smu) pp_smu = &dc->res_pool->pp_smu->nv_funcs; - if (display_count == 0) + for (irq_src = DC_IRQ_SOURCE_HPD1; irq_src <= DC_IRQ_SOURCE_HPD6; irq_src++) { + hpd_state = dal_get_hpd_state_dcn20(dc->res_pool->irqs, irq_src); + if (hpd_state) + break; + } + + if (display_count == 0 && !hpd_state) enter_display_off = true; if (enter_display_off == safe_to_lower) { diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c index c4b067d018956..49d87fe5c1678 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c @@ -132,6 +132,31 @@ enum dc_irq_source to_dal_irq_source_dcn20( } } +uint32_t dal_get_hpd_state_dcn20(struct irq_service *irq_service, enum dc_irq_source source) +{ + const struct irq_source_info *info; + uint32_t addr; + uint32_t value; + uint32_t current_status; + + info = find_irq_source_info(irq_service, source); + if (!info) + return 0; + + addr = info->status_reg; + if (!addr) + return 0; + + value = dm_read_reg(irq_service->ctx, addr); + current_status = + get_reg_field_value( + value, + HPD0_DC_HPD_INT_STATUS, + DC_HPD_SENSE); + + return current_status; +} + static bool hpd_ack( struct irq_service *irq_service, const struct irq_source_info *info) diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.h b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.h index aee4b37999f19..f60a203e71889 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.h +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.h @@ -31,4 +31,6 @@ struct irq_service *dal_irq_service_dcn20_create( struct irq_service_init_data *init_data); +uint32_t dal_get_hpd_state_dcn20(struct irq_service *irq_service, enum dc_irq_source source); + #endif From 13d463eced3c780711469eae8ad77e006728f191 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sat, 4 Sep 2021 11:58:21 -0400 Subject: [PATCH 127/151] drm/amd/display: [FW Promotion] Release 0.0.83 Acked-by: Rodrigo Siqueira Signed-off-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 2c4ec3cac70e8..1edc5bb4d6683 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -47,10 +47,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x3f002dea8 +#define DMUB_FW_VERSION_GIT_HASH 0xb24cbe3d #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 82 +#define DMUB_FW_VERSION_REVISION 83 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 From d51fc42adae665cd2ca16be3f46d1c2bbb668036 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 6 Sep 2021 20:42:16 -0400 Subject: [PATCH 128/151] drm/amd/display: 3.2.153 Acked-by: Rodrigo Siqueira Signed-off-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8897750bdaea0..1306dedc1a982 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -45,7 +45,7 @@ /* forward declaration */ struct aux_payload; -#define DC_VER "3.2.152" +#define DC_VER "3.2.153" #define MAX_SURFACES 3 #define MAX_PLANES 6 From 4b7786d87fb3adf3e534c4f1e4f824d8700b786b Mon Sep 17 00:00:00 2001 From: "Liu, Zhan" Date: Thu, 2 Sep 2021 15:08:29 -0400 Subject: [PATCH 129/151] drm/amd/display: Fix DCN3 B0 DP Alt Mapping [Why] DCN3 B0 has a mux, which redirects PHYC and PHYD to PHYF and PHYG. [How] Fix DIG mapping. Reviewed-by: Charlene Liu Acked-by: Rodrigo Siqueira Signed-off-by: Zhan Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 613d34bde7dd1..a823a64d02a57 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -1383,6 +1383,12 @@ static struct stream_encoder *dcn31_stream_encoder_create( return NULL; } + if (ctx->asic_id.chip_family == FAMILY_YELLOW_CARP && + ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) { + if ((eng_id == ENGINE_ID_DIGC) || (eng_id == ENGINE_ID_DIGD)) + eng_id = eng_id + 3; // For B0 only. C->F, D->G. + } + dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, vpg, afmt, &stream_enc_regs[eng_id], From 4de0bfe67bc98fb2a1115bc58ef3b9bc21717629 Mon Sep 17 00:00:00 2001 From: Jimmy Kizito Date: Wed, 25 Aug 2021 19:12:08 -0400 Subject: [PATCH 130/151] drm/amd/display: Fix link training fallback logic [Why] Link training should fail if stream bandwidth exceeds link bandwidth. [How] Correct fallback logic and use named variables to make intention clear. Reviewed-by: Meenakshikumar Somasundaram Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Signed-off-by: Jimmy Kizito Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 7ea5051093404..e3f102425fee6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2462,12 +2462,16 @@ bool perform_link_training_with_retries( if (type == dc_connection_none) break; } else if (do_fallback) { + uint32_t req_bw; + uint32_t link_bw; + decide_fallback_link_setting(*link_setting, ¤t_setting, status); /* Fail link training if reduced link bandwidth no longer meets * stream requirements. */ - if (dc_bandwidth_in_kbps_from_timing(&stream->timing) < - dc_link_bandwidth_kbps(link, ¤t_setting)) + req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing); + link_bw = dc_link_bandwidth_kbps(link, ¤t_setting); + if (req_bw > link_bw) break; } From b3492ed160768ad60ad6753269099213b6772a70 Mon Sep 17 00:00:00 2001 From: Jimmy Kizito Date: Sat, 28 Aug 2021 12:07:11 -0400 Subject: [PATCH 131/151] drm/amd/display: Fix concurrent dynamic encoder assignment [Why] Trying to enable multiple displays simultaneously exposed shortcomings with the algorithm for dynamic link encoder assignment. The main problems were: - Assuming stream order remained constant across states would sometimes lead to invalid DIG encoder assignment. - Incorrect logic for deciding whether or not a DIG could support a stream would also sometimes lead to invalid DIG encoder assignment. - Changes in encoder assignment were wholesale while updating of the pipe backend is incremental. This would lead to the hardware state not matching the software state even with valid encoder assignments. [How] The following changes fix the identified problems. - Use stream pointer rather than stream index to track streams across states. - Fix DIG compatibility check by examining the link signal type rather than the stream signal type. - Modify assignment algorithm to make incremental updates so software and hardware states remain coherent. Additionally: - Add assertions and an encoder assignment validation function link_enc_cfg_validate() to detect potential problems with encoder assignment closer to their root cause. - Reduce the frequency with which the assignment algorithm is executed. It should not be necessary for fast state validation. Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Signed-off-by: Jimmy Kizito Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- .../drm/amd/display/dc/core/dc_link_enc_cfg.c | 329 ++++++++++++++---- .../gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- .../drm/amd/display/dc/inc/hw/link_encoder.h | 1 + .../gpu/drm/amd/display/dc/inc/link_enc_cfg.h | 3 + 5 files changed, 260 insertions(+), 77 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index e3f102425fee6..2a58de375d8f8 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2384,7 +2384,7 @@ bool perform_link_training_with_retries( /* Dynamically assigned link encoders associated with stream rather than * link. */ - if (link->dc->res_pool->funcs->link_encs_assign) + if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign) link_enc = stream->link_enc; else link_enc = link->link_enc; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c index 49b17bbea8d1a..5536184fff46b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c @@ -35,78 +35,116 @@ static bool is_dig_link_enc_stream(struct dc_stream_state *stream) int i; /* Loop over created link encoder objects. */ - for (i = 0; i < stream->ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) { - link_enc = stream->ctx->dc->res_pool->link_encoders[i]; - - if (link_enc && - ((uint32_t)stream->signal & link_enc->output_signals)) { - if (dc_is_dp_signal(stream->signal)) { - /* DIGs do not support DP2.0 streams with 128b/132b encoding. */ - struct dc_link_settings link_settings = {0}; - - decide_link_settings(stream, &link_settings); - if ((link_settings.link_rate >= LINK_RATE_LOW) && - link_settings.link_rate <= LINK_RATE_HIGH3) { + if (stream) { + for (i = 0; i < stream->ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) { + link_enc = stream->ctx->dc->res_pool->link_encoders[i]; + + /* Need to check link signal type rather than stream signal type which may not + * yet match. + */ + if (link_enc && ((uint32_t)stream->link->connector_signal & link_enc->output_signals)) { + if (dc_is_dp_signal(stream->signal)) { + /* DIGs do not support DP2.0 streams with 128b/132b encoding. */ + struct dc_link_settings link_settings = {0}; + + decide_link_settings(stream, &link_settings); + if ((link_settings.link_rate >= LINK_RATE_LOW) && + link_settings.link_rate <= LINK_RATE_HIGH3) { + is_dig_stream = true; + break; + } + } else { is_dig_stream = true; break; } - } else { - is_dig_stream = true; - break; } } } - return is_dig_stream; } -/* Update DIG link encoder resource tracking variables in dc_state. */ -static void update_link_enc_assignment( +/* Return stream using DIG link encoder resource. NULL if unused. */ +static struct dc_stream_state *get_stream_using_link_enc( + struct dc_state *state, + enum engine_id eng_id) +{ + struct dc_stream_state *stream = NULL; + int i; + + for (i = 0; i < state->stream_count; i++) { + struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + + if ((assignment.valid == true) && (assignment.eng_id == eng_id)) { + stream = state->streams[i]; + break; + } + } + + return stream; +} + +static void remove_link_enc_assignment( struct dc_state *state, struct dc_stream_state *stream, - enum engine_id eng_id, - bool add_enc) + enum engine_id eng_id) { int eng_idx; - int stream_idx; int i; if (eng_id != ENGINE_ID_UNKNOWN) { eng_idx = eng_id - ENGINE_ID_DIGA; - stream_idx = -1; - /* Index of stream in dc_state used to update correct entry in + /* stream ptr of stream in dc_state used to update correct entry in * link_enc_assignments table. */ - for (i = 0; i < state->stream_count; i++) { - if (stream == state->streams[i]) { - stream_idx = i; + for (i = 0; i < MAX_PIPES; i++) { + struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + + if (assignment.valid && assignment.stream == stream) { + state->res_ctx.link_enc_assignments[i].valid = false; + /* Only add link encoder back to availability pool if not being + * used by any other stream (i.e. removing SST stream or last MST stream). + */ + if (get_stream_using_link_enc(state, eng_id) == NULL) + state->res_ctx.link_enc_avail[eng_idx] = eng_id; + stream->link_enc = NULL; break; } } + } +} + +static void add_link_enc_assignment( + struct dc_state *state, + struct dc_stream_state *stream, + enum engine_id eng_id) +{ + int eng_idx; + int i; + + if (eng_id != ENGINE_ID_UNKNOWN) { + eng_idx = eng_id - ENGINE_ID_DIGA; - /* Update link encoder assignments table, link encoder availability - * pool and link encoder assigned to stream in state. - * Add/remove encoder resource to/from stream. + /* stream ptr of stream in dc_state used to update correct entry in + * link_enc_assignments table. */ - if (stream_idx != -1) { - if (add_enc) { - state->res_ctx.link_enc_assignments[stream_idx] = (struct link_enc_assignment){ + for (i = 0; i < state->stream_count; i++) { + if (stream == state->streams[i]) { + state->res_ctx.link_enc_assignments[i] = (struct link_enc_assignment){ .valid = true, .ep_id = (struct display_endpoint_id) { .link_id = stream->link->link_id, .ep_type = stream->link->ep_type}, - .eng_id = eng_id}; + .eng_id = eng_id, + .stream = stream}; state->res_ctx.link_enc_avail[eng_idx] = ENGINE_ID_UNKNOWN; stream->link_enc = stream->ctx->dc->res_pool->link_encoders[eng_idx]; - } else { - state->res_ctx.link_enc_assignments[stream_idx].valid = false; - state->res_ctx.link_enc_avail[eng_idx] = eng_id; - stream->link_enc = NULL; + break; } - } else { - dm_output_to_console("%s: Stream not found in dc_state.\n", __func__); } + + /* Attempted to add an encoder assignment for a stream not in dc_state. */ + ASSERT(i != state->stream_count); } } @@ -127,30 +165,29 @@ static enum engine_id find_first_avail_link_enc( return eng_id; } -/* Return stream using DIG link encoder resource. NULL if unused. */ -static struct dc_stream_state *get_stream_using_link_enc( - struct dc_state *state, - enum engine_id eng_id) +static bool is_avail_link_enc(struct dc_state *state, enum engine_id eng_id) { - struct dc_stream_state *stream = NULL; - int stream_idx = -1; - int i; + bool is_avail = false; + int eng_idx = eng_id - ENGINE_ID_DIGA; - for (i = 0; i < state->stream_count; i++) { - struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + if (eng_id != ENGINE_ID_UNKNOWN && state->res_ctx.link_enc_avail[eng_idx] != ENGINE_ID_UNKNOWN) + is_avail = true; - if ((assignment.valid == true) && (assignment.eng_id == eng_id)) { - stream_idx = i; - break; - } - } + return is_avail; +} - if (stream_idx != -1) - stream = state->streams[stream_idx]; - else - dm_output_to_console("%s: No stream using DIG(%d).\n", __func__, eng_id); +/* Test for display_endpoint_id equality. */ +static bool are_ep_ids_equal(struct display_endpoint_id *lhs, struct display_endpoint_id *rhs) +{ + bool are_equal = false; - return stream; + if (lhs->link_id.id == rhs->link_id.id && + lhs->link_id.enum_id == rhs->link_id.enum_id && + lhs->link_id.type == rhs->link_id.type && + lhs->ep_type == rhs->ep_type) + are_equal = true; + + return are_equal; } void link_enc_cfg_init( @@ -175,11 +212,17 @@ void link_enc_cfg_link_encs_assign( { enum engine_id eng_id = ENGINE_ID_UNKNOWN; int i; + int j; + + ASSERT(state->stream_count == stream_count); /* Release DIG link encoder resources before running assignment algorithm. */ for (i = 0; i < stream_count; i++) dc->res_pool->funcs->link_enc_unassign(state, streams[i]); + for (i = 0; i < MAX_PIPES; i++) + ASSERT(state->res_ctx.link_enc_assignments[i].valid == false); + /* (a) Assign DIG link encoders to physical (unmappable) endpoints first. */ for (i = 0; i < stream_count; i++) { struct dc_stream_state *stream = streams[i]; @@ -191,26 +234,73 @@ void link_enc_cfg_link_encs_assign( /* Physical endpoints have a fixed mapping to DIG link encoders. */ if (!stream->link->is_dig_mapping_flexible) { eng_id = stream->link->eng_id; - update_link_enc_assignment(state, stream, eng_id, true); + add_link_enc_assignment(state, stream, eng_id); + } + } + + /* (b) Retain previous assignments for mappable endpoints if encoders still available. */ + eng_id = ENGINE_ID_UNKNOWN; + + if (state != dc->current_state) { + struct dc_state *prev_state = dc->current_state; + + for (i = 0; i < stream_count; i++) { + struct dc_stream_state *stream = state->streams[i]; + + /* Skip stream if not supported by DIG link encoder. */ + if (!is_dig_link_enc_stream(stream)) + continue; + + if (!stream->link->is_dig_mapping_flexible) + continue; + + for (j = 0; j < prev_state->stream_count; j++) { + struct dc_stream_state *prev_stream = prev_state->streams[j]; + + if (stream == prev_stream && stream->link == prev_stream->link && + prev_state->res_ctx.link_enc_assignments[j].valid) { + eng_id = prev_state->res_ctx.link_enc_assignments[j].eng_id; + if (is_avail_link_enc(state, eng_id)) + add_link_enc_assignment(state, stream, eng_id); + } + } } } - /* (b) Then assign encoders to mappable endpoints. */ + /* (c) Then assign encoders to remaining mappable endpoints. */ eng_id = ENGINE_ID_UNKNOWN; for (i = 0; i < stream_count; i++) { struct dc_stream_state *stream = streams[i]; /* Skip stream if not supported by DIG link encoder. */ - if (!is_dig_link_enc_stream(stream)) + if (!is_dig_link_enc_stream(stream)) { + ASSERT(stream->link->is_dig_mapping_flexible != true); continue; + } /* Mappable endpoints have a flexible mapping to DIG link encoders. */ if (stream->link->is_dig_mapping_flexible) { - eng_id = find_first_avail_link_enc(stream->ctx, state); - update_link_enc_assignment(state, stream, eng_id, true); + struct link_encoder *link_enc = NULL; + + /* Skip if encoder assignment retained in step (b) above. */ + if (stream->link_enc) + continue; + + /* For MST, multiple streams will share the same link / display + * endpoint. These streams should use the same link encoder + * assigned to that endpoint. + */ + link_enc = link_enc_cfg_get_link_enc_used_by_link(state, stream->link); + if (link_enc == NULL) + eng_id = find_first_avail_link_enc(stream->ctx, state); + else + eng_id = link_enc->preferred_engine; + add_link_enc_assignment(state, stream, eng_id); } } + + link_enc_cfg_validate(dc, state); } void link_enc_cfg_link_enc_unassign( @@ -226,7 +316,7 @@ void link_enc_cfg_link_enc_unassign( if (stream->link_enc) eng_id = stream->link_enc->preferred_engine; - update_link_enc_assignment(state, stream, eng_id, false); + remove_link_enc_assignment(state, stream, eng_id); } bool link_enc_cfg_is_transmitter_mappable( @@ -248,21 +338,18 @@ struct dc_link *link_enc_cfg_get_link_using_link_enc( enum engine_id eng_id) { struct dc_link *link = NULL; - int stream_idx = -1; int i; for (i = 0; i < state->stream_count; i++) { struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; if ((assignment.valid == true) && (assignment.eng_id == eng_id)) { - stream_idx = i; + link = state->streams[i]->link; break; } } - if (stream_idx != -1) - link = state->streams[stream_idx]->link; - else + if (link == NULL) dm_output_to_console("%s: No link using DIG(%d).\n", __func__, eng_id); return link; @@ -282,13 +369,9 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_link( for (i = 0; i < state->stream_count; i++) { struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; - if (assignment.valid == true && - assignment.ep_id.link_id.id == ep_id.link_id.id && - assignment.ep_id.link_id.enum_id == ep_id.link_id.enum_id && - assignment.ep_id.link_id.type == ep_id.link_id.type && - assignment.ep_id.ep_type == ep_id.ep_type) { + + if (assignment.valid == true && are_ep_ids_equal(&assignment.ep_id, &ep_id)) link_enc = link->dc->res_pool->link_encoders[assignment.eng_id - ENGINE_ID_DIGA]; - } } return link_enc; @@ -318,3 +401,99 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream( return link_enc; } + +bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state) +{ + bool is_valid = false; + bool valid_entries = true; + bool valid_stream_ptrs = true; + bool valid_uniqueness = true; + bool valid_avail = true; + bool valid_streams = true; + int i, j; + uint8_t valid_count = 0; + uint8_t dig_stream_count = 0; + int matching_stream_ptrs = 0; + int eng_ids_per_ep_id[MAX_PIPES] = {0}; + + /* (1) No. valid entries same as stream count. */ + for (i = 0; i < MAX_PIPES; i++) { + struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + + if (assignment.valid) + valid_count++; + + if (is_dig_link_enc_stream(state->streams[i])) + dig_stream_count++; + } + if (valid_count != dig_stream_count) + valid_entries = false; + + /* (2) Matching stream ptrs. */ + for (i = 0; i < MAX_PIPES; i++) { + struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + + if (assignment.valid) { + if (assignment.stream == state->streams[i]) + matching_stream_ptrs++; + else + valid_stream_ptrs = false; + } + } + + /* (3) Each endpoint assigned unique encoder. */ + for (i = 0; i < MAX_PIPES; i++) { + struct link_enc_assignment assignment_i = state->res_ctx.link_enc_assignments[i]; + + if (assignment_i.valid) { + struct display_endpoint_id ep_id_i = assignment_i.ep_id; + + eng_ids_per_ep_id[i]++; + for (j = 0; j < MAX_PIPES; j++) { + struct link_enc_assignment assignment_j = state->res_ctx.link_enc_assignments[j]; + + if (j == i) + continue; + + if (assignment_j.valid) { + struct display_endpoint_id ep_id_j = assignment_j.ep_id; + + if (are_ep_ids_equal(&ep_id_i, &ep_id_j) && + assignment_i.eng_id != assignment_j.eng_id) { + valid_uniqueness = false; + eng_ids_per_ep_id[i]++; + } + } + } + } + } + + /* (4) Assigned encoders not in available pool. */ + for (i = 0; i < MAX_PIPES; i++) { + struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + + if (assignment.valid) { + for (j = 0; j < dc->res_pool->res_cap->num_dig_link_enc; j++) { + if (state->res_ctx.link_enc_avail[j] == assignment.eng_id) { + valid_avail = false; + break; + } + } + } + } + + /* (5) All streams have valid link encoders. */ + for (i = 0; i < state->stream_count; i++) { + struct dc_stream_state *stream = state->streams[i]; + + if (is_dig_link_enc_stream(stream) && stream->link_enc == NULL) { + valid_streams = false; + break; + } + } + + is_valid = valid_entries && valid_stream_ptrs && valid_uniqueness && valid_avail && valid_streams; + ASSERT(is_valid); + + return is_valid; +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 8766b124d4b01..b4e986f736ada 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2241,7 +2241,7 @@ enum dc_status dc_validate_global_state( * Update link encoder to stream assignment. * TODO: Split out reason allocation from validation. */ - if (dc->res_pool->funcs->link_encs_assign) + if (dc->res_pool->funcs->link_encs_assign && fast_validate == false) dc->res_pool->funcs->link_encs_assign( dc, new_ctx, new_ctx->streams, new_ctx->stream_count); #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 5084289810e22..23af9640c544a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -212,6 +212,7 @@ struct link_enc_assignment { bool valid; struct display_endpoint_id ep_id; enum engine_id eng_id; + struct dc_stream_state *stream; }; #if defined(CONFIG_DRM_AMD_DC_DCN) diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h index 2472c9aed0955..09f7c868feedf 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h @@ -93,4 +93,7 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream( struct dc_state *state, const struct dc_stream_state *stream); +/* Returns true if encoder assignments in supplied state pass validity checks. */ +bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state); + #endif /* DC_INC_LINK_ENC_CFG_H_ */ From 0d4b4253ad6d9faacdc52fd30ae056ef167c4f94 Mon Sep 17 00:00:00 2001 From: Jimmy Kizito Date: Thu, 2 Sep 2021 10:01:02 -0400 Subject: [PATCH 132/151] drm/amd/display: Fix dynamic encoder reassignment [Why] Incorrect encoder assignments were being used while applying a new state to hardware. (1) When committing a new state to hardware requires resetting the back-end, the encoder assignments of the current or old state should be used when disabling the back-end; and the encoder assignments for the next or new state should be used when re-enabling the back-end. (2) Link training on hot plug could take over an encoder already in use by another stream without first disabling it. [How] (1) Introduce a resource context 'link_enc_cfg_context' which includes: - a mode to indicate when transitioning from current to next state. - transient encoder assignments to use during this state transition. Update the encoder configuration interface to respond to queries about encoder assignment based on the mode of operation. (2) Check if an encoder is already in use before attempting to perform link training on hot plug. Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Signed-off-by: Jimmy Kizito Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 13 +- .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 27 +-- .../drm/amd/display/dc/core/dc_link_enc_cfg.c | 178 +++++++++++++----- .../drm/amd/display/dc/core/dc_link_hwss.c | 6 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 15 +- .../display/dc/dce110/dce110_hw_sequencer.c | 2 +- .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 4 +- .../drm/amd/display/dc/dcn20/dcn20_resource.c | 5 +- .../display/dc/dcn31/dcn31_dio_link_encoder.c | 6 +- .../drm/amd/display/dc/dcn31/dcn31_hwseq.c | 4 + .../gpu/drm/amd/display/dc/inc/core_types.h | 18 +- .../drm/amd/display/dc/inc/hw/link_encoder.h | 5 + .../gpu/drm/amd/display/dc/inc/link_enc_cfg.h | 20 +- 13 files changed, 215 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 2225095576724..4ec3de34bd673 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3490,11 +3490,8 @@ static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off) link_enc = pipe_ctx->stream->link->link_enc; config.phy_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A; } else if (pipe_ctx->stream->link->dc->res_pool->funcs->link_encs_assign) { - /* Use link encoder assignment from current DC state - which may differ from the DC state to be - * committed - when updating PSP config. - */ link_enc = link_enc_cfg_get_link_enc_used_by_stream( - pipe_ctx->stream->link->dc->current_state, + pipe_ctx->stream->ctx->dc, pipe_ctx->stream); config.phy_idx = 0; /* Clear phy_idx for non-physical display endpoints. */ } @@ -3619,7 +3616,7 @@ void core_link_enable_stream( return; if (dc->res_pool->funcs->link_encs_assign && stream->link->ep_type != DISPLAY_ENDPOINT_PHY) - link_enc = stream->link_enc; + link_enc = link_enc_cfg_get_link_enc_used_by_stream(dc, stream); else link_enc = stream->link->link_enc; ASSERT(link_enc); @@ -4216,14 +4213,14 @@ bool dc_link_is_fec_supported(const struct dc_link *link) */ if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign) { - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); if (link_enc == NULL) - link_enc = link_enc_cfg_get_next_avail_link_enc(link->dc, link->dc->current_state); + link_enc = link_enc_cfg_get_next_avail_link_enc(link->ctx->dc); } else link_enc = link->link_enc; ASSERT(link_enc); - return (dc_is_dp_signal(link->connector_signal) && + return (dc_is_dp_signal(link->connector_signal) && link_enc && link_enc->features.fec_supported && link->dpcd_caps.fec_cap.bits.FEC_CAPABLE && !IS_FPGA_MAXIMUS_DC(link->ctx->dce_environment)); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 2a58de375d8f8..0fe0eb06eaccb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -304,7 +304,7 @@ static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *li */ if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); else link_enc = link->link_enc; ASSERT(link_enc); @@ -339,7 +339,7 @@ static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *li */ if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); else link_enc = link->link_enc; ASSERT(link_enc); @@ -2385,7 +2385,7 @@ bool perform_link_training_with_retries( * link. */ if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign) - link_enc = stream->link_enc; + link_enc = link_enc_cfg_get_link_enc_used_by_stream(link->ctx->dc, pipe_ctx->stream); else link_enc = link->link_enc; @@ -2666,9 +2666,9 @@ bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_ */ if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign) { - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); if (link_enc == NULL) - link_enc = link_enc_cfg_get_next_avail_link_enc(link->dc, link->dc->current_state); + link_enc = link_enc_cfg_get_next_avail_link_enc(link->ctx->dc); } else link_enc = link->link_enc; ASSERT(link_enc); @@ -2697,9 +2697,9 @@ static struct dc_link_settings get_max_link_cap(struct dc_link *link) */ if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign) { - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); if (link_enc == NULL) - link_enc = link_enc_cfg_get_next_avail_link_enc(link->dc, link->dc->current_state); + link_enc = link_enc_cfg_get_next_avail_link_enc(link->ctx->dc); } else link_enc = link->link_enc; ASSERT(link_enc); @@ -2881,7 +2881,13 @@ bool dp_verify_link_cap( enum link_training_result status; union hpd_irq_data irq_data; - if (link->dc->debug.skip_detection_link_training) { + /* Accept reported capabilities if link supports flexible encoder mapping or encoder already in use. */ + if (link->dc->debug.skip_detection_link_training || + link->is_dig_mapping_flexible) { + link->verified_link_cap = *known_limit_link_setting; + return true; + } else if (link->link_enc && link->dc->res_pool->funcs->link_encs_assign && + !link_enc_cfg_is_link_enc_avail(link->ctx->dc, link->link_enc->preferred_engine)) { link->verified_link_cap = *known_limit_link_setting; return true; } @@ -5679,7 +5685,7 @@ enum dc_status dp_set_fec_ready(struct dc_link *link, bool ready) */ if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); else link_enc = link->link_enc; ASSERT(link_enc); @@ -5726,8 +5732,7 @@ void dp_set_fec_enable(struct dc_link *link, bool enable) */ if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link( - link->dc->current_state, link); + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); else link_enc = link->link_enc; ASSERT(link_enc); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c index 5536184fff46b..4dce25c39b756 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_enc_cfg.c @@ -63,6 +63,18 @@ static bool is_dig_link_enc_stream(struct dc_stream_state *stream) return is_dig_stream; } +static struct link_enc_assignment get_assignment(struct dc *dc, int i) +{ + struct link_enc_assignment assignment; + + if (dc->current_state->res_ctx.link_enc_cfg_ctx.mode == LINK_ENC_CFG_TRANSIENT) + assignment = dc->current_state->res_ctx.link_enc_cfg_ctx.transient_assignments[i]; + else /* LINK_ENC_CFG_STEADY */ + assignment = dc->current_state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; + + return assignment; +} + /* Return stream using DIG link encoder resource. NULL if unused. */ static struct dc_stream_state *get_stream_using_link_enc( struct dc_state *state, @@ -72,7 +84,7 @@ static struct dc_stream_state *get_stream_using_link_enc( int i; for (i = 0; i < state->stream_count; i++) { - struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; if ((assignment.valid == true) && (assignment.eng_id == eng_id)) { stream = state->streams[i]; @@ -98,15 +110,15 @@ static void remove_link_enc_assignment( * link_enc_assignments table. */ for (i = 0; i < MAX_PIPES; i++) { - struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; if (assignment.valid && assignment.stream == stream) { - state->res_ctx.link_enc_assignments[i].valid = false; + state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].valid = false; /* Only add link encoder back to availability pool if not being * used by any other stream (i.e. removing SST stream or last MST stream). */ if (get_stream_using_link_enc(state, eng_id) == NULL) - state->res_ctx.link_enc_avail[eng_idx] = eng_id; + state->res_ctx.link_enc_cfg_ctx.link_enc_avail[eng_idx] = eng_id; stream->link_enc = NULL; break; } @@ -130,14 +142,14 @@ static void add_link_enc_assignment( */ for (i = 0; i < state->stream_count; i++) { if (stream == state->streams[i]) { - state->res_ctx.link_enc_assignments[i] = (struct link_enc_assignment){ + state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i] = (struct link_enc_assignment){ .valid = true, .ep_id = (struct display_endpoint_id) { .link_id = stream->link->link_id, .ep_type = stream->link->ep_type}, .eng_id = eng_id, .stream = stream}; - state->res_ctx.link_enc_avail[eng_idx] = ENGINE_ID_UNKNOWN; + state->res_ctx.link_enc_cfg_ctx.link_enc_avail[eng_idx] = ENGINE_ID_UNKNOWN; stream->link_enc = stream->ctx->dc->res_pool->link_encoders[eng_idx]; break; } @@ -157,7 +169,7 @@ static enum engine_id find_first_avail_link_enc( int i; for (i = 0; i < ctx->dc->res_pool->res_cap->num_dig_link_enc; i++) { - eng_id = state->res_ctx.link_enc_avail[i]; + eng_id = state->res_ctx.link_enc_cfg_ctx.link_enc_avail[i]; if (eng_id != ENGINE_ID_UNKNOWN) break; } @@ -170,7 +182,7 @@ static bool is_avail_link_enc(struct dc_state *state, enum engine_id eng_id) bool is_avail = false; int eng_idx = eng_id - ENGINE_ID_DIGA; - if (eng_id != ENGINE_ID_UNKNOWN && state->res_ctx.link_enc_avail[eng_idx] != ENGINE_ID_UNKNOWN) + if (eng_id != ENGINE_ID_UNKNOWN && state->res_ctx.link_enc_cfg_ctx.link_enc_avail[eng_idx] != ENGINE_ID_UNKNOWN) is_avail = true; return is_avail; @@ -190,6 +202,28 @@ static bool are_ep_ids_equal(struct display_endpoint_id *lhs, struct display_end return are_equal; } +static struct link_encoder *get_link_enc_used_by_link( + struct dc_state *state, + const struct dc_link *link) +{ + struct link_encoder *link_enc = NULL; + struct display_endpoint_id ep_id; + int i; + + ep_id = (struct display_endpoint_id) { + .link_id = link->link_id, + .ep_type = link->ep_type}; + + for (i = 0; i < state->stream_count; i++) { + struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; + + if (assignment.valid == true && are_ep_ids_equal(&assignment.ep_id, &ep_id)) + link_enc = link->dc->res_pool->link_encoders[assignment.eng_id - ENGINE_ID_DIGA]; + } + + return link_enc; +} + void link_enc_cfg_init( struct dc *dc, struct dc_state *state) @@ -198,10 +232,12 @@ void link_enc_cfg_init( for (i = 0; i < dc->res_pool->res_cap->num_dig_link_enc; i++) { if (dc->res_pool->link_encoders[i]) - state->res_ctx.link_enc_avail[i] = (enum engine_id) i; + state->res_ctx.link_enc_cfg_ctx.link_enc_avail[i] = (enum engine_id) i; else - state->res_ctx.link_enc_avail[i] = ENGINE_ID_UNKNOWN; + state->res_ctx.link_enc_cfg_ctx.link_enc_avail[i] = ENGINE_ID_UNKNOWN; } + + state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_STEADY; } void link_enc_cfg_link_encs_assign( @@ -221,7 +257,7 @@ void link_enc_cfg_link_encs_assign( dc->res_pool->funcs->link_enc_unassign(state, streams[i]); for (i = 0; i < MAX_PIPES; i++) - ASSERT(state->res_ctx.link_enc_assignments[i].valid == false); + ASSERT(state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i].valid == false); /* (a) Assign DIG link encoders to physical (unmappable) endpoints first. */ for (i = 0; i < stream_count; i++) { @@ -258,8 +294,8 @@ void link_enc_cfg_link_encs_assign( struct dc_stream_state *prev_stream = prev_state->streams[j]; if (stream == prev_stream && stream->link == prev_stream->link && - prev_state->res_ctx.link_enc_assignments[j].valid) { - eng_id = prev_state->res_ctx.link_enc_assignments[j].eng_id; + prev_state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[j].valid) { + eng_id = prev_state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[j].eng_id; if (is_avail_link_enc(state, eng_id)) add_link_enc_assignment(state, stream, eng_id); } @@ -291,7 +327,7 @@ void link_enc_cfg_link_encs_assign( * endpoint. These streams should use the same link encoder * assigned to that endpoint. */ - link_enc = link_enc_cfg_get_link_enc_used_by_link(state, stream->link); + link_enc = get_link_enc_used_by_link(state, stream->link); if (link_enc == NULL) eng_id = find_first_avail_link_enc(stream->ctx, state); else @@ -301,6 +337,15 @@ void link_enc_cfg_link_encs_assign( } link_enc_cfg_validate(dc, state); + + /* Update transient assignments. */ + for (i = 0; i < MAX_PIPES; i++) { + dc->current_state->res_ctx.link_enc_cfg_ctx.transient_assignments[i] = + state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; + } + + /* Current state mode will be set to steady once this state committed. */ + state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_STEADY; } void link_enc_cfg_link_enc_unassign( @@ -320,12 +365,12 @@ void link_enc_cfg_link_enc_unassign( } bool link_enc_cfg_is_transmitter_mappable( - struct dc_state *state, + struct dc *dc, struct link_encoder *link_enc) { bool is_mappable = false; enum engine_id eng_id = link_enc->preferred_engine; - struct dc_stream_state *stream = get_stream_using_link_enc(state, eng_id); + struct dc_stream_state *stream = link_enc_cfg_get_stream_using_link_enc(dc, eng_id); if (stream) is_mappable = stream->link->is_dig_mapping_flexible; @@ -333,30 +378,43 @@ bool link_enc_cfg_is_transmitter_mappable( return is_mappable; } -struct dc_link *link_enc_cfg_get_link_using_link_enc( - struct dc_state *state, +struct dc_stream_state *link_enc_cfg_get_stream_using_link_enc( + struct dc *dc, enum engine_id eng_id) { - struct dc_link *link = NULL; + struct dc_stream_state *stream = NULL; int i; - for (i = 0; i < state->stream_count; i++) { - struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + for (i = 0; i < MAX_PIPES; i++) { + struct link_enc_assignment assignment = get_assignment(dc, i); if ((assignment.valid == true) && (assignment.eng_id == eng_id)) { - link = state->streams[i]->link; + stream = assignment.stream; break; } } - if (link == NULL) - dm_output_to_console("%s: No link using DIG(%d).\n", __func__, eng_id); + return stream; +} +struct dc_link *link_enc_cfg_get_link_using_link_enc( + struct dc *dc, + enum engine_id eng_id) +{ + struct dc_link *link = NULL; + struct dc_stream_state *stream = NULL; + + stream = link_enc_cfg_get_stream_using_link_enc(dc, eng_id); + + if (stream) + link = stream->link; + + // dm_output_to_console("%s: No link using DIG(%d).\n", __func__, eng_id); return link; } struct link_encoder *link_enc_cfg_get_link_enc_used_by_link( - struct dc_state *state, + struct dc *dc, const struct dc_link *link) { struct link_encoder *link_enc = NULL; @@ -367,41 +425,74 @@ struct link_encoder *link_enc_cfg_get_link_enc_used_by_link( .link_id = link->link_id, .ep_type = link->ep_type}; - for (i = 0; i < state->stream_count; i++) { - struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + for (i = 0; i < MAX_PIPES; i++) { + struct link_enc_assignment assignment = get_assignment(dc, i); - if (assignment.valid == true && are_ep_ids_equal(&assignment.ep_id, &ep_id)) + if (assignment.valid == true && are_ep_ids_equal(&assignment.ep_id, &ep_id)) { link_enc = link->dc->res_pool->link_encoders[assignment.eng_id - ENGINE_ID_DIGA]; + break; + } } return link_enc; } -struct link_encoder *link_enc_cfg_get_next_avail_link_enc( - const struct dc *dc, - const struct dc_state *state) +struct link_encoder *link_enc_cfg_get_next_avail_link_enc(struct dc *dc) { struct link_encoder *link_enc = NULL; - enum engine_id eng_id; + enum engine_id encs_assigned[MAX_DIG_LINK_ENCODERS]; + int i; + + for (i = 0; i < MAX_DIG_LINK_ENCODERS; i++) + encs_assigned[i] = ENGINE_ID_UNKNOWN; - eng_id = find_first_avail_link_enc(dc->ctx, state); - if (eng_id != ENGINE_ID_UNKNOWN) - link_enc = dc->res_pool->link_encoders[eng_id - ENGINE_ID_DIGA]; + /* Add assigned encoders to list. */ + for (i = 0; i < MAX_PIPES; i++) { + struct link_enc_assignment assignment = get_assignment(dc, i); + + if (assignment.valid) + encs_assigned[assignment.eng_id - ENGINE_ID_DIGA] = assignment.eng_id; + } + + for (i = 0; i < dc->res_pool->res_cap->num_dig_link_enc; i++) { + if (encs_assigned[i] == ENGINE_ID_UNKNOWN) { + link_enc = dc->res_pool->link_encoders[i]; + break; + } + } return link_enc; } struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream( - struct dc_state *state, + struct dc *dc, const struct dc_stream_state *stream) { struct link_encoder *link_enc; - link_enc = link_enc_cfg_get_link_enc_used_by_link(state, stream->link); + link_enc = link_enc_cfg_get_link_enc_used_by_link(dc, stream->link); return link_enc; } +bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id) +{ + bool is_avail = true; + int i; + + /* Add assigned encoders to list. */ + for (i = 0; i < MAX_PIPES; i++) { + struct link_enc_assignment assignment = get_assignment(dc, i); + + if (assignment.valid && assignment.eng_id == eng_id) { + is_avail = false; + break; + } + } + + return is_avail; +} + bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state) { bool is_valid = false; @@ -418,7 +509,7 @@ bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state) /* (1) No. valid entries same as stream count. */ for (i = 0; i < MAX_PIPES; i++) { - struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; if (assignment.valid) valid_count++; @@ -431,7 +522,7 @@ bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state) /* (2) Matching stream ptrs. */ for (i = 0; i < MAX_PIPES; i++) { - struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; if (assignment.valid) { if (assignment.stream == state->streams[i]) @@ -443,14 +534,15 @@ bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state) /* (3) Each endpoint assigned unique encoder. */ for (i = 0; i < MAX_PIPES; i++) { - struct link_enc_assignment assignment_i = state->res_ctx.link_enc_assignments[i]; + struct link_enc_assignment assignment_i = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; if (assignment_i.valid) { struct display_endpoint_id ep_id_i = assignment_i.ep_id; eng_ids_per_ep_id[i]++; for (j = 0; j < MAX_PIPES; j++) { - struct link_enc_assignment assignment_j = state->res_ctx.link_enc_assignments[j]; + struct link_enc_assignment assignment_j = + state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[j]; if (j == i) continue; @@ -470,11 +562,11 @@ bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state) /* (4) Assigned encoders not in available pool. */ for (i = 0; i < MAX_PIPES; i++) { - struct link_enc_assignment assignment = state->res_ctx.link_enc_assignments[i]; + struct link_enc_assignment assignment = state->res_ctx.link_enc_cfg_ctx.link_enc_assignments[i]; if (assignment.valid) { for (j = 0; j < dc->res_pool->res_cap->num_dig_link_enc; j++) { - if (state->res_ctx.link_enc_avail[j] == assignment.eng_id) { + if (state->res_ctx.link_enc_cfg_ctx.link_enc_avail[j] == assignment.eng_id) { valid_avail = false; break; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index dae0ab761b619..64f76f57c85d0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -87,7 +87,7 @@ void dp_enable_link_phy( /* Link should always be assigned encoder when en-/disabling. */ if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + link_enc = link_enc_cfg_get_link_enc_used_by_link(dc, link); else link_enc = link->link_enc; ASSERT(link_enc); @@ -247,7 +247,7 @@ void dp_disable_link_phy(struct dc_link *link, enum signal_type signal) /* Link should always be assigned encoder when en-/disabling. */ if (link->is_dig_mapping_flexible && dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + link_enc = link_enc_cfg_get_link_enc_used_by_link(dc, link); else link_enc = link->link_enc; ASSERT(link_enc); @@ -391,7 +391,7 @@ void dp_set_hw_test_pattern( */ if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign) - encoder = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + encoder = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); else encoder = link->link_enc; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index b4e986f736ada..adc656fc48484 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -41,6 +41,7 @@ #include "set_mode_types.h" #include "virtual/virtual_stream_encoder.h" #include "dpcd_defs.h" +#include "link_enc_cfg.h" #include "dc_link_dp.h" #if defined(CONFIG_DRM_AMD_DC_SI) @@ -2826,8 +2827,18 @@ bool pipe_need_reprogram( #endif /* DIG link encoder resource assignment for stream changed. */ - if (pipe_ctx_old->stream->link_enc != pipe_ctx->stream->link_enc) - return true; + if (pipe_ctx_old->stream->ctx->dc->res_pool->funcs->link_encs_assign) { + bool need_reprogram = false; + struct dc *dc = pipe_ctx_old->stream->ctx->dc; + enum link_enc_cfg_mode mode = dc->current_state->res_ctx.link_enc_cfg_ctx.mode; + + dc->current_state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_STEADY; + if (link_enc_cfg_get_link_enc_used_by_stream(dc, pipe_ctx_old->stream) != pipe_ctx->stream->link_enc) + need_reprogram = true; + dc->current_state->res_ctx.link_enc_cfg_ctx.mode = mode; + + return need_reprogram; + } return false; } diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 102f764627521..af3e68d3e7476 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1219,7 +1219,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) if (link->ep_type == DISPLAY_ENDPOINT_PHY) link_enc = link->link_enc; else if (dc->res_pool->funcs->link_encs_assign) - link_enc = link_enc_cfg_get_link_enc_used_by_link(link->dc->current_state, link); + link_enc = link_enc_cfg_get_link_enc_used_by_link(link->ctx->dc, link); ASSERT(link_enc); #if defined(CONFIG_DRM_AMD_DC_DCN) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index c0aed7d07eeba..fc83744149d9f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -54,6 +54,7 @@ #include "hw_sequencer.h" #include "inc/link_dpcd.h" #include "dpcd_defs.h" +#include "inc/link_enc_cfg.h" #define DC_LOGGER_INIT(logger) @@ -2385,9 +2386,10 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign) - link_enc = pipe_ctx->stream->link_enc; + link_enc = link_enc_cfg_get_link_enc_used_by_stream(link->ctx->dc, pipe_ctx->stream); else link_enc = link->link_enc; + ASSERT(link_enc); /* For MST, there are multiply stream go to only one link. * connect DIG back_end to front_end while enable_stream and diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 1872c456e2c9d..3c388afa06dcd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -1610,10 +1610,9 @@ static void get_pixel_clock_parameters( */ if (link->is_dig_mapping_flexible && link->dc->res_pool->funcs->link_encs_assign) { - link_enc = link_enc_cfg_get_link_enc_used_by_stream(stream->link->dc->current_state, stream); + link_enc = link_enc_cfg_get_link_enc_used_by_stream(stream->ctx->dc, stream); if (link_enc == NULL) - link_enc = link_enc_cfg_get_next_avail_link_enc(stream->link->dc, - stream->link->dc->current_state); + link_enc = link_enc_cfg_get_next_avail_link_enc(stream->ctx->dc); } else link_enc = stream->link->link_enc; ASSERT(link_enc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c index 77b81f6c24b9f..03f0290d41f27 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c @@ -367,7 +367,7 @@ void dcn31_link_encoder_enable_dp_output( enum clock_source_id clock_source) { /* Enable transmitter and encoder. */ - if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc->current_state, enc)) { + if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { dcn20_link_encoder_enable_dp_output(enc, link_settings, clock_source); @@ -383,7 +383,7 @@ void dcn31_link_encoder_enable_dp_mst_output( enum clock_source_id clock_source) { /* Enable transmitter and encoder. */ - if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc->current_state, enc)) { + if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { dcn10_link_encoder_enable_dp_mst_output(enc, link_settings, clock_source); @@ -398,7 +398,7 @@ void dcn31_link_encoder_disable_output( enum signal_type signal) { /* Disable transmitter and encoder. */ - if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc->current_state, enc)) { + if (!link_enc_cfg_is_transmitter_mappable(enc->ctx->dc, enc)) { dcn10_link_encoder_disable_output(enc, signal); diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c index d3598ce1f5de1..0713910a3aa9f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c @@ -48,6 +48,7 @@ #include "dc_link_dp.h" #include "inc/link_dpcd.h" #include "dcn10/dcn10_hw_sequencer.h" +#include "inc/link_enc_cfg.h" #define DC_LOGGER_INIT(logger) @@ -599,4 +600,7 @@ void dcn31_reset_hw_ctx_wrap( old_clk->funcs->cs_power_down(old_clk); } } + + /* New dc_state in the process of being applied to hardware. */ + dc->current_state->res_ctx.link_enc_cfg_ctx.mode = LINK_ENC_CFG_TRANSIENT; } diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index 0473cd28e8d17..0fea258c6db34 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -387,6 +387,17 @@ struct pipe_ctx { bool vtp_locked; }; +/* Data used for dynamic link encoder assignment. + * Tracks current and future assignments; available link encoders; + * and mode of operation (whether to use current or future assignments). + */ +struct link_enc_cfg_context { + enum link_enc_cfg_mode mode; + struct link_enc_assignment link_enc_assignments[MAX_PIPES]; + enum engine_id link_enc_avail[MAX_DIG_LINK_ENCODERS]; + struct link_enc_assignment transient_assignments[MAX_PIPES]; +}; + struct resource_context { struct pipe_ctx pipe_ctx[MAX_PIPES]; bool is_stream_enc_acquired[MAX_PIPES * 2]; @@ -394,12 +405,7 @@ struct resource_context { uint8_t clock_source_ref_count[MAX_CLOCK_SOURCES]; uint8_t dp_clock_source_ref_count; bool is_dsc_acquired[MAX_PIPES]; - /* A table/array of encoder-to-link assignments. One entry per stream. - * Indexed by stream index in dc_state. - */ - struct link_enc_assignment link_enc_assignments[MAX_PIPES]; - /* List of available link encoders. Uses engine ID as encoder identifier. */ - enum engine_id link_enc_avail[MAX_DIG_LINK_ENCODERS]; + struct link_enc_cfg_context link_enc_cfg_ctx; #if defined(CONFIG_DRM_AMD_DC_DCN) bool is_hpo_dp_stream_enc_acquired[MAX_HPO_DP2_ENCODERS]; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index 23af9640c544a..bb0e91756ddd9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -215,6 +215,11 @@ struct link_enc_assignment { struct dc_stream_state *stream; }; +enum link_enc_cfg_mode { + LINK_ENC_CFG_STEADY, /* Normal operation - use current_state. */ + LINK_ENC_CFG_TRANSIENT /* During commit state - use state to be committed. */ +}; + #if defined(CONFIG_DRM_AMD_DC_DCN) enum dp2_link_mode { DP2_LINK_TRAINING_TPS1, diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h index 09f7c868feedf..83b2199b2c83f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link_enc_cfg.h @@ -70,29 +70,35 @@ void link_enc_cfg_link_enc_unassign( * endpoint. */ bool link_enc_cfg_is_transmitter_mappable( - struct dc_state *state, + struct dc *dc, struct link_encoder *link_enc); +/* Return stream using DIG link encoder resource. NULL if unused. */ +struct dc_stream_state *link_enc_cfg_get_stream_using_link_enc( + struct dc *dc, + enum engine_id eng_id); + /* Return link using DIG link encoder resource. NULL if unused. */ struct dc_link *link_enc_cfg_get_link_using_link_enc( - struct dc_state *state, + struct dc *dc, enum engine_id eng_id); /* Return DIG link encoder used by link. NULL if unused. */ struct link_encoder *link_enc_cfg_get_link_enc_used_by_link( - struct dc_state *state, + struct dc *dc, const struct dc_link *link); /* Return next available DIG link encoder. NULL if none available. */ -struct link_encoder *link_enc_cfg_get_next_avail_link_enc( - const struct dc *dc, - const struct dc_state *state); +struct link_encoder *link_enc_cfg_get_next_avail_link_enc(struct dc *dc); /* Return DIG link encoder used by stream. NULL if unused. */ struct link_encoder *link_enc_cfg_get_link_enc_used_by_stream( - struct dc_state *state, + struct dc *dc, const struct dc_stream_state *stream); +/* Return true if encoder available to use. */ +bool link_enc_cfg_is_link_enc_avail(struct dc *dc, enum engine_id eng_id); + /* Returns true if encoder assignments in supplied state pass validity checks. */ bool link_enc_cfg_validate(struct dc *dc, struct dc_state *state); From f777bb9a966941718feb6a34b7e8c849846910c4 Mon Sep 17 00:00:00 2001 From: "Lai, Derek" Date: Fri, 3 Sep 2021 12:31:17 +0800 Subject: [PATCH 133/151] drm/amd/display: Added power down on boot for DCN3 [Why] The change of setting a timer callback on boot for 10 seconds is still working, just lost power down on boot and power down for DCN3. [How] Added power down on boot and power down for DCN3. Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Derek Lai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c index 10c83f4083b56..c6a737781ad18 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c @@ -34,6 +34,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = { .program_gamut_remap = dcn10_program_gamut_remap, .init_hw = dcn31_init_hw, + .power_down_on_boot = dcn10_power_down_on_boot, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, @@ -93,6 +94,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = { .set_flip_control_gsl = dcn20_set_flip_control_gsl, .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync, .calc_vupdate_position = dcn10_calc_vupdate_position, + .power_down = dce110_power_down, .set_backlight_level = dcn21_set_backlight_level, .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .set_pipe = dcn21_set_pipe, From 808643ea56a2f96a42873d5e11c399957d6493aa Mon Sep 17 00:00:00 2001 From: Nikola Cornij Date: Tue, 7 Sep 2021 22:09:01 -0400 Subject: [PATCH 134/151] drm/amd/display: Use adjusted DCN301 watermarks [why] If DCN30 watermark calc is used for DCN301, the calculated values are wrong due to the data structure mismatch between DCN30 and DCN301. However, using the original DCN301 watermark values causes underflow. [how] - Add DCN21-style watermark calculations - Adjust DCN301 watermark values to remove the underflow Reviewed-by: Zhan Liu Acked-by: Rodrigo Siqueira Signed-off-by: Nikola Cornij Signed-off-by: Alex Deucher --- .../display/dc/clk_mgr/dcn301/vg_clk_mgr.c | 4 +- .../amd/display/dc/dcn301/dcn301_resource.c | 96 ++++++++++++++++++- 2 files changed, 97 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c index 7046da14bb2a5..3eee32faa208c 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c @@ -582,8 +582,8 @@ static struct wm_table lpddr5_wm_table = { .wm_inst = WM_A, .wm_type = WM_TYPE_PSTATE_CHG, .pstate_latency_us = 11.65333, - .sr_exit_time_us = 5.32, - .sr_enter_plus_exit_time_us = 6.38, + .sr_exit_time_us = 7.95, + .sr_enter_plus_exit_time_us = 9, .valid = true, }, { diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c index 73b8fcb3c5c9d..5350c93d7772e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c @@ -1626,12 +1626,106 @@ static void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30); } +static void calculate_wm_set_for_vlevel( + int vlevel, + struct wm_range_table_entry *table_entry, + struct dcn_watermarks *wm_set, + struct display_mode_lib *dml, + display_e2e_pipe_params_st *pipes, + int pipe_cnt) +{ + double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us; + + ASSERT(vlevel < dml->soc.num_states); + /* only pipe 0 is read for voltage and dcf/soc clocks */ + pipes[0].clks_cfg.voltage = vlevel; + pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz; + pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz; + + dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us; + dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us; + dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us; + + wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000; + wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000; + wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000; + wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000; + wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000; + wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000; + wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000; + wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000; + dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached; + +} + +static void dcn301_calculate_wm_and_dlg( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel_req) +{ + int i, pipe_idx; + int vlevel, vlevel_max; + struct wm_range_table_entry *table_entry; + struct clk_bw_params *bw_params = dc->clk_mgr->bw_params; + + ASSERT(bw_params); + + vlevel_max = bw_params->clk_table.num_entries - 1; + + /* WM Set D */ + table_entry = &bw_params->wm_table.entries[WM_D]; + if (table_entry->wm_type == WM_TYPE_RETRAINING) + vlevel = 0; + else + vlevel = vlevel_max; + calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d, + &context->bw_ctx.dml, pipes, pipe_cnt); + /* WM Set C */ + table_entry = &bw_params->wm_table.entries[WM_C]; + vlevel = min(max(vlevel_req, 2), vlevel_max); + calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c, + &context->bw_ctx.dml, pipes, pipe_cnt); + /* WM Set B */ + table_entry = &bw_params->wm_table.entries[WM_B]; + vlevel = min(max(vlevel_req, 1), vlevel_max); + calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b, + &context->bw_ctx.dml, pipes, pipe_cnt); + + /* WM Set A */ + table_entry = &bw_params->wm_table.entries[WM_A]; + vlevel = min(vlevel_req, vlevel_max); + calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a, + &context->bw_ctx.dml, pipes, pipe_cnt); + + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { + if (!context->res_ctx.pipe_ctx[i].stream) + continue; + + pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt); + pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); + + if (dc->config.forced_clocks) { + pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz; + pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz; + } + if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000) + pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0; + if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000) + pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0; + + pipe_idx++; + } + + dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); +} + static struct resource_funcs dcn301_res_pool_funcs = { .destroy = dcn301_destroy_resource_pool, .link_enc_create = dcn301_link_encoder_create, .panel_cntl_create = dcn301_panel_cntl_create, .validate_bandwidth = dcn30_validate_bandwidth, - .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg, + .calculate_wm_and_dlg = dcn301_calculate_wm_and_dlg, .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer, From 253a55918ce128f15a3be66db5e2072665143554 Mon Sep 17 00:00:00 2001 From: "Guo, Bing" Date: Tue, 24 Aug 2021 12:08:22 -0400 Subject: [PATCH 135/151] drm/amd/display: Fix issue with dynamic bpp change for DCN3x Why: Screen sometimes would have artifacts or blink once at the time when bpp is dynamically changed. How: 1. Changed to update PPS infopacket in frame mode instead of immediate mode since other updates for bpp change are double-buffered. 2. Changed double-buffering enablement programming for DCN30 as advised by ASIC team Reviewed-by: Wenjing Liu Acked-by: Rodrigo Siqueira Signed-off-by: Bing Guo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 +- .../drm/amd/display/dc/core/dc_link_hwss.c | 29 ++- .../display/dc/dcn20/dcn20_stream_encoder.c | 3 +- .../dc/dcn30/dcn30_dio_stream_encoder.c | 18 +- .../gpu/drm/amd/display/dc/dcn30/dcn30_optc.c | 17 +- .../gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c | 198 ++++++++++++------ .../gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h | 6 +- .../dc/dcn31/dcn31_hpo_dp_stream_encoder.c | 15 +- .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 2 +- .../amd/display/dc/inc/hw/stream_encoder.h | 6 +- .../dc/virtual/virtual_stream_encoder.c | 3 +- 11 files changed, 204 insertions(+), 97 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 4ec3de34bd673..2bd38d19a447d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3554,7 +3554,7 @@ static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pi /* Set DPS PPS SDP (AKA "info frames") */ if (pipe_ctx->stream->timing.flags.DSC) { - dp_set_dsc_pps_sdp(pipe_ctx, true); + dp_set_dsc_pps_sdp(pipe_ctx, true, true); } /* Allocate Payload */ @@ -3803,7 +3803,7 @@ void core_link_enable_stream( if (dc_is_dp_signal(pipe_ctx->stream->signal) || dc_is_virtual_signal(pipe_ctx->stream->signal)) { dp_set_dsc_on_rx(pipe_ctx, true); - dp_set_dsc_pps_sdp(pipe_ctx, true); + dp_set_dsc_pps_sdp(pipe_ctx, true, true); } } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 64f76f57c85d0..cc4b28e94727d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -607,7 +607,8 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.hpo_dp_stream_enc, false, - NULL); + NULL, + true); else #endif if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { @@ -615,7 +616,7 @@ void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) pipe_ctx->stream_res.stream_enc, OPTC_DSC_DISABLED, 0, 0); pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.stream_enc, false, NULL); + pipe_ctx->stream_res.stream_enc, false, NULL, true); } } @@ -650,7 +651,16 @@ bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable) return result; } -bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable) +/* + * For dynamic bpp change case, dsc is programmed with MASTER_UPDATE_LOCK enabled; + * hence PPS info packet update need to use frame update instead of immediate update. + * Added parameter immediate_update for this purpose. + * The decision to use frame update is hard-coded in function dp_update_dsc_config(), + * which is the only place where a "false" would be passed in for param immediate_update. + * + * immediate_update is only applicable when DSC is enabled. + */ +bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update) { struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc; struct dc_stream_state *stream = pipe_ctx->stream; @@ -682,13 +692,15 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.hpo_dp_stream_enc, true, - &dsc_packed_pps[0]); + &dsc_packed_pps[0], + immediate_update); else #endif pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.stream_enc, true, - &dsc_packed_pps[0]); + &dsc_packed_pps[0], + immediate_update); } } else { /* disable DSC PPS in stream encoder */ @@ -698,11 +710,12 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable) pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_set_dsc_pps_info_packet( pipe_ctx->stream_res.hpo_dp_stream_enc, false, - NULL); + NULL, + true); else #endif pipe_ctx->stream_res.stream_enc->funcs->dp_set_dsc_pps_info_packet( - pipe_ctx->stream_res.stream_enc, false, NULL); + pipe_ctx->stream_res.stream_enc, false, NULL, true); } } @@ -720,7 +733,7 @@ bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx) return false; dp_set_dsc_on_stream(pipe_ctx, true); - dp_set_dsc_pps_sdp(pipe_ctx, true); + dp_set_dsc_pps_sdp(pipe_ctx, true, false); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c index 44f31b7b9ac90..11c50b5087544 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c @@ -292,7 +292,8 @@ static void enc2_dp_set_dsc_config(struct stream_encoder *enc, static void enc2_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, bool enable, - uint8_t *dsc_packed_pps) + uint8_t *dsc_packed_pps, + bool immediate_update) { struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c index b73dfd2661b91..3ea6dacec80c0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c @@ -77,7 +77,8 @@ static void enc3_update_hdmi_info_packet( enc1->base.vpg->funcs->update_generic_info_packet( enc1->base.vpg, packet_index, - info_packet); + info_packet, + true); /* enable transmission of packet(s) - * packet transmission begins on the next frame */ @@ -335,7 +336,8 @@ static void enc3_dp_set_dsc_config(struct stream_encoder *enc, static void enc3_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, bool enable, - uint8_t *dsc_packed_pps) + uint8_t *dsc_packed_pps, + bool immediate_update) { struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); @@ -365,7 +367,8 @@ static void enc3_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, enc1->base.vpg->funcs->update_generic_info_packet( enc1->base.vpg, 11 + i, - &pps_sdp); + &pps_sdp, + immediate_update); } /* SW should make sure VBID[6] update line number is bigger @@ -429,19 +432,22 @@ static void enc3_stream_encoder_update_dp_info_packets( enc->vpg->funcs->update_generic_info_packet( enc->vpg, 0, /* packetIndex */ - &info_frame->vsc); + &info_frame->vsc, + true); } if (info_frame->spd.valid) { enc->vpg->funcs->update_generic_info_packet( enc->vpg, 2, /* packetIndex */ - &info_frame->spd); + &info_frame->spd, + true); } if (info_frame->hdrsmd.valid) { enc->vpg->funcs->update_generic_info_packet( enc->vpg, 3, /* packetIndex */ - &info_frame->hdrsmd); + &info_frame->hdrsmd, + true); } /* packetIndex 4 is used for send immediate sdp message, and please * use other packetIndex (such as 5,6) for other info packet diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c index 089be73475918..5d9e6413d67a2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c @@ -73,16 +73,23 @@ void optc3_lock_doublebuffer_enable(struct timing_generator *optc) OTG_H_BLANK_END, &h_blank_end); REG_UPDATE_2(OTG_GLOBAL_CONTROL1, - MASTER_UPDATE_LOCK_DB_START_Y, v_blank_start, - MASTER_UPDATE_LOCK_DB_END_Y, v_blank_end); + MASTER_UPDATE_LOCK_DB_START_Y, v_blank_start - 1, + MASTER_UPDATE_LOCK_DB_END_Y, v_blank_start); REG_UPDATE_2(OTG_GLOBAL_CONTROL4, - DIG_UPDATE_POSITION_X, 20, - DIG_UPDATE_POSITION_Y, v_blank_start); + DIG_UPDATE_POSITION_X, h_blank_start - 180 - 1, + DIG_UPDATE_POSITION_Y, v_blank_start - 1); + // there is a DIG_UPDATE_VCOUNT_MODE and it is 0. + REG_UPDATE_3(OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_START_X, h_blank_start - 200 - 1, - MASTER_UPDATE_LOCK_DB_END_X, h_blank_end, + MASTER_UPDATE_LOCK_DB_END_X, h_blank_start - 180, MASTER_UPDATE_LOCK_DB_EN, 1); REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1); + + REG_SET_3(OTG_VUPDATE_KEEPOUT, 0, + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0, + MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, 100, + OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1); } void optc3_lock_doublebuffer_disable(struct timing_generator *optc) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c index 9748aaa044f70..14bc44b1f8866 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.c @@ -46,7 +46,8 @@ void vpg3_update_generic_info_packet( struct vpg *vpg, uint32_t packet_index, - const struct dc_info_packet *info_packet) + const struct dc_info_packet *info_packet, + bool immediate_update) { struct dcn30_vpg *vpg3 = DCN30_VPG_FROM_VPG(vpg); uint32_t i; @@ -106,69 +107,138 @@ void vpg3_update_generic_info_packet( /* atomically update double-buffered GENERIC0 registers in immediate mode * (update at next block_update when block_update_lock == 0). */ - switch (packet_index) { - case 0: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC0_IMMEDIATE_UPDATE, 1); - break; - case 1: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC1_IMMEDIATE_UPDATE, 1); - break; - case 2: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC2_IMMEDIATE_UPDATE, 1); - break; - case 3: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC3_IMMEDIATE_UPDATE, 1); - break; - case 4: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC4_IMMEDIATE_UPDATE, 1); - break; - case 5: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC5_IMMEDIATE_UPDATE, 1); - break; - case 6: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC6_IMMEDIATE_UPDATE, 1); - break; - case 7: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC7_IMMEDIATE_UPDATE, 1); - break; - case 8: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC8_IMMEDIATE_UPDATE, 1); - break; - case 9: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC9_IMMEDIATE_UPDATE, 1); - break; - case 10: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC10_IMMEDIATE_UPDATE, 1); - break; - case 11: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC11_IMMEDIATE_UPDATE, 1); - break; - case 12: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC12_IMMEDIATE_UPDATE, 1); - break; - case 13: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC13_IMMEDIATE_UPDATE, 1); - break; - case 14: - REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, - VPG_GENERIC14_IMMEDIATE_UPDATE, 1); - break; - default: - break; + if (immediate_update) { + switch (packet_index) { + case 0: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC0_IMMEDIATE_UPDATE, 1); + break; + case 1: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC1_IMMEDIATE_UPDATE, 1); + break; + case 2: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC2_IMMEDIATE_UPDATE, 1); + break; + case 3: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC3_IMMEDIATE_UPDATE, 1); + break; + case 4: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC4_IMMEDIATE_UPDATE, 1); + break; + case 5: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC5_IMMEDIATE_UPDATE, 1); + break; + case 6: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC6_IMMEDIATE_UPDATE, 1); + break; + case 7: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC7_IMMEDIATE_UPDATE, 1); + break; + case 8: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC8_IMMEDIATE_UPDATE, 1); + break; + case 9: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC9_IMMEDIATE_UPDATE, 1); + break; + case 10: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC10_IMMEDIATE_UPDATE, 1); + break; + case 11: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC11_IMMEDIATE_UPDATE, 1); + break; + case 12: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC12_IMMEDIATE_UPDATE, 1); + break; + case 13: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC13_IMMEDIATE_UPDATE, 1); + break; + case 14: + REG_UPDATE(VPG_GSP_IMMEDIATE_UPDATE_CTRL, + VPG_GENERIC14_IMMEDIATE_UPDATE, 1); + break; + default: + break; + } + } else { + switch (packet_index) { + case 0: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC0_FRAME_UPDATE, 1); + break; + case 1: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC1_FRAME_UPDATE, 1); + break; + case 2: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC2_FRAME_UPDATE, 1); + break; + case 3: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC3_FRAME_UPDATE, 1); + break; + case 4: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC4_FRAME_UPDATE, 1); + break; + case 5: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC5_FRAME_UPDATE, 1); + break; + case 6: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC6_FRAME_UPDATE, 1); + break; + case 7: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC7_FRAME_UPDATE, 1); + break; + case 8: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC8_FRAME_UPDATE, 1); + break; + case 9: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC9_FRAME_UPDATE, 1); + break; + case 10: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC10_FRAME_UPDATE, 1); + break; + case 11: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC11_FRAME_UPDATE, 1); + break; + case 12: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC12_FRAME_UPDATE, 1); + break; + case 13: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC13_FRAME_UPDATE, 1); + break; + case 14: + REG_UPDATE(VPG_GSP_FRAME_UPDATE_CTRL, + VPG_GENERIC14_FRAME_UPDATE, 1); + break; + + default: + break; + } + } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h index 96dccb2f1124a..ed9a5549c389b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h @@ -138,7 +138,8 @@ struct vpg_funcs { void (*update_generic_info_packet)( struct vpg *vpg, uint32_t packet_index, - const struct dc_info_packet *info_packet); + const struct dc_info_packet *info_packet, + bool immediate_update); void (*vpg_poweron)( struct vpg *vpg); @@ -163,7 +164,8 @@ struct dcn30_vpg { void vpg3_update_generic_info_packet( struct vpg *vpg, uint32_t packet_index, - const struct dc_info_packet *info_packet); + const struct dc_info_packet *info_packet, + bool immediate_update); void vpg3_construct(struct dcn30_vpg *vpg3, struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c index 25e4794eb9ad5..565f12dd179a8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c @@ -442,21 +442,24 @@ static void dcn31_hpo_dp_stream_enc_update_dp_info_packets( enc->vpg->funcs->update_generic_info_packet( enc->vpg, 0, /* packetIndex */ - &info_frame->vsc); + &info_frame->vsc, + true); sdp_stream_enable = true; } if (info_frame->spd.valid) { enc->vpg->funcs->update_generic_info_packet( enc->vpg, 2, /* packetIndex */ - &info_frame->spd); + &info_frame->spd, + true); sdp_stream_enable = true; } if (info_frame->hdrsmd.valid) { enc->vpg->funcs->update_generic_info_packet( enc->vpg, 3, /* packetIndex */ - &info_frame->hdrsmd); + &info_frame->hdrsmd, + true); sdp_stream_enable = true; } /* enable/disable transmission of packet(s). @@ -520,7 +523,8 @@ static uint32_t hpo_dp_is_gsp_enabled( static void dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet( struct hpo_dp_stream_encoder *enc, bool enable, - uint8_t *dsc_packed_pps) + uint8_t *dsc_packed_pps, + bool immediate_update) { struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); @@ -544,7 +548,8 @@ static void dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet( enc3->base.vpg->funcs->update_generic_info_packet( enc3->base.vpg, 11 + i, - &pps_sdp); + &pps_sdp, + immediate_update); } /* SW should make sure VBID[6] update line number is bigger diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h index 3cc110e13213c..cb8e785a866e1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h @@ -166,7 +166,7 @@ uint8_t dc_dp_initialize_scrambling_data_symbols( enum dc_status dp_set_fec_ready(struct dc_link *link, bool ready); void dp_set_fec_enable(struct dc_link *link, bool enable); bool dp_set_dsc_enable(struct pipe_ctx *pipe_ctx, bool enable); -bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable); +bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable, bool immediate_update); void dp_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable); bool dp_update_dsc_config(struct pipe_ctx *pipe_ctx); bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 9f03fda5b9658..c88e113b94d12 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -229,7 +229,8 @@ struct stream_encoder_funcs { void (*dp_set_dsc_pps_info_packet)(struct stream_encoder *enc, bool enable, - uint8_t *dsc_packed_pps); + uint8_t *dsc_packed_pps, + bool immediate_update); void (*set_dynamic_metadata)(struct stream_encoder *enc, bool enable, @@ -298,7 +299,8 @@ struct hpo_dp_stream_encoder_funcs { void (*dp_set_dsc_pps_info_packet)( struct hpo_dp_stream_encoder *enc, bool enable, - uint8_t *dsc_packed_pps); + uint8_t *dsc_packed_pps, + bool immediate_update); void (*map_stream_to_link)( struct hpo_dp_stream_encoder *enc, diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c index 42a29b712e0e6..1e39aae6b1cf6 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c @@ -104,7 +104,8 @@ static void virtual_setup_stereo_sync( static void virtual_stream_encoder_set_dsc_pps_info_packet( struct stream_encoder *enc, bool enable, - uint8_t *dsc_packed_pps) + uint8_t *dsc_packed_pps, + bool immediate_update) {} static const struct stream_encoder_funcs virtual_str_enc_funcs = { From 5d694266bd14d5a0ac359ef6aef88dbc93efda70 Mon Sep 17 00:00:00 2001 From: Michael Strauss Date: Wed, 8 Sep 2021 14:39:09 -0400 Subject: [PATCH 136/151] drm/amd/display: Disable mem low power for CM HW block on DCN3.1 [WHY] Currently causes visible flicker in some scenarios on OLED eDPs Reviewed-by: Haonan Wang Acked-by: Rodrigo Siqueira Signed-off-by: Michael Strauss Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index a823a64d02a57..0b60ac676423c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -1013,7 +1013,7 @@ static const struct dc_debug_options debug_defaults_drv = { .i2c = true, .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled .dscl = true, - .cm = true, + .cm = false, // visible flicker on OLED eDPs .mpc = true, .optc = true, .vpg = true, From bdd1a21b52557ea8f61d0a5dc2f77151b576eb70 Mon Sep 17 00:00:00 2001 From: "Liu, Zhan" Date: Thu, 9 Sep 2021 13:26:37 -0400 Subject: [PATCH 137/151] drm/amd/display: Fix B0 USB-C DP Alt mode [Why] Starting from B0, along with RDPCSTX, RDPCSPIPE registers are also used. [How] Make sure RDPCSPIPE registers are programmed correctly. Reviewed-by: Charlene Liu Acked-by: Rodrigo Siqueira Signed-off-by: Zhan Liu Signed-off-by: Alex Deucher --- .../amd/display/dc/dcn10/dcn10_link_encoder.h | 1 + .../display/dc/dcn31/dcn31_dio_link_encoder.c | 33 ++++++++++++++++++- .../display/dc/dcn31/dcn31_dio_link_encoder.h | 11 ++++++- .../include/asic_reg/dpcs/dpcs_4_2_0_offset.h | 27 +++++++++++++++ 4 files changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h index d8b22618b79e8..c337588231ff0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h @@ -118,6 +118,7 @@ struct dcn10_link_enc_registers { uint32_t RDPCSTX_PHY_CNTL4; uint32_t RDPCSTX_PHY_CNTL5; uint32_t RDPCSTX_PHY_CNTL6; + uint32_t RDPCSPIPE_PHY_CNTL6; uint32_t RDPCSTX_PHY_CNTL7; uint32_t RDPCSTX_PHY_CNTL8; uint32_t RDPCSTX_PHY_CNTL9; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c index 03f0290d41f27..4f0a0803db6cd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c @@ -37,6 +37,7 @@ #include "link_enc_cfg.h" #include "dc_dmub_srv.h" +#include "dal_asic_id.h" #define CTX \ enc10->base.ctx @@ -215,7 +216,7 @@ static const struct link_encoder_funcs dcn31_link_enc_funcs = { .fec_is_active = enc2_fec_is_active, .get_dig_frontend = dcn10_get_dig_frontend, .get_dig_mode = dcn10_get_dig_mode, - .is_in_alt_mode = dcn20_link_encoder_is_in_alt_mode, + .is_in_alt_mode = dcn31_link_encoder_is_in_alt_mode, .get_max_link_cap = dcn20_link_encoder_get_max_link_cap, .set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux, }; @@ -408,3 +409,33 @@ void dcn31_link_encoder_disable_output( } } +bool dcn31_link_encoder_is_in_alt_mode(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + uint32_t dp_alt_mode_disable; + bool is_usb_c_alt_mode = false; + + if (enc->features.flags.bits.DP_IS_USB_C) { + if (enc->ctx->asic_id.hw_internal_rev != YELLOW_CARP_B0) { + // [Note] no need to check hw_internal_rev once phy mux selection is ready + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable); + } else { + /* + * B0 phys use a new set of registers to check whether alt mode is disabled. + * if value == 1 alt mode is disabled, otherwise it is enabled. + */ + if ((enc10->base.transmitter == TRANSMITTER_UNIPHY_A) + || (enc10->base.transmitter == TRANSMITTER_UNIPHY_B) + || (enc10->base.transmitter == TRANSMITTER_UNIPHY_E)) { + REG_GET(RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable); + } else { + // [Note] need to change TRANSMITTER_UNIPHY_C/D to F/G once phy mux selection is ready + REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable); + } + } + + is_usb_c_alt_mode = (dp_alt_mode_disable == 0); + } + + return is_usb_c_alt_mode; +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h index 32d146312838b..bec50e4402ff2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h @@ -69,6 +69,7 @@ SRI(RDPCSTX_PHY_CNTL4, RDPCSTX, id), \ SRI(RDPCSTX_PHY_CNTL5, RDPCSTX, id), \ SRI(RDPCSTX_PHY_CNTL6, RDPCSTX, id), \ + SRI(RDPCSPIPE_PHY_CNTL6, RDPCSPIPE, id), \ SRI(RDPCSTX_PHY_CNTL7, RDPCSTX, id), \ SRI(RDPCSTX_PHY_CNTL8, RDPCSTX, id), \ SRI(RDPCSTX_PHY_CNTL9, RDPCSTX, id), \ @@ -115,7 +116,9 @@ LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX2_MPLL_EN, mask_sh),\ LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DP_TX3_MPLL_EN, mask_sh),\ LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh),\ + LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh),\ + LE_SF(RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE_ACK, mask_sh),\ LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_QUOT, mask_sh),\ LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL7, RDPCS_PHY_DP_MPLLB_FRACN_DEN, mask_sh),\ LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL8, RDPCS_PHY_DP_MPLLB_SSC_PEAK, mask_sh),\ @@ -243,4 +246,10 @@ void dcn31_link_encoder_disable_output( struct link_encoder *enc, enum signal_type signal); +/* + * Check whether USB-C DP Alt mode is disabled + */ +bool dcn31_link_encoder_is_in_alt_mode( + struct link_encoder *enc); + #endif /* __DC_LINK_ENCODER__DCN31_H__ */ diff --git a/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_4_2_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_4_2_0_offset.h index 92caf8441d1e0..01a56556cde13 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_4_2_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_4_2_0_offset.h @@ -11932,5 +11932,32 @@ #define ixDPCSSYS_CR4_RAWLANEX_DIG_PCS_XF_RX_OVRD_OUT_2 0xe0c7 #define ixDPCSSYS_CR4_RAWLANEX_DIG_PCS_XF_TX_OVRD_IN_2 0xe0c8 +//RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6 +#define RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6__RDPCS_PHY_DPALT_DP4__SHIFT 0x10 +#define RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6__RDPCS_PHY_DPALT_DISABLE__SHIFT 0x11 +#define RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6__RDPCS_PHY_DPALT_DISABLE_ACK__SHIFT 0x12 +#define RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6__RDPCS_PHY_DPALT_DP4_MASK 0x00010000L +#define RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6__RDPCS_PHY_DPALT_DISABLE_MASK 0x00020000L +#define RDPCSPIPE0_RDPCSPIPE_PHY_CNTL6__RDPCS_PHY_DPALT_DISABLE_ACK_MASK 0x00040000L + +//RDPCSPIPE1_RDPCSPIPE_PHY_CNTL6 +#define RDPCSPIPE1_RDPCSPIPE_PHY_CNTL6__RDPCS_PHY_DPALT_DP4__SHIFT 0x10 +#define RDPCSPIPE1_RDPCSPIPE_PHY_CNTL6__RDPCS_PHY_DPALT_DISABLE__SHIFT 0x11 +#define RDPCSPIPE1_RDPCSPIPE_PHY_CNTL6__RDPCS_PHY_DPALT_DISABLE_ACK__SHIFT 0x12 +#define RDPCSPIPE1_RDPCSPIPE_PHY_CNTL6__RDPCS_PHY_DPALT_DP4_MASK 0x00010000L +#define RDPCSPIPE1_RDPCSPIPE_PHY_CNTL6__RDPCS_PHY_DPALT_DISABLE_MASK 0x00020000L +#define RDPCSPIPE1_RDPCSPIPE_PHY_CNTL6__RDPCS_PHY_DPALT_DISABLE_ACK_MASK 0x00040000L + +//[Note] Hack. RDPCSPIPE only has 2 instances. +#define regRDPCSPIPE0_RDPCSPIPE_PHY_CNTL6 0x2d73 +#define regRDPCSPIPE0_RDPCSPIPE_PHY_CNTL6_BASE_IDX 2 +#define regRDPCSPIPE1_RDPCSPIPE_PHY_CNTL6 0x2e4b +#define regRDPCSPIPE1_RDPCSPIPE_PHY_CNTL6_BASE_IDX 2 +#define regRDPCSPIPE2_RDPCSPIPE_PHY_CNTL6 0x2d73 +#define regRDPCSPIPE2_RDPCSPIPE_PHY_CNTL6_BASE_IDX 2 +#define regRDPCSPIPE3_RDPCSPIPE_PHY_CNTL6 0x2e4b +#define regRDPCSPIPE3_RDPCSPIPE_PHY_CNTL6_BASE_IDX 2 +#define regRDPCSPIPE4_RDPCSPIPE_PHY_CNTL6 0x2d73 +#define regRDPCSPIPE4_RDPCSPIPE_PHY_CNTL6_BASE_IDX 2 #endif From 05408f24ecc47df5fbf69ae563237ec47d43a32f Mon Sep 17 00:00:00 2001 From: "Liu, Zhan" Date: Fri, 10 Sep 2021 14:50:08 -0400 Subject: [PATCH 138/151] drm/amd/display: DIG mapping change is causing a blocker [Why] DIG mapping change is causing a blocker [How] Revert the change for now. We will re-implement it later. Reviewed-by: Jimmy Kizito Acked-by: Rodrigo Siqueira Signed-off-by: Zhan Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 0b60ac676423c..6f0c788d1904f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -1383,12 +1383,6 @@ static struct stream_encoder *dcn31_stream_encoder_create( return NULL; } - if (ctx->asic_id.chip_family == FAMILY_YELLOW_CARP && - ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) { - if ((eng_id == ENGINE_ID_DIGC) || (eng_id == ENGINE_ID_DIGD)) - eng_id = eng_id + 3; // For B0 only. C->F, D->G. - } - dcn30_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios, eng_id, vpg, afmt, &stream_enc_regs[eng_id], From 39371f7d1396fa281eda67d0ede8221e5d8defe5 Mon Sep 17 00:00:00 2001 From: Meenakshikumar Somasundaram Date: Fri, 10 Sep 2021 11:18:41 -0400 Subject: [PATCH 139/151] drm/amd/display: Creating a fw boot options bit for an upcoming feature [Why] Need a bit for x86 driver to enable a FW boot option for an upcoming feature. [How] Added a bit in dmub_fw_boot_options for an upcoming feature. Reviewed-by: Jimmy Kizito Reviewed-by: Jun Lei Acked-by: Rodrigo Siqueira Signed-off-by: Meenakshikumar Somasundaram Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 1edc5bb4d6683..1b377364ace78 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -372,7 +372,8 @@ union dmub_fw_boot_options { uint32_t reserved2: 1; /**< reserved for an unreleased feature */ uint32_t reserved_unreleased1: 1; /**< reserved for an unreleased feature */ uint32_t invalid_vbios_data: 1; /**< 1 if VBIOS data table is invalid */ - uint32_t reserved : 23; /**< reserved */ + uint32_t reserved_unreleased2: 1; /**< reserved for an unreleased feature */ + uint32_t reserved : 22; /**< reserved */ } bits; /**< boot bits */ uint32_t all; /**< 32-bit access to bits */ }; From 60f39edd897ea134a4ddb789a6795681691c3183 Mon Sep 17 00:00:00 2001 From: Jimmy Kizito Date: Sun, 12 Sep 2021 11:21:52 -0400 Subject: [PATCH 140/151] drm/amd/display: Fix null pointer dereference for encoders [Why] Links which are dynamically assigned link encoders have their link encoder set to NULL. [How] Check that a pointer to a link_encoder object is non-NULL before using it. Reviewed-by: Aric Cyr Reviewed-by: Meenakshikumar Somasundaram Acked-by: Rodrigo Siqueira Signed-off-by: Jimmy Kizito Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 0fe0eb06eaccb..6421c896f2a12 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -5705,7 +5705,7 @@ enum dc_status dp_set_fec_ready(struct dc_link *link, bool ready) link_enc->funcs->fec_set_ready(link_enc, true); link->fec_state = dc_link_fec_ready; } else { - link_enc->funcs->fec_set_ready(link->link_enc, false); + link_enc->funcs->fec_set_ready(link_enc, false); link->fec_state = dc_link_fec_not_ready; dm_error("dpcd write failed to set fec_ready"); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index e1edbfa761f1f..c5e2b4f138fd9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1587,7 +1587,7 @@ void dcn10_power_down_on_boot(struct dc *dc) for (i = 0; i < dc->link_count; i++) { struct dc_link *link = dc->links[i]; - if (link->link_enc->funcs->is_dig_enabled && + if (link->link_enc && link->link_enc->funcs->is_dig_enabled && link->link_enc->funcs->is_dig_enabled(link->link_enc) && dc->hwss.power_down) { dc->hwss.power_down(dc); From 2800ff0e1f899f7ba5f5ccabcb006444675970a4 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sun, 12 Sep 2021 20:04:13 -0400 Subject: [PATCH 141/151] drm/amd/display: [FW Promotion] Release 0.0.84 Acked-by: Rodrigo Siqueira Signed-off-by: Anthony Koo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 1b377364ace78..359f091e37f1d 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -47,10 +47,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0xb24cbe3d +#define DMUB_FW_VERSION_GIT_HASH 0x607c9623 #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 83 +#define DMUB_FW_VERSION_REVISION 84 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 From c719b0cd884a3351eb1bccc8d1b445212b989426 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 13 Sep 2021 00:05:54 -0400 Subject: [PATCH 142/151] drm/amd/display: 3.2.154 This new DC version brings improvements in the following areas: - New firmware version - Fix HPD problems on DCN2 - Fix generic encoder problems and null deferences - Adjust DCN301 watermark - Rework dynamic bpp for DCN3x - Improve link training fallback logic Acked-by: Rodrigo Siqueira Signed-off-by: Aric Cyr Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1306dedc1a982..e5dcbee6e6723 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -45,7 +45,7 @@ /* forward declaration */ struct aux_payload; -#define DC_VER "3.2.153" +#define DC_VER "3.2.154" #define MAX_SURFACES 3 #define MAX_PLANES 6 From 655c167edc8c260b6df08bdcfaca8afde0efbeb6 Mon Sep 17 00:00:00 2001 From: Hayden Goodfellow Date: Sun, 12 Sep 2021 21:32:09 -0400 Subject: [PATCH 143/151] drm/amd/display: Fix wrong format specifier in amdgpu_dm.c [Why] Currently, the 32bit kernel build fails due to an incorrect string format specifier. ARRAY_SIZE() returns size_t type as it uses sizeof(). However, we specify it in a string as %ld. This causes a compiler error and causes the 32bit build to fail. [How] Change the %ld to %zu as size_t (which sizeof() returns) is an unsigned integer data type. We use 'z' to ensure it also works with 64bit build. Reviewed-by: Harry Wentland Acked-by: Rodrigo Siqueira Signed-off-by: Hayden Goodfellow Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1c0547bb09de5..07adac1a8c42b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -760,7 +760,7 @@ static void dm_dmub_outbox1_low_irq(void *interrupt_params) do { dc_stat_get_dmub_notification(adev->dm.dc, ¬ify); if (notify.type > ARRAY_SIZE(dm->dmub_thread_offload)) { - DRM_ERROR("DM: notify type %d larger than the array size %ld !", notify.type, + DRM_ERROR("DM: notify type %d larger than the array size %zu!", notify.type, ARRAY_SIZE(dm->dmub_thread_offload)); continue; } From 6effad8abe0ba4db3d9c58ed585127858a990f35 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Sat, 18 Sep 2021 13:43:41 +0800 Subject: [PATCH 144/151] drm/amdgpu: move amdgpu_virt_release_full_gpu to fini_early stage adev->rmmio is set to be NULL in amdgpu_device_unmap_mmio to prevent access after pci_remove, however, in SRIOV case, amdgpu_virt_release_full_gpu will still use adev->rmmio for access after amdgpu_device_unmap_mmio. The patch is to move such SRIOV calling earlier to fini_early stage. Fixes: 07775fc13878 ("drm/amdgpu: Unmap all MMIO mappings") Cc: Andrey Grodzovsky Signed-off-by: Leslie Shi Signed-off-by: Guchun Chen Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 620c7b773b15a..48089dc0180b5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2745,6 +2745,11 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev) adev->ip_blocks[i].status.hw = false; } + if (amdgpu_sriov_vf(adev)) { + if (amdgpu_virt_release_full_gpu(adev, false)) + DRM_ERROR("failed to release exclusive mode on fini\n"); + } + return 0; } @@ -2805,10 +2810,6 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev) amdgpu_ras_fini(adev); - if (amdgpu_sriov_vf(adev)) - if (amdgpu_virt_release_full_gpu(adev, false)) - DRM_ERROR("failed to release exclusive mode on fini\n"); - return 0; } From 640ae42efb828be69a9ee6ac88fb3d5a3e678ddf Mon Sep 17 00:00:00 2001 From: John Clements Date: Wed, 22 Sep 2021 14:04:52 +0800 Subject: [PATCH 145/151] drm/amdgpu: Updated RAS infrastructure Update RAS infrastructure to support RAS query for MCA subblocks Reviewed-by: Hawking Zhang Signed-off-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c | 8 +- drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 146 ++++++++++++++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 19 ++- drivers/gpu/drm/amd/amdgpu/mca_v3_0.c | 9 +- drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c | 4 +- drivers/gpu/drm/amd/amdgpu/ta_ras_if.h | 11 +- 7 files changed, 146 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c index a2d3dbbf7d257..ce538f4819f92 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c @@ -31,7 +31,7 @@ void amdgpu_mca_query_correctable_error_count(struct amdgpu_device *adev, uint64_t mc_status_addr, unsigned long *error_count) { - uint64_t mc_status = RREG64_PCIE(mc_status_addr * 4); + uint64_t mc_status = RREG64_PCIE(mc_status_addr); if (REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1 && REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, CECC) == 1) @@ -42,7 +42,7 @@ void amdgpu_mca_query_uncorrectable_error_count(struct amdgpu_device *adev, uint64_t mc_status_addr, unsigned long *error_count) { - uint64_t mc_status = RREG64_PCIE(mc_status_addr * 4); + uint64_t mc_status = RREG64_PCIE(mc_status_addr); if ((REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Val) == 1) && (REG_GET_FIELD(mc_status, MCA_UMC_UMC0_MCUMC_STATUST0, Deferred) == 1 || @@ -56,7 +56,7 @@ void amdgpu_mca_query_uncorrectable_error_count(struct amdgpu_device *adev, void amdgpu_mca_reset_error_count(struct amdgpu_device *adev, uint64_t mc_status_addr) { - WREG64_PCIE(mc_status_addr * 4, 0x0ULL); + WREG64_PCIE(mc_status_addr, 0x0ULL); } void amdgpu_mca_query_ras_error_count(struct amdgpu_device *adev, @@ -87,8 +87,8 @@ int amdgpu_mca_ras_late_init(struct amdgpu_device *adev, if (!mca_dev->ras_if) return -ENOMEM; mca_dev->ras_if->block = mca_dev->ras_funcs->ras_block; + mca_dev->ras_if->sub_block_index = mca_dev->ras_funcs->ras_sub_block; mca_dev->ras_if->type = AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE; - mca_dev->ras_if->sub_block_index = 0; } ih_info.head = fs_info.head = *mca_dev->ras_if; r = amdgpu_ras_late_init(adev, mca_dev->ras_if, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h index f860f2f0e296e..c74bc7177066e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h @@ -29,6 +29,7 @@ struct amdgpu_mca_ras_funcs { void (*query_ras_error_address)(struct amdgpu_device *adev, void *ras_error_status); uint32_t ras_block; + uint32_t ras_sub_block; const char* sysfs_name; }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index b5332db4d2873..912ea1f9fd04c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -61,9 +61,30 @@ const char *ras_block_string[] = { "mp0", "mp1", "fuse", - "mpio", + "mca", }; +const char *ras_mca_block_string[] = { + "mca_mp0", + "mca_mp1", + "mca_mpio", + "mca_iohc", +}; + +const char *get_ras_block_str(struct ras_common_if *ras_block) +{ + if (!ras_block) + return "NULL"; + + if (ras_block->block >= AMDGPU_RAS_BLOCK_COUNT) + return "OUT OF RANGE"; + + if (ras_block->block == AMDGPU_RAS_BLOCK__MCA) + return ras_mca_block_string[ras_block->sub_block_index]; + + return ras_block_string[ras_block->block]; +} + #define ras_err_str(i) (ras_error_string[ffs(i)]) #define RAS_DEFAULT_FLAGS (AMDGPU_RAS_FLAG_INIT_BY_VBIOS) @@ -188,7 +209,7 @@ static int amdgpu_ras_find_block_id_by_name(const char *name, int *block_id) for (i = 0; i < ARRAY_SIZE(ras_block_string); i++) { *block_id = i; - if (strcmp(name, ras_block_str(i)) == 0) + if (strcmp(name, ras_block_string[i]) == 0) return 0; } return -EINVAL; @@ -510,7 +531,6 @@ static ssize_t amdgpu_ras_sysfs_read(struct device *dev, if (amdgpu_ras_query_error_status(obj->adev, &info)) return -EINVAL; - if (obj->adev->asic_type == CHIP_ALDEBARAN) { if (amdgpu_ras_reset_error_status(obj->adev, info.head.block)) DRM_WARN("Failed to reset error counter and error status"); @@ -530,7 +550,7 @@ static inline void put_obj(struct ras_manager *obj) if (obj && (--obj->use == 0)) list_del(&obj->node); if (obj && (obj->use < 0)) - DRM_ERROR("RAS ERROR: Unbalance obj(%s) use\n", ras_block_str(obj->head.block)); + DRM_ERROR("RAS ERROR: Unbalance obj(%s) use\n", get_ras_block_str(&obj->head)); } /* make one obj and return it. */ @@ -546,7 +566,14 @@ static struct ras_manager *amdgpu_ras_create_obj(struct amdgpu_device *adev, if (head->block >= AMDGPU_RAS_BLOCK_COUNT) return NULL; - obj = &con->objs[head->block]; + if (head->block == AMDGPU_RAS_BLOCK__MCA) { + if (head->sub_block_index >= AMDGPU_RAS_MCA_BLOCK__LAST) + return NULL; + + obj = &con->objs[AMDGPU_RAS_BLOCK__LAST + head->sub_block_index]; + } else + obj = &con->objs[head->block]; + /* already exist. return obj? */ if (alive_obj(obj)) return NULL; @@ -574,19 +601,21 @@ struct ras_manager *amdgpu_ras_find_obj(struct amdgpu_device *adev, if (head->block >= AMDGPU_RAS_BLOCK_COUNT) return NULL; - obj = &con->objs[head->block]; + if (head->block == AMDGPU_RAS_BLOCK__MCA) { + if (head->sub_block_index >= AMDGPU_RAS_MCA_BLOCK__LAST) + return NULL; + + obj = &con->objs[AMDGPU_RAS_BLOCK__LAST + head->sub_block_index]; + } else + obj = &con->objs[head->block]; - if (alive_obj(obj)) { - WARN_ON(head->block != obj->head.block); + if (alive_obj(obj)) return obj; - } } else { - for (i = 0; i < AMDGPU_RAS_BLOCK_COUNT; i++) { + for (i = 0; i < AMDGPU_RAS_BLOCK_COUNT + AMDGPU_RAS_MCA_BLOCK_COUNT; i++) { obj = &con->objs[i]; - if (alive_obj(obj)) { - WARN_ON(i != obj->head.block); + if (alive_obj(obj)) return obj; - } } } @@ -627,8 +656,6 @@ static int __amdgpu_ras_feature_enable(struct amdgpu_device *adev, */ if (!amdgpu_ras_is_feature_allowed(adev, head)) return 0; - if (!(!!enable ^ !!amdgpu_ras_is_feature_enabled(adev, head))) - return 0; if (enable) { if (!obj) { @@ -679,18 +706,13 @@ int amdgpu_ras_feature_enable(struct amdgpu_device *adev, /* Do not enable if it is not allowed. */ WARN_ON(enable && !amdgpu_ras_is_feature_allowed(adev, head)); - /* Are we alerady in that state we are going to set? */ - if (!(!!enable ^ !!amdgpu_ras_is_feature_enabled(adev, head))) { - ret = 0; - goto out; - } if (!amdgpu_ras_intr_triggered()) { ret = psp_ras_enable_features(&adev->psp, info, enable); if (ret) { dev_err(adev->dev, "ras %s %s failed %d\n", enable ? "enable":"disable", - ras_block_str(head->block), + get_ras_block_str(head), ret); goto out; } @@ -732,7 +754,7 @@ int amdgpu_ras_feature_enable_on_boot(struct amdgpu_device *adev, if (!ret) dev_info(adev->dev, "RAS INFO: %s setup object\n", - ras_block_str(head->block)); + get_ras_block_str(head)); } } else { /* setup the object then issue a ras TA disable cmd.*/ @@ -782,17 +804,39 @@ static int amdgpu_ras_enable_all_features(struct amdgpu_device *adev, bool bypass) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - int ras_block_count = AMDGPU_RAS_BLOCK_COUNT; int i; - const enum amdgpu_ras_error_type default_ras_type = - AMDGPU_RAS_ERROR__NONE; + const enum amdgpu_ras_error_type default_ras_type = AMDGPU_RAS_ERROR__NONE; - for (i = 0; i < ras_block_count; i++) { + for (i = 0; i < AMDGPU_RAS_BLOCK_COUNT; i++) { struct ras_common_if head = { .block = i, .type = default_ras_type, .sub_block_index = 0, }; + + if (i == AMDGPU_RAS_BLOCK__MCA) + continue; + + if (bypass) { + /* + * bypass psp. vbios enable ras for us. + * so just create the obj + */ + if (__amdgpu_ras_feature_enable(adev, &head, 1)) + break; + } else { + if (amdgpu_ras_feature_enable(adev, &head, 1)) + break; + } + } + + for (i = 0; i < AMDGPU_RAS_MCA_BLOCK_COUNT; i++) { + struct ras_common_if head = { + .block = AMDGPU_RAS_BLOCK__MCA, + .type = default_ras_type, + .sub_block_index = i, + }; + if (bypass) { /* * bypass psp. vbios enable ras for us. @@ -810,6 +854,32 @@ static int amdgpu_ras_enable_all_features(struct amdgpu_device *adev, } /* feature ctl end */ + +void amdgpu_ras_mca_query_error_status(struct amdgpu_device *adev, + struct ras_common_if *ras_block, + struct ras_err_data *err_data) +{ + switch (ras_block->sub_block_index) { + case AMDGPU_RAS_MCA_BLOCK__MP0: + if (adev->mca.mp0.ras_funcs && + adev->mca.mp0.ras_funcs->query_ras_error_count) + adev->mca.mp0.ras_funcs->query_ras_error_count(adev, &err_data); + break; + case AMDGPU_RAS_MCA_BLOCK__MP1: + if (adev->mca.mp1.ras_funcs && + adev->mca.mp1.ras_funcs->query_ras_error_count) + adev->mca.mp1.ras_funcs->query_ras_error_count(adev, &err_data); + break; + case AMDGPU_RAS_MCA_BLOCK__MPIO: + if (adev->mca.mpio.ras_funcs && + adev->mca.mpio.ras_funcs->query_ras_error_count) + adev->mca.mpio.ras_funcs->query_ras_error_count(adev, &err_data); + break; + default: + break; + } +} + /* query/inject/cure begin */ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_if *info) @@ -873,6 +943,9 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, adev->hdp.ras_funcs->query_ras_error_count) adev->hdp.ras_funcs->query_ras_error_count(adev, &err_data); break; + case AMDGPU_RAS_BLOCK__MCA: + amdgpu_ras_mca_query_error_status(adev, &info->head, &err_data); + break; default: break; } @@ -894,13 +967,13 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, adev->smuio.funcs->get_socket_id(adev), adev->smuio.funcs->get_die_id(adev), obj->err_data.ce_count, - ras_block_str(info->head.block)); + get_ras_block_str(&info->head)); } else { dev_info(adev->dev, "%ld correctable hardware errors " "detected in %s block, no user " "action is needed.\n", obj->err_data.ce_count, - ras_block_str(info->head.block)); + get_ras_block_str(&info->head)); } } if (err_data.ue_count) { @@ -913,12 +986,12 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, adev->smuio.funcs->get_socket_id(adev), adev->smuio.funcs->get_die_id(adev), obj->err_data.ue_count, - ras_block_str(info->head.block)); + get_ras_block_str(&info->head)); } else { dev_info(adev->dev, "%ld uncorrectable hardware errors " "detected in %s block\n", obj->err_data.ue_count, - ras_block_str(info->head.block)); + get_ras_block_str(&info->head)); } } @@ -1028,9 +1101,7 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev, case AMDGPU_RAS_BLOCK__SDMA: case AMDGPU_RAS_BLOCK__MMHUB: case AMDGPU_RAS_BLOCK__PCIE_BIF: - case AMDGPU_RAS_BLOCK__MP0: - case AMDGPU_RAS_BLOCK__MP1: - case AMDGPU_RAS_BLOCK__MPIO: + case AMDGPU_RAS_BLOCK__MCA: ret = psp_ras_trigger_error(&adev->psp, &block_info); break; case AMDGPU_RAS_BLOCK__XGMI_WAFL: @@ -1038,13 +1109,13 @@ int amdgpu_ras_error_inject(struct amdgpu_device *adev, break; default: dev_info(adev->dev, "%s error injection is not supported yet\n", - ras_block_str(info->head.block)); + get_ras_block_str(&info->head)); ret = -EINVAL; } if (ret) dev_err(adev->dev, "ras inject %s failed %d\n", - ras_block_str(info->head.block), ret); + get_ras_block_str(&info->head), ret); return ret; } @@ -1387,7 +1458,7 @@ void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev) if (amdgpu_ras_is_supported(adev, obj->head.block) && (obj->attr_inuse == 1)) { sprintf(fs_info.debugfs_name, "%s_err_inject", - ras_block_str(obj->head.block)); + get_ras_block_str(&obj->head)); fs_info.head = obj->head; amdgpu_ras_debugfs_create(adev, &fs_info, dir); } @@ -2185,7 +2256,8 @@ int amdgpu_ras_init(struct amdgpu_device *adev) return 0; con = kmalloc(sizeof(struct amdgpu_ras) + - sizeof(struct ras_manager) * AMDGPU_RAS_BLOCK_COUNT, + sizeof(struct ras_manager) * AMDGPU_RAS_BLOCK_COUNT + + sizeof(struct ras_manager) * AMDGPU_RAS_MCA_BLOCK_COUNT, GFP_KERNEL|__GFP_ZERO); if (!con) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 1670467c20546..ec42e9873aaa9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -49,15 +49,22 @@ enum amdgpu_ras_block { AMDGPU_RAS_BLOCK__MP0, AMDGPU_RAS_BLOCK__MP1, AMDGPU_RAS_BLOCK__FUSE, - AMDGPU_RAS_BLOCK__MPIO, + AMDGPU_RAS_BLOCK__MCA, AMDGPU_RAS_BLOCK__LAST }; -extern const char *ras_block_string[]; +enum amdgpu_ras_mca_block { + AMDGPU_RAS_MCA_BLOCK__MP0 = 0, + AMDGPU_RAS_MCA_BLOCK__MP1, + AMDGPU_RAS_MCA_BLOCK__MPIO, + AMDGPU_RAS_MCA_BLOCK__IOHC, + + AMDGPU_RAS_MCA_BLOCK__LAST +}; -#define ras_block_str(i) (ras_block_string[i]) #define AMDGPU_RAS_BLOCK_COUNT AMDGPU_RAS_BLOCK__LAST +#define AMDGPU_RAS_MCA_BLOCK_COUNT AMDGPU_RAS_MCA_BLOCK__LAST #define AMDGPU_RAS_BLOCK_MASK ((1ULL << AMDGPU_RAS_BLOCK_COUNT) - 1) enum amdgpu_ras_gfx_subblock { @@ -544,8 +551,8 @@ amdgpu_ras_block_to_ta(enum amdgpu_ras_block block) { return TA_RAS_BLOCK__MP1; case AMDGPU_RAS_BLOCK__FUSE: return TA_RAS_BLOCK__FUSE; - case AMDGPU_RAS_BLOCK__MPIO: - return TA_RAS_BLOCK__MPIO; + case AMDGPU_RAS_BLOCK__MCA: + return TA_RAS_BLOCK__MCA; default: WARN_ONCE(1, "RAS ERROR: unexpected block id %d\n", block); return TA_RAS_BLOCK__UMC; @@ -640,4 +647,6 @@ void amdgpu_release_ras_context(struct amdgpu_device *adev); int amdgpu_persistent_edc_harvesting_supported(struct amdgpu_device *adev); +const char *get_ras_block_str(struct ras_common_if *ras_block); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c b/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c index 058b65730a846..8f7107d392afb 100644 --- a/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mca_v3_0.c @@ -52,7 +52,8 @@ const struct amdgpu_mca_ras_funcs mca_v3_0_mp0_ras_funcs = { .ras_fini = mca_v3_0_mp0_ras_fini, .query_ras_error_count = mca_v3_0_mp0_query_ras_error_count, .query_ras_error_address = NULL, - .ras_block = AMDGPU_RAS_BLOCK__MP0, + .ras_block = AMDGPU_RAS_BLOCK__MCA, + .ras_sub_block = AMDGPU_RAS_MCA_BLOCK__MP0, .sysfs_name = "mp0_err_count", }; @@ -79,7 +80,8 @@ const struct amdgpu_mca_ras_funcs mca_v3_0_mp1_ras_funcs = { .ras_fini = mca_v3_0_mp1_ras_fini, .query_ras_error_count = mca_v3_0_mp1_query_ras_error_count, .query_ras_error_address = NULL, - .ras_block = AMDGPU_RAS_BLOCK__MP1, + .ras_block = AMDGPU_RAS_BLOCK__MCA, + .ras_sub_block = AMDGPU_RAS_MCA_BLOCK__MP1, .sysfs_name = "mp1_err_count", }; @@ -106,7 +108,8 @@ const struct amdgpu_mca_ras_funcs mca_v3_0_mpio_ras_funcs = { .ras_fini = mca_v3_0_mpio_ras_fini, .query_ras_error_count = mca_v3_0_mpio_query_ras_error_count, .query_ras_error_address = NULL, - .ras_block = AMDGPU_RAS_BLOCK__MPIO, + .ras_block = AMDGPU_RAS_BLOCK__MCA, + .ras_sub_block = AMDGPU_RAS_MCA_BLOCK__MPIO, .sysfs_name = "mpio_err_count", }; diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c index 0a9fc19b1be02..91b3afa946f59 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c @@ -387,13 +387,13 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device "errors detected in %s block, " "no user action is needed.\n", obj->err_data.ce_count, - ras_block_str(adev->nbio.ras_if->block)); + get_ras_block_str(adev->nbio.ras_if)); if (err_data.ue_count) dev_info(adev->dev, "%ld uncorrectable hardware " "errors detected in %s block\n", obj->err_data.ue_count, - ras_block_str(adev->nbio.ras_if->block)); + get_ras_block_str(adev->nbio.ras_if)); } dev_info(adev->dev, "RAS controller interrupt triggered " diff --git a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h index 532260fd64db1..82d956d15b54f 100644 --- a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h +++ b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h @@ -73,10 +73,19 @@ enum ta_ras_block { TA_RAS_BLOCK__MP0, TA_RAS_BLOCK__MP1, TA_RAS_BLOCK__FUSE, - TA_RAS_BLOCK__MPIO, + TA_RAS_BLOCK__MCA, TA_NUM_BLOCK_MAX }; +enum ta_ras_mca_block +{ + TA_RAS_MCA_BLOCK__MP0 = 0, + TA_RAS_MCA_BLOCK__MP1 = 1, + TA_RAS_MCA_BLOCK__MPIO = 2, + TA_RAS_MCA_BLOCK__IOHC = 3, + TA_MCA_NUM_BLOCK_MAX +}; + enum ta_ras_error_type { TA_RAS_ERROR__NONE = 0, TA_RAS_ERROR__PARITY = 1, From 586d71a42725dbc67cbb15f9904c65d99a757b0f Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Fri, 17 Sep 2021 14:32:14 -0400 Subject: [PATCH 146/151] drm/amdkfd: handle svm migrate init error If svm migration init failed to create pgmap for device memory, set pgmap type to 0 to disable device SVM support capability. Signed-off-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index dab290a4d19d1..165e0ebb619da 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -894,6 +894,9 @@ int svm_migrate_init(struct amdgpu_device *adev) r = devm_memremap_pages(adev->dev, pgmap); if (IS_ERR(r)) { pr_err("failed to register HMM device memory\n"); + + /* Disable SVM support capability */ + pgmap->type = 0; devm_release_mem_region(adev->dev, res->start, res->end - res->start + 1); return PTR_ERR(r); From 22f4f4faf337d5fb2d2750aff13215726814273e Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Mon, 20 Sep 2021 17:25:52 -0400 Subject: [PATCH 147/151] drm/amdkfd: fix svm_migrate_fini warning Device manager releases device-specific resources when a driver disconnects from a device, devm_memunmap_pages and devm_release_mem_region calls in svm_migrate_fini are redundant. It causes below warning trace after patch "drm/amdgpu: Split amdgpu_device_fini into early and late", so remove function svm_migrate_fini. BUG: https://gitlab.freedesktop.org/drm/amd/-/issues/1718 WARNING: CPU: 1 PID: 3646 at drivers/base/devres.c:795 devm_release_action+0x51/0x60 Call Trace: ? memunmap_pages+0x360/0x360 svm_migrate_fini+0x2d/0x60 [amdgpu] kgd2kfd_device_exit+0x23/0xa0 [amdgpu] amdgpu_amdkfd_device_fini_sw+0x1d/0x30 [amdgpu] amdgpu_device_fini_sw+0x45/0x290 [amdgpu] amdgpu_driver_release_kms+0x12/0x30 [amdgpu] drm_dev_release+0x20/0x40 [drm] release_nodes+0x196/0x1e0 device_release_driver_internal+0x104/0x1d0 driver_detach+0x47/0x90 bus_remove_driver+0x7a/0xd0 pci_unregister_driver+0x3d/0x90 amdgpu_exit+0x11/0x20 [amdgpu] Signed-off-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 1 - drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 13 ++++--------- drivers/gpu/drm/amd/amdkfd/kfd_migrate.h | 5 ----- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 98d1b3ab3a464..c2a4d920da40e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -971,7 +971,6 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, void kgd2kfd_device_exit(struct kfd_dev *kfd) { if (kfd->init_complete) { - svm_migrate_fini((struct amdgpu_device *)kfd->kgd); device_queue_manager_uninit(kfd->dqm); kfd_interrupt_exit(kfd); kfd_topology_remove_device(kfd); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index 165e0ebb619da..4a16e3c257b92 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -891,6 +891,10 @@ int svm_migrate_init(struct amdgpu_device *adev) pgmap->ops = &svm_migrate_pgmap_ops; pgmap->owner = SVM_ADEV_PGMAP_OWNER(adev); pgmap->flags = MIGRATE_VMA_SELECT_DEVICE_PRIVATE; + + /* Device manager releases device-specific resources, memory region and + * pgmap when driver disconnects from device. + */ r = devm_memremap_pages(adev->dev, pgmap); if (IS_ERR(r)) { pr_err("failed to register HMM device memory\n"); @@ -911,12 +915,3 @@ int svm_migrate_init(struct amdgpu_device *adev) return 0; } - -void svm_migrate_fini(struct amdgpu_device *adev) -{ - struct dev_pagemap *pgmap = &adev->kfd.dev->pgmap; - - devm_memunmap_pages(adev->dev, pgmap); - devm_release_mem_region(adev->dev, pgmap->range.start, - pgmap->range.end - pgmap->range.start + 1); -} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h index 0de76b5d49739..2f5b3394c9ed9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.h @@ -47,7 +47,6 @@ unsigned long svm_migrate_addr_to_pfn(struct amdgpu_device *adev, unsigned long addr); int svm_migrate_init(struct amdgpu_device *adev); -void svm_migrate_fini(struct amdgpu_device *adev); #else @@ -55,10 +54,6 @@ static inline int svm_migrate_init(struct amdgpu_device *adev) { return 0; } -static inline void svm_migrate_fini(struct amdgpu_device *adev) -{ - /* empty */ -} #endif /* IS_ENABLED(CONFIG_HSA_AMD_SVM) */ From 73490d26588443ba95cfcca00b6ac2267718fcdd Mon Sep 17 00:00:00 2001 From: John Clements Date: Thu, 23 Sep 2021 16:36:09 +0800 Subject: [PATCH 148/151] drm/amdgpu: Consolidate RAS cmd warning messages Explicity post warning if cmd is issued against unsupported IP Update to latest RAS TA interface Reviewed-by: Hawking Zhang Signed-off-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 12 ++++---- drivers/gpu/drm/amd/amdgpu/ta_ras_if.h | 40 ++++++++++++------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 7d09b28889afe..55ffc3da89ced 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1311,6 +1311,11 @@ int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id) else if (ras_cmd->ras_out_message.flags.reg_access_failure_flag) dev_warn(psp->adev->dev, "RAS internal register access blocked\n"); + + if (ras_cmd->ras_status == TA_RAS_STATUS__ERROR_UNSUPPORTED_IP) + dev_warn(psp->adev->dev, "RAS WARNING: cmd failed due to unsupported ip\n"); + else if (ras_cmd->ras_status) + dev_warn(psp->adev->dev, "RAS WARNING: ras status = 0x%X\n", ras_cmd->ras_status); } return ret; @@ -1339,9 +1344,6 @@ int psp_ras_enable_features(struct psp_context *psp, if (ret) return -EINVAL; - if (ras_cmd->ras_status) - dev_warn(psp->adev->dev, "RAS WARNING: ras status = 0x%X\n", ras_cmd->ras_status); - return 0; } @@ -1484,10 +1486,8 @@ int psp_ras_trigger_error(struct psp_context *psp, if (amdgpu_ras_intr_triggered()) return 0; - if (ras_cmd->ras_status) { - dev_warn(psp->adev->dev, "RAS WARNING: ras status = 0x%X\n", ras_cmd->ras_status); + if (ras_cmd->ras_status) return -EINVAL; - } return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h index 82d956d15b54f..de24a0a97d5e5 100644 --- a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h +++ b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h @@ -38,9 +38,8 @@ enum ras_command { TA_RAS_COMMAND__TRIGGER_ERROR, }; -enum ta_ras_status -{ - TA_RAS_STATUS__SUCCESS = 0x00, +enum ta_ras_status { + TA_RAS_STATUS__SUCCESS = 0x0000, TA_RAS_STATUS__RESET_NEEDED = 0xA001, TA_RAS_STATUS__ERROR_INVALID_PARAMETER = 0xA002, TA_RAS_STATUS__ERROR_RAS_NOT_AVAILABLE = 0xA003, @@ -55,7 +54,12 @@ enum ta_ras_status TA_RAS_STATUS__ERROR_GET_DEV_INFO = 0xA00C, TA_RAS_STATUS__ERROR_UNSUPPORTED_DEV = 0xA00D, TA_RAS_STATUS__ERROR_NOT_INITIALIZED = 0xA00E, - TA_RAS_STATUS__ERROR_TEE_INTERNAL = 0xA00F + TA_RAS_STATUS__ERROR_TEE_INTERNAL = 0xA00F, + TA_RAS_STATUS__ERROR_UNSUPPORTED_FUNCTION = 0xA010, + TA_RAS_STATUS__ERROR_SYS_DRV_REG_ACCESS = 0xA011, + TA_RAS_STATUS__ERROR_RAS_READ_WRITE = 0xA012, + TA_RAS_STATUS__ERROR_NULL_PTR = 0xA013, + TA_RAS_STATUS__ERROR_UNSUPPORTED_IP = 0xA014 }; enum ta_ras_block { @@ -77,8 +81,7 @@ enum ta_ras_block { TA_NUM_BLOCK_MAX }; -enum ta_ras_mca_block -{ +enum ta_ras_mca_block { TA_RAS_MCA_BLOCK__MP0 = 0, TA_RAS_MCA_BLOCK__MP1 = 1, TA_RAS_MCA_BLOCK__MPIO = 2, @@ -115,17 +118,15 @@ struct ta_ras_trigger_error_input { uint64_t value; // method if error injection. i.e persistent, coherent etc. }; -struct ta_ras_init_flags -{ - uint8_t poison_mode_en; - uint8_t dgpu_mode; +struct ta_ras_init_flags { + uint8_t poison_mode_en; + uint8_t dgpu_mode; }; -struct ta_ras_output_flags -{ - uint8_t ras_init_success_flag; - uint8_t err_inject_switch_disable_flag; - uint8_t reg_access_failure_flag; +struct ta_ras_output_flags { + uint8_t ras_init_success_flag; + uint8_t err_inject_switch_disable_flag; + uint8_t reg_access_failure_flag; }; /* Common input structure for RAS callbacks */ @@ -136,14 +137,13 @@ union ta_ras_cmd_input { struct ta_ras_disable_features_input disable_features; struct ta_ras_trigger_error_input trigger_error; - uint32_t reserve_pad[256]; + uint32_t reserve_pad[256]; }; -union ta_ras_cmd_output -{ - struct ta_ras_output_flags flags; +union ta_ras_cmd_output { + struct ta_ras_output_flags flags; - uint32_t reserve_pad[256]; + uint32_t reserve_pad[256]; }; /* Shared Memory structures */ From 9080a18fc554cea0858fae6692a7003c5f0365fc Mon Sep 17 00:00:00 2001 From: Candice Li Date: Wed, 15 Sep 2021 15:14:18 +0800 Subject: [PATCH 149/151] drm/amdgpu: Remove all code paths under the EAGAIN path in RAS late init All code paths under the EAGAIN path in RAS late init are unused. Signed-off-by: Candice Li Reviewed-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 33 +------------------------ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 3 --- 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 912ea1f9fd04c..e1c34eef76b7c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2131,19 +2131,6 @@ static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev) } /* recovery end */ -/* return 0 if ras will reset gpu and repost.*/ -int amdgpu_ras_request_reset_on_boot(struct amdgpu_device *adev, - unsigned int block) -{ - struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - - if (!ras) - return -EINVAL; - - ras->flags |= AMDGPU_RAS_FLAG_INIT_NEED_RESET; - return 0; -} - static bool amdgpu_ras_asic_supported(struct amdgpu_device *adev) { return adev->asic_type == CHIP_VEGA10 || @@ -2382,12 +2369,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev, r = amdgpu_ras_feature_enable_on_boot(adev, ras_block, 1); if (r) { - if (r == -EAGAIN) { - /* request gpu reset. will run again */ - amdgpu_ras_request_reset_on_boot(adev, - ras_block->block); - return 0; - } else if (adev->in_suspend || amdgpu_in_reset(adev)) { + if (adev->in_suspend || amdgpu_in_reset(adev)) { /* in resume phase, if fail to enable ras, * clean up all ras fs nodes, and disable ras */ goto cleanup; @@ -2479,19 +2461,6 @@ void amdgpu_ras_resume(struct amdgpu_device *adev) } } } - - if (con->flags & AMDGPU_RAS_FLAG_INIT_NEED_RESET) { - con->flags &= ~AMDGPU_RAS_FLAG_INIT_NEED_RESET; - /* setup ras obj state as disabled. - * for init_by_vbios case. - * if we want to enable ras, just enable it in a normal way. - * If we want do disable it, need setup ras obj as enabled, - * then issue another TA disable cmd. - * See feature_enable_on_boot - */ - amdgpu_ras_disable_all_features(adev, 1); - amdgpu_ras_reset_gpu(adev); - } } void amdgpu_ras_suspend(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index ec42e9873aaa9..37b3c40272b4c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -32,7 +32,6 @@ #include "amdgpu_ras_eeprom.h" #define AMDGPU_RAS_FLAG_INIT_BY_VBIOS (0x1 << 0) -#define AMDGPU_RAS_FLAG_INIT_NEED_RESET (0x1 << 1) enum amdgpu_ras_block { AMDGPU_RAS_BLOCK__UMC = 0, @@ -495,8 +494,6 @@ static inline int amdgpu_ras_is_supported(struct amdgpu_device *adev, } int amdgpu_ras_recovery_init(struct amdgpu_device *adev); -int amdgpu_ras_request_reset_on_boot(struct amdgpu_device *adev, - unsigned int block); void amdgpu_ras_resume(struct amdgpu_device *adev); void amdgpu_ras_suspend(struct amdgpu_device *adev); From 7f19e11d0e936548ce4b8e4ec36d5680c7ffea20 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Thu, 23 Sep 2021 11:58:43 +0800 Subject: [PATCH 150/151] drm/amd/pm: Update intermediate power state for SI Update the current state as boot state during dpm initialization. During the subsequent initialization, set_power_state gets called to transition to the final power state. set_power_state refers to values from the current state and without current state populated, it could result in NULL pointer dereference. For ex: on platforms where PCI speed change is supported through ACPI ATCS method, the link speed of current state needs to be queried before deciding on changing to final power state's link speed. The logic to query ATCS-support was broken on certain platforms. The issue became visible when broken ATCS-support logic got fixed with commit f9b7f3703ff9 ("drm/amdgpu/acpi: make ATPX/ATCS structures global (v2)"). Bug:https://gitlab.freedesktop.org/drm/amd/-/issues/1698 Signed-off-by: Lijo Lazar Reviewed-by: Hawking Zhang Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/si_dpm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c index bdbbeb959c681..81f82aa05ec28 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c @@ -6867,6 +6867,8 @@ static int si_dpm_enable(struct amdgpu_device *adev) si_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, true); si_thermal_start_thermal_controller(adev); + ni_update_current_ps(adev, boot_ps); + return 0; } From 2485e2753ec896b169526e3ef7988589d1c458f5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 30 Jul 2021 14:46:53 -0400 Subject: [PATCH 151/151] drm/amdgpu: make soc15_common_ip_funcs static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's not used outside of soc15.c Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 4 +++- drivers/gpu/drm/amd/amdgpu/soc15.h | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 0fc97c364fd76..15e295a1412c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -85,6 +85,8 @@ #define mmMP0_MISC_LIGHT_SLEEP_CTRL 0x01ba #define mmMP0_MISC_LIGHT_SLEEP_CTRL_BASE_IDX 0 +static const struct amd_ip_funcs soc15_common_ip_funcs; + /* Vega, Raven, Arcturus */ static const struct amdgpu_video_codec_info vega_video_codecs_encode_array[] = { @@ -1645,7 +1647,7 @@ static int soc15_common_set_powergating_state(void *handle, return 0; } -const struct amd_ip_funcs soc15_common_ip_funcs = { +static const struct amd_ip_funcs soc15_common_ip_funcs = { .name = "soc15_common", .early_init = soc15_common_early_init, .late_init = soc15_common_late_init, diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.h b/drivers/gpu/drm/amd/amdgpu/soc15.h index 034cfdfc4dbe7..a025339ac5e99 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.h +++ b/drivers/gpu/drm/amd/amdgpu/soc15.h @@ -31,8 +31,6 @@ #define SOC15_FLUSH_GPU_TLB_NUM_WREG 6 #define SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT 3 -extern const struct amd_ip_funcs soc15_common_ip_funcs; - struct soc15_reg_golden { u32 hwip; u32 instance;