From: Bhuvanachandra Pinninti <[email protected]> [why] Direct DIO registers access in hwseq layer was creating register conflicts.
[how] Migrated DIO registers from hwseq to dio component. Reviewed-by: Jun Lei <[email protected]> Signed-off-by: Bhuvanachandra Pinninti <[email protected]> Signed-off-by: Wayne Lin <[email protected]> --- drivers/gpu/drm/amd/display/dc/dio/Makefile | 2 +- .../drm/amd/display/dc/dio/dcn10/dcn10_dio.c | 47 +++++++++++++++++++ .../drm/amd/display/dc/dio/dcn10/dcn10_dio.h | 42 +++++++++++++++++ .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 4 +- .../amd/display/dc/hwss/dcn201/dcn201_hwseq.c | 5 +- .../amd/display/dc/hwss/dcn30/dcn30_hwseq.c | 4 +- .../amd/display/dc/hwss/dcn31/dcn31_hwseq.c | 10 ++-- .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 4 +- .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 10 ++-- .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 4 +- .../gpu/drm/amd/display/dc/inc/core_types.h | 2 + drivers/gpu/drm/amd/display/dc/inc/hw/dio.h | 22 +++++++++ .../dc/resource/dcn401/dcn401_resource.c | 41 ++++++++++++++++ 13 files changed, 179 insertions(+), 18 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_dio.c create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_dio.h create mode 100644 drivers/gpu/drm/amd/display/dc/inc/hw/dio.h diff --git a/drivers/gpu/drm/amd/display/dc/dio/Makefile b/drivers/gpu/drm/amd/display/dc/dio/Makefile index 0dfd480976f7..02eec03dc204 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dio/Makefile @@ -27,7 +27,7 @@ ifdef CONFIG_DRM_AMD_DC_FP ############################################################################### # DCN10 ############################################################################### -DIO_DCN10 = dcn10_link_encoder.o dcn10_stream_encoder.o +DIO_DCN10 = dcn10_link_encoder.o dcn10_stream_encoder.o dcn10_dio.o AMD_DAL_DIO_DCN10 = $(addprefix $(AMDDALPATH)/dc/dio/dcn10/,$(DIO_DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_dio.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_dio.c new file mode 100644 index 000000000000..edcf4e67483b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_dio.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2025 Advanced Micro Devices, Inc. + +#include "dc_hw_types.h" +#include "dm_services.h" +#include "reg_helper.h" +#include "dcn10_dio.h" + +#define CTX \ + dio10->base.ctx +#define REG(reg)\ + dio10->regs->reg + +#undef FN +#define FN(reg_name, field_name) \ + dio10->shifts->field_name, dio10->masks->field_name + +static void dcn10_dio_mem_pwr_ctrl(struct dio *dio, bool enable_i2c_light_sleep) +{ + struct dcn10_dio *dio10 = TO_DCN10_DIO(dio); + + /* power AFMT HDMI memory */ + REG_WRITE(DIO_MEM_PWR_CTRL, 0); + + if (enable_i2c_light_sleep) + REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 1); +} + +static const struct dio_funcs dcn10_dio_funcs = { + .mem_pwr_ctrl = dcn10_dio_mem_pwr_ctrl, +}; + +void dcn10_dio_construct( + struct dcn10_dio *dio10, + struct dc_context *ctx, + const struct dcn_dio_registers *regs, + const struct dcn_dio_shift *shifts, + const struct dcn_dio_mask *masks) +{ + dio10->base.ctx = ctx; + dio10->base.funcs = &dcn10_dio_funcs; + + dio10->regs = regs; + dio10->shifts = shifts; + dio10->masks = masks; +} diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_dio.h b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_dio.h new file mode 100644 index 000000000000..369c5996326e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_dio.h @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2025 Advanced Micro Devices, Inc. + +#ifndef __DCN10_DIO_H__ +#define __DCN10_DIO_H__ + +#include "dio.h" + +#define TO_DCN10_DIO(dio_base) \ + container_of(dio_base, struct dcn10_dio, base) + +#define DIO_REG_LIST_DCN10()\ + SR(DIO_MEM_PWR_CTRL) + +struct dcn_dio_registers { + uint32_t DIO_MEM_PWR_CTRL; +}; + +struct dcn_dio_shift { + uint8_t I2C_LIGHT_SLEEP_FORCE; +}; + +struct dcn_dio_mask { + uint32_t I2C_LIGHT_SLEEP_FORCE; +}; + +struct dcn10_dio { + struct dio base; + const struct dcn_dio_registers *regs; + const struct dcn_dio_shift *shifts; + const struct dcn_dio_mask *masks; +}; + +void dcn10_dio_construct( + struct dcn10_dio *dio10, + struct dc_context *ctx, + const struct dcn_dio_registers *regs, + const struct dcn_dio_shift *shifts, + const struct dcn_dio_mask *masks); + +#endif /* __DCN10_DIO_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c index f89b2f5a9bbd..5243177c1faa 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c @@ -50,6 +50,7 @@ #include "link_hwss.h" #include "dpcd_defs.h" #include "dsc.h" +#include "dio/dcn10/dcn10_dio.h" #include "dce/dmub_psr.h" #include "dc_dmub_srv.h" #include "dce/dmub_hw_lock_mgr.h" @@ -1881,7 +1882,8 @@ void dcn10_init_hw(struct dc *dc) /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ if (!is_optimized_init_done) - REG_WRITE(DIO_MEM_PWR_CTRL, 0); + if (dc->res_pool->dio && dc->res_pool->dio->funcs->mem_pwr_ctrl) + dc->res_pool->dio->funcs->mem_pwr_ctrl(dc->res_pool->dio, false); if (!dc->debug.disable_clock_gate) { /* enable all DCN clock gating */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c index 7cd225a6cf6c..ce18d75fd991 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c @@ -40,6 +40,8 @@ #include "clk_mgr.h" #include "reg_helper.h" #include "dcn10/dcn10_hubbub.h" +#include "dio/dcn10/dcn10_dio.h" + #define CTX \ hws->ctx @@ -360,7 +362,8 @@ void dcn201_init_hw(struct dc *dc) } /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ - REG_WRITE(DIO_MEM_PWR_CTRL, 0); + if (dc->res_pool->dio && dc->res_pool->dio->funcs->mem_pwr_ctrl) + dc->res_pool->dio->funcs->mem_pwr_ctrl(dc->res_pool->dio, false); if (!dc->debug.disable_clock_gate) { /* enable all DCN clock gating */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c index 3ff15ec9dc17..d58f2cf2615c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c @@ -53,6 +53,7 @@ #include "dcn30/dcn30_resource.h" #include "link_service.h" #include "dc_state_priv.h" +#include "dio/dcn10/dcn10_dio.h" #define TO_DCN_DCCG(dccg)\ container_of(dccg, struct dcn_dccg, base) @@ -794,7 +795,8 @@ void dcn30_init_hw(struct dc *dc) } /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ - REG_WRITE(DIO_MEM_PWR_CTRL, 0); + if (dc->res_pool->dio && dc->res_pool->dio->funcs->mem_pwr_ctrl) + dc->res_pool->dio->funcs->mem_pwr_ctrl(dc->res_pool->dio, false); if (!dc->debug.disable_clock_gate) { /* enable all DCN clock gating */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c index 91a672a46289..db2f7cbb12ff 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c @@ -53,6 +53,7 @@ #include "dcn30/dcn30_vpg.h" #include "dce/dce_i2c_hw.h" #include "dce/dmub_abm_lcd.h" +#include "dio/dcn10/dcn10_dio.h" #define DC_LOGGER_INIT(logger) @@ -237,12 +238,9 @@ void dcn31_init_hw(struct dc *dc) abms[i]->funcs->abm_init(abms[i], backlight, user_level); } - /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ - REG_WRITE(DIO_MEM_PWR_CTRL, 0); - - // Set i2c to light sleep until engine is setup - if (dc->debug.enable_mem_low_power.bits.i2c) - REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 1); + /* Power on DIO memory (AFMT HDMI) and set I2C to light sleep */ + if (dc->res_pool->dio && dc->res_pool->dio->funcs->mem_pwr_ctrl) + dc->res_pool->dio->funcs->mem_pwr_ctrl(dc->res_pool->dio, dc->debug.enable_mem_low_power.bits.i2c); if (hws->funcs.setup_hpo_hw_control) hws->funcs.setup_hpo_hw_control(hws, false); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c index 3f76fba7dccc..37300e12e645 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c @@ -52,6 +52,7 @@ #include "link_service.h" #include "../dcn20/dcn20_hwseq.h" #include "dc_state_priv.h" +#include "dio/dcn10/dcn10_dio.h" #define DC_LOGGER_INIT(logger) @@ -955,7 +956,8 @@ void dcn32_init_hw(struct dc *dc) } /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ - REG_WRITE(DIO_MEM_PWR_CTRL, 0); + if (dc->res_pool->dio && dc->res_pool->dio->funcs->mem_pwr_ctrl) + dc->res_pool->dio->funcs->mem_pwr_ctrl(dc->res_pool->dio, false); if (!dc->debug.disable_clock_gate) { /* enable all DCN clock gating */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index 1c7263f9ef51..b5a4cefbd35f 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -53,6 +53,7 @@ #include "dcn30/dcn30_vpg.h" #include "dce/dce_i2c_hw.h" #include "dsc.h" +#include "dio/dcn10/dcn10_dio.h" #include "dcn20/dcn20_optc.h" #include "dcn30/dcn30_cm_common.h" #include "dcn31/dcn31_hwseq.h" @@ -272,12 +273,9 @@ void dcn35_init_hw(struct dc *dc) } } - /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ - REG_WRITE(DIO_MEM_PWR_CTRL, 0); - - // Set i2c to light sleep until engine is setup - if (dc->debug.enable_mem_low_power.bits.i2c) - REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 0); + /* Power on DIO memory (AFMT HDMI) and optionally disable I2C light sleep */ + if (dc->res_pool->dio && dc->res_pool->dio->funcs->mem_pwr_ctrl) + dc->res_pool->dio->funcs->mem_pwr_ctrl(dc->res_pool->dio, !dc->debug.enable_mem_low_power.bits.i2c); if (hws->funcs.setup_hpo_hw_control) hws->funcs.setup_hpo_hw_control(hws, false); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 567ed207d7cd..9cda39d0ed95 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -39,6 +39,7 @@ #include "dc_state_priv.h" #include "link_enc_cfg.h" #include "../hw_sequencer.h" +#include "dio/dcn10/dcn10_dio.h" #define DC_LOGGER_INIT(logger) @@ -320,7 +321,8 @@ void dcn401_init_hw(struct dc *dc) } /* power AFMT HDMI memory TODO: may move to dis/en output save power*/ - REG_WRITE(DIO_MEM_PWR_CTRL, 0); + if (dc->res_pool->dio && dc->res_pool->dio->funcs->mem_pwr_ctrl) + dc->res_pool->dio->funcs->mem_pwr_ctrl(dc->res_pool->dio, false); if (!dc->debug.disable_clock_gate) { /* enable all DCN clock gating */ 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 61d8ef759aca..43579b0e1482 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -35,6 +35,7 @@ #include "hubp.h" #include "mpc.h" #include "dwb.h" +#include "hw/dio.h" #include "mcif_wb.h" #include "panel_cntl.h" #include "dmub/inc/dmub_cmd.h" @@ -250,6 +251,7 @@ struct resource_pool { struct timing_generator *timing_generators[MAX_PIPES]; struct stream_encoder *stream_enc[MAX_PIPES * 2]; struct hubbub *hubbub; + struct dio *dio; struct mpc *mpc; struct pp_smu_funcs *pp_smu; struct dce_aux *engines[MAX_PIPES]; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dio.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dio.h new file mode 100644 index 000000000000..532bf54cf2c4 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dio.h @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +// +// Copyright 2025 Advanced Micro Devices, Inc. + +#ifndef __DC_DIO_H__ +#define __DC_DIO_H__ + +#include "dc_types.h" + +struct dc_context; +struct dio; + +struct dio_funcs { + void (*mem_pwr_ctrl)(struct dio *dio, bool enable_i2c_light_sleep); +}; + +struct dio { + const struct dio_funcs *funcs; + struct dc_context *ctx; +}; + +#endif /* __DC_DIO_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c index 1cdbb65da4a3..df3acf589582 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c @@ -21,6 +21,7 @@ #include "dcn401/dcn401_hubbub.h" #include "dcn401/dcn401_mpc.h" #include "dcn401/dcn401_hubp.h" +#include "dio/dcn10/dcn10_dio.h" #include "irq/dcn401/irq_service_dcn401.h" #include "dcn401/dcn401_dpp.h" #include "dcn401/dcn401_optc.h" @@ -634,6 +635,22 @@ static const struct dcn20_vmid_mask vmid_masks = { DCN20_VMID_MASK_SH_LIST(_MASK) }; +#define dio_regs_init() \ + DIO_REG_LIST_DCN10() + +static struct dcn_dio_registers dio_regs; + +#define DIO_MASK_SH_LIST_DCN401(mask_sh)\ + HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh) + +static const struct dcn_dio_shift dio_shift = { + DIO_MASK_SH_LIST_DCN401(__SHIFT) +}; + +static const struct dcn_dio_mask dio_mask = { + DIO_MASK_SH_LIST_DCN401(_MASK) +}; + static const struct resource_caps res_cap_dcn4_01 = { .num_timing_generator = 4, .num_opp = 4, @@ -881,6 +898,22 @@ static struct hubbub *dcn401_hubbub_create(struct dc_context *ctx) return &hubbub2->base; } +static struct dio *dcn401_dio_create(struct dc_context *ctx) +{ + struct dcn10_dio *dio10 = kzalloc(sizeof(struct dcn10_dio), GFP_KERNEL); + + if (!dio10) + return NULL; + +#undef REG_STRUCT +#define REG_STRUCT dio_regs + dio_regs_init(); + + dcn10_dio_construct(dio10, ctx, &dio_regs, &dio_shift, &dio_mask); + + return &dio10->base; +} + static struct hubp *dcn401_hubp_create( struct dc_context *ctx, uint32_t inst) @@ -2071,6 +2104,14 @@ static bool dcn401_resource_construct( goto create_fail; } + /* DIO */ + pool->base.dio = dcn401_dio_create(ctx); + if (pool->base.dio == NULL) { + BREAK_TO_DEBUGGER(); + dm_error("DC: failed to create dio!\n"); + goto create_fail; + } + /* HUBPs, DPPs, OPPs, TGs, ABMs */ for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) { -- 2.43.0
