]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/display: Add dcn42 DC resources
authorRoman Li <Roman.Li@amd.com>
Mon, 2 Feb 2026 23:06:17 +0000 (18:06 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 23 Feb 2026 19:28:33 +0000 (14:28 -0500)
Display Core resources for DCN 4.2:
- CLK_MGR
- DCCG
- DIO
- DPP
- GPIO
- HPO
- HUBBUB
- HUBP
- HWSS
- IRQ
- MMHUBBUB
- MPC
- OPTC
- PG

Signed-off-by: Roman Li <Roman.Li@amd.com>
Acked-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
40 files changed:
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.h [new file with mode: 0644]

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c
new file mode 100644 (file)
index 0000000..55434f0
--- /dev/null
@@ -0,0 +1,1152 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dcn42_clk_mgr.h"
+
+#include "dccg.h"
+#include "clk_mgr_internal.h"
+
+// For dce12_get_dp_ref_freq_khz
+#include "dce100/dce_clk_mgr.h"
+
+// For dcn20_update_clocks_update_dpp_dto
+#include "dcn20/dcn20_clk_mgr.h"
+
+
+
+
+#include "reg_helper.h"
+#include "core_types.h"
+#include "dcn42_smu.h"
+#include "dm_helpers.h"
+
+/* TODO: remove this include once we ported over remaining clk mgr functions*/
+#include "dcn30/dcn30_clk_mgr.h"
+#include "dcn31/dcn31_clk_mgr.h"
+
+#include "dcn35/dcn35_clk_mgr.h"
+
+#include "dc_dmub_srv.h"
+#include "link_service.h"
+#include "logger_types.h"
+
+
+#undef DC_LOGGER
+#define DC_LOGGER \
+       clk_mgr->base.base.ctx->logger
+
+
+#define DCN_BASE__INST0_SEG1                       0x000000C0
+
+#define regCLK8_CLK2_BYPASS_CNTL                        0x4c2a
+#define regCLK8_CLK2_BYPASS_CNTL_BASE_IDX      0
+#define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL__SHIFT  0x0
+#define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_DIV__SHIFT  0x10
+#define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL_MASK            0x00000007L
+#define CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_DIV_MASK            0x000F0000L
+
+#define regDENTIST_DISPCLK_CNTL 0x0064
+#define regDENTIST_DISPCLK_CNTL_BASE_IDX 1
+
+// DENTIST_DISPCLK_CNTL
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_WDIVIDER__SHIFT 0x0
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_RDIVIDER__SHIFT 0x8
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_DONE__SHIFT 0x13
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPPCLK_CHG_DONE__SHIFT 0x14
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPPCLK_WDIVIDER__SHIFT 0x18
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_WDIVIDER_MASK 0x0000007FL
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_RDIVIDER_MASK 0x00007F00L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_DONE_MASK 0x00080000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPPCLK_CHG_DONE_MASK 0x00100000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPPCLK_WDIVIDER_MASK 0x7F000000L
+#define mmDENTIST_DISPCLK_CNTL 0x0124
+#define mmCLK8_CLK_TICK_CNT_CONFIG_REG                  0x1B851
+#define mmCLK8_CLK0_CURRENT_CNT                         0x1B853
+#define mmCLK8_CLK1_CURRENT_CNT                         0x1B854
+#define mmCLK8_CLK2_CURRENT_CNT                         0x1B855
+#define mmCLK8_CLK3_CURRENT_CNT                         0x1B856
+#define mmCLK8_CLK4_CURRENT_CNT                         0x1B857
+
+
+#define mmCLK8_CLK0_BYPASS_CNTL                         0x1B81A
+#define mmCLK8_CLK1_BYPASS_CNTL                         0x1B822
+#define mmCLK8_CLK2_BYPASS_CNTL                         0x1B82A
+#define mmCLK8_CLK3_BYPASS_CNTL                         0x1B832
+#define mmCLK8_CLK4_BYPASS_CNTL                         0x1B83A
+
+
+#define mmCLK8_CLK0_DS_CNTL                             0x1B814
+#define mmCLK8_CLK1_DS_CNTL                             0x1B81C
+#define mmCLK8_CLK2_DS_CNTL                             0x1B824
+#define mmCLK8_CLK3_DS_CNTL                             0x1B82C
+#define mmCLK8_CLK4_DS_CNTL                             0x1B834
+
+
+
+
+#undef FN
+#define FN(reg_name, field_name) \
+       clk_mgr->clk_mgr_shift->field_name, clk_mgr->clk_mgr_mask->field_name
+
+#define REG(reg) \
+       (clk_mgr->regs->reg)
+
+#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
+
+#define BASE(seg) BASE_INNER(seg)
+
+#define SR(reg_name)\
+               .reg_name = BASE(reg ## reg_name ## _BASE_IDX) +  \
+                                       reg ## reg_name
+
+#define CLK_SR_DCN42(reg_name)\
+       .reg_name = mm ## reg_name
+
+static const struct clk_mgr_registers clk_mgr_regs_dcn42 = {
+       CLK_REG_LIST_DCN42()
+};
+
+static const struct clk_mgr_shift clk_mgr_shift_dcn42 = {
+       CLK_COMMON_MASK_SH_LIST_DCN42(__SHIFT)
+};
+
+static const struct clk_mgr_mask clk_mgr_mask_dcn42 = {
+       CLK_COMMON_MASK_SH_LIST_DCN42(_MASK)
+};
+
+
+
+#define TO_CLK_MGR_DCN42(clk_mgr_int)\
+       container_of(clk_mgr_int, struct clk_mgr_dcn42, base)
+
+int dcn42_get_active_display_cnt_wa(
+               struct dc *dc,
+               struct dc_state *context,
+               int *all_active_disps)
+{
+       int i, display_count = 0;
+       bool tmds_present = false;
+
+       for (i = 0; i < context->stream_count; i++) {
+               const struct dc_stream_state *stream = context->streams[i];
+
+               if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
+                               stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
+                               stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
+                       tmds_present = true;
+       }
+
+       for (i = 0; i < dc->link_count; i++) {
+               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 && link->link_enc->funcs->is_dig_enabled &&
+                               link->link_enc->funcs->is_dig_enabled(link->link_enc))
+                       display_count++;
+       }
+       if (all_active_disps != NULL)
+               *all_active_disps = display_count;
+       /* WA for hang on HDMI after display off back on*/
+       if (display_count == 0 && tmds_present)
+               display_count = 1;
+
+       return display_count;
+}
+
+void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
+               struct dc_state *context,
+               int ref_dtbclk_khz)
+{
+       /* DCN42 does not implement set_dtbclk_dto function, so this is a no-op */
+}
+
+void dcn42_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr,
+               struct dc_state *context, bool safe_to_lower)
+{
+       int i;
+       bool dppclk_active[MAX_PIPES] = {0};
+
+
+       clk_mgr->dccg->ref_dppclk = clk_mgr->base.clks.dppclk_khz;
+       for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
+               int dpp_inst = 0, dppclk_khz, prev_dppclk_khz;
+
+               dppclk_khz = context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz;
+
+               if (context->res_ctx.pipe_ctx[i].plane_res.dpp)
+                       dpp_inst = context->res_ctx.pipe_ctx[i].plane_res.dpp->inst;
+               else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz == 0) {
+                       /* dpp == NULL && dppclk_khz == 0 is valid because of pipe harvesting.
+                        * In this case just continue in loop
+                        */
+                       continue;
+               } else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz > 0) {
+                       /* The software state is not valid if dpp resource is NULL and
+                        * dppclk_khz > 0.
+                        */
+                       ASSERT(false);
+                       continue;
+               }
+
+               prev_dppclk_khz = clk_mgr->dccg->pipe_dppclk_khz[i];
+
+               if (safe_to_lower || prev_dppclk_khz < dppclk_khz)
+                       clk_mgr->dccg->funcs->update_dpp_dto(
+                                                       clk_mgr->dccg, dpp_inst, dppclk_khz);
+               dppclk_active[dpp_inst] = true;
+       }
+       if (safe_to_lower)
+               for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
+                       struct dpp *old_dpp = clk_mgr->base.ctx->dc->current_state->res_ctx.pipe_ctx[i].plane_res.dpp;
+
+                       if (old_dpp && !dppclk_active[old_dpp->inst])
+                               clk_mgr->dccg->funcs->update_dpp_dto(clk_mgr->dccg, old_dpp->inst, 0);
+               }
+}
+
+void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
+                       struct dc_state *context,
+                       bool safe_to_lower)
+{
+       union dmub_rb_cmd cmd;
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(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 = 0;
+       bool update_dppclk = false;
+       bool update_dispclk = false;
+       bool dpp_clock_lowered = false;
+       int all_active_disps = 0;
+
+       if (dc->work_arounds.skip_clock_update)
+               return;
+
+       display_count = dcn42_get_active_display_cnt_wa(dc, context, &all_active_disps);
+
+       /*dml21 issue*/
+       ASSERT(new_clocks->dtbclk_en && new_clocks->ref_dtbclk_khz > 590000); //remove this section if assert is hit
+       if (new_clocks->dtbclk_en && new_clocks->ref_dtbclk_khz < 590000)
+               new_clocks->ref_dtbclk_khz = 600000;
+
+       /*
+        * if it is safe to lower, but we are already in the lower state, we don't have to do anything
+        * also if safe to lower is false, we just go in the higher state
+        */
+       if (safe_to_lower) {
+               if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
+                               new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
+                       dcn42_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
+                       clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
+               }
+
+               if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) {
+                       if (clk_mgr->base.ctx->dc->config.allow_0_dtb_clk)
+                               dcn42_smu_set_dtbclk(clk_mgr, false);
+                       clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
+               }
+               /* check that we're not already in lower */
+               if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
+                       /* if we can go lower, go lower */
+                       if (display_count == 0)
+                               clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER;
+               }
+       } else {
+               if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
+                               new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
+                       dcn42_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
+                       clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
+               }
+               if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) {
+                       int actual_dtbclk = 0;
+
+                       dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
+                       dcn42_smu_set_dtbclk(clk_mgr, true);
+                       if (clk_mgr_base->boot_snapshot.timer_threhold)
+                               actual_dtbclk = REG_READ(CLK8_CLK4_CURRENT_CNT) / (clk_mgr_base->boot_snapshot.timer_threhold / 48000);
+
+
+                       if (actual_dtbclk > 590000) {
+                               clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz;
+                               clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
+                       }
+               }
+
+               /* check that we're not already in D0 */
+               if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_MISSION_MODE) {
+                       union display_idle_optimization_u idle_info = { 0 };
+
+                       dcn42_smu_set_display_idle_optimization(clk_mgr, idle_info.data);
+                       /* update power state */
+                       clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_MISSION_MODE;
+               }
+       }
+       if (dc->debug.force_min_dcfclk_mhz > 0)
+               new_clocks->dcfclk_khz = (new_clocks->dcfclk_khz > (dc->debug.force_min_dcfclk_mhz * 1000)) ?
+                               new_clocks->dcfclk_khz : (dc->debug.force_min_dcfclk_mhz * 1000);
+
+       if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) {
+               clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
+               clk_mgr_base->clks.fclk_khz = new_clocks->fclk_khz;
+               clk_mgr_base->clks.dramclk_khz = new_clocks->dramclk_khz;
+               dcn42_smu_set_hard_min_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_khz);
+       }
+
+       if (should_set_clock(safe_to_lower,
+                       new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) {
+               clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
+               dcn42_smu_set_min_deep_sleep_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz);
+       }
+
+       // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow.
+
+       if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
+               if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
+                       dpp_clock_lowered = true;
+               clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz;
+               update_dppclk = true;
+       }
+
+       if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) &&
+           (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) {
+               int requested_dispclk_khz = new_clocks->dispclk_khz;
+
+               dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true);
+
+               /* Clamp the requested clock to PMFW based on their limit. */
+               if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz)
+                       requested_dispclk_khz = dc->debug.min_disp_clk_khz;
+
+               dcn42_smu_set_dispclk(clk_mgr, requested_dispclk_khz);
+               clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
+               dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false);
+
+               update_dispclk = true;
+       }
+
+       /* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */
+       if (!dc->debug.disable_dtb_ref_clk_switch &&
+           should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000,
+                            clk_mgr_base->clks.ref_dtbclk_khz / 1000)) {
+               dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
+               clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz;
+       }
+
+       if (dpp_clock_lowered) {
+               // increase per DPP DTO before lowering global dppclk
+               dcn42_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
+               dcn42_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
+       } else {
+               // increase global DPPCLK before lowering per DPP DTO
+               if (update_dppclk || update_dispclk)
+                       dcn42_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
+               dcn42_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
+       }
+       // notify DMCUB of latest clocks
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.notify_clocks.header.type = DMUB_CMD__CLK_MGR;
+       cmd.notify_clocks.header.sub_type = DMUB_CMD__CLK_MGR_NOTIFY_CLOCKS;
+       cmd.notify_clocks.clocks.dcfclk_khz = clk_mgr_base->clks.dcfclk_khz;
+       cmd.notify_clocks.clocks.dcfclk_deep_sleep_khz =
+               clk_mgr_base->clks.dcfclk_deep_sleep_khz;
+       cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz;
+       cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz;
+
+       dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+}
+
+
+void dcn42_enable_pme_wa(struct clk_mgr *clk_mgr_base)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+       dcn42_smu_enable_pme_wa(clk_mgr);
+}
+
+
+bool dcn42_are_clock_states_equal(struct dc_clocks *a,
+               struct dc_clocks *b)
+{
+       if (a->dispclk_khz != b->dispclk_khz)
+               return false;
+       else if (a->dppclk_khz != b->dppclk_khz)
+               return false;
+       else if (a->dcfclk_khz != b->dcfclk_khz)
+               return false;
+       else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz)
+               return false;
+       else if (a->zstate_support != b->zstate_support)
+               return false;
+       else if (a->dtbclk_en != b->dtbclk_en)
+               return false;
+
+       return true;
+}
+
+static void dcn42_dump_clk_registers_internal(struct dcn42_clk_internal *internal, struct clk_mgr *clk_mgr_base)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       uint32_t ratio = 1;
+
+       internal->CLK8_CLK_TICK_CNT__TIMER_THRESHOLD = REG_READ(CLK8_CLK_TICK_CNT_CONFIG_REG) & 0xFFFFFF;
+
+       ratio = internal->CLK8_CLK_TICK_CNT__TIMER_THRESHOLD / 48000;
+       ASSERT(ratio != 0);
+
+       if (ratio) {
+               // read dcf deep sleep divider
+               internal->CLK8_CLK0_DS_CNTL = REG_READ(CLK8_CLK0_DS_CNTL);
+               internal->CLK8_CLK3_DS_CNTL = REG_READ(CLK8_CLK3_DS_CNTL);
+               // read dispclk
+               internal->CLK8_CLK0_CURRENT_CNT = REG_READ(CLK8_CLK0_CURRENT_CNT) / ratio;
+               internal->CLK8_CLK0_BYPASS_CNTL = REG_READ(CLK8_CLK0_BYPASS_CNTL);
+               // read dppclk
+               internal->CLK8_CLK1_CURRENT_CNT = REG_READ(CLK8_CLK1_CURRENT_CNT) / ratio;
+               internal->CLK8_CLK1_BYPASS_CNTL = REG_READ(CLK8_CLK1_BYPASS_CNTL);
+               // read dprefclk
+               internal->CLK8_CLK2_CURRENT_CNT = REG_READ(CLK8_CLK2_CURRENT_CNT) / ratio;
+               internal->CLK8_CLK2_BYPASS_CNTL = REG_READ(CLK8_CLK2_BYPASS_CNTL);
+               // read dcfclk
+               internal->CLK8_CLK3_CURRENT_CNT = REG_READ(CLK8_CLK3_CURRENT_CNT) / ratio;
+               internal->CLK8_CLK3_BYPASS_CNTL = REG_READ(CLK8_CLK3_BYPASS_CNTL);
+               // read dtbclk
+               internal->CLK8_CLK4_CURRENT_CNT = REG_READ(CLK8_CLK4_CURRENT_CNT) / ratio;
+               internal->CLK8_CLK4_BYPASS_CNTL = REG_READ(CLK8_CLK4_BYPASS_CNTL);
+       }
+
+}
+
+static void dcn42_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
+               struct clk_mgr_dcn42 *clk_mgr)
+{
+       struct dcn42_clk_internal internal = {0};
+       char *bypass_clks[5] = {"0x0 DFS", "0x1 REFCLK", "0x2 ERROR", "0x3 400 FCH", "0x4 600 FCH"};
+
+       dcn42_dump_clk_registers_internal(&internal, &clk_mgr->base.base);
+       regs_and_bypass->timer_threhold = internal.CLK8_CLK_TICK_CNT__TIMER_THRESHOLD;
+       regs_and_bypass->dcfclk = internal.CLK8_CLK3_CURRENT_CNT / 10;
+       regs_and_bypass->dcf_deep_sleep_divider = internal.CLK8_CLK3_DS_CNTL / 10;
+       regs_and_bypass->dcf_deep_sleep_allow = internal.CLK8_CLK3_DS_CNTL & 0x10; /*bit 4: CLK0_ALLOW_DS*/
+       regs_and_bypass->dprefclk = internal.CLK8_CLK2_CURRENT_CNT / 10;
+       regs_and_bypass->dispclk = internal.CLK8_CLK0_CURRENT_CNT / 10;
+       regs_and_bypass->dppclk = internal.CLK8_CLK1_CURRENT_CNT / 10;
+       regs_and_bypass->dtbclk = internal.CLK8_CLK4_CURRENT_CNT / 10;
+
+       regs_and_bypass->dppclk_bypass = internal.CLK8_CLK1_BYPASS_CNTL & 0x0007;
+       if (regs_and_bypass->dppclk_bypass > 4)
+               regs_and_bypass->dppclk_bypass = 0;
+       regs_and_bypass->dcfclk_bypass = internal.CLK8_CLK3_BYPASS_CNTL & 0x0007;
+       if (regs_and_bypass->dcfclk_bypass > 4)
+               regs_and_bypass->dcfclk_bypass = 0;
+       regs_and_bypass->dispclk_bypass = internal.CLK8_CLK0_BYPASS_CNTL & 0x0007;
+       if (regs_and_bypass->dispclk_bypass > 4)
+               regs_and_bypass->dispclk_bypass = 0;
+       regs_and_bypass->dprefclk_bypass = internal.CLK8_CLK2_BYPASS_CNTL & 0x0007;
+       if (regs_and_bypass->dprefclk_bypass > 4)
+               regs_and_bypass->dprefclk_bypass = 0;
+
+       if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) {
+               DC_LOG_SMU("clk_type,clk_value,deepsleep_cntl,deepsleep_allow,bypass\n");
+
+               DC_LOG_SMU("dcfclk,%d,%d,%d,%s\n",
+                                  regs_and_bypass->dcfclk,
+                                  regs_and_bypass->dcf_deep_sleep_divider,
+                                  regs_and_bypass->dcf_deep_sleep_allow,
+                                  bypass_clks[(int) regs_and_bypass->dcfclk_bypass]);
+
+               DC_LOG_SMU("dprefclk,%d,N/A,N/A,%s\n",
+                       regs_and_bypass->dprefclk,
+                       bypass_clks[(int) regs_and_bypass->dprefclk_bypass]);
+
+               DC_LOG_SMU("dispclk,%d,N/A,N/A,%s\n",
+                       regs_and_bypass->dispclk,
+                       bypass_clks[(int) regs_and_bypass->dispclk_bypass]);
+
+               //split
+               DC_LOG_SMU("SPLIT\n");
+
+               // REGISTER VALUES
+               DC_LOG_SMU("reg_name,value,clk_type\n");
+
+               DC_LOG_SMU("CLK1_CLK3_CURRENT_CNT,%d,dcfclk\n",
+                               internal.CLK8_CLK3_CURRENT_CNT);
+
+               DC_LOG_SMU("CLK1_CLK3_DS_CNTL,%d,dcf_deep_sleep_divider\n",
+                                       internal.CLK8_CLK3_DS_CNTL);
+
+               DC_LOG_SMU("CLK1_CLK3_ALLOW_DS,%d,dcf_deep_sleep_allow\n",
+                                       (internal.CLK8_CLK3_DS_CNTL & 0x10));
+
+               DC_LOG_SMU("CLK1_CLK2_CURRENT_CNT,%d,dprefclk\n",
+                                       internal.CLK8_CLK2_CURRENT_CNT);
+
+               DC_LOG_SMU("CLK1_CLK0_CURRENT_CNT,%d,dispclk\n",
+                                       internal.CLK8_CLK0_CURRENT_CNT);
+
+               DC_LOG_SMU("CLK1_CLK1_CURRENT_CNT,%d,dppclk\n",
+                                       internal.CLK8_CLK1_CURRENT_CNT);
+
+               DC_LOG_SMU("CLK1_CLK3_BYPASS_CNTL,%d,dcfclk_bypass\n",
+                                       internal.CLK8_CLK3_BYPASS_CNTL);
+
+               DC_LOG_SMU("CLK1_CLK2_BYPASS_CNTL,%d,dprefclk_bypass\n",
+                                       internal.CLK8_CLK2_BYPASS_CNTL);
+
+               DC_LOG_SMU("CLK1_CLK0_BYPASS_CNTL,%d,dispclk_bypass\n",
+                                       internal.CLK8_CLK0_BYPASS_CNTL);
+
+               DC_LOG_SMU("CLK1_CLK1_BYPASS_CNTL,%d,dppclk_bypass\n",
+                                       internal.CLK8_CLK1_BYPASS_CNTL);
+       }
+}
+
+bool dcn42_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       struct dc_context *ctx = clk_mgr->base.ctx;
+
+
+       if (ctx->dc->config.ignore_dpref_ss) {
+               /*revert bios's ss info for test only*/
+               return (clk_mgr->dprefclk_ss_percentage == 0);
+       }
+       /*need to update after BU*/
+       return false;
+}
+
+static void init_clk_states(struct clk_mgr *clk_mgr)
+{
+       uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz;
+
+       memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
+
+       clk_mgr->clks.dtbclk_en = true; // request DTBCLK disable on first commit
+       clk_mgr->clks.ref_dtbclk_khz = ref_dtbclk;      // restore ref_dtbclk
+       clk_mgr->clks.p_state_change_support = true;
+       clk_mgr->clks.prev_p_state_change_support = true;
+       clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN;
+       clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN;
+}
+
+static void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr,
+               struct dcn42_smu_dpm_clks *smu_dpm_clks)
+{
+       DpmClocks_t_dcn42 *table = smu_dpm_clks->dpm_clks;
+
+       if (!clk_mgr->smu_ver)
+               return;
+
+       if (!table || smu_dpm_clks->mc_address.quad_part == 0)
+               return;
+
+       memset(table, 0, sizeof(*table));
+
+       dcn42_smu_set_dram_addr_high(clk_mgr,
+                       smu_dpm_clks->mc_address.high_part);
+       dcn42_smu_set_dram_addr_low(clk_mgr,
+                       smu_dpm_clks->mc_address.low_part);
+       dcn42_smu_transfer_dpm_table_smu_2_dram(clk_mgr);
+}
+
+void dcn42_init_single_clock(unsigned int *entry_0,
+               uint32_t *smu_entry_0,
+               uint8_t num_levels)
+{
+       int i;
+       char *entry_i = (char *)entry_0;
+
+       ASSERT(num_levels <= MAX_NUM_DPM_LVL);
+       if (num_levels > MAX_NUM_DPM_LVL)
+               num_levels = MAX_NUM_DPM_LVL;
+
+
+       for (i = 0; i < num_levels; i++) {
+               *((unsigned int *)entry_i) = smu_entry_0[i];
+               entry_i += sizeof(struct clk_limit_table_entry);
+       }
+}
+
+unsigned int dcn42_convert_wck_ratio(uint8_t wck_ratio)
+{
+       switch (wck_ratio) {
+       case WCK_RATIO_1_2:
+               return 2;
+
+       case WCK_RATIO_1_4:
+               return 4;
+
+       default:
+                       break;
+       }
+
+       return 1;
+}
+
+void dcn42_init_clocks(struct clk_mgr *clk_mgr_base)
+{
+       struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       struct clk_mgr_dcn42 *clk_mgr = TO_CLK_MGR_DCN42(clk_mgr_int);
+       struct dcn42_smu_dpm_clks smu_dpm_clks = { 0 };
+
+       init_clk_states(clk_mgr_base);
+
+       // to adjust dp_dto reference clock if ssc is enable otherwise to apply dprefclk
+       if (dcn42_is_spll_ssc_enabled(clk_mgr_base))
+               clk_mgr_base->dp_dto_source_clock_in_khz =
+                       dce_adjust_dp_ref_freq_for_ss(clk_mgr_int, clk_mgr_base->dprefclk_khz);
+       else
+               clk_mgr_base->dp_dto_source_clock_in_khz = clk_mgr_base->dprefclk_khz;
+
+       dcn42_dump_clk_registers(&clk_mgr_base->boot_snapshot, clk_mgr);
+
+       clk_mgr_base->clks.ref_dtbclk_khz =  clk_mgr_base->boot_snapshot.dtbclk * 10;
+       if (clk_mgr_base->boot_snapshot.dtbclk > 59000) {
+               /*dtbclk enabled based on*/
+               clk_mgr_base->clks.dtbclk_en = true;
+       }
+
+       smu_dpm_clks.dpm_clks = (DpmClocks_t_dcn42 *)dm_helpers_allocate_gpu_mem(
+                               clk_mgr_base->ctx,
+                               DC_MEM_ALLOC_TYPE_GART,
+                               sizeof(DpmClocks_t_dcn42),
+                               &smu_dpm_clks.mc_address.quad_part);
+
+       ASSERT(smu_dpm_clks.dpm_clks);
+       if (clk_mgr_base->ctx->dc->debug.pstate_enabled && clk_mgr_int->smu_present && smu_dpm_clks.mc_address.quad_part != 0) {
+               int i;
+               DpmClocks_t_dcn42 *dpm_clks = smu_dpm_clks.dpm_clks;
+
+               dcn42_get_dpm_table_from_smu(clk_mgr_int, &smu_dpm_clks);
+               DC_LOG_SMU("NumDcfClkLevelsEnabled: %d\n"
+                                  "NumDispClkLevelsEnabled: %d\n"
+                                  "NumSocClkLevelsEnabled: %d\n"
+                                  "VcnClkLevelsEnabled: %d\n"
+                                  "FClkLevelsEnabled: %d\n"
+                                  "NumMemPstatesEnabled: %d\n"
+                                  "MinGfxClk: %d\n"
+                                  "MaxGfxClk: %d\n",
+                                  dpm_clks->NumDcfClkLevelsEnabled,
+                                  dpm_clks->NumDispClkLevelsEnabled,
+                                  dpm_clks->NumSocClkLevelsEnabled,
+                                  dpm_clks->VcnClkLevelsEnabled,
+                                  dpm_clks->NumFclkLevelsEnabled,
+                                  dpm_clks->NumMemPstatesEnabled,
+                                  dpm_clks->MinGfxClk,
+                                  dpm_clks->MaxGfxClk);
+
+               for (i = 0; i < NUM_DCFCLK_DPM_LEVELS; i++) {
+                       DC_LOG_SMU("dpm_clks->DcfClocks[%d] = %d\n",
+                                          i,
+                                          dpm_clks->DcfClocks[i]);
+               }
+               for (i = 0; i < NUM_DISPCLK_DPM_LEVELS; i++) {
+                       DC_LOG_SMU("dpm_clks->DispClocks[%d] = %d\n",
+                                          i, dpm_clks->DispClocks[i]);
+               }
+               for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) {
+                       DC_LOG_SMU("dpm_clks->SocClocks[%d] = %d\n",
+                                          i, dpm_clks->SocClocks[i]);
+               }
+               for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
+                       DC_LOG_SMU("dpm_clks->FclkClocks_Freq[%d] = %d\n",
+                                          i, dpm_clks->FclkClocks_Freq[i]);
+                       DC_LOG_SMU("dpm_clks->FclkClocks_Voltage[%d] = %d\n",
+                                          i, dpm_clks->FclkClocks_Voltage[i]);
+               }
+               for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++)
+                       DC_LOG_SMU("dpm_clks->SocVoltage[%d] = %d\n",
+                                          i, dpm_clks->SocVoltage[i]);
+
+               for (i = 0; i < NUM_MEM_PSTATE_LEVELS; i++) {
+                       DC_LOG_SMU("dpm_clks.MemPstateTable[%d].UClk = %d\n"
+                                          "dpm_clks->MemPstateTable[%d].MemClk= %d\n"
+                                          "dpm_clks->MemPstateTable[%d].Voltage = %d\n",
+                                          i, dpm_clks->MemPstateTable[i].UClk,
+                                          i, dpm_clks->MemPstateTable[i].MemClk,
+                                          i, dpm_clks->MemPstateTable[i].Voltage);
+               }
+
+               if (clk_mgr_base->ctx->dc_bios->integrated_info && clk_mgr_base->ctx->dc->config.use_default_clock_table == false) {
+                       /* DCFCLK */
+                       dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz,
+                                       dpm_clks->DcfClocks,
+                                       dpm_clks->NumDcfClkLevelsEnabled);
+                       clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels = dpm_clks->NumDcfClkLevelsEnabled;
+
+                       /* SOCCLK */
+                       dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz,
+                                       dpm_clks->SocClocks,
+                                       dpm_clks->NumSocClkLevelsEnabled);
+                       clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_socclk_levels = dpm_clks->NumSocClkLevelsEnabled;
+
+                       /* DISPCLK */
+                       dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz,
+                                       dpm_clks->DispClocks,
+                                       dpm_clks->NumDispClkLevelsEnabled);
+                       clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels = dpm_clks->NumDispClkLevelsEnabled;
+
+                       /* DPPCLK */
+                       dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dppclk_mhz,
+                                       dpm_clks->DppClocks,
+                                       dpm_clks->NumDispClkLevelsEnabled);
+                       clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dppclk_levels = dpm_clks->NumDispClkLevelsEnabled;
+
+                       /* FCLK */
+                       dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz,
+                                       dpm_clks->FclkClocks_Freq,
+                                       NUM_FCLK_DPM_LEVELS);
+                       clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_fclk_levels = dpm_clks->NumFclkLevelsEnabled;
+                       clk_mgr_base->bw_params->clk_table.num_entries = dpm_clks->NumFclkLevelsEnabled;
+
+                       /* Memory Pstate table is in reverse order*/
+                       ASSERT(dpm_clks->NumMemPstatesEnabled <= NUM_MEM_PSTATE_LEVELS);
+                       if (dpm_clks->NumMemPstatesEnabled > NUM_MEM_PSTATE_LEVELS)
+                               dpm_clks->NumMemPstatesEnabled = NUM_MEM_PSTATE_LEVELS;
+                       for (i = 0; i < dpm_clks->NumMemPstatesEnabled; i++) {
+                               clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].memclk_mhz = dpm_clks->MemPstateTable[i].UClk;
+                               clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].wck_ratio = dcn42_convert_wck_ratio(dpm_clks->MemPstateTable[i].WckRatio)    ;
+                       }
+                       clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels = dpm_clks->NumMemPstatesEnabled;
+
+                       /* DTBCLK*/
+                       clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz = clk_mgr_base->clks.ref_dtbclk_khz / 1000;
+                       clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels = 1;
+
+                       /* Refresh bounding box */
+                       clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
+                                       clk_mgr_base->ctx->dc, clk_mgr_base->bw_params);
+               }
+       }
+       if (smu_dpm_clks.dpm_clks && smu_dpm_clks.mc_address.quad_part != 0)
+               dm_helpers_free_gpu_mem(clk_mgr_base->ctx, DC_MEM_ALLOC_TYPE_GART,
+                               smu_dpm_clks.dpm_clks);
+}
+
+static struct clk_bw_params dcn42_bw_params = {
+       .vram_type = Ddr4MemType,
+       .num_channels = 1,
+       .clk_table = {
+               .num_entries = 4,
+       },
+
+};
+
+static struct wm_table ddr5_wm_table = {
+       .entries = {
+               {
+                       .wm_inst = WM_A,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.72,
+                       .sr_exit_time_us = 28.0,
+                       .sr_enter_plus_exit_time_us = 30.0,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_B,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.72,
+                       .sr_exit_time_us = 28.0,
+                       .sr_enter_plus_exit_time_us = 30.0,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_C,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.72,
+                       .sr_exit_time_us = 28.0,
+                       .sr_enter_plus_exit_time_us = 30.0,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_D,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.72,
+                       .sr_exit_time_us = 28.0,
+                       .sr_enter_plus_exit_time_us = 30.0,
+                       .valid = true,
+               },
+       }
+};
+
+static struct wm_table lpddr5_wm_table = {
+       .entries = {
+               {
+                       .wm_inst = WM_A,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.65333,
+                       .sr_exit_time_us = 28.0,
+                       .sr_enter_plus_exit_time_us = 30.0,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_B,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.65333,
+                       .sr_exit_time_us = 28.0,
+                       .sr_enter_plus_exit_time_us = 30.0,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_C,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.65333,
+                       .sr_exit_time_us = 28.0,
+                       .sr_enter_plus_exit_time_us = 30.0,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_D,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.65333,
+                       .sr_exit_time_us = 28.0,
+                       .sr_enter_plus_exit_time_us = 30.0,
+                       .valid = true,
+               },
+       }
+};
+
+struct dcn42_ss_info_table dcn42_ss_info_table = {
+       .ss_divider = 1000,
+       .ss_percentage = {0, 0, 375, 375, 375}
+};
+
+static void dcn42_read_ss_info_from_lut(struct clk_mgr_internal *clk_mgr)
+{
+       uint32_t clock_source;
+
+       clock_source = (REG_READ(CLK8_CLK2_BYPASS_CNTL) & CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL_MASK);
+       // If it's DFS mode, clock_source is 0.
+       if (dcn42_is_spll_ssc_enabled(&clk_mgr->base) && (clock_source < ARRAY_SIZE(dcn42_ss_info_table.ss_percentage))) {
+               clk_mgr->dprefclk_ss_percentage = dcn42_ss_info_table.ss_percentage[clock_source];
+
+               if (clk_mgr->dprefclk_ss_percentage != 0) {
+                       clk_mgr->ss_on_dprefclk = true;
+                       clk_mgr->dprefclk_ss_divider = dcn42_ss_info_table.ss_divider;
+               }
+       }
+}
+
+/* Exposed for dcn42b reuse */
+void dcn42_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn42_watermarks *table)
+{
+       int i, num_valid_sets;
+
+       num_valid_sets = 0;
+
+       for (i = 0; i < WM_SET_COUNT; i++) {
+               /* skip empty entries, the smu array has no holes*/
+               if (!bw_params->wm_table.entries[i].valid)
+                       continue;
+
+               table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmSetting = bw_params->wm_table.entries[i].wm_inst;
+               table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType = bw_params->wm_table.entries[i].wm_type;
+               /* We will not select WM based on fclk, so leave it as unconstrained */
+               table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0;
+               table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF;
+
+               if (table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType == WM_TYPE_PSTATE_CHG) {
+                       if (i == 0)
+                               table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk = 0;
+                       else {
+                               /* add 1 to make it non-overlapping with next lvl */
+                               table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk =
+                                               bw_params->clk_table.entries[i - 1].dcfclk_mhz + 1;
+                       }
+                       table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxMclk =
+                                       bw_params->clk_table.entries[i].dcfclk_mhz;
+
+               } else {
+                       /* unconstrained for memory retraining */
+                       table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0;
+                       table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF;
+
+                       /* Modify previous watermark range to cover up to max */
+                       if (num_valid_sets > 0)
+                               table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF;
+               }
+               num_valid_sets++;
+       }
+
+       ASSERT(num_valid_sets != 0); /* Must have at least one set of valid watermarks */
+
+       /* modify the min and max to make sure we cover the whole range*/
+       table->WatermarkRow[WM_DCFCLK][0].MinMclk = 0;
+       table->WatermarkRow[WM_DCFCLK][0].MinClock = 0;
+       table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxMclk = 0xFFFF;
+       table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF;
+
+       /* This is for writeback only, does not matter currently as no writeback support*/
+       table->WatermarkRow[WM_SOCCLK][0].WmSetting = WM_A;
+       table->WatermarkRow[WM_SOCCLK][0].MinClock = 0;
+       table->WatermarkRow[WM_SOCCLK][0].MaxClock = 0xFFFF;
+       table->WatermarkRow[WM_SOCCLK][0].MinMclk = 0;
+       table->WatermarkRow[WM_SOCCLK][0].MaxMclk = 0xFFFF;
+}
+
+void dcn42_notify_wm_ranges(struct clk_mgr *clk_mgr_base)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       struct clk_mgr_dcn42 *clk_mgr_dcn42 = TO_CLK_MGR_DCN42(clk_mgr);
+       struct dcn42_watermarks *table = clk_mgr_dcn42->smu_wm_set.wm_set;
+
+       if (!clk_mgr->smu_ver)
+               return;
+
+       if (!table || clk_mgr_dcn42->smu_wm_set.mc_address.quad_part == 0)
+               return;
+
+       memset(table, 0, sizeof(*table));
+
+       dcn42_build_watermark_ranges(clk_mgr_base->bw_params, table);
+
+       dcn42_smu_set_dram_addr_high(clk_mgr,
+                       clk_mgr_dcn42->smu_wm_set.mc_address.high_part);
+       dcn42_smu_set_dram_addr_low(clk_mgr,
+                       clk_mgr_dcn42->smu_wm_set.mc_address.low_part);
+       dcn42_smu_transfer_wm_table_dram_2_smu(clk_mgr);
+}
+
+void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base)
+{
+       int display_count;
+       struct dc *dc = clk_mgr_base->ctx->dc;
+       struct dc_state *context = dc->current_state;
+
+       if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
+               display_count = dcn42_get_active_display_cnt_wa(dc, context, NULL);
+               /* if we can go lower, go lower */
+               if (display_count == 0)
+                       clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER;
+       }
+
+       if (clk_mgr_base->clks.pwr_state == DCN_PWR_STATE_LOW_POWER) {
+               union display_idle_optimization_u idle_info = { 0 };
+               struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+               idle_info.idle_info.df_request_disabled = 1;
+               idle_info.idle_info.phy_ref_clk_off = 1;
+               idle_info.idle_info.s0i2_rdy = 1;
+               dcn42_smu_set_display_idle_optimization(clk_mgr, idle_info.data);
+       }
+}
+
+void dcn42_exit_low_power_state(struct clk_mgr *clk_mgr_base)
+{
+
+}
+
+static void dcn42_init_clocks_fpga(struct clk_mgr *clk_mgr)
+{
+       init_clk_states(clk_mgr);
+
+}
+
+static void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr,
+               struct dc_state *context,
+               bool safe_to_lower)
+{
+       struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
+       struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
+       int fclk_adj = new_clocks->fclk_khz;
+
+       /* TODO: remove this after correctly set by DML */
+       new_clocks->dcfclk_khz = 400000;
+       new_clocks->socclk_khz = 400000;
+
+       /* Min fclk = 1.2GHz since all the extra scemi logic seems to run off of it */
+       //int fclk_adj = new_clocks->fclk_khz > 1200000 ? new_clocks->fclk_khz : 1200000;
+       new_clocks->fclk_khz = 4320000;
+
+       if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, clk_mgr->clks.phyclk_khz))
+               clk_mgr->clks.phyclk_khz = new_clocks->phyclk_khz;
+
+       if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr->clks.dcfclk_khz))
+               clk_mgr->clks.dcfclk_khz = new_clocks->dcfclk_khz;
+
+       if (should_set_clock(safe_to_lower,
+                       new_clocks->dcfclk_deep_sleep_khz, clk_mgr->clks.dcfclk_deep_sleep_khz))
+               clk_mgr->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
+
+       if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr->clks.socclk_khz))
+               clk_mgr->clks.socclk_khz = new_clocks->socclk_khz;
+
+       if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr->clks.dramclk_khz))
+               clk_mgr->clks.dramclk_khz = new_clocks->dramclk_khz;
+
+       if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->clks.dppclk_khz))
+               clk_mgr->clks.dppclk_khz = new_clocks->dppclk_khz;
+
+       if (should_set_clock(safe_to_lower, fclk_adj, clk_mgr->clks.fclk_khz))
+               clk_mgr->clks.fclk_khz = fclk_adj;
+
+       if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr->clks.dispclk_khz))
+               clk_mgr->clks.dispclk_khz = new_clocks->dispclk_khz;
+
+       /* Both fclk and ref_dppclk run on the same scemi clock.
+        * So take the higher value since the DPP DTO is typically programmed
+        * such that max dppclk is 1:1 with ref_dppclk.
+        */
+       if (clk_mgr->clks.fclk_khz > clk_mgr->clks.dppclk_khz)
+               clk_mgr->clks.dppclk_khz = clk_mgr->clks.fclk_khz;
+       if (clk_mgr->clks.dppclk_khz > clk_mgr->clks.fclk_khz)
+               clk_mgr->clks.fclk_khz = clk_mgr->clks.dppclk_khz;
+
+       // Both fclk and ref_dppclk run on the same scemi clock.
+       clk_mgr_int->dccg->ref_dppclk = clk_mgr->clks.fclk_khz;
+
+       /* TODO: set dtbclk in correct place */
+       clk_mgr->clks.dtbclk_en = true;
+
+       dm_set_dcn_clocks(clk_mgr->ctx, &clk_mgr->clks);
+       dcn42_update_clocks_update_dpp_dto(clk_mgr_int, context, safe_to_lower);
+
+       dcn42_update_clocks_update_dtb_dto(clk_mgr_int, context, clk_mgr->clks.ref_dtbclk_khz);
+}
+
+unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+       unsigned int num_clk_levels;
+
+       switch (clk_type) {
+       case CLK_TYPE_DISPCLK:
+               num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dispclk_levels;
+               return num_clk_levels ?
+                               clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dispclk_mhz * 1000 :
+                               clk_mgr->base.boot_snapshot.dispclk;
+       case CLK_TYPE_DPPCLK:
+               num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dppclk_levels;
+               return num_clk_levels ?
+                               clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dppclk_mhz * 1000 :
+                               clk_mgr->base.boot_snapshot.dppclk;
+       case CLK_TYPE_DSCCLK:
+               num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dispclk_levels;
+               return num_clk_levels ?
+                               clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dispclk_mhz * 1000 / 3 :
+                               clk_mgr->base.boot_snapshot.dispclk / 3;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       uint32_t dispclk_wdivider;
+       int disp_divider;
+
+       REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, &dispclk_wdivider);
+       disp_divider = dentist_get_divider_from_did(dispclk_wdivider);
+
+       /* Return DISPCLK freq in Khz */
+       if (disp_divider)
+               return (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / disp_divider;
+
+       return 0;
+}
+bool dcn42_is_smu_present(struct clk_mgr *clk_mgr_base)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       return clk_mgr->smu_present;
+}
+
+static struct clk_mgr_funcs dcn42_funcs = {
+       .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
+       .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz,
+       .update_clocks = dcn42_update_clocks,
+       .init_clocks = dcn42_init_clocks,
+       .enable_pme_wa = dcn42_enable_pme_wa,
+       .are_clock_states_equal = dcn42_are_clock_states_equal,
+       .notify_wm_ranges = dcn42_notify_wm_ranges,
+       .set_low_power_state = dcn42_set_low_power_state,
+       .exit_low_power_state = dcn42_exit_low_power_state,
+       .get_max_clock_khz = dcn42_get_max_clock_khz,
+       .get_dispclk_from_dentist = dcn42_get_dispclk_from_dentist,
+       .is_smu_present = dcn42_is_smu_present,
+};
+
+struct clk_mgr_funcs dcn42_fpga_funcs = {
+       .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
+       .update_clocks = dcn42_update_clocks_fpga,
+       .init_clocks = dcn42_init_clocks_fpga,
+       .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz,
+};
+
+void dcn42_clk_mgr_construct(
+               struct dc_context *ctx,
+               struct clk_mgr_dcn42 *clk_mgr,
+               struct pp_smu_funcs *pp_smu,
+               struct dccg *dccg)
+{
+       clk_mgr->base.base.ctx = ctx;
+       clk_mgr->base.base.funcs = &dcn42_funcs;
+       clk_mgr->base.regs = &clk_mgr_regs_dcn42;
+       clk_mgr->base.clk_mgr_shift = &clk_mgr_shift_dcn42;
+       clk_mgr->base.clk_mgr_mask = &clk_mgr_mask_dcn42;
+
+       clk_mgr->base.pp_smu = pp_smu;
+
+       clk_mgr->base.dccg = dccg;
+       clk_mgr->base.dfs_bypass_disp_clk = 0;
+
+       clk_mgr->base.dprefclk_ss_percentage = 0;
+       clk_mgr->base.dprefclk_ss_divider = 1000;
+       clk_mgr->base.ss_on_dprefclk = false;
+       clk_mgr->base.dfs_ref_freq_khz = 48000; /*sync with pmfw*/
+
+       clk_mgr->smu_wm_set.wm_set = (struct dcn42_watermarks *)dm_helpers_allocate_gpu_mem(
+                               clk_mgr->base.base.ctx,
+                               DC_MEM_ALLOC_TYPE_GART,
+                               sizeof(struct dcn42_watermarks),
+                               &clk_mgr->smu_wm_set.mc_address.quad_part);
+
+       ASSERT(clk_mgr->smu_wm_set.wm_set);
+
+       /* Changed from DCN3.2_clock_frequency doc to match
+        * dcn32_dump_clk_registers from 4 * dentist_vco_freq_khz /
+        * dprefclk DID divider
+        */
+       clk_mgr->base.base.dprefclk_khz = 600000;
+
+               clk_mgr->base.smu_present = false;
+
+               if (ctx->dc_bios->integrated_info) {
+                       clk_mgr->base.base.dentist_vco_freq_khz = ctx->dc_bios->integrated_info->dentist_vco_freq;
+
+                       if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
+                               dcn42_bw_params.wm_table = lpddr5_wm_table;
+                       else
+                               dcn42_bw_params.wm_table = ddr5_wm_table;
+                       dcn42_bw_params.vram_type = ctx->dc_bios->integrated_info->memory_type;
+                       dcn42_bw_params.dram_channel_width_bytes = ctx->dc_bios->integrated_info->memory_type == 0x22 ? 8 : 4;
+                       dcn42_bw_params.num_channels = ctx->dc_bios->integrated_info->ma_channel_number ? ctx->dc_bios->integrated_info->ma_channel_number : 4;
+               }
+               /* in case we don't get a value from the BIOS, use default */
+               if (clk_mgr->base.base.dentist_vco_freq_khz == 0)
+                       clk_mgr->base.base.dentist_vco_freq_khz = 3000000; /* 3000MHz */
+
+               /* Saved clocks configured at boot for debug purposes */
+               dcn42_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr);
+
+       if (clk_mgr->base.smu_present)
+               clk_mgr->base.base.dprefclk_khz = dcn42_smu_get_dprefclk(&clk_mgr->base);
+       clk_mgr->base.base.clks.ref_dtbclk_khz = 600000;
+       dce_clock_read_ss_info(&clk_mgr->base);
+       /*when clk src is from FCH, it could have ss, same clock src as DPREF clk*/
+
+       dcn42_read_ss_info_from_lut(&clk_mgr->base);
+
+       clk_mgr->base.base.bw_params = &dcn42_bw_params;
+}
+
+void dcn42_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int)
+{
+       struct clk_mgr_dcn42 *clk_mgr = TO_CLK_MGR_DCN42(clk_mgr_int);
+
+       if (clk_mgr->smu_wm_set.wm_set && clk_mgr->smu_wm_set.mc_address.quad_part != 0)
+               dm_helpers_free_gpu_mem(clk_mgr_int->base.ctx, DC_MEM_ALLOC_TYPE_GART,
+                               clk_mgr->smu_wm_set.wm_set);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h
new file mode 100644 (file)
index 0000000..99fcdb6
--- /dev/null
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 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.
+ *
+ */
+
+#ifndef __DCN42_CLK_MGR_H__
+#define __DCN42_CLK_MGR_H__
+#include "clk_mgr_internal.h"
+
+#define NUM_CLOCK_SOURCES 5
+
+struct dcn42_watermarks;
+
+struct dcn42_smu_watermark_set {
+       struct dcn42_watermarks *wm_set;
+       union large_integer mc_address;
+};
+
+struct dcn42_ss_info_table {
+       uint32_t ss_divider;
+       uint32_t ss_percentage[NUM_CLOCK_SOURCES];
+};
+
+struct clk_mgr_dcn42 {
+       struct clk_mgr_internal base;
+       struct dcn42_smu_watermark_set smu_wm_set;
+};
+
+bool dcn42_are_clock_states_equal(struct dc_clocks *a,
+                                                                 struct dc_clocks *b);
+void dcn42_init_clocks(struct clk_mgr *clk_mgr);
+void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
+                                                struct dc_state *context,
+                                                bool safe_to_lower);
+
+void dcn42_clk_mgr_construct(struct dc_context *ctx,
+                                                        struct clk_mgr_dcn42 *clk_mgr,
+                                                        struct pp_smu_funcs *pp_smu,
+                                                        struct dccg *dccg);
+
+void dcn42_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int);
+
+/* Exposed for dcn42b reuse */
+void dcn42_init_single_clock(unsigned int *entry_0,
+                             uint32_t *smu_entry_0,
+                             uint8_t num_levels);
+unsigned int dcn42_convert_wck_ratio(uint8_t wck_ratio);
+extern struct dcn42_ss_info_table dcn42_ss_info_table;
+void dcn42_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn42_watermarks *table);
+void dcn42_enable_pme_wa(struct clk_mgr *clk_mgr_base);
+void dcn42_notify_wm_ranges(struct clk_mgr *clk_mgr_base);
+void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base);
+void dcn42_exit_low_power_state(struct clk_mgr *clk_mgr_base);
+unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type);
+bool dcn42_is_smu_present(struct clk_mgr *clk_mgr_base);
+int dcn42_get_active_display_cnt_wa(struct dc *dc, struct dc_state *context, int *all_active_disps);
+void dcn42_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, bool safe_to_lower);
+void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, int ref_dtbclk_khz);
+bool dcn42_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base);
+#endif //__DCN42_CLK_MGR_H__
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.c
new file mode 100644 (file)
index 0000000..19df8b4
--- /dev/null
@@ -0,0 +1,431 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+
+
+#include "core_types.h"
+#include "clk_mgr_internal.h"
+#include "reg_helper.h"
+#include "dm_helpers.h"
+#include "dcn42_smu.h"
+
+#include "mp/mp_15_0_0_offset.h"
+#include "mp/mp_15_0_0_sh_mask.h"
+
+#ifdef BASE_INNER
+#undef BASE_INNER
+#endif
+
+#define MP1_BASE__INST0_SEG0                       0x00016000
+#define MP1_BASE__INST0_SEG1                       0x00016200
+#define MP1_BASE__INST0_SEG2                       0x00E00000
+#define MP1_BASE__INST0_SEG3                       0x00E80000
+#define MP1_BASE__INST0_SEG4                       0x00EC0000
+#define MP1_BASE__INST0_SEG5                       0x00F00000
+#define MP1_BASE__INST0_SEG6                       0x02400400
+#define MP1_BASE__INST0_SEG7                       0x0243F400
+#define MP1_BASE__INST0_SEG8                       0x3C004000
+#define MP1_BASE__INST0_SEG9                       0x3C3F4000
+
+#define BASE_INNER(seg) MP1_BASE__INST0_SEG ## seg
+
+#define BASE(seg) BASE_INNER(seg)
+
+#define REG(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name)
+
+#define FN(reg_name, field) \
+       FD(reg_name##__##field)
+
+#include "logger_types.h"
+#undef DC_LOGGER
+#define DC_LOGGER \
+       CTX->logger
+#define smu_print(str, ...) {DC_LOG_SMU(str, ##__VA_ARGS__); }
+
+// VBIOS and DAL to PMFW Interface
+
+// DAL to PMFW interface registers
+#define DAL_MSG_REG                             MP1_SMN_C2PMSG_71
+#define DAL_RESP_REG                            MP1_SMN_C2PMSG_72
+#define DAL_ARG_REG                             MP1_SMN_C2PMSG_73
+
+/** @defgroup ResponseCodes PMFW Response Codes
+*  @{
+*/
+// SMU Response Codes:
+#define DALSMC_Result_OK                        0x01 ///< Message Response OK
+#define DALSMC_Result_Failed                    0xFF ///< Message Response Failed
+#define DALSMC_Result_UnknownCmd                0xFE ///< Message Response Unknown Command
+#define DALSMC_Result_CmdRejectedPrereq         0xFD ///< Message Response Command Failed Prerequisite
+#define DALSMC_Result_CmdRejectedBusy           0xFC ///< Message Response Command Rejected due to PMFW is busy. Sender should retry sending this message
+/** @}*/
+
+// Message Definitions:
+/** @defgroup definitions Message definitions
+*  @{
+*/
+#define DALSMC_MSG_TestMessage                  0x01 ///< To check if PMFW is alive and responding. Requirement specified by PMFW team
+#define DALSMC_MSG_GetPmfwVersion               0x02 ///< Get version
+#define DALSMC_MSG_SetDispclkFreq               0x03 ///< Set display clock frequency in MHZ
+#define DALSMC_MSG_SetDppclkFreq                0x04 ///< Set DPP clock frequency in MHZ
+#define DALSMC_MSG_SetHardMinDcfclkByFreq       0x05 ///< Set DCF clock frequency hard min in MHZ
+#define DALSMC_MSG_SetMinDeepSleepDcfclk        0x06 ///< Set DCF clock minimum frequency in deep sleep in MHZ
+#define DALSMC_MSG_UpdatePmeRestore             0x07 ///< To ask PMFW to write into Azalia for PME wake up event
+#define DALSMC_MSG_SetDramAddrHigh              0x08 ///< Set DRAM address high 32 bits for WM table transfer
+#define DALSMC_MSG_SetDramAddrLow               0x09 ///< Set DRAM address low 32 bits for WM table transfer
+
+#define DALSMC_MSG_TransferTableSmu2Dram        0x0A ///< Transfer table from PMFW SRAM to system DRAM
+#define DALSMC_MSG_TransferTableDram2Smu        0x0B ///< Transfer table from system DRAM to PMFW
+#define DALSMC_MSG_SetDisplayIdleOptimizations  0x0C ///< Set Idle state optimization for display off
+#define DALSMC_MSG_GetDprefclkFreq              0x0D ///< Get DPREF clock frequency. Return in MHZ
+#define DALSMC_MSG_GetDtbclkFreq                0x0E ///< Get DTB clock frequency. Return in MHZ
+#define DALSMC_MSG_AllowZstatesEntry            0x0F ///< Inform PMFW of display allowing Zstate entry
+#define DALSMC_MSG_SetDtbClk                    0x10 ///< Inform PMFW to turn of/off DTB cl0ck. arg = 1: turn DTB on with 600MHZ; arg = 0: turn DTB clk off
+#define DALSMC_MSG_DispIPS2Exit                 0x11 ///< Display IPS2 exit
+
+#define DALSMC_MSG_QueryIPS2Support             0x12 ///< Return 1: support; else not supported
+#define DALSMC_Message_Count                    0x13 ///< Total number of VBIS and DAL messages
+/** @}*/
+
+
+union dcn42_dpia_host_router_bw {
+       struct {
+               uint32_t hr_id : 16;
+               uint32_t bw_mbps : 16;
+       } bits;
+       uint32_t all;
+};
+
+/*
+ * Function to be used instead of REG_WAIT macro because the wait ends when
+ * the register is NOT EQUAL to zero, and because `the translation in msg_if.h
+ * won't work with REG_WAIT.
+ */
+static uint32_t dcn42_smu_wait_for_response(struct clk_mgr_internal *clk_mgr,
+               unsigned int delay_us, unsigned int max_retries)
+{
+       uint32_t res_val = DALSMC_Result_CmdRejectedBusy;
+
+       do {
+               res_val = REG_READ(DAL_RESP_REG);
+               if (res_val != DALSMC_Result_CmdRejectedBusy)
+                       break;
+
+               if (delay_us >= 1000)
+                       msleep(delay_us/1000);
+               else if (delay_us > 0)
+                       udelay(delay_us);
+
+               if (clk_mgr->base.ctx->dc->debug.disable_timeout)
+                       max_retries++;
+       } while (max_retries--);
+
+       return res_val;
+}
+
+static int dcn42_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr,
+                                        unsigned int msg_id,
+                                        unsigned int param)
+{
+       uint32_t result;
+
+       result = dcn42_smu_wait_for_response(clk_mgr, 10, 2000000);
+
+       if (result != DALSMC_Result_OK) {
+               DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id);
+
+               if (result == DALSMC_Result_CmdRejectedBusy)
+                       return -1;
+       }
+
+       /* First clear response register */
+       REG_WRITE(DAL_RESP_REG, DALSMC_Result_CmdRejectedBusy);
+
+       /* Set the parameter register for the SMU message, unit is Mhz */
+       REG_WRITE(DAL_ARG_REG, param);
+
+       /* Trigger the message transaction by writing the message ID */
+       REG_WRITE(DAL_MSG_REG, msg_id);
+
+       result = dcn42_smu_wait_for_response(clk_mgr, 10, 2000000);
+
+       if (result == DALSMC_Result_Failed) {
+               if (msg_id == DALSMC_MSG_TransferTableDram2Smu &&
+                   param == TABLE_WATERMARKS)
+                       DC_LOG_WARNING("Watermarks table not configured properly by SMU");
+               REG_WRITE(DAL_RESP_REG, DALSMC_Result_OK);
+               DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id);
+               return -1;
+       }
+
+       if (IS_SMU_TIMEOUT(result)) {
+               ASSERT(0);
+               result = dcn42_smu_wait_for_response(clk_mgr, 10, 2000000);
+               //dm_helpers_smu_timeout(CTX, msg_id, param, 10 * 200000);
+               DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id);
+       }
+
+       return REG_READ(DAL_ARG_REG);
+}
+
+int dcn42_smu_get_pmfw_version(struct clk_mgr_internal *clk_mgr)
+{
+       return dcn42_smu_send_msg_with_param(
+                       clk_mgr,
+                       DALSMC_MSG_GetPmfwVersion,
+                       0);
+}
+
+
+int dcn42_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz)
+{
+       int actual_dispclk_set_mhz = -1;
+
+       if (!clk_mgr->smu_present)
+               return requested_dispclk_khz;
+
+       /*  Unit of SMU msg parameter is Mhz */
+       actual_dispclk_set_mhz = dcn42_smu_send_msg_with_param(
+                       clk_mgr,
+                       DALSMC_MSG_SetDispclkFreq,
+                       khz_to_mhz_ceil(requested_dispclk_khz));
+
+       smu_print("requested_dispclk_khz = %d, actual_dispclk_set_mhz: %d\n",
+               requested_dispclk_khz, actual_dispclk_set_mhz);
+       return actual_dispclk_set_mhz * 1000;
+}
+
+
+int dcn42_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz)
+{
+       int actual_dcfclk_set_mhz = -1;
+
+       if (!clk_mgr->smu_present)
+               return requested_dcfclk_khz;
+
+       actual_dcfclk_set_mhz = dcn42_smu_send_msg_with_param(
+                       clk_mgr,
+                       DALSMC_MSG_SetHardMinDcfclkByFreq,
+                       khz_to_mhz_ceil(requested_dcfclk_khz));
+
+       smu_print("requested_dcfclk_khz = %d, actual_dcfclk_set_mhz: %d\n",
+               requested_dcfclk_khz, actual_dcfclk_set_mhz);
+
+       return actual_dcfclk_set_mhz * 1000;
+}
+
+int dcn42_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz)
+{
+       int actual_min_ds_dcfclk_mhz = -1;
+
+       if (!clk_mgr->smu_present)
+               return requested_min_ds_dcfclk_khz;
+
+       actual_min_ds_dcfclk_mhz = dcn42_smu_send_msg_with_param(
+                       clk_mgr,
+                       DALSMC_MSG_SetMinDeepSleepDcfclk,
+                       khz_to_mhz_ceil(requested_min_ds_dcfclk_khz));
+
+       smu_print("requested_min_ds_dcfclk_khz = %d, actual_min_ds_dcfclk_mhz: %d\n",
+               requested_min_ds_dcfclk_khz, actual_min_ds_dcfclk_mhz);
+
+       return actual_min_ds_dcfclk_mhz * 1000;
+}
+
+int dcn42_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz)
+{
+       int actual_dppclk_set_mhz = -1;
+
+       if (!clk_mgr->smu_present)
+               return requested_dpp_khz;
+
+       actual_dppclk_set_mhz = dcn42_smu_send_msg_with_param(
+                       clk_mgr,
+                       DALSMC_MSG_SetDppclkFreq,
+                       khz_to_mhz_ceil(requested_dpp_khz));
+
+       smu_print("requested_dpp_khz = %d, actual_dppclk_set_mhz: %d\n",
+               requested_dpp_khz, actual_dppclk_set_mhz);
+
+       return actual_dppclk_set_mhz * 1000;
+}
+
+void dcn42_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info)
+{
+       if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
+               return;
+
+       if (!clk_mgr->smu_present)
+               return;
+
+       dcn42_smu_send_msg_with_param(
+               clk_mgr,
+               DALSMC_MSG_SetDisplayIdleOptimizations,
+               idle_info);
+       smu_print("%s: SMC_MSG_SetDisplayIdleOptimizations idle_info  = %x\n", __func__, idle_info);
+}
+
+void dcn42_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable)
+{
+       union display_idle_optimization_u idle_info = { 0 };
+
+       if (!clk_mgr->smu_present)
+               return;
+
+       if (enable) {
+               idle_info.idle_info.df_request_disabled = 1;
+               idle_info.idle_info.phy_ref_clk_off = 1;
+       }
+
+       dcn42_smu_send_msg_with_param(
+                       clk_mgr,
+                       DALSMC_MSG_SetDisplayIdleOptimizations,
+                       idle_info.data);
+       smu_print("%s smu_enable_phy_refclk_pwrdwn  = %d\n", __func__, enable ? 1 : 0);
+}
+
+void dcn42_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr)
+{
+       if (!clk_mgr->smu_present)
+               return;
+
+       dcn42_smu_send_msg_with_param(
+                       clk_mgr,
+                       DALSMC_MSG_UpdatePmeRestore,
+                       0);
+       smu_print("%s: SMC_MSG_UpdatePmeRestore\n", __func__);
+}
+
+void dcn42_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high)
+{
+       if (!clk_mgr->smu_present)
+               return;
+
+       dcn42_smu_send_msg_with_param(clk_mgr,
+                       DALSMC_MSG_SetDramAddrHigh, addr_high);
+}
+
+void dcn42_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low)
+{
+       if (!clk_mgr->smu_present)
+               return;
+
+       dcn42_smu_send_msg_with_param(clk_mgr,
+                       DALSMC_MSG_SetDramAddrLow, addr_low);
+}
+
+void dcn42_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr)
+{
+       if (!clk_mgr->smu_present)
+               return;
+
+       dcn42_smu_send_msg_with_param(clk_mgr,
+                       DALSMC_MSG_TransferTableSmu2Dram, TABLE_DPMCLOCKS);
+}
+
+void dcn42_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr)
+{
+       if (!clk_mgr->smu_present)
+               return;
+
+       dcn42_smu_send_msg_with_param(clk_mgr,
+                       DALSMC_MSG_TransferTableDram2Smu, TABLE_WATERMARKS);
+}
+
+void dcn42_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support)
+{
+       unsigned int msg_id, param, retv;
+
+       if (!clk_mgr->smu_present)
+               return;
+
+       switch (support) {
+
+       case DCN_ZSTATE_SUPPORT_ALLOW:
+               msg_id = DALSMC_MSG_AllowZstatesEntry;
+               param = (1 << 10) | (1 << 9) | (1 << 8);
+               smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW, param = 0x%x\n", __func__, param);
+               break;
+
+       case DCN_ZSTATE_SUPPORT_DISALLOW:
+               msg_id = DALSMC_MSG_AllowZstatesEntry;
+               param = 0;
+               smu_print("%s: SMC_MSG_AllowZstatesEntry msg_id = DISALLOW, param = 0x%x\n",  __func__, param);
+               break;
+
+
+       case DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY:
+               msg_id = DALSMC_MSG_AllowZstatesEntry;
+               param = (1 << 10);
+               smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z10_ONLY, param = 0x%x\n", __func__, param);
+               break;
+
+       case DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY:
+               msg_id = DALSMC_MSG_AllowZstatesEntry;
+               param = (1 << 10) | (1 << 8);
+               smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z8_Z10_ONLY, param = 0x%x\n", __func__, param);
+               break;
+
+       case DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY:
+               msg_id = DALSMC_MSG_AllowZstatesEntry;
+               param = (1 << 8);
+               smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z8_ONLY, param = 0x%x\n", __func__, param);
+               break;
+
+       default: //DCN_ZSTATE_SUPPORT_UNKNOWN
+               msg_id = DALSMC_MSG_AllowZstatesEntry;
+               param = 0;
+               break;
+       }
+
+
+       retv = dcn42_smu_send_msg_with_param(
+               clk_mgr,
+               msg_id,
+               param);
+       smu_print("%s:  msg_id = %d, param = 0x%x, return = 0x%x\n", __func__, msg_id, param, retv);
+}
+
+int dcn42_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr)
+{
+       int dprefclk;
+
+       if (!clk_mgr->smu_present)
+               return 0;
+
+       dprefclk = dcn42_smu_send_msg_with_param(clk_mgr,
+                                                DALSMC_MSG_GetDprefclkFreq,
+                                                0);
+
+       smu_print("%s:  SMU DPREF clk  = %d mhz\n",  __func__, dprefclk);
+       return dprefclk * 1000;
+}
+
+int dcn42_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr)
+{
+       int dtbclk;
+
+       if (!clk_mgr->smu_present)
+               return 0;
+
+       dtbclk = dcn42_smu_send_msg_with_param(clk_mgr,
+                                              DALSMC_MSG_GetDtbclkFreq,
+                                              0);
+
+       smu_print("%s: get_dtbclk  = %dmhz\n", __func__, dtbclk);
+       return dtbclk * 1000;
+}
+/* Arg = 1: Turn DTB on; 0: Turn DTB CLK OFF. when it is on, it is 600MHZ */
+void dcn42_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable)
+{
+       if (!clk_mgr->smu_present)
+               return;
+
+       dcn42_smu_send_msg_with_param(
+                       clk_mgr,
+                       DALSMC_MSG_SetDtbClk,
+                       enable);
+       smu_print("%s: smu_set_dtbclk = %d\n", __func__, enable ? 1 : 0);
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.h
new file mode 100644 (file)
index 0000000..8ba7ff0
--- /dev/null
@@ -0,0 +1,190 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 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.
+ *
+ */
+
+#ifndef DAL_DC_42_SMU_H_
+#define DAL_DC_42_SMU_H_
+
+#include "os_types.h"
+
+#ifndef PMFW_DRIVER_IF_H
+#define PMFW_DRIVER_IF_H
+#define PMFW_DRIVER_IF_VERSION 7
+
+typedef enum {
+       DSPCLK_DCFCLK = 0,
+       DSPCLK_DISPCLK,
+       DSPCLK_PIXCLK,
+       DSPCLK_PHYCLK,
+       DSPCLK_COUNT,
+} DSPCLK_e;
+
+typedef struct {
+       uint16_t Freq; // in MHz
+       uint16_t Vid;  // min voltage in SVI3 VID
+} DisplayClockTable_t;
+
+typedef struct {
+       uint16_t MinClock; // This is either DCFCLK or SOCCLK (in MHz)
+       uint16_t MaxClock; // This is either DCFCLK or SOCCLK (in MHz)
+       uint16_t MinMclk;
+       uint16_t MaxMclk;
+
+       uint8_t WmSetting;
+       uint8_t WmType; // Used for normal pstate change or memory retraining
+       uint8_t Padding[2];
+} WatermarkRowGeneric_t;
+
+#define NUM_WM_RANGES 4
+#define WM_PSTATE_CHG 0
+#define WM_RETRAINING 1
+
+typedef enum {
+       WM_SOCCLK = 0,
+       WM_DCFCLK,
+       WM_COUNT,
+} WM_CLOCK_e;
+
+typedef struct {
+       WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES];
+
+       uint32_t MmHubPadding[7]; // SMU internal use
+} Watermarks_t;
+
+#define NUM_DCFCLK_DPM_LEVELS 8
+#define NUM_DISPCLK_DPM_LEVELS 8
+#define NUM_DPPCLK_DPM_LEVELS 8
+#define NUM_SOCCLK_DPM_LEVELS 8
+#define NUM_VCN_DPM_LEVELS 8
+#define NUM_SOC_VOLTAGE_LEVELS 8
+#define NUM_VPE_DPM_LEVELS 8
+#define NUM_FCLK_DPM_LEVELS 8
+#define NUM_MEM_PSTATE_LEVELS 4
+
+typedef enum {
+       WCK_RATIO_1_1 = 0, // DDR5, Wck:ck is always 1:1;
+       WCK_RATIO_1_2,
+       WCK_RATIO_1_4,
+       WCK_RATIO_MAX
+} WCK_RATIO_e;
+
+typedef struct {
+       uint32_t UClk;
+       uint32_t MemClk;
+       uint32_t Voltage;
+       uint8_t WckRatio;
+       uint8_t Spare[3];
+} MemPstateTable_t;
+
+
+       // Watermarks
+
+
+// Freq in MHz
+// Voltage in milli volts with 2 fractional bits
+typedef struct {
+       uint32_t DcfClocks[NUM_DCFCLK_DPM_LEVELS];
+       uint32_t DispClocks[NUM_DISPCLK_DPM_LEVELS];
+       uint32_t DppClocks[NUM_DPPCLK_DPM_LEVELS];
+       uint32_t SocClocks[NUM_SOCCLK_DPM_LEVELS];
+       uint32_t VClocks[NUM_VCN_DPM_LEVELS];
+       uint32_t DClocks[NUM_VCN_DPM_LEVELS];
+       uint32_t VPEClocks[NUM_VPE_DPM_LEVELS];
+       uint32_t FclkClocks_Freq[NUM_FCLK_DPM_LEVELS];
+       uint32_t FclkClocks_Voltage[NUM_FCLK_DPM_LEVELS];
+       uint32_t SocVoltage[NUM_SOC_VOLTAGE_LEVELS];
+       MemPstateTable_t MemPstateTable[NUM_MEM_PSTATE_LEVELS];
+
+       uint8_t  NumDcfClkLevelsEnabled;
+       uint8_t  NumDispClkLevelsEnabled; //Applies to both Dispclk and Dppclk
+       uint8_t  NumSocClkLevelsEnabled;
+       uint8_t  VcnClkLevelsEnabled;     //Applies to both Vclk and Dclk
+
+       uint8_t  VpeClkLevelsEnabled;
+       uint8_t  NumMemPstatesEnabled;
+       uint8_t  NumFclkLevelsEnabled;
+       uint8_t  spare;
+
+       uint32_t MinGfxClk;
+       uint32_t MaxGfxClk;
+} DpmClocks_t_dcn42;
+
+// Throttler Status Bitmask
+
+
+#define TABLE_BIOS_IF 0    // Called by BIOS
+#define TABLE_WATERMARKS 1 // Called by DAL through VBIOS
+#define TABLE_CUSTOM_DPM 2 // Called by Driver
+#define TABLE_SPARE1 3
+#define TABLE_DPMCLOCKS 4    // Called by Driver
+#define TABLE_MOMENTARY_PM 5 // Called by Tools
+#define TABLE_MODERN_STDBY 6 // Called by Tools for Modern Standby Log
+#define TABLE_SMU_METRICS 7  // Called by Driver
+#define TABLE_COUNT 8
+
+#endif
+
+struct dcn42_watermarks {
+       // Watermarks
+       WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES];
+       uint32_t MmHubPadding[7]; // SMU internal use
+};
+
+struct dcn42_smu_dpm_clks {
+       DpmClocks_t_dcn42 *dpm_clks;
+       union large_integer mc_address;
+};
+
+struct display_idle_optimization {
+       unsigned int df_request_disabled : 1;
+       unsigned int phy_ref_clk_off : 1;
+       unsigned int s0i2_rdy : 1;
+       unsigned int reserved : 29;
+};
+
+union display_idle_optimization_u {
+       struct display_idle_optimization idle_info;
+       uint32_t data;
+};
+
+int dcn42_smu_get_pmfw_version(struct clk_mgr_internal *clk_mgr);
+int dcn42_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz);
+int dcn42_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz);
+int dcn42_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz);
+int dcn42_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz);
+void dcn42_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info);
+void dcn42_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable);
+void dcn42_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr);
+void dcn42_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high);
+void dcn42_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low);
+void dcn42_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr);
+void dcn42_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr);
+
+void dcn42_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support);
+void dcn42_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable);
+void dcn42_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable);
+
+int dcn42_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr);
+int dcn42_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr);
+
+#endif /* DAL_DC_42_SMU_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c
new file mode 100644 (file)
index 0000000..d1593dc
--- /dev/null
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "reg_helper.h"
+#include "core_types.h"
+#include "dcn35/dcn35_dccg.h"
+#include "dcn42_dccg.h"
+
+#define TO_DCN_DCCG(dccg)\
+       container_of(dccg, struct dcn_dccg, base)
+
+#define REG(reg) \
+       (dccg_dcn->regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+       dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name
+
+#define CTX \
+       dccg_dcn->base.ctx
+#define DC_LOGGER \
+       dccg->ctx->logger
+
+void dccg42_otg_add_pixel(struct dccg *dccg,
+               uint32_t otg_inst)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       switch (otg_inst) {
+       case 0:
+               REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+                               OTG0_ADD_PIXEL, 1);
+               break;
+       case 1:
+               REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+                               OTG1_ADD_PIXEL, 1);
+               break;
+       case 2:
+               REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+                               OTG2_ADD_PIXEL, 1);
+               break;
+       case 3:
+               REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+                               OTG3_ADD_PIXEL, 1);
+               break;
+       default:
+               ASSERT(0);
+       }
+}
+
+void dccg42_otg_drop_pixel(struct dccg *dccg,
+               uint32_t otg_inst)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       switch (otg_inst) {
+       case 0:
+               REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+                               OTG0_DROP_PIXEL, 1);
+               break;
+       case 1:
+               REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+                               OTG1_DROP_PIXEL, 1);
+               break;
+       case 2:
+               REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+                               OTG2_DROP_PIXEL, 1);
+               break;
+       case 3:
+               REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+                               OTG3_DROP_PIXEL, 1);
+               break;
+       default:
+               ASSERT(0);
+       }
+}
+
+void dccg42_enable_global_fgcg(struct dccg *dccg, bool value)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       if (dccg->ctx->dc->debug.disable_clock_gate)
+               value = false;
+       REG_UPDATE(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, !value);
+}
+
+void dccg42_set_physymclk(
+               struct dccg *dccg,
+               int phy_inst,
+               enum physymclk_clock_source clk_src,
+               bool force_enable)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       switch (phy_inst) {
+       case 0:
+               if (force_enable) {
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+                                       PHYASYMCLK_ROOT_GATE_DISABLE, 1);
+                       REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
+                                       PHYASYMCLK_EN, 1,
+                                       PHYASYMCLK_SRC_SEL, clk_src);
+               } else {
+                       REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
+                                       PHYASYMCLK_EN, 0,
+                                       PHYASYMCLK_SRC_SEL, 0);
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+                                       PHYASYMCLK_ROOT_GATE_DISABLE,
+                                       dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1);
+               }
+               break;
+       case 1:
+               if (force_enable) {
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+                                       PHYBSYMCLK_ROOT_GATE_DISABLE, 1);
+                       REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
+                                       PHYBSYMCLK_EN, 1,
+                                       PHYBSYMCLK_SRC_SEL, clk_src);
+               } else {
+                       REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
+                                       PHYBSYMCLK_EN, 0,
+                                       PHYBSYMCLK_SRC_SEL, 0);
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+                                       PHYBSYMCLK_ROOT_GATE_DISABLE,
+                                       dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1);
+               }
+               break;
+       case 2:
+               if (force_enable) {
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+                                       PHYCSYMCLK_ROOT_GATE_DISABLE, 1);
+                       REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
+                                       PHYCSYMCLK_EN, 1,
+                                       PHYCSYMCLK_SRC_SEL, clk_src);
+               } else {
+                       REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
+                                       PHYCSYMCLK_EN, 0,
+                                       PHYCSYMCLK_SRC_SEL, 0);
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+                                       PHYCSYMCLK_ROOT_GATE_DISABLE,
+                                       dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1);
+               }
+               break;
+       case 3:
+               if (force_enable) {
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+                                       PHYDSYMCLK_ROOT_GATE_DISABLE, 1);
+                       REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
+                                       PHYDSYMCLK_EN, 1,
+                                       PHYDSYMCLK_SRC_SEL, clk_src);
+               } else {
+                       REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
+                                       PHYDSYMCLK_EN, 0,
+                                       PHYDSYMCLK_SRC_SEL, 0);
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+                                       PHYDSYMCLK_ROOT_GATE_DISABLE,
+                                       dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1);
+               }
+               break;
+       case 4:
+               if (force_enable) {
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+                                       PHYESYMCLK_ROOT_GATE_DISABLE, 1);
+                       REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
+                                       PHYESYMCLK_EN, 1,
+                                       PHYESYMCLK_SRC_SEL, clk_src);
+               } else {
+                       REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
+                                       PHYESYMCLK_EN, 0,
+                                       PHYESYMCLK_SRC_SEL, 0);
+                       REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+                                       PHYESYMCLK_ROOT_GATE_DISABLE,
+                                       dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1);
+               }
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+}
+
+static void dccg42_init(struct dccg *dccg)
+{
+       int otg_inst;
+       struct dcn_dccg *dccg_dcn = TO_DCN_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.
+        */
+       for (otg_inst = 0; otg_inst < 4; otg_inst++)
+               dccg35_disable_symclk32_se(dccg, otg_inst);
+
+       if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) {
+               dccg401_disable_symclk32_le(dccg, 0);
+               dccg401_disable_symclk32_le(dccg, 1);
+               dccg401_disable_symclk32_le(dccg, 2);
+               dccg401_disable_symclk32_le(dccg, 3);
+       }
+
+       if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) {
+               dccg401_disable_dpstreamclk(dccg, 0);
+               dccg401_disable_dpstreamclk(dccg, 1);
+               dccg401_disable_dpstreamclk(dccg, 2);
+               dccg401_disable_dpstreamclk(dccg, 3);
+       }
+       if (!dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) {
+               REG_UPDATE_5(DCCG_GATE_DISABLE_CNTL2,
+                       PHYASYMCLK_ROOT_GATE_DISABLE, 1,
+                       PHYBSYMCLK_ROOT_GATE_DISABLE, 1,
+                       PHYCSYMCLK_ROOT_GATE_DISABLE, 1,
+                       PHYDSYMCLK_ROOT_GATE_DISABLE, 1,
+                       PHYESYMCLK_ROOT_GATE_DISABLE, 1);
+       }
+}
+
+
+static const struct dccg_funcs dccg42_funcs = {
+       .update_dpp_dto = dccg35_update_dpp_dto,
+       .dpp_root_clock_control = dccg35_dpp_root_clock_control,
+       .get_dccg_ref_freq = dccg401_get_dccg_ref_freq,
+       .dccg_init = dccg42_init,
+       .set_dpstreamclk = dccg401_set_dpstreamclk,
+       /* Redundant with above^ */
+       /* .set_dpstreamclk_root_clock_gating = dccg35_set_dpstreamclk_root_clock_gating, */
+       .enable_symclk32_se = dccg31_enable_symclk32_se,
+       .disable_symclk32_se = dccg35_disable_symclk32_se,
+       .enable_symclk32_le = dccg401_enable_symclk32_le,
+       .disable_symclk32_le = dccg401_disable_symclk32_le,
+       .set_symclk32_le_root_clock_gating = dccg31_set_symclk32_le_root_clock_gating,
+       .set_physymclk = dccg42_set_physymclk,
+       .set_dtbclk_dto = NULL,
+       .set_dto_dscclk = dccg401_set_dto_dscclk,
+       .set_ref_dscclk = dccg401_set_ref_dscclk,
+       .set_valid_pixel_rate = NULL,
+       .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
+       .set_audio_dtbclk_dto = NULL,
+       .otg_add_pixel = dccg42_otg_add_pixel,
+       .otg_drop_pixel = dccg42_otg_drop_pixel,
+       .disable_dsc = dccg35_disable_dscclk,
+       .enable_dsc = dccg35_enable_dscclk,
+       .set_pixel_rate_div = dccg401_set_pixel_rate_div,
+       .get_pixel_rate_div = dccg401_get_pixel_rate_div,
+       .trigger_dio_fifo_resync = dccg35_trigger_dio_fifo_resync,
+       .set_dp_dto = dccg401_set_dp_dto,
+       .enable_symclk_se = dccg35_enable_symclk_se,
+       .disable_symclk_se = dccg35_disable_symclk_se,
+       .set_dtbclk_p_src = dccg401_set_dtbclk_p_src,
+       .dccg_root_gate_disable_control = dccg35_root_gate_disable_control,
+       .dccg_read_reg_state = dccg31_read_reg_state,
+       .dccg_enable_global_fgcg = dccg42_enable_global_fgcg,
+};
+
+struct dccg *dccg42_create(
+       struct dc_context *ctx,
+       const struct dccg_registers *regs,
+       const struct dccg_shift *dccg_shift,
+       const struct dccg_mask *dccg_mask)
+{
+       struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
+       struct dccg *base;
+
+       if (dccg_dcn == NULL) {
+               BREAK_TO_DEBUGGER();
+               return NULL;
+       }
+
+       base = &dccg_dcn->base;
+       base->ctx = ctx;
+       base->funcs = &dccg42_funcs;
+
+       dccg_dcn->regs = regs;
+       dccg_dcn->dccg_shift = dccg_shift;
+       dccg_dcn->dccg_mask = dccg_mask;
+
+       return &dccg_dcn->base;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h
new file mode 100644 (file)
index 0000000..96eae00
--- /dev/null
@@ -0,0 +1,263 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2024-2026 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 __DCN42_DCCG_H__
+#define __DCN42_DCCG_H__
+
+#include "dcn401/dcn401_dccg.h"
+
+#define DCCG_MASK_SH_LIST_DCN42_COMMON(mask_sh) \
+       DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 0, mask_sh),\
+       DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 1, mask_sh),\
+       DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 2, mask_sh),\
+       DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 3, mask_sh),\
+       DCCG_SF(DPPCLK_CTRL, DPPCLK0_EN, mask_sh),\
+       DCCG_SF(DPPCLK_CTRL, DPPCLK1_EN, mask_sh),\
+       DCCG_SF(DPPCLK_CTRL, DPPCLK2_EN, mask_sh),\
+       DCCG_SF(DPPCLK_CTRL, DPPCLK3_EN, mask_sh),\
+       DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_STEP_DELAY, mask_sh),\
+       DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_STEP_SIZE, mask_sh),\
+       DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_FREQ_RAMP_DONE, mask_sh),\
+       DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_MAX_ERRDET_CYCLES, mask_sh),\
+       DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_RESET, mask_sh),\
+       DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_STATE, mask_sh),\
+       DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_OVR_EN, mask_sh),\
+       DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_CHG_FWD_CORR_DISABLE, mask_sh),\
+       DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_PHASE, mask_sh),\
+       DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_MODULO, mask_sh),\
+       DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_EN, mask_sh),\
+       DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_SRC_SEL, mask_sh),\
+       DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_EN, mask_sh),\
+       DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_SRC_SEL, mask_sh),\
+       DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_EN, mask_sh),\
+       DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_SRC_SEL, mask_sh),\
+       DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_EN, mask_sh),\
+       DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_SRC_SEL, mask_sh),\
+       DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_EN, mask_sh),\
+       DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_SRC_SEL, mask_sh),\
+       DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK0_EN, mask_sh),\
+       DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN, mask_sh),\
+       DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN, mask_sh),\
+       DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN, mask_sh),\
+       DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK0_SRC_SEL, mask_sh),\
+       DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK1_SRC_SEL, mask_sh),\
+       DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_SRC_SEL, mask_sh),\
+       DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_SRC_SEL, mask_sh),\
+       DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_EN, mask_sh),\
+       DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE2_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_EN, mask_sh),\
+       DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_EN, mask_sh),\
+       DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE2_EN, mask_sh),\
+       DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_EN, mask_sh),\
+       DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE0_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE1_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE2_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE3_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE0_EN, mask_sh),\
+       DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE1_EN, mask_sh),\
+       DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE2_EN, mask_sh),\
+       DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE3_EN, mask_sh),\
+       DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 0, mask_sh),\
+       DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 1, mask_sh),\
+       DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 2, mask_sh),\
+       DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 3, mask_sh),\
+       DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG0_ADD_PIXEL, mask_sh),\
+       DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG1_ADD_PIXEL, mask_sh),\
+       DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG2_ADD_PIXEL, mask_sh),\
+       DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG3_ADD_PIXEL, mask_sh),\
+       DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG0_DROP_PIXEL, mask_sh),\
+       DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG1_DROP_PIXEL, mask_sh),\
+       DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG2_DROP_PIXEL, mask_sh),\
+       DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG3_DROP_PIXEL, mask_sh),\
+       DCCG_SF(OTG_PIXEL_RATE_DIV, OTG0_TMDS_PIXEL_RATE_DIV, mask_sh),\
+       DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO0_INT, mask_sh),\
+       DCCG_SF(OTG_PIXEL_RATE_DIV, OTG1_TMDS_PIXEL_RATE_DIV, mask_sh),\
+       DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO1_INT, mask_sh),\
+       DCCG_SF(OTG_PIXEL_RATE_DIV, OTG2_TMDS_PIXEL_RATE_DIV, mask_sh),\
+       DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO2_INT, mask_sh),\
+       DCCG_SF(OTG_PIXEL_RATE_DIV, OTG3_TMDS_PIXEL_RATE_DIV, mask_sh),\
+       DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO3_INT, mask_sh),\
+       DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P0_SRC_SEL, mask_sh),\
+       DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P0_EN, mask_sh),\
+       DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P1_SRC_SEL, mask_sh),\
+       DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P1_EN, mask_sh),\
+       DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P2_SRC_SEL, mask_sh),\
+       DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P2_EN, mask_sh),\
+       DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_SRC_SEL, mask_sh),\
+       DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_EN, mask_sh),\
+       DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\
+       DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\
+       DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh),\
+       DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, mask_sh),\
+       DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\
+       DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 0, mask_sh),\
+       DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 1, mask_sh),\
+       DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 2, mask_sh),\
+       DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 3, mask_sh),\
+       DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 0, mask_sh),\
+       DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 1, mask_sh),\
+       DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 2, mask_sh),\
+       DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 3, mask_sh),\
+       DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK0_EN, mask_sh),\
+       DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK1_EN, mask_sh),\
+       DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK2_EN, mask_sh),\
+       DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK3_EN, mask_sh),\
+       DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_PHASE, mask_sh),\
+       DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_MODULO, mask_sh),\
+       DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_PHASE, mask_sh),\
+       DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_MODULO, mask_sh),\
+       DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_PHASE, mask_sh),\
+       DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_MODULO, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL, DISPCLK_DCCG_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, HDMICHARCLK0_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, HDMISTREAMCLK0_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKA_FE_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKB_FE_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKC_FE_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKD_FE_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKA_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKB_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKC_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKD_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE0_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE1_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE2_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE3_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE0_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE1_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE2_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE3_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE0_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE1_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE2_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE3_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE0_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE1_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE2_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE3_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL4, HDMICHARCLK0_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYA_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYB_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYC_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYD_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL6, HDMISTREAMCLK0_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, mask_sh),\
+       DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, mask_sh),\
+       DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, mask_sh),\
+       DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, mask_sh),\
+       DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, mask_sh),\
+       DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, mask_sh),\
+       DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, mask_sh),\
+       DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, mask_sh),\
+       DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_SRC_SEL, mask_sh)
+
+#define DCCG_MASK_SH_LIST_DCN42(mask_sh) \
+       DCCG_MASK_SH_LIST_DCN42_COMMON(mask_sh),\
+       DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_EN, mask_sh),\
+       DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_SRC_SEL, mask_sh),\
+       DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_PHASE, mask_sh),\
+       DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_MODULO, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_PHASE, mask_sh),\
+       DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_MODULO, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYE_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, mask_sh),\
+       DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_SRC_SEL, mask_sh),\
+       DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, mask_sh),\
+       DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_EN, mask_sh),\
+       DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_SRC_SEL, mask_sh)
+
+
+void dccg42_otg_add_pixel(struct dccg *dccg,
+               uint32_t otg_inst);
+
+void dccg42_otg_drop_pixel(struct dccg *dccg,
+               uint32_t otg_inst);
+void dccg42_enable_global_fgcg(struct dccg *dccg, bool value);
+
+void dccg42_set_physymclk(
+               struct dccg *dccg,
+               int phy_inst,
+               enum physymclk_clock_source clk_src,
+               bool force_enable);
+
+struct dccg *dccg42_create(
+       struct dc_context *ctx,
+       const struct dccg_registers *regs,
+       const struct dccg_shift *dccg_shift,
+       const struct dccg_mask *dccg_mask);
+
+#endif //__DCN42_DCCG_H__
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c
new file mode 100644 (file)
index 0000000..35dfe3b
--- /dev/null
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "reg_helper.h"
+
+#include "core_types.h"
+#include "link_encoder.h"
+#include "dcn35/dcn35_dio_link_encoder.h"
+#include "dcn42_dio_link_encoder.h"
+
+#ifndef MIN
+#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
+#endif
+
+#define CTX \
+       enc10->base.ctx
+#define DC_LOGGER \
+       enc10->base.ctx->logger
+
+#define REG(reg)\
+       (enc10->link_regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+       enc10->link_shift->field_name, enc10->link_mask->field_name
+
+#define HPD_REG(reg)\
+       (enc10->hpd_regs->reg)
+
+#define HPD_REG_GET(reg_name, field, val)      \
+               generic_reg_get(CTX, HPD_REG(reg_name), \
+                               FN(reg_name, field), val)
+
+#define HPD_REG_SET_N(reg_name, n, initial_val, ...)   \
+               generic_reg_set_ex(CTX, \
+                               HPD_REG(reg_name), \
+                               initial_val, \
+                               n, __VA_ARGS__)
+
+#define HPD_REG_SET_2(reg, init_value, f1, v1, f2, v2) \
+               HPD_REG_SET_N(reg, 2, init_value, \
+                               FN(reg, f1), v1,\
+                               FN(reg, f2), v2)
+
+bool dcn42_get_hpd_state(struct link_encoder *enc)
+{
+       struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+       uint32_t state;
+
+       HPD_REG_GET(DC_HPD_INT_STATUS, DC_HPD_SENSE, &state);
+
+       return state;
+}
+
+bool dcn42_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms,    int delay_on_disconnect_in_ms)
+{
+       struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+
+       HPD_REG_SET_2(DC_HPD_TOGGLE_FILT_CNTL, 0,
+                       DC_HPD_CONNECT_INT_DELAY, delay_on_connect_in_ms,
+                       DC_HPD_DISCONNECT_INT_DELAY, delay_on_disconnect_in_ms);
+
+       return true;
+}
+
+static const struct link_encoder_funcs dcn42_link_enc_funcs = {
+       .read_state = link_enc2_read_state,
+       .validate_output_with_stream =
+                       dcn30_link_encoder_validate_output_with_stream,
+       .hw_init = dcn35_link_encoder_init,
+       .setup = dcn35_link_encoder_setup,
+       .enable_tmds_output = dcn10_link_encoder_enable_tmds_output,
+       .enable_dp_output = dcn35_link_encoder_enable_dp_output,
+       .enable_dp_mst_output = dcn35_link_encoder_enable_dp_mst_output,
+       .disable_output = dcn35_link_encoder_disable_output,
+       .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings,
+       .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern,
+       .update_mst_stream_allocation_table =
+               dcn10_link_encoder_update_mst_stream_allocation_table,
+       .psr_program_dp_dphy_fast_training =
+                       dcn10_psr_program_dp_dphy_fast_training,
+       .psr_program_secondary_packet = dcn10_psr_program_secondary_packet,
+       .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe,
+       .enable_hpd = dcn10_link_encoder_enable_hpd,
+       .disable_hpd = dcn10_link_encoder_disable_hpd,
+       .is_dig_enabled = dcn35_is_dig_enabled,
+       .destroy = dcn10_link_encoder_destroy,
+       .fec_set_enable = enc2_fec_set_enable,
+       .fec_set_ready = enc2_fec_set_ready,
+       .fec_is_active = enc2_fec_is_active,
+       .get_dig_frontend = dcn10_get_dig_frontend,
+       .get_dig_mode = dcn401_get_dig_mode,
+       .is_in_alt_mode = dcn32_link_encoder_is_in_alt_mode,
+       .get_max_link_cap = dcn32_link_encoder_get_max_link_cap,
+       .set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
+       .enable_dpia_output = dcn35_link_encoder_enable_dpia_output,
+       .disable_dpia_output = dcn35_link_encoder_disable_dpia_output,
+       .get_hpd_state = dcn42_get_hpd_state,
+       .program_hpd_filter = dcn42_program_hpd_filter,
+};
+
+void dcn42_link_encoder_construct(
+       struct dcn20_link_encoder *enc20,
+       const struct encoder_init_data *init_data,
+       const struct encoder_feature_support *enc_features,
+       const struct dcn10_link_enc_registers *link_regs,
+       const struct dcn10_link_enc_aux_registers *aux_regs,
+       const struct dcn10_link_enc_hpd_registers *hpd_regs,
+       const struct dcn10_link_enc_shift *link_shift,
+       const struct dcn10_link_enc_mask *link_mask)
+{
+       struct bp_connector_speed_cap_info bp_cap_info = {0};
+       const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;
+       enum bp_result result = BP_RESULT_OK;
+       struct dcn10_link_encoder *enc10 = &enc20->enc10;
+
+       enc10->base.funcs = &dcn42_link_enc_funcs;
+       enc10->base.ctx = init_data->ctx;
+       enc10->base.id = init_data->encoder;
+
+       enc10->base.hpd_source = init_data->hpd_source;
+       enc10->base.connector = init_data->connector;
+
+
+       enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
+
+       enc10->base.features = *enc_features;
+       if (enc10->base.connector.id == CONNECTOR_ID_USBC)
+               enc10->base.features.flags.bits.DP_IS_USB_C = 1;
+
+       enc10->base.transmitter = init_data->transmitter;
+
+       /* set the flag to indicate whether driver poll the I2C data pin
+        * while doing the DP sink detect
+        */
+
+/*     if (dal_adapter_service_is_feature_supported(as,
+               FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))
+               enc10->base.features.flags.bits.
+                       DP_SINK_DETECT_POLL_DATA_PIN = true;*/
+
+       enc10->base.output_signals =
+               SIGNAL_TYPE_DVI_SINGLE_LINK |
+               SIGNAL_TYPE_DVI_DUAL_LINK |
+               SIGNAL_TYPE_LVDS |
+               SIGNAL_TYPE_DISPLAY_PORT |
+               SIGNAL_TYPE_DISPLAY_PORT_MST |
+               SIGNAL_TYPE_EDP |
+               SIGNAL_TYPE_HDMI_TYPE_A;
+
+       enc10->link_regs = link_regs;
+       enc10->aux_regs = aux_regs;
+       enc10->hpd_regs = hpd_regs;
+       enc10->link_shift = link_shift;
+       enc10->link_mask = link_mask;
+
+       switch (enc10->base.transmitter) {
+       case TRANSMITTER_UNIPHY_A:
+               enc10->base.preferred_engine = ENGINE_ID_DIGA;
+       break;
+       case TRANSMITTER_UNIPHY_B:
+               enc10->base.preferred_engine = ENGINE_ID_DIGB;
+       break;
+       case TRANSMITTER_UNIPHY_C:
+               enc10->base.preferred_engine = ENGINE_ID_DIGC;
+       break;
+       case TRANSMITTER_UNIPHY_D:
+               enc10->base.preferred_engine = ENGINE_ID_DIGD;
+       break;
+       case TRANSMITTER_UNIPHY_E:
+               enc10->base.preferred_engine = ENGINE_ID_DIGE;
+       break;
+       default:
+               ASSERT_CRITICAL(false);
+               enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
+       }
+
+       /* default to one to mirror Windows behavior */
+       enc10->base.features.flags.bits.HDMI_6GB_EN = 1;
+
+       if (bp_funcs->get_connector_speed_cap_info)
+               result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios,
+                                               enc10->base.connector, &bp_cap_info);
+
+       /* Override features with DCE-specific values */
+       if (result == BP_RESULT_OK) {
+               enc10->base.features.flags.bits.IS_HBR2_CAPABLE =
+                               bp_cap_info.DP_HBR2_EN;
+               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 = 1;
+               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;
+       } else {
+               DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
+                               __func__,
+                               result);
+       }
+       if (enc10->base.ctx->dc->debug.hdmi20_disable) {
+               enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
+       }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.h
new file mode 100644 (file)
index 0000000..4b5a959
--- /dev/null
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 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.
+ *
+ */
+
+#ifndef __DC_LINK_ENCODER__DCN42_H__
+#define __DC_LINK_ENCODER__DCN42_H__
+
+#include "dcn401/dcn401_dio_link_encoder.h"
+
+#define LINK_ENCODER_MASK_SH_LIST_DCN42(mask_sh) \
+       LE_SF(DIG0_DIG_BE_EN_CNTL, DIG_BE_ENABLE, mask_sh),\
+       LE_SF(DIG0_DIG_BE_CNTL, DIG_RB_SWITCH_EN, mask_sh),\
+       LE_SF(DIG0_DIG_BE_CNTL, DIG_HPD_SELECT, mask_sh),\
+       LE_SF(DIG0_DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, mask_sh),\
+       LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_MODE, mask_sh),\
+       LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_CLK_EN, mask_sh),\
+       LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SOFT_RESET, mask_sh),\
+       LE_SF(DIG0_DIG_BE_CLK_CNTL, HDCP_SOFT_RESET, mask_sh),\
+       LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_CLOCK_ON, mask_sh),\
+       LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_HDCP_CLOCK_ON, mask_sh),\
+       LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_TMDS_CLOCK_ON, mask_sh),\
+       LE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\
+       LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \
+       LE_SF(DP0_DP_DPHY_CNTL, DPHY_BYPASS, mask_sh),\
+       LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE0, mask_sh),\
+       LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE1, mask_sh),\
+       LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE2, mask_sh),\
+       LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE3, mask_sh),\
+       LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, mask_sh),\
+       LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL, mask_sh),\
+       LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM1, mask_sh),\
+       LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM2, mask_sh),\
+       LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM3, mask_sh),\
+       LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM4, mask_sh),\
+       LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM5, mask_sh),\
+       LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM6, mask_sh),\
+       LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM7, mask_sh),\
+       LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM8, mask_sh),\
+       LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, mask_sh),\
+       LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, mask_sh),\
+       LE_SF(DP0_DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, mask_sh),\
+       LE_SF(DP0_DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, mask_sh),\
+       LE_SF(DP0_DP_DPHY_TRAINING_PATTERN_SEL, DPHY_TRAINING_PATTERN_SEL, mask_sh),\
+       LE_SF(DP0_DP_DPHY_HBR2_PATTERN_CONTROL, DP_DPHY_HBR2_PATTERN_CONTROL, mask_sh),\
+       LE_SF(DP0_DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, mask_sh),\
+       LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL, mask_sh),\
+       LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE, mask_sh),\
+       LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE, mask_sh),\
+       LE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\
+       LE_SF(DP0_DP_CONFIG, DP_UDI_LANES, mask_sh),\
+       LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_LINE_NUM, mask_sh),\
+       LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_PRIORITY, mask_sh),\
+       LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC0, mask_sh),\
+       LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC1, mask_sh),\
+       LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT0, mask_sh),\
+       LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT1, mask_sh),\
+       LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC2, mask_sh),\
+       LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC3, mask_sh),\
+       LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT2, mask_sh),\
+       LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT3, mask_sh),\
+       LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_SAT_UPDATE, mask_sh),\
+       LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_16_MTP_KEEPOUT, mask_sh),\
+       LE_SF(DP_AUX0_AUX_CONTROL, AUX_HPD_SEL, mask_sh),\
+       LE_SF(DP_AUX0_AUX_CONTROL, AUX_LS_READ_EN, mask_sh),\
+       LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW, mask_sh),\
+       LE_SF(HPD0_DC_HPD_CONTROL, DC_HPD_EN, mask_sh),\
+       LE_SF(HPD0_DC_HPD_INT_STATUS, DC_HPD_SENSE, mask_sh),\
+       LE_SF(HPD0_DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_CONNECT_INT_DELAY, mask_sh),\
+       LE_SF(HPD0_DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_DISCONNECT_INT_DELAY, mask_sh),\
+       LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_EN, mask_sh),\
+       LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, mask_sh),\
+       LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, mask_sh),\
+       LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \
+       LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_START_WINDOW, mask_sh),\
+       LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_HALF_SYM_DETECT_LEN, mask_sh),\
+       LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_TRANSITION_FILTER_EN, mask_sh),\
+       LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT, mask_sh),\
+       LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_START, mask_sh),\
+       LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_STOP, mask_sh),\
+       LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_PHASE_DETECT_LEN, mask_sh),\
+       LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \
+       LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\
+       LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\
+       LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\
+       LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\
+       LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\
+       LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, DISPCLK_R_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, DISPCLK_G_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, REFCLK_R_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, REFCLK_G_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, SOCCLK_G_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, SYMCLK_FE_R_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, SYMCLK_FE_G_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, SYMCLK_R_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, SYMCLK_G_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, DIO_FGCG_REP_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, DISPCLK_G_HDCP_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, SYMCLKA_G_HDCP_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, SYMCLKB_G_HDCP_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, SYMCLKC_G_HDCP_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, SYMCLKD_G_HDCP_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, SYMCLKE_G_HDCP_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, SYMCLKF_G_HDCP_GATE_DIS, mask_sh),\
+       LE_SF(DIO_CLK_CNTL, SYMCLKG_G_HDCP_GATE_DIS, mask_sh)
+
+void dcn42_link_encoder_construct(
+       struct dcn20_link_encoder *enc20,
+       const struct encoder_init_data *init_data,
+       const struct encoder_feature_support *enc_features,
+       const struct dcn10_link_enc_registers *link_regs,
+       const struct dcn10_link_enc_aux_registers *aux_regs,
+       const struct dcn10_link_enc_hpd_registers *hpd_regs,
+       const struct dcn10_link_enc_shift *link_shift,
+       const struct dcn10_link_enc_mask *link_mask);
+
+bool dcn42_get_hpd_state(struct link_encoder *enc);
+bool dcn42_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms,    int delay_on_disconnect_in_ms);
+
+#endif /* __DC_LINK_ENCODER__DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c
new file mode 100644 (file)
index 0000000..65afbfc
--- /dev/null
@@ -0,0 +1,522 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dc_bios_types.h"
+#include "dcn30/dcn30_dio_stream_encoder.h"
+#include "dcn32/dcn32_dio_stream_encoder.h"
+#include "dcn35/dcn35_dio_stream_encoder.h"
+#include "dcn401/dcn401_dio_stream_encoder.h"
+#include "dcn31/dcn31_apg.h"
+
+#include "dcn42_dio_stream_encoder.h"
+#include "reg_helper.h"
+#include "hw_shared.h"
+#include "link_service.h"
+#include "dpcd_defs.h"
+
+#define DC_LOGGER \
+               enc1->base.ctx->logger
+
+#define REG(reg)\
+       (enc1->regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+       enc1->se_shift->field_name, enc1->se_mask->field_name
+
+#define VBI_LINE_0 0
+#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000
+
+#define CTX \
+       enc1->base.ctx
+
+/* setup stream encoder in hdmi mode */
+static void enc42_stream_encoder_hdmi_set_stream_attribute(
+       struct stream_encoder *enc,
+       struct dc_crtc_timing *crtc_timing,
+       int actual_pix_clk_khz,
+       bool enable_audio)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       if (!enc->ctx->dc->debug.avoid_vbios_exec_table) {
+               struct bp_encoder_control cntl = {0};
+
+               cntl.action = ENCODER_CONTROL_SETUP;
+               cntl.engine_id = enc1->base.id;
+               cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A;
+               cntl.enable_dp_audio = enable_audio;
+               cntl.pixel_clock = actual_pix_clk_khz;
+               cntl.lanes_number = LANE_COUNT_FOUR;
+
+               if (enc1->base.bp->funcs->encoder_control(
+                               enc1->base.bp, &cntl) != BP_RESULT_OK)
+                       return;
+
+       } else {
+
+               //Set pattern for clock channel, default vlue 0x63 does not work
+               REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F);
+
+               //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup
+
+               //DIG_SOURCE_SELECT is already set in dig_connect_to_otg
+
+               /* DIG_START is removed from the register spec */
+       }
+
+       /* Configure pixel encoding */
+       enc401_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing);
+
+       /* setup HDMI engine */
+       REG_UPDATE_4(HDMI_CONTROL,
+               HDMI_DEEP_COLOR_ENABLE, 0,
+               HDMI_DATA_SCRAMBLE_EN, 0,
+               HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1,
+               HDMI_CLOCK_CHANNEL_RATE, 0);
+
+       /* Configure color depth */
+       switch (crtc_timing->display_color_depth) {
+       case COLOR_DEPTH_888:
+               REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0);
+               break;
+       case COLOR_DEPTH_101010:
+               if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
+                       REG_UPDATE_2(HDMI_CONTROL,
+                                       HDMI_DEEP_COLOR_DEPTH, 1,
+                                       HDMI_DEEP_COLOR_ENABLE, 0);
+               } else {
+                       REG_UPDATE_2(HDMI_CONTROL,
+                                       HDMI_DEEP_COLOR_DEPTH, 1,
+                                       HDMI_DEEP_COLOR_ENABLE, 1);
+                       }
+               break;
+       case COLOR_DEPTH_121212:
+               if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
+                       REG_UPDATE_2(HDMI_CONTROL,
+                                       HDMI_DEEP_COLOR_DEPTH, 2,
+                                       HDMI_DEEP_COLOR_ENABLE, 0);
+               } else {
+                       REG_UPDATE_2(HDMI_CONTROL,
+                                       HDMI_DEEP_COLOR_DEPTH, 2,
+                                       HDMI_DEEP_COLOR_ENABLE, 1);
+                       }
+               break;
+       case COLOR_DEPTH_161616:
+               REG_UPDATE_2(HDMI_CONTROL,
+                               HDMI_DEEP_COLOR_DEPTH, 3,
+                               HDMI_DEEP_COLOR_ENABLE, 1);
+               break;
+       default:
+               break;
+       }
+
+       if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) {
+               /* enable HDMI data scrambler
+                * HDMI_CLOCK_CHANNEL_RATE_MORE_340M
+                * Clock channel frequency is 1/4 of character rate.
+                */
+               REG_UPDATE_2(HDMI_CONTROL,
+                       HDMI_DATA_SCRAMBLE_EN, 1,
+                       HDMI_CLOCK_CHANNEL_RATE, 1);
+       } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) {
+
+               /* TODO: New feature for DCE11, still need to implement */
+
+               /* enable HDMI data scrambler
+                * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE
+                * Clock channel frequency is the same
+                * as character rate
+                */
+               REG_UPDATE_2(HDMI_CONTROL,
+                       HDMI_DATA_SCRAMBLE_EN, 1,
+                       HDMI_CLOCK_CHANNEL_RATE, 0);
+       }
+
+       /* Enable transmission of General Control packet on every frame */
+       REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL,
+               HDMI_GC_CONT, 1,
+               HDMI_GC_SEND, 1,
+               HDMI_NULL_SEND, 1);
+
+       /* Disable Audio Content Protection packet transmission */
+       REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0);
+       /* following belongs to audio */
+       /* Enable Audio InfoFrame packet transmission. */
+       REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1);
+
+       /* Select line number on which to send Audio InfoFrame packets */
+       REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_LINE,
+                               VBI_LINE_0 + 2);
+
+       /* set HDMI GC AVMUTE */
+       REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0);
+}
+
+static void enc42_stream_encoder_stop_dp_info_packets(
+       struct stream_encoder *enc)
+{
+       /* stop generic packets on DP */
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+       uint32_t value = 0;
+
+       REG_SET_9(DP_SEC_CNTL, 0,
+               DP_SEC_GSP0_ENABLE, 0,
+               DP_SEC_GSP1_ENABLE, 0,
+               DP_SEC_GSP2_ENABLE, 0,
+               DP_SEC_GSP3_ENABLE, 0,
+               DP_SEC_GSP4_ENABLE, 0,
+               DP_SEC_GSP5_ENABLE, 0,
+               DP_SEC_GSP6_ENABLE, 0,
+               DP_SEC_GSP7_ENABLE, 0,
+               DP_SEC_STREAM_ENABLE, 0);
+
+       /* this register shared with audio info frame.
+        * therefore we need to keep master enabled
+        * if at least one of the fields is not 0
+        */
+       value = REG_READ(DP_SEC_CNTL);
+       if (value)
+               REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1);
+}
+
+static void enc42_stream_encoder_update_hdmi_info_packets(
+       struct stream_encoder *enc,
+       const struct encoder_info_frame *info_frame)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1);
+       REG_UPDATE(DIG_FE_AUDIO_CNTL, APG_CLOCK_ENABLE, 1);
+
+       /*Always add mandatory packets first followed by optional ones*/
+       enc3_update_hdmi_info_packet(enc1, 0, &info_frame->avi);
+       enc3_update_hdmi_info_packet(enc1, 5, &info_frame->hfvsif);
+       enc3_update_hdmi_info_packet(enc1, 2, &info_frame->gamut);
+       enc3_update_hdmi_info_packet(enc1, 1, &info_frame->vendor);
+       enc3_update_hdmi_info_packet(enc1, 3, &info_frame->spd);
+       enc3_update_hdmi_info_packet(enc1, 4, &info_frame->hdrsmd);
+       enc3_update_hdmi_info_packet(enc1, 6, &info_frame->vtem);
+}
+
+static void enc42_dp_set_dsc_pps_info_packet(struct stream_encoder *enc,
+                                       bool enable,
+                                       uint8_t *dsc_packed_pps,
+                                       bool immediate_update)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       if (enable) {
+               struct dc_info_packet pps_sdp;
+               int i;
+
+               /* Configure for PPS packet size (128 bytes) */
+               REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 1);
+
+               /* 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);
+                       enc1->base.vpg->funcs->update_generic_info_packet(
+                                                       enc1->base.vpg,
+                                                       11 + i,
+                                                       &pps_sdp,
+                                                       immediate_update);
+               }
+
+               /* SW should make sure VBID[6] update line number is bigger
+                * than PPS transmit line number
+                */
+               REG_UPDATE(DP_GSP11_CNTL,
+                               DP_SEC_GSP11_LINE_NUM, 2);
+               REG_UPDATE_2(DP_MSA_VBID_MISC,
+                               DP_VBID6_LINE_REFERENCE, 0,
+                               DP_VBID6_LINE_NUM, 3);
+
+               /* Send PPS data at the line number specified above.
+                * DP spec requires PPS to be sent only when it changes, however since
+                * decoder has to be able to handle its change on every frame, we're
+                * sending it always (i.e. on every frame) to reduce the chance it'd be
+                * missed by decoder. If it turns out required to send PPS only when it
+                * changes, we can use DP_SEC_GSP11_SEND register.
+                */
+               REG_UPDATE(DP_GSP11_CNTL,
+                       DP_SEC_GSP11_ENABLE, 1);
+               REG_UPDATE(DP_SEC_CNTL,
+                       DP_SEC_STREAM_ENABLE, 1);
+       } else {
+               /* Disable Generic Stream Packet 11 (GSP) transmission */
+               REG_UPDATE(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, 0);
+               REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 0);
+       }
+}
+
+static void enc42_se_dp_audio_setup(
+       struct stream_encoder *enc,
+       unsigned int az_inst,
+       struct audio_info *info)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+       enc42_se_enable_audio_clock(enc, true);
+
+       REG_UPDATE(DIG_FE_AUDIO_CNTL,
+                       DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst);
+
+       enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info);
+}
+
+#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1
+
+static void enc42_se_setup_dp_audio(
+       struct stream_encoder *enc)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       /* --- DP Audio packet configurations --- */
+
+       /* ATP Configuration */
+       REG_SET(DP_SEC_AUD_N, 0,
+                       DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT);
+
+       /* Async/auto-calc timestamp mode */
+       REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE,
+                       DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC);
+}
+
+static void enc42_se_dp_audio_enable(
+       struct stream_encoder *enc)
+{
+       ASSERT (enc->apg);
+       enc42_se_enable_audio_clock(enc, true);
+       /*APG_CONTROL2 for DP*/
+       enc42_se_setup_dp_audio(enc);
+       /*DP_SEC_CNTL programming*/
+       enc1_se_enable_dp_audio(enc);
+       /*APG_en*/
+       enc->apg->funcs->enable_apg(enc->apg);
+
+}
+
+static void enc42_se_disable_dp_audio(
+       struct stream_encoder *enc)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+       uint32_t value = 0;
+
+       /* Disable Audio packets */
+       REG_UPDATE_5(DP_SEC_CNTL,
+                       DP_SEC_ASP_ENABLE, 0,
+                       DP_SEC_ATP_ENABLE, 0,
+                       DP_SEC_AIP_ENABLE, 0,
+                       DP_SEC_ACM_ENABLE, 0,
+                       DP_SEC_STREAM_ENABLE, 0);
+
+       /* This register shared with encoder info frame. Therefore we need to
+        * keep master enabled if at least on of the fields is not 0
+        */
+       value = REG_READ(DP_SEC_CNTL);
+       if (value != 0)
+               REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1);
+}
+
+static void enc42_se_dp_audio_disable(
+       struct stream_encoder *enc)
+{
+
+       enc->apg->funcs->disable_apg(enc->apg);
+       enc42_se_disable_dp_audio(enc);
+       enc42_se_enable_audio_clock(enc, false);
+}
+
+static void enc42_se_setup_hdmi_audio(
+       struct stream_encoder *enc,
+       const struct audio_crtc_info *crtc_info)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       struct audio_clock_info audio_clock_info = {0};
+
+       /* HDMI_AUDIO_PACKET_CONTROL */
+       REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL,
+                       HDMI_AUDIO_DELAY_EN, 1);
+
+       /* HDMI_ACR_PACKET_CONTROL */
+       REG_UPDATE_2(HDMI_ACR_PACKET_CONTROL,
+                       HDMI_ACR_AUTO_SEND, 1,
+                       HDMI_ACR_SOURCE, 0);
+
+       /* Program audio clock sample/regeneration parameters */
+       get_audio_clock_info(crtc_info->color_depth,
+                            crtc_info->requested_pixel_clock_100Hz,
+                            crtc_info->calculated_pixel_clock_100Hz,
+                            &audio_clock_info);
+       DC_LOG_HW_AUDIO("\n%s:Input::requested_pixel_clock_100Hz = %d" \
+                       "calculated_pixel_clock_100Hz = %d\n", __func__,\
+                       crtc_info->requested_pixel_clock_100Hz, \
+                       crtc_info->calculated_pixel_clock_100Hz);
+
+       /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */
+       REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz);
+
+       /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */
+       REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz);
+
+       /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */
+       REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz);
+
+       /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */
+       REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz);
+
+       /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */
+       REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz);
+
+       /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */
+       REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz);
+
+       /* Video driver cannot know in advance which sample rate will
+        * be used by HD Audio driver
+        * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is
+        * programmed below in interruppt callback
+        */
+}
+
+static void enc42_se_hdmi_audio_disable(
+       struct stream_encoder *enc)
+{
+       ASSERT (enc->apg);
+       enc->apg->funcs->disable_apg(enc->apg);
+       enc42_se_enable_audio_clock(enc, false);
+}
+
+void enc42_se_enable_audio_clock(
+       struct stream_encoder *enc,
+       bool enable)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       REG_UPDATE(DIG_FE_AUDIO_CNTL, APG_CLOCK_ENABLE, !!enable);
+}
+
+
+static void enc42_se_hdmi_audio_setup(
+       struct stream_encoder *enc,
+       unsigned int az_inst,
+       struct audio_info *info,
+       struct audio_crtc_info *audio_crtc_info)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       ASSERT (enc->apg);
+       enc42_se_enable_audio_clock(enc, true);
+       /*ACR setup*/
+       enc42_se_setup_hdmi_audio(enc, audio_crtc_info);
+
+       REG_UPDATE(DIG_FE_AUDIO_CNTL,
+                               DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst);
+
+       /*APG_DBG_GEN_CONTROL*/
+       enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info);
+       /*APG enable*/
+       enc->apg->funcs->enable_apg(enc->apg);
+}
+
+static void enc42_audio_mute_control(
+       struct stream_encoder *enc,
+       bool mute)
+{
+       if (mute)
+               enc->apg->funcs->disable_apg(enc->apg);
+       else
+               enc->apg->funcs->enable_apg(enc->apg);
+}
+void enc42_reset_hdmi_stream_attribute(
+       struct stream_encoder *enc)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       REG_UPDATE_3(HDMI_CONTROL,
+               HDMI_DEEP_COLOR_ENABLE, 0,
+               HDMI_DATA_SCRAMBLE_EN, 0,
+               HDMI_CLOCK_CHANNEL_RATE, 0);
+}
+
+static const struct stream_encoder_funcs dcn42_str_enc_funcs = {
+       .dp_set_stream_attribute =
+               enc401_stream_encoder_dp_set_stream_attribute,
+       .hdmi_set_stream_attribute =
+               enc42_stream_encoder_hdmi_set_stream_attribute,
+       .dvi_set_stream_attribute =
+               enc401_stream_encoder_dvi_set_stream_attribute,
+       .set_throttled_vcp_size =
+               enc1_stream_encoder_set_throttled_vcp_size,
+       .update_hdmi_info_packets =
+               enc42_stream_encoder_update_hdmi_info_packets,
+       .stop_hdmi_info_packets =
+               enc3_stream_encoder_stop_hdmi_info_packets,
+       .update_dp_info_packets_sdp_line_num =
+               enc3_stream_encoder_update_dp_info_packets_sdp_line_num,
+       .update_dp_info_packets =
+               enc3_stream_encoder_update_dp_info_packets,
+       .stop_dp_info_packets =
+               enc42_stream_encoder_stop_dp_info_packets,
+       .dp_blank =
+               enc1_stream_encoder_dp_blank,
+       .dp_unblank =
+               enc401_stream_encoder_dp_unblank,
+       .audio_mute_control = enc42_audio_mute_control,
+
+       .dp_audio_setup = enc42_se_dp_audio_setup,
+       .dp_audio_enable = enc42_se_dp_audio_enable,
+       .dp_audio_disable = enc42_se_dp_audio_disable,
+
+       .hdmi_audio_setup = enc42_se_hdmi_audio_setup,
+       .hdmi_audio_disable = enc42_se_hdmi_audio_disable,
+       .setup_stereo_sync  = enc1_setup_stereo_sync,
+       .set_avmute = enc1_stream_encoder_set_avmute,
+       .dig_connect_to_otg = enc1_dig_connect_to_otg,
+       .dig_source_otg = enc1_dig_source_otg,
+
+       .dp_get_pixel_format  = enc1_stream_encoder_dp_get_pixel_format,
+
+       .enc_read_state = enc401_read_state,
+       .dp_set_dsc_config = NULL,
+       .dp_set_dsc_pps_info_packet = enc42_dp_set_dsc_pps_info_packet,
+       .set_dynamic_metadata = enc401_set_dynamic_metadata,
+       .hdmi_reset_stream_attribute = enc42_reset_hdmi_stream_attribute,
+       .enable_stream = enc401_stream_encoder_enable,
+
+       .set_input_mode = enc401_set_dig_input_mode,
+       .enable_fifo = enc35_enable_fifo,
+       .disable_fifo = enc35_disable_fifo,
+       .map_stream_to_link = enc401_stream_encoder_map_to_link,
+};
+
+void dcn42_dio_stream_encoder_construct(
+       struct dcn10_stream_encoder *enc1,
+       struct dc_context *ctx,
+       struct dc_bios *bp,
+       enum engine_id eng_id,
+       struct vpg *vpg,
+       struct apg *apg,
+       const struct dcn10_stream_enc_registers *regs,
+       const struct dcn10_stream_encoder_shift *se_shift,
+       const struct dcn10_stream_encoder_mask *se_mask)
+{
+       enc1->base.funcs = &dcn42_str_enc_funcs;
+       enc1->base.ctx = ctx;
+       enc1->base.id = eng_id;
+       enc1->base.bp = bp;
+       enc1->base.vpg = vpg;
+       enc1->base.apg = apg;
+       enc1->regs = regs;
+       enc1->se_shift = se_shift;
+       enc1->se_mask = se_mask;
+       enc1->base.stream_enc_inst = vpg->inst;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.h
new file mode 100644 (file)
index 0000000..7a98fee
--- /dev/null
@@ -0,0 +1,206 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 - 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 __DC_DIO_STREAM_ENCODER_DCN42_H__
+#define __DC_DIO_STREAM_ENCODER_DCN42_H__
+
+#include "dcn30/dcn30_vpg.h"
+#include "stream_encoder.h"
+#include "dcn20/dcn20_stream_encoder.h"
+
+#define SE_COMMON_MASK_SH_LIST_DCN42(mask_sh)\
+       SE_SF(DP0_DP_PIXEL_FORMAT, PIXEL_ENCODING_TYPE, mask_sh),\
+       SE_SF(DP0_DP_PIXEL_FORMAT, UNCOMPRESSED_PIXEL_FORMAT, mask_sh),\
+       SE_SF(DP0_DP_PIXEL_FORMAT, UNCOMPRESSED_COMPONENT_DEPTH, mask_sh),\
+       SE_SF(DP0_DP_PIXEL_FORMAT, COMPRESSED_PIXEL_FORMAT, mask_sh),\
+       SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\
+       SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\
+       SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\
+       SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\
+       SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\
+       SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\
+       SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\
+       SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\
+       SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\
+       SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\
+       SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\
+       SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\
+       SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\
+       SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\
+       SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\
+       SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\
+       SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\
+       SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\
+       SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\
+       SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\
+       SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\
+       SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\
+       SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\
+       SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\
+       SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\
+       SE_SF(DIG1_HDMI_CONTROL, TMDS_PIXEL_ENCODING, mask_sh),\
+       SE_SF(DIG1_HDMI_CONTROL, TMDS_COLOR_FORMAT, mask_sh),\
+       SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\
+       SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\
+       SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP11_PPS, mask_sh),\
+       SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, mask_sh),\
+       SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\
+       SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\
+       SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\
+       SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\
+       SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\
+       SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\
+       SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\
+       SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\
+       SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\
+       SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\
+       SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\
+       SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\
+       SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\
+       SE_SF(DP0_DP_VID_TIMING, DP_VID_N_INTERVAL, mask_sh),\
+       SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh), \
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_CONT, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_SEND, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC8_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC9_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC10_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC11_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC12_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC13_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL10, HDMI_GENERIC14_LINE, mask_sh),\
+       SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\
+       SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\
+       SE_SF(DME0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\
+       SE_SF(DME0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\
+       SE_SF(DME0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\
+       SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\
+       SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\
+       SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\
+       SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\
+       SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\
+       SE_SF(DIG0_HDMI_CONTROL, DOLBY_VISION_EN, mask_sh),\
+       SE_SF(DIG0_DIG_FE_EN_CNTL, DIG_FE_ENABLE, mask_sh),\
+       SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_MODE, mask_sh),\
+       SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, mask_sh),\
+       SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_SOFT_RESET, mask_sh),\
+       SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\
+       SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh),\
+       SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\
+       SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE, mask_sh),\
+       SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, mask_sh),\
+       SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, mask_sh),\
+       SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET, mask_sh),\
+       SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, mask_sh),\
+       SE_SF(DIG0_STREAM_MAPPER_CONTROL, DIG_STREAM_LINK_TARGET, mask_sh),\
+       SE_SF(DIG0_DIG_FE_AUDIO_CNTL, DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, mask_sh),\
+       SE_SF(DIG0_DIG_FE_AUDIO_CNTL, APG_CLOCK_ENABLE, mask_sh)
+
+void dcn42_dio_stream_encoder_construct(
+       struct dcn10_stream_encoder *enc1,
+       struct dc_context *ctx,
+       struct dc_bios *bp,
+       enum engine_id eng_id,
+       struct vpg *vpg,
+       struct apg *apg,
+       const struct dcn10_stream_enc_registers *regs,
+       const struct dcn10_stream_encoder_shift *se_shift,
+       const struct dcn10_stream_encoder_mask *se_mask);
+
+void enc42_se_enable_audio_clock(
+       struct stream_encoder *enc,
+       bool enable);
+
+void enc42_reset_hdmi_stream_attribute(
+       struct stream_encoder *enc);
+#endif /* __DC_DIO_STREAM_ENCODER_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c
new file mode 100644 (file)
index 0000000..244c91b
--- /dev/null
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dm_services.h"
+#include "core_types.h"
+#include "reg_helper.h"
+#include "dcn42_dpp.h"
+#include "dcn35/dcn35_dpp.h"
+
+#define REG(reg)\
+       dpp->tf_regs->reg
+
+#define CTX \
+       dpp->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+       dpp->tf_shift->field_name, dpp->tf_mask->field_name
+
+static const uint32_t *get_hist_rgb_luma_coefs(enum dc_color_space color_space)
+{
+       // Coefs in s.6.12.
+       // Y = 0.2126R + 0.7152G + 0.0722B
+       static const uint32_t luma_transform_bt_709[] = {0x1cb36, 0x1e6e2, 0x1b27b};
+       // Y = 0.2627R + 0.678G + 0.0593B
+       static const uint32_t luma_transform_bt_2020[] = {0x1d0d0, 0x1e5b2, 0x1ae5c};
+
+       switch (color_space) {
+       case COLOR_SPACE_2020_RGB_FULLRANGE:
+       case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
+               return luma_transform_bt_2020;
+       default:
+               return luma_transform_bt_709;
+       }
+}
+
+static void dpp42_dpp_cm_hist_control(
+       struct dpp *dpp_base,
+       struct cm_hist_control cntl,
+       enum dc_color_space color_space)
+{
+       struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base);
+
+       REG_UPDATE_10(
+               CM_HIST_CNTL,
+               CM_HIST_SEL, cntl.tap_point,
+               CM_HIST_CH_EN, cntl.channels_enabled,
+               CM_HIST_SRC1_SEL, cntl.src_1_select,
+               CM_HIST_SRC2_SEL, cntl.src_2_select,
+               CM_HIST_SRC3_SEL, cntl.src_3_select,
+               CM_HIST_CH1_XBAR, cntl.ch1_src,
+               CM_HIST_CH2_XBAR, cntl.ch2_src,
+               CM_HIST_CH3_XBAR, cntl.ch3_src,
+               CM_HIST_FORMAT, cntl.format,
+               CM_HIST_READ_CHANNEL_MASK, cntl.read_channel_mask);
+
+       if (cntl.src_2_select == CM_HIST_SRC2_MODE_RGB_TO_Y) {
+               const uint32_t *luma_transform = get_hist_rgb_luma_coefs(color_space);
+
+               REG_UPDATE(CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, luma_transform[0]);
+               REG_UPDATE(CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, luma_transform[1]);
+               REG_UPDATE(CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, luma_transform[2]);
+       } else {
+               REG_UPDATE(CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, 0);
+               REG_UPDATE(CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, 0x1f000); // 1 in s.6.12
+               REG_UPDATE(CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, 0);
+       }
+}
+
+static bool dpp42_dpp_cm_hist_read(struct dpp *dpp_base, struct cm_hist *hist_out)
+{
+       struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base);
+       uint32_t channel_mask = 0;
+       uint32_t rdy_status = 0, rdy_status_a = 0, rdy_status_b = 0;
+       bool ch1, ch2, ch3;
+
+       if (hist_out == NULL)
+               return false;
+
+
+       REG_GET(CM_HIST_CNTL, CM_HIST_READ_CHANNEL_MASK, &channel_mask);
+       ch1 = (channel_mask & 1) > 0;
+       ch2 = (channel_mask & 2) > 0;
+       ch3 = (channel_mask & 4) > 0;
+
+       REG_GET(CM_HIST_STATUS, CM_HIST_BUFA_RDY_STATUS, &rdy_status_a);
+       REG_GET(CM_HIST_STATUS, CM_HIST_BUFB_RDY_STATUS, &rdy_status_b);
+
+       rdy_status = rdy_status_a || rdy_status_b;
+
+       if (rdy_status) {
+               REG_UPDATE(CM_HIST_LOCK, CM_HIST_LOCK, 1);
+               REG_UPDATE(CM_HIST_INDEX, CM_HIST_INDEX, 0);
+               for (int i = 0; i < 256; i++) {
+                       uint32_t temp;
+
+                       if (ch1) {
+                               REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp);
+                               hist_out->ch1[i] += temp;
+                       }
+                       if (ch2) {
+                               REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp);
+                               hist_out->ch2[i] += temp;
+                       }
+                       if (ch3) {
+                               REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp);
+                               hist_out->ch3[i] += temp;
+                       }
+               }
+               REG_UPDATE(CM_HIST_LOCK, CM_HIST_LOCK, 0);
+               return true;
+       } else {
+               return false;
+       }
+}
+
+static void dpp42_dpp_setup(
+       struct dpp *dpp_base,
+       enum surface_pixel_format format,
+       enum expansion_mode mode,
+       struct dc_csc_transform input_csc_color_matrix,
+       enum dc_color_space input_color_space,
+       struct cnv_alpha_2bit_lut *alpha_2bit_lut)
+{
+       struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
+       uint32_t pixel_format = 0;
+       uint32_t alpha_en = 1;
+       enum dc_color_space color_space = COLOR_SPACE_SRGB;
+       enum dcn10_input_csc_select select = INPUT_CSC_SELECT_BYPASS;
+       uint32_t is_2bit = 0;
+       uint32_t alpha_plane_enable = 0;
+       uint32_t dealpha_en = 0, dealpha_ablnd_en = 0;
+       uint32_t realpha_en = 0, realpha_ablnd_en = 0;
+       uint32_t program_prealpha_dealpha = 0;
+       struct out_csc_color_matrix tbl_entry;
+       int i;
+
+       REG_SET_2(FORMAT_CONTROL, 0,
+               CNVC_BYPASS, 0,
+               FORMAT_EXPANSION_MODE, mode);
+
+       REG_UPDATE(FORMAT_CONTROL, FORMAT_CNV16, 0);
+       REG_UPDATE(FORMAT_CONTROL, CNVC_BYPASS_MSB_ALIGN, 0);
+       REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE, 0);
+       REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE_C, 0);
+
+       REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_R, 0);
+       REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_G, 1);
+       REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_B, 2);
+
+       switch (format) {
+       case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
+               pixel_format = 1;
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
+               pixel_format = 3;
+               alpha_en = 0;
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
+       case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
+               pixel_format = 8;
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
+       case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
+               pixel_format = 10;
+               is_2bit = 1;
+               break;
+       case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
+               pixel_format = 65;
+               color_space = COLOR_SPACE_YCBCR709;
+               select = INPUT_CSC_SELECT_ICSC;
+               break;
+       case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
+               pixel_format = 64;
+               color_space = COLOR_SPACE_YCBCR709;
+               select = INPUT_CSC_SELECT_ICSC;
+               break;
+       case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
+               pixel_format = 67;
+               color_space = COLOR_SPACE_YCBCR709;
+               select = INPUT_CSC_SELECT_ICSC;
+               break;
+       case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
+               pixel_format = 66;
+               color_space = COLOR_SPACE_YCBCR709;
+               select = INPUT_CSC_SELECT_ICSC;
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
+       case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
+               pixel_format = 26; /* ARGB16161616_UNORM */
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
+               pixel_format = 24;
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
+               pixel_format = 25;
+               break;
+       case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888:
+               pixel_format = 12;
+               color_space = COLOR_SPACE_YCBCR709;
+               select = INPUT_CSC_SELECT_ICSC;
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX:
+               pixel_format = 112;
+               alpha_en = 0;
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX:
+               pixel_format = 113;
+               alpha_en = 0;
+               break;
+       case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010:
+               pixel_format = 114;
+               color_space = COLOR_SPACE_YCBCR709;
+               select = INPUT_CSC_SELECT_ICSC;
+               is_2bit = 1;
+               break;
+       case SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102:
+               pixel_format = 115;
+               color_space = COLOR_SPACE_YCBCR709;
+               select = INPUT_CSC_SELECT_ICSC;
+               is_2bit = 1;
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_RGBE:
+               pixel_format = 116;
+               alpha_plane_enable = 0;
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
+               pixel_format = 116;
+               alpha_plane_enable = 1;
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT:
+               pixel_format = 118;
+               alpha_en = 0;
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT:
+               pixel_format = 119;
+               alpha_en = 0;
+               break;
+       default:
+               break;
+       }
+
+       /* Set default color space based on format if none is given. */
+       color_space = input_color_space ? input_color_space : color_space;
+
+       if (is_2bit == 1 && alpha_2bit_lut != NULL) {
+               REG_UPDATE(ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT0, alpha_2bit_lut->lut0);
+               REG_UPDATE(ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT1, alpha_2bit_lut->lut1);
+               REG_UPDATE(ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT2, alpha_2bit_lut->lut2);
+               REG_UPDATE(ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT3, alpha_2bit_lut->lut3);
+       }
+
+       REG_SET_2(CNVC_SURFACE_PIXEL_FORMAT, 0,
+               CNVC_SURFACE_PIXEL_FORMAT, pixel_format,
+               CNVC_ALPHA_PLANE_ENABLE, alpha_plane_enable);
+       REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en);
+
+       if (program_prealpha_dealpha) {
+               dealpha_en = 1;
+               realpha_en = 1;
+       }
+       REG_SET_2(PRE_DEALPHA, 0,
+               PRE_DEALPHA_EN, dealpha_en,
+               PRE_DEALPHA_ABLND_EN, dealpha_ablnd_en);
+       REG_SET_2(PRE_REALPHA, 0,
+               PRE_REALPHA_EN, realpha_en,
+               PRE_REALPHA_ABLND_EN, realpha_ablnd_en);
+
+       /* If input adjustment exists, program the ICSC with those values. */
+       if (input_csc_color_matrix.enable_adjustment == true) {
+               for (i = 0; i < 12; i++)
+                       tbl_entry.regval[i] = input_csc_color_matrix.matrix[i];
+
+               tbl_entry.color_space = input_color_space;
+
+               if (color_space >= COLOR_SPACE_YCBCR601)
+                       select = INPUT_CSC_SELECT_ICSC;
+               else
+                       select = INPUT_CSC_SELECT_BYPASS;
+
+               dpp3_program_post_csc(dpp_base, color_space, select,
+                       &tbl_entry);
+       } else {
+               dpp3_program_post_csc(dpp_base, color_space, select, NULL);
+       }
+}
+
+static struct dpp_funcs dcn42_dpp_funcs = {
+       .dpp_program_gamcor_lut         = dpp3_program_gamcor_lut,
+       .dpp_read_state                         = dpp401_read_state,
+       .dpp_reset                                      = dpp_reset,
+       .dpp_set_scaler                         = dpp401_dscl_set_scaler_manual_scale,
+       .dpp_get_optimal_number_of_taps = dpp3_get_optimal_number_of_taps,
+       .dpp_set_pre_degam                      = dpp3_set_pre_degam,
+       .dpp_setup                                      = dpp42_dpp_setup,
+       .dpp_program_cm_dealpha         = dpp3_program_cm_dealpha,
+       .dpp_program_cm_bias            = dpp3_program_cm_bias,
+       .dpp_program_bias_and_scale     = dpp35_program_bias_and_scale_fcnv,
+       .dpp_cnv_set_alpha_keyer        = dpp2_cnv_set_alpha_keyer,
+       .set_cursor_attributes          = dpp401_set_cursor_attributes,
+       .set_cursor_position            = dpp401_set_cursor_position,
+       .set_optional_cursor_attributes = dpp401_set_optional_cursor_attributes,
+       .dpp_dppclk_control                     = dpp35_dppclk_control,
+       .dpp_set_hdr_multiplier         = dpp3_set_hdr_multiplier,
+       .set_cursor_matrix                      = dpp401_set_cursor_matrix,
+       .dpp_cm_hist_control        = dpp42_dpp_cm_hist_control,
+       .dpp_cm_hist_read           = dpp42_dpp_cm_hist_read,
+       .dpp_read_reg_state                     = dpp30_read_reg_state,
+};
+
+
+static struct dpp_caps dcn42_dpp_cap = {
+       .dscl_data_proc_format = DSCL_DATA_PRCESSING_FLOAT_FORMAT,
+       .max_lb_partitions = 63,
+       .dscl_calc_lb_num_partitions = dscl401_calc_lb_num_partitions,
+};
+
+bool dpp42_construct(
+       struct dcn42_dpp *dpp,
+       struct dc_context *ctx,
+       uint32_t inst,
+       const struct dcn42_dpp_registers *tf_regs,
+       const struct dcn42_dpp_shift *tf_shift,
+       const struct dcn42_dpp_mask *tf_mask)
+{
+       dpp->base.ctx = ctx;
+
+       dpp->base.inst = inst;
+       dpp->base.funcs = &dcn42_dpp_funcs;
+       dpp->base.caps = &dcn42_dpp_cap;
+
+       dpp->tf_regs = tf_regs;
+       dpp->tf_shift = tf_shift;
+       dpp->tf_mask = tf_mask;
+
+       return true;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h
new file mode 100644 (file)
index 0000000..f4ee419
--- /dev/null
@@ -0,0 +1,469 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2026 Advanced Micro Devices, Inc. */
+
+#ifndef __DCN42_DPP_H__
+#define __DCN42_DPP_H__
+
+#include "dcn401/dcn401_dpp.h"
+
+#define TO_DCN42_DPP(dpp)\
+        container_of(dpp, struct dcn42_dpp, base)
+
+#define DPP_REG_LIST_SH_MASK_DCN42_COMMON(mask_sh)\
+       TF_SF(CM0_CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, mask_sh),\
+       TF_SF(CM0_CM_DEALPHA, CM_DEALPHA_EN, mask_sh),\
+       TF_SF(CM0_CM_DEALPHA, CM_DEALPHA_ABLND, mask_sh),\
+       TF_SF(CM0_CM_BIAS_CR_R, CM_BIAS_CR_R, mask_sh),\
+       TF_SF(CM0_CM_BIAS_Y_G_CB_B, CM_BIAS_Y_G, mask_sh),\
+       TF_SF(CM0_CM_BIAS_Y_G_CB_B, CM_BIAS_CB_B, mask_sh),\
+       TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_DIS, mask_sh),\
+       TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, mask_sh),\
+       TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_DIS, mask_sh),\
+       TF_SF(CNVC_CFG0_PRE_DEGAM, PRE_DEGAM_MODE, mask_sh),\
+       TF_SF(CNVC_CFG0_PRE_DEGAM, PRE_DEGAM_SELECT, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_MODE, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_PWL_DISABLE, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_MODE_CURRENT, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT_CURRENT, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_LUT_INDEX, CM_GAMCOR_LUT_INDEX, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_LUT_DATA, CM_GAMCOR_LUT_DATA, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_WRITE_COLOR_MASK, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_READ_COLOR_SEL, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_READ_DBG, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_HOST_SEL, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_CONFIG_MODE, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_RAMA_START_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_B, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_RAMA_START_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_RAMA_START_SLOPE_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_RAMA_START_BASE_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_BASE_B, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL1_B, CM_GAMCOR_RAMA_EXP_REGION_END_BASE_B, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL2_B, CM_GAMCOR_RAMA_EXP_REGION_END_B, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL2_B, CM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_RAMA_OFFSET_B, CM_GAMCOR_RAMA_OFFSET_B, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\
+       TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
+       TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\
+       TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh),\
+       TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh),\
+       TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh),\
+       TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_START, mask_sh),\
+       TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_END, mask_sh),\
+       TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_START, mask_sh),\
+       TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_END, mask_sh),\
+       TF_SF(DSCL0_LB_DATA_FORMAT, INTERLEAVE_EN, mask_sh),\
+       TF2_SF(DSCL0, LB_DATA_FORMAT__ALPHA_EN, mask_sh),\
+       TF_SF(DSCL0_LB_MEMORY_CTRL, MEMORY_CONFIG, mask_sh),\
+       TF_SF(DSCL0_LB_MEMORY_CTRL, LB_MAX_PARTITIONS, mask_sh),\
+       TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_MODE, mask_sh),\
+       TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_NUM_PIPE, mask_sh),\
+       TF_SF(DSCL0_DSCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh),\
+       TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_PIPE_ID, mask_sh),\
+       TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS, mask_sh),\
+       TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS, mask_sh),\
+       TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS_C, mask_sh),\
+       TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS_C, mask_sh),\
+       TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_TAP_PAIR_IDX, mask_sh),\
+       TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_PHASE, mask_sh),\
+       TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_FILTER_TYPE, mask_sh),\
+       TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF, mask_sh),\
+       TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF_EN, mask_sh),\
+       TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF, mask_sh),\
+       TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF_EN, mask_sh),\
+       TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh),\
+       TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_EN, mask_sh),\
+       TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_FACTOR, mask_sh),\
+       TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh),\
+       TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_EN, mask_sh),\
+       TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_FACTOR, mask_sh),\
+       TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT, mask_sh),\
+       TF_SF(DSCL0_SCL_MODE, DSCL_MODE, mask_sh),\
+       TF_SF(DSCL0_RECOUT_START, RECOUT_START_X, mask_sh),\
+       TF_SF(DSCL0_RECOUT_START, RECOUT_START_Y, mask_sh),\
+       TF_SF(DSCL0_RECOUT_SIZE, RECOUT_WIDTH, mask_sh),\
+       TF_SF(DSCL0_RECOUT_SIZE, RECOUT_HEIGHT, mask_sh),\
+       TF_SF(DSCL0_MPC_SIZE, MPC_WIDTH, mask_sh),\
+       TF_SF(DSCL0_MPC_SIZE, MPC_HEIGHT, mask_sh),\
+       TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh),\
+       TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh),\
+       TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO_C, SCL_H_SCALE_RATIO_C, mask_sh),\
+       TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO_C, SCL_V_SCALE_RATIO_C, mask_sh),\
+       TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh),\
+       TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh),\
+       TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_FRAC_C, mask_sh),\
+       TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_INT_C, mask_sh),\
+       TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh),\
+       TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh),\
+       TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_FRAC_C, mask_sh),\
+       TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_INT_C, mask_sh),\
+       TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\
+       TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh), \
+       TF_SF(CNVC_CFG0_PRE_DEALPHA, PRE_DEALPHA_EN, mask_sh), \
+       TF_SF(CNVC_CFG0_PRE_DEALPHA, PRE_DEALPHA_ABLND_EN, mask_sh), \
+       TF_SF(CNVC_CFG0_PRE_REALPHA, PRE_REALPHA_EN, mask_sh), \
+       TF_SF(CNVC_CFG0_PRE_REALPHA, PRE_REALPHA_ABLND_EN, mask_sh), \
+       TF_SF(CNVC_CFG0_PRE_CSC_MODE, PRE_CSC_MODE, mask_sh), \
+       TF_SF(CNVC_CFG0_PRE_CSC_MODE, PRE_CSC_MODE_CURRENT, mask_sh), \
+       TF_SF(CNVC_CFG0_PRE_CSC_C11_C12, PRE_CSC_C11, mask_sh), \
+       TF_SF(CNVC_CFG0_PRE_CSC_C11_C12, PRE_CSC_C12, mask_sh), \
+       TF_SF(CNVC_CFG0_PRE_CSC_C33_C34, PRE_CSC_C33, mask_sh), \
+       TF_SF(CNVC_CFG0_PRE_CSC_C33_C34, PRE_CSC_C34, mask_sh), \
+       TF_SF(CM0_CM_POST_CSC_CONTROL, CM_POST_CSC_MODE, mask_sh), \
+       TF_SF(CM0_CM_POST_CSC_CONTROL, CM_POST_CSC_MODE_CURRENT, mask_sh), \
+       TF_SF(CM0_CM_POST_CSC_C11_C12, CM_POST_CSC_C11, mask_sh), \
+       TF_SF(CM0_CM_POST_CSC_C11_C12, CM_POST_CSC_C12, mask_sh), \
+       TF_SF(CM0_CM_POST_CSC_C33_C34, CM_POST_CSC_C33, mask_sh), \
+       TF_SF(CM0_CM_POST_CSC_C33_C34, CM_POST_CSC_C34, mask_sh), \
+       TF_SF(CM0_CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_INDEX, mask_sh), \
+       TF_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \
+       TF2_SF(CNVC_CFG0, FORMAT_CONTROL__ALPHA_EN, mask_sh), \
+       TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \
+       TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \
+       TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_ALPHA_PLANE_ENABLE, mask_sh), \
+       TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \
+       TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \
+       TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \
+       TF_SF(CM_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \
+       TF_SF(CM_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \
+       TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y, CUR0_FP_BIAS_G_Y, mask_sh), \
+       TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y, CUR0_FP_SCALE_G_Y, mask_sh), \
+       TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB, CUR0_FP_BIAS_RB_CRCB, mask_sh), \
+       TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB, CUR0_FP_SCALE_RB_CRCB, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_MODE, CUR0_MATRIX_MODE, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_MODE, CUR0_MATRIX_MODE_CURRENT, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_MODE, CUR0_MATRIX_COEF_FORMAT, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_C11_C12_A, CUR0_MATRIX_C11_A, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_C11_C12_A, CUR0_MATRIX_C12_A, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_C13_C14_A, CUR0_MATRIX_C13_A, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_C13_C14_A, CUR0_MATRIX_C14_A, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_C21_C22_A, CUR0_MATRIX_C21_A, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_C21_C22_A, CUR0_MATRIX_C22_A, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_C23_C24_A, CUR0_MATRIX_C23_A, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_C23_C24_A, CUR0_MATRIX_C24_A, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_C31_C32_A, CUR0_MATRIX_C31_A, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_C31_C32_A, CUR0_MATRIX_C32_A, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_C33_C34_A, CUR0_MATRIX_C33_A, mask_sh), \
+       TF_SF(CM_CUR0_CUR0_MATRIX_C33_C34_A, CUR0_MATRIX_C34_A, mask_sh), \
+       TF_SF(DPP_TOP0_DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \
+       TF_SF(CM0_CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, mask_sh), \
+       TF_SF(CM0_CM_CONTROL, CM_BYPASS, mask_sh), \
+       TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SEL, mask_sh), \
+       TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH_EN, mask_sh), \
+       TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SRC1_SEL, mask_sh), \
+       TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SRC2_SEL, mask_sh), \
+       TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SRC3_SEL, mask_sh), \
+       TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH1_XBAR, mask_sh), \
+       TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH2_XBAR, mask_sh), \
+       TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH3_XBAR, mask_sh), \
+       TF_SF(CM0_CM_HIST_CNTL, CM_HIST_FORMAT, mask_sh), \
+       TF_SF(CM0_CM_HIST_CNTL, CM_HIST_READ_CHANNEL_MASK, mask_sh), \
+       TF_SF(CM0_CM_HIST_LOCK, CM_HIST_LOCK, mask_sh), \
+       TF_SF(CM0_CM_HIST_INDEX, CM_HIST_INDEX, mask_sh), \
+       TF_SF(CM0_CM_HIST_DATA, CM_HIST_DATA, mask_sh), \
+       TF_SF(CM0_CM_HIST_DATA, CM_HIST_DATA, mask_sh), \
+       TF_SF(CM0_CM_HIST_STATUS, CM_HIST_BUFA_RDY_STATUS, mask_sh), \
+       TF_SF(CM0_CM_HIST_STATUS, CM_HIST_BUFB_RDY_STATUS, mask_sh), \
+       TF_SF(CM0_CM_HIST_SCALE_SRC1, CM_HIST_SCALE_SRC1, mask_sh), \
+       TF_SF(CM0_CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, mask_sh), \
+       TF_SF(CM0_CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, mask_sh), \
+       TF_SF(CM0_CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, mask_sh), \
+       TF_SF(CM0_CM_HIST_SCALE_SRC3, CM_HIST_SCALE_SRC3, mask_sh), \
+       TF_SF(CM0_CM_HIST_BIAS_SRC1, CM_HIST_BIAS_SRC1, mask_sh), \
+       TF_SF(CM0_CM_HIST_BIAS_SRC2, CM_HIST_BIAS_SRC2, mask_sh), \
+       TF_SF(CM0_CM_HIST_BIAS_SRC3, CM_HIST_BIAS_SRC3, mask_sh), \
+       TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \
+       TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \
+       TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \
+       TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \
+       TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CNV16, mask_sh), \
+       TF_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS_MSB_ALIGN, mask_sh), \
+       TF_SF(CNVC_CFG0_FORMAT_CONTROL, CLAMP_POSITIVE, mask_sh), \
+       TF_SF(CNVC_CFG0_FORMAT_CONTROL, CLAMP_POSITIVE_C, mask_sh), \
+       TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_R, mask_sh), \
+       TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_G, mask_sh), \
+       TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_B, mask_sh), \
+       TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT0, mask_sh), \
+       TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT1, mask_sh), \
+       TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT2, mask_sh), \
+       TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT3, mask_sh), \
+       TF_SF(CNVC_CFG0_FCNV_FP_BIAS_R, FCNV_FP_BIAS_R, mask_sh), \
+       TF_SF(CNVC_CFG0_FCNV_FP_BIAS_G, FCNV_FP_BIAS_G, mask_sh), \
+       TF_SF(CNVC_CFG0_FCNV_FP_BIAS_B, FCNV_FP_BIAS_B, mask_sh), \
+       TF_SF(CNVC_CFG0_FCNV_FP_SCALE_R, FCNV_FP_SCALE_R, mask_sh), \
+       TF_SF(CNVC_CFG0_FCNV_FP_SCALE_G, FCNV_FP_SCALE_G, mask_sh), \
+       TF_SF(CNVC_CFG0_FCNV_FP_SCALE_B, FCNV_FP_SCALE_B, mask_sh), \
+       TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, COLOR_KEYER_EN, mask_sh), \
+       TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, LUMA_KEYER_EN, mask_sh), \
+       TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, COLOR_KEYER_MODE, mask_sh), \
+       TF_SF(CNVC_CFG0_COLOR_KEYER_ALPHA, COLOR_KEYER_ALPHA_LOW, mask_sh), \
+       TF_SF(CNVC_CFG0_COLOR_KEYER_ALPHA, COLOR_KEYER_ALPHA_HIGH, mask_sh), \
+       TF_SF(CNVC_CFG0_COLOR_KEYER_RED, COLOR_KEYER_RED_LOW, mask_sh), \
+       TF_SF(CNVC_CFG0_COLOR_KEYER_RED, COLOR_KEYER_RED_HIGH, mask_sh), \
+       TF_SF(CNVC_CFG0_COLOR_KEYER_GREEN, COLOR_KEYER_GREEN_LOW, mask_sh), \
+       TF_SF(CNVC_CFG0_COLOR_KEYER_GREEN, COLOR_KEYER_GREEN_HIGH, mask_sh), \
+       TF_SF(CNVC_CFG0_COLOR_KEYER_BLUE, COLOR_KEYER_BLUE_LOW, mask_sh), \
+       TF_SF(CNVC_CFG0_COLOR_KEYER_BLUE, COLOR_KEYER_BLUE_HIGH, mask_sh), \
+       TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_PIX_INV_MODE, mask_sh), \
+       TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_PIXEL_ALPHA_MOD_EN, mask_sh), \
+       TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_ROM_EN, mask_sh),\
+       TF_SF(DSCL0_OBUF_MEM_PWR_CTRL, OBUF_MEM_PWR_FORCE, mask_sh),\
+       TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, mask_sh),\
+       TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_DIS, mask_sh),\
+       TF_SF(DSCL0_DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, mask_sh),\
+       TF_SF(DSCL0_DSCL_SC_MODE, SCL_SC_MATRIX_MODE, mask_sh),\
+       TF_SF(DSCL0_DSCL_SC_MODE, SCL_SC_LTONL_EN, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_MODE, SCL_EASF_H_EN, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_MODE, SCL_EASF_H_RINGEST_FORCE_EN, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_MODE, SCL_EASF_H_2TAP_SHARP_FACTOR, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF1_EN, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_MODE, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF3_MODE, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_FLAT1_GAIN, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_FLAT2_GAIN, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_ROC_GAIN, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_REDUCE, SCL_EASF_H_RINGEST_EVENTAP_REDUCEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_REDUCE, SCL_EASF_H_RINGEST_EVENTAP_REDUCEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_GAIN, SCL_EASF_H_RINGEST_EVENTAP_GAIN1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_GAIN, SCL_EASF_H_RINGEST_EVENTAP_GAIN2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MAXA, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MAXB, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MINA, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MINB, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG0, SCL_EASF_H_BF1_PWL_IN_SEG0, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG0, SCL_EASF_H_BF1_PWL_BASE_SEG0, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG0, SCL_EASF_H_BF1_PWL_SLOPE_SEG0, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG1, SCL_EASF_H_BF1_PWL_IN_SEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG1, SCL_EASF_H_BF1_PWL_BASE_SEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG1, SCL_EASF_H_BF1_PWL_SLOPE_SEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG2, SCL_EASF_H_BF1_PWL_IN_SEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG2, SCL_EASF_H_BF1_PWL_BASE_SEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG2, SCL_EASF_H_BF1_PWL_SLOPE_SEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG3, SCL_EASF_H_BF1_PWL_IN_SEG3, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG3, SCL_EASF_H_BF1_PWL_BASE_SEG3, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG3, SCL_EASF_H_BF1_PWL_SLOPE_SEG3, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG4, SCL_EASF_H_BF1_PWL_IN_SEG4, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG4, SCL_EASF_H_BF1_PWL_BASE_SEG4, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG4, SCL_EASF_H_BF1_PWL_SLOPE_SEG4, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG5, SCL_EASF_H_BF1_PWL_IN_SEG5, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG5, SCL_EASF_H_BF1_PWL_BASE_SEG5, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG5, SCL_EASF_H_BF1_PWL_SLOPE_SEG5, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG6, SCL_EASF_H_BF1_PWL_IN_SEG6, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG6, SCL_EASF_H_BF1_PWL_BASE_SEG6, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG6, SCL_EASF_H_BF1_PWL_SLOPE_SEG6, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG7, SCL_EASF_H_BF1_PWL_IN_SEG7, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG7, SCL_EASF_H_BF1_PWL_BASE_SEG7, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG0, SCL_EASF_H_BF3_PWL_IN_SEG0, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG0, SCL_EASF_H_BF3_PWL_BASE_SEG0, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG0, SCL_EASF_H_BF3_PWL_SLOPE_SEG0, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG1, SCL_EASF_H_BF3_PWL_IN_SEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG1, SCL_EASF_H_BF3_PWL_BASE_SEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG1, SCL_EASF_H_BF3_PWL_SLOPE_SEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG2, SCL_EASF_H_BF3_PWL_IN_SEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG2, SCL_EASF_H_BF3_PWL_BASE_SEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG2, SCL_EASF_H_BF3_PWL_SLOPE_SEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG3, SCL_EASF_H_BF3_PWL_IN_SEG3, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG3, SCL_EASF_H_BF3_PWL_BASE_SEG3, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG3, SCL_EASF_H_BF3_PWL_SLOPE_SEG3, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG4, SCL_EASF_H_BF3_PWL_IN_SEG4, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG4, SCL_EASF_H_BF3_PWL_BASE_SEG4, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG4, SCL_EASF_H_BF3_PWL_SLOPE_SEG4, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG5, SCL_EASF_H_BF3_PWL_IN_SEG5, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG5, SCL_EASF_H_BF3_PWL_BASE_SEG5, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_MODE, SCL_EASF_V_EN, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_MODE, SCL_EASF_V_RINGEST_FORCE_EN, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_MODE, SCL_EASF_V_2TAP_SHARP_FACTOR, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF1_EN, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_MODE, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF3_MODE, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_FLAT1_GAIN, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_FLAT2_GAIN, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_ROC_GAIN, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL1, SCL_EASF_V_RINGEST_3TAP_DNTILT_UPTILT, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL1, SCL_EASF_V_RINGEST_3TAP_UPTILT_MAXVAL, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL2, SCL_EASF_V_RINGEST_3TAP_DNTILT_SLOPE, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL2, SCL_EASF_V_RINGEST_3TAP_UPTILT1_SLOPE, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL3, SCL_EASF_V_RINGEST_3TAP_UPTILT2_SLOPE, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL3, SCL_EASF_V_RINGEST_3TAP_UPTILT2_OFFSET, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_REDUCE, SCL_EASF_V_RINGEST_EVENTAP_REDUCEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_REDUCE, SCL_EASF_V_RINGEST_EVENTAP_REDUCEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_GAIN, SCL_EASF_V_RINGEST_EVENTAP_GAIN1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_GAIN, SCL_EASF_V_RINGEST_EVENTAP_GAIN2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MAXA, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MAXB, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MINA, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MINB, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG0, SCL_EASF_V_BF1_PWL_IN_SEG0, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG0, SCL_EASF_V_BF1_PWL_BASE_SEG0, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG0, SCL_EASF_V_BF1_PWL_SLOPE_SEG0, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG1, SCL_EASF_V_BF1_PWL_IN_SEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG1, SCL_EASF_V_BF1_PWL_BASE_SEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG1, SCL_EASF_V_BF1_PWL_SLOPE_SEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG2, SCL_EASF_V_BF1_PWL_IN_SEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG2, SCL_EASF_V_BF1_PWL_BASE_SEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG2, SCL_EASF_V_BF1_PWL_SLOPE_SEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG3, SCL_EASF_V_BF1_PWL_IN_SEG3, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG3, SCL_EASF_V_BF1_PWL_BASE_SEG3, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG3, SCL_EASF_V_BF1_PWL_SLOPE_SEG3, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG4, SCL_EASF_V_BF1_PWL_IN_SEG4, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG4, SCL_EASF_V_BF1_PWL_BASE_SEG4, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG4, SCL_EASF_V_BF1_PWL_SLOPE_SEG4, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG5, SCL_EASF_V_BF1_PWL_IN_SEG5, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG5, SCL_EASF_V_BF1_PWL_BASE_SEG5, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG5, SCL_EASF_V_BF1_PWL_SLOPE_SEG5, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG6, SCL_EASF_V_BF1_PWL_IN_SEG6, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG6, SCL_EASF_V_BF1_PWL_BASE_SEG6, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG6, SCL_EASF_V_BF1_PWL_SLOPE_SEG6, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG7, SCL_EASF_V_BF1_PWL_IN_SEG7, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG7, SCL_EASF_V_BF1_PWL_BASE_SEG7, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG0, SCL_EASF_V_BF3_PWL_IN_SEG0, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG0, SCL_EASF_V_BF3_PWL_BASE_SEG0, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG0, SCL_EASF_V_BF3_PWL_SLOPE_SEG0, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG1, SCL_EASF_V_BF3_PWL_IN_SEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG1, SCL_EASF_V_BF3_PWL_BASE_SEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG1, SCL_EASF_V_BF3_PWL_SLOPE_SEG1, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG2, SCL_EASF_V_BF3_PWL_IN_SEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG2, SCL_EASF_V_BF3_PWL_BASE_SEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG2, SCL_EASF_V_BF3_PWL_SLOPE_SEG2, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG3, SCL_EASF_V_BF3_PWL_IN_SEG3, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG3, SCL_EASF_V_BF3_PWL_BASE_SEG3, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG3, SCL_EASF_V_BF3_PWL_SLOPE_SEG3, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG4, SCL_EASF_V_BF3_PWL_IN_SEG4, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG4, SCL_EASF_V_BF3_PWL_BASE_SEG4, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG4, SCL_EASF_V_BF3_PWL_SLOPE_SEG4, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG5, SCL_EASF_V_BF3_PWL_IN_SEG5, mask_sh),\
+       TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG5, SCL_EASF_V_BF3_PWL_BASE_SEG5, mask_sh),\
+       TF_SF(DSCL0_DSCL_SC_MATRIX_C0C1, SCL_SC_MATRIX_C0, mask_sh),\
+       TF_SF(DSCL0_DSCL_SC_MATRIX_C0C1, SCL_SC_MATRIX_C1, mask_sh),\
+       TF_SF(DSCL0_DSCL_SC_MATRIX_C2C3, SCL_SC_MATRIX_C2, mask_sh),\
+       TF_SF(DSCL0_DSCL_SC_MATRIX_C2C3, SCL_SC_MATRIX_C3, mask_sh),\
+       TF_SF(DSCL0_ISHARP_DELTA_CTRL, ISHARP_DELTA_LUT_HOST_SELECT, mask_sh),\
+       TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_DIS, mask_sh),\
+       TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_FORCE, mask_sh),\
+       TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_STATE, mask_sh),\
+       TF_SF(DSCL0_ISHARP_DELTA_DATA, ISHARP_DELTA_DATA, mask_sh),\
+       TF_SF(DSCL0_ISHARP_DELTA_INDEX, ISHARP_DELTA_INDEX, mask_sh),\
+       TF_SF(DSCL0_ISHARP_MODE, ISHARP_EN, mask_sh),\
+       TF_SF(DSCL0_ISHARP_MODE, ISHARP_NOISEDET_EN, mask_sh),\
+       TF_SF(DSCL0_ISHARP_MODE, ISHARP_NOISEDET_MODE, mask_sh),\
+       TF_SF(DSCL0_ISHARP_MODE, ISHARP_LBA_MODE, mask_sh),\
+       TF_SF(DSCL0_ISHARP_MODE, ISHARP_DELTA_LUT_SELECT, mask_sh),\
+       TF_SF(DSCL0_ISHARP_MODE, ISHARP_FMT_MODE, mask_sh),\
+       TF_SF(DSCL0_ISHARP_MODE, ISHARP_FMT_NORM, mask_sh),\
+       TF_SF(DSCL0_ISHARP_MODE, ISHARP_DELTA_LUT_SELECT_CURRENT, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG0, ISHARP_LBA_PWL_IN_SEG0, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG0, ISHARP_LBA_PWL_BASE_SEG0, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG0, ISHARP_LBA_PWL_SLOPE_SEG0, mask_sh), \
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG1, ISHARP_LBA_PWL_IN_SEG1, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG1, ISHARP_LBA_PWL_BASE_SEG1, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG1, ISHARP_LBA_PWL_SLOPE_SEG1, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG2, ISHARP_LBA_PWL_IN_SEG2, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG2, ISHARP_LBA_PWL_BASE_SEG2, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG2, ISHARP_LBA_PWL_SLOPE_SEG2, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG3, ISHARP_LBA_PWL_IN_SEG3, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG3, ISHARP_LBA_PWL_BASE_SEG3, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG3, ISHARP_LBA_PWL_SLOPE_SEG3, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG4, ISHARP_LBA_PWL_IN_SEG4, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG4, ISHARP_LBA_PWL_BASE_SEG4, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG4, ISHARP_LBA_PWL_SLOPE_SEG4, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG5, ISHARP_LBA_PWL_IN_SEG5, mask_sh),\
+       TF_SF(DSCL0_ISHARP_LBA_PWL_SEG5, ISHARP_LBA_PWL_BASE_SEG5, mask_sh),\
+       TF_SF(DSCL0_ISHARP_NOISEDET_THRESHOLD, ISHARP_NOISEDET_UTHRE, mask_sh),\
+       TF_SF(DSCL0_ISHARP_NOISEDET_THRESHOLD, ISHARP_NOISEDET_DTHRE, mask_sh), \
+       TF_SF(DSCL0_ISHARP_NOISE_GAIN_PWL, ISHARP_NOISEDET_PWL_START_IN, mask_sh), \
+       TF_SF(DSCL0_ISHARP_NOISE_GAIN_PWL, ISHARP_NOISEDET_PWL_END_IN, mask_sh), \
+       TF_SF(DSCL0_ISHARP_NOISE_GAIN_PWL, ISHARP_NOISEDET_PWL_SLOPE, mask_sh), \
+       TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_EN_P, mask_sh), \
+       TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_PIVOT_P, mask_sh), \
+       TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_SLOPE_P, mask_sh), \
+       TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_EN_N, mask_sh), \
+       TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_PIVOT_N, mask_sh), \
+       TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_SLOPE_N, mask_sh), \
+       TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_FRAC_BOT, mask_sh),\
+       TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_INT_BOT, mask_sh),\
+       TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_FRAC_BOT_C, mask_sh),\
+       TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh)
+
+#define DPP_REG_FIELD_LIST_DCN42(type) \
+       DPP_REG_FIELD_LIST_DCN401(type); \
+       type CM_HIST_SEL; \
+       type CM_HIST_CH_EN; \
+       type CM_HIST_SRC1_SEL; \
+       type CM_HIST_SRC2_SEL; \
+       type CM_HIST_SRC3_SEL; \
+       type CM_HIST_CH1_XBAR; \
+       type CM_HIST_CH2_XBAR; \
+       type CM_HIST_CH3_XBAR; \
+       type CM_HIST_FORMAT; \
+       type CM_HIST_READ_CHANNEL_MASK; \
+       type CM_HIST_LOCK; \
+       type CM_HIST_INDEX; \
+       type CM_HIST_DATA; \
+       type CM_HIST_BUFA_RDY_STATUS; \
+       type CM_HIST_BUFB_RDY_STATUS; \
+       type CM_HIST_SCALE_SRC1; \
+       type CM_HIST_COEFA_SRC2; \
+       type CM_HIST_COEFB_SRC2; \
+       type CM_HIST_COEFC_SRC2; \
+       type CM_HIST_SCALE_SRC3; \
+       type CM_HIST_BIAS_SRC1;  \
+       type CM_HIST_BIAS_SRC2;  \
+       type CM_HIST_BIAS_SRC3
+
+
+#define DPP_REG_VARIABLE_LIST_DCN42 \
+       DPP_REG_VARIABLE_LIST_DCN401; \
+       uint32_t ALPHA_2BIT_LUT01; \
+       uint32_t ALPHA_2BIT_LUT23; \
+       uint32_t CM_HIST_CNTL; \
+       uint32_t CM_HIST_INDEX; \
+       uint32_t CM_HIST_LOCK; \
+       uint32_t CM_HIST_DATA; \
+       uint32_t CM_HIST_STATUS; \
+       uint32_t CM_HIST_SCALE_SRC1; \
+       uint32_t CM_HIST_COEFA_SRC2; \
+       uint32_t CM_HIST_COEFB_SRC2; \
+       uint32_t CM_HIST_COEFC_SRC2; \
+       uint32_t CM_HIST_SCALE_SRC3; \
+       uint32_t CM_HIST_BIAS_SRC1;  \
+       uint32_t CM_HIST_BIAS_SRC2;  \
+       uint32_t CM_HIST_BIAS_SRC3
+
+struct dcn42_dpp_registers {
+       DPP_REG_VARIABLE_LIST_DCN42;
+};
+
+struct dcn42_dpp_shift {
+       DPP_REG_FIELD_LIST_DCN42(uint8_t);
+};
+
+struct dcn42_dpp_mask {
+       DPP_REG_FIELD_LIST_DCN42(uint32_t);
+};
+struct dcn42_dpp {
+       struct dpp base;
+       const struct dcn42_dpp_registers *tf_regs;
+       const struct dcn42_dpp_shift *tf_shift;
+       const struct dcn42_dpp_mask *tf_mask;
+       const uint16_t *filter_v;
+       const uint16_t *filter_h;
+       const uint16_t *filter_v_c;
+       const uint16_t *filter_h_c;
+       int lb_pixel_depth_supported;
+       int lb_memory_size;
+       int lb_bits_per_entry;
+       bool is_write_to_ram_a_safe;
+       struct scaler_data scl_data;
+       struct pwl_params pwl_data;
+};
+
+bool dpp42_construct(struct dcn42_dpp *dpp42,
+       struct dc_context *ctx,
+       uint32_t inst,
+       const struct dcn42_dpp_registers *tf_regs,
+       const struct dcn42_dpp_shift *tf_shift,
+       const struct dcn42_dpp_mask *tf_mask);
+
+
+#endif /* __DCN42_DPP_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.c
new file mode 100644 (file)
index 0000000..7d2090c
--- /dev/null
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+#include "../hw_factory.h"
+
+
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+#include "../hw_hpd.h"
+#include "../hw_generic.h"
+
+
+
+#include "dcn/dcn_4_2_0_offset.h"
+#include "dcn/dcn_4_2_0_sh_mask.h"
+#include "dpcs/dpcs_4_0_0_offset.h"
+#include "dpcs/dpcs_4_0_0_sh_mask.h"
+
+#include "reg_helper.h"
+#include "../hpd_regs.h"
+#include "hw_factory_dcn42.h"
+
+#define DCN_BASE__INST0_SEG2                       0x000034C0
+
+/* begin *********************
+ * macros to expend register list macro defined in HW object header file */
+
+/* DCN */
+#define block HPD
+#define reg_num 0
+
+#undef BASE_INNER
+#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
+
+#define BASE(seg) BASE_INNER(seg)
+
+
+
+#define REG(reg_name)\
+               (BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name)
+
+#define SF_HPD(reg_name, field_name, post_fix)\
+       .field_name = HPD0_ ## reg_name ## __ ## field_name ## post_fix
+
+#define REGI(reg_name, block, id)\
+       (BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
+                               reg ## block ## id ## _ ## reg_name)
+
+#define SF(reg_name, field_name, post_fix)\
+       .field_name = reg_name ## __ ## field_name ## post_fix
+
+/* macros to expend register list macro defined in HW object header file
+ * end *********************/
+
+// DC_GPIO_HPD_* registers are gone.
+#undef HPD_REG_LIST
+#define HPD_REG_LIST(id) \
+       .int_status = REGI(DC_HPD_INT_STATUS, HPD, id),\
+       .toggle_filt_cntl = REGI(DC_HPD_TOGGLE_FILT_CNTL, HPD, id)
+
+#define hpd_regs(id) \
+{\
+       HPD_REG_LIST(id)\
+}
+
+static const struct hpd_registers hpd_regs[] = {
+       hpd_regs(0),
+       hpd_regs(1),
+       hpd_regs(2),
+       hpd_regs(3),
+       hpd_regs(4),
+};
+
+static const struct hpd_sh_mask hpd_shift = {
+               HPD_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct hpd_sh_mask hpd_mask = {
+               HPD_MASK_SH_LIST(_MASK)
+};
+
+#include "../ddc_regs.h"
+
+ /* set field name */
+#define SF_DDC(reg_name, field_name, post_fix)\
+       .field_name = reg_name ## __ ## field_name ## post_fix
+
+static const struct ddc_registers ddc_data_regs_dcn[] = {
+       ddc_data_regs_dcn2(1),
+       ddc_data_regs_dcn2(2),
+       ddc_data_regs_dcn2(3),
+       ddc_data_regs_dcn2(4),
+       ddc_data_regs_dcn2(5),
+       {
+               // add a dummy entry for cases no such port
+               {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+               .ddc_setup = 0,
+               .phy_aux_cntl = 0,
+               .dc_gpio_aux_ctrl_5 = 0
+       },
+       {
+                       DDC_GPIO_VGA_REG_LIST(DATA),
+                       .ddc_setup = 0,
+                       .phy_aux_cntl = 0,
+                       .dc_gpio_aux_ctrl_5 = 0
+       }
+};
+
+static const struct ddc_registers ddc_clk_regs_dcn[] = {
+       ddc_clk_regs_dcn2(1),
+       ddc_clk_regs_dcn2(2),
+       ddc_clk_regs_dcn2(3),
+       ddc_clk_regs_dcn2(4),
+       ddc_clk_regs_dcn2(5),
+       {
+               // add a dummy entry for cases no such port
+               {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+               .ddc_setup = 0,
+               .phy_aux_cntl = 0,
+               .dc_gpio_aux_ctrl_5 = 0
+       },
+       {
+                       DDC_GPIO_VGA_REG_LIST(CLK),
+                       .ddc_setup = 0,
+                       .phy_aux_cntl = 0,
+                       .dc_gpio_aux_ctrl_5 = 0
+       }
+};
+
+static const struct ddc_sh_mask ddc_shift[] = {
+       DDC_MASK_SH_LIST_DCN2(__SHIFT, 1),
+       DDC_MASK_SH_LIST_DCN2(__SHIFT, 2),
+       DDC_MASK_SH_LIST_DCN2(__SHIFT, 3),
+       DDC_MASK_SH_LIST_DCN2(__SHIFT, 4),
+       DDC_MASK_SH_LIST_DCN2(__SHIFT, 5),
+       DDC_MASK_SH_LIST_DCN2(__SHIFT, 6),
+       DDC_MASK_SH_LIST_DCN2_VGA(__SHIFT)
+};
+
+static const struct ddc_sh_mask ddc_mask[] = {
+       DDC_MASK_SH_LIST_DCN2(_MASK, 1),
+       DDC_MASK_SH_LIST_DCN2(_MASK, 2),
+       DDC_MASK_SH_LIST_DCN2(_MASK, 3),
+       DDC_MASK_SH_LIST_DCN2(_MASK, 4),
+       DDC_MASK_SH_LIST_DCN2(_MASK, 5),
+       DDC_MASK_SH_LIST_DCN2(_MASK, 6),
+       DDC_MASK_SH_LIST_DCN2_VGA(_MASK)
+};
+
+#include "../generic_regs.h"
+
+/* set field name */
+#define SF_GENERIC(reg_name, field_name, post_fix)\
+       .field_name = 0
+
+static const struct generic_registers generic_regs[] = {
+       {{ 0 }},
+       {{ 0 }},
+};
+
+static const struct generic_sh_mask generic_shift[] = {
+       { 0 },
+       { 0 },
+};
+
+static const struct generic_sh_mask generic_mask[] = {
+       { 0 },
+       { 0 },
+};
+
+static void define_generic_registers(struct hw_gpio_pin *pin, uint32_t en)
+{
+       struct hw_generic *generic = HW_GENERIC_FROM_BASE(pin);
+
+       generic->regs = &generic_regs[en];
+       generic->shifts = &generic_shift[en];
+       generic->masks = &generic_mask[en];
+       generic->base.regs = &generic_regs[en].gpio;
+}
+
+static void define_ddc_registers(
+               struct hw_gpio_pin *pin,
+               uint32_t en)
+{
+       struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin);
+
+       switch (pin->id) {
+       case GPIO_ID_DDC_DATA:
+               ddc->regs = &ddc_data_regs_dcn[en];
+               ddc->base.regs = &ddc_data_regs_dcn[en].gpio;
+               break;
+       case GPIO_ID_DDC_CLOCK:
+               ddc->regs = &ddc_clk_regs_dcn[en];
+               ddc->base.regs = &ddc_clk_regs_dcn[en].gpio;
+               break;
+       default:
+               ASSERT_CRITICAL(false);
+               return;
+       }
+
+       ddc->shifts = &ddc_shift[en];
+       ddc->masks = &ddc_mask[en];
+
+}
+
+static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en)
+{
+       struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin);
+
+       hpd->regs = &hpd_regs[en];
+       hpd->shifts = &hpd_shift;
+       hpd->masks = &hpd_mask;
+       hpd->base.regs = &hpd_regs[en].gpio;
+}
+
+
+/* function table */
+static const struct hw_factory_funcs funcs = {
+       .init_ddc_data = dal_hw_ddc_init,
+       .init_generic = dal_hw_generic_init,
+       .init_hpd = dal_hw_hpd_init,
+       .get_ddc_pin = dal_hw_ddc_get_pin,
+       .get_hpd_pin = dal_hw_hpd_get_pin,
+       .get_generic_pin = dal_hw_generic_get_pin,
+       .define_hpd_registers = define_hpd_registers,
+       .define_ddc_registers = define_ddc_registers,
+       .define_generic_registers = define_generic_registers
+};
+
+/*
+ * dal_hw_factory_dcn42_init
+ *
+ * @brief
+ * Initialize HW factory function pointers and pin info
+ *
+ * @param
+ * struct hw_factory *factory - [out] struct of function pointers
+ */
+void dal_hw_factory_dcn42_init(struct hw_factory *factory)
+{
+       factory->number_of_pins[GPIO_ID_DDC_DATA] = 8;
+       factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8;
+       factory->number_of_pins[GPIO_ID_GENERIC] = 4;
+       factory->number_of_pins[GPIO_ID_HPD] = 5;
+       factory->number_of_pins[GPIO_ID_GPIO_PAD] = 28;
+       factory->number_of_pins[GPIO_ID_VIP_PAD] = 0;
+       factory->number_of_pins[GPIO_ID_SYNC] = 0;
+       factory->number_of_pins[GPIO_ID_GSL] = 0;/*add this*/
+
+       factory->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.h b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.h
new file mode 100644 (file)
index 0000000..b723380
--- /dev/null
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 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.
+ *
+ */
+
+#ifndef __DAL_HW_FACTORY_DCN42_H__
+#define __DAL_HW_FACTORY_DCN42_H__
+
+/* Initialize HW factory function pointers and pin info */
+void dal_hw_factory_dcn42_init(struct hw_factory *factory);
+
+#endif /* __DAL_HW_FACTORY_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c
new file mode 100644 (file)
index 0000000..dcbcf6b
--- /dev/null
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "hw_translate_dcn42.h"
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+#include "../hw_translate.h"
+
+
+#include "dcn/dcn_4_2_0_offset.h"
+#include "dcn/dcn_4_2_0_sh_mask.h"
+#include "dpcs/dpcs_4_0_0_offset.h"
+#include "dpcs/dpcs_4_0_0_sh_mask.h"
+
+#define DCN_BASE__INST0_SEG2                       0x000034C0
+
+/* begin *********************
+ * macros to expend register list macro defined in HW object header file */
+
+/* DCN */
+#define block HPD
+#define reg_num 0
+
+#undef BASE_INNER
+#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
+
+#define BASE(seg) BASE_INNER(seg)
+
+#undef REG
+#define REG(reg_name)\
+               (BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name)
+#define SF_HPD(reg_name, field_name, post_fix)\
+       .field_name = reg_name ## __ ## field_name ## post_fix
+
+
+/* macros to expend register list macro defined in HW object header file
+ * end *********************/
+
+
+static bool offset_to_id(
+       uint32_t offset,
+       uint32_t mask,
+       enum gpio_id *id,
+       uint32_t *en)
+{
+       switch (offset) {
+       /* HPD */
+       case REG(HPD0_DC_HPD_INT_STATUS):
+               *id = GPIO_ID_HPD;
+               *en = GPIO_HPD_1;
+               return true;
+       case REG(HPD1_DC_HPD_INT_STATUS):
+               *id = GPIO_ID_HPD;
+               *en = GPIO_HPD_2;
+               return true;
+       case REG(HPD2_DC_HPD_INT_STATUS):
+               *id = GPIO_ID_HPD;
+               *en = GPIO_HPD_3;
+               return true;
+       case REG(HPD3_DC_HPD_INT_STATUS):
+               *id = GPIO_ID_HPD;
+               *en = GPIO_HPD_4;
+               return true;
+       case REG(HPD4_DC_HPD_INT_STATUS):
+               *id = GPIO_ID_HPD;
+               *en = GPIO_HPD_5;
+               return true;
+       /* DDC */
+       /* we don't care about the GPIO_ID for DDC
+        * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK
+        * directly in the create method
+        */
+       case REG(DC_GPIO_DDC1_A):
+               *en = GPIO_DDC_LINE_DDC1;
+               return true;
+       case REG(DC_GPIO_DDC2_A):
+               *en = GPIO_DDC_LINE_DDC2;
+               return true;
+       case REG(DC_GPIO_DDC3_A):
+               *en = GPIO_DDC_LINE_DDC3;
+               return true;
+       case REG(DC_GPIO_DDC4_A):
+               *en = GPIO_DDC_LINE_DDC4;
+               return true;
+       case REG(DC_GPIO_DDC5_A):
+               *en = GPIO_DDC_LINE_DDC5;
+               return true;
+       case REG(DC_GPIO_DDCVGA_A):
+               *en = GPIO_DDC_LINE_DDC_VGA;
+               return true;
+       default:
+               ASSERT_CRITICAL(false);
+               return false;
+       }
+}
+
+
+static bool id_to_offset(
+       enum gpio_id id,
+       uint32_t en,
+       struct gpio_pin_info *info)
+{
+       bool result = true;
+
+       switch (id) {
+       case GPIO_ID_DDC_DATA:
+               info->mask = DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK;
+               switch (en) {
+               case GPIO_DDC_LINE_DDC1:
+                       info->offset = REG(DC_GPIO_DDC1_A);
+               break;
+               case GPIO_DDC_LINE_DDC2:
+                       info->offset = REG(DC_GPIO_DDC2_A);
+               break;
+               case GPIO_DDC_LINE_DDC3:
+                       info->offset = REG(DC_GPIO_DDC3_A);
+               break;
+               case GPIO_DDC_LINE_DDC4:
+                       info->offset = REG(DC_GPIO_DDC4_A);
+               break;
+               case GPIO_DDC_LINE_DDC5:
+                       info->offset = REG(DC_GPIO_DDC5_A);
+               break;
+               case GPIO_DDC_LINE_DDC_VGA:
+                       info->offset = REG(DC_GPIO_DDCVGA_A);
+               break;
+               case GPIO_DDC_LINE_I2C_PAD:
+               default:
+                       ASSERT_CRITICAL(false);
+                       result = false;
+               }
+       break;
+       case GPIO_ID_DDC_CLOCK:
+               info->mask = DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A_MASK;
+               switch (en) {
+               case GPIO_DDC_LINE_DDC1:
+                       info->offset = REG(DC_GPIO_DDC1_A);
+               break;
+               case GPIO_DDC_LINE_DDC2:
+                       info->offset = REG(DC_GPIO_DDC2_A);
+               break;
+               case GPIO_DDC_LINE_DDC3:
+                       info->offset = REG(DC_GPIO_DDC3_A);
+               break;
+               case GPIO_DDC_LINE_DDC4:
+                       info->offset = REG(DC_GPIO_DDC4_A);
+               break;
+               case GPIO_DDC_LINE_DDC5:
+                       info->offset = REG(DC_GPIO_DDC5_A);
+               break;
+               case GPIO_DDC_LINE_DDC_VGA:
+                       info->offset = REG(DC_GPIO_DDCVGA_A);
+               break;
+               case GPIO_DDC_LINE_I2C_PAD:
+               default:
+                       ASSERT_CRITICAL(false);
+                       result = false;
+               }
+       break;
+       case GPIO_ID_SYNC:
+       case GPIO_ID_VIP_PAD:
+       default:
+               ASSERT_CRITICAL(false);
+               result = false;
+       }
+
+       if (result) {
+               info->offset_y = info->offset + 2;
+               info->offset_en = info->offset + 1;
+               info->offset_mask = info->offset - 1;
+
+               info->mask_y = info->mask;
+               info->mask_en = info->mask;
+               info->mask_mask = info->mask;
+       }
+
+       return result;
+}
+
+
+/* function table */
+static const struct hw_translate_funcs funcs = {
+       .offset_to_id = offset_to_id,
+       .id_to_offset = id_to_offset,
+};
+
+
+/*
+ * dal_hw_translate_dcn42_init
+ *
+ * @brief
+ * Initialize Hw translate function pointers.
+ *
+ * @param
+ * struct hw_translate *tr - [out] struct of function pointers
+ *
+ */
+void dal_hw_translate_dcn42_init(struct hw_translate *tr)
+{
+       tr->funcs = &funcs;
+}
+
+
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.h b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.h
new file mode 100644 (file)
index 0000000..007b4d5
--- /dev/null
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 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.
+ *
+ */
+
+#ifndef __DAL_HW_TRANSLATE_DCN42_H__
+#define __DAL_HW_TRANSLATE_DCN42_H__
+
+struct hw_translate;
+
+/* Initialize Hw translate function pointers */
+void dal_hw_translate_dcn42_init(struct hw_translate *tr);
+#ifdef DAL_EMULATION_SUPPORTED
+void dal_emulated_hw_translate_dcn42_init(struct hw_translate *tr);
+#endif
+
+#endif /* __DAL_HW_TRANSLATE_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.c
new file mode 100644 (file)
index 0000000..4b86b1b
--- /dev/null
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dc_bios_types.h"
+#include "dcn31/dcn31_hpo_dp_link_encoder.h"
+#include "dcn32/dcn32_hpo_dp_link_encoder.h"
+#include "dcn42_hpo_dp_link_encoder.h"
+#include "reg_helper.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
+
+
+static void dcn42_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_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]);
+}
+
+static struct hpo_dp_link_encoder_funcs dcn42_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 = dcn32_hpo_dp_link_enc_is_in_alt_mode,
+       .read_state = dcn42_hpo_dp_link_enc_read_state,
+       .set_ffe = dcn31_hpo_dp_link_enc_set_ffe,
+};
+
+void hpo_dp_link_encoder42_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 = &dcn42_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/hpo/dcn42/dcn42_hpo_dp_link_encoder.h b/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.h
new file mode 100644 (file)
index 0000000..3e84d01
--- /dev/null
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2026 Advanced Micro Devices, Inc. */
+
+
+#ifndef __DAL_DCN42_HPO_DP_LINK_ENCODER_H__
+#define __DAL_DCN42_HPO_DP_LINK_ENCODER_H__
+
+#include "link_encoder.h"
+
+void hpo_dp_link_encoder42_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);
+
+#endif   // __DAL_DCN32_HPO_DP_LINK_ENCODER_H__
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c
new file mode 100644 (file)
index 0000000..d6e6fba
--- /dev/null
@@ -0,0 +1,539 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dcn30/dcn30_hubbub.h"
+#include "dcn31/dcn31_hubbub.h"
+#include "dcn32/dcn32_hubbub.h"
+#include "dcn35/dcn35_hubbub.h"
+#include "dcn42/dcn42_hubbub.h"
+#include "dm_services.h"
+#include "reg_helper.h"
+
+#define DCN42_CRB_SEGMENT_SIZE_KB 64
+
+#define CTX \
+       hubbub2->base.ctx
+#define DC_LOGGER \
+       hubbub2->base.ctx->logger
+#define REG(reg)\
+       hubbub2->regs->reg
+
+#undef FN
+#define FN(reg_name, field_name) \
+       hubbub2->shifts->field_name, hubbub2->masks->field_name
+
+static bool hubbub42_program_urgent_watermarks(
+               struct hubbub *hubbub,
+               union dcn_watermark_set *watermarks,
+               bool safe_to_lower)
+{
+       struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+       bool wm_pending = false;
+
+       /* Repeat for water mark set A, B, C and D. */
+       /* clock state A */
+       if (safe_to_lower || watermarks->dcn4x.a.urgent > hubbub2->watermarks.dcn4x.a.urgent) {
+               hubbub2->watermarks.dcn4x.a.urgent = watermarks->dcn4x.a.urgent;
+               REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,
+                               DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, watermarks->dcn4x.a.urgent);
+       } else if (watermarks->dcn4x.a.urgent < hubbub2->watermarks.dcn4x.a.urgent)
+               wm_pending = true;
+
+       /* determine the transfer time for a quantity of data for a particular requestor.*/
+       if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip) {
+               hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip = watermarks->dcn4x.a.frac_urg_bw_flip;
+               REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0,
+                               DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->dcn4x.a.frac_urg_bw_flip);
+       } else if (watermarks->dcn4x.a.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom) {
+               hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom = watermarks->dcn4x.a.frac_urg_bw_nom;
+               REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0,
+                               DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->dcn4x.a.frac_urg_bw_nom);
+       } else if (watermarks->dcn4x.a.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.a.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem) {
+               hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem = watermarks->dcn4x.a.refcyc_per_trip_to_mem;
+               REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0,
+                               DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, watermarks->dcn4x.a.refcyc_per_trip_to_mem);
+       } else if (watermarks->dcn4x.a.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem)
+               wm_pending = true;
+
+       /* clock state B */
+       if (safe_to_lower || watermarks->dcn4x.b.urgent > hubbub2->watermarks.dcn4x.b.urgent) {
+               hubbub2->watermarks.dcn4x.b.urgent = watermarks->dcn4x.b.urgent;
+               REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0,
+                               DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, watermarks->dcn4x.b.urgent);
+       } else if (watermarks->dcn4x.b.urgent < hubbub2->watermarks.dcn4x.b.urgent)
+               wm_pending = true;
+
+       /* determine the transfer time for a quantity of data for a particular requestor.*/
+       if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip) {
+               hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip = watermarks->dcn4x.b.frac_urg_bw_flip;
+               REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0,
+                               DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->dcn4x.b.frac_urg_bw_flip);
+       } else if (watermarks->dcn4x.b.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom) {
+               hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom = watermarks->dcn4x.b.frac_urg_bw_nom;
+               REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0,
+                               DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->dcn4x.b.frac_urg_bw_nom);
+       } else if (watermarks->dcn4x.b.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.b.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem) {
+               hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem = watermarks->dcn4x.b.refcyc_per_trip_to_mem;
+               REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0,
+                               DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, watermarks->dcn4x.b.refcyc_per_trip_to_mem);
+       } else if (watermarks->dcn4x.b.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem)
+               wm_pending = true;
+
+       /* clock state C */
+       if (safe_to_lower || watermarks->dcn4x.c.urgent > hubbub2->watermarks.dcn4x.c.urgent) {
+               hubbub2->watermarks.dcn4x.c.urgent = watermarks->dcn4x.c.urgent;
+               REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0,
+                               DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, watermarks->dcn4x.c.urgent);
+       } else if (watermarks->dcn4x.c.urgent < hubbub2->watermarks.dcn4x.c.urgent)
+               wm_pending = true;
+
+       /* determine the transfer time for a quantity of data for a particular requestor.*/
+       if (safe_to_lower || watermarks->dcn4x.c.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip) {
+               hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip = watermarks->dcn4x.c.frac_urg_bw_flip;
+               REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0,
+                               DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->dcn4x.c.frac_urg_bw_flip);
+       } else if (watermarks->dcn4x.c.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.c.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom) {
+               hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom = watermarks->dcn4x.c.frac_urg_bw_nom;
+               REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0,
+                               DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->dcn4x.c.frac_urg_bw_nom);
+       } else if (watermarks->dcn4x.c.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.c.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem) {
+               hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem = watermarks->dcn4x.c.refcyc_per_trip_to_mem;
+               REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0,
+                               DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, watermarks->dcn4x.c.refcyc_per_trip_to_mem);
+       } else if (watermarks->dcn4x.c.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem)
+               wm_pending = true;
+
+       /* clock state D */
+       if (safe_to_lower || watermarks->dcn4x.d.urgent > hubbub2->watermarks.dcn4x.d.urgent) {
+               hubbub2->watermarks.dcn4x.d.urgent = watermarks->dcn4x.d.urgent;
+               REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0,
+                               DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, watermarks->dcn4x.d.urgent);
+       } else if (watermarks->dcn4x.d.urgent < hubbub2->watermarks.dcn4x.d.urgent)
+               wm_pending = true;
+
+       /* determine the transfer time for a quantity of data for a particular requestor.*/
+       if (safe_to_lower || watermarks->dcn4x.d.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip) {
+               hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip = watermarks->dcn4x.d.frac_urg_bw_flip;
+               REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0,
+                               DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->dcn4x.d.frac_urg_bw_flip);
+       } else if (watermarks->dcn4x.d.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.d.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom) {
+               hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom = watermarks->dcn4x.d.frac_urg_bw_nom;
+               REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0,
+                               DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->dcn4x.d.frac_urg_bw_nom);
+       } else if (watermarks->dcn4x.d.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.d.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem) {
+               hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem = watermarks->dcn4x.d.refcyc_per_trip_to_mem;
+               REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0,
+                               DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, watermarks->dcn4x.d.refcyc_per_trip_to_mem);
+       } else if (watermarks->dcn4x.d.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem)
+               wm_pending = true;
+
+       return wm_pending;
+}
+
+static bool hubbub42_program_stutter_watermarks(
+               struct hubbub *hubbub,
+               union dcn_watermark_set *watermarks,
+               bool safe_to_lower)
+{
+       struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+       bool wm_pending = false;
+
+       /* clock state A */
+       if (safe_to_lower || watermarks->dcn4x.a.sr_enter > hubbub2->watermarks.dcn4x.a.sr_enter) {
+               hubbub2->watermarks.dcn4x.a.sr_enter =  watermarks->dcn4x.a.sr_enter;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, watermarks->dcn4x.a.sr_enter);
+       } else if (watermarks->dcn4x.a.sr_enter < hubbub2->watermarks.dcn4x.a.sr_enter)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.a.sr_exit > hubbub2->watermarks.dcn4x.a.sr_exit) {
+               hubbub2->watermarks.dcn4x.a.sr_exit = watermarks->dcn4x.a.sr_exit;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, watermarks->dcn4x.a.sr_exit);
+       } else if (watermarks->dcn4x.a.sr_exit < hubbub2->watermarks.dcn4x.a.sr_exit)
+               wm_pending = true;
+
+       /* clock state B */
+       if (safe_to_lower || watermarks->dcn4x.b.sr_enter > hubbub2->watermarks.dcn4x.b.sr_enter) {
+               hubbub2->watermarks.dcn4x.b.sr_enter =  watermarks->dcn4x.b.sr_enter;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, watermarks->dcn4x.b.sr_enter);
+       } else if (watermarks->dcn4x.b.sr_enter < hubbub2->watermarks.dcn4x.b.sr_enter)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.b.sr_exit > hubbub2->watermarks.dcn4x.b.sr_exit) {
+               hubbub2->watermarks.dcn4x.b.sr_exit = watermarks->dcn4x.b.sr_exit;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, watermarks->dcn4x.b.sr_exit);
+       } else if (watermarks->dcn4x.b.sr_exit < hubbub2->watermarks.dcn4x.b.sr_exit)
+               wm_pending = true;
+
+       /* clock state C */
+       if (safe_to_lower || watermarks->dcn4x.c.sr_enter > hubbub2->watermarks.dcn4x.c.sr_enter) {
+               hubbub2->watermarks.dcn4x.c.sr_enter =  watermarks->dcn4x.c.sr_enter;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, watermarks->dcn4x.c.sr_enter);
+       } else if (watermarks->dcn4x.c.sr_enter < hubbub2->watermarks.dcn4x.c.sr_enter)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.c.sr_exit > hubbub2->watermarks.dcn4x.c.sr_exit) {
+               hubbub2->watermarks.dcn4x.c.sr_exit = watermarks->dcn4x.c.sr_exit;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, watermarks->dcn4x.c.sr_exit);
+       } else if (watermarks->dcn4x.c.sr_exit < hubbub2->watermarks.dcn4x.c.sr_exit)
+               wm_pending = true;
+
+       /* clock state D */
+       if (safe_to_lower || watermarks->dcn4x.d.sr_enter > hubbub2->watermarks.dcn4x.d.sr_enter) {
+               hubbub2->watermarks.dcn4x.d.sr_enter =  watermarks->dcn4x.d.sr_enter;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, watermarks->dcn4x.d.sr_enter);
+       } else if (watermarks->dcn4x.d.sr_enter < hubbub2->watermarks.dcn4x.d.sr_enter)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.d.sr_exit > hubbub2->watermarks.dcn4x.d.sr_exit) {
+               hubbub2->watermarks.dcn4x.d.sr_exit = watermarks->dcn4x.d.sr_exit;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, watermarks->dcn4x.d.sr_exit);
+       } else if (watermarks->dcn4x.d.sr_exit < hubbub2->watermarks.dcn4x.d.sr_exit)
+               wm_pending = true;
+
+       return wm_pending;
+}
+
+static bool hubbub42_program_pstate_watermarks(
+               struct hubbub *hubbub,
+               union dcn_watermark_set *watermarks,
+               bool safe_to_lower)
+{
+       struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+       bool wm_pending = false;
+
+       /* Section for UCLK_PSTATE_CHANGE_WATERMARKS */
+       /* UCLK state A */
+       if (safe_to_lower || watermarks->dcn4x.a.uclk_pstate > hubbub2->watermarks.dcn4x.a.uclk_pstate) {
+               hubbub2->watermarks.dcn4x.a.uclk_pstate = watermarks->dcn4x.a.uclk_pstate;
+               REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, 0,
+                               DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.uclk_pstate);
+       } else if (watermarks->dcn4x.a.uclk_pstate < hubbub2->watermarks.dcn4x.a.uclk_pstate)
+               wm_pending = true;
+
+       /* UCLK state B */
+       if (safe_to_lower || watermarks->dcn4x.b.uclk_pstate > hubbub2->watermarks.dcn4x.b.uclk_pstate) {
+               hubbub2->watermarks.dcn4x.b.uclk_pstate = watermarks->dcn4x.b.uclk_pstate;
+               REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, 0,
+                               DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.uclk_pstate);
+       } else if (watermarks->dcn4x.b.uclk_pstate < hubbub2->watermarks.dcn4x.b.uclk_pstate)
+               wm_pending = true;
+
+       /* UCLK state C */
+       if (safe_to_lower || watermarks->dcn4x.c.uclk_pstate > hubbub2->watermarks.dcn4x.c.uclk_pstate) {
+               hubbub2->watermarks.dcn4x.c.uclk_pstate = watermarks->dcn4x.c.uclk_pstate;
+               REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, 0,
+                               DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, watermarks->dcn4x.c.uclk_pstate);
+       } else if (watermarks->dcn4x.c.uclk_pstate < hubbub2->watermarks.dcn4x.c.uclk_pstate)
+               wm_pending = true;
+
+       /* UCLK state D */
+       if (safe_to_lower || watermarks->dcn4x.d.uclk_pstate > hubbub2->watermarks.dcn4x.d.uclk_pstate) {
+               hubbub2->watermarks.dcn4x.d.uclk_pstate = watermarks->dcn4x.d.uclk_pstate;
+               REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, 0,
+                               DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, watermarks->dcn4x.d.uclk_pstate);
+       } else if (watermarks->dcn4x.d.uclk_pstate < hubbub2->watermarks.dcn4x.d.uclk_pstate)
+               wm_pending = true;
+
+       /* Section for FCLK_PSTATE_CHANGE_WATERMARKS */
+       /* FCLK state A */
+       if (safe_to_lower || watermarks->dcn4x.a.fclk_pstate > hubbub2->watermarks.dcn4x.a.fclk_pstate) {
+               hubbub2->watermarks.dcn4x.a.fclk_pstate = watermarks->dcn4x.a.fclk_pstate;
+               REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, 0,
+                               DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.fclk_pstate);
+       } else if (watermarks->dcn4x.a.fclk_pstate < hubbub2->watermarks.dcn4x.a.fclk_pstate)
+               wm_pending = true;
+
+       /* FCLK state B */
+       if (safe_to_lower || watermarks->dcn4x.b.fclk_pstate > hubbub2->watermarks.dcn4x.b.fclk_pstate) {
+               hubbub2->watermarks.dcn4x.b.fclk_pstate = watermarks->dcn4x.b.fclk_pstate;
+               REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, 0,
+                               DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.fclk_pstate);
+       } else if (watermarks->dcn4x.b.fclk_pstate < hubbub2->watermarks.dcn4x.b.fclk_pstate)
+               wm_pending = true;
+
+       /* FCLK state C */
+       if (safe_to_lower || watermarks->dcn4x.c.fclk_pstate > hubbub2->watermarks.dcn4x.c.fclk_pstate) {
+               hubbub2->watermarks.dcn4x.c.fclk_pstate = watermarks->dcn4x.c.fclk_pstate;
+               REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, 0,
+                               DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, watermarks->dcn4x.c.fclk_pstate);
+       } else if (watermarks->dcn4x.c.fclk_pstate < hubbub2->watermarks.dcn4x.c.fclk_pstate)
+               wm_pending = true;
+
+       /* FCLK state D */
+       if (safe_to_lower || watermarks->dcn4x.d.fclk_pstate > hubbub2->watermarks.dcn4x.d.fclk_pstate) {
+               hubbub2->watermarks.dcn4x.d.fclk_pstate = watermarks->dcn4x.d.fclk_pstate;
+               REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, 0,
+                               DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, watermarks->dcn4x.d.fclk_pstate);
+       } else if (watermarks->dcn4x.d.fclk_pstate < hubbub2->watermarks.dcn4x.d.fclk_pstate)
+               wm_pending = true;
+
+       return wm_pending;
+}
+
+static bool hubbub42_program_usr_watermarks(
+               struct hubbub *hubbub,
+               union dcn_watermark_set *watermarks,
+               bool safe_to_lower)
+{
+       struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+       bool wm_pending = false;
+
+       /* clock state A */
+       if (safe_to_lower || watermarks->dcn4x.a.usr > hubbub2->watermarks.dcn4x.a.usr) {
+               hubbub2->watermarks.dcn4x.a.usr = watermarks->dcn4x.a.usr;
+               REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, 0,
+                               DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, watermarks->dcn4x.a.usr);
+       } else if (watermarks->dcn4x.a.usr < hubbub2->watermarks.dcn4x.a.usr)
+               wm_pending = true;
+
+       /* clock state B */
+       if (safe_to_lower || watermarks->dcn4x.b.usr > hubbub2->watermarks.dcn4x.b.usr) {
+               hubbub2->watermarks.dcn4x.b.usr = watermarks->dcn4x.b.usr;
+               REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, 0,
+                               DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, watermarks->dcn4x.b.usr);
+       } else if (watermarks->dcn4x.b.usr < hubbub2->watermarks.dcn4x.b.usr)
+               wm_pending = true;
+
+       /* clock state C */
+       if (safe_to_lower || watermarks->dcn4x.c.usr > hubbub2->watermarks.dcn4x.c.usr) {
+               hubbub2->watermarks.dcn4x.c.usr = watermarks->dcn4x.c.usr;
+               REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, 0,
+                               DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, watermarks->dcn4x.c.usr);
+       } else if (watermarks->dcn4x.c.usr < hubbub2->watermarks.dcn4x.c.usr)
+               wm_pending = true;
+
+       /* clock state D */
+       if (safe_to_lower || watermarks->dcn4x.d.usr > hubbub2->watermarks.dcn4x.d.usr) {
+               hubbub2->watermarks.dcn4x.d.usr = watermarks->dcn4x.d.usr;
+               REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, 0,
+                               DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, watermarks->dcn4x.d.usr);
+       } else if (watermarks->dcn4x.d.usr < hubbub2->watermarks.dcn4x.d.usr)
+               wm_pending = true;
+
+       return wm_pending;
+}
+
+static bool hubbub42_program_stutter_z8_watermarks(
+               struct hubbub *hubbub,
+               union dcn_watermark_set *watermarks,
+               bool safe_to_lower)
+{
+       struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+       bool wm_pending = false;
+
+       /* clock state A */
+       if (safe_to_lower || watermarks->dcn4x.a.sr_enter_z8 > hubbub2->watermarks.dcn4x.a.sr_enter_z8) {
+               hubbub2->watermarks.dcn4x.a.sr_enter_z8 = watermarks->dcn4x.a.sr_enter_z8;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, watermarks->dcn4x.a.sr_enter_z8);
+       } else if (watermarks->dcn4x.a.sr_enter_z8 < hubbub2->watermarks.dcn4x.a.sr_enter_z8)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.a.sr_exit_z8 > hubbub2->watermarks.dcn4x.a.sr_exit_z8) {
+               hubbub2->watermarks.dcn4x.a.sr_exit_z8 = watermarks->dcn4x.a.sr_exit_z8;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, watermarks->dcn4x.a.sr_exit_z8);
+       } else if (watermarks->dcn4x.a.sr_exit_z8 < hubbub2->watermarks.dcn4x.a.sr_exit_z8)
+               wm_pending = true;
+
+       /* clock state B */
+       if (safe_to_lower || watermarks->dcn4x.b.sr_enter_z8 > hubbub2->watermarks.dcn4x.b.sr_enter_z8) {
+               hubbub2->watermarks.dcn4x.b.sr_enter_z8 = watermarks->dcn4x.b.sr_enter_z8;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, watermarks->dcn4x.b.sr_enter_z8);
+       } else if (watermarks->dcn4x.b.sr_enter_z8 < hubbub2->watermarks.dcn4x.b.sr_enter_z8)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.b.sr_exit_z8 > hubbub2->watermarks.dcn4x.b.sr_exit_z8) {
+               hubbub2->watermarks.dcn4x.b.sr_exit_z8 = watermarks->dcn4x.b.sr_exit_z8;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, watermarks->dcn4x.b.sr_exit_z8);
+       } else if (watermarks->dcn4x.b.sr_exit_z8 < hubbub2->watermarks.dcn4x.b.sr_exit_z8)
+               wm_pending = true;
+
+       /* clock state C */
+       if (safe_to_lower || watermarks->dcn4x.c.sr_enter_z8 > hubbub2->watermarks.dcn4x.c.sr_enter_z8) {
+               hubbub2->watermarks.dcn4x.c.sr_enter_z8 = watermarks->dcn4x.c.sr_enter_z8;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, watermarks->dcn4x.c.sr_enter_z8);
+       } else if (watermarks->dcn4x.c.sr_enter_z8 < hubbub2->watermarks.dcn4x.c.sr_enter_z8)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.c.sr_exit_z8 > hubbub2->watermarks.dcn4x.c.sr_exit_z8) {
+               hubbub2->watermarks.dcn4x.c.sr_exit_z8 = watermarks->dcn4x.c.sr_exit_z8;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, watermarks->dcn4x.c.sr_exit_z8);
+       } else if (watermarks->dcn4x.c.sr_exit_z8 < hubbub2->watermarks.dcn4x.c.sr_exit_z8)
+               wm_pending = true;
+
+       /* clock state D */
+       if (safe_to_lower || watermarks->dcn4x.d.sr_enter_z8 > hubbub2->watermarks.dcn4x.d.sr_enter_z8) {
+               hubbub2->watermarks.dcn4x.d.sr_enter_z8 = watermarks->dcn4x.d.sr_enter_z8;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, watermarks->dcn4x.d.sr_enter_z8);
+       } else if (watermarks->dcn4x.d.sr_enter_z8 < hubbub2->watermarks.dcn4x.d.sr_enter_z8)
+               wm_pending = true;
+
+       if (safe_to_lower || watermarks->dcn4x.d.sr_exit_z8 > hubbub2->watermarks.dcn4x.d.sr_exit_z8) {
+               hubbub2->watermarks.dcn4x.d.sr_exit_z8 = watermarks->dcn4x.d.sr_exit_z8;
+               REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 0,
+                               DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, watermarks->dcn4x.d.sr_exit_z8);
+       } else if (watermarks->dcn4x.d.sr_exit_z8 < hubbub2->watermarks.dcn4x.d.sr_exit_z8)
+               wm_pending = true;
+
+       return wm_pending;
+}
+
+static void hubbub42_allow_self_refresh_control(struct hubbub *hubbub, bool allow)
+{
+       struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+       /*
+        * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 1 means do not allow stutter
+        * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 means allow stutter
+        */
+
+       REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
+                       DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0,
+                       DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, !allow);
+
+       if (!allow && hubbub->ctx->dc->debug.disable_stutter) {/*controlled by registry key*/
+               REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
+                       DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_VALUE, 0,
+                       DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_ENABLE, 1);
+               REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
+                       DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, 0,
+                       DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, 1);
+       }
+}
+static void hubbub42_set_sdp_control(struct hubbub *hubbub, bool dc_control)
+{
+       struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+       REG_UPDATE(DCHUBBUB_SDPIF_CFG0,
+                       SDPIF_PORT_CONTROL, dc_control);
+}
+
+static bool hubbub42_program_watermarks(
+               struct hubbub *hubbub,
+               union dcn_watermark_set *watermarks,
+               unsigned int refclk_mhz,
+               bool safe_to_lower)
+{
+       bool wm_pending = false;
+       struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+       if (!safe_to_lower && hubbub->ctx->dc->debug.disable_stutter_for_wm_program) {
+               /* before raising watermarks, SDP control give to DF, stutter must be disabled */
+               wm_pending = true;
+               hubbub42_set_sdp_control(hubbub, false);
+               hubbub42_allow_self_refresh_control(hubbub, false);
+       }
+       if (hubbub42_program_urgent_watermarks(hubbub, watermarks, safe_to_lower))
+               wm_pending = true;
+
+       if (hubbub42_program_stutter_watermarks(hubbub, watermarks, safe_to_lower))
+               wm_pending = true;
+
+       if (hubbub42_program_pstate_watermarks(hubbub, watermarks, safe_to_lower))
+               wm_pending = true;
+
+       if (hubbub42_program_usr_watermarks(hubbub, watermarks, safe_to_lower))
+               wm_pending = true;
+
+       if (hubbub42_program_stutter_z8_watermarks(hubbub, watermarks, safe_to_lower))
+               wm_pending = true;
+
+       REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,
+                       DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
+       REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
+                       DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0xFF,
+                       DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);/*hw delta*/
+       REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF);
+
+       if (safe_to_lower || hubbub->ctx->dc->debug.disable_stutter)
+               hubbub42_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
+       if (safe_to_lower && hubbub->ctx->dc->debug.disable_stutter_for_wm_program) {
+               hubbub42_set_sdp_control(hubbub, true);
+       }
+       hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow);
+
+       return wm_pending;
+}
+
+static const struct hubbub_funcs hubbub42_funcs = {
+       .update_dchub = hubbub2_update_dchub,
+       .init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx,
+       .init_vm_ctx = hubbub2_init_vm_ctx,
+       .dcc_support_swizzle = hubbub3_dcc_support_swizzle,
+       .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,
+       .get_dcc_compression_cap = hubbub3_get_dcc_compression_cap,
+       .wm_read_state = hubbub35_wm_read_state,
+       .get_dchub_ref_freq = hubbub35_get_dchub_ref_freq,
+       .program_watermarks = hubbub42_program_watermarks,
+       .allow_self_refresh_control = hubbub42_allow_self_refresh_control,
+       .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
+       .force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes,
+       .force_pstate_change_control = hubbub3_force_pstate_change_control,
+       .init_watermarks = hubbub35_init_watermarks,
+       .program_det_size = dcn32_program_det_size,
+       .program_compbuf_size = dcn35_program_compbuf_size,
+       .init_crb = dcn35_init_crb,
+       .hubbub_read_state = hubbub2_read_state,
+       .force_usr_retraining_allow = hubbub32_force_usr_retraining_allow,
+       .dchubbub_init = hubbub35_init,
+       .dchvm_init = dcn35_dchvm_init,
+};
+
+void hubbub42_construct(struct dcn20_hubbub *hubbub2,
+       struct dc_context *ctx,
+       const struct dcn_hubbub_registers *hubbub_regs,
+       const struct dcn_hubbub_shift *hubbub_shift,
+       const struct dcn_hubbub_mask *hubbub_mask,
+       int det_size_kb,
+       int pixel_chunk_size_kb,
+       int config_return_buffer_size_kb)
+{
+       hubbub2->base.ctx = ctx;
+       hubbub2->base.funcs = &hubbub42_funcs;
+       hubbub2->regs = hubbub_regs;
+       hubbub2->shifts = hubbub_shift;
+       hubbub2->masks = hubbub_mask;
+
+       hubbub2->detile_buf_size = det_size_kb * 1024;
+       hubbub2->pixel_chunk_size = pixel_chunk_size_kb * 1024;
+       hubbub2->crb_size_segs = config_return_buffer_size_kb / DCN42_CRB_SEGMENT_SIZE_KB;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.h
new file mode 100644 (file)
index 0000000..926ddc1
--- /dev/null
@@ -0,0 +1,268 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 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 __DC_HUBBUB_DCN42_H__
+#define __DC_HUBBUB_DCN42_H__
+
+#include "dcn32/dcn32_hubbub.h"
+
+#define DCN42_CRB_SIZE_KB 1792
+#define DCN42_DEFAULT_DET_SIZE 320
+#define DCN42_CRB_SEGMENT_SIZE_KB 64
+
+#define HUBBUB_REG_LIST_DCN42(id)\
+       SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\
+       SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\
+       SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\
+       SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\
+       SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\
+       SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\
+       SR(DCHUBBUB_ARB_SAT_LEVEL),\
+       SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\
+       SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \
+       SR(DCHUBBUB_SOFT_RESET),\
+       SR(DCHUBBUB_CRC_CTRL), \
+       SR(DCN_VM_FB_LOCATION_BASE),\
+       SR(DCN_VM_FB_LOCATION_TOP),\
+       SR(DCN_VM_FB_OFFSET),\
+       SR(DCN_VM_AGP_BOT),\
+       SR(DCN_VM_AGP_TOP),\
+       SR(DCN_VM_AGP_BASE),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\
+       SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A),\
+       SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B),\
+       SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C),\
+       SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D),\
+       SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A),\
+       SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B),\
+       SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C),\
+       SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D),\
+       SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A),\
+       SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B),\
+       SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C),\
+       SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D),\
+       SR(DCHUBBUB_DET0_CTRL),\
+       SR(DCHUBBUB_DET1_CTRL),\
+       SR(DCHUBBUB_DET2_CTRL),\
+       SR(DCHUBBUB_DET3_CTRL),\
+       SR(DCHUBBUB_COMPBUF_CTRL),\
+       SR(COMPBUF_RESERVED_SPACE),\
+       SR(DCHUBBUB_DEBUG_CTRL_0),\
+       SR(DCHUBBUB_ARB_USR_RETRAINING_CNTL),\
+       SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A),\
+       SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B),\
+       SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C),\
+       SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D),\
+       SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A),\
+       SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B),\
+       SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C),\
+       SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D),\
+       SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A),\
+       SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B),\
+       SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C),\
+       SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D),\
+       SR(DCN_VM_FAULT_ADDR_MSB),\
+       SR(DCN_VM_FAULT_ADDR_LSB),\
+       SR(DCN_VM_FAULT_CNTL),\
+       SR(DCN_VM_FAULT_STATUS),\
+       SR(SDPIF_REQUEST_RATE_LIMIT),\
+       SR(DCHUBBUB_CLOCK_CNTL),\
+       SR(DCHUBBUB_SDPIF_CFG0),\
+       SR(DCHUBBUB_SDPIF_CFG1),\
+       SR(DCHUBBUB_MEM_PWR_MODE_CTRL),\
+       SR(DCHUBBUB_ARB_HOSTVM_CNTL),\
+       SR(DCHVM_CTRL0),\
+       SR(DCHVM_MEM_CTRL),\
+       SR(DCHVM_CLK_CTRL),\
+       SR(DCHVM_RIOMMU_CTRL0),\
+       SR(DCHVM_RIOMMU_STAT0),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D),\
+       SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D),\
+       SR(DCHUBBUB_ARB_QOS_FORCE)
+
+#define HUBBUB_MASK_SH_LIST_DCN4_2(mask_sh)\
+       HUBBUB_MASK_SH_LIST_DCN32(mask_sh), \
+       HUBBUB_SF(DCHVM_CTRL0, HOSTVM_INIT_REQ, mask_sh),\
+       HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_PWR_REQ_DIS, mask_sh),\
+       HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_FORCE_REQ, mask_sh),\
+       HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_POWER_STATUS, mask_sh),\
+       HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DISPCLK_R_GATE_DIS, mask_sh),\
+       HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DISPCLK_G_GATE_DIS, mask_sh),\
+       HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DCFCLK_R_GATE_DIS, mask_sh),\
+       HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DCFCLK_G_GATE_DIS, mask_sh),\
+       HUBBUB_SF(DCHVM_CLK_CTRL, TR_REQ_REQCLKREQ_MODE, mask_sh),\
+       HUBBUB_SF(DCHVM_CLK_CTRL, TW_RSP_COMPCLKREQ_MODE, mask_sh),\
+       HUBBUB_SF(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, mask_sh),\
+       HUBBUB_SF(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, mask_sh),\
+       HUBBUB_SF(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, mask_sh),\
+       HUBBUB_SF(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, mask_sh),\
+       HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_64B, mask_sh),\
+       HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_ZS, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DCHUBBUB_FGCG_REP_DIS, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MAX_REQ_OUTSTAND, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_CSTATE_DEEPSLEEP_LEGACY_MODE, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_SOFT_RESET, DCHUBBUB_GLOBAL_SOFT_RESET, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_VALUE, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_ENABLE, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MAX_REQ_OUTSTAND, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \
+       HUBBUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FB_LOCATION_TOP, FB_TOP, mask_sh), \
+       HUBBUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET, mask_sh), \
+       HUBBUB_SF(DCN_VM_AGP_BOT, AGP_BOT, mask_sh), \
+       HUBBUB_SF(DCN_VM_AGP_TOP, AGP_TOP, mask_sh), \
+       HUBBUB_SF(DCN_VM_AGP_BASE, AGP_BASE, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_DEBUG_CTRL_0, DET_DEPTH, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_DET0_CTRL, DET0_SIZE, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_DET1_CTRL, DET1_SIZE, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_DET2_CTRL, DET2_SIZE, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_DET3_CTRL, DET3_SIZE, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, mask_sh),\
+       HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_64B, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_VALUE, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_ENABLE, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_DO_NOT_FORCE_ALLOW_USR_RETRAINING_DURING_PSTATE_CHANGE_REQUEST, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_DO_NOT_FORCE_ALLOW_USR_RETRAINING_DURING_PRE_CSTATE, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, mask_sh), \
+       HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_ADDR_MSB, DCN_VM_FAULT_ADDR_MSB, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_ADDR_LSB, DCN_VM_FAULT_ADDR_LSB, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_CLEAR, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_INTERRUPT_ENABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_RANGE_FAULT_DISABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_PRQ_FAULT_DISABLE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \
+       HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh),\
+       HUBBUB_SF(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DISPCLK_R_DCHUBBUB_GATE_DIS, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DCFCLK_R_DCHUBBUB_GATE_DIS, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_SDPIF_CFG0, SDPIF_PORT_CONTROL, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_SDPIF_CFG1, SDPIF_MAX_NUM_OUTSTANDING, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_MEM_PWR_MODE_CTRL, DET_MEM_PWR_LS_MODE, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_ERROR_STATUS, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_DETECTION_EN, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_TIMER_RESET, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_STATUS, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_CLEAR, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_CTRL_STATUS, URGENT_ZERO_SIZE_REQ_EN, mask_sh),\
+       HUBBUB_SF(DCHUBBUB_CTRL_STATUS, CSTATE_SWATH_CHK_GOOD_MODE, mask_sh)
+
+void hubbub42_construct(struct dcn20_hubbub *hubbub2,
+       struct dc_context *ctx,
+       const struct dcn_hubbub_registers *hubbub_regs,
+       const struct dcn_hubbub_shift *hubbub_shift,
+       const struct dcn_hubbub_mask *hubbub_mask,
+       int det_size_kb,
+       int pixel_chunk_size_kb,
+       int config_return_buffer_size_kb);
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c
new file mode 100644 (file)
index 0000000..07c38dc
--- /dev/null
@@ -0,0 +1,643 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dcn401/dcn401_hubp.h"
+#include "dcn42_hubp.h"
+#include "reg_helper.h"
+
+#define REG(reg) \
+       hubp2->hubp_regs->reg
+
+#define CTX \
+       hubp2->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+       hubp2->hubp_shift->field_name, hubp2->hubp_mask->field_name
+
+static void hubp42_set_fgcg(struct hubp *hubp, bool enable)
+{
+       struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+       REG_UPDATE(HUBP_CLK_CNTL, HUBP_FGCG_REP_DIS, !enable);
+}
+
+static void hubp42_init(struct hubp *hubp)
+{
+       hubp3_init(hubp);
+
+       hubp42_set_fgcg(hubp, hubp->ctx->dc->debug.enable_fine_grain_clock_gating.bits.dchub);
+
+       /*do nothing for now for dcn3.5 or later*/
+}
+
+static void hubp42_program_pixel_format(
+       struct hubp *hubp,
+       enum surface_pixel_format format)
+{
+       struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+       uint32_t green_bar = 1;
+       uint32_t red_bar = 3;
+       uint32_t blue_bar = 2;
+
+       /* swap for ABGR format */
+       if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888
+                       || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010
+                       || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS
+                       || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616
+                       || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
+               red_bar = 2;
+               blue_bar = 3;
+       }
+
+       REG_UPDATE_3(HUBPRET_CONTROL,
+                       CROSSBAR_SRC_Y_G, green_bar,
+                       CROSSBAR_SRC_CB_B, blue_bar,
+                       CROSSBAR_SRC_CR_R, red_bar);
+
+       /* Mapping is same as ipp programming (cnvc) */
+
+       switch (format) {
+       case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 1);
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 3);
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
+       case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 8);
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
+       case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
+       case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 10);
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
+       case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: /* we use crossbar already */
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 26); /* ARGB16161616_UNORM */
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
+       case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:/*we use crossbar already*/
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 24);
+               break;
+
+       case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 65);
+               break;
+       case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 64);
+               break;
+       case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 67);
+               break;
+       case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 66);
+               break;
+       case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 12);
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 112);
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 113);
+               break;
+       case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 114);
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 118);
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT:
+               REG_UPDATE(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 119);
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_RGBE:
+               REG_UPDATE_2(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 116,
+                               ALPHA_PLANE_EN, 0);
+               break;
+       case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
+               REG_UPDATE_2(DCSURF_SURFACE_CONFIG,
+                               SURFACE_PIXEL_FORMAT, 116,
+                               ALPHA_PLANE_EN, 1);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               break;
+       }
+
+       /* don't see the need of program the xbar in DCN 1.0 */
+}
+
+void hubp42_program_deadline(
+               struct hubp *hubp,
+               struct dml2_display_dlg_regs *dlg_attr,
+               struct dml2_display_ttu_regs *ttu_attr)
+{
+       struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+       /* DLG - Per hubp */
+       REG_SET_2(BLANK_OFFSET_0, 0,
+               REFCYC_H_BLANK_END, dlg_attr->refcyc_h_blank_end,
+               DLG_V_BLANK_END, dlg_attr->dlg_vblank_end);
+
+       REG_SET(BLANK_OFFSET_1, 0,
+               MIN_DST_Y_NEXT_START, dlg_attr->min_dst_y_next_start);
+
+       REG_SET(DST_DIMENSIONS, 0,
+               REFCYC_PER_HTOTAL, dlg_attr->refcyc_per_htotal);
+
+       REG_SET_2(DST_AFTER_SCALER, 0,
+               REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler,
+               DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler);
+
+       REG_SET(REF_FREQ_TO_PIX_FREQ, 0,
+               REF_FREQ_TO_PIX_FREQ, dlg_attr->ref_freq_to_pix_freq);
+
+       /* DLG - Per luma/chroma */
+       REG_SET(VBLANK_PARAMETERS_1, 0,
+               REFCYC_PER_PTE_GROUP_VBLANK_L, dlg_attr->refcyc_per_pte_group_vblank_l);
+
+       if (REG(NOM_PARAMETERS_0))
+               REG_SET(NOM_PARAMETERS_0, 0,
+                       DST_Y_PER_PTE_ROW_NOM_L, dlg_attr->dst_y_per_pte_row_nom_l);
+
+       if (REG(NOM_PARAMETERS_1))
+               REG_SET(NOM_PARAMETERS_1, 0,
+                       REFCYC_PER_PTE_GROUP_NOM_L, dlg_attr->refcyc_per_pte_group_nom_l);
+
+       REG_SET(NOM_PARAMETERS_4, 0,
+               DST_Y_PER_META_ROW_NOM_L, dlg_attr->dst_y_per_meta_row_nom_l);
+
+       REG_SET(NOM_PARAMETERS_5, 0,
+               REFCYC_PER_META_CHUNK_NOM_L, dlg_attr->refcyc_per_meta_chunk_nom_l);
+
+       REG_SET_2(PER_LINE_DELIVERY, 0,
+               REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l,
+               REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c);
+
+       REG_SET(VBLANK_PARAMETERS_2, 0,
+               REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c);
+
+       if (REG(NOM_PARAMETERS_2))
+               REG_SET(NOM_PARAMETERS_2, 0,
+                       DST_Y_PER_PTE_ROW_NOM_C, dlg_attr->dst_y_per_pte_row_nom_c);
+
+       if (REG(NOM_PARAMETERS_3))
+               REG_SET(NOM_PARAMETERS_3, 0,
+                       REFCYC_PER_PTE_GROUP_NOM_C, dlg_attr->refcyc_per_pte_group_nom_c);
+
+       REG_SET(NOM_PARAMETERS_6, 0,
+               DST_Y_PER_META_ROW_NOM_C, dlg_attr->dst_y_per_meta_row_nom_c);
+
+       REG_SET(NOM_PARAMETERS_7, 0,
+               REFCYC_PER_META_CHUNK_NOM_C, dlg_attr->refcyc_per_meta_chunk_nom_c);
+
+       /* TTU - per hubp */
+       REG_SET_2(DCN_TTU_QOS_WM, 0,
+               QoS_LEVEL_LOW_WM, ttu_attr->qos_level_low_wm,
+               QoS_LEVEL_HIGH_WM, ttu_attr->qos_level_high_wm);
+
+       /* TTU - per luma/chroma */
+       /* Assumed surf0 is luma and 1 is chroma */
+
+       REG_SET_3(DCN_SURF0_TTU_CNTL0, 0,
+               REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_l,
+               QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_l,
+               QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_l);
+
+       REG_SET_3(DCN_SURF1_TTU_CNTL0, 0,
+               REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_c,
+               QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_c,
+               QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_c);
+
+       REG_SET_3(DCN_CUR0_TTU_CNTL0, 0,
+               REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_cur0,
+               QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_cur0,
+               QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_cur0);
+
+       REG_SET(FLIP_PARAMETERS_1, 0,
+               REFCYC_PER_PTE_GROUP_FLIP_L, dlg_attr->refcyc_per_pte_group_flip_l);
+       REG_SET(HUBP_3DLUT_DLG_PARAM, 0, REFCYC_PER_3DLUT_GROUP, dlg_attr->refcyc_per_tdlut_group);
+
+       REG_UPDATE(DCN_DMDATA_VM_CNTL,
+                       REFCYC_PER_VM_DMDATA, dlg_attr->refcyc_per_vm_dmdata);
+}
+
+void hubp42_setup(
+               struct hubp *hubp,
+           struct dml2_dchub_per_pipe_register_set *pipe_regs,
+               union dml2_global_sync_programming *pipe_global_sync,
+               struct dc_crtc_timing *timing)
+{
+       /* otg is locked when this func is called. Register are double buffered.
+        * disable the requestors is not needed
+        */
+       hubp401_vready_at_or_After_vsync(hubp, pipe_global_sync, timing);
+       hubp401_program_requestor(hubp, &pipe_regs->rq_regs);
+       hubp42_program_deadline(hubp, &pipe_regs->dlg_regs, &pipe_regs->ttu_regs);
+}
+static void hubp42_program_surface_config(
+       struct hubp *hubp,
+       enum surface_pixel_format format,
+       struct dc_tiling_info *tiling_info,
+       struct plane_size *plane_size,
+       enum dc_rotation_angle rotation,
+       struct dc_plane_dcc_param *dcc,
+       bool horizontal_mirror,
+       unsigned int compat_level)
+{
+       struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+       hubp3_dcc_control_sienna_cichlid(hubp, dcc);
+       hubp3_program_tiling(hubp2, tiling_info, format);
+       hubp2_program_size(hubp, format, plane_size, dcc);
+       hubp2_program_rotation(hubp, rotation, horizontal_mirror);
+       hubp42_program_pixel_format(hubp, format);
+}
+
+void hubp42_program_3dlut_fl_crossbar(struct hubp *hubp,
+       enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_r,
+       enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_g,
+       enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_b)
+{
+       struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+       REG_UPDATE_3(HUBP_3DLUT_CONTROL,
+               HUBP_3DLUT_CROSSBAR_SEL_R, bit_slice_r,
+               HUBP_3DLUT_CROSSBAR_SEL_G, bit_slice_g,
+               HUBP_3DLUT_CROSSBAR_SEL_B, bit_slice_b);
+}
+
+static bool hubp42_program_surface_flip_and_addr(
+       struct hubp *hubp,
+       const struct dc_plane_address *address,
+       bool flip_immediate)
+{
+       struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+       //program flip type
+       REG_UPDATE(DCSURF_FLIP_CONTROL,
+                       SURFACE_FLIP_TYPE, flip_immediate);
+
+       // Program VMID reg
+       if (flip_immediate == 0)
+               REG_UPDATE(VMID_SETTINGS_0,
+                       VMID, address->vmid);
+
+       if (address->type == PLN_ADDR_TYPE_GRPH_STEREO) {
+               REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0);
+               REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x1);
+
+       } else {
+               // turn off stereo if not in stereo
+               REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0x0);
+               REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x0);
+       }
+
+       /* HW automatically latch rest of address register on write to
+        * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used
+        *
+        * program high first and then the low addr, order matters!
+        */
+       switch (address->type) {
+       case PLN_ADDR_TYPE_GRAPHICS:
+               /* DCN1.0 does not support const color
+                * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1
+                * base on address->grph.dcc_const_color
+                * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma
+                * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma
+                */
+
+               if (address->grph.addr.quad_part == 0)
+                       break;
+
+               REG_UPDATE_2(DCSURF_SURFACE_CONTROL,
+                               PRIMARY_SURFACE_TMZ, address->tmz_surface,
+                               PRIMARY_META_SURFACE_TMZ, address->tmz_surface);
+
+               if (address->grph.meta_addr.quad_part != 0) {
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0,
+                                       PRIMARY_META_SURFACE_ADDRESS_HIGH,
+                                       address->grph.meta_addr.high_part);
+
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0,
+                                       PRIMARY_META_SURFACE_ADDRESS,
+                                       address->grph.meta_addr.low_part);
+               }
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
+                               PRIMARY_SURFACE_ADDRESS_HIGH,
+                               address->grph.addr.high_part);
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0,
+                               PRIMARY_SURFACE_ADDRESS,
+                               address->grph.addr.low_part);
+               break;
+       case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
+               if (address->video_progressive.luma_addr.quad_part == 0
+                               || address->video_progressive.chroma_addr.quad_part == 0)
+                       break;
+
+               REG_UPDATE_4(DCSURF_SURFACE_CONTROL,
+                               PRIMARY_SURFACE_TMZ, address->tmz_surface,
+                               PRIMARY_SURFACE_TMZ_C, address->tmz_surface,
+                               PRIMARY_META_SURFACE_TMZ, address->tmz_surface,
+                               PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface);
+
+               if (address->video_progressive.luma_meta_addr.quad_part != 0) {
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0,
+                                       PRIMARY_META_SURFACE_ADDRESS_HIGH_C,
+                                       address->video_progressive.chroma_meta_addr.high_part);
+
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0,
+                                       PRIMARY_META_SURFACE_ADDRESS_C,
+                                       address->video_progressive.chroma_meta_addr.low_part);
+
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0,
+                                       PRIMARY_META_SURFACE_ADDRESS_HIGH,
+                                       address->video_progressive.luma_meta_addr.high_part);
+
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0,
+                                       PRIMARY_META_SURFACE_ADDRESS,
+                                       address->video_progressive.luma_meta_addr.low_part);
+               }
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0,
+                               PRIMARY_SURFACE_ADDRESS_HIGH_C,
+                               address->video_progressive.chroma_addr.high_part);
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0,
+                               PRIMARY_SURFACE_ADDRESS_C,
+                               address->video_progressive.chroma_addr.low_part);
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
+                               PRIMARY_SURFACE_ADDRESS_HIGH,
+                               address->video_progressive.luma_addr.high_part);
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0,
+                               PRIMARY_SURFACE_ADDRESS,
+                               address->video_progressive.luma_addr.low_part);
+               break;
+       case PLN_ADDR_TYPE_GRPH_STEREO:
+               if (address->grph_stereo.left_addr.quad_part == 0)
+                       break;
+               if (address->grph_stereo.right_addr.quad_part == 0)
+                       break;
+
+               REG_UPDATE_8(DCSURF_SURFACE_CONTROL,
+                               PRIMARY_SURFACE_TMZ, address->tmz_surface,
+                               PRIMARY_SURFACE_TMZ_C, address->tmz_surface,
+                               PRIMARY_META_SURFACE_TMZ, address->tmz_surface,
+                               PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface,
+                               SECONDARY_SURFACE_TMZ, address->tmz_surface,
+                               SECONDARY_SURFACE_TMZ_C, address->tmz_surface,
+                               SECONDARY_META_SURFACE_TMZ, address->tmz_surface,
+                               SECONDARY_META_SURFACE_TMZ_C, address->tmz_surface);
+
+               if (address->grph_stereo.right_meta_addr.quad_part != 0) {
+
+                       REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C, 0,
+                               SECONDARY_META_SURFACE_ADDRESS_HIGH_C,
+                               address->grph_stereo.right_alpha_meta_addr.high_part);
+
+                       REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_C, 0,
+                               SECONDARY_META_SURFACE_ADDRESS_C,
+                               address->grph_stereo.right_alpha_meta_addr.low_part);
+
+                       REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0,
+                                       SECONDARY_META_SURFACE_ADDRESS_HIGH,
+                                       address->grph_stereo.right_meta_addr.high_part);
+
+                       REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0,
+                                       SECONDARY_META_SURFACE_ADDRESS,
+                                       address->grph_stereo.right_meta_addr.low_part);
+               }
+               if (address->grph_stereo.left_meta_addr.quad_part != 0) {
+
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0,
+                               PRIMARY_META_SURFACE_ADDRESS_HIGH_C,
+                               address->grph_stereo.left_alpha_meta_addr.high_part);
+
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0,
+                               PRIMARY_META_SURFACE_ADDRESS_C,
+                               address->grph_stereo.left_alpha_meta_addr.low_part);
+
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0,
+                                       PRIMARY_META_SURFACE_ADDRESS_HIGH,
+                                       address->grph_stereo.left_meta_addr.high_part);
+
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0,
+                                       PRIMARY_META_SURFACE_ADDRESS,
+                                       address->grph_stereo.left_meta_addr.low_part);
+               }
+
+               REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH_C, 0,
+                               SECONDARY_SURFACE_ADDRESS_HIGH_C,
+                               address->grph_stereo.right_alpha_addr.high_part);
+
+               REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_C, 0,
+                               SECONDARY_SURFACE_ADDRESS_C,
+                               address->grph_stereo.right_alpha_addr.low_part);
+
+               REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0,
+                               SECONDARY_SURFACE_ADDRESS_HIGH,
+                               address->grph_stereo.right_addr.high_part);
+
+               REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0,
+                               SECONDARY_SURFACE_ADDRESS,
+                               address->grph_stereo.right_addr.low_part);
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0,
+                               PRIMARY_SURFACE_ADDRESS_HIGH_C,
+                               address->grph_stereo.left_alpha_addr.high_part);
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0,
+                               PRIMARY_SURFACE_ADDRESS_C,
+                               address->grph_stereo.left_alpha_addr.low_part);
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
+                               PRIMARY_SURFACE_ADDRESS_HIGH,
+                               address->grph_stereo.left_addr.high_part);
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0,
+                               PRIMARY_SURFACE_ADDRESS,
+                               address->grph_stereo.left_addr.low_part);
+               break;
+       case PLN_ADDR_TYPE_RGBEA:
+               if (address->rgbea.addr.quad_part == 0
+                               || address->rgbea.alpha_addr.quad_part == 0)
+                       break;
+
+               REG_UPDATE_4(DCSURF_SURFACE_CONTROL,
+                               PRIMARY_SURFACE_TMZ, address->tmz_surface,
+                               PRIMARY_SURFACE_TMZ_C, address->tmz_surface,
+                               PRIMARY_META_SURFACE_TMZ, address->tmz_surface,
+                               PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface);
+
+               if (address->rgbea.meta_addr.quad_part != 0) {
+
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0,
+                                       PRIMARY_META_SURFACE_ADDRESS_HIGH_C,
+                                       address->rgbea.alpha_meta_addr.high_part);
+
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0,
+                                       PRIMARY_META_SURFACE_ADDRESS_C,
+                                       address->rgbea.alpha_meta_addr.low_part);
+
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0,
+                                       PRIMARY_META_SURFACE_ADDRESS_HIGH,
+                                       address->rgbea.meta_addr.high_part);
+
+                       REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0,
+                                       PRIMARY_META_SURFACE_ADDRESS,
+                                       address->rgbea.meta_addr.low_part);
+               }
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0,
+                               PRIMARY_SURFACE_ADDRESS_HIGH_C,
+                               address->rgbea.alpha_addr.high_part);
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0,
+                               PRIMARY_SURFACE_ADDRESS_C,
+                               address->rgbea.alpha_addr.low_part);
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
+                               PRIMARY_SURFACE_ADDRESS_HIGH,
+                               address->rgbea.addr.high_part);
+
+               REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0,
+                               PRIMARY_SURFACE_ADDRESS,
+                               address->rgbea.addr.low_part);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               break;
+       }
+
+       hubp->request_address = *address;
+
+       return true;
+}
+
+struct hubp_funcs dcn42_hubp_funcs = {
+       .hubp_enable_tripleBuffer = hubp2_enable_triplebuffer,
+       .hubp_is_triplebuffer_enabled = hubp2_is_triplebuffer_enabled,
+       .hubp_program_surface_flip_and_addr = hubp42_program_surface_flip_and_addr,
+       .hubp_program_surface_config = hubp42_program_surface_config,
+       .hubp_is_flip_pending = hubp2_is_flip_pending,
+       .hubp_setup2 = hubp42_setup,
+       .hubp_setup_interdependent2 = hubp401_setup_interdependent,
+       .hubp_set_vm_system_aperture_settings = hubp3_set_vm_system_aperture_settings,
+       .set_blank = hubp2_set_blank,
+       .dcc_control = hubp3_dcc_control,
+       .hubp_reset = hubp_reset,
+       .mem_program_viewport = min_set_viewport,
+       .set_cursor_attributes  = hubp32_cursor_set_attributes,
+       .set_cursor_position    = hubp401_cursor_set_position,
+       .hubp_clk_cntl = hubp2_clk_cntl,
+       .hubp_vtg_sel = hubp2_vtg_sel,
+       .dmdata_set_attributes = hubp3_dmdata_set_attributes,
+       .dmdata_load = hubp2_dmdata_load,
+       .dmdata_status_done = hubp2_dmdata_status_done,
+       .hubp_read_state = hubp42_read_state,
+       .hubp_clear_underflow = hubp2_clear_underflow,
+       .hubp_set_flip_control_surface_gsl = hubp2_set_flip_control_surface_gsl,
+       .hubp_init = hubp42_init,
+       .set_unbounded_requesting = hubp31_set_unbounded_requesting,
+       .hubp_soft_reset = hubp31_soft_reset,
+       .hubp_set_flip_int = hubp1_set_flip_int,
+       .hubp_in_blank = hubp1_in_blank,
+       .program_extended_blank = hubp31_program_extended_blank_value,
+       .hubp_update_3dlut_fl_bias_scale = hubp401_update_3dlut_fl_bias_scale,
+       .hubp_program_3dlut_fl_mode = hubp401_program_3dlut_fl_mode,
+       .hubp_program_3dlut_fl_format = hubp401_program_3dlut_fl_format,
+       .hubp_program_3dlut_fl_addr = hubp401_program_3dlut_fl_addr,
+       .hubp_program_3dlut_fl_dlg_param = hubp401_program_3dlut_fl_dlg_param,
+       .hubp_enable_3dlut_fl = hubp401_enable_3dlut_fl,
+       .hubp_program_3dlut_fl_addressing_mode = hubp401_program_3dlut_fl_addressing_mode,
+       .hubp_program_3dlut_fl_width = hubp401_program_3dlut_fl_width,
+       .hubp_program_3dlut_fl_tmz_protected = hubp401_program_3dlut_fl_tmz_protected,
+       .hubp_program_3dlut_fl_crossbar = hubp42_program_3dlut_fl_crossbar,
+       .hubp_get_3dlut_fl_done = hubp401_get_3dlut_fl_done,
+       .hubp_program_3dlut_fl_config = hubp401_program_3dlut_fl_config,
+       .hubp_read_reg_state = hubp3_read_reg_state
+};
+
+bool hubp42_construct(
+       struct dcn20_hubp *hubp2,
+       struct dc_context *ctx,
+       uint32_t inst,
+       const struct dcn_hubp2_registers *hubp_regs,
+       const struct dcn_hubp2_shift *hubp_shift,
+       const struct dcn_hubp2_mask *hubp_mask)
+{
+       hubp2->base.funcs = &dcn42_hubp_funcs;
+       hubp2->base.ctx = ctx;
+       hubp2->hubp_regs = hubp_regs;
+       hubp2->hubp_shift = hubp_shift;
+       hubp2->hubp_mask = hubp_mask;
+       hubp2->base.inst = inst;
+       hubp2->base.opp_id = OPP_ID_INVALID;
+       hubp2->base.mpcc_id = 0xf;
+
+       return true;
+}
+
+
+void hubp42_read_state(struct hubp *hubp)
+{
+       struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+       struct dcn_hubp_state *s = &hubp2->state;
+       struct dcn_fl_regs_st *fl_regs = &s->fl_regs;
+
+       hubp401_read_state(hubp);
+
+       /* CONTROL */
+       REG_GET_5(HUBP_3DLUT_CONTROL,
+                       HUBP_3DLUT_ENABLE, &fl_regs->lut_enable,
+                       HUBP_3DLUT_DONE, &fl_regs->lut_done,
+                       HUBP_3DLUT_ADDRESSING_MODE, &fl_regs->lut_addr_mode,
+                       HUBP_3DLUT_WIDTH, &fl_regs->lut_width,
+                       HUBP_3DLUT_MPC_WIDTH, &fl_regs->lut_mpc_width);
+
+       REG_GET_4(HUBP_3DLUT_CONTROL,
+                       HUBP_3DLUT_TMZ, &fl_regs->lut_tmz,
+                       HUBP_3DLUT_CROSSBAR_SEL_R, &fl_regs->lut_crossbar_sel_r,
+                       HUBP_3DLUT_CROSSBAR_SEL_G, &fl_regs->lut_crossbar_sel_g,
+                       HUBP_3DLUT_CROSSBAR_SEL_B, &fl_regs->lut_crossbar_sel_b);
+
+       /* ADDR */
+       REG_GET(HUBP_3DLUT_ADDRESS_HIGH,
+                       HUBP_3DLUT_ADDRESS_HIGH, &fl_regs->lut_addr_hi);
+       REG_GET(HUBP_3DLUT_ADDRESS_LOW,
+                       HUBP_3DLUT_ADDRESS_LOW, &fl_regs->lut_addr_lo);
+       /* CLK */
+       REG_GET(HUBP_3DLUT_DLG_PARAM,
+                       REFCYC_PER_3DLUT_GROUP, &fl_regs->refcyc_3dlut_group);
+       /* FL */
+       REG_GET_2(_3DLUT_FL_BIAS_SCALE,
+               HUBP0_3DLUT_FL_BIAS, &fl_regs->lut_fl_bias,
+               HUBP0_3DLUT_FL_SCALE, &fl_regs->lut_fl_scale);
+       REG_GET_2(_3DLUT_FL_CONFIG,
+               HUBP0_3DLUT_FL_MODE, &fl_regs->lut_fl_mode,
+               HUBP0_3DLUT_FL_FORMAT, &fl_regs->lut_fl_format);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h
new file mode 100644 (file)
index 0000000..976614f
--- /dev/null
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 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 __DC_HUBP_DCN42_H__
+#define __DC_HUBP_DCN42_H__
+
+#include "dcn35/dcn35_hubp.h"
+
+#define HUBP_MASK_SH_LIST_DCN42(mask_sh)\
+       HUBP_MASK_SH_LIST_DCN35(mask_sh),\
+       HUBP_SF(HUBP0_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_MODE, mask_sh),\
+       HUBP_SF(HUBP0_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_FORMAT, mask_sh),\
+       HUBP_SF(HUBP0_3DLUT_FL_BIAS_SCALE, HUBP0_3DLUT_FL_BIAS, mask_sh),\
+       HUBP_SF(HUBP0_3DLUT_FL_BIAS_SCALE, HUBP0_3DLUT_FL_SCALE, mask_sh),\
+       HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_ENABLE, mask_sh),\
+       HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_DONE, mask_sh),\
+       HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_ADDRESSING_MODE, mask_sh),\
+       HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_WIDTH, mask_sh),\
+       HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_MPC_WIDTH, mask_sh),\
+       HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_TMZ, mask_sh),\
+       HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SEL_B, mask_sh),\
+       HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SEL_G, mask_sh),\
+       HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SEL_R, mask_sh),\
+       HUBP_SF(CURSOR0_0_HUBP_3DLUT_ADDRESS_HIGH, HUBP_3DLUT_ADDRESS_HIGH, mask_sh),\
+       HUBP_SF(CURSOR0_0_HUBP_3DLUT_ADDRESS_LOW, HUBP_3DLUT_ADDRESS_LOW, mask_sh),\
+       HUBP_SF(CURSOR0_0_HUBP_3DLUT_DLG_PARAM, REFCYC_PER_3DLUT_GROUP, mask_sh)
+
+bool hubp42_construct(
+       struct dcn20_hubp *hubp2,
+       struct dc_context *ctx,
+       uint32_t inst,
+       const struct dcn_hubp2_registers *hubp_regs,
+       const struct dcn_hubp2_shift *hubp_shift,
+       const struct dcn_hubp2_mask *hubp_mask);
+
+void hubp42_program_3dlut_fl_crossbar(
+       struct hubp *hubp,
+       enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_r,
+       enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_g,
+       enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_b);
+
+void hubp42_read_state(struct hubp *hubp);
+
+void hubp42_setup(
+               struct hubp *hubp,
+           struct dml2_dchub_per_pipe_register_set *pipe_regs,
+               union dml2_global_sync_programming *pipe_global_sync,
+               struct dc_crtc_timing *timing);
+
+void hubp42_program_deadline(
+               struct hubp *hubp,
+               struct dml2_display_dlg_regs *dlg_attr,
+               struct dml2_display_ttu_regs *ttu_attr);
+
+
+#endif /* __DC_HUBP_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
new file mode 100644 (file)
index 0000000..c9c6ef8
--- /dev/null
@@ -0,0 +1,1476 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dm_services.h"
+#include "dm_helpers.h"
+#include "core_types.h"
+#include "resource.h"
+#include "dccg.h"
+#include "dce/dce_hwseq.h"
+#include "dcn30/dcn30_cm_common.h"
+#include "reg_helper.h"
+#include "abm.h"
+#include "hubp.h"
+#include "dchubbub.h"
+#include "timing_generator.h"
+#include "opp.h"
+#include "ipp.h"
+#include "mpc.h"
+#include "mcif_wb.h"
+#include "dc_dmub_srv.h"
+#include "link_hwss.h"
+#include "dpcd_defs.h"
+#include "dcn401/dcn401_hwseq.h"
+#include "dcn42_hwseq.h"
+#include "clk_mgr.h"
+#include "dsc.h"
+#include "dcn20/dcn20_optc.h"
+#include "dce/dmub_hw_lock_mgr.h"
+#include "dcn42/dcn42_resource.h"
+#include "link_service.h"
+#include "../dcn10/dcn10_hwseq.h"
+#include "../dcn20/dcn20_hwseq.h"
+#include "dc_state_priv.h"
+#include "dc_stream_priv.h"
+#include "dcn35/dcn35_hwseq.h"
+#include "dcn42/dcn42_hwseq.h"
+#include "dce/dmub_hw_lock_mgr.h"
+#include "dio/dcn10/dcn10_dio.h"
+
+#define DC_LOGGER \
+       ctx->logger
+
+#define CTX \
+       hws->ctx
+
+#define REG(reg)\
+       hws->regs->reg
+
+#undef FN
+#define FN(reg_name, field_name) \
+       hws->shifts->field_name, hws->masks->field_name
+
+
+static void print_pg_status(struct dc *dc, const char *debug_func, const char *debug_log)
+{
+       if (dc->debug.enable_pg_cntl_debug_logs && dc->res_pool->pg_cntl) {
+               if (dc->res_pool->pg_cntl->funcs->print_pg_status)
+                       dc->res_pool->pg_cntl->funcs->print_pg_status(dc->res_pool->pg_cntl, debug_func, debug_log);
+       }
+}
+void dcn42_init_hw(struct dc *dc)
+{
+       struct abm **abms = dc->res_pool->multiple_abms;
+       struct dce_hwseq *hws = dc->hwseq;
+       struct dc_bios *dcb = dc->ctx->dc_bios;
+       struct resource_pool *res_pool = dc->res_pool;
+       int i;
+       int edp_num;
+       uint32_t backlight = MAX_BACKLIGHT_LEVEL;
+       uint32_t user_level = MAX_BACKLIGHT_LEVEL;
+       int current_dchub_ref_freq = 0;
+
+       if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) {
+               dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
+
+               // mark dcmode limits present if any clock has distinct AC and DC values from SMU
+               dc->caps.dcmode_power_limits_present = dc->clk_mgr->funcs->is_dc_mode_present &&
+                               dc->clk_mgr->funcs->is_dc_mode_present(dc->clk_mgr);
+       }
+
+       // Initialize the dccg
+       if (res_pool->dccg->funcs->dccg_init)
+               res_pool->dccg->funcs->dccg_init(res_pool->dccg);
+
+       // Disable DMUB Initialization until IPS state programming is finalized
+       //if (!dcb->funcs->is_accelerated_mode(dcb)) {
+       //      hws->funcs.bios_golden_init(dc);
+       //}
+
+       // Set default OPTC memory power states
+       if (dc->debug.enable_mem_low_power.bits.optc) {
+               // Shutdown when unassigned and light sleep in VBLANK
+               REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1);
+       }
+
+       if (dc->debug.enable_mem_low_power.bits.vga) {
+               // Power down VGA memory
+               REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1);
+       }
+
+       if (dc->ctx->dc_bios->fw_info_valid) {
+               res_pool->ref_clocks.xtalin_clock_inKhz =
+                               dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
+
+               if (res_pool->hubbub) {
+                       (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
+                                       dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
+                                       &res_pool->ref_clocks.dccg_ref_clock_inKhz);
+
+                       current_dchub_ref_freq = res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
+
+                       (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
+                                       res_pool->ref_clocks.dccg_ref_clock_inKhz,
+                                       &res_pool->ref_clocks.dchub_ref_clock_inKhz);
+               } else {
+                       // Not all ASICs have DCCG sw component
+                       res_pool->ref_clocks.dccg_ref_clock_inKhz =
+                                       res_pool->ref_clocks.xtalin_clock_inKhz;
+                       res_pool->ref_clocks.dchub_ref_clock_inKhz =
+                                       res_pool->ref_clocks.xtalin_clock_inKhz;
+               }
+       } else
+               ASSERT_CRITICAL(false);
+
+       for (i = 0; i < dc->link_count; i++) {
+               /* Power up AND update implementation according to the
+                * required signal (which may be different from the
+                * default signal on connector).
+                */
+               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 */
+               if (link->link_enc->funcs->is_dig_enabled &&
+                       link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
+                       link->link_status.link_active = true;
+                       link->phy_state.symclk_state = SYMCLK_ON_TX_ON;
+                       if (link->link_enc->funcs->fec_is_active &&
+                                       link->link_enc->funcs->fec_is_active(link->link_enc))
+                               link->fec_state = dc_link_fec_enabled;
+               }
+       }
+
+       /* enable_power_gating_plane before dsc_pg_control because
+        * FORCEON = 1 with hw default value on bootup, resume from s3
+        */
+       if (hws->funcs.enable_power_gating_plane)
+               hws->funcs.enable_power_gating_plane(dc->hwseq, true);
+
+       /* we want to turn off all dp displays before doing detection */
+       dc->link_srv->blank_all_dp_displays(dc);
+
+       /* If taking control over from VBIOS, we may want to optimize our first
+        * mode set, so we need to skip powering down pipes until we know which
+        * pipes we want to use.
+        * Otherwise, if taking control is not possible, we need to power
+        * everything down.
+        */
+       if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) {
+               /* Disable boot optimizations means power down everything including PHY, DIG,
+                * and OTG (i.e. the boot is not optimized because we do a full power down).
+                */
+               if (dc->hwss.enable_accelerated_mode && dc->debug.disable_boot_optimizations)
+                       dc->hwss.enable_accelerated_mode(dc, dc->current_state);
+               else
+                       hws->funcs.init_pipes(dc, dc->current_state);
+
+               if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
+                       dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
+                                       !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
+
+       }
+
+       /* In headless boot cases, DIG may be turned
+        * on which causes HW/SW discrepancies.
+        * To avoid this, power down hardware on boot
+        * if DIG is turned on and seamless boot not enabled
+        */
+       if (!dc->config.seamless_boot_edp_requested) {
+               struct dc_link *edp_links[MAX_NUM_EDP];
+               struct dc_link *edp_link;
+
+               dc_get_edp_links(dc, edp_links, &edp_num);
+               if (edp_num) {
+                       for (i = 0; i < edp_num; i++) {
+                               edp_link = edp_links[i];
+                               if (edp_link->link_enc->funcs->is_dig_enabled &&
+                                               edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
+                                               dc->hwss.edp_backlight_control &&
+                                               hws->funcs.power_down &&
+                                               dc->hwss.edp_power_control) {
+                                       dc->hwss.edp_backlight_control(edp_link, false);
+                                       hws->funcs.power_down(dc);
+                                       dc->hwss.edp_power_control(edp_link, false);
+                               }
+                       }
+               } else {
+                       for (i = 0; i < dc->link_count; i++) {
+                               struct dc_link *link = dc->links[i];
+
+                               if (link->link_enc->funcs->is_dig_enabled &&
+                                               link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
+                                               hws->funcs.power_down) {
+                                       hws->funcs.power_down(dc);
+                                       break;
+                               }
+
+                       }
+               }
+       }
+
+       for (i = 0; i < res_pool->audio_count; i++) {
+               struct audio *audio = res_pool->audios[i];
+
+               audio->funcs->hw_init(audio);
+       }
+
+       for (i = 0; i < dc->link_count; i++) {
+               struct dc_link *link = dc->links[i];
+
+               if (link->panel_cntl) {
+                       backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
+                       user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL;
+               }
+       }
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               if (abms[i] != NULL && abms[i]->funcs != NULL)
+                       abms[i]->funcs->abm_init(abms[i], backlight, user_level);
+       }
+
+       /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
+       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 */
+               REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
+
+               REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
+       }
+
+       dcn401_setup_hpo_hw_control(hws, true);
+
+       if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
+               dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
+
+       if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_wm_ranges)
+               dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
+
+       if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
+               dc->res_pool->hubbub->funcs->force_pstate_change_control(
+                               dc->res_pool->hubbub, false, false);
+
+       if (dc->res_pool->hubbub->funcs->init_crb)
+               dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
+
+       if (dc->res_pool->hubbub->funcs->set_request_limit && dc->config.sdpif_request_limit_words_per_umc > 0)
+               dc->res_pool->hubbub->funcs->set_request_limit(dc->res_pool->hubbub, dc->ctx->dc_bios->vram_info.num_chans, dc->config.sdpif_request_limit_words_per_umc);
+
+       // Get DMCUB capabilities
+       if (dc->ctx->dmub_srv) {
+               dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv);
+               dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
+               dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver > 0;
+               dc->caps.dmub_caps.fams_ver = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver;
+               dc->debug.fams2_config.bits.enable &=
+                               dc->caps.dmub_caps.fams_ver == dc->debug.fams_version.ver; // sw & fw fams versions must match for support
+               if ((!dc->debug.fams2_config.bits.enable && dc->res_pool->funcs->update_bw_bounding_box)
+                       || res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 != current_dchub_ref_freq) {
+                       /* update bounding box if FAMS2 disabled, or if dchub clk has changed */
+                       if (dc->clk_mgr)
+                               dc->res_pool->funcs->update_bw_bounding_box(dc,
+                                                                           dc->clk_mgr->bw_params);
+               }
+       }
+       if (dc->res_pool->pg_cntl) {
+               if (dc->res_pool->pg_cntl->funcs->init_pg_status)
+                       dc->res_pool->pg_cntl->funcs->init_pg_status(dc->res_pool->pg_cntl);
+       }
+       print_pg_status(dc, __func__, ": after init_pg_status");
+}
+
+void dcn42_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
+{
+       struct hubp *hubp = pipe_ctx->plane_res.hubp;
+       struct mpcc_blnd_cfg blnd_cfg = {0};
+       bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha;
+       int mpcc_id;
+       struct mpcc *new_mpcc;
+       struct mpc *mpc = dc->res_pool->mpc;
+       struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
+
+
+       blnd_cfg.overlap_only = false;
+       blnd_cfg.global_gain = 0xfff;
+
+       if (per_pixel_alpha) {
+               blnd_cfg.pre_multiplied_alpha = pipe_ctx->plane_state->pre_multiplied_alpha;
+               if (pipe_ctx->plane_state->global_alpha) {
+                       blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN;
+                       blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value;
+               } else {
+                       blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
+               }
+       } else {
+               blnd_cfg.pre_multiplied_alpha = false;
+               blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
+       }
+
+       if (pipe_ctx->plane_state->global_alpha)
+               blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
+       else
+               blnd_cfg.global_alpha = 0xfff;
+
+       blnd_cfg.background_color_bpc = 4;
+       blnd_cfg.bottom_gain_mode = 0;
+       blnd_cfg.top_gain = 0x1f000;
+       blnd_cfg.bottom_inside_gain = 0x1f000;
+       blnd_cfg.bottom_outside_gain = 0x1f000;
+
+       if (pipe_ctx->plane_state->format
+                       == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA)
+               blnd_cfg.pre_multiplied_alpha = false;
+
+       /*
+        * TODO: remove hack
+        * Note: currently there is a bug in init_hw such that
+        * on resume from hibernate, BIOS sets up MPCC0, and
+        * we do mpcc_remove but the mpcc cannot go to idle
+        * after remove. This cause us to pick mpcc1 here,
+        * which causes a pstate hang for yet unknown reason.
+        */
+       mpcc_id = hubp->inst;
+
+       /* If there is no full update, don't need to touch MPC tree*/
+       if (!pipe_ctx->plane_state->update_flags.bits.full_update &&
+               !pipe_ctx->update_flags.bits.mpcc) {
+               mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
+               dc->hwss.update_visual_confirm_color(dc, pipe_ctx, mpcc_id);
+               return;
+       }
+
+       /* check if this MPCC is already being used */
+       new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
+       /* remove MPCC if being used */
+       if (new_mpcc != NULL)
+               mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc);
+       else
+               if (dc->debug.sanity_checks)
+                       mpc->funcs->assert_mpcc_idle_before_connect(
+                                       dc->res_pool->mpc, mpcc_id);
+
+       /* Call MPC to insert new plane */
+       new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
+                       mpc_tree_params,
+                       &blnd_cfg,
+                       NULL,
+                       NULL,
+                       hubp->inst,
+                       mpcc_id);
+       dc->hwss.update_visual_confirm_color(dc, pipe_ctx, mpcc_id);
+
+       ASSERT(new_mpcc != NULL);
+       hubp->opp_id = pipe_ctx->stream_res.opp->inst;
+       hubp->mpcc_id = mpcc_id;
+}
+
+void dcn42_program_cm_hist(
+       struct dc *dc,
+       struct pipe_ctx *pipe_ctx,
+       const struct dc_plane_state *plane_state)
+{
+       struct dpp *dpp = pipe_ctx->plane_res.dpp;
+
+       if (dpp && dpp->funcs->dpp_cm_hist_control)
+               dpp->funcs->dpp_cm_hist_control(dpp,
+                       plane_state->cm_hist_control, plane_state->color_space);
+}
+
+static void dc_get_lut_xbar(
+       enum dc_cm2_gpu_mem_pixel_component_order order,
+       enum hubp_3dlut_fl_crossbar_bit_slice *cr_r,
+       enum hubp_3dlut_fl_crossbar_bit_slice *y_g,
+       enum hubp_3dlut_fl_crossbar_bit_slice *cb_b)
+{
+       switch (order) {
+       case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA:
+               *cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47;
+               *y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
+               *cb_b =  hubp_3dlut_fl_crossbar_bit_slice_0_15;
+               break;
+       case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_BGRA:
+               *cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15;
+               *y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
+               *cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47;
+               break;
+       }
+}
+
+static void dc_get_lut_mode(
+       enum dc_cm2_gpu_mem_layout layout,
+       enum hubp_3dlut_fl_mode *mode,
+       enum hubp_3dlut_fl_addressing_mode *addr_mode)
+{
+       switch (layout) {
+       case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB:
+               *mode = hubp_3dlut_fl_mode_native_1;
+               *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
+               break;
+       case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR:
+               *mode = hubp_3dlut_fl_mode_native_2;
+               *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
+               break;
+       case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR:
+               *mode = hubp_3dlut_fl_mode_transform;
+               *addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear;
+               break;
+       default:
+               *mode = hubp_3dlut_fl_mode_disable;
+               *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
+               break;
+       }
+}
+
+static void dc_get_lut_format(
+       enum dc_cm2_gpu_mem_format dc_format,
+       enum hubp_3dlut_fl_format *format)
+{
+       switch (dc_format) {
+       case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB:
+               *format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
+               break;
+       case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB:
+               *format = hubp_3dlut_fl_format_unorm_12lsb_bitslice;
+               break;
+       case DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10:
+               *format = hubp_3dlut_fl_format_float_fp1_5_10;
+               break;
+       }
+}
+
+static bool dc_is_rmcm_3dlut_supported(struct hubp *hubp, struct mpc *mpc)
+{
+       if (mpc->funcs->rmcm.power_on_shaper_3dlut &&
+               mpc->funcs->rmcm.fl_3dlut_configure &&
+               hubp->funcs->hubp_program_3dlut_fl_config)
+               return true;
+
+       return false;
+}
+
+static bool is_rmcm_3dlut_fl_supported(struct dc *dc, enum dc_cm2_gpu_mem_size size)
+{
+       if (!dc->caps.color.mpc.rmcm_3d_lut_caps.dma_3d_lut)
+               return false;
+       if (size == DC_CM2_GPU_MEM_SIZE_171717)
+               return (dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_17);
+       else if (size == DC_CM2_GPU_MEM_SIZE_333333)
+               return (dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_33);
+       return false;
+}
+
+static void dcn42_set_mcm_location_post_blend(struct dc *dc, struct pipe_ctx *pipe_ctx, bool bPostBlend)
+{
+       struct mpc *mpc = dc->res_pool->mpc;
+       int mpcc_id = pipe_ctx->plane_res.hubp->inst;
+
+       if (!pipe_ctx->plane_state)
+               return;
+
+       mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id);
+       pipe_ctx->plane_state->mcm_location = (bPostBlend) ?
+                                                                                       MPCC_MOVABLE_CM_LOCATION_AFTER :
+                                                                                       MPCC_MOVABLE_CM_LOCATION_BEFORE;
+}
+
+static void dcn42_get_mcm_lut_xable_from_pipe_ctx(struct dc *dc, struct pipe_ctx *pipe_ctx,
+               enum MCM_LUT_XABLE *shaper_xable,
+               enum MCM_LUT_XABLE *lut3d_xable,
+               enum MCM_LUT_XABLE *lut1d_xable)
+{
+       enum dc_cm2_shaper_3dlut_setting shaper_3dlut_setting = DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL;
+       bool lut1d_enable = false;
+       struct mpc *mpc = dc->res_pool->mpc;
+       int mpcc_id = pipe_ctx->plane_res.hubp->inst;
+
+       if (!pipe_ctx->plane_state)
+               return;
+       shaper_3dlut_setting = pipe_ctx->plane_state->mcm_shaper_3dlut_setting;
+       lut1d_enable = pipe_ctx->plane_state->mcm_lut1d_enable;
+       mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id);
+       pipe_ctx->plane_state->mcm_location = MPCC_MOVABLE_CM_LOCATION_BEFORE;
+
+       *lut1d_xable = lut1d_enable ? MCM_LUT_ENABLE : MCM_LUT_DISABLE;
+
+       switch (shaper_3dlut_setting) {
+       case DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL:
+               *lut3d_xable = *shaper_xable = MCM_LUT_DISABLE;
+               break;
+       case DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER:
+               *lut3d_xable = MCM_LUT_DISABLE;
+               *shaper_xable = MCM_LUT_ENABLE;
+               break;
+       case DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT:
+               *lut3d_xable = *shaper_xable = MCM_LUT_ENABLE;
+               break;
+       }
+}
+
+static void fl_get_lut_mode(
+       enum dc_cm2_gpu_mem_layout layout,
+       enum dc_cm2_gpu_mem_size   size,
+       enum hubp_3dlut_fl_mode *mode,
+       enum hubp_3dlut_fl_addressing_mode *addr_mode,
+       enum hubp_3dlut_fl_width *width)
+{
+       *width = hubp_3dlut_fl_width_17;
+
+       if (size == DC_CM2_GPU_MEM_SIZE_333333)
+               *width = hubp_3dlut_fl_width_33;
+
+       switch (layout) {
+       case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB:
+               *mode = hubp_3dlut_fl_mode_native_1;
+               *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
+               break;
+       case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR:
+               *mode = hubp_3dlut_fl_mode_native_2;
+               *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
+               break;
+       case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR:
+               *mode = hubp_3dlut_fl_mode_transform;
+               *addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear;
+               break;
+       default:
+               *mode = hubp_3dlut_fl_mode_disable;
+               *addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
+               break;
+       }
+}
+
+bool dcn42_program_rmcm_luts(
+       struct hubp *hubp,
+       struct pipe_ctx *pipe_ctx,
+       enum dc_cm2_transfer_func_source lut3d_src,
+       struct dc_cm2_func_luts *mcm_luts,
+       struct mpc *mpc,
+       bool lut_bank_a,
+       int mpcc_id)
+{
+       struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
+       union mcm_lut_params m_lut_params = {0};
+       enum MCM_LUT_XABLE shaper_xable, lut3d_xable = MCM_LUT_DISABLE, lut1d_xable;
+               enum hubp_3dlut_fl_mode mode;
+       enum hubp_3dlut_fl_addressing_mode addr_mode;
+       enum hubp_3dlut_fl_format format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
+       enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
+       enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_0_15;
+       enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47;
+       enum hubp_3dlut_fl_width width = hubp_3dlut_fl_width_17;
+
+
+       struct dc *dc = hubp->ctx->dc;
+       struct hubp_fl_3dlut_config fl_config;
+       struct mpc_fl_3dlut_config mpc_fl_config;
+
+       struct dc_stream_state *stream = pipe_ctx->stream;
+       bool bypass_rmcm_shaper = false;
+       // true->false when it can be allocated at DI time
+       struct dc_rmcm_3dlut *rmcm_3dlut = dc_stream_get_3dlut_for_stream(dc, stream, false);
+
+       //check to see current pipe is part of a stream with allocated rmcm 3dlut
+       if (!rmcm_3dlut)
+               return false;
+
+       rmcm_3dlut->protection_bits = mcm_luts->lut3d_data.rmcm_tmz;
+
+       dcn42_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable);
+
+       /* Shaper */
+       if (mcm_luts->shaper) {
+               memset(&m_lut_params, 0, sizeof(m_lut_params));
+
+               if (mcm_luts->shaper->type == TF_TYPE_HWPWL) {
+                       m_lut_params.pwl = &mcm_luts->shaper->pwl;
+               } else if (mcm_luts->shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
+                       ASSERT(false);
+                       cm_helper_translate_curve_to_hw_format(
+                                       dc->ctx,
+                                       mcm_luts->shaper,
+                                       &dpp_base->shaper_params, true);
+                       m_lut_params.pwl = &dpp_base->shaper_params;
+               }
+               if (m_lut_params.pwl) {
+                       if (mpc->funcs->rmcm.populate_lut)
+                               mpc->funcs->rmcm.populate_lut(mpc, m_lut_params, lut_bank_a, mpcc_id);
+                       if (mpc->funcs->rmcm.program_lut_mode)
+                               mpc->funcs->rmcm.program_lut_mode(mpc, !bypass_rmcm_shaper, lut_bank_a, mpcc_id);
+               } else {
+                       //RMCM 3dlut won't work without its shaper
+                       return false;
+               }
+       }
+
+       /* 3DLUT */
+       switch (lut3d_src) {
+       case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM:
+               memset(&m_lut_params, 0, sizeof(m_lut_params));
+               // Don't know what to do in this case.
+               //case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM:
+               break;
+       case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM:
+               fl_get_lut_mode(mcm_luts->lut3d_data.gpu_mem_params.layout,
+                               mcm_luts->lut3d_data.gpu_mem_params.size,
+                               &mode,
+                               &addr_mode,
+                               &width);
+
+               if (!dc_is_rmcm_3dlut_supported(hubp, mpc) ||
+                       !mpc->funcs->rmcm.is_config_supported(
+                               (width == hubp_3dlut_fl_width_17 ||
+                                width == hubp_3dlut_fl_width_transformed) ? 17 : 33))
+                       return false;
+
+               // setting native or transformed mode,
+               dc_get_lut_mode(mcm_luts->lut3d_data.gpu_mem_params.layout, &mode, &addr_mode);
+
+               //seems to be only for the MCM
+               dc_get_lut_format(mcm_luts->lut3d_data.gpu_mem_params.format_params.format, &format);
+
+               dc_get_lut_xbar(
+                       mcm_luts->lut3d_data.gpu_mem_params.component_order,
+                       &crossbar_bit_slice_cr_r,
+                       &crossbar_bit_slice_y_g,
+                       &crossbar_bit_slice_cb_b);
+
+               fl_config.mode                                  = mode;
+               fl_config.enabled                               = lut3d_xable != MCM_LUT_DISABLE;
+               fl_config.address                               = mcm_luts->lut3d_data.gpu_mem_params.addr;
+               fl_config.format                                = format;
+               fl_config.crossbar_bit_slice_y_g  = crossbar_bit_slice_y_g;
+               fl_config.crossbar_bit_slice_cb_b = crossbar_bit_slice_cb_b;
+               fl_config.crossbar_bit_slice_cr_r = crossbar_bit_slice_cr_r;
+               fl_config.width                             = width;
+               fl_config.protection_bits               = rmcm_3dlut->protection_bits;
+               fl_config.addr_mode                         = addr_mode;
+               fl_config.layout                = mcm_luts->lut3d_data.gpu_mem_params.layout;
+               fl_config.bias  = mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.bias;
+               fl_config.scale = mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.scale;
+
+               mpc_fl_config.enabled                   = fl_config.enabled;
+               mpc_fl_config.width                 = width;
+               mpc_fl_config.select_lut_bank_a = lut_bank_a;
+               mpc_fl_config.bit_depth             = mcm_luts->lut3d_data.gpu_mem_params.bit_depth;
+               mpc_fl_config.hubp_index                = hubp->inst;
+               mpc_fl_config.bias      = mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.bias;
+               mpc_fl_config.scale     = mcm_luts->lut3d_data.gpu_mem_params.format_params.float_params.scale;
+
+               //1. power down the block
+               mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, false);
+
+               //2. program RMCM - 3dlut reg programming
+               mpc->funcs->rmcm.fl_3dlut_configure(mpc, &mpc_fl_config, mpcc_id);
+
+               hubp->funcs->hubp_program_3dlut_fl_config(hubp, &fl_config);
+
+               //3. power on the block
+               mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, true);
+
+               break;
+       default:
+               return false;
+       }
+
+       return true;
+}
+
+void dcn42_populate_mcm_luts(struct dc *dc,
+               struct pipe_ctx *pipe_ctx,
+               struct dc_cm2_func_luts mcm_luts,
+               bool lut_bank_a)
+{
+       struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
+       struct hubp *hubp = pipe_ctx->plane_res.hubp;
+       int mpcc_id = hubp->inst;
+       struct mpc *mpc = dc->res_pool->mpc;
+       union mcm_lut_params m_lut_params;
+       enum dc_cm2_transfer_func_source lut3d_src = mcm_luts.lut3d_data.lut3d_src;
+       enum hubp_3dlut_fl_format format = 0;
+       enum hubp_3dlut_fl_mode mode;
+       enum hubp_3dlut_fl_width width = 0;
+       enum hubp_3dlut_fl_addressing_mode addr_mode;
+       enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g = 0;
+       enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b = 0;
+       enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r = 0;
+       enum MCM_LUT_XABLE shaper_xable = MCM_LUT_DISABLE;
+       enum MCM_LUT_XABLE lut3d_xable = MCM_LUT_DISABLE;
+       enum MCM_LUT_XABLE lut1d_xable = MCM_LUT_DISABLE;
+       bool rval;
+
+       dcn42_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable);
+
+       //MCM - setting its location (Before/After) blender
+       //set to post blend (true)
+       dcn42_set_mcm_location_post_blend(
+               dc,
+               pipe_ctx,
+               mcm_luts.lut3d_data.mpc_mcm_post_blend);
+
+       //RMCM - 3dLUT+Shaper
+       if (mcm_luts.lut3d_data.rmcm_3dlut_enable &&
+               is_rmcm_3dlut_fl_supported(dc, mcm_luts.lut3d_data.gpu_mem_params.size)) {
+               dcn42_program_rmcm_luts(
+                       hubp,
+                       pipe_ctx,
+                       lut3d_src,
+                       &mcm_luts,
+                       mpc,
+                       lut_bank_a,
+                       mpcc_id);
+       }
+
+       /* 1D LUT */
+       if (mcm_luts.lut1d_func) {
+               memset(&m_lut_params, 0, sizeof(m_lut_params));
+               if (mcm_luts.lut1d_func->type == TF_TYPE_HWPWL)
+                       m_lut_params.pwl = &mcm_luts.lut1d_func->pwl;
+               else if (mcm_luts.lut1d_func->type == TF_TYPE_DISTRIBUTED_POINTS) {
+                       rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx,
+                                       mcm_luts.lut1d_func,
+                                       &dpp_base->regamma_params, false);
+                       m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL;
+               }
+               if (m_lut_params.pwl) {
+                       if (mpc->funcs->populate_lut)
+                               mpc->funcs->populate_lut(mpc, MCM_LUT_1DLUT, m_lut_params, lut_bank_a, mpcc_id);
+               }
+               if (mpc->funcs->program_lut_mode)
+                       mpc->funcs->program_lut_mode(mpc, MCM_LUT_1DLUT, lut1d_xable && m_lut_params.pwl, lut_bank_a, mpcc_id);
+       }
+
+       /* Shaper */
+       if (mcm_luts.shaper && mcm_luts.lut3d_data.mpc_3dlut_enable) {
+               memset(&m_lut_params, 0, sizeof(m_lut_params));
+               if (mcm_luts.shaper->type == TF_TYPE_HWPWL)
+                       m_lut_params.pwl = &mcm_luts.shaper->pwl;
+               else if (mcm_luts.shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
+                       ASSERT(false);
+                       rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx,
+                                       mcm_luts.shaper,
+                                       &dpp_base->regamma_params, true);
+                       m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL;
+               }
+               if (m_lut_params.pwl) {
+                       if (mpc->funcs->mcm.populate_lut)
+                               mpc->funcs->mcm.populate_lut(mpc, m_lut_params, lut_bank_a, mpcc_id);
+                       if (mpc->funcs->program_lut_mode)
+                               mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, MCM_LUT_ENABLE, lut_bank_a, mpcc_id);
+               }
+       }
+
+       /* 3DLUT */
+       switch (lut3d_src) {
+       case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM:
+               memset(&m_lut_params, 0, sizeof(m_lut_params));
+               if (hubp->funcs->hubp_enable_3dlut_fl)
+                       hubp->funcs->hubp_enable_3dlut_fl(hubp, false);
+
+               if (mcm_luts.lut3d_data.lut3d_func && mcm_luts.lut3d_data.lut3d_func->state.bits.initialized) {
+                       m_lut_params.lut3d = &mcm_luts.lut3d_data.lut3d_func->lut_3d;
+                       if (mpc->funcs->populate_lut)
+                               mpc->funcs->populate_lut(mpc, MCM_LUT_3DLUT, m_lut_params, lut_bank_a, mpcc_id);
+                       if (mpc->funcs->program_lut_mode)
+                               mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a,
+                                               mpcc_id);
+               }
+               break;
+       case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM:
+               switch (mcm_luts.lut3d_data.gpu_mem_params.size) {
+               case DC_CM2_GPU_MEM_SIZE_333333:
+                       width = hubp_3dlut_fl_width_33;
+                       break;
+               case DC_CM2_GPU_MEM_SIZE_171717:
+                       width = hubp_3dlut_fl_width_17;
+                       break;
+               case DC_CM2_GPU_MEM_SIZE_TRANSFORMED:
+                       width = hubp_3dlut_fl_width_transformed;
+                       break;
+               default:
+                       //TODO: Handle default case
+                       break;
+               }
+
+               //check for support
+               if (mpc->funcs->mcm.is_config_supported &&
+                       !mpc->funcs->mcm.is_config_supported(width))
+                       break;
+
+               if (mpc->funcs->program_lut_read_write_control)
+                       mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, mpcc_id);
+               if (mpc->funcs->program_lut_mode)
+                       mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a, mpcc_id);
+
+               if (hubp->funcs->hubp_program_3dlut_fl_addr)
+                       hubp->funcs->hubp_program_3dlut_fl_addr(hubp, mcm_luts.lut3d_data.gpu_mem_params.addr);
+
+               if (mpc->funcs->mcm.program_bit_depth)
+                       mpc->funcs->mcm.program_bit_depth(mpc, mcm_luts.lut3d_data.gpu_mem_params.bit_depth, mpcc_id);
+
+               dc_get_lut_mode(mcm_luts.lut3d_data.gpu_mem_params.layout, &mode, &addr_mode);
+               if (hubp->funcs->hubp_program_3dlut_fl_mode)
+                       hubp->funcs->hubp_program_3dlut_fl_mode(hubp, mode);
+
+               if (hubp->funcs->hubp_program_3dlut_fl_addressing_mode)
+                       hubp->funcs->hubp_program_3dlut_fl_addressing_mode(hubp, addr_mode);
+
+               switch (mcm_luts.lut3d_data.gpu_mem_params.format_params.format) {
+               case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB:
+                       format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
+                       break;
+               case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB:
+                       format = hubp_3dlut_fl_format_unorm_12lsb_bitslice;
+                       break;
+               case DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10:
+                       format = hubp_3dlut_fl_format_float_fp1_5_10;
+                       break;
+               }
+               if (hubp->funcs->hubp_program_3dlut_fl_format)
+                       hubp->funcs->hubp_program_3dlut_fl_format(hubp, format);
+               if (hubp->funcs->hubp_update_3dlut_fl_bias_scale &&
+                               mpc->funcs->mcm.program_bias_scale) {
+                       mpc->funcs->mcm.program_bias_scale(mpc,
+                               mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias,
+                               mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale,
+                               mpcc_id);
+                       hubp->funcs->hubp_update_3dlut_fl_bias_scale(hubp,
+                                               mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias,
+                                               mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale);
+               }
+
+               //navi 4x has a bug and r and blue are swapped and need to be worked around here in
+               //TODO: need to make a method for get_xbar per asic OR do the workaround in program_crossbar for 4x
+               dc_get_lut_xbar(
+                       mcm_luts.lut3d_data.gpu_mem_params.component_order,
+                       &crossbar_bit_slice_cr_r,
+                       &crossbar_bit_slice_y_g,
+                       &crossbar_bit_slice_cb_b);
+
+               if (hubp->funcs->hubp_program_3dlut_fl_crossbar)
+                       hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp,
+                                       crossbar_bit_slice_cr_r,
+                                       crossbar_bit_slice_y_g,
+                                       crossbar_bit_slice_cb_b);
+
+               if (mpc->funcs->mcm.program_lut_read_write_control)
+                       mpc->funcs->mcm.program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, true, mpcc_id);
+
+               if (mpc->funcs->mcm.program_3dlut_size)
+                       mpc->funcs->mcm.program_3dlut_size(mpc, width, mpcc_id);
+
+               if (mpc->funcs->update_3dlut_fast_load_select)
+                       mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, hubp->inst);
+
+               if (hubp->funcs->hubp_enable_3dlut_fl)
+                       hubp->funcs->hubp_enable_3dlut_fl(hubp, true);
+               else {
+                       if (mpc->funcs->program_lut_mode) {
+                               mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, MCM_LUT_DISABLE, lut_bank_a, mpcc_id);
+                               mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, MCM_LUT_DISABLE, lut_bank_a, mpcc_id);
+                               mpc->funcs->program_lut_mode(mpc, MCM_LUT_1DLUT, MCM_LUT_DISABLE, lut_bank_a, mpcc_id);
+                       }
+               }
+               break;
+       }
+}
+
+bool dcn42_set_mcm_luts(struct pipe_ctx *pipe_ctx,
+                               const struct dc_plane_state *plane_state)
+{
+       struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
+       int mpcc_id = pipe_ctx->plane_res.hubp->inst;
+       struct dc *dc = pipe_ctx->stream_res.opp->ctx->dc;
+       struct mpc *mpc = dc->res_pool->mpc;
+       bool result;
+       const struct pwl_params *lut_params = NULL;
+       bool rval;
+
+       if (plane_state->mcm_luts.lut3d_data.lut3d_src == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
+               dcn42_populate_mcm_luts(dc, pipe_ctx, plane_state->mcm_luts, plane_state->lut_bank_a);
+               return true;
+       }
+
+       mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id);
+       pipe_ctx->plane_state->mcm_location = MPCC_MOVABLE_CM_LOCATION_BEFORE;
+       // 1D LUT
+       if (plane_state->blend_tf.type == TF_TYPE_HWPWL)
+               lut_params = &plane_state->blend_tf.pwl;
+       else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) {
+               rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
+                               &plane_state->blend_tf,
+                               &dpp_base->regamma_params, false);
+               lut_params = rval ? &dpp_base->regamma_params : NULL;
+       }
+       result = mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id);
+       lut_params = NULL;
+
+       // Shaper
+       if (plane_state->in_shaper_func.type == TF_TYPE_HWPWL)
+               lut_params = &plane_state->in_shaper_func.pwl;
+       else if (plane_state->in_shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
+               // TODO: dpp_base replace
+               rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
+                               &plane_state->in_shaper_func,
+                               &dpp_base->shaper_params, true);
+               lut_params = rval ? &dpp_base->shaper_params : NULL;
+       }
+       result &= mpc->funcs->program_shaper(mpc, lut_params, mpcc_id);
+
+       // 3D
+       if (mpc->funcs->program_3dlut) {
+               if (plane_state->lut3d_func.state.bits.initialized == 1)
+                       result &= mpc->funcs->program_3dlut(mpc, &plane_state->lut3d_func.lut_3d, mpcc_id);
+               else
+                       result &= mpc->funcs->program_3dlut(mpc, NULL, mpcc_id);
+       }
+
+       return result;
+}
+void dcn42_hardware_release(struct dc *dc)
+{
+       dcn35_hardware_release(dc);
+
+}
+static int count_active_streams(const struct dc *dc)
+{
+       int i, count = 0;
+
+       for (i = 0; i < dc->current_state->stream_count; ++i) {
+               struct dc_stream_state *stream = dc->current_state->streams[i];
+
+               if (stream && (!stream->dpms_off || dc->config.disable_ips_in_dpms_off))
+                       count += 1;
+       }
+
+       return count;
+}
+
+void dcn42_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,
+       struct pg_block_update *update_state)
+{
+       bool hpo_frl_stream_enc_acquired = false;
+       bool hpo_dp_stream_enc_acquired = false;
+       int i = 0, j = 0;
+
+       memset(update_state, 0, sizeof(struct pg_block_update));
+
+       update_state->pg_res_update[PG_DIO] = true;
+
+       for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) {
+               if (context->res_ctx.is_hpo_dp_stream_enc_acquired[i] &&
+                               dc->res_pool->hpo_dp_stream_enc[i]) {
+                       hpo_dp_stream_enc_acquired = true;
+                       break;
+               }
+       }
+
+       if (!hpo_frl_stream_enc_acquired && !hpo_dp_stream_enc_acquired)
+               update_state->pg_res_update[PG_HPO] = true;
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+               for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++)
+                       update_state->pg_pipe_res_update[j][i] = true;
+
+               if (!pipe_ctx)
+                       continue;
+
+               if (pipe_ctx->plane_res.hubp)
+                       update_state->pg_pipe_res_update[PG_HUBP][pipe_ctx->plane_res.hubp->inst] = false;
+
+               if (pipe_ctx->plane_res.dpp && pipe_ctx->plane_res.hubp)
+                       update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->plane_res.hubp->inst] = false;
+
+               if (pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp)
+                       update_state->pg_pipe_res_update[PG_MPCC][pipe_ctx->plane_res.mpcc_inst] = false;
+
+               if (pipe_ctx->stream_res.dsc) {
+                       update_state->pg_pipe_res_update[PG_DSC][pipe_ctx->stream_res.dsc->inst] = false;
+                       if (dc->caps.sequential_ono) {
+                               update_state->pg_pipe_res_update[PG_HUBP][pipe_ctx->stream_res.dsc->inst] = false;
+                               update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->stream_res.dsc->inst] = false;
+                       }
+               }
+               if (pipe_ctx->stream_res.opp)
+                       update_state->pg_pipe_res_update[PG_OPP][pipe_ctx->stream_res.opp->inst] = false;
+
+               if (pipe_ctx->stream_res.hpo_dp_stream_enc)
+                       update_state->pg_pipe_res_update[PG_DPSTREAM][pipe_ctx->stream_res.hpo_dp_stream_enc->inst] = false;
+
+               if (pipe_ctx->link_res.dio_link_enc) {
+                       update_state->pg_res_update[PG_DIO] = false;
+               }
+               if (pipe_ctx->link_res.hpo_dp_link_enc) {
+                       update_state->pg_res_update[PG_HPO] = false;
+               }
+       }
+
+
+       for (i = 0; i < dc->link_count; i++) {
+               update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = true;
+               if (dc->links[i]->type != dc_connection_none)
+                       update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = false;
+       }
+
+       /*domain24 controls all the otg, mpc, opp, as long as one otg is still up, avoid enabling OTG PG*/
+       for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
+               struct timing_generator *tg = dc->res_pool->timing_generators[i];
+               if (tg && tg->funcs->is_tg_enabled(tg)) {
+                       update_state->pg_pipe_res_update[PG_OPTC][i] = false;
+               } else {
+                        // Update pg_pipe_res_enable state
+                       if (dc->res_pool->pg_cntl->funcs->optc_pg_control)
+                               dc->res_pool->pg_cntl->funcs->optc_pg_control(dc->res_pool->pg_cntl, i, false);
+               }
+       }
+
+}
+
+void dcn42_prepare_bandwidth(
+       struct dc *dc,
+       struct dc_state *context)
+{
+
+       struct pg_block_update pg_update_state;
+
+       if (dc->hwss.calc_blocks_to_ungate) {
+               dc->hwss.calc_blocks_to_ungate(dc, context, &pg_update_state);
+
+               if (dc->hwss.root_clock_control)
+                       dc->hwss.root_clock_control(dc, &pg_update_state, true);
+               /*power up required HW block*/
+               if (dc->hwss.hw_block_power_up)
+                       dc->hwss.hw_block_power_up(dc, &pg_update_state);
+       }
+
+       dcn20_prepare_bandwidth(dc, context);
+}
+
+void dcn42_optimize_bandwidth(struct dc *dc, struct dc_state *context)
+{
+               struct pg_block_update pg_update_state;
+
+       print_pg_status(dc, __func__, ": before rcg and power up");
+
+       dcn401_optimize_bandwidth(dc, context);
+
+       if (dc->hwss.calc_blocks_to_gate) {
+               dc->hwss.calc_blocks_to_gate(dc, context, &pg_update_state);
+               /*try to power down unused block*/
+               if (dc->hwss.hw_block_power_down)
+                       dc->hwss.hw_block_power_down(dc, &pg_update_state);
+
+               if (dc->hwss.root_clock_control)
+                       dc->hwss.root_clock_control(dc, &pg_update_state, false);
+       }
+
+       print_pg_status(dc, __func__, ": after rcg and power up");
+
+}
+
+void dcn42_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context,
+       struct pg_block_update *update_state)
+{
+       bool hpo_frl_stream_enc_acquired = false;
+       bool hpo_dp_stream_enc_acquired = false;
+       int i = 0, j = 0;
+
+       memset(update_state, 0, sizeof(struct pg_block_update));
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *cur_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+               struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i];
+
+               if (cur_pipe == NULL || new_pipe == NULL)
+                       continue;
+
+               if ((!cur_pipe->plane_state && new_pipe->plane_state) ||
+                       (!cur_pipe->stream && new_pipe->stream) ||
+                       (cur_pipe->stream != new_pipe->stream && new_pipe->stream)) {
+                       // New pipe addition
+                       for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++) {
+                               if (j == PG_HUBP && new_pipe->plane_res.hubp)
+                                       update_state->pg_pipe_res_update[j][new_pipe->plane_res.hubp->inst] = true;
+
+                               if (j == PG_DPP && new_pipe->plane_res.dpp)
+                                       update_state->pg_pipe_res_update[j][new_pipe->plane_res.dpp->inst] = true;
+
+                               if (j == PG_MPCC && new_pipe->plane_res.dpp)
+                                       update_state->pg_pipe_res_update[j][new_pipe->plane_res.mpcc_inst] = true;
+
+                               if (j == PG_DSC && new_pipe->stream_res.dsc)
+                                       update_state->pg_pipe_res_update[j][new_pipe->stream_res.dsc->inst] = true;
+
+                               if (j == PG_OPP && new_pipe->stream_res.opp)
+                                       update_state->pg_pipe_res_update[j][new_pipe->stream_res.opp->inst] = true;
+
+                               if (j == PG_OPTC && new_pipe->stream_res.tg)
+                                       update_state->pg_pipe_res_update[j][new_pipe->stream_res.tg->inst] = true;
+
+                               if (j == PG_DPSTREAM && new_pipe->stream_res.hpo_dp_stream_enc)
+                                       update_state->pg_pipe_res_update[j][new_pipe->stream_res.hpo_dp_stream_enc->inst] = true;
+                       }
+               } else if (cur_pipe->plane_state == new_pipe->plane_state ||
+                               cur_pipe == new_pipe) {
+                       //unchanged pipes
+                       for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++) {
+                               if (j == PG_HUBP &&
+                                       cur_pipe->plane_res.hubp != new_pipe->plane_res.hubp &&
+                                       new_pipe->plane_res.hubp)
+                                       update_state->pg_pipe_res_update[j][new_pipe->plane_res.hubp->inst] = true;
+
+                               if (j == PG_DPP &&
+                                       cur_pipe->plane_res.dpp != new_pipe->plane_res.dpp &&
+                                       new_pipe->plane_res.dpp)
+                                       update_state->pg_pipe_res_update[j][new_pipe->plane_res.dpp->inst] = true;
+
+                               if (j == PG_OPP &&
+                                       cur_pipe->stream_res.opp != new_pipe->stream_res.opp &&
+                                       new_pipe->stream_res.opp)
+                                       update_state->pg_pipe_res_update[j][new_pipe->stream_res.opp->inst] = true;
+
+                               if (j == PG_DSC &&
+                                       cur_pipe->stream_res.dsc != new_pipe->stream_res.dsc &&
+                                       new_pipe->stream_res.dsc)
+                                       update_state->pg_pipe_res_update[j][new_pipe->stream_res.dsc->inst] = true;
+
+                               if (j == PG_OPTC &&
+                                       cur_pipe->stream_res.tg != new_pipe->stream_res.tg &&
+                                       new_pipe->stream_res.tg)
+                                       update_state->pg_pipe_res_update[j][new_pipe->stream_res.tg->inst] = true;
+
+                               if (j == PG_DPSTREAM &&
+                                       cur_pipe->stream_res.hpo_dp_stream_enc != new_pipe->stream_res.hpo_dp_stream_enc &&
+                                       new_pipe->stream_res.hpo_dp_stream_enc)
+                                       update_state->pg_pipe_res_update[j][new_pipe->stream_res.hpo_dp_stream_enc->inst] = true;
+                       }
+               }
+       }
+
+       for (i = 0; i < dc->link_count; i++)
+               if (dc->links[i]->type != dc_connection_none)
+                       update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = true;
+
+       for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
+               if (dc->current_state->res_ctx.is_stream_enc_acquired[i]) {
+                       update_state->pg_res_update[PG_DIO] = true;
+                       break;
+               }
+       }
+       for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) {
+               if (context->res_ctx.is_hpo_dp_stream_enc_acquired[i] &&
+                               dc->res_pool->hpo_dp_stream_enc[i]) {
+                       hpo_dp_stream_enc_acquired = true;
+                       break;
+               }
+       }
+
+       if (hpo_frl_stream_enc_acquired || hpo_dp_stream_enc_acquired)
+               update_state->pg_res_update[PG_HPO] = true;
+
+       if (hpo_frl_stream_enc_acquired)
+               update_state->pg_pipe_res_update[PG_HDMISTREAM][0] = true;
+
+       if (count_active_streams(dc) > 0) {
+               update_state->pg_res_update[PG_DCCG] = true;
+               update_state->pg_res_update[PG_DCIO] = true;
+               update_state->pg_res_update[PG_DCHUBBUB] = true;
+               update_state->pg_res_update[PG_DCHVM] = true;
+               update_state->pg_res_update[PG_DCOH] = true;
+       }
+}
+/**
+ * dcn42_hw_block_power_down() - power down sequence
+ *
+ * The following sequence describes the ON-OFF (ONO) for power down:
+ *
+ *     ONO Region 4, DCPG 25: hpo
+ *     ONO Region 11, DCPG 3: dchubp3, dpp3
+ *     ONO Region 9, DCPG 2: dchubp2, dpp2
+ *     ONO Region 7, DCPG 1: dchubp1, dpp1
+ *     ONO Region 5, DCPG 0: dchubp0, dpp0
+ *     ONO Region 2, DCPG 23: dchubbub, dchububmem, dchvm
+ *     ONO Region 12, DCPG 19: dsc3
+ *     ONO Region 10, DCPG 18: dsc2
+ *     ONO Region 8, DCPG 17: dsc1
+ *     ONO Region 6, DCPG 16: dsc0
+ *     ONO Region 3, DCPG 24: mpc, opp, optc, dwb
+ *     ONO Region 1, DCPG 26: dio
+ *     ONO Region 0, DCPG 22: dccg dcio dcoh - SKIPPED
+ *
+ *  No seuential ONO power up/down order for DCN42
+ *  Driver PG should only be limited to DCHUBP/DPP, DSC, HPO and DIO, so further optimization can be done
+ *
+ * @dc: Current DC state
+ * @update_state: update PG sequence states for HW block
+ */
+ void dcn42_hw_block_power_down(struct dc *dc,
+       struct pg_block_update *update_state)
+{
+       int i = 0;
+       struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl;
+       bool block_disabled = true;
+
+       if (!pg_cntl)
+               return;
+       if (dc->debug.ignore_pg)
+               return;
+
+       if (update_state->pg_res_update[PG_HPO]) {
+               if (pg_cntl->funcs->hpo_pg_control)
+                       pg_cntl->funcs->hpo_pg_control(pg_cntl, false);
+       }
+
+       for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
+               if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
+                       update_state->pg_pipe_res_update[PG_DPP][i]) {
+                       if (pg_cntl->funcs->hubp_dpp_pg_control)
+                               pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, false);
+               }
+       }
+
+       if (update_state->pg_res_update[PG_DCHUBBUB]) {
+               if (pg_cntl->funcs->mem_pg_control)
+                       pg_cntl->funcs->mem_pg_control(pg_cntl, false);
+       }
+
+       for (i = dc->res_pool->res_cap->num_dsc-1; i >= 0; i--) {
+               if (update_state->pg_pipe_res_update[PG_DSC][i]) {
+                       if (pg_cntl->funcs->dsc_pg_control)
+                               pg_cntl->funcs->dsc_pg_control(pg_cntl, i, false);
+               }
+       }
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               if (!update_state->pg_pipe_res_update[PG_MPCC][i] ||
+                       !update_state->pg_pipe_res_update[PG_OPP][i] ||
+                       !update_state->pg_pipe_res_update[PG_OPTC][i]) {
+                               block_disabled = false;
+                               break;
+               }
+       }
+
+       if (block_disabled) {
+               if (pg_cntl->funcs->plane_otg_pg_control)
+                       pg_cntl->funcs->plane_otg_pg_control(pg_cntl, false);
+       }
+
+       if (update_state->pg_res_update[PG_DIO]) {
+               if (pg_cntl->funcs->dio_pg_control)
+                       pg_cntl->funcs->dio_pg_control(pg_cntl, false);
+       }
+
+       if (update_state->pg_res_update[PG_DCCG] &&
+               update_state->pg_res_update[PG_DCIO] &&
+               update_state->pg_res_update[PG_DCOH]) {
+               // Driver PG should not power down DCCG, DCIO, DCOH. This is handled by IPS.
+               if (pg_cntl->funcs->io_clk_pg_control)
+                       pg_cntl->funcs->io_clk_pg_control(pg_cntl, false);
+               }
+}
+
+/**
+ * dcn42_hw_block_power_up() - power up sequence
+ *
+ * The following sequence describes the ON-OFF (ONO) for power up:
+ *
+ *     ONO Region 0, DCPG 22: dccg dcio dcoh
+ *  ONO Region 1, DCPG 26: dio
+ *     ONO Region 3, DCPG 24: mpc, opp, optc, dwb
+ *  ONO Region 6, DCPG 16: dsc0
+ *  ONO Region 8, DCPG 17: dsc1
+ *  ONO Region 10, DCPG 18: dsc2
+ *     ONO Region 12, DCPG 19: dsc3
+ *     ONO Region 2, DCPG 23: dchubbub, dchububmem, dchvm
+ *     ONO Region 5, DCPG 0: dchubp0, dpp0
+ *     ONO Region 7, DCPG 1: dchubp1, dpp1
+ *     ONO Region 9, DCPG 2: dchubp2, dpp2
+ *     ONO Region 11, DCPG 3: dchubp3, dpp3
+ *     ONO Region 4, DCPG 25: hpo
+
+ *  No sequential power up/down ordering for DCN42
+ *
+ * @dc: Current DC state
+ * @update_state: update PG sequence states for HW block
+ */
+void dcn42_hw_block_power_up(struct dc *dc,
+       struct pg_block_update *update_state)
+{
+       int i = 0;
+       struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl;
+       bool block_enabled = false;
+
+       if (!pg_cntl)
+               return;
+       if (dc->debug.ignore_pg)
+               return;
+
+       if (update_state->pg_res_update[PG_DCCG] ||
+               update_state->pg_res_update[PG_DCIO] ||
+               update_state->pg_res_update[PG_DCOH]) {
+               if (pg_cntl->funcs->io_clk_pg_control)
+                       pg_cntl->funcs->io_clk_pg_control(pg_cntl, true);
+       }
+
+       if (update_state->pg_res_update[PG_DIO]) {
+               if (pg_cntl->funcs->dio_pg_control)
+                       pg_cntl->funcs->dio_pg_control(pg_cntl, true);
+       }
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               if (update_state->pg_pipe_res_update[PG_MPCC][i] ||
+                       update_state->pg_pipe_res_update[PG_OPP][i] ||
+                       update_state->pg_pipe_res_update[PG_OPTC][i]) {
+                               block_enabled = true;
+                               break;
+               }
+       }
+       if (block_enabled) {
+               if (pg_cntl->funcs->plane_otg_pg_control)
+                       pg_cntl->funcs->plane_otg_pg_control(pg_cntl, true);
+       }
+
+       for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
+               if (update_state->pg_pipe_res_update[PG_DSC][i]) {
+                       if (pg_cntl->funcs->dsc_pg_control)
+                               pg_cntl->funcs->dsc_pg_control(pg_cntl, i, true);
+               }
+       }
+
+       if (update_state->pg_res_update[PG_DCHUBBUB]) {
+               if (pg_cntl->funcs->mem_pg_control)
+                       pg_cntl->funcs->mem_pg_control(pg_cntl, true);
+       }
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
+                       update_state->pg_pipe_res_update[PG_DPP][i]) {
+                       if (pg_cntl->funcs->hubp_dpp_pg_control)
+                               pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, true);
+               }
+       }
+       if (update_state->pg_res_update[PG_HPO]) {
+               if (pg_cntl->funcs->hpo_pg_control)
+                       pg_cntl->funcs->hpo_pg_control(pg_cntl, true);
+       }
+}
+void dcn42_root_clock_control(struct dc *dc,
+       struct pg_block_update *update_state, bool power_on)
+{
+       int i = 0;
+       struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl;
+
+       if (!pg_cntl)
+               return;
+       /*enable root clock first when power up*/
+       if (power_on) {
+               for (i = 0; i < dc->res_pool->pipe_count; i++) {
+                       if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
+                               update_state->pg_pipe_res_update[PG_DPP][i]) {
+                               if (dc->hwseq->funcs.dpp_root_clock_control)
+                                       dc->hwseq->funcs.dpp_root_clock_control(dc->hwseq, i, power_on);
+                       }
+                       if (update_state->pg_pipe_res_update[PG_DPSTREAM][i])
+                               if (dc->hwseq->funcs.dpstream_root_clock_control)
+                                       dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on);
+               }
+
+               for (i = 0; i < dc->res_pool->dig_link_enc_count; i++)
+                       if (update_state->pg_pipe_res_update[PG_PHYSYMCLK][i])
+                               if (dc->hwseq->funcs.physymclk_root_clock_control)
+                                       dc->hwseq->funcs.physymclk_root_clock_control(dc->hwseq, i, power_on);
+
+       }
+       for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
+               if (update_state->pg_pipe_res_update[PG_DSC][i]) {
+                       if (power_on) {
+                               if (dc->res_pool->dccg->funcs->enable_dsc)
+                                       dc->res_pool->dccg->funcs->enable_dsc(dc->res_pool->dccg, i);
+                       } else {
+                               if (dc->res_pool->dccg->funcs->disable_dsc)
+                                       dc->res_pool->dccg->funcs->disable_dsc(dc->res_pool->dccg, i);
+                       }
+               }
+       }
+       /*disable root clock first when power down*/
+       if (!power_on) {
+               for (i = 0; i < dc->res_pool->pipe_count; i++) {
+                       if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
+                               update_state->pg_pipe_res_update[PG_DPP][i]) {
+                               if (dc->hwseq->funcs.dpp_root_clock_control)
+                                       dc->hwseq->funcs.dpp_root_clock_control(dc->hwseq, i, power_on);
+                       }
+                       if (update_state->pg_pipe_res_update[PG_DPSTREAM][i])
+                               if (dc->hwseq->funcs.dpstream_root_clock_control)
+                                       dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on);
+               }
+
+               for (i = 0; i < dc->res_pool->dig_link_enc_count; i++)
+                       if (update_state->pg_pipe_res_update[PG_PHYSYMCLK][i])
+                               if (dc->hwseq->funcs.physymclk_root_clock_control)
+                                       dc->hwseq->funcs.physymclk_root_clock_control(dc->hwseq, i, power_on);
+
+       }
+}
+void dcn42_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
+{
+       struct crtc_stereo_flags flags = { 0 };
+       struct dc_stream_state *stream = pipe_ctx->stream;
+
+       dcn10_config_stereo_parameters(stream, &flags);
+
+       pipe_ctx->stream_res.opp->funcs->opp_program_stereo(
+               pipe_ctx->stream_res.opp,
+               flags.PROGRAM_STEREO == 1,
+               &stream->timing);
+
+       pipe_ctx->stream_res.tg->funcs->program_stereo(
+               pipe_ctx->stream_res.tg,
+               &stream->timing,
+               &flags);
+
+       return;
+}
+void dcn42_dmub_hw_control_lock(struct dc *dc, struct dc_state *context, bool lock)
+{
+
+       union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
+
+       if (!dc->ctx || !dc->ctx->dmub_srv)
+               return;
+
+       /* Use helper to check PSR/Replay for all streams in context */
+
+       if (!dc->debug.fams2_config.bits.enable && !dc_dmub_srv_is_cursor_offload_enabled(dc)
+               && !dmub_hw_lock_mgr_does_context_require_lock(dc, context))
+               return;
+
+       hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
+       hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
+       hw_lock_cmd.bits.lock = lock;
+       hw_lock_cmd.bits.should_release = !lock;
+       dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
+}
+
+void dcn42_dmub_hw_control_lock_fast(union block_sequence_params *params)
+{
+       struct dc *dc = params->dmub_hw_control_lock_fast_params.dc;
+       bool lock = params->dmub_hw_control_lock_fast_params.lock;
+
+       /* Use helper to check PSR/Replay for the given stream in fast path */
+       if (params->dmub_hw_control_lock_fast_params.is_required) {
+               union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
+               hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
+               hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
+               hw_lock_cmd.bits.lock = lock;
+               hw_lock_cmd.bits.should_release = !lock;
+               dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
+       }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h
new file mode 100644 (file)
index 0000000..89ebb65
--- /dev/null
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2026 Advanced Micro Devices, Inc. */
+
+#ifndef __DC_HWSS_DCN42_H__
+#define __DC_HWSS_DCN42_H__
+
+#include "dc.h"
+#include "hw_sequencer_private.h"
+
+void dcn42_init_hw(struct dc *dc);
+void dcn42_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx);
+
+void dcn42_program_cm_hist(
+       struct dc *dc,
+       struct pipe_ctx *pipe_ctx,
+       const struct dc_plane_state *plane_state);
+
+bool dcn42_set_mcm_luts(struct pipe_ctx *pipe_ctx,
+       const struct dc_plane_state *plane_state);
+
+void dcn42_populate_mcm_luts(struct dc *dc,
+               struct pipe_ctx *pipe_ctx,
+               struct dc_cm2_func_luts mcm_luts,
+               bool lut_bank_a);
+
+bool dcn42_program_rmcm_luts(
+       struct hubp *hubp,
+       struct pipe_ctx *pipe_ctx,
+       enum dc_cm2_transfer_func_source lut3d_src,
+       struct dc_cm2_func_luts *mcm_luts,
+       struct mpc *mpc,
+       bool lut_bank_a,
+       int mpcc_id);
+void dcn42_hardware_release(struct dc *dc);
+
+void dcn42_prepare_bandwidth(
+       struct dc *dc,
+       struct dc_state *context);
+void dcn42_optimize_bandwidth(struct dc *dc, struct dc_state *context);
+void dcn42_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,
+               struct pg_block_update *update_state);
+void dcn42_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context,
+               struct pg_block_update *update_state);
+void dcn42_hw_block_power_down(struct dc *dc,
+       struct pg_block_update *update_state);
+void dcn42_hw_block_power_up(struct dc *dc,
+               struct pg_block_update *update_state);
+void dcn42_root_clock_control(struct dc *dc,
+               struct pg_block_update *update_state, bool power_on);
+void dcn42_dmub_hw_control_lock(struct dc *dc, struct dc_state *context, bool lock);
+void dcn42_dmub_hw_control_lock_fast(union block_sequence_params *params);
+void dcn42_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc);
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c
new file mode 100644 (file)
index 0000000..a8e2f59
--- /dev/null
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dce110/dce110_hwseq.h"
+#include "dcn10/dcn10_hwseq.h"
+#include "dcn20/dcn20_hwseq.h"
+#include "dcn21/dcn21_hwseq.h"
+#include "dcn30/dcn30_hwseq.h"
+#include "dcn31/dcn31_hwseq.h"
+#include "dcn32/dcn32_hwseq.h"
+#include "dcn314/dcn314_hwseq.h"
+#include "dcn35/dcn35_hwseq.h"
+#include "dcn401/dcn401_hwseq.h"
+#include "dcn42/dcn42_hwseq.h"
+#include "dcn42_init.h"
+
+static const struct hw_sequencer_funcs dcn42_funcs = {
+       .program_gamut_remap = dcn401_program_gamut_remap,
+       .init_hw = dcn42_init_hw,
+       .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
+       .power_down_on_boot = dcn35_power_down_on_boot,
+       .apply_ctx_for_surface = NULL,
+       .program_front_end_for_ctx = dcn401_program_front_end_for_ctx,
+       .clear_surface_dcc_and_tiling = dcn10_reset_surface_dcc_and_tiling,
+       .wait_for_pending_cleared = dcn10_wait_for_pending_cleared,
+       .post_unlock_program_front_end = dcn401_post_unlock_program_front_end,
+       .update_plane_addr = dcn20_update_plane_addr,
+       .update_dchub = dcn10_update_dchub,
+       .update_pending_status = dcn10_update_pending_status,
+       .program_output_csc = dcn20_program_output_csc,
+       .trigger_3dlut_dma_load = dcn401_trigger_3dlut_dma_load,
+       .enable_accelerated_mode = dce110_enable_accelerated_mode,
+       .enable_timing_synchronization = dcn10_enable_timing_synchronization,
+       .enable_per_frame_crtc_position_reset = dcn10_enable_per_frame_crtc_position_reset,
+       .update_info_frame = dcn31_update_info_frame,
+       .send_immediate_sdp_message = dcn10_send_immediate_sdp_message,
+       .enable_stream = dcn401_enable_stream,
+       .disable_stream = dce110_disable_stream,
+       .unblank_stream = dcn401_unblank_stream,
+       .blank_stream = dce110_blank_stream,
+       .enable_audio_stream = dce110_enable_audio_stream,
+       .disable_audio_stream = dce110_disable_audio_stream,
+       .disable_plane = dcn35_disable_plane,
+       .pipe_control_lock = dcn20_pipe_control_lock,
+       .interdependent_update_lock = dcn401_interdependent_update_lock,
+       .cursor_lock = dcn10_cursor_lock,
+       .prepare_bandwidth = dcn42_prepare_bandwidth,
+       .optimize_bandwidth = dcn42_optimize_bandwidth,
+       .update_bandwidth = dcn401_update_bandwidth,
+       .set_drr = dcn35_set_drr,
+       .get_position = dcn10_get_position,
+       .set_static_screen_control = dcn35_set_static_screen_control,
+       .setup_stereo = dcn42_setup_stereo,
+       .set_avmute = dcn30_set_avmute,
+       .log_hw_state = dcn10_log_hw_state,
+       .get_hw_state = dcn10_get_hw_state,
+       .clear_status_bits = dcn10_clear_status_bits,
+       .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
+       .edp_backlight_control = dce110_edp_backlight_control,
+       .edp_power_control = dce110_edp_power_control,
+       .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready,
+       .edp_wait_for_T12 = dce110_edp_wait_for_T12,
+       .set_cursor_position = dcn401_set_cursor_position,
+       .set_cursor_attribute = dcn10_set_cursor_attribute,
+       .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level,
+       .setup_periodic_interrupt = dcn10_setup_periodic_interrupt,
+       .set_clock = dcn10_set_clock,
+       .get_clock = dcn10_get_clock,
+       .program_triplebuffer = dcn20_program_triple_buffer,
+       .enable_writeback = dcn30_enable_writeback,
+       .disable_writeback = dcn30_disable_writeback,
+       .update_writeback = dcn30_update_writeback,
+       .dmdata_status_done = dcn20_dmdata_status_done,
+       .program_dmdata_engine = dcn30_program_dmdata_engine,
+       .set_dmdata_attributes = dcn20_set_dmdata_attributes,
+       .init_sys_ctx = dcn31_init_sys_ctx,
+       .init_vm_ctx = dcn20_init_vm_ctx,
+       .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,
+       .apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations,
+       .does_plane_fit_in_mall = NULL,
+       .set_backlight_level = dcn31_set_backlight_level,
+       .set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
+       .hardware_release = dcn42_hardware_release,
+       .set_pipe = dcn21_set_pipe,
+       .enable_lvds_link_output = dce110_enable_lvds_link_output,
+       .enable_tmds_link_output = dce110_enable_tmds_link_output,
+       .enable_dp_link_output = dce110_enable_dp_link_output,
+       .disable_link_output = dcn401_disable_link_output,
+       .set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
+       .optimize_pwr_state = dcn21_optimize_pwr_state,
+       .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state,
+       .get_dcc_en_bits = dcn10_get_dcc_en_bits,
+       .enable_phantom_streams = dcn32_enable_phantom_streams,
+       .disable_phantom_streams = dcn32_disable_phantom_streams,
+       .update_visual_confirm_color = dcn10_update_visual_confirm_color,
+       .update_phantom_vp_position = dcn32_update_phantom_vp_position,
+       .apply_update_flags_for_phantom = dcn32_apply_update_flags_for_phantom,
+       .wait_for_dcc_meta_propagation = dcn401_wait_for_dcc_meta_propagation,
+       .is_pipe_topology_transition_seamless = dcn32_is_pipe_topology_transition_seamless,
+       .dmub_hw_control_lock = dcn42_dmub_hw_control_lock,
+       .fams2_update_config = dcn401_fams2_update_config,
+       .dmub_hw_control_lock_fast = dcn42_dmub_hw_control_lock_fast,
+       .program_outstanding_updates = dcn401_program_outstanding_updates,
+       .wait_for_all_pending_updates = dcn30_wait_for_all_pending_updates,
+       .detect_pipe_changes = dcn401_detect_pipe_changes,
+       .enable_plane = dcn35_enable_plane,
+       .update_dchubp_dpp = dcn20_update_dchubp_dpp,
+       .post_unlock_reset_opp = dcn20_post_unlock_reset_opp,
+       .get_underflow_debug_data = dcn30_get_underflow_debug_data,
+       // Driver PG
+       .hw_block_power_up = dcn42_hw_block_power_up,
+       .hw_block_power_down = dcn42_hw_block_power_down,
+       .root_clock_control = dcn42_root_clock_control,
+       .calc_blocks_to_gate = dcn42_calc_blocks_to_gate,
+       .calc_blocks_to_ungate = dcn42_calc_blocks_to_ungate,
+
+};
+
+static const struct hwseq_private_funcs dcn42_private_funcs = {
+       .init_pipes = dcn35_init_pipes,
+       .plane_atomic_disconnect = dcn10_plane_atomic_disconnect,
+       .update_mpcc = dcn42_update_mpcc,
+       .set_input_transfer_func = dcn32_set_input_transfer_func,
+       .set_output_transfer_func = dcn401_set_output_transfer_func,
+       .power_down = dce110_power_down,
+       .enable_display_power_gating = dcn10_dummy_display_power_gating,
+       .blank_pixel_data = dcn20_blank_pixel_data,
+       .reset_hw_ctx_wrap = dcn401_reset_hw_ctx_wrap,
+       .enable_stream_timing = dcn401_enable_stream_timing,
+       .edp_backlight_control = dce110_edp_backlight_control,
+       .setup_vupdate_interrupt = dcn20_setup_vupdate_interrupt,
+       .did_underflow_occur = dcn10_did_underflow_occur,
+       .init_blank = dcn32_init_blank,
+       .disable_vga = dcn20_disable_vga,
+       .bios_golden_init = dcn10_bios_golden_init,
+       .plane_atomic_disable = dcn35_plane_atomic_disable,
+       .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree,
+       .update_odm = dcn401_update_odm,
+       .dsc_pg_status = dcn32_dsc_pg_status,
+       .set_hdr_multiplier = dcn10_set_hdr_multiplier,
+       .wait_for_blank_complete = dcn20_wait_for_blank_complete,
+       .set_mcm_luts = dcn42_set_mcm_luts,
+       .program_mall_pipe_config = dcn32_program_mall_pipe_config,
+       .update_mall_sel = dcn32_update_mall_sel,
+       .calculate_dccg_k1_k2_values = NULL,
+       .apply_single_controller_ctx_to_hw = dce110_apply_single_controller_ctx_to_hw,
+       .reset_back_end_for_pipe = dcn401_reset_back_end_for_pipe,
+       .populate_mcm_luts = NULL,
+       .perform_3dlut_wa_unlock = dcn401_perform_3dlut_wa_unlock,
+       .program_cm_hist = dcn42_program_cm_hist,
+       .dpp_root_clock_control = dcn35_dpp_root_clock_control,
+       .dpstream_root_clock_control = dcn35_dpstream_root_clock_control,
+       .physymclk_root_clock_control = dcn35_physymclk_root_clock_control,
+       .resync_fifo_dccg_dio = dcn314_resync_fifo_dccg_dio,
+       .wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed,
+       .set_wait_for_update_needed_for_pipe = dcn10_set_wait_for_update_needed_for_pipe,
+};
+
+void dcn42_hw_sequencer_init_functions(struct dc *dc)
+{
+       dc->hwss = dcn42_funcs;
+       dc->hwseq->funcs = dcn42_private_funcs;
+
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.h
new file mode 100644 (file)
index 0000000..f66eb75
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2026 Advanced Micro Devices, Inc. */
+
+#ifndef __DC_DCN42_INIT_H__
+#define __DC_DCN42_INIT_H__
+
+struct dc;
+
+void dcn42_hw_sequencer_init_functions(struct dc *dc);
+
+#endif /* __DC_DCN401_INIT_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c
new file mode 100644 (file)
index 0000000..19e0741
--- /dev/null
@@ -0,0 +1,412 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dm_services.h"
+#include "include/logger_interface.h"
+#include "../dce110/irq_service_dce110.h"
+
+#include "ivsrcid/dcn/irqsrcs_dcn_1_0.h"
+#include "dcn/dcn_4_2_0_offset.h"
+#include "dcn/dcn_4_2_0_sh_mask.h"
+
+#include "irq_service_dcn42.h"
+
+#define DCN_BASE__INST0_SEG2 0x000034C0
+
+static enum dc_irq_source to_dal_irq_source_dcn42(
+       struct irq_service *irq_service,
+       uint32_t src_id,
+       uint32_t ext_id)
+{
+       switch (src_id) {
+       case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
+               return DC_IRQ_SOURCE_VBLANK1;
+       case DCN_1_0__SRCID__DC_D2_OTG_VSTARTUP:
+               return DC_IRQ_SOURCE_VBLANK2;
+       case DCN_1_0__SRCID__DC_D3_OTG_VSTARTUP:
+               return DC_IRQ_SOURCE_VBLANK3;
+       case DCN_1_0__SRCID__DC_D4_OTG_VSTARTUP:
+               return DC_IRQ_SOURCE_VBLANK4;
+       case DCN_1_0__SRCID__DC_D5_OTG_VSTARTUP:
+               return DC_IRQ_SOURCE_VBLANK5;
+       case DCN_1_0__SRCID__DC_D6_OTG_VSTARTUP:
+               return DC_IRQ_SOURCE_VBLANK6;
+       case DCN_1_0__SRCID__OTG1_VERTICAL_INTERRUPT0_CONTROL:
+               return DC_IRQ_SOURCE_DC1_VLINE0;
+       case DCN_1_0__SRCID__OTG2_VERTICAL_INTERRUPT0_CONTROL:
+               return DC_IRQ_SOURCE_DC2_VLINE0;
+       case DCN_1_0__SRCID__OTG3_VERTICAL_INTERRUPT0_CONTROL:
+               return DC_IRQ_SOURCE_DC3_VLINE0;
+       case DCN_1_0__SRCID__OTG4_VERTICAL_INTERRUPT0_CONTROL:
+               return DC_IRQ_SOURCE_DC4_VLINE0;
+       case DCN_1_0__SRCID__OTG5_VERTICAL_INTERRUPT0_CONTROL:
+               return DC_IRQ_SOURCE_DC5_VLINE0;
+       case DCN_1_0__SRCID__OTG6_VERTICAL_INTERRUPT0_CONTROL:
+               return DC_IRQ_SOURCE_DC6_VLINE0;
+       case DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT:
+               return DC_IRQ_SOURCE_PFLIP1;
+       case DCN_1_0__SRCID__HUBP1_FLIP_INTERRUPT:
+               return DC_IRQ_SOURCE_PFLIP2;
+       case DCN_1_0__SRCID__HUBP2_FLIP_INTERRUPT:
+               return DC_IRQ_SOURCE_PFLIP3;
+       case DCN_1_0__SRCID__HUBP3_FLIP_INTERRUPT:
+               return DC_IRQ_SOURCE_PFLIP4;
+       case DCN_1_0__SRCID__HUBP4_FLIP_INTERRUPT:
+               return DC_IRQ_SOURCE_PFLIP5;
+       case DCN_1_0__SRCID__HUBP5_FLIP_INTERRUPT:
+               return DC_IRQ_SOURCE_PFLIP6;
+       case DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT:
+               return DC_IRQ_SOURCE_VUPDATE1;
+       case DCN_1_0__SRCID__OTG1_IHC_V_UPDATE_NO_LOCK_INTERRUPT:
+               return DC_IRQ_SOURCE_VUPDATE2;
+       case DCN_1_0__SRCID__OTG2_IHC_V_UPDATE_NO_LOCK_INTERRUPT:
+               return DC_IRQ_SOURCE_VUPDATE3;
+       case DCN_1_0__SRCID__OTG3_IHC_V_UPDATE_NO_LOCK_INTERRUPT:
+               return DC_IRQ_SOURCE_VUPDATE4;
+       case DCN_1_0__SRCID__OTG4_IHC_V_UPDATE_NO_LOCK_INTERRUPT:
+               return DC_IRQ_SOURCE_VUPDATE5;
+       case DCN_1_0__SRCID__OTG5_IHC_V_UPDATE_NO_LOCK_INTERRUPT:
+               return DC_IRQ_SOURCE_VUPDATE6;
+       case DCN_1_0__SRCID__DMCUB_OUTBOX_LOW_PRIORITY_READY_INT:
+               return DC_IRQ_SOURCE_DMCUB_OUTBOX;
+       case DCN_1_0__SRCID__DC_HPD1_INT:
+               /* generic src_id for all HPD and HPDRX interrupts */
+               switch (ext_id) {
+               case DCN_1_0__CTXID__DC_HPD1_INT:
+                       return DC_IRQ_SOURCE_HPD1;
+               case DCN_1_0__CTXID__DC_HPD2_INT:
+                       return DC_IRQ_SOURCE_HPD2;
+               case DCN_1_0__CTXID__DC_HPD3_INT:
+                       return DC_IRQ_SOURCE_HPD3;
+               case DCN_1_0__CTXID__DC_HPD4_INT:
+                       return DC_IRQ_SOURCE_HPD4;
+               case DCN_1_0__CTXID__DC_HPD5_INT:
+                       return DC_IRQ_SOURCE_HPD5;
+               case DCN_1_0__CTXID__DC_HPD6_INT:
+                       return DC_IRQ_SOURCE_HPD6;
+               case DCN_1_0__CTXID__DC_HPD1_RX_INT:
+                       return DC_IRQ_SOURCE_HPD1RX;
+               case DCN_1_0__CTXID__DC_HPD2_RX_INT:
+                       return DC_IRQ_SOURCE_HPD2RX;
+               case DCN_1_0__CTXID__DC_HPD3_RX_INT:
+                       return DC_IRQ_SOURCE_HPD3RX;
+               case DCN_1_0__CTXID__DC_HPD4_RX_INT:
+                       return DC_IRQ_SOURCE_HPD4RX;
+               case DCN_1_0__CTXID__DC_HPD5_RX_INT:
+                       return DC_IRQ_SOURCE_HPD5RX;
+               case DCN_1_0__CTXID__DC_HPD6_RX_INT:
+                       return DC_IRQ_SOURCE_HPD6RX;
+               default:
+                       return DC_IRQ_SOURCE_INVALID;
+               }
+               break;
+       default:
+               return DC_IRQ_SOURCE_INVALID;
+       }
+
+}
+
+static struct irq_source_info_funcs hpd_irq_info_funcs = {
+       .set = NULL,
+       .ack = hpd0_ack
+};
+
+static struct irq_source_info_funcs hpd_rx_irq_info_funcs = {
+       .set = NULL,
+       .ack = NULL
+};
+
+static struct irq_source_info_funcs pflip_irq_info_funcs = {
+       .set = NULL,
+       .ack = NULL
+};
+
+static struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = {
+       .set = NULL,
+       .ack = NULL
+};
+
+static struct irq_source_info_funcs vblank_irq_info_funcs = {
+       .set = NULL,
+       .ack = NULL
+};
+
+static struct irq_source_info_funcs outbox_irq_info_funcs = {
+       .set = NULL,
+       .ack = NULL
+};
+
+static struct irq_source_info_funcs vline0_irq_info_funcs = {
+       .set = NULL,
+       .ack = NULL
+};
+
+static struct irq_source_info_funcs vline1_irq_info_funcs = {
+       .set = NULL,
+       .ack = NULL
+};
+
+static struct irq_source_info_funcs vline2_irq_info_funcs = {
+       .set = NULL,
+       .ack = NULL
+};
+
+#undef BASE_INNER
+#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
+
+/* compile time expand base address. */
+#define BASE(seg) \
+       BASE_INNER(seg)
+
+#define SRI(reg_name, block, id)\
+       (BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
+                       reg ## block ## id ## _ ## reg_name)
+
+#define SRI_DMUB(reg_name)\
+       (BASE(reg ## reg_name ## _BASE_IDX) + \
+                       reg ## reg_name)
+
+#define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\
+       .enable_reg = SRI(reg1, block, reg_num),\
+       .enable_mask = \
+               block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
+       .enable_value = {\
+               block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
+               ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+       },\
+       .ack_reg = SRI(reg2, block, reg_num),\
+       .ack_mask = \
+               block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\
+       .ack_value = \
+               block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \
+
+#define IRQ_REG_ENTRY_DMUB(reg1, mask1, reg2, mask2)\
+       .enable_reg = SRI_DMUB(reg1),\
+       .enable_mask = \
+               reg1 ## __ ## mask1 ## _MASK,\
+       .enable_value = {\
+               reg1 ## __ ## mask1 ## _MASK,\
+               ~reg1 ## __ ## mask1 ## _MASK \
+       },\
+       .ack_reg = SRI_DMUB(reg2),\
+       .ack_mask = \
+               reg2 ## __ ## mask2 ## _MASK,\
+       .ack_value = \
+               reg2 ## __ ## mask2 ## _MASK \
+
+#define hpd_int_entry(reg_num)\
+       [DC_IRQ_SOURCE_HPD1 + reg_num] = {\
+               IRQ_REG_ENTRY(HPD, reg_num,\
+                       DC_HPD_INT_CONTROL, DC_HPD_INT_EN,\
+                       DC_HPD_INT_CONTROL, DC_HPD_INT_ACK),\
+               .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\
+               .funcs = &hpd_irq_info_funcs\
+       }
+
+#define hpd_rx_int_entry(reg_num)\
+       [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\
+               IRQ_REG_ENTRY(HPD, reg_num,\
+                       DC_HPD_INT_CONTROL, DC_HPD_RX_INT_EN,\
+                       DC_HPD_INT_CONTROL, DC_HPD_RX_INT_ACK),\
+               .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\
+               .funcs = &hpd_rx_irq_info_funcs\
+       }
+#define pflip_int_entry(reg_num)\
+       [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\
+               IRQ_REG_ENTRY(HUBPREQ, reg_num,\
+                       DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_INT_MASK,\
+                       DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_CLEAR),\
+               .funcs = &pflip_irq_info_funcs\
+       }
+
+#define vblank_int_entry(reg_num)\
+       [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\
+               IRQ_REG_ENTRY(OTG, reg_num,\
+                       OTG_GLOBAL_SYNC_STATUS, VSTARTUP_INT_EN,\
+                       OTG_GLOBAL_SYNC_STATUS, VSTARTUP_EVENT_CLEAR),\
+               .funcs = &vblank_irq_info_funcs\
+       }
+
+#define vupdate_no_lock_int_entry(reg_num)\
+       [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\
+               IRQ_REG_ENTRY(OTG, reg_num,\
+                       OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_INT_EN,\
+                       OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR),\
+               .funcs = &vupdate_no_lock_irq_info_funcs\
+       }
+
+#define vline0_int_entry(reg_num)\
+       [DC_IRQ_SOURCE_DC1_VLINE0 + reg_num] = {\
+               IRQ_REG_ENTRY(OTG, reg_num,\
+                       OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE,\
+                       OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_CLEAR),\
+               .funcs = &vline0_irq_info_funcs\
+       }
+#define vline1_int_entry(reg_num)\
+       [DC_IRQ_SOURCE_DC1_VLINE1 + reg_num] = {\
+               IRQ_REG_ENTRY(OTG, reg_num,\
+                       OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE,\
+                       OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_CLEAR),\
+               .funcs = &vline1_irq_info_funcs\
+       }
+#define vline2_int_entry(reg_num)\
+       [DC_IRQ_SOURCE_DC1_VLINE2 + reg_num] = {\
+               IRQ_REG_ENTRY(OTG, reg_num,\
+                       OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE,\
+                       OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_CLEAR),\
+               .funcs = &vline2_irq_info_funcs\
+       }
+#define dmub_outbox_int_entry()\
+       [DC_IRQ_SOURCE_DMCUB_OUTBOX] = {\
+               IRQ_REG_ENTRY_DMUB(\
+                       DMCUB_INTERRUPT_ENABLE, DMCUB_OUTBOX1_READY_INT_EN,\
+                       DMCUB_INTERRUPT_ACK, DMCUB_OUTBOX1_READY_INT_ACK),\
+               .funcs = &outbox_irq_info_funcs\
+       }
+
+#define dummy_irq_entry() \
+       {\
+               .funcs = &dummy_irq_info_funcs\
+       }
+
+#define i2c_int_entry(reg_num) \
+       [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry()
+
+#define dp_sink_int_entry(reg_num) \
+       [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry()
+
+#define gpio_pad_int_entry(reg_num) \
+       [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry()
+
+#define dc_underflow_int_entry(reg_num) \
+       [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry()
+
+static struct irq_source_info_funcs dummy_irq_info_funcs = {
+       .set = dal_irq_service_dummy_set,
+       .ack = dal_irq_service_dummy_ack
+};
+
+static const struct irq_source_info irq_source_info_dcn42[DAL_IRQ_SOURCES_NUMBER] = {
+       [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(),
+       /* HPD (1-4) */
+       hpd_int_entry(0),
+       hpd_int_entry(1),
+       hpd_int_entry(2),
+       hpd_int_entry(3),
+       /* HPD RX (1-4) */
+       hpd_rx_int_entry(0),
+       hpd_rx_int_entry(1),
+       hpd_rx_int_entry(2),
+       hpd_rx_int_entry(3),
+       /* I2C (1-6) */
+       i2c_int_entry(1),
+       i2c_int_entry(2),
+       i2c_int_entry(3),
+       i2c_int_entry(4),
+       i2c_int_entry(5),
+       i2c_int_entry(6),
+       /* DP sink (1-6) keep table shape */
+       dp_sink_int_entry(1),
+       dp_sink_int_entry(2),
+       dp_sink_int_entry(3),
+       dp_sink_int_entry(4),
+       dp_sink_int_entry(5),
+       dp_sink_int_entry(6),
+       [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(),
+       /* PFLIP (1-4) */
+       pflip_int_entry(0),
+       pflip_int_entry(1),
+       pflip_int_entry(2),
+       pflip_int_entry(3),
+       [DC_IRQ_SOURCE_PFLIP5] = dummy_irq_entry(),
+       [DC_IRQ_SOURCE_PFLIP6] = dummy_irq_entry(),
+       [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(),
+       /* GPIO pads */
+       gpio_pad_int_entry(0),
+       gpio_pad_int_entry(1),
+       gpio_pad_int_entry(2),
+       gpio_pad_int_entry(3),
+       gpio_pad_int_entry(4),
+       gpio_pad_int_entry(5),
+       gpio_pad_int_entry(6),
+       gpio_pad_int_entry(7),
+       gpio_pad_int_entry(8),
+       gpio_pad_int_entry(9),
+       gpio_pad_int_entry(10),
+       gpio_pad_int_entry(11),
+       gpio_pad_int_entry(12),
+       gpio_pad_int_entry(13),
+       gpio_pad_int_entry(14),
+       gpio_pad_int_entry(15),
+       gpio_pad_int_entry(16),
+       gpio_pad_int_entry(17),
+       gpio_pad_int_entry(18),
+       gpio_pad_int_entry(19),
+       gpio_pad_int_entry(20),
+       gpio_pad_int_entry(21),
+       gpio_pad_int_entry(22),
+       gpio_pad_int_entry(23),
+       gpio_pad_int_entry(24),
+       gpio_pad_int_entry(25),
+       gpio_pad_int_entry(26),
+       gpio_pad_int_entry(27),
+       gpio_pad_int_entry(28),
+       gpio_pad_int_entry(29),
+       gpio_pad_int_entry(30),
+       /* Underflow (1-4 active, keep 5-6 dummy) */
+       dc_underflow_int_entry(1),
+       dc_underflow_int_entry(2),
+       dc_underflow_int_entry(3),
+       dc_underflow_int_entry(4),
+       dc_underflow_int_entry(5),
+       dc_underflow_int_entry(6),
+       [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(),
+       [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(),
+       vblank_int_entry(0),
+       vblank_int_entry(1),
+       vblank_int_entry(2),
+       vblank_int_entry(3),
+       [DC_IRQ_SOURCE_DC5_VLINE1] = dummy_irq_entry(),
+       [DC_IRQ_SOURCE_DC6_VLINE1] = dummy_irq_entry(),
+       dmub_outbox_int_entry(),
+       vupdate_no_lock_int_entry(0),
+       vupdate_no_lock_int_entry(1),
+       vupdate_no_lock_int_entry(2),
+       vupdate_no_lock_int_entry(3),
+       vline0_int_entry(0),
+       vline0_int_entry(1),
+       vline0_int_entry(2),
+       vline0_int_entry(3),
+       vline1_int_entry(0),
+       vline1_int_entry(1),
+       vline1_int_entry(2),
+       vline1_int_entry(3),
+       vline2_int_entry(0),
+       vline2_int_entry(1),
+       vline2_int_entry(2),
+       vline2_int_entry(3),
+};
+
+static const struct irq_service_funcs irq_service_funcs_dcn42 = {
+       .to_dal_irq_source = to_dal_irq_source_dcn42
+};
+
+static void dcn42_irq_construct(struct irq_service *irq_service,
+                               struct irq_service_init_data *init_data)
+{
+       dal_irq_service_construct(irq_service, init_data);
+       irq_service->info = irq_source_info_dcn42;
+       irq_service->funcs = &irq_service_funcs_dcn42;
+}
+
+struct irq_service *dal_irq_service_dcn42_create(struct irq_service_init_data *init_data)
+{
+       struct irq_service *irq_service = kzalloc(sizeof(*irq_service), GFP_KERNEL);
+
+       if (!irq_service)
+               return NULL;
+
+       dcn42_irq_construct(irq_service, init_data);
+       return irq_service;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.h b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.h
new file mode 100644 (file)
index 0000000..a3f70bc
--- /dev/null
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2025 Advanced Micro Devices, Inc.
+ *
+ * DCN4.2 IRQ service interface (dal-dev only)
+ */
+#ifndef __IRQ_SERVICE_DCN42_H__
+#define __IRQ_SERVICE_DCN42_H__
+
+#include "../dce110/irq_service_dce110.h"
+
+struct irq_service *dal_irq_service_dcn42_create(
+       struct irq_service_init_data *init_data);
+
+#endif /* __IRQ_SERVICE_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.c b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.c
new file mode 100644 (file)
index 0000000..4700bdc
--- /dev/null
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dcn35/dcn35_mmhubbub.h"
+#include "dcn42_mmhubbub.h"
+#include "reg_helper.h"
+
+#define REG(reg)                                                             \
+       ((const struct dcn35_mmhubbub_registers *)(mcif_wb30->mcif_wb_regs)) \
+               ->reg
+
+#define CTX mcif_wb30->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name)                                                \
+       ((const struct dcn35_mmhubbub_shift *)(mcif_wb30->mcif_wb_shift))       \
+               ->field_name,                                                   \
+               ((const struct dcn35_mmhubbub_mask *)(mcif_wb30->mcif_wb_mask)) \
+                       ->field_name
+
+void dcn42_mmhubbub_set_fgcg(struct dcn30_mmhubbub *mcif_wb30, bool enabled)
+{
+       REG_UPDATE(MMHUBBUB_CLOCK_CNTL, MMHUBBUB_FGCG_REP_DIS, !enabled);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.h
new file mode 100644 (file)
index 0000000..0dd1f0d
--- /dev/null
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2026 Advanced Micro Devices, Inc. */
+
+
+#ifndef __DCN42_MMHUBBUB_H
+#define __DCN42_MMHUBBUB_H
+
+#include "mcif_wb.h"
+#include "dcn32/dcn32_mmhubbub.h"
+#include "dcn35/dcn35_mmhubbub.h"
+
+void dcn42_mmhubbub_set_fgcg(struct dcn30_mmhubbub *mcif_wb30, bool enabled);
+#endif // __DCN42_MMHUBBUB_H
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c
new file mode 100644 (file)
index 0000000..304b231
--- /dev/null
@@ -0,0 +1,1121 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "reg_helper.h"
+#include "dc.h"
+#include "dcn42_mpc.h"
+#include "dcn10/dcn10_cm_common.h"
+#include "basics/conversion.h"
+#include "mpc.h"
+
+#define REG(reg)\
+       mpc42->mpc_regs->reg
+
+#define CTX \
+       mpc42->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+       mpc42->mpc_shift->field_name, mpc42->mpc_mask->field_name
+
+
+static void mpc42_init_mpcc(struct mpcc *mpcc, int mpcc_inst)
+{
+       mpcc->mpcc_id = mpcc_inst;
+       mpcc->dpp_id = 0xf;
+       mpcc->mpcc_bot = NULL;
+       mpcc->blnd_cfg.overlap_only = false;
+       mpcc->blnd_cfg.global_alpha = 0xfff;
+       mpcc->blnd_cfg.global_gain = 0xfff;
+       mpcc->blnd_cfg.background_color_bpc = 4;
+       mpcc->blnd_cfg.bottom_gain_mode = 0;
+       mpcc->blnd_cfg.top_gain = 0x1f000;
+       mpcc->blnd_cfg.bottom_inside_gain = 0x1f000;
+       mpcc->blnd_cfg.bottom_outside_gain = 0x1f000;
+       mpcc->sm_cfg.enable = false;
+       mpcc->shared_bottom = false;
+}
+
+void mpc42_update_blending(
+       struct mpc *mpc,
+       struct mpcc_blnd_cfg *blnd_cfg,
+       int mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       struct mpcc *mpcc = mpc1_get_mpcc(mpc, mpcc_id);
+
+       REG_UPDATE_5(MPCC_CONTROL[mpcc_id],
+                       MPCC_ALPHA_BLND_MODE,           blnd_cfg->alpha_mode,
+                       MPCC_ALPHA_MULTIPLIED_MODE,     blnd_cfg->pre_multiplied_alpha,
+                       MPCC_BLND_ACTIVE_OVERLAP_ONLY,  blnd_cfg->overlap_only,
+                       MPCC_BG_BPC,                    blnd_cfg->background_color_bpc,
+                       MPCC_BOT_GAIN_MODE,             blnd_cfg->bottom_gain_mode);
+       REG_UPDATE_2(MPCC_CONTROL2[mpcc_id],
+                       MPCC_GLOBAL_ALPHA,              blnd_cfg->global_alpha,
+                       MPCC_GLOBAL_GAIN,               blnd_cfg->global_gain);
+
+       REG_SET(MPCC_TOP_GAIN[mpcc_id], 0, MPCC_TOP_GAIN, blnd_cfg->top_gain);
+       REG_SET(MPCC_BOT_GAIN_INSIDE[mpcc_id], 0, MPCC_BOT_GAIN_INSIDE, blnd_cfg->bottom_inside_gain);
+       REG_SET(MPCC_BOT_GAIN_OUTSIDE[mpcc_id], 0, MPCC_BOT_GAIN_OUTSIDE, blnd_cfg->bottom_outside_gain);
+
+       mpcc->blnd_cfg = *blnd_cfg;
+}
+
+/* Shaper functions */
+void mpc42_power_on_shaper_3dlut(
+       struct mpc *mpc,
+       uint32_t mpcc_id,
+       bool power_on)
+{
+       uint32_t power_status_shaper = 2;
+       uint32_t power_status_3dlut  = 2;
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+       int max_retries = 10;
+
+       REG_SET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], 0,
+               MPCC_MCM_3DLUT_MEM_PWR_DIS, power_on == true ? 1:0);
+       REG_SET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], 0,
+               MPCC_MCM_SHAPER_MEM_PWR_DIS, power_on == true ? 1:0);
+       /* wait for memory to fully power up */
+       if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
+               REG_WAIT(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_SHAPER_MEM_PWR_STATE, 0, 1, max_retries);
+               REG_WAIT(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_3DLUT_MEM_PWR_STATE, 0, 1, max_retries);
+       }
+
+       /*read status is not mandatory, it is just for debugging*/
+       REG_GET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_SHAPER_MEM_PWR_STATE, &power_status_shaper);
+       REG_GET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_3DLUT_MEM_PWR_STATE, &power_status_3dlut);
+
+       if (power_status_shaper != 0 && power_on == true)
+               BREAK_TO_DEBUGGER();
+
+       if (power_status_3dlut != 0 && power_on == true)
+               BREAK_TO_DEBUGGER();
+}
+
+void mpc42_configure_shaper_lut(
+       struct mpc *mpc,
+       bool is_ram_a,
+       uint32_t mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       REG_UPDATE(MPCC_MCM_SHAPER_SCALE_G_B[mpcc_id],
+               MPCC_MCM_SHAPER_SCALE_B, 0x7000);
+       REG_UPDATE(MPCC_MCM_SHAPER_SCALE_G_B[mpcc_id],
+               MPCC_MCM_SHAPER_SCALE_G, 0x7000);
+       REG_UPDATE(MPCC_MCM_SHAPER_SCALE_R[mpcc_id],
+               MPCC_MCM_SHAPER_SCALE_R, 0x7000);
+       REG_UPDATE(MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id],
+                       MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, 7);
+       REG_UPDATE(MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id],
+                       MPCC_MCM_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
+       REG_SET(MPCC_MCM_SHAPER_LUT_INDEX[mpcc_id], 0, MPCC_MCM_SHAPER_LUT_INDEX, 0);
+}
+
+
+void mpc42_program_3dlut_size(struct mpc *mpc, uint32_t width, int mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+       uint32_t size = 0xff;
+
+       REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE, &size);
+
+       REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE,
+               (width == 33) ? 2 :
+               (width == 17) ? 0 : 2);
+
+       REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE, &size);
+}
+
+void mpc42_program_3dlut_fl_bias_scale(struct mpc *mpc, uint16_t bias, uint16_t scale, int mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       REG_UPDATE_2(MPCC_MCM_3DLUT_OUT_OFFSET_R[mpcc_id],
+               MPCC_MCM_3DLUT_OUT_OFFSET_R, bias,
+               MPCC_MCM_3DLUT_OUT_SCALE_R, scale);
+
+       REG_UPDATE_2(MPCC_MCM_3DLUT_OUT_OFFSET_G[mpcc_id],
+               MPCC_MCM_3DLUT_OUT_OFFSET_G, bias,
+               MPCC_MCM_3DLUT_OUT_SCALE_G, scale);
+
+       REG_UPDATE_2(MPCC_MCM_3DLUT_OUT_OFFSET_B[mpcc_id],
+               MPCC_MCM_3DLUT_OUT_OFFSET_B, bias,
+               MPCC_MCM_3DLUT_OUT_SCALE_B, scale);
+}
+
+void mpc42_program_bit_depth(struct mpc *mpc, uint16_t bit_depth, int mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPCC_MCM_3DLUT_WRITE_EN_MASK, 0xF);
+
+       //program bit_depth
+       REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+               MPCC_MCM_3DLUT_30BIT_EN,
+               (bit_depth == 10) ? 1 : 0);
+}
+
+bool mpc42_is_config_supported(uint32_t width)
+{
+       if (width == 17)
+               return true;
+
+       return false;
+}
+
+void mpc42_populate_lut(struct mpc *mpc, const union mcm_lut_params params,
+       bool lut_bank_a, int mpcc_id)
+{
+       const enum dc_lut_mode next_mode = lut_bank_a ? LUT_RAM_A : LUT_RAM_B;
+       const struct pwl_params *lut_shaper = params.pwl;
+
+       if (lut_shaper == NULL)
+               return;
+       if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
+               mpc42_power_on_shaper_3dlut(mpc, mpcc_id, true);
+
+       mpc42_configure_shaper_lut(mpc, next_mode == LUT_RAM_A, mpcc_id);
+
+       if (next_mode == LUT_RAM_A)
+               mpc32_program_shaper_luta_settings(mpc, lut_shaper, mpcc_id);
+       else
+               mpc32_program_shaper_lutb_settings(mpc, lut_shaper, mpcc_id);
+
+       mpc32_program_shaper_lut(
+                       mpc, lut_shaper->rgb_resulted, lut_shaper->hw_points_num, mpcc_id);
+
+       mpc42_power_on_shaper_3dlut(mpc, mpcc_id, false);
+}
+
+void mpc42_program_lut_read_write_control(struct mpc *mpc, const enum MCM_LUT_ID id,
+       bool lut_bank_a, bool enabled, int mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       switch (id) {
+       case MCM_LUT_3DLUT:
+               REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_MODE,
+                       (!enabled) ? 0 :
+                       (lut_bank_a) ? 1 : 2);
+               REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPCC_MCM_3DLUT_RAM_SEL, lut_bank_a ? 0 : 1);
+               break;
+       case MCM_LUT_SHAPER:
+               mpc32_configure_shaper_lut(mpc, lut_bank_a, mpcc_id);
+               break;
+       default:
+               break;
+       }
+}
+
+/* RMCM Shaper functions */
+void mpc42_power_on_rmcm_shaper_3dlut(
+       struct mpc *mpc,
+       uint32_t mpcc_id,
+       bool power_on)
+{
+       uint32_t power_status_shaper = 2;
+       uint32_t power_status_3dlut  = 2;
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+       int max_retries = 10;
+
+       REG_SET(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], 0,
+               MPC_RMCM_3DLUT_MEM_PWR_DIS, power_on == true ? 0 : 1);
+       REG_SET(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], 0,
+               MPC_RMCM_SHAPER_MEM_PWR_DIS, power_on == true ? 0 : 1);
+       /* wait for memory to fully power up */
+       if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
+               REG_WAIT(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_SHAPER_MEM_PWR_STATE, 0, 1, max_retries);
+               REG_WAIT(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_3DLUT_MEM_PWR_STATE, 0, 1, max_retries);
+       }
+
+       /*read status is not mandatory, it is just for debugging*/
+       REG_GET(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_SHAPER_MEM_PWR_STATE, &power_status_shaper);
+       REG_GET(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_3DLUT_MEM_PWR_STATE, &power_status_3dlut);
+
+       if (power_status_shaper != 0 && power_on == true)
+               BREAK_TO_DEBUGGER();
+
+       if (power_status_3dlut != 0 && power_on == true)
+               BREAK_TO_DEBUGGER();
+}
+
+void mpc42_configure_rmcm_shaper_lut(
+       struct mpc *mpc,
+       bool is_ram_a,
+       uint32_t mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       REG_UPDATE(MPC_RMCM_SHAPER_SCALE_G_B[mpcc_id],
+               MPC_RMCM_SHAPER_SCALE_B, 0x7000);
+       REG_UPDATE(MPC_RMCM_SHAPER_SCALE_G_B[mpcc_id],
+               MPC_RMCM_SHAPER_SCALE_G, 0x7000);
+       REG_UPDATE(MPC_RMCM_SHAPER_SCALE_R[mpcc_id],
+               MPC_RMCM_SHAPER_SCALE_R, 0x7000);
+       REG_UPDATE(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id],
+                       MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, 7);
+       REG_UPDATE(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id],
+                       MPC_RMCM_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
+       REG_SET(MPC_RMCM_SHAPER_LUT_INDEX[mpcc_id], 0, MPC_RMCM_SHAPER_LUT_INDEX, 0);
+}
+
+void mpc42_program_rmcm_shaper_luta_settings(
+       struct mpc *mpc,
+       const struct pwl_params *params,
+       uint32_t mpcc_id)
+{
+       const struct gamma_curve *curve;
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       REG_SET_2(MPC_RMCM_SHAPER_RAMA_START_CNTL_B[mpcc_id], 0,
+               MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
+               MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
+       REG_SET_2(MPC_RMCM_SHAPER_RAMA_START_CNTL_G[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
+       REG_SET_2(MPC_RMCM_SHAPER_RAMA_START_CNTL_R[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
+
+       REG_SET_2(MPC_RMCM_SHAPER_RAMA_END_CNTL_B[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
+       REG_SET_2(MPC_RMCM_SHAPER_RAMA_END_CNTL_G[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y);
+       REG_SET_2(MPC_RMCM_SHAPER_RAMA_END_CNTL_R[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y);
+
+       curve = params->arr_curve_points;
+       if (curve) {
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_0_1[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_2_3[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_4_5[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_6_7[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_8_9[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_10_11[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_12_13[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_14_15[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_16_17[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_18_19[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_20_21[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_22_23[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_24_25[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_26_27[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_28_29[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_30_31[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_32_33[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+       }
+}
+
+
+void mpc42_program_rmcm_shaper_lutb_settings(
+       struct mpc *mpc,
+       const struct pwl_params *params,
+       uint32_t mpcc_id)
+{
+       const struct gamma_curve *curve;
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       REG_SET_2(MPC_RMCM_SHAPER_RAMB_START_CNTL_B[mpcc_id], 0,
+               MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
+               MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0);
+       REG_SET_2(MPC_RMCM_SHAPER_RAMB_START_CNTL_G[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0);
+       REG_SET_2(MPC_RMCM_SHAPER_RAMB_START_CNTL_R[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0);
+
+       REG_SET_2(MPC_RMCM_SHAPER_RAMB_END_CNTL_B[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
+       REG_SET_2(MPC_RMCM_SHAPER_RAMB_END_CNTL_G[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y);
+       REG_SET_2(MPC_RMCM_SHAPER_RAMB_END_CNTL_R[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y);
+
+       curve = params->arr_curve_points;
+       if (curve) {
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_0_1[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_2_3[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_4_5[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_6_7[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_8_9[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                       MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_10_11[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_12_13[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_14_15[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_16_17[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_18_19[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_20_21[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_22_23[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_24_25[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_26_27[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_28_29[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_30_31[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+               curve += 2;
+               REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_32_33[mpcc_id], 0,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+                               MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+       }
+}
+
+void mpc42_program_rmcm_shaper_lut(
+       struct mpc *mpc,
+       const struct pwl_result_data *rgb,
+       uint32_t num,
+       uint32_t mpcc_id)
+{
+       uint32_t i, red, green, blue;
+       uint32_t  red_delta, green_delta, blue_delta;
+       uint32_t  red_value, green_value, blue_value;
+
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       for (i = 0; i < num; i++) {
+
+               red   = rgb[i].red_reg;
+               green = rgb[i].green_reg;
+               blue  = rgb[i].blue_reg;
+
+               red_delta   = rgb[i].delta_red_reg;
+               green_delta = rgb[i].delta_green_reg;
+               blue_delta  = rgb[i].delta_blue_reg;
+
+               red_value   = ((red_delta   & 0x3ff) << 14) | (red   & 0x3fff);
+               green_value = ((green_delta & 0x3ff) << 14) | (green & 0x3fff);
+               blue_value  = ((blue_delta  & 0x3ff) << 14) | (blue  & 0x3fff);
+
+               REG_SET(MPC_RMCM_SHAPER_LUT_DATA[mpcc_id], 0, MPC_RMCM_SHAPER_LUT_DATA, red_value);
+               REG_SET(MPC_RMCM_SHAPER_LUT_DATA[mpcc_id], 0, MPC_RMCM_SHAPER_LUT_DATA, green_value);
+               REG_SET(MPC_RMCM_SHAPER_LUT_DATA[mpcc_id], 0, MPC_RMCM_SHAPER_LUT_DATA, blue_value);
+       }
+}
+
+void mpc42_enable_3dlut_fl(struct mpc *mpc, bool enable, int mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       //if enabled cho0se mpc 0, else: off (default value)
+       REG_UPDATE(MPC_RMCM_CNTL[mpcc_id], MPC_RMCM_CNTL, enable ? 0 : 0xF); //0xF is not connected
+
+       REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPC_RMCM_3DLUT_WRITE_EN_MASK, 0);
+
+       REG_UPDATE(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_3DLUT_MEM_PWR_DIS, enable ? 0 : 3);
+}
+
+void mpc42_update_3dlut_fast_load_select(struct mpc *mpc, int mpcc_id, int hubp_idx)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       REG_SET(MPC_RMCM_3DLUT_FAST_LOAD_SELECT[mpcc_id], 0,
+               MPC_RMCM_3DLUT_FL_SEL,
+               hubp_idx);
+}
+
+void mpc42_populate_rmcm_lut(struct mpc *mpc, const union mcm_lut_params params,
+       bool lut_bank_a, int mpcc_id)
+{
+       const enum dc_lut_mode next_mode = lut_bank_a ? LUT_RAM_A : LUT_RAM_B;
+       const struct pwl_params *lut_shaper = params.pwl;
+
+       if (lut_shaper == NULL)
+               return;
+       if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
+               mpc42_power_on_rmcm_shaper_3dlut(mpc, mpcc_id, true);
+
+       mpc42_configure_rmcm_shaper_lut(mpc, next_mode == LUT_RAM_A, mpcc_id);
+
+       if (next_mode == LUT_RAM_A)
+               mpc42_program_rmcm_shaper_luta_settings(mpc, lut_shaper, mpcc_id);
+       else
+               mpc42_program_rmcm_shaper_lutb_settings(mpc, lut_shaper, mpcc_id);
+
+       mpc42_program_rmcm_shaper_lut(
+                       mpc, lut_shaper->rgb_resulted, lut_shaper->hw_points_num, mpcc_id);
+
+       mpc42_power_on_rmcm_shaper_3dlut(mpc, mpcc_id, false);
+}
+
+void mpc42_program_rmcm_lut_read_write_control(struct mpc *mpc, const enum MCM_LUT_ID id,
+       bool lut_bank_a, bool enabled, int mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       switch (id) {
+       case MCM_LUT_3DLUT:
+               REG_UPDATE(MPC_RMCM_3DLUT_MODE[mpcc_id], MPC_RMCM_3DLUT_MODE,
+                       (!enabled) ? 0 :
+                       (lut_bank_a) ? 1 : 2);
+
+               REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+                       MPC_RMCM_3DLUT_RAM_SEL,
+                       (lut_bank_a) ? 0 : 1);
+               break;
+       case MCM_LUT_SHAPER:
+               REG_UPDATE(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id],
+                       MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, 7);
+
+               REG_UPDATE(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id],
+                       MPC_RMCM_SHAPER_LUT_WRITE_SEL,
+                       lut_bank_a == true ? 0:1);
+
+               REG_SET(MPC_RMCM_SHAPER_LUT_INDEX[mpcc_id], 0,
+                       MPC_RMCM_SHAPER_LUT_INDEX, 0);
+               break;
+       default:
+               break;
+       }
+}
+
+void mpc42_program_lut_mode(struct mpc *mpc, const enum MCM_LUT_XABLE xable,
+       bool lut_bank_a, int mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       switch (xable) {
+       case MCM_LUT_DISABLE:
+               REG_UPDATE(MPC_RMCM_SHAPER_CONTROL[mpcc_id], MPC_RMCM_SHAPER_LUT_MODE, 0);
+               break;
+       case MCM_LUT_ENABLE:
+               REG_UPDATE(MPC_RMCM_SHAPER_CONTROL[mpcc_id], MPC_RMCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2);
+               break;
+       }
+}
+
+void mpc42_program_rmcm_3dlut_size(struct mpc *mpc, uint32_t width, int mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+       uint32_t size = 0xff;
+
+       REG_GET(MPC_RMCM_3DLUT_MODE[mpcc_id], MPC_RMCM_3DLUT_SIZE, &size);
+
+       REG_UPDATE(MPC_RMCM_3DLUT_MODE[mpcc_id], MPC_RMCM_3DLUT_SIZE,
+               (width == 33) ? 2 : 0);
+
+       REG_GET(MPC_RMCM_3DLUT_MODE[mpcc_id], MPC_RMCM_3DLUT_SIZE, &size);
+}
+
+void mpc42_program_rmcm_3dlut_fast_load_bias_scale(struct mpc *mpc, uint16_t bias, uint16_t scale, int mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_R[mpcc_id],
+               MPC_RMCM_3DLUT_OUT_OFFSET_R, bias,
+               MPC_RMCM_3DLUT_OUT_SCALE_R, scale);
+
+       REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_G[mpcc_id],
+               MPC_RMCM_3DLUT_OUT_OFFSET_G, bias,
+               MPC_RMCM_3DLUT_OUT_SCALE_G, scale);
+
+       REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_B[mpcc_id],
+               MPC_RMCM_3DLUT_OUT_OFFSET_B, bias,
+               MPC_RMCM_3DLUT_OUT_SCALE_B, scale);
+}
+
+void mpc42_program_rmcm_bit_depth(struct mpc *mpc, uint16_t bit_depth, int mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPC_RMCM_3DLUT_WRITE_EN_MASK, 0xF);
+
+       //program bit_depth
+       REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+               MPC_RMCM_3DLUT_30BIT_EN,
+               (bit_depth == 10) ? 1 : 0);
+}
+
+bool mpc42_is_rmcm_config_supported(uint32_t width)
+{
+       if (width == 17 || width == 33)
+               return true;
+
+       return false;
+}
+
+void mpc42_set_fl_config(
+       struct mpc *mpc,
+       struct mpc_fl_3dlut_config *cfg,
+       int mpcc_id)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       /*
+       From: Jie Zhou
+
+               To program any of the memories content.  The following sequence is used.
+       Set the MPCC_OGAM/SHAPER/3DLUT/1DLUT_PWR_DIS to 1 (Only need to set the one
+       that is being programmed) Set DISPCLK_G_PIPE<i>_GATE_DISABLE to 1 for the
+       MPCC pipe that’s being used, so the memory’s clock is ungated. Program the
+       target memory. Set the MPCC_OGAM/SHAPER/3DLUT/1DLUT_PWR_DIS back to 0.
+       Set DISPCLK_G_PIPE<i>_GATE_DISABLE back to 0
+       */
+
+       //disconnect fl from mpc
+       REG_SET(MPCC_MCM_3DLUT_FAST_LOAD_SELECT[mpcc_id], 0,
+               MPCC_MCM_3DLUT_FL_SEL, 0xF);
+
+       REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+               MPC_RMCM_3DLUT_WRITE_EN_MASK, 0xF);
+
+       //program bit_depth
+       REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+               MPC_RMCM_3DLUT_30BIT_EN, (cfg->bit_depth == 10) ? 1 : 0);
+
+       REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+               MPC_RMCM_3DLUT_RAM_SEL, (cfg->select_lut_bank_a) ? 0 : 1);
+
+       //bias and scale
+       REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_R[mpcc_id],
+               MPC_RMCM_3DLUT_OUT_OFFSET_R, cfg->bias,
+               MPC_RMCM_3DLUT_OUT_SCALE_R, cfg->scale);
+
+       REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_G[mpcc_id],
+               MPC_RMCM_3DLUT_OUT_OFFSET_G, cfg->bias,
+               MPC_RMCM_3DLUT_OUT_SCALE_G, cfg->scale);
+
+       REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_B[mpcc_id],
+               MPC_RMCM_3DLUT_OUT_OFFSET_B, cfg->bias,
+               MPC_RMCM_3DLUT_OUT_SCALE_B, cfg->scale);
+
+       //width
+       REG_UPDATE_2(MPC_RMCM_3DLUT_MODE[mpcc_id],
+               MPC_RMCM_3DLUT_SIZE, (cfg->width == 33) ? 2 : 0,
+               MPC_RMCM_3DLUT_MODE, (!cfg->enabled) ? 0 : (cfg->select_lut_bank_a) ? 1 : 2);
+
+       //connect to hubp
+       REG_SET(MPC_RMCM_3DLUT_FAST_LOAD_SELECT[mpcc_id], 0,
+               MPC_RMCM_3DLUT_FL_SEL, cfg->hubp_index);
+
+       //ENABLE
+       //if enabled pick mpc 0, else: off (0xF)
+       //in future we'll select specific MPC
+       REG_UPDATE(MPC_RMCM_CNTL[mpcc_id], MPC_RMCM_CNTL, cfg->enabled ? 0 : 0xF);
+}
+
+//static void rmcm_program_gamut_remap(
+//     struct mpc *mpc,
+//     unsigned int mpcc_id,
+//     const uint16_t *regval,
+//     enum mpcc_gamut_remap_id gamut_remap_block_id,
+//     enum mpcc_gamut_remap_mode_select mode_select)
+//{
+//     struct color_matrices_reg gamut_regs;
+//     struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+//
+//     if (gamut_remap_block_id == MPCC_OGAM_GAMUT_REMAP ||
+//             gamut_remap_block_id == MPCC_MCM_FIRST_GAMUT_REMAP ||
+//             gamut_remap_block_id == MPCC_MCM_SECOND_GAMUT_REMAP) {
+//             mpc_program_gamut_remap(mpc, mpcc_id, regval, gamut_remap_block_id, mode_select);
+//             return;
+//     }
+//     if (gamut_remap_block_id == MPCC_OGAM_GAMUT_REMAP) {
+//
+//             if (regval == NULL || mode_select == MPCC_GAMUT_REMAP_MODE_SELECT_0) {
+//                     REG_SET(MPC_RMCM_GAMUT_REMAP_MODE[mpcc_id], 0,
+//                             MPC_RMCM_GAMUT_REMAP_MODE, mode_select);
+//                     return;
+//             }
+//
+//             gamut_regs.shifts.csc_c11 = mpc42->mpc_shift->MPCC_GAMUT_REMAP_C11_A;
+//             gamut_regs.masks.csc_c11 = mpc42->mpc_mask->MPCC_GAMUT_REMAP_C11_A;
+//             gamut_regs.shifts.csc_c12 = mpc42->mpc_shift->MPCC_GAMUT_REMAP_C12_A;
+//             gamut_regs.masks.csc_c12 = mpc42->mpc_mask->MPCC_GAMUT_REMAP_C12_A;
+//
+//             switch (mode_select) {
+//             case MPCC_GAMUT_REMAP_MODE_SELECT_1:
+//                     gamut_regs.csc_c11_c12 = REG(MPC_RMCM_GAMUT_REMAP_C11_C12_A[mpcc_id]);
+//                     gamut_regs.csc_c33_c34 = REG(MPC_RMCM_GAMUT_REMAP_C33_C34_A[mpcc_id]);
+//                     break;
+//             case MPCC_GAMUT_REMAP_MODE_SELECT_2:
+//                     gamut_regs.csc_c11_c12 = REG(MPC_RMCM_GAMUT_REMAP_C11_C12_B[mpcc_id]);
+//                     gamut_regs.csc_c33_c34 = REG(MPC_RMCM_GAMUT_REMAP_C33_C34_B[mpcc_id]);
+//                     break;
+//             default:
+//                     break;
+//             }
+//
+//             cm_helper_program_color_matrices(
+//                     mpc->ctx,
+//                     regval,
+//                     &gamut_regs);
+//
+//             //select coefficient set to use, set A (MODE_1) or set B (MODE_2)
+//             REG_SET(MPC_RMCM_GAMUT_REMAP_MODE[mpcc_id], 0, MPC_RMCM_GAMUT_REMAP_MODE, mode_select);
+//     }
+//}
+
+//static bool is_mpc_legacy_gamut_id(enum mpcc_gamut_remap_id gamut_remap_block_id)
+//{
+//     if (gamut_remap_block_id == MPCC_OGAM_GAMUT_REMAP ||
+//             gamut_remap_block_id == MPCC_MCM_FIRST_GAMUT_REMAP ||
+//             gamut_remap_block_id == MPCC_MCM_SECOND_GAMUT_REMAP) {
+//             return true;
+//     }
+//     return false;
+//}
+//static void program_gamut_remap(
+//     struct mpc *mpc,
+//     unsigned int mpcc_id,
+//     const uint16_t *regval,
+//     enum mpcc_gamut_remap_id gamut_remap_block_id,
+//     enum mpcc_gamut_remap_mode_select mode_select)
+//{
+//     if (is_mpc_legacy_gamut_id(gamut_remap_block_id))
+//             mpc_program_gamut_remap(mpc, mpcc_id, regval, gamut_remap_block_id, mode_select);
+//     else
+//             rmcm_program_gamut_remap(mpc, mpcc_id, regval, gamut_remap_block_id, mode_select);
+//}
+
+//void mpc42_set_gamut_remap(
+//     struct mpc *mpc,
+//     int mpcc_id,
+//     const struct mpc_grph_gamut_adjustment *adjust)
+//{
+//     struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+//     unsigned int i = 0;
+//     uint32_t mode_select = 0;
+//
+//     if (adjust->gamut_adjust_type != GRAPHICS_GAMUT_ADJUST_TYPE_SW) {
+//             /* Bypass / Disable if type is bypass or hw */
+//             program_gamut_remap(mpc, mpcc_id, NULL,
+//                     adjust->mpcc_gamut_remap_block_id, MPCC_GAMUT_REMAP_MODE_SELECT_0);
+//     } else {
+//             struct fixed31_32 arr_matrix[12];
+//             uint16_t arr_reg_val[12];
+//
+//             for (i = 0; i < 12; i++)
+//                     arr_matrix[i] = adjust->temperature_matrix[i];
+//
+//             convert_float_matrix(arr_reg_val, arr_matrix, 12);
+//
+//             if (is_mpc_legacy_gamut_id(adjust->mpcc_gamut_remap_block_id))
+//                     REG_GET(MPCC_GAMUT_REMAP_MODE[mpcc_id],
+//                             MPCC_GAMUT_REMAP_MODE_CURRENT, &mode_select);
+//             else
+//                     REG_GET(MPC_RMCM_GAMUT_REMAP_MODE[mpcc_id],
+//                             MPC_RMCM_GAMUT_REMAP_MODE_CURRENT, &mode_select);
+//
+//             //If current set in use not set A (MODE_1), then use set A, otherwise use set B
+//             if (mode_select != MPCC_GAMUT_REMAP_MODE_SELECT_1)
+//                     mode_select = MPCC_GAMUT_REMAP_MODE_SELECT_1;
+//             else
+//                     mode_select = MPCC_GAMUT_REMAP_MODE_SELECT_2;
+//
+//             program_gamut_remap(mpc, mpcc_id, arr_reg_val,
+//                     adjust->mpcc_gamut_remap_block_id, mode_select);
+//     }
+//}
+
+//static void read_gamut_remap(struct mpc *mpc,
+//     int mpcc_id,
+//     uint16_t *regval,
+//     enum mpcc_gamut_remap_id gamut_remap_block_id,
+//     uint32_t *mode_select)
+//{
+//     struct color_matrices_reg gamut_regs = {0};
+//     struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+//
+//     if (is_mpc_legacy_gamut_id(gamut_remap_block_id)) {
+//             mpc_read_gamut_remap(mpc, mpcc_id, regval, gamut_remap_block_id, mode_select);
+//     }
+//     if (gamut_remap_block_id == MPCC_RMCM_GAMUT_REMAP) {
+//             //current coefficient set in use
+//             REG_GET(MPC_RMCM_GAMUT_REMAP_MODE[mpcc_id], MPC_RMCM_GAMUT_REMAP_MODE, mode_select);
+//
+//             gamut_regs.shifts.csc_c11 = mpc42->mpc_shift->MPCC_GAMUT_REMAP_C11_A;
+//             gamut_regs.masks.csc_c11 = mpc42->mpc_mask->MPCC_GAMUT_REMAP_C11_A;
+//             gamut_regs.shifts.csc_c12 = mpc42->mpc_shift->MPCC_GAMUT_REMAP_C12_A;
+//             gamut_regs.masks.csc_c12 = mpc42->mpc_mask->MPCC_GAMUT_REMAP_C12_A;
+//
+//             switch (*mode_select) {
+//             case MPCC_GAMUT_REMAP_MODE_SELECT_1:
+//                     gamut_regs.csc_c11_c12 = REG(MPC_RMCM_GAMUT_REMAP_C11_C12_A[mpcc_id]);
+//                     gamut_regs.csc_c33_c34 = REG(MPC_RMCM_GAMUT_REMAP_C33_C34_A[mpcc_id]);
+//                     break;
+//             case MPCC_GAMUT_REMAP_MODE_SELECT_2:
+//                     gamut_regs.csc_c11_c12 = REG(MPC_RMCM_GAMUT_REMAP_C11_C12_B[mpcc_id]);
+//                     gamut_regs.csc_c33_c34 = REG(MPC_RMCM_GAMUT_REMAP_C33_C34_B[mpcc_id]);
+//                     break;
+//             default:
+//                     break;
+//             }
+//     }
+//
+//     if (*mode_select != MPCC_GAMUT_REMAP_MODE_SELECT_0) {
+//             cm_helper_read_color_matrices(
+//                     mpc42->base.ctx,
+//                     regval,
+//                     &gamut_regs);
+//     }
+//}
+
+//void mpc42_get_gamut_remap(struct mpc *mpc,
+//     int mpcc_id,
+//     struct mpc_grph_gamut_adjustment *adjust)
+//{
+//     uint16_t arr_reg_val[12] = {0};
+//     uint32_t mode_select;
+//
+//     read_gamut_remap(mpc, mpcc_id, arr_reg_val, adjust->mpcc_gamut_remap_block_id, &mode_select);
+//
+//     if (mode_select == MPCC_GAMUT_REMAP_MODE_SELECT_0) {
+//             adjust->gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
+//             return;
+//     }
+//
+//     adjust->gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
+//     convert_hw_matrix(adjust->temperature_matrix,
+//             arr_reg_val, ARRAY_SIZE(arr_reg_val));
+//}
+
+void mpc42_read_mpcc_state(
+               struct mpc *mpc,
+               int mpcc_inst,
+               struct mpcc_state *s)
+{
+       struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+       mpc1_read_mpcc_state(mpc, mpcc_inst, s);
+
+       if (mpcc_inst < 2) {
+               /* RMCM 3DLUT Status */
+               REG_GET_4(MPC_RMCM_MEM_PWR_CTRL[mpcc_inst], MPC_RMCM_3DLUT_MEM_PWR_FORCE, &s->rmcm_regs.rmcm_3dlut_mem_pwr_force,
+                               MPC_RMCM_3DLUT_MEM_PWR_DIS, &s->rmcm_regs.rmcm_3dlut_mem_pwr_dis,
+                               MPC_RMCM_3DLUT_MEM_LOW_PWR_MODE, &s->rmcm_regs.rmcm_3dlut_mem_pwr_mode,
+                               MPC_RMCM_3DLUT_MEM_PWR_STATE, &s->rmcm_regs.rmcm_3dlut_mem_pwr_state);
+
+               REG_GET_3(MPC_RMCM_3DLUT_MODE[mpcc_inst], MPC_RMCM_3DLUT_SIZE, &s->rmcm_regs.rmcm_3dlut_size,
+                               MPC_RMCM_3DLUT_MODE, &s->rmcm_regs.rmcm_3dlut_mode,
+                               MPC_RMCM_3DLUT_MODE_CURRENT, &s->rmcm_regs.rmcm_3dlut_mode_cur);
+
+               REG_GET_4(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_inst], MPC_RMCM_3DLUT_READ_SEL, &s->rmcm_regs.rmcm_3dlut_read_sel,
+                               MPC_RMCM_3DLUT_30BIT_EN, &s->rmcm_regs.rmcm_3dlut_30bit_en,
+                               MPC_RMCM_3DLUT_WRITE_EN_MASK, &s->rmcm_regs.rmcm_3dlut_wr_en_mask,
+                               MPC_RMCM_3DLUT_RAM_SEL, &s->rmcm_regs.rmcm_3dlut_ram_sel);
+
+               REG_GET(MPC_RMCM_3DLUT_OUT_NORM_FACTOR[mpcc_inst], MPC_RMCM_3DLUT_OUT_NORM_FACTOR, &s->rmcm_regs.rmcm_3dlut_out_norm_factor);
+
+               REG_GET(MPC_RMCM_3DLUT_FAST_LOAD_SELECT[mpcc_inst], MPC_RMCM_3DLUT_FL_SEL, &s->rmcm_regs.rmcm_3dlut_fl_sel);
+
+               REG_GET_2(MPC_RMCM_3DLUT_OUT_OFFSET_R[mpcc_inst], MPC_RMCM_3DLUT_OUT_OFFSET_R, &s->rmcm_regs.rmcm_3dlut_out_offset_r,
+                               MPC_RMCM_3DLUT_OUT_SCALE_R, &s->rmcm_regs.rmcm_3dlut_out_scale_r);
+
+               REG_GET_3(MPC_RMCM_3DLUT_FAST_LOAD_STATUS[mpcc_inst], MPC_RMCM_3DLUT_FL_DONE, &s->rmcm_regs.rmcm_3dlut_fl_done,
+                               MPC_RMCM_3DLUT_FL_SOFT_UNDERFLOW, &s->rmcm_regs.rmcm_3dlut_fl_soft_underflow,
+                               MPC_RMCM_3DLUT_FL_HARD_UNDERFLOW, &s->rmcm_regs.rmcm_3dlut_fl_hard_underflow);
+
+               /* RMCM Shaper Status */
+               REG_GET_4(MPC_RMCM_MEM_PWR_CTRL[mpcc_inst], MPC_RMCM_SHAPER_MEM_PWR_FORCE, &s->rmcm_regs.rmcm_shaper_mem_pwr_force,
+                               MPC_RMCM_SHAPER_MEM_PWR_DIS, &s->rmcm_regs.rmcm_shaper_mem_pwr_dis,
+                               MPC_RMCM_SHAPER_MEM_LOW_PWR_MODE, &s->rmcm_regs.rmcm_shaper_mem_pwr_mode,
+                               MPC_RMCM_SHAPER_MEM_PWR_STATE, &s->rmcm_regs.rmcm_shaper_mem_pwr_state);
+
+               REG_GET_2(MPC_RMCM_SHAPER_CONTROL[mpcc_inst], MPC_RMCM_SHAPER_LUT_MODE, &s->rmcm_regs.rmcm_shaper_lut_mode,
+                               MPC_RMCM_SHAPER_MODE_CURRENT, &s->rmcm_regs.rmcm_shaper_mode_cur);
+
+               REG_GET_2(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_inst], MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, &s->rmcm_regs.rmcm_shaper_lut_write_en_mask,
+                               MPC_RMCM_SHAPER_LUT_WRITE_SEL, &s->rmcm_regs.rmcm_shaper_lut_write_sel);
+
+               REG_GET(MPC_RMCM_SHAPER_OFFSET_B[mpcc_inst], MPC_RMCM_SHAPER_OFFSET_B, &s->rmcm_regs.rmcm_shaper_offset_b);
+
+               REG_GET(MPC_RMCM_SHAPER_SCALE_G_B[mpcc_inst], MPC_RMCM_SHAPER_SCALE_B, &s->rmcm_regs.rmcm_shaper_scale_b);
+
+               REG_GET_2(MPC_RMCM_SHAPER_RAMA_START_CNTL_B[mpcc_inst], MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, &s->rmcm_regs.rmcm_shaper_rama_exp_region_start_b,
+                               MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, &s->rmcm_regs.rmcm_shaper_rama_exp_region_start_seg_b);
+
+               REG_GET_2(MPC_RMCM_SHAPER_RAMA_END_CNTL_B[mpcc_inst], MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, &s->rmcm_regs.rmcm_shaper_rama_exp_region_end_b,
+                               MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, &s->rmcm_regs.rmcm_shaper_rama_exp_region_end_base_b);
+
+               REG_GET(MPC_RMCM_CNTL[mpcc_inst], MPC_RMCM_CNTL, &s->rmcm_regs.rmcm_cntl);
+       }
+}
+
+static const struct mpc_funcs dcn42_mpc_funcs = {
+       .read_mpcc_state = mpc42_read_mpcc_state,
+       .insert_plane = mpc1_insert_plane,
+       .remove_mpcc = mpc1_remove_mpcc,
+       .mpc_init = mpc32_mpc_init,
+       .mpc_init_single_inst = mpc3_mpc_init_single_inst,
+       .update_blending = mpc42_update_blending,
+       .cursor_lock = mpc1_cursor_lock,
+       .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp,
+       .wait_for_idle = mpc2_assert_idle_mpcc,
+       .assert_mpcc_idle_before_connect = mpc2_assert_mpcc_idle_before_connect,
+       .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw,
+       .set_denorm =  mpc3_set_denorm,
+       .set_denorm_clamp = mpc3_set_denorm_clamp,
+       .set_output_csc = mpc3_set_output_csc,
+       .set_ocsc_default = mpc3_set_ocsc_default,
+       .set_output_gamma = mpc3_set_output_gamma,
+       .set_dwb_mux = mpc3_set_dwb_mux,
+       .disable_dwb_mux = mpc3_disable_dwb_mux,
+       .is_dwb_idle = mpc3_is_dwb_idle,
+       .set_gamut_remap = mpc401_set_gamut_remap,
+       .program_shaper = mpc32_program_shaper,
+       .program_3dlut = mpc32_program_3dlut,
+       .program_1dlut = mpc32_program_post1dlut,
+       .power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut,
+       .get_mpc_out_mux = mpc1_get_mpc_out_mux,
+       .mpc_read_reg_state = mpc3_read_reg_state,
+       .set_bg_color = mpc1_set_bg_color,
+       .set_movable_cm_location = mpc401_set_movable_cm_location,
+       .update_3dlut_fast_load_select = mpc401_update_3dlut_fast_load_select,
+       .get_3dlut_fast_load_status = mpc401_get_3dlut_fast_load_status,
+       .populate_lut = mpc401_populate_lut,
+       .program_lut_read_write_control = mpc401_program_lut_read_write_control,
+       .program_lut_mode = mpc401_program_lut_mode,
+       .mcm = {
+               .program_lut_read_write_control = mpc42_program_lut_read_write_control,
+               .program_3dlut_size = mpc42_program_3dlut_size,
+               .program_bias_scale = mpc42_program_3dlut_fl_bias_scale,
+               .program_bit_depth = mpc42_program_bit_depth,
+               .is_config_supported = mpc42_is_config_supported,
+               .populate_lut = mpc42_populate_lut,
+       },
+       .rmcm = {
+               .enable_3dlut_fl = mpc42_enable_3dlut_fl,
+               .update_3dlut_fast_load_select = mpc42_update_3dlut_fast_load_select,
+               .program_lut_read_write_control = mpc42_program_rmcm_lut_read_write_control,
+               .program_lut_mode = mpc42_program_lut_mode,
+               .program_3dlut_size = mpc42_program_rmcm_3dlut_size,
+               .program_bias_scale = mpc42_program_rmcm_3dlut_fast_load_bias_scale,
+               .program_bit_depth = mpc42_program_rmcm_bit_depth,
+               .is_config_supported = mpc42_is_rmcm_config_supported,
+               .power_on_shaper_3dlut = mpc42_power_on_rmcm_shaper_3dlut,
+               .populate_lut = mpc42_populate_rmcm_lut,
+               .fl_3dlut_configure = mpc42_set_fl_config,
+       },
+};
+
+void dcn42_mpc_construct(struct dcn42_mpc *mpc42,
+       struct dc_context *ctx,
+       const struct dcn42_mpc_registers *mpc_regs,
+       const struct dcn42_mpc_shift *mpc_shift,
+       const struct dcn42_mpc_mask *mpc_mask,
+       int num_mpcc,
+       int num_rmu)
+{
+       int i;
+
+       mpc42->base.ctx = ctx;
+
+       mpc42->base.funcs = &dcn42_mpc_funcs;
+
+       mpc42->mpc_regs = mpc_regs;
+       mpc42->mpc_shift = mpc_shift;
+       mpc42->mpc_mask = mpc_mask;
+
+       mpc42->mpcc_in_use_mask = 0;
+       mpc42->num_mpcc = num_mpcc;
+       mpc42->num_rmu = num_rmu;
+
+       for (i = 0; i < MAX_MPCC; i++)
+               mpc42_init_mpcc(&mpc42->base.mpcc_array[i], i);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h
new file mode 100644 (file)
index 0000000..9b87fd2
--- /dev/null
@@ -0,0 +1,1006 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2026 Advanced Micro Devices, Inc. */
+
+#ifndef __DC_MPCC_DCN42_H__
+#define __DC_MPCC_DCN42_H__
+
+#include "dcn401/dcn401_mpc.h"
+
+#define TO_DCN42_MPC(mpc_base) \
+       container_of(mpc_base, struct dcn42_mpc, base)
+
+#define MPC_COMMON_MASK_SH_LIST_DCN42(mask_sh) \
+       SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\
+       SF(MPCC0_MPCC_BOT_SEL, MPCC_BOT_SEL, mask_sh),\
+       SF(MPCC0_MPCC_CONTROL, MPCC_MODE, mask_sh),\
+       SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_BLND_MODE, mask_sh),\
+       SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_MULTIPLIED_MODE, mask_sh),\
+       SF(MPCC0_MPCC_CONTROL, MPCC_BLND_ACTIVE_OVERLAP_ONLY, mask_sh),\
+       SF(MPCC0_MPCC_CONTROL2, MPCC_GLOBAL_ALPHA, mask_sh),\
+       SF(MPCC0_MPCC_CONTROL2, MPCC_GLOBAL_GAIN, mask_sh),\
+       SF(MPCC0_MPCC_STATUS, MPCC_IDLE, mask_sh),\
+       SF(MPCC0_MPCC_STATUS, MPCC_BUSY, mask_sh),\
+       SF(MPCC0_MPCC_OPP_ID, MPCC_OPP_ID, mask_sh),\
+       SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\
+       SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\
+       SF(MPCC0_MPCC_BG_B_CB, MPCC_BG_B_CB, mask_sh),\
+       SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_EN, mask_sh),\
+       SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_MODE, mask_sh),\
+       SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FRAME_ALT, mask_sh),\
+       SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FIELD_ALT, mask_sh),\
+       SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_FRAME_POL, mask_sh),\
+       SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_TOP_POL, mask_sh),\
+       SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh),\
+       SF(MPCC0_MPCC_UPDATE_LOCK_SEL, MPCC_UPDATE_LOCK_SEL, mask_sh),\
+       SF(MPCC0_MPCC_CONTROL, MPCC_BG_BPC, mask_sh),\
+       SF(MPCC0_MPCC_CONTROL, MPCC_BOT_GAIN_MODE, mask_sh),\
+       SF(MPCC0_MPCC_TOP_GAIN, MPCC_TOP_GAIN, mask_sh),\
+       SF(MPCC0_MPCC_BOT_GAIN_INSIDE, MPCC_BOT_GAIN_INSIDE, mask_sh),\
+       SF(MPCC0_MPCC_BOT_GAIN_OUTSIDE, MPCC_BOT_GAIN_OUTSIDE, mask_sh),\
+       SF(MPCC0_MPCC_MOVABLE_CM_LOCATION_CONTROL, MPCC_MOVABLE_CM_LOCATION_CNTL, mask_sh),\
+       SF(MPCC0_MPCC_MOVABLE_CM_LOCATION_CONTROL, MPCC_MOVABLE_CM_LOCATION_CNTL_CURRENT, mask_sh),\
+       SF(MPC_OUT0_CSC_MODE, MPC_OCSC_MODE, mask_sh),\
+       SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C11_A, mask_sh),\
+       SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C12_A, mask_sh),\
+       SF(MPCC0_MPCC_STATUS, MPCC_DISABLED, mask_sh),\
+       SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_FORCE, mask_sh),\
+       SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_DIS, mask_sh),\
+       SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_LOW_PWR_MODE, mask_sh),\
+       SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_STATE, mask_sh),\
+       SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_MODE, mask_sh),\
+       SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MAX_R_CR, mask_sh),\
+       SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MIN_R_CR, mask_sh),\
+       SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MAX_G_Y, mask_sh),\
+       SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MIN_G_Y, mask_sh),\
+       SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MAX_B_CB, mask_sh),\
+       SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MIN_B_CB, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE_CURRENT, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_COEF_FORMAT, MPCC_GAMUT_REMAP_COEF_FORMAT, mask_sh),\
+       SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C11_A, mask_sh),\
+       SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C12_A, mask_sh),\
+       SF(MPC_DWB0_MUX, MPC_DWB0_MUX, mask_sh),\
+       SF(MPC_DWB0_MUX, MPC_DWB0_MUX_STATUS, mask_sh),\
+       SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL, mask_sh),\
+       SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL_DISABLE, mask_sh),\
+       SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_MODE, mask_sh),\
+       SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_COUNT, mask_sh), \
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_B, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL1_B, MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_SLOPE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_BASE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_B, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_B, MPCC_OGAM_RAMA_OFFSET_B, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_G, MPCC_OGAM_RAMA_OFFSET_G, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_R, MPCC_OGAM_RAMA_OFFSET_R, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_LUT_INDEX, MPCC_OGAM_LUT_INDEX, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_PWL_DISABLE, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE_CURRENT, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT_CURRENT, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_WRITE_COLOR_MASK, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_COLOR_SEL, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_HOST_SEL, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_CONFIG_MODE, mask_sh),\
+       SF(MPCC_OGAM0_MPCC_OGAM_LUT_DATA, MPCC_OGAM_LUT_DATA, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_MODE, MPCC_MCM_3DLUT_MODE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_MODE, MPCC_MCM_3DLUT_SIZE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_MODE, MPCC_MCM_3DLUT_MODE_CURRENT, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM_3DLUT_WRITE_EN_MASK, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM_3DLUT_RAM_SEL, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM_3DLUT_30BIT_EN, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM_3DLUT_READ_SEL, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_INDEX, MPCC_MCM_3DLUT_INDEX, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_DATA, MPCC_MCM_3DLUT_DATA0, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_DATA, MPCC_MCM_3DLUT_DATA1, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_DATA_30BIT, MPCC_MCM_3DLUT_DATA_30BIT, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_CONTROL, MPCC_MCM_SHAPER_LUT_MODE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_CONTROL, MPCC_MCM_SHAPER_MODE_CURRENT, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_OFFSET_R, MPCC_MCM_SHAPER_OFFSET_R, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_OFFSET_G, MPCC_MCM_SHAPER_OFFSET_G, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_OFFSET_B, MPCC_MCM_SHAPER_OFFSET_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_SCALE_R, MPCC_MCM_SHAPER_SCALE_R, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_SCALE_G_B, MPCC_MCM_SHAPER_SCALE_G, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_SCALE_G_B, MPCC_MCM_SHAPER_SCALE_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_LUT_INDEX, MPCC_MCM_SHAPER_LUT_INDEX, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_LUT_DATA, MPCC_MCM_SHAPER_LUT_DATA, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, MPCC_MCM_SHAPER_LUT_WRITE_SEL, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_START_CNTL_B, MPCC_MCM_SHAPER_RAMA_EXP_REGION_START_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_START_CNTL_B, MPCC_MCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_END_CNTL_B, MPCC_MCM_SHAPER_RAMA_EXP_REGION_END_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_END_CNTL_B, MPCC_MCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_MODE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_SELECT, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_PWL_DISABLE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_MODE_CURRENT, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_SELECT_CURRENT, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_INDEX, MPCC_MCM_1DLUT_LUT_INDEX, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_DATA, MPCC_MCM_1DLUT_LUT_DATA, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_READ_COLOR_SEL, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_HOST_SEL, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_CONFIG_MODE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_BASE_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_END_CNTL1_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_BASE_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_END_CNTL2_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_END_CNTL2_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_OFFSET_B, MPCC_MCM_1DLUT_RAMA_OFFSET_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM_1DLUT_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM_1DLUT_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM_1DLUT_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM_1DLUT_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_SHAPER_MEM_PWR_FORCE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_SHAPER_MEM_PWR_DIS, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_SHAPER_MEM_LOW_PWR_MODE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_3DLUT_MEM_PWR_FORCE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_3DLUT_MEM_PWR_DIS, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_3DLUT_MEM_LOW_PWR_MODE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_1DLUT_MEM_PWR_FORCE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_1DLUT_MEM_PWR_DIS, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_1DLUT_MEM_LOW_PWR_MODE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_SHAPER_MEM_PWR_STATE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_3DLUT_MEM_PWR_STATE, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_1DLUT_MEM_PWR_STATE, mask_sh),\
+       SF(CUR_VUPDATE_LOCK_SET0, CUR_VUPDATE_LOCK_SET, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_FIRST_GAMUT_REMAP_COEF_FORMAT, MPCC_MCM_FIRST_GAMUT_REMAP_COEF_FORMAT, mask_sh), \
+       SF(MPCC_MCM0_MPCC_MCM_FIRST_GAMUT_REMAP_MODE, MPCC_MCM_FIRST_GAMUT_REMAP_MODE, mask_sh), \
+       SF(MPCC_MCM0_MPCC_MCM_FIRST_GAMUT_REMAP_MODE, MPCC_MCM_FIRST_GAMUT_REMAP_MODE_CURRENT, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C11_C12_A, MPCC_MCM_FIRST_GAMUT_REMAP_C11_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C11_C12_A, MPCC_MCM_FIRST_GAMUT_REMAP_C12_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C13_C14_A, MPCC_MCM_FIRST_GAMUT_REMAP_C13_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C13_C14_A, MPCC_MCM_FIRST_GAMUT_REMAP_C14_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C21_C22_A, MPCC_MCM_FIRST_GAMUT_REMAP_C21_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C21_C22_A, MPCC_MCM_FIRST_GAMUT_REMAP_C22_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C23_C24_A, MPCC_MCM_FIRST_GAMUT_REMAP_C23_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C23_C24_A, MPCC_MCM_FIRST_GAMUT_REMAP_C24_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C31_C32_A, MPCC_MCM_FIRST_GAMUT_REMAP_C31_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C31_C32_A, MPCC_MCM_FIRST_GAMUT_REMAP_C32_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C33_C34_A, MPCC_MCM_FIRST_GAMUT_REMAP_C33_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C33_C34_A, MPCC_MCM_FIRST_GAMUT_REMAP_C34_A, mask_sh), \
+       SF(MPCC_MCM0_MPCC_MCM_SECOND_GAMUT_REMAP_COEF_FORMAT, MPCC_MCM_SECOND_GAMUT_REMAP_COEF_FORMAT, mask_sh), \
+       SF(MPCC_MCM0_MPCC_MCM_SECOND_GAMUT_REMAP_MODE, MPCC_MCM_SECOND_GAMUT_REMAP_MODE, mask_sh), \
+       SF(MPCC_MCM0_MPCC_MCM_SECOND_GAMUT_REMAP_MODE, MPCC_MCM_SECOND_GAMUT_REMAP_MODE_CURRENT, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C11_C12_A, MPCC_MCM_SECOND_GAMUT_REMAP_C11_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C11_C12_A, MPCC_MCM_SECOND_GAMUT_REMAP_C12_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C13_C14_A, MPCC_MCM_SECOND_GAMUT_REMAP_C13_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C13_C14_A, MPCC_MCM_SECOND_GAMUT_REMAP_C14_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C21_C22_A, MPCC_MCM_SECOND_GAMUT_REMAP_C21_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C21_C22_A, MPCC_MCM_SECOND_GAMUT_REMAP_C22_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C23_C24_A, MPCC_MCM_SECOND_GAMUT_REMAP_C23_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C23_C24_A, MPCC_MCM_SECOND_GAMUT_REMAP_C24_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C31_C32_A, MPCC_MCM_SECOND_GAMUT_REMAP_C31_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C31_C32_A, MPCC_MCM_SECOND_GAMUT_REMAP_C32_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C33_C34_A, MPCC_MCM_SECOND_GAMUT_REMAP_C33_A, mask_sh), \
+       SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C33_C34_A, MPCC_MCM_SECOND_GAMUT_REMAP_C34_A, mask_sh), \
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_FAST_LOAD_SELECT, MPCC_MCM_3DLUT_FL_SEL, mask_sh), \
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_FAST_LOAD_STATUS, MPCC_MCM_3DLUT_FL_DONE, mask_sh), \
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_FAST_LOAD_STATUS, MPCC_MCM_3DLUT_FL_SOFT_UNDERFLOW, mask_sh), \
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_FAST_LOAD_STATUS, MPCC_MCM_3DLUT_FL_HARD_UNDERFLOW, mask_sh), \
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_R, MPCC_MCM_3DLUT_OUT_OFFSET_R, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_R, MPCC_MCM_3DLUT_OUT_SCALE_R, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_G, MPCC_MCM_3DLUT_OUT_OFFSET_G, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_G, MPCC_MCM_3DLUT_OUT_SCALE_G, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_B, MPCC_MCM_3DLUT_OUT_OFFSET_B, mask_sh),\
+       SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_B, MPCC_MCM_3DLUT_OUT_SCALE_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_CONTROL, MPC_RMCM_SHAPER_LUT_MODE, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_CONTROL, MPC_RMCM_SHAPER_MODE_CURRENT, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_OFFSET_R, MPC_RMCM_SHAPER_OFFSET_R, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_OFFSET_G, MPC_RMCM_SHAPER_OFFSET_G, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_OFFSET_B, MPC_RMCM_SHAPER_OFFSET_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_SCALE_R, MPC_RMCM_SHAPER_SCALE_R, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_SCALE_G_B, MPC_RMCM_SHAPER_SCALE_G, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_SCALE_G_B, MPC_RMCM_SHAPER_SCALE_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_LUT_INDEX, MPC_RMCM_SHAPER_LUT_INDEX, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_LUT_DATA, MPC_RMCM_SHAPER_LUT_DATA, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, MPC_RMCM_SHAPER_LUT_WRITE_SEL, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_B, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_B, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_G, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_G, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_G, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_R, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_R, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_R, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_B, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_B, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_G, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_G, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_G, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_G, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_R, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_R, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_R, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_R, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM_SHAPER_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM_SHAPER_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM_SHAPER_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM_SHAPER_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM_SHAPER_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM_SHAPER_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM_SHAPER_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM_SHAPER_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM_SHAPER_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM_SHAPER_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM_SHAPER_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM_SHAPER_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM_SHAPER_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM_SHAPER_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM_SHAPER_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM_SHAPER_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM_SHAPER_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM_SHAPER_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM_SHAPER_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM_SHAPER_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM_SHAPER_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM_SHAPER_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM_SHAPER_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM_SHAPER_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM_SHAPER_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM_SHAPER_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM_SHAPER_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM_SHAPER_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM_SHAPER_RAMA_EXP_REGION16_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM_SHAPER_RAMA_EXP_REGION16_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM_SHAPER_RAMA_EXP_REGION17_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM_SHAPER_RAMA_EXP_REGION17_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM_SHAPER_RAMA_EXP_REGION18_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM_SHAPER_RAMA_EXP_REGION18_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM_SHAPER_RAMA_EXP_REGION19_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM_SHAPER_RAMA_EXP_REGION19_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM_SHAPER_RAMA_EXP_REGION20_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM_SHAPER_RAMA_EXP_REGION20_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM_SHAPER_RAMA_EXP_REGION21_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM_SHAPER_RAMA_EXP_REGION21_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM_SHAPER_RAMA_EXP_REGION22_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM_SHAPER_RAMA_EXP_REGION22_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM_SHAPER_RAMA_EXP_REGION23_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM_SHAPER_RAMA_EXP_REGION23_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM_SHAPER_RAMA_EXP_REGION24_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM_SHAPER_RAMA_EXP_REGION24_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM_SHAPER_RAMA_EXP_REGION25_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM_SHAPER_RAMA_EXP_REGION25_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM_SHAPER_RAMA_EXP_REGION26_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM_SHAPER_RAMA_EXP_REGION26_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM_SHAPER_RAMA_EXP_REGION27_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM_SHAPER_RAMA_EXP_REGION27_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM_SHAPER_RAMA_EXP_REGION28_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM_SHAPER_RAMA_EXP_REGION28_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM_SHAPER_RAMA_EXP_REGION29_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM_SHAPER_RAMA_EXP_REGION29_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM_SHAPER_RAMA_EXP_REGION30_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM_SHAPER_RAMA_EXP_REGION30_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM_SHAPER_RAMA_EXP_REGION31_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM_SHAPER_RAMA_EXP_REGION31_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM_SHAPER_RAMA_EXP_REGION32_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM_SHAPER_RAMA_EXP_REGION32_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_B, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_B, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_G, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_G, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_G, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_R, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_R, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_R, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_B, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_B, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_G, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_G, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_G, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_G, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_R, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_R, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_R, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_R, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM_SHAPER_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM_SHAPER_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM_SHAPER_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM_SHAPER_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM_SHAPER_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM_SHAPER_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM_SHAPER_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM_SHAPER_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM_SHAPER_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM_SHAPER_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM_SHAPER_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM_SHAPER_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM_SHAPER_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM_SHAPER_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM_SHAPER_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM_SHAPER_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM_SHAPER_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM_SHAPER_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM_SHAPER_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM_SHAPER_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM_SHAPER_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM_SHAPER_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM_SHAPER_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM_SHAPER_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM_SHAPER_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM_SHAPER_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM_SHAPER_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM_SHAPER_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM_SHAPER_RAMB_EXP_REGION16_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM_SHAPER_RAMB_EXP_REGION16_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM_SHAPER_RAMB_EXP_REGION17_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM_SHAPER_RAMB_EXP_REGION17_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM_SHAPER_RAMB_EXP_REGION18_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM_SHAPER_RAMB_EXP_REGION18_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM_SHAPER_RAMB_EXP_REGION19_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM_SHAPER_RAMB_EXP_REGION19_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM_SHAPER_RAMB_EXP_REGION20_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM_SHAPER_RAMB_EXP_REGION20_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM_SHAPER_RAMB_EXP_REGION21_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM_SHAPER_RAMB_EXP_REGION21_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM_SHAPER_RAMB_EXP_REGION22_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM_SHAPER_RAMB_EXP_REGION22_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM_SHAPER_RAMB_EXP_REGION23_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM_SHAPER_RAMB_EXP_REGION23_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM_SHAPER_RAMB_EXP_REGION24_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM_SHAPER_RAMB_EXP_REGION24_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM_SHAPER_RAMB_EXP_REGION25_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM_SHAPER_RAMB_EXP_REGION25_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM_SHAPER_RAMB_EXP_REGION26_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM_SHAPER_RAMB_EXP_REGION26_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM_SHAPER_RAMB_EXP_REGION27_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM_SHAPER_RAMB_EXP_REGION27_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM_SHAPER_RAMB_EXP_REGION28_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM_SHAPER_RAMB_EXP_REGION28_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM_SHAPER_RAMB_EXP_REGION29_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM_SHAPER_RAMB_EXP_REGION29_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM_SHAPER_RAMB_EXP_REGION30_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM_SHAPER_RAMB_EXP_REGION30_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM_SHAPER_RAMB_EXP_REGION31_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM_SHAPER_RAMB_EXP_REGION31_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM_SHAPER_RAMB_EXP_REGION32_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM_SHAPER_RAMB_EXP_REGION32_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM_SHAPER_RAMB_EXP_REGION33_LUT_OFFSET, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM_SHAPER_RAMB_EXP_REGION33_NUM_SEGMENTS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_MODE, MPC_RMCM_3DLUT_MODE, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_MODE, MPC_RMCM_3DLUT_SIZE, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_MODE, MPC_RMCM_3DLUT_MODE_CURRENT, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_INDEX, MPC_RMCM_3DLUT_INDEX, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_DATA, MPC_RMCM_3DLUT_DATA0, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_DATA, MPC_RMCM_3DLUT_DATA1, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_DATA_30BIT, MPC_RMCM_3DLUT_DATA_30BIT, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM_3DLUT_WRITE_EN_MASK, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM_3DLUT_RAM_SEL, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM_3DLUT_30BIT_EN, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM_3DLUT_READ_SEL, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_NORM_FACTOR, MPC_RMCM_3DLUT_OUT_NORM_FACTOR, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_R, MPC_RMCM_3DLUT_OUT_OFFSET_R, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_R, MPC_RMCM_3DLUT_OUT_SCALE_R, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_G, MPC_RMCM_3DLUT_OUT_OFFSET_G, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_G, MPC_RMCM_3DLUT_OUT_SCALE_G, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_B, MPC_RMCM_3DLUT_OUT_OFFSET_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_B, MPC_RMCM_3DLUT_OUT_SCALE_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_COEF_FORMAT, MPC_RMCM_GAMUT_REMAP_COEF_FORMAT, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_MODE, MPC_RMCM_GAMUT_REMAP_MODE, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_MODE, MPC_RMCM_GAMUT_REMAP_MODE_CURRENT, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C11_C12_A, MPC_RMCM_GAMUT_REMAP_C11_A, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C11_C12_A, MPC_RMCM_GAMUT_REMAP_C12_A, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C13_C14_A, MPC_RMCM_GAMUT_REMAP_C13_A, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C13_C14_A, MPC_RMCM_GAMUT_REMAP_C14_A, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C21_C22_A, MPC_RMCM_GAMUT_REMAP_C21_A, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C21_C22_A, MPC_RMCM_GAMUT_REMAP_C22_A, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C23_C24_A, MPC_RMCM_GAMUT_REMAP_C23_A, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C23_C24_A, MPC_RMCM_GAMUT_REMAP_C24_A, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C31_C32_A, MPC_RMCM_GAMUT_REMAP_C31_A, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C31_C32_A, MPC_RMCM_GAMUT_REMAP_C32_A, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C33_C34_A, MPC_RMCM_GAMUT_REMAP_C33_A, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C33_C34_A, MPC_RMCM_GAMUT_REMAP_C34_A, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C11_C12_B, MPC_RMCM_GAMUT_REMAP_C11_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C11_C12_B, MPC_RMCM_GAMUT_REMAP_C12_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C13_C14_B, MPC_RMCM_GAMUT_REMAP_C13_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C13_C14_B, MPC_RMCM_GAMUT_REMAP_C14_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C21_C22_B, MPC_RMCM_GAMUT_REMAP_C21_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C21_C22_B, MPC_RMCM_GAMUT_REMAP_C22_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C23_C24_B, MPC_RMCM_GAMUT_REMAP_C23_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C23_C24_B, MPC_RMCM_GAMUT_REMAP_C24_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C31_C32_B, MPC_RMCM_GAMUT_REMAP_C31_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C31_C32_B, MPC_RMCM_GAMUT_REMAP_C32_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C33_C34_B, MPC_RMCM_GAMUT_REMAP_C33_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C33_C34_B, MPC_RMCM_GAMUT_REMAP_C34_B, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_SHAPER_MEM_PWR_FORCE, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_SHAPER_MEM_PWR_DIS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_SHAPER_MEM_LOW_PWR_MODE, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_3DLUT_MEM_PWR_FORCE, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_3DLUT_MEM_PWR_DIS, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_3DLUT_MEM_LOW_PWR_MODE, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_SHAPER_MEM_PWR_STATE, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_3DLUT_MEM_PWR_STATE, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_FAST_LOAD_SELECT, MPC_RMCM_3DLUT_FL_SEL, mask_sh),\
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_FAST_LOAD_STATUS, MPC_RMCM_3DLUT_FL_DONE, mask_sh), \
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_FAST_LOAD_STATUS, MPC_RMCM_3DLUT_FL_SOFT_UNDERFLOW, mask_sh), \
+       SF(MPC_RMCM0_MPC_RMCM_3DLUT_FAST_LOAD_STATUS, MPC_RMCM_3DLUT_FL_HARD_UNDERFLOW, mask_sh), \
+       SF(MPC_RMCM0_MPC_RMCM_CNTL, MPC_RMCM_CNTL, mask_sh), \
+       SF(MPC_RMCM0_MPC_RMCM_TEST_DEBUG_INDEX, MPC_RMCM_TEST_DEBUG_INDEX, mask_sh), \
+       SF(MPC_RMCM0_MPC_RMCM_TEST_DEBUG_INDEX, MPC_RMCM_TEST_DEBUG_WRITE_EN, mask_sh), \
+       SF(MPC_RMCM0_MPC_RMCM_TEST_DEBUG_DATA, MPC_RMCM_TEST_DEBUG_DATA, mask_sh)
+
+#define MPC_RMCM_REG_LIST_DCN42(inst)\
+       SRII(MPC_RMCM_SHAPER_CONTROL, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_OFFSET_R, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_OFFSET_G, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_OFFSET_B, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_SCALE_R, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_SCALE_G_B, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_LUT_INDEX, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_LUT_DATA, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_START_CNTL_B, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_START_CNTL_G, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_START_CNTL_R, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_END_CNTL_B, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_END_CNTL_G, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_END_CNTL_R, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_START_CNTL_B, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_START_CNTL_G, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_START_CNTL_R, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_END_CNTL_B, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_END_CNTL_G, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_END_CNTL_R, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_3DLUT_MODE, MPC_RMCM, inst), /*TODO: may need to add other 3DLUT regs*/\
+       SRII(MPC_RMCM_3DLUT_INDEX, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_3DLUT_DATA, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_3DLUT_DATA_30BIT, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_3DLUT_OUT_NORM_FACTOR, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_3DLUT_OUT_OFFSET_R, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_3DLUT_OUT_OFFSET_G, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_3DLUT_OUT_OFFSET_B, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_COEF_FORMAT, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_MODE, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_C11_C12_A, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_C13_C14_A, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_C21_C22_A, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_C23_C24_A, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_C31_C32_A, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_C33_C34_A, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_C11_C12_B, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_C13_C14_B, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_C21_C22_B, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_C23_C24_B, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_C31_C32_B, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_GAMUT_REMAP_C33_C34_B, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_3DLUT_FAST_LOAD_SELECT, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_3DLUT_FAST_LOAD_STATUS, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_CNTL, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_TEST_DEBUG_INDEX, MPC_RMCM, inst),\
+       SRII(MPC_RMCM_TEST_DEBUG_DATA, MPC_RMCM, inst)
+
+
+#define MPC_REG_LIST_DCN42(inst) \
+       MPC_REG_LIST_DCN4_01_RI(inst),\
+       SRII(MPCC_CONTROL2, MPCC, inst)
+
+#define MPC_REG_FIELD_LIST_DCN42(type) \
+       MPC_REG_FIELD_LIST_DCN4_01(type); \
+       type MPCC_MCM_3DLUT_OUT_OFFSET_R;\
+       type MPCC_MCM_3DLUT_OUT_SCALE_R;\
+       type MPCC_MCM_3DLUT_OUT_OFFSET_G;\
+       type MPCC_MCM_3DLUT_OUT_SCALE_G;\
+       type MPCC_MCM_3DLUT_OUT_OFFSET_B;\
+       type MPCC_MCM_3DLUT_OUT_SCALE_B;\
+       type MPC_RMCM_SHAPER_LUT_MODE;\
+       type MPC_RMCM_SHAPER_MODE_CURRENT;\
+       type MPC_RMCM_SHAPER_OFFSET_R;\
+       type MPC_RMCM_SHAPER_OFFSET_G;\
+       type MPC_RMCM_SHAPER_OFFSET_B;\
+       type MPC_RMCM_SHAPER_SCALE_R;\
+       type MPC_RMCM_SHAPER_SCALE_G;\
+       type MPC_RMCM_SHAPER_SCALE_B;\
+       type MPC_RMCM_SHAPER_LUT_INDEX;\
+       type MPC_RMCM_SHAPER_LUT_DATA;\
+       type MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK;\
+       type MPC_RMCM_SHAPER_LUT_WRITE_SEL; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_G; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_R;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_G;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_G;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_R;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_R;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION2_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION2_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION3_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION3_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION4_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION4_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION5_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION5_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION6_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION6_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION7_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION7_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION8_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION8_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION9_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION9_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION10_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION10_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION11_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION11_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION12_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION12_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION13_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION13_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION14_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION14_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION15_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION15_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION16_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION16_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION17_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION17_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION18_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION18_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION19_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION19_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION20_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION20_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION21_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION21_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION22_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION22_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION23_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION23_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION24_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION24_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION25_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION25_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION26_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION26_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION27_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION27_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION28_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION28_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION29_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION29_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION30_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION30_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION31_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION31_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION32_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION32_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_G; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_R;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_G;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_G;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_R;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_R;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION2_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION2_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION3_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION3_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION4_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION4_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION5_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION5_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION6_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION6_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION7_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION7_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION8_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION8_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION9_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION9_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION10_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION10_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION11_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION11_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION12_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION12_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION13_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION13_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION14_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION14_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION15_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION15_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION16_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION16_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION17_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION17_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION18_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION18_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION19_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION19_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION20_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION20_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION21_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION21_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION22_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION22_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION23_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION23_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION24_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION24_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION25_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION25_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION26_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION26_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION27_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION27_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION28_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION28_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION29_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION29_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION30_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION30_NUM_SEGMENTS;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION31_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION31_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION32_LUT_OFFSET; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION32_NUM_SEGMENTS; \
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION33_LUT_OFFSET;\
+       type MPC_RMCM_SHAPER_RAMB_EXP_REGION33_NUM_SEGMENTS;\
+       type MPC_RMCM_3DLUT_MODE;\
+       type MPC_RMCM_3DLUT_SIZE;\
+       type MPC_RMCM_3DLUT_MODE_CURRENT;\
+       type MPC_RMCM_3DLUT_INDEX; \
+       type MPC_RMCM_3DLUT_DATA0; \
+       type MPC_RMCM_3DLUT_DATA1; \
+       type MPC_RMCM_3DLUT_DATA_30BIT; \
+       type MPC_RMCM_3DLUT_WRITE_EN_MASK;\
+       type MPC_RMCM_3DLUT_RAM_SEL;\
+       type MPC_RMCM_3DLUT_30BIT_EN;\
+       type MPC_RMCM_3DLUT_READ_SEL;\
+       type MPC_RMCM_3DLUT_OUT_NORM_FACTOR;\
+       type MPC_RMCM_3DLUT_OUT_OFFSET_R;\
+       type MPC_RMCM_3DLUT_OUT_SCALE_R; \
+       type MPC_RMCM_3DLUT_OUT_OFFSET_G; \
+       type MPC_RMCM_3DLUT_OUT_SCALE_G; \
+       type MPC_RMCM_3DLUT_OUT_OFFSET_B; \
+       type MPC_RMCM_3DLUT_OUT_SCALE_B;\
+       type MPC_RMCM_GAMUT_REMAP_COEF_FORMAT;\
+       type MPC_RMCM_GAMUT_REMAP_MODE;\
+       type MPC_RMCM_GAMUT_REMAP_MODE_CURRENT;\
+       type MPC_RMCM_GAMUT_REMAP_C11_A;\
+       type MPC_RMCM_GAMUT_REMAP_C12_A;\
+       type MPC_RMCM_GAMUT_REMAP_C13_A; \
+       type MPC_RMCM_GAMUT_REMAP_C14_A; \
+       type MPC_RMCM_GAMUT_REMAP_C21_A; \
+       type MPC_RMCM_GAMUT_REMAP_C22_A; \
+       type MPC_RMCM_GAMUT_REMAP_C23_A;\
+       type MPC_RMCM_GAMUT_REMAP_C24_A;\
+       type MPC_RMCM_GAMUT_REMAP_C31_A;\
+       type MPC_RMCM_GAMUT_REMAP_C32_A;\
+       type MPC_RMCM_GAMUT_REMAP_C33_A;\
+       type MPC_RMCM_GAMUT_REMAP_C34_A;\
+       type MPC_RMCM_GAMUT_REMAP_C11_B;\
+       type MPC_RMCM_GAMUT_REMAP_C12_B;\
+       type MPC_RMCM_GAMUT_REMAP_C13_B; \
+       type MPC_RMCM_GAMUT_REMAP_C14_B; \
+       type MPC_RMCM_GAMUT_REMAP_C21_B; \
+       type MPC_RMCM_GAMUT_REMAP_C22_B; \
+       type MPC_RMCM_GAMUT_REMAP_C23_B;\
+       type MPC_RMCM_GAMUT_REMAP_C24_B;\
+       type MPC_RMCM_GAMUT_REMAP_C31_B;\
+       type MPC_RMCM_GAMUT_REMAP_C32_B;\
+       type MPC_RMCM_GAMUT_REMAP_C33_B;\
+       type MPC_RMCM_GAMUT_REMAP_C34_B;\
+       type MPC_RMCM_SHAPER_MEM_PWR_FORCE; \
+       type MPC_RMCM_SHAPER_MEM_PWR_DIS; \
+       type MPC_RMCM_SHAPER_MEM_LOW_PWR_MODE; \
+       type MPC_RMCM_3DLUT_MEM_PWR_FORCE;\
+       type MPC_RMCM_3DLUT_MEM_PWR_DIS;\
+       type MPC_RMCM_3DLUT_MEM_LOW_PWR_MODE;\
+       type MPC_RMCM_SHAPER_MEM_PWR_STATE;\
+       type MPC_RMCM_3DLUT_MEM_PWR_STATE;\
+       type MPC_RMCM_3DLUT_FL_SEL;\
+       type MPC_RMCM_3DLUT_FL_DONE; \
+       type MPC_RMCM_3DLUT_FL_SOFT_UNDERFLOW; \
+       type MPC_RMCM_3DLUT_FL_HARD_UNDERFLOW; \
+       type MPC_RMCM_CNTL; \
+       type MPC_RMCM_TEST_DEBUG_INDEX;\
+       type MPC_RMCM_TEST_DEBUG_WRITE_EN;\
+       type MPC_RMCM_TEST_DEBUG_DATA
+
+#define MPC_REG_VARIABLE_LIST_DCN42 \
+       MPC_REG_VARIABLE_LIST_DCN4_01 \
+       uint32_t MPCC_CONTROL2[MAX_MPCC];\
+       uint32_t MPC_RMCM_SHAPER_CONTROL[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_OFFSET_R[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_OFFSET_G[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_OFFSET_B[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_SCALE_R[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_SCALE_G_B[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_LUT_INDEX[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_LUT_DATA[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_START_CNTL_B[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_START_CNTL_G[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_START_CNTL_R[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_END_CNTL_B[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_END_CNTL_G[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_END_CNTL_R[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_0_1[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_2_3[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_4_5[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_6_7[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_8_9[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_10_11[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_12_13[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_14_15[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_16_17[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_18_19[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_20_21[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_22_23[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_24_25[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_26_27[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_28_29[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_30_31[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMA_REGION_32_33[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_START_CNTL_B[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_START_CNTL_G[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_START_CNTL_R[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_END_CNTL_B[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_END_CNTL_G[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_END_CNTL_R[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_0_1[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_2_3[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_4_5[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_6_7[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_8_9[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_10_11[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_12_13[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_14_15[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_16_17[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_18_19[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_20_21[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_22_23[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_24_25[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_26_27[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_28_29[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_30_31[MAX_MPCC]; \
+       uint32_t MPC_RMCM_SHAPER_RAMB_REGION_32_33[MAX_MPCC]; \
+       uint32_t MPC_RMCM_3DLUT_MODE[MAX_MPCC]; \
+       uint32_t MPC_RMCM_3DLUT_INDEX[MAX_MPCC]; \
+       uint32_t MPC_RMCM_3DLUT_DATA[MAX_MPCC]; \
+       uint32_t MPC_RMCM_3DLUT_DATA_30BIT[MAX_MPCC]; \
+       uint32_t MPC_RMCM_3DLUT_READ_WRITE_CONTROL[MAX_MPCC]; \
+       uint32_t MPC_RMCM_3DLUT_OUT_NORM_FACTOR[MAX_MPCC]; \
+       uint32_t MPC_RMCM_3DLUT_OUT_OFFSET_R[MAX_MPCC]; \
+       uint32_t MPC_RMCM_3DLUT_OUT_OFFSET_G[MAX_MPCC]; \
+       uint32_t MPC_RMCM_3DLUT_OUT_OFFSET_B[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_COEF_FORMAT[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_MODE[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_C11_C12_A[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_C13_C14_A[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_C21_C22_A[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_C23_C24_A[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_C31_C32_A[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_C33_C34_A[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_C11_C12_B[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_C13_C14_B[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_C21_C22_B[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_C23_C24_B[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_C31_C32_B[MAX_MPCC]; \
+       uint32_t MPC_RMCM_GAMUT_REMAP_C33_C34_B[MAX_MPCC]; \
+       uint32_t MPC_RMCM_MEM_PWR_CTRL[MAX_MPCC]; \
+       uint32_t MPC_RMCM_3DLUT_FAST_LOAD_SELECT[MAX_MPCC]; \
+       uint32_t MPC_RMCM_3DLUT_FAST_LOAD_STATUS[MAX_MPCC]; \
+       uint32_t MPC_RMCM_CNTL[MAX_MPCC]; \
+       uint32_t MPC_RMCM_TEST_DEBUG_INDEX[MAX_MPCC]; \
+       uint32_t MPC_RMCM_TEST_DEBUG_DATA[MAX_MPCC]
+
+struct dcn42_mpc_shift {
+       MPC_REG_FIELD_LIST_DCN42(uint8_t);
+};
+
+struct dcn42_mpc_mask {
+       MPC_REG_FIELD_LIST_DCN42(uint32_t);
+};
+
+struct dcn42_mpc_registers {
+       MPC_REG_VARIABLE_LIST_DCN42;
+};
+
+struct dcn42_mpc {
+       struct mpc base;
+
+       int mpcc_in_use_mask;
+       int num_mpcc;
+       const struct dcn42_mpc_registers *mpc_regs;
+       const struct dcn42_mpc_shift *mpc_shift;
+       const struct dcn42_mpc_mask *mpc_mask;
+       int num_rmu;
+};
+void dcn42_mpc_construct(struct dcn42_mpc *mpc401,
+       struct dc_context *ctx,
+       const struct dcn42_mpc_registers *mpc_regs,
+       const struct dcn42_mpc_shift *mpc_shift,
+       const struct dcn42_mpc_mask *mpc_mask,
+       int num_mpcc,
+       int num_rmu);
+
+
+void mpc42_program_shaper_lutb_settings(
+       struct mpc *mpc,
+       const struct pwl_params *params,
+       uint32_t mpcc_id);
+void mpc42_program_shaper_luta_settings(
+               struct mpc *mpc,
+               const struct pwl_params *params,
+               uint32_t mpcc_id);
+void mpc42_configure_shaper_lut(
+               struct mpc *mpc,
+               bool is_ram_a,
+               uint32_t mpcc_id);
+void mpc42_power_on_shaper_3dlut(
+               struct mpc *mpc,
+               uint32_t mpcc_id,
+               bool power_on);
+void mpc42_program_3dlut_size(
+               struct mpc *mpc,
+               uint32_t width,
+               int mpcc_id);
+void mpc42_program_3dlut_fl_bias_scale(
+               struct mpc *mpc,
+               uint16_t bias,
+               uint16_t scale,
+               int mpcc_id);
+void mpc42_program_bit_depth(
+               struct mpc *mpc,
+               uint16_t bit_depth,
+               int mpcc_id);
+void mpc42_populate_lut(
+               struct mpc *mpc,
+               const union mcm_lut_params params,
+               bool lut_bank_a,
+               int mpcc_id);
+void mpc42_program_lut_read_write_control(
+               struct mpc *mpc,
+               const enum MCM_LUT_ID id,
+               bool lut_bank_a,
+               bool enabled,
+               int mpcc_id);
+
+bool mpc42_is_config_supported(uint32_t width);
+
+/* RMCM */
+void mpc42_program_rmcm_shaper_lut(
+               struct mpc *mpc,
+               const struct pwl_result_data *rgb,
+               uint32_t num,
+               uint32_t mpcc_id);
+void mpc42_program_rmcm_shaper_lutb_settings(
+               struct mpc *mpc,
+               const struct pwl_params *params,
+               uint32_t mpcc_id);
+void mpc42_program_rmcm_shaper_luta_settings(
+               struct mpc *mpc,
+               const struct pwl_params *params,
+               uint32_t mpcc_id);
+void mpc42_configure_rmcm_shaper_lut(
+               struct mpc *mpc,
+               bool is_ram_a,
+               uint32_t mpcc_id);
+void mpc42_power_on_rmcm_shaper_3dlut(
+               struct mpc *mpc,
+               uint32_t mpcc_id,
+               bool power_on);
+void mpc42_enable_3dlut_fl(
+               struct mpc *mpc,
+               bool enable,
+               int mpcc_id);
+void mpc42_update_3dlut_fast_load_select(
+               struct mpc *mpc,
+               int mpcc_id,
+               int hubp_idx);
+void mpc42_populate_rmcm_lut(
+               struct mpc *mpc,
+               const union mcm_lut_params params,
+               bool lut_bank_a,
+               int mpcc_id);
+void mpc42_program_rmcm_lut_read_write_control(
+               struct mpc *mpc,
+               const enum MCM_LUT_ID id,
+               bool lut_bank_a,
+               bool enabled,
+               int mpcc_id);
+void mpc42_program_lut_mode(
+               struct mpc *mpc,
+               const enum MCM_LUT_XABLE xable,
+               bool lut_bank_a,
+               int mpcc_id);
+void mpc42_program_rmcm_3dlut_size(
+               struct mpc *mpc,
+               uint32_t width,
+               int mpcc_id);
+void mpc42_program_rmcm_3dlut_fast_load_bias_scale(
+               struct mpc *mpc,
+               uint16_t bias,
+               uint16_t scale,
+               int mpcc_id);
+void mpc42_program_rmcm_bit_depth(
+               struct mpc *mpc,
+               uint16_t bit_depth,
+               int mpcc_id);
+
+bool mpc42_is_rmcm_config_supported(uint32_t width);
+
+void mpc42_set_fl_config(
+       struct mpc *mpc,
+       struct mpc_fl_3dlut_config *cfg,
+       int mpcc_id);
+
+void mpc42_read_mpcc_state(
+               struct mpc *mpc,
+               int mpcc_inst,
+               struct mpcc_state *s);
+
+void mpc42_update_blending(
+       struct mpc *mpc,
+       struct mpcc_blnd_cfg *blnd_cfg,
+       int mpcc_id);
+
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c
new file mode 100644 (file)
index 0000000..effd05b
--- /dev/null
@@ -0,0 +1,198 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dcn42_optc.h"
+#include "dcn30/dcn30_optc.h"
+#include "dcn31/dcn31_optc.h"
+#include "dcn32/dcn32_optc.h"
+#include "dcn401/dcn401_optc.h"
+#include "reg_helper.h"
+#include "dc.h"
+#include "dcn_calc_math.h"
+#include "dc_dmub_srv.h"
+
+#define REG(reg)\
+       optc1->tg_regs->reg
+
+#define CTX \
+       optc1->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+       optc1->tg_shift->field_name, optc1->tg_mask->field_name
+
+/*
+ * optc42_get_crc - Capture CRC result per component
+ *
+ * @optc: timing_generator instance.
+ * @r_cr: 16-bit primary CRC signature for red data.
+ * @g_y: 16-bit primary CRC signature for green data.
+ * @b_cb: 16-bit primary CRC signature for blue data.
+ *
+ * This function reads the CRC signature from the OPTC registers. Notice that
+ * we have three registers to keep the CRC result per color component (RGB).
+ *
+ * Returns:
+ * If CRC is disabled, return false; otherwise, return true, and the CRC
+ * results in the parameters.
+ */
+
+static bool optc42_get_crc(struct timing_generator *optc, uint8_t idx,
+                  uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
+{
+       uint32_t field = 0;
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+       REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field);
+
+       /* Early return if CRC is not enabled for this CRTC */
+       if (!field)
+               return false;
+
+
+       switch (idx) {
+       case 0:
+               /* OTG_CRC0_DATA_RG has the CRC16 results for the red component */
+               REG_GET(OTG_CRC0_DATA_R,
+                       CRC0_R_CR, r_cr);
+
+               /* OTG_CRC0_DATA_RG has the CRC16 results for the green component */
+               REG_GET(OTG_CRC0_DATA_G,
+                       CRC0_G_Y, g_y);
+
+               /* OTG_CRC0_DATA_B has the CRC16 results for the blue component */
+               REG_GET(OTG_CRC0_DATA_B,
+                       CRC0_B_CB, b_cb);
+               break;
+       case 1:
+               /* OTG_CRC1_DATA_RG has the CRC16 results for the red component */
+               REG_GET(OTG_CRC1_DATA_R,
+                       CRC0_R_CR, r_cr);
+
+               /* OTG_CRC1_DATA_RG has the CRC16 results for the green component */
+               REG_GET(OTG_CRC1_DATA_G,
+                       CRC0_G_Y, g_y);
+
+               /* OTG_CRC1_DATA_B has the CRC16 results for the blue component */
+               REG_GET(OTG_CRC1_DATA_B,
+                       CRC0_B_CB, b_cb);
+               break;
+       default:
+               return false;
+       }
+       return true;
+}
+
+void optc42_enable_pwa(struct timing_generator *optc, struct otc_pwa_frame_sync *pwa_sync_param)
+{
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+       /*VCOUNT_MODE :
+       00      OTG_PWA_FRAME_SYNC_VCOUNT_0     Vcount counting from VSYNC.
+       01      OTG_PWA_FRAME_SYNC_VCOUNT_1     Vcount counting from VSTARTUP.*/
+
+       if (pwa_sync_param == NULL)
+               return;
+       if (optc1->base.ctx->dc->debug.enable_otg_frame_sync_pwa) {
+               /*take mode 1, use line number from vstartup to get output frame as earlier as possible*/
+               REG_UPDATE_3(OTG_PWA_FRAME_SYNC_CONTROL,
+                       OTG_PWA_FRAME_SYNC_EN, 1,
+                       OTG_PWA_FRAME_SYNC_VCOUNT_MODE, pwa_sync_param->pwa_sync_mode,
+                       OTG_PWA_FRAME_SYNC_LINE, pwa_sync_param->pwa_frame_sync_line_offset);
+       }
+}
+void  optc42_disable_pwa(struct timing_generator *optc)
+{
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+       REG_UPDATE(OTG_PWA_FRAME_SYNC_CONTROL,
+                       OTG_PWA_FRAME_SYNC_EN, 0);
+}
+
+static struct timing_generator_funcs dcn42_tg_funcs = {
+               .validate_timing = optc1_validate_timing,
+               .program_timing = optc1_program_timing,
+               .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
+               .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
+               .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
+               .program_global_sync = optc401_program_global_sync,
+               .enable_crtc = optc401_enable_crtc,
+               .disable_crtc = optc401_disable_crtc,
+               .phantom_crtc_post_enable = optc401_phantom_crtc_post_enable,
+               .disable_phantom_crtc = optc401_disable_phantom_otg,
+               /* used by enable_timing_synchronization. Not need for FPGA */
+               .is_counter_moving = optc1_is_counter_moving,
+               .get_position = optc1_get_position,
+               .get_frame_count = optc1_get_vblank_counter,
+               .get_scanoutpos = optc1_get_crtc_scanoutpos,
+               .get_otg_active_size = optc1_get_otg_active_size,
+               .set_early_control = optc1_set_early_control,
+               /* used by enable_timing_synchronization. Not need for FPGA */
+               .wait_for_state = optc1_wait_for_state,
+               .set_blank_color = optc3_program_blank_color,
+               .did_triggered_reset_occur = optc1_did_triggered_reset_occur,
+               .triplebuffer_lock = optc3_triplebuffer_lock,
+               .triplebuffer_unlock = optc2_triplebuffer_unlock,
+               .enable_reset_trigger = optc1_enable_reset_trigger,
+               .enable_crtc_reset = optc1_enable_crtc_reset,
+               .disable_reset_trigger = optc1_disable_reset_trigger,
+               .lock = optc3_lock,
+               .unlock = optc1_unlock,
+               .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable,
+               .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,
+               .enable_optc_clock = optc1_enable_optc_clock,
+               .set_drr = optc401_set_drr,
+               .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
+               .set_vtotal_min_max = optc401_set_vtotal_min_max,
+               .set_static_screen_control = optc1_set_static_screen_control,
+               .program_stereo = optc1_program_stereo,
+               .is_stereo_left_eye = optc1_is_stereo_left_eye,
+               .tg_init = optc3_tg_init,
+               .is_tg_enabled = optc1_is_tg_enabled,
+               .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
+               .clear_optc_underflow = optc1_clear_optc_underflow,
+               .setup_global_swap_lock = NULL,
+               .get_crc = optc42_get_crc,
+               .configure_crc = optc1_configure_crc,
+               .set_dsc_config = optc3_set_dsc_config,
+               .get_dsc_status = optc2_get_dsc_status,
+               .set_dwb_source = NULL,
+               .set_odm_bypass = optc401_set_odm_bypass,
+               .set_odm_combine = optc401_set_odm_combine,
+               .wait_odm_doublebuffer_pending_clear = optc32_wait_odm_doublebuffer_pending_clear,
+               .set_h_timing_div_manual_mode = optc401_set_h_timing_div_manual_mode,
+               .get_optc_source = optc2_get_optc_source,
+               .set_out_mux = optc401_set_out_mux,
+               .set_drr_trigger_window = optc3_set_drr_trigger_window,
+               .set_vtotal_change_limit = optc3_set_vtotal_change_limit,
+               .set_gsl = optc2_set_gsl,
+               .set_gsl_source_select = optc2_set_gsl_source_select,
+               .set_vtg_params = optc1_set_vtg_params,
+               .program_manual_trigger = optc2_program_manual_trigger,
+               .setup_manual_trigger = optc2_setup_manual_trigger,
+               .get_hw_timing = optc1_get_hw_timing,
+               .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
+               .get_optc_double_buffer_pending = optc3_get_optc_double_buffer_pending,
+               .get_otg_double_buffer_pending = optc3_get_otg_update_pending,
+               .get_pipe_update_pending = optc3_get_pipe_update_pending,
+               .set_vupdate_keepout = optc401_set_vupdate_keepout,
+               .wait_update_lock_status = optc401_wait_update_lock_status,
+               .optc_read_reg_state = optc31_read_reg_state,
+               .enable_otg_pwa = optc42_enable_pwa,
+               .disable_otg_pwa = optc42_disable_pwa,
+};
+
+void dcn42_timing_generator_init(struct optc *optc1)
+{
+       optc1->base.funcs = &dcn42_tg_funcs;
+
+       optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
+       optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
+
+       optc1->min_h_blank = 32;
+       optc1->min_v_blank = 3;
+       optc1->min_v_blank_interlace = 5;
+       optc1->min_h_sync_width = 4;
+       optc1->min_v_sync_width = 1;
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h
new file mode 100644 (file)
index 0000000..45d2187
--- /dev/null
@@ -0,0 +1,211 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2024 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 __DC_OPTC_DCN42_H__
+#define __DC_OPTC_DCN42_H__
+
+#include "dcn10/dcn10_optc.h"
+
+#define OPTC_COMMON_MASK_SH_LIST_DCN42(mask_sh)\
+       SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\
+       SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\
+       SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\
+       SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\
+       SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\
+       SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\
+       SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_START_X, mask_sh),\
+       SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_END_X, mask_sh),\
+       SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\
+       SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_START_Y, mask_sh),\
+       SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_END_Y, mask_sh),\
+       SF(OTG0_OTG_GLOBAL_CONTROL2, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\
+       SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_X, mask_sh),\
+       SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_Y, mask_sh),\
+       SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\
+       SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\
+       SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\
+       SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\
+       SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\
+       SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\
+       SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\
+       SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\
+       SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\
+       SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\
+       SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\
+       SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\
+       SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, mask_sh),\
+       SF(OTG0_OTG_CONTROL, OTG_CURRENT_MASTER_EN_STATE, mask_sh),\
+       SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\
+       SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\
+       SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\
+       SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\
+       SF(OTG0_OTG_CONTROL, OTG_OUT_MUX, mask_sh),\
+       SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\
+       SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\
+       SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\
+       SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\
+       SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\
+       SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\
+       SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\
+       SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\
+       SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\
+       SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\
+       SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\
+       SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\
+       SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\
+       SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\
+       SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\
+       SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MIN_EN, mask_sh),\
+       SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\
+       SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\
+       SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\
+       SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\
+       SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\
+       SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\
+       SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\
+       SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\
+       SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\
+       SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\
+       SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\
+       SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\
+       SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\
+       SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\
+       SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\
+       SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\
+       SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\
+       SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\
+       SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\
+       SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\
+       SF(OTG0_OTG_M_CONST_DTO0, OTG_M_CONST_DTO_PHASE, mask_sh),\
+       SF(OTG0_OTG_M_CONST_DTO1, OTG_M_CONST_DTO_MODULO, mask_sh),\
+       SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\
+       SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\
+       SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\
+       SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\
+       SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\
+       SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\
+       SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\
+       SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\
+       SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\
+       SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\
+       SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\
+       SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\
+       SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\
+       SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\
+       SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\
+       SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_DOUBLE_BUFFER_PENDING, mask_sh),\
+       SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\
+       SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\
+       SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\
+       SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\
+       SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\
+       SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\
+       SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\
+       SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\
+       SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\
+       SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\
+       SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\
+       SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\
+       SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\
+       SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\
+       SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\
+       SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\
+       SF(OTG0_OTG_CRC0_DATA_R, CRC0_R_CR, mask_sh),\
+       SF(OTG0_OTG_CRC0_DATA_G, CRC0_G_Y, mask_sh),\
+       SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\
+       SF(OTG0_OTG_CRC1_DATA_R, CRC1_R_CR, mask_sh),\
+       SF(OTG0_OTG_CRC1_DATA_G, CRC1_G_Y, mask_sh),\
+       SF(OTG0_OTG_CRC1_DATA_B, CRC1_B_CB, mask_sh),\
+       SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\
+       SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\
+       SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\
+       SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\
+       SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\
+       SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\
+       SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\
+       SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\
+       SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_START, mask_sh),\
+       SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_END, mask_sh),\
+       SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_START, mask_sh),\
+       SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_END, mask_sh),\
+       SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_START, mask_sh),\
+       SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_END, mask_sh),\
+       SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_START, mask_sh),\
+       SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_END, mask_sh),\
+       SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\
+       SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\
+       SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\
+       SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\
+       SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh),\
+       SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\
+       SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\
+       SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \
+       SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\
+       SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\
+       SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \
+       SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \
+       SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \
+       SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \
+       SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \
+       SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\
+       SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\
+       SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG2_SRC_SEL, mask_sh),\
+       SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG3_SRC_SEL, mask_sh),\
+       SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\
+       SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\
+       SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\
+       SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\
+       SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\
+       SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\
+       SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\
+       SF(ODM0_OPTC_WIDTH_CONTROL2, OPTC_SEGMENT_WIDTH_LAST, mask_sh),\
+       SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\
+       SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\
+       SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\
+       SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\
+       SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE_MANUAL, mask_sh),\
+       SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\
+       SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh),\
+       SF(OTG0_OTG_PSTATE_REGISTER, OTG_PSTATE_KEEPOUT_START, mask_sh),\
+       SF(OTG0_OTG_PSTATE_REGISTER, OTG_PSTATE_EXTEND, mask_sh),\
+       SF(OTG0_OTG_PSTATE_REGISTER, OTG_UNBLANK, mask_sh),\
+       SF(OTG0_OTG_PSTATE_REGISTER, OTG_PSTATE_ALLOW_WIDTH_MIN, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_FLIP_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_DC_REG_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_CURSOR_UPDATE_PENDING, mask_sh),\
+       SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_VUPDATE_KEEPOUT_STATUS, mask_sh),\
+       SF(OTG0_OTG_PWA_FRAME_SYNC_CONTROL, OTG_PWA_FRAME_SYNC_EN, mask_sh),\
+       SF(OTG0_OTG_PWA_FRAME_SYNC_CONTROL, OTG_PWA_FRAME_SYNC_VCOUNT_MODE, mask_sh),\
+       SF(OTG0_OTG_PWA_FRAME_SYNC_CONTROL, OTG_PWA_FRAME_SYNC_LINE, mask_sh),\
+       SF(OTG0_INTERRUPT_DEST, OTG0_IHC_OTG_VERTICAL_INTERRUPT2_DEST, mask_sh)
+
+void dcn42_timing_generator_init(struct optc *optc1);
+void optc42_enable_pwa(struct timing_generator *optc, struct otc_pwa_frame_sync *pwa_sync_param);
+void optc42_disable_pwa(struct timing_generator *optc);
+
+#endif /* __DC_OPTC_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c
new file mode 100644 (file)
index 0000000..3685080
--- /dev/null
@@ -0,0 +1,648 @@
+// SPDX-License-Identifier: MIT
+
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "reg_helper.h"
+#include "core_types.h"
+#include "dcn42_pg_cntl.h"
+#include "dccg.h"
+
+#define TO_DCN_PG_CNTL(pg_cntl)\
+       container_of(pg_cntl, struct dcn_pg_cntl, base)
+
+#define REG(reg) \
+       (pg_cntl_dcn->regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+       pg_cntl_dcn->pg_cntl_shift->field_name, pg_cntl_dcn->pg_cntl_mask->field_name
+
+#define CTX \
+       pg_cntl_dcn->base.ctx
+#define DC_LOGGER \
+       pg_cntl->ctx->logger
+
+static bool pg_cntl42_dsc_pg_status(struct pg_cntl *pg_cntl, unsigned int dsc_inst)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t pwr_status = 0;
+
+       if (pg_cntl->ctx->dc->debug.ignore_pg)
+               return true;
+
+       switch (dsc_inst) {
+       case 0: /* DSC0 */
+               REG_GET(DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+               break;
+       case 1: /* DSC1 */
+               REG_GET(DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+               break;
+       case 2: /* DSC2 */
+               REG_GET(DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+               break;
+       case 3: /* DSC3 */
+               REG_GET(DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               break;
+       }
+
+       return pwr_status == 0;
+}
+
+void pg_cntl42_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bool power_on)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t power_gate = power_on ? 0 : 1;
+       uint32_t pwr_status = power_on ? 0 : 2;
+       uint32_t org_ip_request_cntl = 0;
+       bool block_enabled;
+
+       /*need to enable dscclk regardless DSC_PG*/
+       if (pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc && power_on)
+               pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc(
+                               pg_cntl->ctx->dc->res_pool->dccg, dsc_inst);
+
+       if (pg_cntl->ctx->dc->debug.ignore_pg ||
+               pg_cntl->ctx->dc->debug.disable_dsc_power_gate ||
+               pg_cntl->ctx->dc->idle_optimizations_allowed)
+               return;
+
+       block_enabled = pg_cntl42_dsc_pg_status(pg_cntl, dsc_inst);
+       if (power_on) {
+               if (block_enabled)
+                       return;
+       } else {
+               if (!block_enabled)
+                       return;
+       }
+
+       REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+       if (org_ip_request_cntl == 0)
+               REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+       if (power_on) {
+               if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+                       pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, false);
+       }
+       switch (dsc_inst) {
+       case 0: /* DSC0 */
+               REG_UPDATE(DOMAIN16_PG_CONFIG,
+                               DOMAIN_POWER_GATE, power_gate);
+
+               REG_WAIT(DOMAIN16_PG_STATUS,
+                               DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+                               1, 1000);
+               break;
+       case 1: /* DSC1 */
+               REG_UPDATE(DOMAIN17_PG_CONFIG,
+                               DOMAIN_POWER_GATE, power_gate);
+
+               REG_WAIT(DOMAIN17_PG_STATUS,
+                               DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+                               1, 1000);
+               break;
+       case 2: /* DSC2 */
+               REG_UPDATE(DOMAIN18_PG_CONFIG,
+                               DOMAIN_POWER_GATE, power_gate);
+
+               REG_WAIT(DOMAIN18_PG_STATUS,
+                               DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+                               1, 1000);
+               break;
+       case 3: /* DSC3 */
+               REG_UPDATE(DOMAIN19_PG_CONFIG,
+                               DOMAIN_POWER_GATE, power_gate);
+
+               REG_WAIT(DOMAIN19_PG_STATUS,
+                               DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+                               1, 1000);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               break;
+       }
+
+       if (power_on) {
+               if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+                       pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, true);
+       }
+
+       if (dsc_inst < MAX_PIPES)
+               pg_cntl->pg_pipe_res_enable[PG_DSC][dsc_inst] = power_on;
+
+       if (pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc && !power_on) {
+               /*this is to disable dscclk*/
+               pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc(
+                       pg_cntl->ctx->dc->res_pool->dccg, dsc_inst);
+       }
+}
+
+static bool pg_cntl42_hubp_dpp_pg_status(struct pg_cntl *pg_cntl, unsigned int hubp_dpp_inst)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t pwr_status = 0;
+
+       switch (hubp_dpp_inst) {
+       case 0:
+               /* DPP0 & HUBP0 */
+               REG_GET(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+               break;
+       case 1:
+               /* DPP1 & HUBP1 */
+               REG_GET(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+               break;
+       case 2:
+               /* DPP2 & HUBP2 */
+               REG_GET(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+               break;
+       case 3:
+               /* DPP3 & HUBP3 */
+               REG_GET(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               break;
+       }
+
+       return pwr_status == 0;
+}
+
+void pg_cntl42_hubp_dpp_pg_control(struct pg_cntl *pg_cntl, unsigned int hubp_dpp_inst, bool power_on)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t power_gate = power_on ? 0 : 1;
+       uint32_t pwr_status = power_on ? 0 : 2;
+       uint32_t org_ip_request_cntl;
+       bool block_enabled;
+
+       if (pg_cntl->ctx->dc->debug.ignore_pg ||
+               pg_cntl->ctx->dc->debug.disable_hubp_power_gate ||
+               pg_cntl->ctx->dc->debug.disable_dpp_power_gate ||
+               pg_cntl->ctx->dc->idle_optimizations_allowed)
+               return;
+
+       block_enabled = pg_cntl42_hubp_dpp_pg_status(pg_cntl, hubp_dpp_inst);
+       if (power_on) {
+               if (block_enabled)
+                       return;
+       } else {
+               if (!block_enabled)
+                       return;
+       }
+
+       REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+       if (org_ip_request_cntl == 0)
+               REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+       if (power_on) {
+               if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+                       pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, false);
+       }
+
+       switch (hubp_dpp_inst) {
+       case 0:
+               /* DPP0 & HUBP0 */
+               REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+               REG_WAIT(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+               break;
+       case 1:
+               /* DPP1 & HUBP1 */
+               REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+               REG_WAIT(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+               break;
+       case 2:
+               /* DPP2 & HUBP2 */
+               REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+               REG_WAIT(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+               break;
+       case 3:
+               /* DPP3 & HUBP3 */
+               REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+               REG_WAIT(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               break;
+       }
+
+       if (power_on) {
+               if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+                       pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, true);
+       }
+       DC_LOG_DEBUG("HUBP DPP instance %d, power %s", hubp_dpp_inst,
+               power_on ? "ON" : "OFF");
+
+       if (hubp_dpp_inst < MAX_PIPES) {
+               pg_cntl->pg_pipe_res_enable[PG_HUBP][hubp_dpp_inst] = power_on;
+               pg_cntl->pg_pipe_res_enable[PG_DPP][hubp_dpp_inst] = power_on;
+       }
+}
+
+static bool pg_cntl42_hpo_pg_status(struct pg_cntl *pg_cntl)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t pwr_status = 0;
+
+       REG_GET(DOMAIN25_PG_STATUS,
+                       DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+       return pwr_status == 0;
+}
+
+void pg_cntl42_hpo_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t power_gate = power_on ? 0 : 1;
+       uint32_t pwr_status = power_on ? 0 : 2;
+       uint32_t org_ip_request_cntl;
+       uint32_t power_forceon;
+       bool block_enabled;
+
+       if (pg_cntl->ctx->dc->debug.ignore_pg ||
+               pg_cntl->ctx->dc->debug.disable_hpo_power_gate ||
+               pg_cntl->ctx->dc->idle_optimizations_allowed)
+               return;
+
+       block_enabled = pg_cntl42_hpo_pg_status(pg_cntl);
+       if (power_on) {
+               if (block_enabled)
+                       return;
+       } else {
+               if (!block_enabled)
+                       return;
+       }
+
+       REG_GET(DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, &power_forceon);
+       if (power_forceon)
+               return;
+
+       REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+       if (org_ip_request_cntl == 0)
+               REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+       if (power_on) {
+               if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+                       pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, false);
+       }
+       REG_UPDATE(DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+       REG_WAIT(DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+
+       if (power_on) {
+               if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+                       pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, true);
+       }
+       pg_cntl->pg_res_enable[PG_HPO] = power_on;
+}
+
+static bool pg_cntl42_io_clk_status(struct pg_cntl *pg_cntl)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t pwr_status = 0;
+
+       REG_GET(DOMAIN22_PG_STATUS,
+               DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+       return pwr_status == 0;
+}
+
+void pg_cntl42_io_clk_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t power_gate = power_on ? 0 : 1;
+       uint32_t pwr_status = power_on ? 0 : 2;
+       uint32_t org_ip_request_cntl;
+       uint32_t power_forceon;
+       bool block_enabled;
+
+       if (pg_cntl->ctx->dc->debug.ignore_pg ||
+               pg_cntl->ctx->dc->idle_optimizations_allowed ||
+               pg_cntl->ctx->dc->debug.disable_io_clk_power_gate)
+               return;
+
+       block_enabled = pg_cntl42_io_clk_status(pg_cntl);
+       if (power_on) {
+               if (block_enabled)
+                       return;
+       } else {
+               if (!block_enabled)
+                       return;
+       }
+
+       REG_GET(DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, &power_forceon);
+       if (power_forceon)
+               return;
+
+       if (!power_on) {
+               if (!pg_cntl->pg_res_enable[PG_DCCG] || !pg_cntl->pg_res_enable[PG_DCIO] || !pg_cntl->pg_res_enable[PG_DCOH])
+                       return;
+       }
+       REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+       if (org_ip_request_cntl == 0)
+               REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+       /* DCCG, DCOH, DCIO */
+       REG_UPDATE(DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+       REG_WAIT(DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+
+       pg_cntl->pg_res_enable[PG_DCCG] = power_on;
+       pg_cntl->pg_res_enable[PG_DCOH] = power_on;
+       pg_cntl->pg_res_enable[PG_DCIO] = power_on;
+}
+
+static bool pg_cntl42_plane_otg_status(struct pg_cntl *pg_cntl)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t pwr_status = 0;
+
+       REG_GET(DOMAIN24_PG_STATUS,
+               DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+       return pwr_status == 0;
+}
+
+void pg_cntl42_mpcc_pg_control(struct pg_cntl *pg_cntl,
+       unsigned int mpcc_inst, bool power_on)
+{
+       if (pg_cntl->ctx->dc->idle_optimizations_allowed)
+               return;
+
+       if (mpcc_inst < MAX_PIPES)
+               pg_cntl->pg_pipe_res_enable[PG_MPCC][mpcc_inst] = power_on;
+}
+
+void pg_cntl42_opp_pg_control(struct pg_cntl *pg_cntl,
+       unsigned int opp_inst, bool power_on)
+{
+       if (pg_cntl->ctx->dc->idle_optimizations_allowed)
+               return;
+
+       if (opp_inst < MAX_PIPES)
+               pg_cntl->pg_pipe_res_enable[PG_OPP][opp_inst] = power_on;
+}
+
+void pg_cntl42_optc_pg_control(struct pg_cntl *pg_cntl,
+       unsigned int optc_inst, bool power_on)
+{
+       // Defer the ONO domain power up/down to plane_otg_pg_control
+       if (pg_cntl->ctx->dc->idle_optimizations_allowed)
+               return;
+
+       if (optc_inst < MAX_PIPES)
+               pg_cntl->pg_pipe_res_enable[PG_OPTC][optc_inst] = power_on;
+}
+static bool pg_cntl42_mem_status(struct pg_cntl *pg_cntl)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t pwr_status = 0;
+
+       REG_GET(DOMAIN23_PG_STATUS,
+               DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+       return pwr_status == 0;
+}
+
+void pg_cntl42_mem_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t power_gate = power_on ? 0 : 1;
+       uint32_t pwr_status = power_on ? 0 : 2;
+       uint32_t org_ip_request_cntl;
+       uint32_t power_forceon;
+       bool block_enabled;
+
+       if (pg_cntl->ctx->dc->debug.ignore_pg ||
+               pg_cntl->ctx->dc->idle_optimizations_allowed ||
+               pg_cntl->ctx->dc->debug.disable_mem_power_gate)
+               return;
+
+       block_enabled = pg_cntl42_mem_status(pg_cntl);
+       if (power_on) {
+               if (block_enabled)
+                       return;
+       } else {
+               if (!block_enabled)
+                       return;
+       }
+
+       REG_GET(DOMAIN23_PG_CONFIG, DOMAIN_POWER_FORCEON, &power_forceon);
+       if (power_forceon)
+               return;
+
+       if (!power_on) {
+               if (!pg_cntl->pg_res_enable[PG_DCHUBBUB] || !pg_cntl->pg_res_enable[PG_DCHVM])
+                       return;
+       }
+       REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+       if (org_ip_request_cntl == 0)
+               REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+       /* DCHUBBUB, DCHUBBUBMEMn, DCHVM */
+       REG_UPDATE(DOMAIN23_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+       REG_WAIT(DOMAIN23_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+
+       pg_cntl->pg_res_enable[PG_DCHUBBUB] = power_on;
+       pg_cntl->pg_res_enable[PG_DCHVM] = power_on;
+}
+static bool pg_cntl42_dio_pg_status(struct pg_cntl *pg_cntl)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t pwr_status = 0;
+
+       REG_GET(DOMAIN26_PG_STATUS,
+               DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+       return pwr_status == 0;
+}
+
+void pg_cntl42_dio_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t power_gate = power_on ? 0 : 1;
+       uint32_t pwr_status = power_on ? 0 : 2;
+       uint32_t org_ip_request_cntl;
+       bool block_enabled;
+
+       if (pg_cntl->ctx->dc->debug.ignore_pg ||
+               pg_cntl->ctx->dc->idle_optimizations_allowed ||
+               pg_cntl->ctx->dc->debug.disable_dio_power_gate)
+               return;
+
+       block_enabled = pg_cntl42_dio_pg_status(pg_cntl);
+       if (power_on) {
+               if (block_enabled)
+                       return;
+       } else {
+               if (!block_enabled)
+                       return;
+       }
+
+       REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+       if (org_ip_request_cntl == 0)
+               REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+       if (power_on) {
+               if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+                       pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, false);
+       }
+       /* DIO */
+       REG_UPDATE(DOMAIN26_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+       REG_WAIT(DOMAIN26_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+
+       if (power_on) {
+               if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+                       pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, true);
+       }
+       pg_cntl->pg_res_enable[PG_DIO] = power_on;
+
+}
+
+void pg_cntl42_plane_otg_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+       uint32_t power_gate = power_on ? 0 : 1;
+       uint32_t pwr_status = power_on ? 0 : 2;
+       uint32_t org_ip_request_cntl;
+       int i;
+       bool block_enabled;
+       bool all_mpcc_disabled = true, all_opp_disabled = true;
+       bool all_optc_disabled = true, all_stream_disabled = true;
+
+       if (pg_cntl->ctx->dc->debug.ignore_pg ||
+               pg_cntl->ctx->dc->debug.disable_optc_power_gate ||
+               pg_cntl->ctx->dc->idle_optimizations_allowed)
+               return;
+
+       block_enabled = pg_cntl42_plane_otg_status(pg_cntl);
+       if (power_on) {
+               if (block_enabled)
+                       return;
+       } else {
+               if (!block_enabled)
+                       return;
+       }
+
+       for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) {
+               struct pipe_ctx *pipe_ctx = &pg_cntl->ctx->dc->current_state->res_ctx.pipe_ctx[i];
+
+               if (pipe_ctx) {
+                       if (pipe_ctx->stream)
+                               all_stream_disabled = false;
+               }
+
+               if (pg_cntl->pg_pipe_res_enable[PG_MPCC][i])
+                       all_mpcc_disabled = false;
+
+               if (pg_cntl->pg_pipe_res_enable[PG_OPP][i])
+                       all_opp_disabled = false;
+
+               if (pg_cntl->pg_pipe_res_enable[PG_OPTC][i])
+                       all_optc_disabled = false;
+       }
+
+       if (!power_on) {
+               if (!all_mpcc_disabled || !all_opp_disabled || !all_optc_disabled
+                       || !all_stream_disabled)
+                       return;
+       }
+
+       REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+       if (org_ip_request_cntl == 0)
+               REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+       /* MPC, OPP, OPTC, DWB */
+       REG_UPDATE(DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+       REG_WAIT(DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+
+       for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) {
+               pg_cntl->pg_pipe_res_enable[PG_MPCC][i] = power_on;
+               pg_cntl->pg_pipe_res_enable[PG_OPP][i] = power_on;
+               pg_cntl->pg_pipe_res_enable[PG_OPTC][i] = power_on;
+       }
+}
+
+
+void pg_cntl42_init_pg_status(struct pg_cntl *pg_cntl)
+{
+       int i = 0;
+       bool block_enabled;
+
+       pg_cntl->pg_res_enable[PG_HPO] = pg_cntl42_hpo_pg_status(pg_cntl);
+
+       block_enabled = pg_cntl42_io_clk_status(pg_cntl);
+       pg_cntl->pg_res_enable[PG_DCCG] = block_enabled;
+       pg_cntl->pg_res_enable[PG_DCIO] = block_enabled;
+       pg_cntl->pg_res_enable[PG_DCOH] = block_enabled;
+
+       block_enabled = pg_cntl42_dio_pg_status(pg_cntl);
+       pg_cntl->pg_res_enable[PG_DIO] = block_enabled;
+
+       block_enabled = pg_cntl42_mem_status(pg_cntl);
+       pg_cntl->pg_res_enable[PG_DCHUBBUB] = block_enabled;
+       pg_cntl->pg_res_enable[PG_DCHVM] = block_enabled;
+
+       for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) {
+               block_enabled = pg_cntl42_hubp_dpp_pg_status(pg_cntl, i);
+               pg_cntl->pg_pipe_res_enable[PG_HUBP][i] = block_enabled;
+               pg_cntl->pg_pipe_res_enable[PG_DPP][i] = block_enabled;
+
+               block_enabled = pg_cntl42_dsc_pg_status(pg_cntl, i);
+               pg_cntl->pg_pipe_res_enable[PG_DSC][i] = block_enabled;
+       }
+
+       block_enabled = pg_cntl42_plane_otg_status(pg_cntl);
+       for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) {
+               pg_cntl->pg_pipe_res_enable[PG_MPCC][i] = block_enabled;
+               pg_cntl->pg_pipe_res_enable[PG_OPP][i] = block_enabled;
+               pg_cntl->pg_pipe_res_enable[PG_OPTC][i] = block_enabled;
+       }
+}
+
+static const struct pg_cntl_funcs pg_cntl42_funcs = {
+       .init_pg_status = pg_cntl42_init_pg_status,
+       .dsc_pg_control = pg_cntl42_dsc_pg_control,
+       .hubp_dpp_pg_control = pg_cntl42_hubp_dpp_pg_control,
+       .hpo_pg_control = pg_cntl42_hpo_pg_control,
+       .io_clk_pg_control = pg_cntl42_io_clk_pg_control,
+       .plane_otg_pg_control = pg_cntl42_plane_otg_pg_control,
+       .mpcc_pg_control = pg_cntl42_mpcc_pg_control,
+       .opp_pg_control = pg_cntl42_opp_pg_control,
+       .optc_pg_control = pg_cntl42_optc_pg_control,
+       .mem_pg_control = pg_cntl42_mem_pg_control,
+       .dio_pg_control = pg_cntl42_dio_pg_control
+};
+
+struct pg_cntl *pg_cntl42_create(
+       struct dc_context *ctx,
+       const struct pg_cntl_registers *regs,
+       const struct pg_cntl_shift *pg_cntl_shift,
+       const struct pg_cntl_mask *pg_cntl_mask)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = kzalloc(sizeof(*pg_cntl_dcn), GFP_KERNEL);
+       struct pg_cntl *base;
+
+       if (pg_cntl_dcn == NULL) {
+               BREAK_TO_DEBUGGER();
+               return NULL;
+       }
+
+       base = &pg_cntl_dcn->base;
+       base->ctx = ctx;
+       base->funcs = &pg_cntl42_funcs;
+
+       pg_cntl_dcn->regs = regs;
+       pg_cntl_dcn->pg_cntl_shift = pg_cntl_shift;
+       pg_cntl_dcn->pg_cntl_mask = pg_cntl_mask;
+
+       memset(base->pg_pipe_res_enable, 0, PG_HW_PIPE_RESOURCES_NUM_ELEMENT * MAX_PIPES * sizeof(bool));
+       memset(base->pg_res_enable, 0, PG_HW_RESOURCES_NUM_ELEMENT * sizeof(bool));
+
+       return &pg_cntl_dcn->base;
+}
+
+void dcn42_pg_cntl_destroy(struct pg_cntl **pg_cntl)
+{
+       struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(*pg_cntl);
+
+       kfree(pg_cntl_dcn);
+       *pg_cntl = NULL;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h
new file mode 100644 (file)
index 0000000..a0aa14a
--- /dev/null
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: MIT */
+
+/* Copyright 2026 Advanced Micro Devices, Inc.*/
+
+#ifndef __DCN42_PG_CNTL_H__
+#define __DCN42_PG_CNTL_H__
+
+#include "pg_cntl.h"
+
+#define PG_CNTL_REG_LIST_DCN42()\
+       SR(DOMAIN0_PG_CONFIG), \
+       SR(DOMAIN1_PG_CONFIG), \
+       SR(DOMAIN2_PG_CONFIG), \
+       SR(DOMAIN3_PG_CONFIG), \
+       SR(DOMAIN16_PG_CONFIG), \
+       SR(DOMAIN17_PG_CONFIG), \
+       SR(DOMAIN18_PG_CONFIG), \
+       SR(DOMAIN19_PG_CONFIG), \
+       SR(DOMAIN22_PG_CONFIG), \
+       SR(DOMAIN23_PG_CONFIG), \
+       SR(DOMAIN24_PG_CONFIG), \
+       SR(DOMAIN25_PG_CONFIG), \
+       SR(DOMAIN26_PG_CONFIG), \
+       SR(DOMAIN0_PG_STATUS), \
+       SR(DOMAIN1_PG_STATUS), \
+       SR(DOMAIN2_PG_STATUS), \
+       SR(DOMAIN3_PG_STATUS), \
+       SR(DOMAIN16_PG_STATUS), \
+       SR(DOMAIN17_PG_STATUS), \
+       SR(DOMAIN18_PG_STATUS), \
+       SR(DOMAIN19_PG_STATUS), \
+       SR(DOMAIN22_PG_STATUS), \
+       SR(DOMAIN23_PG_STATUS), \
+       SR(DOMAIN24_PG_STATUS), \
+       SR(DOMAIN25_PG_STATUS), \
+       SR(DOMAIN26_PG_STATUS), \
+       SR(DC_IP_REQUEST_CNTL)
+
+#define PG_CNTL_SF(reg_name, field_name, post_fix)\
+       .field_name = reg_name ## __ ## field_name ## post_fix
+
+#define PG_CNTL_MASK_SH_LIST_DCN42(mask_sh) \
+       PG_CNTL_SF(DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+       PG_CNTL_SF(DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+       PG_CNTL_SF(DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+       PG_CNTL_SF(DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+       PG_CNTL_SF(DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+       PG_CNTL_SF(DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+       PG_CNTL_SF(DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+       PG_CNTL_SF(DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+       PG_CNTL_SF(DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+       PG_CNTL_SF(DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN23_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+       PG_CNTL_SF(DOMAIN23_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN24_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+       PG_CNTL_SF(DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+       PG_CNTL_SF(DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN26_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+       PG_CNTL_SF(DOMAIN26_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN0_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+       PG_CNTL_SF(DOMAIN1_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+       PG_CNTL_SF(DOMAIN2_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+       PG_CNTL_SF(DOMAIN3_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+       PG_CNTL_SF(DOMAIN16_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+       PG_CNTL_SF(DOMAIN17_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+       PG_CNTL_SF(DOMAIN18_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+       PG_CNTL_SF(DOMAIN19_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+       PG_CNTL_SF(DOMAIN22_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+       PG_CNTL_SF(DOMAIN23_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN23_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+       PG_CNTL_SF(DOMAIN24_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+       PG_CNTL_SF(DOMAIN25_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+       PG_CNTL_SF(DOMAIN26_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+       PG_CNTL_SF(DOMAIN26_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+       PG_CNTL_SF(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh)
+
+struct pg_cntl_shift {
+       uint8_t IP_REQUEST_EN;
+       uint8_t DOMAIN_POWER_FORCEON;
+       uint8_t DOMAIN_POWER_GATE;
+       uint8_t DOMAIN_DESIRED_PWR_STATE;
+       uint8_t DOMAIN_PGFSM_PWR_STATUS;
+};
+struct pg_cntl_mask {
+       uint32_t IP_REQUEST_EN;
+       uint32_t DOMAIN_POWER_FORCEON;
+       uint32_t DOMAIN_POWER_GATE;
+       uint32_t DOMAIN_DESIRED_PWR_STATE;
+       uint32_t DOMAIN_PGFSM_PWR_STATUS;
+};
+
+struct pg_cntl_registers {
+       uint32_t LONO_STATE;
+       uint32_t DC_IP_REQUEST_CNTL;
+       uint32_t DOMAIN0_PG_CONFIG;
+       uint32_t DOMAIN1_PG_CONFIG;
+       uint32_t DOMAIN2_PG_CONFIG;
+       uint32_t DOMAIN3_PG_CONFIG;
+       uint32_t DOMAIN16_PG_CONFIG;
+       uint32_t DOMAIN17_PG_CONFIG;
+       uint32_t DOMAIN18_PG_CONFIG;
+       uint32_t DOMAIN19_PG_CONFIG;
+       uint32_t DOMAIN22_PG_CONFIG;
+       uint32_t DOMAIN23_PG_CONFIG;
+       uint32_t DOMAIN24_PG_CONFIG;
+       uint32_t DOMAIN25_PG_CONFIG;
+       uint32_t DOMAIN26_PG_CONFIG;
+       uint32_t DOMAIN0_PG_STATUS;
+       uint32_t DOMAIN1_PG_STATUS;
+       uint32_t DOMAIN2_PG_STATUS;
+       uint32_t DOMAIN3_PG_STATUS;
+       uint32_t DOMAIN16_PG_STATUS;
+       uint32_t DOMAIN17_PG_STATUS;
+       uint32_t DOMAIN18_PG_STATUS;
+       uint32_t DOMAIN19_PG_STATUS;
+       uint32_t DOMAIN22_PG_STATUS;
+       uint32_t DOMAIN23_PG_STATUS;
+       uint32_t DOMAIN24_PG_STATUS;
+       uint32_t DOMAIN25_PG_STATUS;
+       uint32_t DOMAIN26_PG_STATUS;
+};
+
+struct dcn_pg_cntl {
+       struct pg_cntl base;
+       const struct pg_cntl_registers *regs;
+       const struct pg_cntl_shift *pg_cntl_shift;
+       const struct pg_cntl_mask *pg_cntl_mask;
+};
+
+void pg_cntl42_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bool power_on);
+void pg_cntl42_hubp_dpp_pg_control(struct pg_cntl *pg_cntl,
+       unsigned int hubp_dpp_inst, bool power_on);
+void pg_cntl42_hpo_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void pg_cntl42_io_clk_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void pg_cntl42_plane_otg_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void pg_cntl42_mpcc_pg_control(struct pg_cntl *pg_cntl,
+       unsigned int mpcc_inst, bool power_on);
+void pg_cntl42_opp_pg_control(struct pg_cntl *pg_cntl,
+       unsigned int opp_inst, bool power_on);
+void pg_cntl42_optc_pg_control(struct pg_cntl *pg_cntl,
+       unsigned int optc_inst, bool power_on);
+void pg_cntl42_mem_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void pg_cntl42_dio_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void dcn42_pg_cntl_destroy(struct pg_cntl **pg_cntl);
+void pg_cntl42_init_pg_status(struct pg_cntl *pg_cntl);
+
+struct pg_cntl *pg_cntl42_create(
+       struct dc_context *ctx,
+       const struct pg_cntl_registers *regs,
+       const struct pg_cntl_shift *pg_cntl_shift,
+       const struct pg_cntl_mask *pg_cntl_mask);
+
+void dcn_pg_cntl_destroy(struct pg_cntl **pg_cntl);
+
+#endif /* DCN42_PG_CNTL */
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
new file mode 100644 (file)
index 0000000..9f2f4d6
--- /dev/null
@@ -0,0 +1,2337 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dm_services.h"
+#include "dc.h"
+
+#include "dcn32/dcn32_init.h"
+#include "dcn42/dcn42_init.h"
+
+#include "resource.h"
+#include "include/irq_service_interface.h"
+
+#include "dcn42_resource.h"
+#include "dcn42_resource_fpu.h"
+#include "dcn20/dcn20_resource.h"
+#include "dcn30/dcn30_resource.h"
+#include "dcn31/dcn31_resource.h"
+#include "dcn32/dcn32_resource.h"
+#include "dcn35/dcn35_resource.h"
+#include "dcn321/dcn321_resource.h"
+#include "dcn401/dcn401_resource.h"
+
+#include "dcn10/dcn10_ipp.h"
+#include "dcn35/dcn35_hubbub.h"
+#include "dcn42/dcn42_hubbub.h"
+#include "dcn401/dcn401_mpc.h"
+#include "dcn42/dcn42_mpc.h"
+#include "dcn35/dcn35_hubp.h"
+#include "dcn42/dcn42_hubp.h"
+#include "irq/dcn42/irq_service_dcn42.h"
+#include "dcn42/dcn42_dpp.h"
+#include "dcn401/dcn401_dsc.h"
+#include "dcn42/dcn42_optc.h"
+#include "dcn20/dcn20_hwseq.h"
+#include "dcn30/dcn30_hwseq.h"
+#include "dce110/dce110_hwseq.h"
+#include "dcn35/dcn35_opp.h"
+#include "dcn30/dcn30_vpg.h"
+#include "dcn31/dcn31_vpg.h"
+#include "dcn42/dcn42_dio_stream_encoder.h"
+#include "dcn42/dcn42_pg_cntl.h"
+#include "dcn31/dcn31_hpo_dp_stream_encoder.h"
+#include "dcn31/dcn31_hpo_dp_link_encoder.h"
+#include "dcn32/dcn32_hpo_dp_link_encoder.h"
+#include "dcn42/dcn42_hpo_dp_link_encoder.h"
+#include "dcn31/dcn31_apg.h"
+#include "dcn31/dcn31_dio_link_encoder.h"
+#include "dcn401/dcn401_dio_link_encoder.h"
+#include "dcn10/dcn10_link_encoder.h"
+#include "dcn321/dcn321_dio_link_encoder.h"
+#include "dce/dce_clock_source.h"
+#include "dce/dce_audio.h"
+#include "dce/dce_hwseq.h"
+#include "clk_mgr.h"
+#include "virtual/virtual_stream_encoder.h"
+#include "dml/display_mode_vba.h"
+#include "dcn42/dcn42_dccg.h"
+#include "dcn10/dcn10_resource.h"
+#include "link_service.h"
+#include "dcn31/dcn31_panel_cntl.h"
+
+#include "dcn30/dcn30_dwb.h"
+#include "dcn42/dcn42_mmhubbub.h"
+#include "dcn42/dcn42_dio_link_encoder.h"
+
+#include "dcn/dcn_4_2_0_offset.h"
+#include "dcn/dcn_4_2_0_sh_mask.h"
+#include "dpcs/dpcs_4_0_0_offset.h"
+#include "dpcs/dpcs_4_0_0_sh_mask.h"
+
+#include "reg_helper.h"
+#include "dce/dmub_abm.h"
+#include "dce/dmub_psr.h"
+#include "dce/dmub_replay.h"
+#include "dce/dce_aux.h"
+#include "dce/dce_i2c.h"
+
+#include "dml/dcn30/display_mode_vba_30.h"
+#include "vm_helper.h"
+#include "dcn20/dcn20_vmid.h"
+
+#include "dc_state_priv.h"
+#include "link_enc_cfg.h"
+
+#include "dml2_0/dml2_wrapper.h"
+
+#define regBIF_BX0_BIOS_SCRATCH_3                            0x003b
+#define regBIF_BX0_BIOS_SCRATCH_3_BASE_IDX                   1
+#define regBIF_BX0_BIOS_SCRATCH_6                            0x003e
+#define regBIF_BX0_BIOS_SCRATCH_6_BASE_IDX                   1
+
+#define DC_LOGGER_INIT(logger)
+
+enum dcn401_clk_src_array_id {
+       DCN401_CLK_SRC_PLL0,
+       DCN401_CLK_SRC_PLL1,
+       DCN401_CLK_SRC_PLL2,
+       DCN401_CLK_SRC_PLL3,
+       DCN401_CLK_SRC_PLL4,
+       DCN401_CLK_SRC_TOTAL
+};
+
+/* begin
+ * macros to expend register list macro defined in HW object header file
+ */
+
+/* DCN */
+#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg]
+
+#define BASE(seg) BASE_INNER(seg)
+
+#define SR(reg_name)                                       \
+       REG_STRUCT.reg_name = BASE(reg##reg_name##_BASE_IDX) + \
+                                                 reg##reg_name
+#define SR_ARR(reg_name, id)                                   \
+       REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + \
+                                                         reg##reg_name
+#define SR_ARR_INIT(reg_name, id, value) \
+       REG_STRUCT[id].reg_name = value
+
+#define SRI(reg_name, block, id)                                         \
+       REG_STRUCT.reg_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+                                                 reg##block##id##_##reg_name
+
+#define SRI_ARR(reg_name, block, id)                                         \
+       REG_STRUCT[id].reg_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+                                                         reg##block##id##_##reg_name
+
+/*
+ * Used when a reg_name would otherwise begin with an integer
+ */
+#define SRI_ARR_US(reg_name, block, id)                                   \
+       REG_STRUCT[id].reg_name = BASE(reg##block##id##reg_name##_BASE_IDX) + \
+                                                         reg##block##id##reg_name
+#define SR_ARR_I2C(reg_name, id) \
+       REG_STRUCT[id - 1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name
+
+#define SRI_ARR_I2C(reg_name, block, id)                                         \
+       REG_STRUCT[id - 1].reg_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+                                                                 reg##block##id##_##reg_name
+
+
+#define SRI_ARR_ALPHABET(reg_name, block, index, id)                            \
+       REG_STRUCT[index].reg_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+                                                                reg##block##id##_##reg_name
+
+#define SRI2(reg_name, block, id)                \
+       .reg_name = BASE(reg##reg_name##_BASE_IDX) + \
+                               reg##reg_name
+#define SRI2_ARR(reg_name, block, id)                          \
+       REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + \
+                                                         reg##reg_name
+
+#define SRIR(var_name, reg_name, block, id)                    \
+       .var_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+                               reg##block##id##_##reg_name
+
+#define SRII(reg_name, block, id)                                            \
+       REG_STRUCT.reg_name[id] = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+                                                         reg##block##id##_##reg_name
+
+#define SRII_ARR_2(reg_name, block, id, inst)                                      \
+       REG_STRUCT[inst].reg_name[id] = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+                                                                       reg##block##id##_##reg_name
+
+#define SRII_MPC_RMU(reg_name, block, id)                                  \
+       .RMU##_##reg_name[id] = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+                                                       reg##block##id##_##reg_name
+
+#define SRII_DWB(reg_name, temp_name, block, id)                              \
+       REG_STRUCT.reg_name[id] = \
+               BASE(reg##block##id##_##temp_name##_BASE_IDX) + \
+                                                         reg##block##id##_##temp_name
+
+#define DCCG_SRII(reg_name, block, id)                                                 \
+       REG_STRUCT.block##_##reg_name[id] = \
+               BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+                                                                               reg##block##id##_##reg_name
+
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+       .field_name = reg_name##__##field_name##post_fix
+
+#define VUPDATE_SRII(reg_name, block, id)                                    \
+       REG_STRUCT.reg_name[id] = BASE(reg##reg_name##_##block##id##_BASE_IDX) + \
+                                                         reg##reg_name##_##block##id
+
+/* NBIO */
+#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg]
+
+#define NBIO_BASE(seg) \
+       NBIO_BASE_INNER(seg)
+
+#define NBIO_SR(reg_name)                                               \
+       REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX0_##reg_name##_BASE_IDX) + \
+                                                 regBIF_BX0_##reg_name
+#define NBIO_SR_ARR(reg_name, id)                                           \
+       REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX0_##reg_name##_BASE_IDX) + \
+                                                         regBIF_BX0_##reg_name
+
+#define CTX ctx
+#define REG(reg_name) \
+       (ctx->dcn_reg_offsets[reg##reg_name##_BASE_IDX] + reg##reg_name)
+
+static struct bios_registers bios_regs;
+
+#define bios_regs_init()     \
+       NBIO_SR(BIOS_SCRATCH_3), \
+               NBIO_SR(BIOS_SCRATCH_6)
+
+#define clk_src_regs_init(index, pllid) \
+       CS_COMMON_REG_LIST_DCN42_RI(index, pllid)
+
+static struct dce110_clk_src_regs clk_src_regs[5];
+
+static const struct dce110_clk_src_shift cs_shift = {
+       CS_COMMON_MASK_SH_LIST_DCN3_1_4(__SHIFT)
+};
+static const struct dce110_clk_src_mask cs_mask = {
+       CS_COMMON_MASK_SH_LIST_DCN3_1_4(_MASK)
+};
+#define abm_regs_init(id) \
+       ABM_DCN42_REG_LIST_RI(id)
+
+static struct dce_abm_registers abm_regs[4];
+
+static const struct dce_abm_shift abm_shift = {
+       ABM_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dce_abm_mask abm_mask = {
+       ABM_MASK_SH_LIST_DCN42(_MASK)};
+
+#define audio_regs_init(id) \
+       AUD_COMMON_REG_LIST_RI(id)
+
+static struct dce_audio_registers audio_regs[5];
+
+static const struct dce_audio_shift audio_shift = {
+               DCN42_AUD_COMMON_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce_audio_mask audio_mask = {
+               DCN42_AUD_COMMON_MASK_SH_LIST(_MASK)
+};
+
+#define vpg_regs_init(id) \
+       VPG_DCN401_REG_LIST_RI(id)
+
+static struct dcn31_vpg_registers vpg_regs[10];
+
+static const struct dcn31_vpg_shift vpg_shift = {
+       DCN31_VPG_MASK_SH_LIST(__SHIFT)};
+
+static const struct dcn31_vpg_mask vpg_mask = {
+       DCN31_VPG_MASK_SH_LIST(_MASK)};
+
+#define apg_regs_init(id) \
+       APG_DCN31_REG_LIST_RI(id)
+
+static struct dcn31_apg_registers apg_regs[10];
+
+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_init(id) \
+       SE_DCN42_REG_LIST_RI(id)
+
+static struct dcn10_stream_enc_registers stream_enc_regs[5];
+
+static const struct dcn10_stream_encoder_shift se_shift = {
+       SE_COMMON_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dcn10_stream_encoder_mask se_mask = {
+       SE_COMMON_MASK_SH_LIST_DCN42(_MASK)};
+
+#define aux_regs_init(id) \
+       DCN2_AUX_REG_LIST_RI(id)
+
+static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5];
+
+#define hpd_regs_init(id) \
+       HPD_REG_LIST_RI(id)
+
+static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5];
+
+#define link_regs_init(id, phyid) \
+       LE_DCN401_REG_LIST_RI(id)
+
+static struct dcn10_link_enc_registers link_enc_regs[5];
+
+static const struct dcn10_link_enc_shift le_shift = {
+       LINK_ENCODER_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dcn10_link_enc_mask le_mask = {
+       LINK_ENCODER_MASK_SH_LIST_DCN42(_MASK)};
+
+#define hpo_dp_stream_encoder_reg_init(id) \
+       DCN42_HPO_DP_STREAM_ENC_REG_LIST_RI(id)
+
+static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4];
+
+static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = {
+       DCN4_2_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT)};
+
+static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = {
+       DCN4_2_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK)};
+
+#define hpo_dp_link_encoder_reg_init(id) \
+       DCN42_HPO_DP_LINK_ENC_REG_LIST_RI(id)
+
+static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[4];
+
+static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = {
+       DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT)};
+
+static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = {
+       DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK)};
+
+#define dpp_regs_init(id) \
+       DPP_REG_LIST_DCN42_COMMON_RI(id)
+
+static struct dcn42_dpp_registers dpp_regs[4];
+
+static const struct dcn42_dpp_shift tf_shift = {
+       DPP_REG_LIST_SH_MASK_DCN42_COMMON(__SHIFT)};
+
+static const struct dcn42_dpp_mask tf_mask = {
+       DPP_REG_LIST_SH_MASK_DCN42_COMMON(_MASK)};
+
+#define opp_regs_init(id) \
+       OPP_REG_LIST_DCN401_RI(id)
+
+static struct dcn20_opp_registers opp_regs[4];
+
+static const struct dcn20_opp_shift opp_shift = {
+       OPP_MASK_SH_LIST_DCN20(__SHIFT)};
+
+static const struct dcn20_opp_mask opp_mask = {
+       OPP_MASK_SH_LIST_DCN20(_MASK)};
+
+#define aux_engine_regs_init(id)                                              \
+       AUX_COMMON_REG_LIST0_RI(id), SR_ARR_INIT(AUXN_IMPCAL, id, 0),             \
+               SR_ARR_INIT(AUXP_IMPCAL, id, 0),                                      \
+               SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK), \
+               SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK)
+
+static struct dce110_aux_registers aux_engine_regs[5];
+
+static const struct dce110_aux_registers_shift aux_shift = {
+       DCN_AUX_MASK_SH_LIST(__SHIFT)};
+
+static const struct dce110_aux_registers_mask aux_mask = {
+       DCN_AUX_MASK_SH_LIST(_MASK)};
+
+#define dwbc_regs_dcn401_init(id) \
+       DWBC_COMMON_REG_LIST_DCN30_RI(id)
+
+static struct dcn30_dwbc_registers dwbc401_regs[1];
+
+static const struct dcn30_dwbc_shift dwbc401_shift = {
+       DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT)};
+
+static const struct dcn30_dwbc_mask dwbc401_mask = {
+       DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK)};
+
+#define mcif_wb_regs_dcn3_init(id) \
+       MCIF_WB_COMMON_REG_LIST_DCN3_5_RI(id)
+
+static struct dcn35_mmhubbub_registers mcif_wb35_regs[1];
+
+static const struct dcn35_mmhubbub_shift mcif_wb35_shift = {
+       MCIF_WB_COMMON_MASK_SH_LIST_DCN3_5(__SHIFT)};
+
+static const struct dcn35_mmhubbub_mask mcif_wb35_mask = {
+       MCIF_WB_COMMON_MASK_SH_LIST_DCN3_5(_MASK)};
+
+#define dsc_regs_init(id) \
+       DSC_REG_LIST_DCN401_RI(id)
+
+static struct dcn401_dsc_registers dsc_regs[4];
+
+static const struct dcn401_dsc_shift dsc_shift = {
+       DSC_REG_LIST_SH_MASK_DCN401(__SHIFT)};
+
+static const struct dcn401_dsc_mask dsc_mask = {
+       DSC_REG_LIST_SH_MASK_DCN401(_MASK)};
+
+static struct dcn42_mpc_registers mpc_regs;
+
+#define dcn_mpc_regs_init()                \
+       MPC_REG_LIST_DCN42(0),                 \
+               MPC_REG_LIST_DCN42(1),             \
+               MPC_REG_LIST_DCN42(2),             \
+               MPC_REG_LIST_DCN42(3),             \
+               MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0), \
+               MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1), \
+               MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2), \
+               MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3), \
+               MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0), \
+               MPC_RMCM_REG_LIST_DCN42(0),                \
+               MPC_RMCM_REG_LIST_DCN42(1)
+
+static const struct dcn42_mpc_shift mpc_shift = {
+       MPC_COMMON_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dcn42_mpc_mask mpc_mask = {
+       MPC_COMMON_MASK_SH_LIST_DCN42(_MASK)};
+
+#define optc_regs_init(id) \
+       OPTC_COMMON_REG_LIST_DCN42_RI(id)
+
+static struct dcn_optc_registers optc_regs[4];
+
+static const struct dcn_optc_shift optc_shift = {
+       OPTC_COMMON_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dcn_optc_mask optc_mask = {
+       OPTC_COMMON_MASK_SH_LIST_DCN42(_MASK)};
+
+#define hubp_regs_init(id) \
+       HUBP_REG_LIST_DCN42_RI(id)
+
+static struct dcn_hubp2_registers hubp_regs[4];
+
+static const struct dcn_hubp2_shift hubp_shift = {
+       HUBP_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dcn_hubp2_mask hubp_mask = {
+       HUBP_MASK_SH_LIST_DCN42(_MASK)};
+
+static struct dcn_hubbub_registers hubbub_reg;
+
+#define hubbub_reg_init() \
+       HUBBUB_REG_LIST_DCN42(0)
+
+static const struct dcn_hubbub_shift hubbub_shift = {
+       HUBBUB_MASK_SH_LIST_DCN4_2(__SHIFT)};
+
+static const struct dcn_hubbub_mask hubbub_mask = {
+       HUBBUB_MASK_SH_LIST_DCN4_2(_MASK)};
+
+static struct dccg_registers dccg_regs;
+
+#define dccg_regs_init() \
+       DCCG_REG_LIST_DCN42_RI()
+
+static const struct dccg_shift dccg_shift = {
+       DCCG_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dccg_mask dccg_mask = {
+       DCCG_MASK_SH_LIST_DCN42(_MASK)};
+
+static struct pg_cntl_registers pg_cntl_regs;
+
+#define pg_cntl_dcn42_regs_init() \
+       PG_CNTL_REG_LIST_DCN42()
+
+static const struct pg_cntl_shift pg_cntl_shift = {
+               PG_CNTL_MASK_SH_LIST_DCN42(__SHIFT)
+};
+
+static const struct pg_cntl_mask pg_cntl_mask = {
+               PG_CNTL_MASK_SH_LIST_DCN42(_MASK)
+};
+#define SRII2(reg_name_pre, reg_name_post, id)                                                       \
+       .reg_name_pre##_##reg_name_post[id] = \
+               BASE(reg##reg_name_pre##id##_##reg_name_post##_BASE_IDX) + \
+                                       reg##reg_name_pre##id##_##reg_name_post
+
+#define HWSEQ_DCN42_REG_LIST()                \
+       SR(DCHUBBUB_GLOBAL_TIMER_CNTL),           \
+               SR(DIO_MEM_PWR_CTRL),                 \
+               SR(ODM_MEM_PWR_CTRL3),                \
+               SR(MMHUBBUB_MEM_PWR_CNTL),            \
+               SR(DCCG_GATE_DISABLE_CNTL),           \
+               SR(DCCG_GATE_DISABLE_CNTL2),          \
+               SR(DCFCLK_CNTL),                      \
+               SR(DC_MEM_GLOBAL_PWR_REQ_CNTL),       \
+               SRII(PIXEL_RATE_CNTL, OTG, 0),        \
+               SRII(PIXEL_RATE_CNTL, OTG, 1),        \
+               SRII(PIXEL_RATE_CNTL, OTG, 2),        \
+               SRII(PIXEL_RATE_CNTL, OTG, 3),\
+               SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0), \
+               SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1), \
+               SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2), \
+               SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\
+               SR(MICROSECOND_TIME_BASE_DIV),        \
+               SR(MILLISECOND_TIME_BASE_DIV),        \
+               SR(DISPCLK_FREQ_CHANGE_CNTL),         \
+               SR(RBBMIF_TIMEOUT_DIS),               \
+               SR(RBBMIF_TIMEOUT_DIS_2),             \
+               SR(DCHUBBUB_CRC_CTRL),                \
+               SR(DPP_TOP0_DPP_CRC_CTRL),            \
+               SR(DPP_TOP0_DPP_CRC_VAL_R),           \
+               SR(DPP_TOP0_DPP_CRC_VAL_G),           \
+               SR(DPP_TOP0_DPP_CRC_VAL_B),           \
+               SR(MPC_CRC_CTRL),                     \
+               SR(MPC_CRC_RESULT_R),                 \
+               SR(MPC_CRC_RESULT_G),                 \
+               SR(MPC_CRC_RESULT_B),                 \
+               SR(MPC_CRC_RESULT_A),                 \
+               SR(DOMAIN0_PG_CONFIG),                \
+               SR(DOMAIN1_PG_CONFIG),                \
+               SR(DOMAIN2_PG_CONFIG),                \
+               SR(DOMAIN3_PG_CONFIG),                \
+               SR(DOMAIN16_PG_CONFIG),               \
+               SR(DOMAIN17_PG_CONFIG),               \
+               SR(DOMAIN18_PG_CONFIG),               \
+               SR(DOMAIN19_PG_CONFIG), \
+               SR(DOMAIN22_PG_CONFIG),               \
+               SR(DOMAIN23_PG_CONFIG),               \
+               SR(DOMAIN24_PG_CONFIG),               \
+               SR(DOMAIN25_PG_CONFIG),               \
+               SR(DOMAIN26_PG_CONFIG),               \
+               SR(DOMAIN0_PG_STATUS),                \
+               SR(DOMAIN1_PG_STATUS),                \
+               SR(DOMAIN2_PG_STATUS),                \
+               SR(DOMAIN3_PG_STATUS),                \
+               SR(DOMAIN16_PG_STATUS),               \
+               SR(DOMAIN17_PG_STATUS),               \
+               SR(DOMAIN18_PG_STATUS),               \
+               SR(DOMAIN19_PG_STATUS),               \
+               SR(DOMAIN22_PG_STATUS),               \
+               SR(DOMAIN23_PG_STATUS),               \
+               SR(DOMAIN24_PG_STATUS),               \
+               SR(DOMAIN25_PG_STATUS),               \
+               SR(DOMAIN26_PG_STATUS),               \
+               SR(DC_IP_REQUEST_CNTL),               \
+               SR(AZALIA_AUDIO_DTO),                 \
+               SR(HPO_TOP_HW_CONTROL),               \
+               SR(AZALIA_CONTROLLER_CLOCK_GATING)
+
+static struct dce_hwseq_registers hwseq_reg;
+
+#define hwseq_reg_init() \
+       HWSEQ_DCN42_REG_LIST()
+
+#define HWSEQ_DCN42_MASK_SH_LIST(mask_sh)                                            \
+       HWSEQ_DCN_MASK_SH_LIST(mask_sh),                                                 \
+               HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \
+               HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \
+               HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh),                  \
+               HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh),                     \
+               HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh),                  \
+               HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh),                     \
+               HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh),                  \
+               HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh),                     \
+               HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh),                  \
+               HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh),                     \
+               HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh),                 \
+               HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh),                    \
+               HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh),                 \
+               HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh),                    \
+               HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh),                 \
+               HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh),                    \
+               HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+               HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+               HWS_SF(, DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh),                 \
+               HWS_SF(, DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh),                    \
+               HWS_SF(, DOMAIN23_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh),                 \
+               HWS_SF(, DOMAIN23_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh),                    \
+               HWS_SF(, DOMAIN24_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh),                 \
+               HWS_SF(, DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh),                    \
+               HWS_SF(, DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh),                 \
+               HWS_SF(, DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh),                    \
+               HWS_SF(, DOMAIN26_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh),                 \
+               HWS_SF(, DOMAIN26_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh),                    \
+               HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh),               \
+               HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh),               \
+               HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh),               \
+               HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh),               \
+               HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh),              \
+               HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh),              \
+               HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh),              \
+               HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh),              \
+               HWS_SF(, DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh),              \
+               HWS_SF(, DOMAIN23_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh),              \
+               HWS_SF(, DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh),              \
+               HWS_SF(, DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh),              \
+               HWS_SF(, DOMAIN26_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh),              \
+               HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh),                        \
+               HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh),                \
+               HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh),      \
+               HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh),                            \
+               HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh),           \
+               HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \
+               HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \
+               HWS_SF(, DMU_CLK_CNTL, DISPCLK_R_DMU_GATE_DIS, mask_sh),\
+               HWS_SF(, DMU_CLK_CNTL, DISPCLK_G_RBBMIF_GATE_DIS, mask_sh),\
+               HWS_SF(, DMU_CLK_CNTL, RBBMIF_FGCG_REP_DIS, mask_sh),\
+               HWS_SF(, DMU_CLK_CNTL, DPREFCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+               HWS_SF(, DMU_CLK_CNTL, DISPCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+               HWS_SF(, DMU_CLK_CNTL, DPPCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+               HWS_SF(, DMU_CLK_CNTL, DTBCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+               HWS_SF(, DMU_CLK_CNTL, DCFCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+               HWS_SF(, DMU_CLK_CNTL, DPIACLK_ALLOW_DS_CLKSTOP, mask_sh),\
+               HWS_SF(, DMU_CLK_CNTL, LONO_FGCG_REP_DIS, mask_sh),\
+               HWS_SF(, DMU_CLK_CNTL, LONO_DISPCLK_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DMU_CLK_CNTL, LONO_SOCCLK_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DMU_CLK_CNTL, LONO_DMCUBCLK_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_FE_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_FE_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_FE_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_FE_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_FE_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, HDMICHARCLK0_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh), \
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK0_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK1_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK2_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK3_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK4_GATE_DISABLE, mask_sh),\
+               HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK5_GATE_DISABLE, mask_sh)
+
+static const struct dce_hwseq_shift hwseq_shift = {
+       HWSEQ_DCN42_MASK_SH_LIST(__SHIFT)};
+
+static const struct dce_hwseq_mask hwseq_mask = {
+       HWSEQ_DCN42_MASK_SH_LIST(_MASK)};
+
+#define vmid_regs_init(id) \
+       DCN20_VMID_REG_LIST_RI(id)
+
+static struct dcn_vmid_registers vmid_regs[16];
+
+static const struct dcn20_vmid_shift vmid_shifts = {
+       DCN20_VMID_MASK_SH_LIST(__SHIFT)};
+
+static const struct dcn20_vmid_mask vmid_masks = {
+       DCN20_VMID_MASK_SH_LIST(_MASK)};
+
+static const struct resource_caps res_cap_dcn42 = {
+       .num_timing_generator = 4,
+       .num_opp = 4,
+       .num_dpp = 4,
+       .num_video_plane = 4,
+       .num_audio = 5,
+       .num_stream_encoder = 5,
+       .num_dig_link_enc = 5,
+       .num_usb4_dpia = 6,
+       .num_hpo_dp_stream_encoder = 4,
+       .num_hpo_dp_link_encoder = 4,
+       .num_pll = 5,
+       .num_dwb = 1,
+       .num_ddc = 5,
+       .num_vmid = 16,
+       .num_mpc_3dlut = 2,
+       .num_dsc = 4,
+};
+
+static const struct dc_plane_cap plane_cap = {
+       .type = DC_PLANE_TYPE_DCN_UNIVERSAL,
+       .per_pixel_alpha = true,
+
+       .pixel_format_support = {
+               .argb8888 = true,
+               .nv12 = true,
+               .fp16 = true,
+               .p010 = true,
+               .ayuv = false,
+       },
+
+       .max_upscale_factor = {.argb8888 = 16000, .nv12 = 16000, .fp16 = 16000},
+
+       // 6:1 downscaling ratio: 1000/6 = 166.666
+       .max_downscale_factor = {.argb8888 = 167, .nv12 = 167, .fp16 = 167},
+
+       .min_width = 64,
+       .min_height = 64};
+
+static const struct dc_debug_options debug_defaults_drv = {
+       .disable_dmcu = true,
+       .force_abm_enable = false,
+       .clock_trace = true,
+       .disable_pplib_clock_request = false,
+       .disable_dpp_power_gate = true,
+       .disable_hubp_power_gate = true,
+       .disable_optc_power_gate = true,
+       .pipe_split_policy = MPC_SPLIT_AVOID,
+       .force_single_disp_pipe_split = false,
+       .disable_dcc = DCC_ENABLE,
+       .vsr_support = true,
+       .performance_trace = false,
+       .max_downscale_src_width = 4096, /*up to 4K for APU*/
+       .disable_pplib_wm_range = false,
+       .scl_reset_length10 = true,
+       .sanity_checks = false,
+       .underflow_assert_delay_us = 0xFFFFFFFF,
+       .dwb_fi_phase = -1, // -1 = disable,
+       .dmub_command_table = true,
+       .pstate_enabled = true,
+       .enable_mem_low_power = {
+               .bits = {
+                       .vga = false,
+                       .i2c = true,
+                       .dscl = true,
+                       .cm = true,
+                       .mpc = true,
+                       .optc = true,
+                       .vpg = true,
+               }},
+       .root_clock_optimization = {
+               .bits = {
+                       .dpp = true,
+                       .dsc = true,/*dscclk and dsc pg*/
+                       .hdmistream = false,
+                       .hdmichar = true,
+                       .dpstream = true,
+                       .symclk32_se = true,
+                       .symclk32_le = true,
+                       .symclk_fe = true,
+                       .physymclk = false,
+                       .dpiasymclk = true,
+               }
+       },
+       .seamless_boot_odm_combine = DML_FAIL_SOURCE_PIXEL_FORMAT,
+       .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/
+       .minimum_z8_residency_time = 1, /* Always allow when other conditions are met */
+       .support_eDP1_5 = true,
+       .use_max_lb = true,
+       .force_disable_subvp = false,
+       .exit_idle_opt_for_cursor_updates = true,
+       .using_dml2 = true,
+       .using_dml21 = true,
+       .enable_single_display_2to1_odm_policy = true,
+
+       // must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions
+       .enable_double_buffered_dsc_pg_support = true,
+       .enable_dp_dig_pixel_rate_div_policy = 1,
+       .allow_sw_cursor_fallback = false,
+       .psp_disabled_wa = true,
+       .alloc_extra_way_for_cursor = true,
+       .min_prefetch_in_strobe_ns = 60000, // 60us
+       .disable_unbounded_requesting = false,
+       .dcc_meta_propagation_delay_us = 10,
+       .disable_timeout = true,
+       .min_disp_clk_khz = 50000,
+       .disable_z10 = false,
+       .ignore_pg = true,
+       .disable_stutter_for_wm_program = true,
+};
+
+static const struct dc_check_config config_defaults = {
+       .enable_legacy_fast_update = false,
+};
+
+static struct dce_aux *dcn42_aux_engine_create(
+       struct dc_context *ctx,
+       uint32_t inst)
+{
+       struct aux_engine_dce110 *aux_engine =
+               kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL);
+
+       if (!aux_engine)
+               return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT aux_engine_regs
+       aux_engine_regs_init(0),
+               aux_engine_regs_init(1),
+               aux_engine_regs_init(2),
+               aux_engine_regs_init(3),
+               aux_engine_regs_init(4);
+
+       dce110_aux_engine_construct(aux_engine, ctx, inst,
+                                                               SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
+                                                               &aux_engine_regs[inst],
+                                                               &aux_mask,
+                                                               &aux_shift,
+                                                               ctx->dc->caps.extended_aux_timeout_support);
+
+       return &aux_engine->base;
+}
+
+#define i2c_inst_regs_init(id) \
+       I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id)
+
+static struct dce_i2c_registers i2c_hw_regs[5];
+
+static const struct dce_i2c_shift i2c_shifts = {
+       I2C_COMMON_MASK_SH_LIST_DCN35(__SHIFT)
+};
+static const struct dce_i2c_mask i2c_masks = {
+       I2C_COMMON_MASK_SH_LIST_DCN35(_MASK)
+};
+
+/* ========================================================== */
+
+/*
+ * DPIA index | Preferred Encoder     |    Host Router
+ *   0        |      C                |       0
+ *   1        |      First Available  |       0
+ *   2        |      D                |       1
+ *   3        |      First Available  |       1
+ *   4        |      E                |       2
+ *   5        |      First Available  |       2
+ */
+/* ========================================================== */
+static const enum engine_id dpia_to_preferred_enc_id_table[] = {
+               ENGINE_ID_DIGC,
+               ENGINE_ID_DIGC,
+               ENGINE_ID_DIGD,
+               ENGINE_ID_DIGD,
+               ENGINE_ID_DIGE,
+               ENGINE_ID_DIGE
+};
+
+static enum engine_id dcn42_get_preferred_eng_id_dpia(unsigned int dpia_index)
+{
+       return dpia_to_preferred_enc_id_table[dpia_index];
+}
+
+static struct dce_i2c_hw *dcn42_i2c_hw_create(
+       struct dc_context *ctx,
+       uint32_t inst)
+{
+       struct dce_i2c_hw *dce_i2c_hw =
+               kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL);
+
+       if (!dce_i2c_hw)
+               return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT i2c_hw_regs
+       i2c_inst_regs_init(1),
+       i2c_inst_regs_init(2),
+       i2c_inst_regs_init(3),
+       i2c_inst_regs_init(4),
+       i2c_inst_regs_init(5);
+       dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst,
+                                                 &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks);
+
+       return dce_i2c_hw;
+}
+
+static struct clock_source *dcn42_clock_source_create(
+       struct dc_context *ctx,
+       struct dc_bios *bios,
+       enum clock_source_id id,
+       const struct dce110_clk_src_regs *regs,
+       bool dp_clk_src)
+{
+       struct dce110_clk_src *clk_src =
+               kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL);
+
+       if (!clk_src)
+               return NULL;
+
+       if (dcn401_clk_src_construct(clk_src, ctx, bios, id,
+                                                                regs, &cs_shift, &cs_mask)) {
+               clk_src->base.dp_clk_src = dp_clk_src;
+               return &clk_src->base;
+       }
+
+       kfree(clk_src);
+       BREAK_TO_DEBUGGER();
+       return NULL;
+}
+
+static struct hubbub *dcn42_hubbub_create(struct dc_context *ctx)
+{
+       int i;
+
+       struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub),
+                                         GFP_KERNEL);
+
+       if (!hubbub3)
+               return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT hubbub_reg
+       hubbub_reg_init();
+
+#undef REG_STRUCT
+#define REG_STRUCT vmid_regs
+       vmid_regs_init(0),
+               vmid_regs_init(1),
+               vmid_regs_init(2),
+               vmid_regs_init(3),
+               vmid_regs_init(4),
+               vmid_regs_init(5),
+               vmid_regs_init(6),
+               vmid_regs_init(7),
+               vmid_regs_init(8),
+               vmid_regs_init(9),
+               vmid_regs_init(10),
+               vmid_regs_init(11),
+               vmid_regs_init(12),
+               vmid_regs_init(13),
+               vmid_regs_init(14),
+               vmid_regs_init(15);
+
+       hubbub42_construct(hubbub3, ctx,
+                                          &hubbub_reg,
+                                          &hubbub_shift,
+                                          &hubbub_mask,
+                                          DCN42_DEFAULT_DET_SIZE,
+                                          8,
+                                          DCN42_CRB_SIZE_KB);
+       for (i = 0; i < res_cap_dcn42.num_vmid; i++) {
+               struct dcn20_vmid *vmid = &hubbub3->vmid[i];
+
+               vmid->ctx = ctx;
+
+               vmid->regs = &vmid_regs[i];
+               vmid->shifts = &vmid_shifts;
+               vmid->masks = &vmid_masks;
+       }
+
+       return &hubbub3->base;
+}
+
+static struct hubp *dcn42_hubp_create(
+       struct dc_context *ctx,
+       uint32_t inst)
+{
+       struct dcn20_hubp *hubp2 =
+               kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL);
+
+       if (!hubp2)
+               return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT hubp_regs
+       hubp_regs_init(0),
+               hubp_regs_init(1),
+               hubp_regs_init(2),
+               hubp_regs_init(3);
+
+       if (hubp42_construct(hubp2, ctx, inst,
+                                                &hubp_regs[inst], &hubp_shift, &hubp_mask))
+               return &hubp2->base;
+
+       BREAK_TO_DEBUGGER();
+       kfree(hubp2);
+       return NULL;
+}
+static const struct dc_panel_config dcn42_panel_config_defaults = {
+       .psr = {
+               .disable_psr = false,
+               .disallow_psrsu = false,
+               .disallow_replay = false,
+       },
+       .ilr = {
+               .optimize_edp_link_rate = true,
+       },
+};
+
+static void dcn42_dpp_destroy(struct dpp **dpp)
+{
+       kfree(TO_DCN42_DPP(*dpp));
+       *dpp = NULL;
+}
+
+static struct dpp *dcn42_dpp_create(
+       struct dc_context *ctx,
+       uint32_t inst)
+{
+       struct dcn42_dpp *dpp42 =
+               kzalloc(sizeof(struct dcn42_dpp), GFP_KERNEL);
+
+       if (!dpp42)
+               return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT dpp_regs
+       dpp_regs_init(0),
+               dpp_regs_init(1),
+               dpp_regs_init(2),
+               dpp_regs_init(3);
+
+       if (dpp42_construct(dpp42, ctx, inst,
+                                               &dpp_regs[inst], &tf_shift, &tf_mask))
+               return &dpp42->base;
+
+       BREAK_TO_DEBUGGER();
+       kfree(dpp42);
+       return NULL;
+}
+
+static struct mpc *dcn42_mpc_create(
+       struct dc_context *ctx,
+       int num_mpcc,
+       int num_rmu)
+{
+       struct dcn42_mpc *mpc401 = kzalloc(sizeof(struct dcn42_mpc),
+                                                                               GFP_KERNEL);
+
+       if (!mpc401)
+               return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT mpc_regs
+       dcn_mpc_regs_init();
+
+       dcn42_mpc_construct(mpc401, ctx,
+                                                &mpc_regs,
+                                                &mpc_shift,
+                                                &mpc_mask,
+                                                num_mpcc,
+                                                num_rmu);
+
+       return &mpc401->base;
+}
+
+static struct output_pixel_processor *dcn42_opp_create(
+       struct dc_context *ctx, uint32_t inst)
+{
+       struct dcn20_opp *opp4 =
+               kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL);
+
+       if (!opp4) {
+               BREAK_TO_DEBUGGER();
+               return NULL;
+       }
+
+#undef REG_STRUCT
+#define REG_STRUCT opp_regs
+       opp_regs_init(0),
+               opp_regs_init(1),
+               opp_regs_init(2),
+               opp_regs_init(3);
+       dcn20_opp_construct(opp4, ctx, inst,
+                                               &opp_regs[inst], &opp_shift, &opp_mask);
+       return &opp4->base;
+}
+
+static struct timing_generator *dcn42_timing_generator_create(
+       struct dc_context *ctx,
+       uint32_t instance)
+{
+       struct optc *tgn10 =
+               kzalloc(sizeof(struct optc), GFP_KERNEL);
+
+       if (!tgn10)
+               return NULL;
+#undef REG_STRUCT
+#define REG_STRUCT optc_regs
+       optc_regs_init(0),
+               optc_regs_init(1),
+               optc_regs_init(2),
+               optc_regs_init(3);
+       tgn10->base.inst = instance;
+       tgn10->base.ctx = ctx;
+
+       tgn10->tg_regs = &optc_regs[instance];
+       tgn10->tg_shift = &optc_shift;
+       tgn10->tg_mask = &optc_mask;
+
+       dcn42_timing_generator_init(tgn10);
+
+       return &tgn10->base;
+}
+
+static const struct encoder_feature_support link_enc_feature = {
+       .max_hdmi_deep_color = COLOR_DEPTH_121212,
+       .max_hdmi_pixel_clock = 600000,
+       .hdmi_ycbcr420_supported = true,
+       .dp_ycbcr420_supported = true,
+       .fec_supported = true,
+       .flags.bits.IS_HBR2_CAPABLE = true,
+       .flags.bits.IS_HBR3_CAPABLE = true,
+       .flags.bits.IS_TPS3_CAPABLE = true,
+       .flags.bits.IS_TPS4_CAPABLE = true};
+
+static struct link_encoder *dcn42_link_encoder_create(
+       struct dc_context *ctx,
+       const struct encoder_init_data *enc_init_data)
+{
+       struct dcn20_link_encoder *enc20 =
+               kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);
+
+       if (!enc20 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
+               return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT link_enc_aux_regs
+       aux_regs_init(0),
+               aux_regs_init(1),
+               aux_regs_init(2),
+               aux_regs_init(3),
+               aux_regs_init(4);
+#undef REG_STRUCT
+#define REG_STRUCT link_enc_hpd_regs
+       hpd_regs_init(0),
+               hpd_regs_init(1),
+               hpd_regs_init(2),
+               hpd_regs_init(3),
+               hpd_regs_init(4);
+#undef REG_STRUCT
+#define REG_STRUCT link_enc_regs
+       link_regs_init(0, A),
+               link_regs_init(1, B),
+               link_regs_init(2, C),
+               link_regs_init(3, D),
+               link_regs_init(4, E);
+
+       dcn42_link_encoder_construct(enc20,
+                                                                 enc_init_data,
+                                                                 &link_enc_feature,
+                                                                 &link_enc_regs[enc_init_data->transmitter],
+                                                                 &link_enc_aux_regs[enc_init_data->channel - 1],
+                                                                 &link_enc_hpd_regs[enc_init_data->hpd_source],
+                                                                 &le_shift,
+                                                                 &le_mask);
+       return &enc20->enc10.base;
+}
+
+static void read_dce_straps(
+       struct dc_context *ctx,
+       struct resource_straps *straps)
+{
+       generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX),
+               FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio);
+}
+
+static struct audio *dcn42_create_audio(
+       struct dc_context *ctx, unsigned int inst)
+{
+
+#undef REG_STRUCT
+#define REG_STRUCT audio_regs
+       audio_regs_init(0),
+               audio_regs_init(1),
+               audio_regs_init(2),
+               audio_regs_init(3),
+               audio_regs_init(4);
+
+       return dce_audio_create(ctx, inst,
+                                                       &audio_regs[inst], &audio_shift, &audio_mask);
+}
+
+static struct vpg *dcn42_vpg_create(
+       struct dc_context *ctx,
+       uint32_t inst)
+{
+       struct dcn31_vpg *vpg4 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL);
+
+       if (!vpg4)
+               return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT vpg_regs
+       vpg_regs_init(0),
+               vpg_regs_init(1),
+               vpg_regs_init(2),
+               vpg_regs_init(3),
+               vpg_regs_init(4),
+               vpg_regs_init(5),
+               vpg_regs_init(6),
+               vpg_regs_init(7),
+               vpg_regs_init(8),
+               vpg_regs_init(9);
+       vpg31_construct(vpg4, ctx, inst,
+                                       &vpg_regs[inst],
+                                       &vpg_shift,
+                                       &vpg_mask);
+
+       return &vpg4->base;
+}
+
+static struct apg *dcn42_apg_create(
+       struct dc_context *ctx,
+       uint32_t inst)
+{
+       struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL);
+
+       if (!apg31)
+               return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT apg_regs
+       apg_regs_init(0),
+               apg_regs_init(1),
+               apg_regs_init(2),
+               apg_regs_init(3),
+               apg_regs_init(4),
+               apg_regs_init(5),
+               apg_regs_init(6),
+               apg_regs_init(7),
+               apg_regs_init(8),
+               apg_regs_init(9);
+
+       apg31_construct(apg31, ctx, inst,
+                                       &apg_regs[inst],
+                                       &apg_shift,
+                                       &apg_mask);
+
+       return &apg31->base;
+}
+
+static struct stream_encoder *dcn42_stream_encoder_create(
+       enum engine_id eng_id,
+       struct dc_context *ctx)
+{
+       struct dcn10_stream_encoder *enc1;
+       struct vpg *vpg;
+       struct apg *apg;
+
+       uint32_t vpg_inst;
+       uint32_t apg_inst;
+
+       /* Mapping of VPG, DME register blocks to DIO block instance */
+       if (eng_id <= ENGINE_ID_DIGE) {
+               vpg_inst = eng_id;
+               apg_inst = eng_id;
+       } else
+               return NULL;
+
+       enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
+       vpg = dcn42_vpg_create(ctx, vpg_inst);
+       apg = dcn42_apg_create(ctx, apg_inst);
+
+       if (!enc1 || !vpg || !apg) {
+               kfree(enc1);
+               kfree(vpg);
+               kfree(apg);
+               return NULL;
+       }
+#undef REG_STRUCT
+#define REG_STRUCT stream_enc_regs
+       stream_enc_regs_init(0),
+               stream_enc_regs_init(1),
+               stream_enc_regs_init(2),
+               stream_enc_regs_init(3),
+               stream_enc_regs_init(4);
+
+       dcn42_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios,
+                                                                       eng_id, vpg, apg,
+                                                                       &stream_enc_regs[eng_id],
+                                                                       &se_shift, &se_mask);
+       return &enc1->base;
+}
+
+static struct hpo_dp_stream_encoder *dcn42_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[5] -> HPO_DP[0]
+        * VPG[6] -> HPO_DP[1]
+        * VPG[7] -> HPO_DP[2]
+        * VPG[8] -> HPO_DP[3]
+        */
+       vpg_inst = hpo_dp_inst + 5;
+
+       /* Mapping of APG register blocks to HPO DP block instance:
+        * APG[6] -> HPO_DP[0]
+        * APG[7] -> HPO_DP[1]
+        * APG[8] -> HPO_DP[2]
+        * APG[9] -> HPO_DP[3]
+        */
+       apg_inst = hpo_dp_inst + 5;
+
+       /* allocate HPO stream encoder and create VPG sub-block */
+       hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL);
+       vpg = dcn42_vpg_create(ctx, vpg_inst);
+       apg = dcn42_apg_create(ctx, apg_inst);
+
+       if (!hpo_dp_enc31 || !vpg || !apg) {
+               kfree(hpo_dp_enc31);
+               kfree(vpg);
+               kfree(apg);
+               return NULL;
+       }
+
+#undef REG_STRUCT
+#define REG_STRUCT hpo_dp_stream_enc_regs
+       hpo_dp_stream_encoder_reg_init(0),
+               hpo_dp_stream_encoder_reg_init(1),
+               hpo_dp_stream_encoder_reg_init(2),
+               hpo_dp_stream_encoder_reg_init(3);
+
+       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 hpo_dp_link_encoder *dcn42_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);
+       if (!hpo_dp_enc31)
+               return NULL; /* out of memory */
+
+#undef REG_STRUCT
+#define REG_STRUCT hpo_dp_link_enc_regs
+       hpo_dp_link_encoder_reg_init(0),
+       hpo_dp_link_encoder_reg_init(1),
+       hpo_dp_link_encoder_reg_init(2),
+       hpo_dp_link_encoder_reg_init(3);
+
+       hpo_dp_link_encoder42_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 *dcn42_hwseq_create(
+       struct dc_context *ctx)
+{
+       struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL);
+
+#undef REG_STRUCT
+#define REG_STRUCT hwseq_reg
+       hwseq_reg_init();
+
+       if (hws) {
+               hws->ctx = ctx;
+               hws->regs = &hwseq_reg;
+               hws->shifts = &hwseq_shift;
+               hws->masks = &hwseq_mask;
+       }
+
+       return hws;
+}
+
+static const struct resource_create_funcs res_create_funcs = {
+       .read_dce_straps = read_dce_straps,
+       .create_audio = dcn42_create_audio,
+       .create_stream_encoder = dcn42_stream_encoder_create,
+       .create_hpo_dp_stream_encoder = dcn42_hpo_dp_stream_encoder_create,
+       .create_hpo_dp_link_encoder = dcn42_hpo_dp_link_encoder_create,
+       .create_hwseq = dcn42_hwseq_create,
+};
+
+static void dcn42_dsc_destroy(struct display_stream_compressor **dsc)
+{
+       kfree(container_of(*dsc, struct dcn401_dsc, base));
+       *dsc = NULL;
+}
+
+static void dcn42_resource_destruct(struct dcn42_resource_pool *pool)
+{
+       unsigned int i;
+
+       for (i = 0; i < pool->base.stream_enc_count; i++) {
+               if (pool->base.stream_enc[i] != NULL) {
+                       if (pool->base.stream_enc[i]->vpg != NULL) {
+                               kfree(DCN31_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg));
+                               pool->base.stream_enc[i]->vpg = NULL;
+                       }
+                       if (pool->base.stream_enc[i]->apg != NULL) {
+                               kfree(DCN31_APG_FROM_APG(pool->base.stream_enc[i]->apg));
+                               pool->base.stream_enc[i]->apg = NULL;
+                       }
+                       kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i]));
+                       pool->base.stream_enc[i] = NULL;
+               }
+       }
+
+       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(DCN31_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.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)
+                       dcn42_dsc_destroy(&pool->base.dscs[i]);
+       }
+
+       if (pool->base.mpc != NULL) {
+               kfree(TO_DCN20_MPC(pool->base.mpc));
+               pool->base.mpc = NULL;
+       }
+       if (pool->base.hubbub != NULL) {
+               kfree(TO_DCN20_HUBBUB(pool->base.hubbub));
+               pool->base.hubbub = NULL;
+       }
+       for (i = 0; i < pool->base.pipe_count; i++) {
+               if (pool->base.dpps[i] != NULL)
+                       dcn42_dpp_destroy(&pool->base.dpps[i]);
+
+               if (pool->base.ipps[i] != NULL)
+                       pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]);
+
+               if (pool->base.hubps[i] != NULL) {
+                       kfree(TO_DCN20_HUBP(pool->base.hubps[i]));
+                       pool->base.hubps[i] = NULL;
+               }
+
+               if (pool->base.irqs != NULL)
+                       dal_irq_service_destroy(&pool->base.irqs);
+       }
+
+       for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
+               if (pool->base.engines[i] != NULL)
+                       dce110_engine_destroy(&pool->base.engines[i]);
+               if (pool->base.hw_i2cs[i] != NULL) {
+                       kfree(pool->base.hw_i2cs[i]);
+                       pool->base.hw_i2cs[i] = NULL;
+               }
+               if (pool->base.sw_i2cs[i] != NULL) {
+                       kfree(pool->base.sw_i2cs[i]);
+                       pool->base.sw_i2cs[i] = NULL;
+               }
+       }
+
+       for (i = 0; i < pool->base.res_cap->num_opp; i++) {
+               if (pool->base.opps[i] != NULL)
+                       pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]);
+       }
+
+       for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
+               if (pool->base.timing_generators[i] != NULL) {
+                       kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i]));
+                       pool->base.timing_generators[i] = NULL;
+               }
+       }
+
+       for (i = 0; i < pool->base.res_cap->num_dwb; i++) {
+               if (pool->base.dwbc[i] != NULL) {
+                       kfree(TO_DCN30_DWBC(pool->base.dwbc[i]));
+                       pool->base.dwbc[i] = NULL;
+               }
+               if (pool->base.mcif_wb[i] != NULL) {
+                       kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i]));
+                       pool->base.mcif_wb[i] = NULL;
+               }
+       }
+
+       for (i = 0; i < pool->base.audio_count; i++) {
+               if (pool->base.audios[i])
+                       dce_aud_destroy(&pool->base.audios[i]);
+       }
+
+       for (i = 0; i < pool->base.clk_src_count; i++) {
+               if (pool->base.clock_sources[i] != NULL) {
+                       dcn20_clock_source_destroy(&pool->base.clock_sources[i]);
+                       pool->base.clock_sources[i] = NULL;
+               }
+       }
+
+       for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) {
+               if (pool->base.mpc_lut[i] != NULL) {
+                       dc_3dlut_func_release(pool->base.mpc_lut[i]);
+                       pool->base.mpc_lut[i] = NULL;
+               }
+               if (pool->base.mpc_shaper[i] != NULL) {
+                       dc_transfer_func_release(pool->base.mpc_shaper[i]);
+                       pool->base.mpc_shaper[i] = NULL;
+               }
+       }
+
+       if (pool->base.dp_clock_source != NULL) {
+               dcn20_clock_source_destroy(&pool->base.dp_clock_source);
+               pool->base.dp_clock_source = NULL;
+       }
+
+       for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
+               if (pool->base.multiple_abms[i] != NULL)
+                       dce_abm_destroy(&pool->base.multiple_abms[i]);
+       }
+
+       if (pool->base.psr != NULL)
+               dmub_psr_destroy(&pool->base.psr);
+
+       if (pool->base.pg_cntl != NULL)
+               dcn_pg_cntl_destroy(&pool->base.pg_cntl);
+       if (pool->base.dccg != NULL)
+               dcn_dccg_destroy(&pool->base.dccg);
+
+       if (pool->base.oem_device != NULL) {
+               struct dc *dc = pool->base.oem_device->ctx->dc;
+
+               dc->link_srv->destroy_ddc_service(&pool->base.oem_device);
+       }
+}
+
+static void dcn42_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx)
+{
+       const struct dc_stream_state *stream = pipe_ctx->stream;
+       struct dc_link *link = stream->link;
+       struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc;
+       struct pixel_clk_params *pixel_clk_params = &pipe_ctx->stream_res.pix_clk_params;
+
+       pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz;
+
+       if (pipe_ctx->dsc_padding_params.dsc_hactive_padding != 0)
+               pixel_clk_params->requested_pix_clk_100hz = pipe_ctx->dsc_padding_params.dsc_pix_clk_100hz;
+
+       if (!pipe_ctx->stream->ctx->dc->config.unify_link_enc_assignment)
+               link_enc = link_enc_cfg_get_link_enc(link);
+       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*/
+
+       /* 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;
+       pixel_clk_params->color_depth =
+               stream->timing.display_color_depth;
+       pixel_clk_params->flags.DISPLAY_BLANKED = 1;
+       pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding;
+
+       if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
+               pixel_clk_params->color_depth = COLOR_DEPTH_888;
+
+       if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
+               pixel_clk_params->requested_pix_clk_100hz *= 2;
+       if (dc_is_tmds_signal(stream->signal) &&
+                       stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
+               pixel_clk_params->requested_pix_clk_100hz /= 2;
+
+       pipe_ctx->clock_source->funcs->get_pix_clk_dividers(
+                       pipe_ctx->clock_source,
+                       &pipe_ctx->stream_res.pix_clk_params,
+                       &pipe_ctx->pll_settings);
+
+       pixel_clk_params->dio_se_pix_per_cycle = 1;
+       if (dc_is_tmds_signal(stream->signal) &&
+                       stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
+               pixel_clk_params->dio_se_pix_per_cycle = 2;
+       } else if (dc_is_dp_signal(stream->signal)) {
+               /* round up to nearest power of 2, or max at 8 pixels per cycle */
+               if (pixel_clk_params->requested_pix_clk_100hz > 4 * stream->ctx->dc->clk_mgr->dprefclk_khz * 10) {
+                       pixel_clk_params->dio_se_pix_per_cycle = 8;
+               } else if (pixel_clk_params->requested_pix_clk_100hz > 2 * stream->ctx->dc->clk_mgr->dprefclk_khz * 10) {
+                       pixel_clk_params->dio_se_pix_per_cycle = 4;
+               } else if (pixel_clk_params->requested_pix_clk_100hz > stream->ctx->dc->clk_mgr->dprefclk_khz * 10) {
+                       pixel_clk_params->dio_se_pix_per_cycle = 2;
+               } else {
+                       pixel_clk_params->dio_se_pix_per_cycle = 1;
+               }
+       }
+}
+
+static bool dcn42_dwbc_create(struct dc_context *ctx, struct resource_pool *pool)
+{
+       int i;
+       uint32_t dwb_count = pool->res_cap->num_dwb;
+
+       for (i = 0; i < dwb_count; i++) {
+               struct dcn30_dwbc *dwbc42 = kzalloc(sizeof(struct dcn30_dwbc),
+                                                                                       GFP_KERNEL);
+
+               if (!dwbc42) {
+                       dm_error("DC: failed to create dwbc42!\n");
+                       return false;
+               }
+
+#undef REG_STRUCT
+#define REG_STRUCT dwbc401_regs
+               dwbc_regs_dcn401_init(0);
+
+               dcn30_dwbc_construct(dwbc42, ctx,
+                               &dwbc401_regs[i],
+                               &dwbc401_shift,
+                               &dwbc401_mask,
+                               i);
+
+               pool->dwbc[i] = &dwbc42->base;
+       }
+       return true;
+}
+
+static void dcn42_mmhubbub_init(struct dcn30_mmhubbub *mcif_wb30,
+                                                               struct dc_context *ctx)
+{
+       dcn42_mmhubbub_set_fgcg(
+               mcif_wb30,
+               ctx->dc->debug.enable_fine_grain_clock_gating.bits.mmhubbub);
+}
+
+static bool dcn42_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool)
+{
+       int i;
+       uint32_t pipe_count = pool->res_cap->num_dwb;
+
+       for (i = 0; i < pipe_count; i++) {
+               struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub),
+                                                                                                  GFP_KERNEL);
+
+               if (!mcif_wb30) {
+                       dm_error("DC: failed to create mcif_wb30!\n");
+                       return false;
+               }
+
+#undef REG_STRUCT
+#define REG_STRUCT mcif_wb35_regs
+               mcif_wb_regs_dcn3_init(0);
+
+               dcn35_mmhubbub_construct(mcif_wb30, ctx,
+                                       &mcif_wb35_regs[i],
+                                       &mcif_wb35_shift,
+                                       &mcif_wb35_mask,
+                                       i);
+
+               dcn42_mmhubbub_init(mcif_wb30, ctx);
+
+               pool->mcif_wb[i] = &mcif_wb30->base;
+       }
+       return true;
+}
+
+static struct display_stream_compressor *dcn42_dsc_create(
+       struct dc_context *ctx, uint32_t inst)
+{
+       struct dcn401_dsc *dsc =
+               kzalloc(sizeof(struct dcn401_dsc), GFP_KERNEL);
+
+       if (!dsc) {
+               BREAK_TO_DEBUGGER();
+               return NULL;
+       }
+
+#undef REG_STRUCT
+#define REG_STRUCT dsc_regs
+       dsc_regs_init(0),
+               dsc_regs_init(1),
+               dsc_regs_init(2),
+               dsc_regs_init(3);
+
+       dsc401_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask);
+       dsc401_set_fgcg(dsc, ctx->dc->debug.enable_fine_grain_clock_gating.bits.dsc);
+
+       dsc->max_image_width = 5760;
+
+       return &dsc->base;
+}
+
+static void dcn42_destroy_resource_pool(struct resource_pool **pool)
+{
+       struct dcn42_resource_pool *dcn42_pool = TO_DCN42_RES_POOL(*pool);
+
+       dcn42_resource_destruct(dcn42_pool);
+       kfree(dcn42_pool);
+       *pool = NULL;
+}
+
+static struct dc_cap_funcs cap_funcs = {
+       .get_dcc_compression_cap = dcn20_get_dcc_compression_cap};
+
+static void dcn42_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
+{
+       DC_FP_START();
+       if (dc->current_state && dc->current_state->bw_ctx.dml2)
+               dml2_reinit(dc, &dc->dml2_options, &dc->current_state->bw_ctx.dml2);
+       DC_FP_END();
+}
+
+enum dc_status dcn42_validate_bandwidth(struct dc *dc,
+                                                         struct dc_state *context,
+                                                         enum dc_validate_mode validate_mode)
+{
+       bool out = false;
+
+       out = dml2_validate(dc, context, context->bw_ctx.dml2,
+                                               validate_mode);
+       DC_FP_START();
+       if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING) {
+               /*not required for mode enumeration*/
+               dcn42_decide_zstate_support(dc, context);
+       }
+       DC_FP_END();
+       return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
+}
+void dcn42_prepare_mcache_programming(struct dc *dc,
+                                                                         struct dc_state *context)
+{
+       if (dc->debug.using_dml21)
+               dml2_prepare_mcache_programming(dc, context,
+                       context->power_source == DC_POWER_SOURCE_DC ?
+                               context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2);
+}
+/* Create a minimal link encoder object not associated with a particular
+ * physical connector.
+ * resource_funcs.link_enc_create_minimal
+ */
+static struct link_encoder *dcn42_link_enc_create_minimal(
+               struct dc_context *ctx, enum engine_id eng_id)
+{
+       struct dcn20_link_encoder *enc20;
+
+       if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc)
+               return NULL;
+
+       enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);
+       if (!enc20)
+               return NULL;
+
+       dcn31_link_encoder_construct_minimal(
+                       enc20,
+                       ctx,
+                       &link_enc_feature,
+                       &link_enc_regs[eng_id - ENGINE_ID_DIGA],
+                       eng_id);
+
+       return &enc20->enc10.base;
+}
+static void dcn42_get_panel_config_defaults(struct dc_panel_config *panel_config)
+{
+       *panel_config = dcn42_panel_config_defaults;
+}
+static unsigned int dcn42_get_max_hw_cursor_size(const struct dc *dc,
+                       struct dc_state *state,
+                       const struct dc_stream_state *stream)
+{
+       return dc->caps.max_cursor_size;
+}
+static struct resource_funcs dcn42_res_pool_funcs = {
+       .destroy = dcn42_destroy_resource_pool,
+       .link_enc_create = dcn42_link_encoder_create,
+       .link_enc_create_minimal = dcn42_link_enc_create_minimal,
+       .link_encs_assign = link_enc_cfg_link_encs_assign,
+       .link_enc_unassign = link_enc_cfg_link_enc_unassign,
+       .panel_cntl_create = dcn32_panel_cntl_create,
+       .validate_bandwidth = dcn42_validate_bandwidth,
+       .calculate_wm_and_dlg = NULL,
+       .populate_dml_pipes = NULL,
+       .acquire_free_pipe_as_secondary_dpp_pipe = dcn32_acquire_free_pipe_as_secondary_dpp_pipe,
+       .acquire_free_pipe_as_secondary_opp_head = dcn32_acquire_free_pipe_as_secondary_opp_head,
+       .release_pipe = dcn20_release_pipe,
+       .add_stream_to_ctx = dcn30_add_stream_to_ctx,
+       .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
+       .remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
+       .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context,
+       .set_mcif_arb_params = dcn30_set_mcif_arb_params,
+       .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
+       .acquire_post_bldn_3dlut = dcn32_acquire_post_bldn_3dlut,
+       .release_post_bldn_3dlut = dcn32_release_post_bldn_3dlut,
+       .update_bw_bounding_box = dcn42_update_bw_bounding_box,
+       .patch_unknown_plane_state = dcn401_patch_unknown_plane_state,
+       .get_panel_config_defaults = dcn42_get_panel_config_defaults,
+       .get_preferred_eng_id_dpia = dcn42_get_preferred_eng_id_dpia,
+       .update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
+       .add_phantom_pipes = dcn32_add_phantom_pipes,
+       .calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
+       .prepare_mcache_programming = dcn42_prepare_mcache_programming,
+       .build_pipe_pix_clk_params = dcn42_build_pipe_pix_clk_params,
+       .get_vstartup_for_pipe = dcn401_get_vstartup_for_pipe,
+       .get_max_hw_cursor_size = dcn42_get_max_hw_cursor_size,
+};
+
+static uint32_t read_pipe_fuses(struct dc_context *ctx)
+{
+       uint32_t value = REG_READ(CC_DC_PIPE_DIS);
+
+       if (value == 0 && ctx->dce_environment == DCE_ENV_DIAG)
+               value = 0xF;
+       /* DCN401 support max 4 pipes */
+       value = value & 0xf;
+       return value;
+}
+
+static bool dcn42_resource_construct(
+       uint8_t num_virtual_links,
+       struct dc *dc,
+       struct dcn42_resource_pool *pool)
+{
+       int i, j;
+       struct dc_context *ctx = dc->ctx;
+       struct irq_service_init_data init_data;
+       uint32_t pipe_fuses = 0;
+       uint32_t num_pipes = 4;
+
+#undef REG_STRUCT
+#define REG_STRUCT bios_regs
+       bios_regs_init();
+
+#undef REG_STRUCT
+#define REG_STRUCT clk_src_regs
+       clk_src_regs_init(0, A),
+       clk_src_regs_init(1, B),
+       clk_src_regs_init(2, C),
+       clk_src_regs_init(3, D),
+       clk_src_regs_init(4, E);
+
+#undef REG_STRUCT
+#define REG_STRUCT abm_regs
+       abm_regs_init(0),
+               abm_regs_init(1),
+               abm_regs_init(2),
+               abm_regs_init(3);
+#undef REG_STRUCT
+#define REG_STRUCT dccg_regs
+       dccg_regs_init();
+
+       ctx->dc_bios->regs = &bios_regs;
+
+       pool->base.res_cap = &res_cap_dcn42;
+
+       /* max number of pipes for ASIC before checking for pipe fuses */
+       num_pipes = pool->base.res_cap->num_dpp;
+       pipe_fuses = read_pipe_fuses(ctx);
+
+       for (i = 0; i < pool->base.res_cap->num_dpp; i++)
+               if (pipe_fuses & 1 << i)
+                       num_pipes--;
+
+       if (pipe_fuses & 1)
+               ASSERT(0); // Unexpected - Pipe 0 should always be fully functional!
+
+       if (pipe_fuses & CC_DC_PIPE_DIS__DC_FULL_DIS_MASK)
+               ASSERT(0); // Entire DCN is harvested!
+
+       pool->base.funcs = &dcn42_res_pool_funcs;
+
+       /*************************************************
+        *  Resource + asic cap harcoding                *
+        *************************************************/
+       pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+       pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator;
+       pool->base.pipe_count = num_pipes;
+       pool->base.mpcc_count = num_pipes;
+       dc->caps.ips_v2_support = true;
+       dc->caps.max_downscale_ratio = 600;
+       dc->caps.i2c_speed_in_khz = 100;
+       dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a applied by default*/
+       /* TODO: Bring max cursor size back to 256 after subvp cursor corruption is fixed*/
+       dc->caps.max_cursor_size = 64;
+       dc->caps.max_buffered_cursor_size = 64;
+       dc->caps.cursor_not_scaled = true;
+       dc->caps.min_horizontal_blanking_period = 80;
+       dc->caps.dmdata_alloc_size = 2048;
+       dc->caps.mall_size_per_mem_channel = 4;
+       /* total size = mall per channel * num channels * 1024 * 1024 */
+       dc->caps.mall_size_total = dc->caps.mall_size_per_mem_channel *
+               dc->ctx->dc_bios->vram_info.num_chans * 1048576;
+       dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8;
+       dc->caps.cache_line_size = 64;
+       dc->caps.cache_num_ways = 16;
+
+       /* Calculate the available MALL space */
+       dc->caps.max_cab_allocation_bytes =
+               dcn32_calc_num_avail_chans_for_mall(dc, dc->ctx->dc_bios->vram_info.num_chans) *
+                               dc->caps.mall_size_per_mem_channel * 1024 * 1024;
+       dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes;
+
+       dc->caps.subvp_fw_processing_delay_us = 15;
+       dc->caps.subvp_drr_max_vblank_margin_us = 40;
+       dc->caps.subvp_prefetch_end_to_mall_start_us = 15;
+       dc->caps.subvp_swath_height_margin_lines = 16;
+       dc->caps.subvp_pstate_allow_width_us = 20;
+       dc->caps.subvp_vertical_int_margin_us = 30;
+       dc->caps.subvp_drr_vblank_start_margin_us = 100; // 100us margin
+
+       dc->caps.max_slave_planes = 2;
+       dc->caps.max_slave_yuv_planes = 2;
+       dc->caps.max_slave_rgb_planes = 2;
+       dc->caps.post_blend_color_processing = true;
+       dc->caps.force_dp_tps4_for_cp2520 = true;
+       if (dc->config.forceHBR2CP2520)
+               dc->caps.force_dp_tps4_for_cp2520 = false;
+       dc->caps.dp_hdmi21_pcon_support = true;
+       dc->caps.dp_hpo = true;
+       dc->caps.edp_dsc_support = true;
+       dc->caps.extended_aux_timeout_support = true;
+       dc->caps.dmcub_support = true;
+       dc->caps.is_apu = true;
+       dc->caps.seamless_odm = true;
+       dc->caps.zstate_support = true;
+       dc->caps.ips_support = true;
+       dc->caps.max_v_total = (1 << 15) - 1;
+       dc->caps.vtotal_limited_by_fp2 = true;
+
+       dc->caps.seamless_odm = true;
+       dc->caps.zstate_support = true;
+       dc->caps.ips_support = true;
+       dc->caps.max_v_total = (1 << 15) - 1;
+       dc->caps.vtotal_limited_by_fp2 = true;
+
+       /* Color pipeline capabilities */
+       dc->caps.color.dpp.dcn_arch = 1;
+       dc->caps.color.dpp.input_lut_shared = 0;
+       dc->caps.color.dpp.icsc = 1;
+       dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr
+       dc->caps.color.dpp.dgam_rom_caps.srgb = 1;
+       dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1;
+       dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1;
+       dc->caps.color.dpp.dgam_rom_caps.pq = 1;
+       dc->caps.color.dpp.dgam_rom_caps.hlg = 1;
+       dc->caps.color.dpp.post_csc = 1;
+       dc->caps.color.dpp.gamma_corr = 1;
+       dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+
+       dc->caps.color.dpp.hw_3d_lut = 0;
+       dc->caps.color.dpp.ogam_ram = 0;
+       // no OGAM ROM on DCN2 and later ASICs
+       dc->caps.color.dpp.ogam_rom_caps.srgb = 0;
+       dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0;
+       dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0;
+       dc->caps.color.dpp.ogam_rom_caps.pq = 0;
+       dc->caps.color.dpp.ogam_rom_caps.hlg = 0;
+       dc->caps.color.dpp.ocsc = 0;
+
+       dc->caps.color.mpc.gamut_remap = 1;
+       //configurable to be before or after BLND in MPCC
+       dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut;
+       dc->caps.color.mpc.num_rmcm_3dluts = 2;
+       dc->caps.color.mpc.ogam_ram = 1;
+       dc->caps.color.mpc.ogam_rom_caps.srgb = 0;
+       dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0;
+       dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0;
+       dc->caps.color.mpc.ogam_rom_caps.pq = 0;
+       dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
+       dc->caps.color.mpc.ocsc = 1;
+       dc->caps.color.mpc.preblend = true;
+       dc->caps.color.mpc.mcm_3d_lut_caps.dma_3d_lut = 1;
+       dc->caps.color.mpc.mcm_3d_lut_caps.lut_dim_caps.dim_9 = 1;
+       dc->caps.color.mpc.mcm_3d_lut_caps.lut_dim_caps.dim_17 = 1;
+       dc->caps.color.mpc.mcm_3d_lut_caps.mem_layout_support.linear_1d = 1;
+       dc->caps.color.mpc.mcm_3d_lut_caps.mem_layout_support.swizzle_3d_bgr = 1;
+       dc->caps.color.mpc.mcm_3d_lut_caps.mem_layout_support.swizzle_3d_rgb = 1;
+       dc->caps.color.mpc.mcm_3d_lut_caps.mem_format_support.unorm_12msb = 1;
+       dc->caps.color.mpc.mcm_3d_lut_caps.mem_format_support.unorm_12lsb = 1;
+       dc->caps.color.mpc.mcm_3d_lut_caps.mem_format_support.float_fp1_5_10 = 1;
+       dc->caps.color.mpc.mcm_3d_lut_caps.mem_pixel_order_support.order_rgba = 1;
+       dc->caps.color.mpc.mcm_3d_lut_caps.mem_pixel_order_support.order_bgra = 1;
+       dc->caps.color.mpc.rmcm_3d_lut_caps.dma_3d_lut = 1;
+       dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_17 = 1;
+       dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_33 = 1;
+       dc->caps.color.mpc.rmcm_3d_lut_caps.mem_layout_support.linear_1d = 1;
+       dc->caps.color.mpc.rmcm_3d_lut_caps.mem_layout_support.swizzle_3d_bgr = 1;
+       dc->caps.color.mpc.rmcm_3d_lut_caps.mem_layout_support.swizzle_3d_rgb = 1;
+       dc->caps.color.mpc.rmcm_3d_lut_caps.mem_format_support.unorm_12msb = 1;
+       dc->caps.color.mpc.rmcm_3d_lut_caps.mem_format_support.unorm_12lsb = 1;
+       dc->caps.color.mpc.rmcm_3d_lut_caps.mem_format_support.float_fp1_5_10 = 1;
+       dc->caps.color.mpc.rmcm_3d_lut_caps.mem_pixel_order_support.order_rgba = 1;
+       dc->caps.color.mpc.rmcm_3d_lut_caps.mem_pixel_order_support.order_bgra = 1;
+
+       dc->caps.num_of_host_routers = 3;
+       dc->caps.num_of_dpias_per_host_router = 2;
+
+       /* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order
+        * to provide some margin.
+        * It's expected for furture ASIC to have equal or higher value, in order to
+        * have determinstic power improvement from generate to genration.
+        * (i.e., we should not expect new ASIC generation with lower vmin rate)
+        */
+       dc->caps.max_disp_clock_khz_at_vmin = 650000;
+       dc->config.use_spl = true;
+       dc->config.prefer_easf = true;
+
+       dc->config.dcn_sharpness_range.sdr_rgb_min = 0;
+       dc->config.dcn_sharpness_range.sdr_rgb_max = 1750;
+       dc->config.dcn_sharpness_range.sdr_rgb_mid = 750;
+       dc->config.dcn_sharpness_range.sdr_yuv_min = 0;
+       dc->config.dcn_sharpness_range.sdr_yuv_max = 3500;
+       dc->config.dcn_sharpness_range.sdr_yuv_mid = 1500;
+       dc->config.dcn_sharpness_range.hdr_rgb_min = 0;
+       dc->config.dcn_sharpness_range.hdr_rgb_max = 2750;
+       dc->config.dcn_sharpness_range.hdr_rgb_mid = 1500;
+
+       dc->config.dcn_override_sharpness_range.sdr_rgb_min = 0;
+       dc->config.dcn_override_sharpness_range.sdr_rgb_max = 3250;
+       dc->config.dcn_override_sharpness_range.sdr_rgb_mid = 1250;
+       dc->config.dcn_override_sharpness_range.sdr_yuv_min = 0;
+       dc->config.dcn_override_sharpness_range.sdr_yuv_max = 3500;
+       dc->config.dcn_override_sharpness_range.sdr_yuv_mid = 1500;
+       dc->config.dcn_override_sharpness_range.hdr_rgb_min = 0;
+       dc->config.dcn_override_sharpness_range.hdr_rgb_max = 2750;
+       dc->config.dcn_override_sharpness_range.hdr_rgb_mid = 1500;
+
+       dc->config.use_pipe_ctx_sync_logic = true;
+       dc->config.dc_mode_clk_limit_support = true;
+       dc->config.enable_windowed_mpo_odm = true;
+       /* Use psp mailbox to enable assr */
+       dc->config.use_assr_psp_message = true;
+       /* dcn42 and afterward always support external panel replay */
+       dc->config.frame_update_cmd_version2 = true;
+
+       /* read VBIOS LTTPR caps */
+       {
+               if (ctx->dc_bios->funcs->get_lttpr_caps) {
+                       enum bp_result bp_query_result;
+                       uint8_t is_vbios_lttpr_enable = 0;
+
+                       bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable);
+                       dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable;
+               }
+
+               dc->caps.vbios_lttpr_aware = true;
+       }
+       dc->check_config = config_defaults;
+
+       if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
+               dc->debug = debug_defaults_drv;
+
+       /*HW default is to have all the FGCG enabled, SW no need to program them*/
+       dc->debug.enable_fine_grain_clock_gating.u32All = 0xFFFF;
+       // Init the vm_helper
+       if (dc->vm_helper)
+               vm_helper_init(dc->vm_helper, 16);
+
+       /*************************************************
+        *  Create resources                             *
+        *************************************************/
+
+       /* Clock Sources for Pixel Clock*/
+       pool->base.clock_sources[DCN401_CLK_SRC_PLL0] =
+               dcn42_clock_source_create(ctx, ctx->dc_bios,
+                                                                 CLOCK_SOURCE_COMBO_PHY_PLL0,
+                                                                 &clk_src_regs[0], false);
+       pool->base.clock_sources[DCN401_CLK_SRC_PLL1] =
+               dcn42_clock_source_create(ctx, ctx->dc_bios,
+                                                                 CLOCK_SOURCE_COMBO_PHY_PLL1,
+                                                                 &clk_src_regs[1], false);
+       pool->base.clock_sources[DCN401_CLK_SRC_PLL2] =
+               dcn42_clock_source_create(ctx, ctx->dc_bios,
+                                                                 CLOCK_SOURCE_COMBO_PHY_PLL2,
+                                                                 &clk_src_regs[2], false);
+       pool->base.clock_sources[DCN401_CLK_SRC_PLL3] =
+               dcn42_clock_source_create(ctx, ctx->dc_bios,
+                                                                 CLOCK_SOURCE_COMBO_PHY_PLL3,
+                                                                 &clk_src_regs[3], false);
+       pool->base.clock_sources[DCN401_CLK_SRC_PLL4] =
+               dcn42_clock_source_create(ctx, ctx->dc_bios,
+                                                                 CLOCK_SOURCE_COMBO_PHY_PLL4,
+                                                                 &clk_src_regs[4], false);
+
+       pool->base.clk_src_count = DCN401_CLK_SRC_TOTAL;
+
+       /* todo: not reuse phy_pll registers */
+       pool->base.dp_clock_source =
+               dcn42_clock_source_create(ctx, ctx->dc_bios,
+                                                                 CLOCK_SOURCE_ID_DP_DTO,
+                                                                 &clk_src_regs[0], true);
+
+       for (i = 0; i < pool->base.clk_src_count; i++) {
+               if (pool->base.clock_sources[i] == NULL) {
+                       dm_error("DC: failed to create clock sources!\n");
+                       BREAK_TO_DEBUGGER();
+                       goto create_fail;
+               }
+       }
+
+       /* DCCG */
+       pool->base.dccg = dccg42_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask);
+       if (pool->base.dccg == NULL) {
+               dm_error("DC: failed to create dccg!\n");
+               BREAK_TO_DEBUGGER();
+               goto create_fail;
+       }
+
+#undef REG_STRUCT
+#define REG_STRUCT pg_cntl_regs
+       pg_cntl_dcn42_regs_init();
+
+       pool->base.pg_cntl = pg_cntl42_create(ctx, &pg_cntl_regs, &pg_cntl_shift, &pg_cntl_mask);
+       if (pool->base.pg_cntl == NULL) {
+               dm_error("DC: failed to create power gate control!\n");
+               BREAK_TO_DEBUGGER();
+               goto create_fail;
+       }
+       /* IRQ Service */
+       init_data.ctx = dc->ctx;
+       pool->base.irqs = dal_irq_service_dcn42_create(&init_data);
+       if (!pool->base.irqs)
+               goto create_fail;
+
+       /* HUBBUB */
+       pool->base.hubbub = dcn42_hubbub_create(ctx);
+       if (pool->base.hubbub == NULL) {
+               BREAK_TO_DEBUGGER();
+               dm_error("DC: failed to create hubbub!\n");
+               goto create_fail;
+       }
+
+       /* HUBPs, DPPs, OPPs, TGs, ABMs */
+       for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) {
+               /* if pipe is disabled, skip instance of HW pipe,
+                * i.e, skip ASIC register instance
+                */
+               if (pipe_fuses & 1 << i)
+                       continue;
+
+               pool->base.hubps[j] = dcn42_hubp_create(ctx, i);
+               if (pool->base.hubps[j] == NULL) {
+                       BREAK_TO_DEBUGGER();
+                       dm_error(
+                               "DC: failed to create hubps!\n");
+                       goto create_fail;
+               }
+
+               pool->base.dpps[j] = dcn42_dpp_create(ctx, i);
+               if (pool->base.dpps[j] == NULL) {
+                       BREAK_TO_DEBUGGER();
+                       dm_error(
+                               "DC: failed to create dpps!\n");
+                       goto create_fail;
+               }
+
+               pool->base.opps[j] = dcn42_opp_create(ctx, i);
+               if (pool->base.opps[j] == NULL) {
+                       BREAK_TO_DEBUGGER();
+                       dm_error(
+                               "DC: failed to create output pixel processor!\n");
+                       goto create_fail;
+               }
+
+               pool->base.timing_generators[j] = dcn42_timing_generator_create(
+                       ctx, i);
+               if (pool->base.timing_generators[j] == NULL) {
+                       BREAK_TO_DEBUGGER();
+                       dm_error("DC: failed to create tg!\n");
+                       goto create_fail;
+               }
+
+               pool->base.multiple_abms[j] = dmub_abm_create(ctx,
+                                                                                                         &abm_regs[i],
+                                                                                                         &abm_shift,
+                                                                                                         &abm_mask);
+               if (pool->base.multiple_abms[j] == NULL) {
+                       dm_error("DC: failed to create abm for pipe %d!\n", i);
+                       BREAK_TO_DEBUGGER();
+                       goto create_fail;
+               }
+
+               /* index for resource pool arrays for next valid pipe */
+               j++;
+       }
+
+       /* PSR */
+       pool->base.psr = dmub_psr_create(ctx);
+       if (pool->base.psr == NULL) {
+               dm_error("DC: failed to create psr obj!\n");
+               BREAK_TO_DEBUGGER();
+               goto create_fail;
+       }
+
+       /* Replay */
+       pool->base.replay = dmub_replay_create(ctx);
+       if (pool->base.replay == NULL) {
+               dm_error("DC: failed to create replay obj!\n");
+               BREAK_TO_DEBUGGER();
+               goto create_fail;
+       }
+
+       /* MPCCs */
+       pool->base.mpc = dcn42_mpc_create(ctx, pool->base.res_cap->num_timing_generator,
+                       pool->base.res_cap->num_mpc_3dlut);
+       if (pool->base.mpc == NULL) {
+               BREAK_TO_DEBUGGER();
+               dm_error("DC: failed to create mpc!\n");
+               goto create_fail;
+       }
+
+       /* DSCs */
+       for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
+               pool->base.dscs[i] = dcn42_dsc_create(ctx, i);
+               if (pool->base.dscs[i] == NULL) {
+                       BREAK_TO_DEBUGGER();
+                       dm_error("DC: failed to create display stream compressor %d!\n", i);
+                       goto create_fail;
+               }
+       }
+
+       /* DWB */
+       if (!dcn42_dwbc_create(ctx, &pool->base)) {
+               BREAK_TO_DEBUGGER();
+               dm_error("DC: failed to create dwbc!\n");
+               goto create_fail;
+       }
+
+       /* MMHUBBUB */
+       if (!dcn42_mmhubbub_create(ctx, &pool->base)) {
+               BREAK_TO_DEBUGGER();
+               dm_error("DC: failed to create mcif_wb!\n");
+               goto create_fail;
+       }
+
+       /* AUX and I2C */
+       for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
+               pool->base.engines[i] = dcn42_aux_engine_create(ctx, i);
+
+               if (pool->base.engines[i] == NULL) {
+                       BREAK_TO_DEBUGGER();
+                       dm_error(
+                               "DC:failed to create aux engine!!\n");
+                       goto create_fail;
+               }
+               pool->base.hw_i2cs[i] = dcn42_i2c_hw_create(ctx, i);
+               if (pool->base.hw_i2cs[i] == NULL) {
+                       BREAK_TO_DEBUGGER();
+                       dm_error(
+                               "DC:failed to create hw i2c!!\n");
+                       goto create_fail;
+               }
+               pool->base.sw_i2cs[i] = NULL;
+       }
+       /* DCN4.2 has 6 DPIA */
+       pool->base.usb4_dpia_count = dc->caps.num_of_host_routers * dc->caps.num_of_dpias_per_host_router;
+       if (dc->debug.dpia_debug.bits.disable_dpia)
+               pool->base.usb4_dpia_count = 0;
+
+       /* Audio, HWSeq, Stream Encoders including HPO and virtual, MPC 3D LUTs */
+       if (!resource_construct(num_virtual_links, dc, &pool->base,
+                                                       &res_create_funcs))
+               goto create_fail;
+
+       /* HW Sequencer init functions and Plane caps */
+       dcn42_hw_sequencer_init_functions(dc);
+
+       dc->caps.max_planes = pool->base.pipe_count;
+
+       for (i = 0; i < dc->caps.max_planes; ++i)
+               dc->caps.planes[i] = plane_cap;
+
+       dc->caps.max_odm_combine_factor = 4;
+
+       dc->cap_funcs = cap_funcs;
+       dc->dcn_ip->max_num_dpp = pool->base.pipe_count;
+
+       // For now enable SDPIF_REQUEST_RATE_LIMIT on DCN4_01 when vram_info.num_chans provided
+       if (dc->config.sdpif_request_limit_words_per_umc == 0)
+               dc->config.sdpif_request_limit_words_per_umc = 16;
+
+       dc->dml2_options.dcn_pipe_count = pool->base.pipe_count;
+        /*this will use real soc clock table*/
+       dc->dml2_options.use_native_soc_bb_construction = true;
+       dc->dml2_options.minimize_dispclk_using_odm = false;
+       if (dc->config.EnableMinDispClkODM)
+               dc->dml2_options.minimize_dispclk_using_odm = true;
+       dc->dml2_options.enable_windowed_mpo_odm = dc->config.enable_windowed_mpo_odm;
+       dc->dml2_options.map_dc_pipes_with_callbacks = true;
+       dc->dml2_options.force_tdlut_enable = true;
+
+       resource_init_common_dml2_callbacks(dc, &dc->dml2_options);
+       dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch =
+                       &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch;
+       dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc;
+       dc->dml2_options.svp_pstate.callbacks.calculate_mall_ways_from_bytes =
+               pool->base.funcs->calculate_mall_ways_from_bytes;
+
+       dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us;
+       dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us;
+       dc->dml2_options.svp_pstate.subvp_pstate_allow_width_us = dc->caps.subvp_pstate_allow_width_us;
+       dc->dml2_options.svp_pstate.subvp_swath_height_margin_lines = dc->caps.subvp_swath_height_margin_lines;
+
+       dc->dml2_options.svp_pstate.force_disable_subvp = dc->debug.force_disable_subvp;
+       dc->dml2_options.svp_pstate.force_enable_subvp = dc->debug.force_subvp_mclk_switch;
+
+       dc->dml2_options.mall_cfg.cache_line_size_bytes = dc->caps.cache_line_size;
+       dc->dml2_options.mall_cfg.cache_num_ways = dc->caps.cache_num_ways;
+       dc->dml2_options.mall_cfg.max_cab_allocation_bytes =
+                               dc->caps.max_cab_allocation_bytes;
+       dc->dml2_options.mall_cfg.mblk_height_4bpe_pixels = DCN3_2_MBLK_HEIGHT_4BPE;
+       dc->dml2_options.mall_cfg.mblk_height_8bpe_pixels = DCN3_2_MBLK_HEIGHT_8BPE;
+       dc->dml2_options.mall_cfg.mblk_size_bytes = DCN3_2_MALL_MBLK_SIZE_BYTES;
+       dc->dml2_options.mall_cfg.mblk_width_pixels = DCN3_2_MBLK_WIDTH;
+
+       dc->dml2_options.max_segments_per_hubp = 24;
+       dc->dml2_options.det_segment_size = DCN42_CRB_SEGMENT_SIZE_KB;
+
+       /* SPL */
+       dc->caps.scl_caps.sharpener_support = true;
+
+       /* init DC limited DML2 options */
+       memcpy(&dc->dml2_dc_power_options, &dc->dml2_options, sizeof(struct dml2_configuration_options));
+       dc->dml2_dc_power_options.use_clock_dc_limits = true;
+
+       return true;
+
+create_fail:
+
+       dcn42_resource_destruct(pool);
+
+       return false;
+}
+struct resource_pool *dcn42_create_resource_pool(
+       const struct dc_init_data *init_data,
+       struct dc *dc)
+{
+       struct dcn42_resource_pool *pool =
+               kzalloc(sizeof(struct dcn401_resource_pool), GFP_KERNEL);
+
+       if (!pool)
+               return NULL;
+
+       if (dcn42_resource_construct(init_data->num_virtual_links, dc, pool))
+               return &pool->base;
+
+       BREAK_TO_DEBUGGER();
+       kfree(pool);
+       return NULL;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h
new file mode 100644 (file)
index 0000000..a9b26df
--- /dev/null
@@ -0,0 +1,588 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 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 _DCN42_RESOURCE_H_
+#define _DCN42_RESOURCE_H_
+
+#include "core_types.h"
+
+#define TO_DCN42_RES_POOL(pool) \
+       container_of(pool, struct dcn42_resource_pool, base)
+
+/* DPP */
+#define DPP_REG_LIST_DCN42_COMMON_RI(id)                                        \
+       SRI_ARR(CM_DEALPHA, CM, id), SRI_ARR(CM_MEM_PWR_STATUS, CM, id),            \
+               SRI_ARR(CM_BIAS_CR_R, CM, id), SRI_ARR(CM_BIAS_Y_G_CB_B, CM, id),       \
+               SRI_ARR(PRE_DEGAM, CNVC_CFG, id), SRI_ARR(CM_GAMCOR_CONTROL, CM, id),   \
+               SRI_ARR(CM_GAMCOR_LUT_CONTROL, CM, id),                                 \
+               SRI_ARR(CM_GAMCOR_LUT_INDEX, CM, id),                                   \
+               SRI_ARR(CM_GAMCOR_LUT_INDEX, CM, id),                                   \
+               SRI_ARR(CM_GAMCOR_LUT_DATA, CM, id),                                    \
+               SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_B, CM, id),                           \
+               SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_G, CM, id),                           \
+               SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_R, CM, id),                           \
+               SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_B, CM, id),                     \
+               SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_G, CM, id),                     \
+               SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_R, CM, id),                     \
+               SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_B, CM, id),                            \
+               SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_B, CM, id),                            \
+               SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_G, CM, id),                            \
+               SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_G, CM, id),                            \
+               SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_R, CM, id),                            \
+               SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_R, CM, id),                            \
+               SRI_ARR(CM_GAMCOR_RAMB_REGION_0_1, CM, id),                             \
+               SRI_ARR(CM_GAMCOR_RAMB_REGION_32_33, CM, id),                           \
+               SRI_ARR(CM_GAMCOR_RAMB_OFFSET_B, CM, id),                               \
+               SRI_ARR(CM_GAMCOR_RAMB_OFFSET_G, CM, id),                               \
+               SRI_ARR(CM_GAMCOR_RAMB_OFFSET_R, CM, id),                               \
+               SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_B, CM, id),                      \
+               SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_G, CM, id),                      \
+               SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_R, CM, id),                      \
+               SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_B, CM, id),                           \
+               SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_G, CM, id),                           \
+               SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_R, CM, id),                           \
+               SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_B, CM, id),                     \
+               SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_G, CM, id),                     \
+               SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_R, CM, id),                     \
+               SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_B, CM, id),                            \
+               SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_B, CM, id),                            \
+               SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_G, CM, id),                            \
+               SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_G, CM, id),                            \
+               SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_R, CM, id),                            \
+               SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_R, CM, id),                            \
+               SRI_ARR(CM_GAMCOR_RAMA_REGION_0_1, CM, id),                             \
+               SRI_ARR(CM_GAMCOR_RAMA_REGION_32_33, CM, id),                           \
+               SRI_ARR(CM_GAMCOR_RAMA_OFFSET_B, CM, id),                               \
+               SRI_ARR(CM_GAMCOR_RAMA_OFFSET_G, CM, id),                               \
+               SRI_ARR(CM_GAMCOR_RAMA_OFFSET_R, CM, id),                               \
+               SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_B, CM, id),                      \
+               SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_G, CM, id),                      \
+               SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_R, CM, id),                      \
+               SRI_ARR(CM_HIST_CNTL, CM, id),                                          \
+               SRI_ARR(CM_HIST_LOCK, CM, id),                                          \
+               SRI_ARR(CM_HIST_INDEX, CM, id),                                         \
+               SRI_ARR(CM_HIST_DATA, CM, id),                                          \
+               SRI_ARR(CM_HIST_STATUS, CM, id),                                        \
+               SRI_ARR(CM_HIST_SCALE_SRC1, CM, id),                                    \
+               SRI_ARR(CM_HIST_COEFA_SRC2, CM, id),                                    \
+               SRI_ARR(CM_HIST_COEFB_SRC2, CM, id),                                    \
+               SRI_ARR(CM_HIST_COEFC_SRC2, CM, id),                                    \
+               SRI_ARR(CM_HIST_SCALE_SRC3, CM, id),                                    \
+               SRI_ARR(CM_HIST_BIAS_SRC1, CM, id),                                     \
+               SRI_ARR(CM_HIST_BIAS_SRC2, CM, id),                                     \
+               SRI_ARR(CM_HIST_BIAS_SRC3, CM, id),                                     \
+               SRI_ARR(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id),                        \
+               SRI_ARR(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id),                        \
+               SRI_ARR(OTG_H_BLANK, DSCL, id), SRI_ARR(OTG_V_BLANK, DSCL, id),         \
+               SRI_ARR(SCL_MODE, DSCL, id), SRI_ARR(LB_DATA_FORMAT, DSCL, id),         \
+               SRI_ARR(LB_MEMORY_CTRL, DSCL, id), SRI_ARR(DSCL_AUTOCAL, DSCL, id),     \
+               SRI_ARR(SCL_TAP_CONTROL, DSCL, id),                                     \
+               SRI_ARR(SCL_COEF_RAM_TAP_SELECT, DSCL, id),                             \
+               SRI_ARR(SCL_COEF_RAM_TAP_DATA, DSCL, id),                               \
+               SRI_ARR(DSCL_2TAP_CONTROL, DSCL, id), SRI_ARR(MPC_SIZE, DSCL, id),      \
+               SRI_ARR(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id),                         \
+               SRI_ARR(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id),                         \
+               SRI_ARR(SCL_HORZ_FILTER_SCALE_RATIO_C, DSCL, id),                       \
+               SRI_ARR(SCL_VERT_FILTER_SCALE_RATIO_C, DSCL, id),                       \
+               SRI_ARR(SCL_HORZ_FILTER_INIT, DSCL, id),                                \
+               SRI_ARR(SCL_HORZ_FILTER_INIT_C, DSCL, id),                              \
+               SRI_ARR(SCL_VERT_FILTER_INIT, DSCL, id),                                \
+               SRI_ARR(SCL_VERT_FILTER_INIT_C, DSCL, id),                              \
+               SRI_ARR(RECOUT_START, DSCL, id), SRI_ARR(RECOUT_SIZE, DSCL, id),        \
+               SRI_ARR(PRE_DEALPHA, CNVC_CFG, id), SRI_ARR(PRE_REALPHA, CNVC_CFG, id), \
+               SRI_ARR(PRE_CSC_MODE, CNVC_CFG, id),                                    \
+               SRI_ARR(PRE_CSC_C11_C12, CNVC_CFG, id),                                 \
+               SRI_ARR(PRE_CSC_C33_C34, CNVC_CFG, id),                                 \
+               SRI_ARR(PRE_CSC_B_C11_C12, CNVC_CFG, id),                               \
+               SRI_ARR(PRE_CSC_B_C33_C34, CNVC_CFG, id),                               \
+               SRI_ARR(CM_POST_CSC_CONTROL, CM, id),                                   \
+               SRI_ARR(CM_POST_CSC_C11_C12, CM, id),                                   \
+               SRI_ARR(CM_POST_CSC_C33_C34, CM, id),                                   \
+               SRI_ARR(CM_POST_CSC_B_C11_C12, CM, id),                                 \
+               SRI_ARR(CM_POST_CSC_B_C33_C34, CM, id),                                 \
+               SRI_ARR(CM_MEM_PWR_CTRL, CM, id), SRI_ARR(CM_CONTROL, CM, id),          \
+               SRI_ARR(CM_TEST_DEBUG_INDEX, CM, id),                                   \
+               SRI_ARR(CM_TEST_DEBUG_DATA, CM, id),                                    \
+               SRI_ARR(FORMAT_CONTROL, CNVC_CFG, id),                                  \
+               SRI_ARR(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id),                       \
+               SRI_ARR(CURSOR0_CONTROL, CM_CUR, id),                                   \
+               SRI_ARR(CURSOR0_COLOR0, CM_CUR, id),                                    \
+               SRI_ARR(CURSOR0_COLOR1, CM_CUR, id),                                    \
+               SRI_ARR(CURSOR0_FP_SCALE_BIAS_G_Y, CM_CUR, id),                         \
+               SRI_ARR(CURSOR0_FP_SCALE_BIAS_RB_CRCB, CM_CUR, id),                     \
+               SRI_ARR(CUR0_MATRIX_MODE, CM_CUR, id),                                  \
+               SRI_ARR(CUR0_MATRIX_C11_C12_A, CM_CUR, id),                             \
+               SRI_ARR(CUR0_MATRIX_C13_C14_A, CM_CUR, id),                             \
+               SRI_ARR(CUR0_MATRIX_C21_C22_A, CM_CUR, id),                             \
+               SRI_ARR(CUR0_MATRIX_C23_C24_A, CM_CUR, id),                             \
+               SRI_ARR(CUR0_MATRIX_C31_C32_A, CM_CUR, id),                             \
+               SRI_ARR(CUR0_MATRIX_C33_C34_A, CM_CUR, id),                             \
+               SRI_ARR(CUR0_MATRIX_C11_C12_B, CM_CUR, id),                             \
+               SRI_ARR(CUR0_MATRIX_C13_C14_B, CM_CUR, id),                             \
+               SRI_ARR(CUR0_MATRIX_C21_C22_B, CM_CUR, id),                             \
+               SRI_ARR(CUR0_MATRIX_C23_C24_B, CM_CUR, id),                             \
+               SRI_ARR(CUR0_MATRIX_C31_C32_B, CM_CUR, id),                             \
+               SRI_ARR(CUR0_MATRIX_C33_C34_B, CM_CUR, id),                             \
+               SRI_ARR(DPP_CONTROL, DPP_TOP, id), SRI_ARR(CM_HDR_MULT_COEF, CM, id),   \
+               SRI_ARR(CURSOR_CONTROL, CURSOR0_, id),                                  \
+               SRI_ARR(ALPHA_2BIT_LUT01, CNVC_CFG, id),                                \
+               SRI_ARR(ALPHA_2BIT_LUT23, CNVC_CFG, id),                                \
+               SRI_ARR(FCNV_FP_BIAS_R, CNVC_CFG, id),                                  \
+               SRI_ARR(FCNV_FP_BIAS_G, CNVC_CFG, id),                                  \
+               SRI_ARR(FCNV_FP_BIAS_B, CNVC_CFG, id),                                  \
+               SRI_ARR(FCNV_FP_SCALE_R, CNVC_CFG, id),                                 \
+               SRI_ARR(FCNV_FP_SCALE_G, CNVC_CFG, id),                                 \
+               SRI_ARR(FCNV_FP_SCALE_B, CNVC_CFG, id),                                 \
+               SRI_ARR(COLOR_KEYER_CONTROL, CNVC_CFG, id),                             \
+               SRI_ARR(COLOR_KEYER_ALPHA, CNVC_CFG, id),                               \
+               SRI_ARR(COLOR_KEYER_RED, CNVC_CFG, id),                                 \
+               SRI_ARR(COLOR_KEYER_GREEN, CNVC_CFG, id),                               \
+               SRI_ARR(COLOR_KEYER_BLUE, CNVC_CFG, id),                                \
+               SRI_ARR(OBUF_MEM_PWR_CTRL, DSCL, id),                                   \
+               SRI_ARR(DSCL_MEM_PWR_STATUS, DSCL, id),                                 \
+               SRI_ARR(DSCL_MEM_PWR_CTRL, DSCL, id),                                   \
+               SRI_ARR(DSCL_CONTROL, DSCL, id),                                        \
+               SRI_ARR(DSCL_SC_MODE, DSCL, id),                                        \
+               SRI_ARR(DSCL_EASF_H_MODE, DSCL, id),                                    \
+               SRI_ARR(DSCL_EASF_H_BF_CNTL, DSCL, id),                                 \
+               SRI_ARR(DSCL_EASF_H_RINGEST_EVENTAP_REDUCE, DSCL, id),                  \
+               SRI_ARR(DSCL_EASF_H_RINGEST_EVENTAP_GAIN, DSCL, id),                    \
+               SRI_ARR(DSCL_EASF_H_BF_FINAL_MAX_MIN, DSCL, id),                        \
+               SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG0, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG1, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG2, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG3, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG4, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG5, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG6, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG7, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG0, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG1, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG2, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG3, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG4, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG5, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_MODE, DSCL, id),                                    \
+               SRI_ARR(DSCL_EASF_V_BF_CNTL, DSCL, id),                                 \
+               SRI_ARR(DSCL_EASF_V_RINGEST_3TAP_CNTL1, DSCL, id),                      \
+               SRI_ARR(DSCL_EASF_V_RINGEST_3TAP_CNTL2, DSCL, id),                      \
+               SRI_ARR(DSCL_EASF_V_RINGEST_3TAP_CNTL3, DSCL, id),                      \
+               SRI_ARR(DSCL_EASF_V_RINGEST_EVENTAP_REDUCE, DSCL, id),                  \
+               SRI_ARR(DSCL_EASF_V_RINGEST_EVENTAP_GAIN, DSCL, id),                    \
+               SRI_ARR(DSCL_EASF_V_BF_FINAL_MAX_MIN, DSCL, id),                        \
+               SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG0, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG1, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG2, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG3, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG4, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG5, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG6, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG7, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG0, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG1, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG2, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG3, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG4, DSCL, id),                            \
+               SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG5, DSCL, id),                            \
+               SRI_ARR(DSCL_SC_MATRIX_C0C1, DSCL, id),                                 \
+               SRI_ARR(DSCL_SC_MATRIX_C2C3, DSCL, id),                                 \
+               SRI_ARR(ISHARP_MODE, DSCL, id),                                         \
+               SRI_ARR(ISHARP_DELTA_LUT_MEM_PWR_CTRL, DSCL, id),                       \
+               SRI_ARR(ISHARP_NOISEDET_THRESHOLD, DSCL, id),                           \
+               SRI_ARR(ISHARP_NOISE_GAIN_PWL, DSCL, id),                               \
+               SRI_ARR(ISHARP_LBA_PWL_SEG0, DSCL, id),                                 \
+               SRI_ARR(ISHARP_LBA_PWL_SEG1, DSCL, id),                                 \
+               SRI_ARR(ISHARP_LBA_PWL_SEG2, DSCL, id),                                 \
+               SRI_ARR(ISHARP_LBA_PWL_SEG3, DSCL, id),                                 \
+               SRI_ARR(ISHARP_LBA_PWL_SEG4, DSCL, id),                                 \
+               SRI_ARR(ISHARP_LBA_PWL_SEG5, DSCL, id),                                 \
+               SRI_ARR(ISHARP_DELTA_CTRL, DSCL, id),                                   \
+               SRI_ARR(ISHARP_DELTA_DATA, DSCL, id),                                   \
+               SRI_ARR(ISHARP_DELTA_INDEX, DSCL, id),                                  \
+               SRI_ARR(ISHARP_NLDELTA_SOFT_CLIP, DSCL, id),                            \
+               SRI_ARR(SCL_VERT_FILTER_INIT_BOT, DSCL, id),                            \
+               SRI_ARR(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id)
+
+/* Stream encoder */
+#define SE_DCN42_REG_LIST_RI(id)                                                \
+       SRI_ARR(HDMI_CONTROL, DIG, id), SRI_ARR(HDMI_DB_CONTROL, DIG, id),          \
+               SRI_ARR(HDMI_GC, DIG, id),                                              \
+               SRI_ARR(HDMI_GENERIC_PACKET_CONTROL0, DIG, id),                         \
+               SRI_ARR(HDMI_GENERIC_PACKET_CONTROL1, DIG, id),                         \
+               SRI_ARR(HDMI_GENERIC_PACKET_CONTROL2, DIG, id),                         \
+               SRI_ARR(HDMI_GENERIC_PACKET_CONTROL3, DIG, id),                         \
+               SRI_ARR(HDMI_GENERIC_PACKET_CONTROL4, DIG, id),                         \
+               SRI_ARR(HDMI_GENERIC_PACKET_CONTROL5, DIG, id),                         \
+               SRI_ARR(HDMI_GENERIC_PACKET_CONTROL6, DIG, id),                         \
+               SRI_ARR(HDMI_GENERIC_PACKET_CONTROL7, DIG, id),                         \
+               SRI_ARR(HDMI_GENERIC_PACKET_CONTROL8, DIG, id),                         \
+               SRI_ARR(HDMI_GENERIC_PACKET_CONTROL9, DIG, id),                         \
+               SRI_ARR(HDMI_GENERIC_PACKET_CONTROL10, DIG, id),                        \
+               SRI_ARR(HDMI_INFOFRAME_CONTROL0, DIG, id),                              \
+               SRI_ARR(HDMI_VBI_PACKET_CONTROL, DIG, id),                              \
+               SRI_ARR(HDMI_AUDIO_PACKET_CONTROL, DIG, id),                            \
+               SRI_ARR(HDMI_ACR_PACKET_CONTROL, DIG, id),                              \
+               SRI_ARR(HDMI_ACR_32_0, DIG, id), SRI_ARR(HDMI_ACR_32_1, DIG, id),       \
+               SRI_ARR(HDMI_ACR_44_0, DIG, id), SRI_ARR(HDMI_ACR_44_1, DIG, id),       \
+               SRI_ARR(HDMI_ACR_48_0, DIG, id), SRI_ARR(HDMI_ACR_48_1, DIG, id),       \
+               SRI_ARR(DP_DB_CNTL, DP, id), SRI_ARR(DP_MSA_MISC, DP, id),              \
+               SRI_ARR(DP_MSA_VBID_MISC, DP, id), SRI_ARR(DP_MSA_COLORIMETRY, DP, id), \
+               SRI_ARR(DP_MSA_TIMING_PARAM1, DP, id),                                  \
+               SRI_ARR(DP_MSA_TIMING_PARAM2, DP, id),                                  \
+               SRI_ARR(DP_MSA_TIMING_PARAM3, DP, id),                                  \
+               SRI_ARR(DP_MSA_TIMING_PARAM4, DP, id),                                  \
+               SRI_ARR(DP_MSE_RATE_CNTL, DP, id), SRI_ARR(DP_MSE_RATE_UPDATE, DP, id), \
+               SRI_ARR(DP_PIXEL_FORMAT, DP, id), SRI_ARR(DP_SEC_CNTL, DP, id),         \
+               SRI_ARR(DP_SEC_CNTL1, DP, id), SRI_ARR(DP_SEC_CNTL2, DP, id),           \
+               SRI_ARR(DP_SEC_CNTL5, DP, id), SRI_ARR(DP_SEC_CNTL6, DP, id),           \
+               SRI_ARR(DP_STEER_FIFO, DP, id), SRI_ARR(DP_VID_M, DP, id),              \
+               SRI_ARR(DP_VID_N, DP, id), SRI_ARR(DP_VID_STREAM_CNTL, DP, id),         \
+               SRI_ARR(DP_VID_TIMING, DP, id), SRI_ARR(DP_SEC_AUD_N, DP, id),          \
+               SRI_ARR(DP_SEC_TIMESTAMP, DP, id),                                      \
+               SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id),                          \
+               SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id),                         \
+               SRI_ARR(DP_SEC_FRAMING4, DP, id), SRI_ARR(DP_GSP11_CNTL, DP, id),       \
+               SRI_ARR(DME_CONTROL, DME, id),                                          \
+               SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id),                          \
+               SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id),                         \
+               SRI_ARR(DIG_FE_CNTL, DIG, id),                                          \
+               SRI_ARR(DIG_FE_EN_CNTL, DIG, id),                                       \
+               SRI_ARR(DIG_FE_CLK_CNTL, DIG, id),                                      \
+               SRI_ARR(DIG_CLOCK_PATTERN, DIG, id),                                    \
+               SRI_ARR(DIG_FIFO_CTRL0, DIG, id),                                       \
+               SRI_ARR(STREAM_MAPPER_CONTROL, DIG, id),\
+               SRI_ARR(DIG_FE_AUDIO_CNTL, DIG, id)
+
+/* HPO DP stream encoder */
+#define DCN42_HPO_DP_STREAM_ENC_REG_LIST_RI(id)                                             \
+       SR_ARR(DP_STREAM_MAPPER_CONTROL0, id),                                                  \
+               SR_ARR(DP_STREAM_MAPPER_CONTROL1, id),                                              \
+               SR_ARR(DP_STREAM_MAPPER_CONTROL2, id),                                              \
+               SR_ARR(DP_STREAM_MAPPER_CONTROL3, id),                                              \
+               SRI_ARR(DP_STREAM_ENC_CLOCK_CONTROL, DP_STREAM_ENC, id),                            \
+               SRI_ARR(DP_STREAM_ENC_INPUT_MUX_CONTROL, DP_STREAM_ENC, id),                        \
+               SRI_ARR(DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC, id),                            \
+               SRI_ARR(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, DP_STREAM_ENC, id), \
+               SRI_ARR(DP_SYM32_ENC_CONTROL, DP_SYM32_ENC, id),                                    \
+               SRI_ARR(DP_SYM32_ENC_VID_PIXEL_FORMAT, DP_SYM32_ENC, id),                           \
+               SRI_ARR(DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id),     \
+               SRI_ARR(DP_SYM32_ENC_VID_MSA0, DP_SYM32_ENC, id),                                   \
+               SRI_ARR(DP_SYM32_ENC_VID_MSA1, DP_SYM32_ENC, id),                                   \
+               SRI_ARR(DP_SYM32_ENC_VID_MSA2, DP_SYM32_ENC, id),                                   \
+               SRI_ARR(DP_SYM32_ENC_VID_MSA3, DP_SYM32_ENC, id),                                   \
+               SRI_ARR(DP_SYM32_ENC_VID_MSA4, DP_SYM32_ENC, id),                                   \
+               SRI_ARR(DP_SYM32_ENC_VID_MSA5, DP_SYM32_ENC, id),                                   \
+               SRI_ARR(DP_SYM32_ENC_VID_MSA6, DP_SYM32_ENC, id),                                   \
+               SRI_ARR(DP_SYM32_ENC_VID_MSA7, DP_SYM32_ENC, id),                                   \
+               SRI_ARR(DP_SYM32_ENC_VID_MSA8, DP_SYM32_ENC, id),                                   \
+               SRI_ARR(DP_SYM32_ENC_VID_MSA_CONTROL, DP_SYM32_ENC, id),                            \
+               SRI_ARR(DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id),              \
+               SRI_ARR(DP_SYM32_ENC_VID_FIFO_CONTROL, DP_SYM32_ENC, id),                           \
+               SRI_ARR(DP_SYM32_ENC_VID_STREAM_CONTROL, DP_SYM32_ENC, id),                         \
+               SRI_ARR(DP_SYM32_ENC_VID_VBID_CONTROL, DP_SYM32_ENC, id),                           \
+               SRI_ARR(DP_SYM32_ENC_SDP_CONTROL, DP_SYM32_ENC, id),                                \
+               SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL0, DP_SYM32_ENC, id),                           \
+               SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL2, DP_SYM32_ENC, id),                           \
+               SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL3, DP_SYM32_ENC, id),                           \
+               SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL5, DP_SYM32_ENC, id),                           \
+               SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL11, DP_SYM32_ENC, id),                          \
+               SRI_ARR(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, DP_SYM32_ENC, id),                \
+               SRI_ARR(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, DP_SYM32_ENC, id),                         \
+               SRI_ARR(DP_SYM32_ENC_VID_CRC_CONTROL, DP_SYM32_ENC, id),                            \
+               SRI_ARR(DP_SYM32_ENC_HBLANK_CONTROL, DP_SYM32_ENC, id)
+
+/*HPO DP link encoder regs */
+#define DCN42_HPO_DP_LINK_ENC_REG_LIST_RI(id)                    \
+       SRI_ARR(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC, id),         \
+               SRI_ARR(DP_DPHY_SYM32_CONTROL, DP_DPHY_SYM32, id),       \
+               SRI_ARR(DP_DPHY_SYM32_STATUS, DP_DPHY_SYM32, id),        \
+               SRI_ARR(DP_DPHY_SYM32_TP_CONFIG, DP_DPHY_SYM32, id),     \
+               SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED0, DP_DPHY_SYM32, id), \
+               SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED1, DP_DPHY_SYM32, id), \
+               SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED2, DP_DPHY_SYM32, id), \
+               SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED3, DP_DPHY_SYM32, id), \
+               SRI_ARR(DP_DPHY_SYM32_TP_SQ_PULSE, DP_DPHY_SYM32, id),   \
+               SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM0, DP_DPHY_SYM32, id),    \
+               SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM1, DP_DPHY_SYM32, id),    \
+               SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM2, DP_DPHY_SYM32, id),    \
+               SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM3, DP_DPHY_SYM32, id),    \
+               SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM4, DP_DPHY_SYM32, id),    \
+               SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM5, DP_DPHY_SYM32, id),    \
+               SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM6, DP_DPHY_SYM32, id),    \
+               SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM7, DP_DPHY_SYM32, id),    \
+               SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM8, DP_DPHY_SYM32, id),    \
+               SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM9, DP_DPHY_SYM32, id),    \
+               SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM10, DP_DPHY_SYM32, id),   \
+               SRI_ARR(DP_DPHY_SYM32_SAT_VC0, DP_DPHY_SYM32, id),       \
+               SRI_ARR(DP_DPHY_SYM32_SAT_VC1, DP_DPHY_SYM32, id),       \
+               SRI_ARR(DP_DPHY_SYM32_SAT_VC2, DP_DPHY_SYM32, id),       \
+               SRI_ARR(DP_DPHY_SYM32_SAT_VC3, DP_DPHY_SYM32, id),       \
+               SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL0, DP_DPHY_SYM32, id), \
+               SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL1, DP_DPHY_SYM32, id), \
+               SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL2, DP_DPHY_SYM32, id), \
+               SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL3, DP_DPHY_SYM32, id), \
+               SRI_ARR(DP_DPHY_SYM32_SAT_UPDATE, DP_DPHY_SYM32, id)
+
+#define VPG_DCN42_REG_LIST_RI(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)
+
+/* DCCG */
+#define DCCG_REG_LIST_DCN42_RI()               \
+       SR(DPPCLK_DTO_CTRL),                       \
+       DCCG_SRII(DTO_PARAM, DPPCLK, 0),       \
+       DCCG_SRII(DTO_PARAM, DPPCLK, 1),       \
+       DCCG_SRII(DTO_PARAM, DPPCLK, 2),       \
+       DCCG_SRII(DTO_PARAM, DPPCLK, 3),       \
+       DCCG_SRII(CLOCK_CNTL, HDMICHARCLK, 0), \
+       SR(HDMISTREAMCLK0_DTO_PARAM),\
+       SR(DCCG_GLOBAL_FGCG_REP_CNTL),\
+       SR(DISPCLK_FREQ_CHANGE_CNTL), \
+       SR(PHYASYMCLK_CLOCK_CNTL),  \
+       SR(PHYBSYMCLK_CLOCK_CNTL), \
+       SR(PHYCSYMCLK_CLOCK_CNTL), \
+       SR(PHYDSYMCLK_CLOCK_CNTL), \
+       SR(PHYESYMCLK_CLOCK_CNTL), \
+       SR(DPSTREAMCLK_CNTL), \
+       SR(HDMISTREAMCLK_CNTL), \
+       SR(SYMCLK32_SE_CNTL), \
+       SR(SYMCLK32_LE_CNTL), \
+       DCCG_SRII(PIXEL_RATE_CNTL, OTG, 0), \
+       DCCG_SRII(PIXEL_RATE_CNTL, OTG, 1), \
+       DCCG_SRII(PIXEL_RATE_CNTL, OTG, 2), \
+       DCCG_SRII(PIXEL_RATE_CNTL, OTG, 3), \
+       SR(OTG_PIXEL_RATE_DIV), \
+       SR(DTBCLK_P_CNTL), \
+       SR(DCCG_AUDIO_DTO_SOURCE), \
+       SR(DENTIST_DISPCLK_CNTL), \
+       SR(DPPCLK_CTRL), \
+       DCCG_SRII(MODULO, DP_DTO, 0), \
+       DCCG_SRII(MODULO, DP_DTO, 1), \
+       DCCG_SRII(MODULO, DP_DTO, 2), \
+       DCCG_SRII(MODULO, DP_DTO, 3), \
+       DCCG_SRII(PHASE, DP_DTO, 0), \
+       DCCG_SRII(PHASE, DP_DTO, 1), \
+       DCCG_SRII(PHASE, DP_DTO, 2), \
+       DCCG_SRII(PHASE, DP_DTO, 3), \
+       SR(OTG_ADD_DROP_PIXEL_CNTL), \
+       SR(DSCCLK0_DTO_PARAM), \
+       SR(DSCCLK1_DTO_PARAM), \
+       SR(DSCCLK2_DTO_PARAM), \
+       SR(DSCCLK3_DTO_PARAM), \
+       SR(DSCCLK_DTO_CTRL), \
+       SR(DCCG_GATE_DISABLE_CNTL), \
+       SR(DCCG_GATE_DISABLE_CNTL2), \
+       SR(DCCG_GATE_DISABLE_CNTL3), \
+       SR(DCCG_GATE_DISABLE_CNTL4), \
+       SR(DCCG_GATE_DISABLE_CNTL5), \
+       SR(DCCG_GATE_DISABLE_CNTL6), \
+       SR(SYMCLKA_CLOCK_ENABLE), \
+       SR(SYMCLKB_CLOCK_ENABLE), \
+       SR(SYMCLKC_CLOCK_ENABLE), \
+       SR(SYMCLKD_CLOCK_ENABLE), \
+       SR(SYMCLKE_CLOCK_ENABLE)
+
+#define DCN42_AUD_COMMON_MASK_SH_LIST(mask_sh)                                             \
+       SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),   \
+               SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\
+               SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\
+               SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\
+               SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_USE_512FBR_DTO, mask_sh),\
+               SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO1_USE_512FBR_DTO, mask_sh),\
+               SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\
+               SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\
+               SF(DCCG_AUDIO_DTO1_MODULE, DCCG_AUDIO_DTO1_MODULE, mask_sh),\
+               SF(DCCG_AUDIO_DTO1_PHASE, DCCG_AUDIO_DTO1_PHASE, mask_sh),\
+               SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES, mask_sh),\
+               SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, CLKSTOP, mask_sh),\
+               SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, EPSS, mask_sh)
+
+       /* HPO FRL stream encoder */
+#define DCN42_HPO_FRL_STREAM_ENC_REG_LIST_RI(id)                                 \
+       DCN3_0_HPO_FRL_STREAM_ENC_REG_LIST_RI(id),                               \
+       SR_ARR(HDMI_STREAM_ENC_AUDIO_CONTROL, id),\
+       SR_ARR(HDMI_TB_ENC_MEM_CTRL, id),\
+       SR_ARR(HDMI_FRL_ENC_MEM_CTRL, id)
+/* OPTC */
+#define OPTC_COMMON_REG_LIST_DCN42_RI(inst)                                      \
+               SRI_ARR(OTG_VSTARTUP_PARAM, OTG, inst),                                      \
+               SRI_ARR(OTG_VUPDATE_PARAM, OTG, inst),                                   \
+               SRI_ARR(OTG_VREADY_PARAM, OTG, inst),                                    \
+               SRI_ARR(OTG_MASTER_UPDATE_LOCK, OTG, inst),                              \
+               SRI_ARR(OTG_MASTER_UPDATE_MODE, OTG, inst),                              \
+               SRI_ARR(OTG_V_COUNT_STOP_CONTROL, OTG, inst),                            \
+               SRI_ARR(OTG_V_COUNT_STOP_CONTROL2, OTG, inst),                           \
+               SRI_ARR(OTG_GSL_CONTROL, OTG, inst),                                     \
+               SRI2_ARR(OPTC_CLOCK_CONTROL, OPTC, inst),\
+               SRI_ARR(OTG_GLOBAL_CONTROL0, OTG, inst),                                 \
+               SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst),                                 \
+               SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst),                                 \
+               SRI_ARR(OTG_GLOBAL_CONTROL4, OTG, inst),                                 \
+               SRI_ARR(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),                           \
+               SRI_ARR(OTG_H_TOTAL, OTG, inst),                                         \
+               SRI_ARR(OTG_H_BLANK_START_END, OTG, inst),                               \
+               SRI_ARR(OTG_H_SYNC_A, OTG, inst),\
+               SRI_ARR(OTG_H_SYNC_A_CNTL, OTG, inst), \
+               SRI_ARR(OTG_H_TIMING_CNTL, OTG, inst), \
+               SRI_ARR(OTG_V_TOTAL, OTG, inst),  \
+               SRI_ARR(OTG_V_BLANK_START_END, OTG, inst),                               \
+               SRI_ARR(OTG_V_SYNC_A, OTG, inst), \
+               SRI_ARR(OTG_V_SYNC_A_CNTL, OTG, inst), \
+               SRI_ARR(OTG_CONTROL, OTG, inst), \
+               SRI_ARR(OTG_STEREO_CONTROL, OTG, inst), \
+               SRI_ARR(OTG_3D_STRUCTURE_CONTROL, OTG, inst),                            \
+               SRI_ARR(OTG_STEREO_STATUS, OTG, inst),                                   \
+               SRI_ARR(OTG_V_TOTAL_MAX, OTG, inst),                                     \
+               SRI_ARR(OTG_V_TOTAL_MIN, OTG, inst),                                     \
+               SRI_ARR(OTG_V_TOTAL_CONTROL, OTG, inst),                                 \
+               SRI_ARR(OTG_TRIGA_CNTL, OTG, inst),                                      \
+               SRI_ARR(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),                            \
+               SRI_ARR(OTG_STATIC_SCREEN_CONTROL, OTG, inst),                           \
+               SRI_ARR(OTG_STATUS_FRAME_COUNT, OTG, inst),                              \
+               SRI_ARR(OTG_STATUS, OTG, inst),                                                                                 \
+               SRI_ARR(OTG_STATUS_POSITION, OTG, inst), \
+               SRI_ARR(OTG_NOM_VERT_POSITION, OTG, inst),                               \
+               SRI_ARR(OTG_M_CONST_DTO0, OTG, inst),                                    \
+               SRI_ARR(OTG_M_CONST_DTO1, OTG, inst),                                    \
+               SRI_ARR(OTG_CLOCK_CONTROL, OTG, inst),                                   \
+               SRI_ARR(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst),                     \
+               SRI_ARR(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst),                    \
+               SRI_ARR(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst),                     \
+               SRI_ARR(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst),                    \
+               SRI_ARR(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst),                     \
+               SRI_ARR(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst),                    \
+               SRI_ARR(OPTC_INPUT_CLOCK_CONTROL, ODM, inst),                            \
+               SRI_ARR(OPTC_DATA_SOURCE_SELECT, ODM, inst),                             \
+               SRI_ARR(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst),                           \
+               SRI_ARR(CONTROL, VTG, inst), \
+               SRI_ARR(OTG_VERT_SYNC_CONTROL, OTG, inst),  \
+               SRI_ARR(OTG_GSL_CONTROL, OTG, inst), \
+               SRI_ARR(OTG_CRC_CNTL, OTG, inst),   \
+               SRI_ARR(OTG_CRC0_DATA_R, OTG, inst),                                     \
+               SRI_ARR(OTG_CRC0_DATA_G, OTG, inst),                                     \
+               SRI_ARR(OTG_CRC0_DATA_B, OTG, inst),                                     \
+               SRI_ARR(OTG_CRC1_DATA_R, OTG, inst),                                     \
+               SRI_ARR(OTG_CRC1_DATA_G, OTG, inst),                                     \
+               SRI_ARR(OTG_CRC1_DATA_B, OTG, inst),                                     \
+               SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst),                          \
+               SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst),                          \
+               SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst),                          \
+               SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst),                          \
+               SRI_ARR(OTG_CRC1_WINDOWA_X_CONTROL, OTG, inst),                          \
+               SRI_ARR(OTG_CRC1_WINDOWA_Y_CONTROL, OTG, inst),                          \
+               SRI_ARR(OTG_CRC1_WINDOWB_X_CONTROL, OTG, inst),                          \
+               SRI_ARR(OTG_CRC1_WINDOWB_Y_CONTROL, OTG, inst),                          \
+               SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL_READBACK, OTG, inst),\
+               SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL_READBACK, OTG, inst),\
+               SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL_READBACK, OTG, inst),\
+               SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL_READBACK, OTG, inst),\
+               SRI_ARR(OTG_CRC1_WINDOWA_X_CONTROL_READBACK, OTG, inst),\
+               SRI_ARR(OTG_CRC1_WINDOWA_Y_CONTROL_READBACK, OTG, inst),\
+               SRI_ARR(OTG_CRC1_WINDOWB_X_CONTROL_READBACK, OTG, inst),\
+               SRI_ARR(OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG, inst),\
+               SR_ARR(GSL_SOURCE_SELECT, inst),                                         \
+               SRI_ARR(OTG_TRIGA_MANUAL_TRIG, OTG, inst),                               \
+               SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst),                                 \
+               SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst),                                 \
+               SRI_ARR(OTG_GSL_WINDOW_X, OTG, inst),                                    \
+               SRI_ARR(OTG_GSL_WINDOW_Y, OTG, inst),                                    \
+               SRI_ARR(OTG_VUPDATE_KEEPOUT, OTG, inst),                                 \
+               SRI_ARR(OTG_DRR_TRIGGER_WINDOW, OTG, inst),                              \
+               SRI_ARR(OTG_DRR_V_TOTAL_CHANGE, OTG, inst),                              \
+               SRI_ARR(OPTC_DATA_FORMAT_CONTROL, ODM, inst),                            \
+               SRI_ARR(OPTC_BYTES_PER_PIXEL, ODM, inst),                                \
+               SRI_ARR(OPTC_WIDTH_CONTROL, ODM, inst),                                  \
+               SRI_ARR(OPTC_WIDTH_CONTROL2, ODM, inst),                                 \
+               SRI_ARR(OPTC_MEMORY_CONFIG, ODM, inst),                                  \
+               SRI_ARR(OTG_DRR_CONTROL, OTG, inst),                                     \
+               SRI_ARR(OTG_PSTATE_REGISTER, OTG, inst),                                 \
+               SRI_ARR(OTG_PWA_FRAME_SYNC_CONTROL, OTG, inst),\
+               SRI_ARR(OTG_PIPE_UPDATE_STATUS, OTG, inst),\
+               SRI_ARR(INTERRUPT_DEST, OTG, inst)
+
+/* CLK SRC */
+#define CS_COMMON_REG_LIST_DCN42_RI(index, pllid)               \
+       SRI_ARR_ALPHABET(PIXCLK_RESYNC_CNTL, PHYPLL, index, pllid), \
+               SRII_ARR_2(PHASE, DP_DTO, 0, index),                    \
+               SRII_ARR_2(PHASE, DP_DTO, 1, index),                    \
+               SRII_ARR_2(PHASE, DP_DTO, 2, index),                    \
+               SRII_ARR_2(PHASE, DP_DTO, 3, index),                    \
+               SRII_ARR_2(MODULO, DP_DTO, 0, index),                   \
+               SRII_ARR_2(MODULO, DP_DTO, 1, index),                   \
+               SRII_ARR_2(MODULO, DP_DTO, 2, index),                   \
+               SRII_ARR_2(MODULO, DP_DTO, 3, index),                   \
+               SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 0, index),             \
+               SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 1, index),             \
+               SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 2, index),             \
+               SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 3, index)
+
+/* ABM */
+#define ABM_DCN42_REG_LIST_RI(id)                               \
+       SRI_ARR(DC_ABM1_HG_SAMPLE_RATE, ABM, id),                   \
+               SRI_ARR(DC_ABM1_LS_SAMPLE_RATE, ABM, id),               \
+               SRI_ARR(DC_ABM1_HG_MISC_CTRL, ABM, id),                 \
+               SRI_ARR(DC_ABM1_IPCSC_COEFF_SEL, ABM, id),              \
+               SRI_ARR(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id),        \
+               SRI_ARR(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id),            \
+               SRI_ARR(BL1_PWM_TARGET_ABM_LEVEL, ABM, id),             \
+               SRI_ARR(BL1_PWM_USER_LEVEL, ABM, id),                   \
+               SRI_ARR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \
+               SRI_ARR(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id),       \
+               SRI_ARR(DC_ABM1_HG_BIN_33_40_SHIFT_INDEX, ABM, id),     \
+               SRI_ARR(DC_ABM1_HG_BIN_33_64_SHIFT_FLAG, ABM, id),      \
+               SRI_ARR(DC_ABM1_HG_BIN_41_48_SHIFT_INDEX, ABM, id),     \
+               SRI_ARR(DC_ABM1_HG_BIN_49_56_SHIFT_INDEX, ABM, id),     \
+               SRI_ARR(DC_ABM1_HG_BIN_57_64_SHIFT_INDEX, ABM, id),     \
+               SRI_ARR(DC_ABM1_HG_RESULT_DATA, ABM, id),               \
+               SRI_ARR(DC_ABM1_HG_RESULT_INDEX, ABM, id),              \
+               SRI_ARR(DC_ABM1_ACE_OFFSET_SLOPE_DATA, ABM, id),        \
+               SRI_ARR(DC_ABM1_ACE_PWL_CNTL, ABM, id)
+
+/* HUBP */
+#define HUBP_REG_LIST_DCN42_RI(id)                                     \
+       HUBP_REG_LIST_DCN30_RI(id), SRI_ARR(DCHUBP_MALL_CONFIG, HUBP, id), \
+               SRI_ARR(DCHUBP_VMPG_CONFIG, HUBP, id),                         \
+               SRI_ARR(UCLK_PSTATE_FORCE, HUBPREQ, id),                       \
+               SRI_ARR(HUBP_3DLUT_DLG_PARAM, CURSOR0_, id),                   \
+               HUBP_3DLUT_FL_REG_LIST_DCN401(id)
+struct dcn42_resource_pool {
+       struct resource_pool base;
+};
+struct resource_pool *dcn42_create_resource_pool(
+       const struct dc_init_data *init_data,
+       struct dc *dc);
+
+enum dc_status dcn42_validate_bandwidth(struct dc *dc,
+                                                         struct dc_state *context,
+                                                         enum dc_validate_mode validate_mode);
+
+void dcn42_prepare_mcache_programming(struct dc *dc, struct dc_state *context);
+
+#endif /* _DCN42_RESOURCE_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.c
new file mode 100644 (file)
index 0000000..33b9775
--- /dev/null
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+
+
+#include "dc.h"
+#include "dcn42_resource_fpu.h"
+
+#define DC_LOGGER_INIT(logger)
+
+
+void dcn42_decide_zstate_support(struct dc *dc, struct dc_state *context)
+{
+       enum dcn_zstate_support_state support = DCN_ZSTATE_SUPPORT_DISALLOW;
+       unsigned int i, plane_count = 0;
+
+       DC_LOGGER_INIT(dc->ctx->logger);
+
+       dc_assert_fp_enabled();
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               if (context->res_ctx.pipe_ctx[i].plane_state)
+                       plane_count++;
+       }
+       /*dcn42 has no z10*/
+       if (context->stream_count == 0 || plane_count == 0) {
+               support = DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY;
+       } else if (context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) {
+               struct dc_link *link = context->streams[0]->sink->link;
+               bool is_psr = (link && (link->psr_settings.psr_version == DC_PSR_VERSION_1 ||
+                                                               link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) && !link->panel_config.psr.disable_psr);
+               bool is_replay = link && link->replay_settings.replay_feature_enabled;
+
+               if (is_psr || is_replay)
+                       support = DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY;
+               else {
+                       /*here we allow z8 for eDP based on dml21 output*/
+                       support = context->bw_ctx.bw.dcn.clk.zstate_support ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY : DCN_ZSTATE_SUPPORT_DISALLOW;
+               }
+
+               DC_LOG_SMU("zstate_support: %d, StutterPeriod: %d\n, z8_stutter_efficiency: %d\n",
+                        support, (int)context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_period,
+                        (int)context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_efficiency);
+       }
+       context->bw_ctx.bw.dcn.clk.zstate_support = support;
+
+}
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.h b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.h
new file mode 100644 (file)
index 0000000..e321032
--- /dev/null
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 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.
+ *
+ */
+
+
+#ifndef _DCN42_RESOURCE_FPU_H_
+#define _DCN42_RESOURCE_FPU_H_
+
+#include "core_types.h"
+
+void dcn42_decide_zstate_support(struct dc *dc, struct dc_state *context);
+
+#endif /* _DCN42_RESOURCE_FPU_H_ */