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

Reply via email to