###############################################################################
# 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))
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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__ */
#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"
/* 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 */
#include "clk_mgr.h"
#include "reg_helper.h"
#include "dcn10/dcn10_hubbub.h"
+#include "dio/dcn10/dcn10_dio.h"
+
#define CTX \
hws->ctx
}
/* 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 */
#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)
}
/* 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 */
#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)
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);
#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)
}
/* 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 */
#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"
}
}
- /* 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);
#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)
}
/* 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 */
#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"
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];
--- /dev/null
+// 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__ */
#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"
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,
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)
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++) {